System.Data.SQLite

Check-in [15e0be2ffb]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Add stress test for the race condition in ticket [72905c9a77]. Also, avoid using 'SELECT *' in any tests.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 15e0be2ffb3578d1dde11f68a462d6b84d386d9b
User & Date: mistachkin 2012-03-11 06:51:03.675
References
2012-03-11
06:52 Closed ticket [72905c9a77]: SQLite error (21): misuse at line 112492 of [ebd01a8def] plus 1 other change artifact: bf2b72f851 user: mistachkin
Context
2012-03-11
07:01
Enable the PreLoadNativeLibrary build property by default. This feature has now been tested on the 32-bit and 64-bit variants of Windows 7 as well as 32-bit Windows XP with no issues. check-in: 0cf606caf6 user: mistachkin tags: trunk
06:51
Add stress test for the race condition in ticket [72905c9a77]. Also, avoid using 'SELECT *' in any tests. check-in: 15e0be2ffb user: mistachkin tags: trunk
2012-02-28
17:35
Stop using the 'StringComparison.InvariantCulture*' values. check-in: 3137eacf49 user: mistachkin tags: trunk
Changes
Unified Diff Show Whitespace Changes Patch
Changes to Tests/basic.eagle.
174
175
176
177
178
179
180


181
182
183
184
185
186
187
          {
            connection.Open();

            return connection.GetSchema("ReservedWords");
          }
        }



        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]







>
>







174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
          {
            connection.Open();

            return connection.GetSchema("ReservedWords");
          }
        }

        ///////////////////////////////////////////////////////////////////////

        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]
233
234
235
236
237
238
239


240
241
242
243
244
245
246
              "Data Source=${dataSource};"))
          {
            connection.Open();

            return connection.GetSchema("ForeignKeys").Rows;
          }
        }



        public static void Main()
        {
          // do nothing.
        }
      }
    }







>
>







235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
              "Data Source=${dataSource};"))
          {
            connection.Open();

            return connection.GetSchema("ForeignKeys").Rows;
          }
        }

        ///////////////////////////////////////////////////////////////////////

        public static void Main()
        {
          // do nothing.
        }
      }
    }
331
332
333
334
335
336
337


338
339
340
341
342
343
344
            //
            // NOTE: Make sure the retry parameter values were set.
            //
            return (newCount == count && newInterval == interval);
          }
        }



        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]







>
>







335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
            //
            // NOTE: Make sure the retry parameter values were set.
            //
            return (newCount == count && newInterval == interval);
          }
        }

        ///////////////////////////////////////////////////////////////////////

        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  set sql { \
    BEGIN EXCLUSIVE TRANSACTION; \
    CREATE TABLE t1(x INTEGER); \
    INSERT INTO t1 (x) VALUES(1); \
    SELECT * FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;







|







400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  set sql { \
    BEGIN EXCLUSIVE TRANSACTION; \
    CREATE TABLE t1(x INTEGER); \
    INSERT INTO t1 (x) VALUES(1); \
    SELECT x FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  set sql { \
    BEGIN EXCLUSIVE TRANSACTION; \
    CREATE TABLE t1(x INTEGER); \
    INSERT INTO t1 (x) VALUES(1); \
    SELECT * FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;







|







458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  set sql { \
    BEGIN EXCLUSIVE TRANSACTION; \
    CREATE TABLE t1(x INTEGER); \
    INSERT INTO t1 (x) VALUES(1); \
    SELECT x FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  set sql { \
    BEGIN EXCLUSIVE TRANSACTION; \
    CREATE TABLE t1(x INTEGER); \
    INSERT INTO t1 (x) VALUES(1); \
    SELECT * FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;







|







519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]

  set sql { \
    BEGIN EXCLUSIVE TRANSACTION; \
    CREATE TABLE t1(x INTEGER); \
    INSERT INTO t1 (x) VALUES(1); \
    SELECT x FROM t1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data;
    using System.Data.SQLite;
864
865
866
867
868
869
870


871
872
873
874
875
876
877
          builder.Add("Date Source", "test.db");
          builder.Add("DateTimeFormat", format);
          builder.Add("DateTimeKind", kind);

          return builder.ToString();
        }



        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]







>
>







870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
          builder.Add("Date Source", "test.db");
          builder.Add("DateTimeFormat", format);
          builder.Add("DateTimeKind", kind);

          return builder.ToString();
        }

        ///////////////////////////////////////////////////////////////////////

        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]
938
939
940
941
942
943
944


945
946
947
948
949
950
951
            propertyValue = typeof(SQLiteConnectionStringBuilder).InvokeMember(
                propertyName, BindingFlags.Instance | BindingFlags.Public |
                BindingFlags.GetProperty, null, builder, null);
          }

          return String.Format("{0}, {1}", propertyValue, builder);
        }



        public static void Main()
        {
          // do nothing.
        }
      }
    }







>
>







946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
            propertyValue = typeof(SQLiteConnectionStringBuilder).InvokeMember(
                propertyName, BindingFlags.Instance | BindingFlags.Public |
                BindingFlags.GetProperty, null, builder, null);
          }

          return String.Format("{0}, {1}", propertyValue, builder);
        }

        ///////////////////////////////////////////////////////////////////////

        public static void Main()
        {
          // do nothing.
        }
      }
    }
Added Tests/tkt-72905c9a77.eagle.








































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
###############################################################################
#
# tkt-72905c9a77.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
package require EagleLibrary
package require EagleTest

runTestPrologue

###############################################################################

package require System.Data.SQLite.Test
runSQLiteTestPrologue

###############################################################################

#
# NOTE: This value is needed as part of the test result; therefore, it must be
#       set outside of the test setup.
#
set id [object invoke Interpreter.GetActive NextId]

###############################################################################

#
# NOTE: *WARNING* This test has been extremely carefully designed; however, it
#       is still quite sensitive to machine timing, resource availability, etc.
#       This test MAY pass even if the bug under test has not been fixed (or
#       has been regressed somehow).  However, due to the unpredictable nature
#       of race conditions, it really is the best that can be done.
#
runTest {test tkt-72905c9a77-1.1 {StaticIsInitialized race condition} -setup {
  set version [file version [getBinaryFileName System.Data.SQLite.dll]]
  set fileName tkt-72905c9a77-1.1.db
} -body {
  set dataSource [file join [getDatabaseDirectory] $fileName]

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System;
    using System.Data.SQLite;
    using System.Diagnostics;
    using System.IO;
    using System.Reflection;
    using System.Text;
    using System.Threading;

    namespace _Dynamic${id}
    {
      public class Test${id}
      {
        public static string GetTraceOutput()
        {
          //
          // NOTE: Create a memory stream to capture all the trace output for
          //       this test.
          //
          MemoryStream memoryStream = new MemoryStream();

          //
          // NOTE: Create the trace listener using the memory stream we just
          //       created.
          //
          using (TraceListener listener = new TextWriterTraceListener(
              memoryStream))
          {
            //
            // NOTE: Add the trace listener to the collection of active trace
            //       listeners (for this application domain).
            //
            Trace.Listeners.Add(listener);

            //
            // NOTE: Lookup the type for the private SQLite3 class in the
            //       System.Data.SQLite assembly.  We need the type in order to
            //       lookup the method used in this test (via reflection).
            //       This is only necessary because the method under test is
            //       private and cannot normally be executed from C#.
            //
            Type type = Type.GetType(
                "System.Data.SQLite.SQLite3, System.Data.SQLite, " +
                "Version=${version}, Culture=neutral, " +
                "PublicKeyToken=db937bc2d44ff139");

            //
            // NOTE: Grab the method object for the private method we need for
            //       this test.
            //
            MethodInfo methodInfo = type.GetMethod("StaticIsInitialized",
                BindingFlags.Static | BindingFlags.NonPublic);

            //
            // NOTE: Create the event that will be used to synchronize all the
            //       created threads so that they start doing their actual test
            //       "work" at approximately the same time.
            //
            using (ManualResetEvent goEvent = new ManualResetEvent(false))
            {
              //
              // NOTE: Create 4 threads for each processor on the machine.
              //       Under normal circumstances, this should give us a good
              //       chance of triggering the race condition being tested.
              //
              int count = 4 * Environment.ProcessorCount;

              //
              // NOTE: Create a random number generator suitable for waiting a
              //       random number of milliseconds between each attempt to
              //       cause the race condition on a given thread.
              //
              Random random = new Random();

              //
              // NOTE: Create a (reusable) delegate that will contain the code
              //       that each created thread is to execute.
              //
              ThreadStart threadStart = delegate()
              {
                try
                {
                  //
                  // NOTE: Wait forever for the "GO" signal so that all threads
                  //       can start working at approximately the same time.
                  //
                  goEvent.WaitOne();

                  //
                  // NOTE: Force the SQLiteLog.StaticIsInitialized method to
                  //       be repeatedly called on every thread right away to
                  //       thoroughly test its locking semantics.  Also, use a
                  //       random delay, in milliseconds, between zero and the
                  //       number of test threads squared after each attempt.
                  //
                  for (int index = 0; index < (count * count); index++)
                  {
                    methodInfo.Invoke(null, null);
                    Thread.Sleep(random.Next(0, (count * count)));
                  }

                  //
                  // NOTE: Create and open a connection and use it to log a
                  //       test message just to make sure that the logging
                  //       system is initialized and in working order.
                  //
                  using (SQLiteConnection connection = new SQLiteConnection(
                      "Data Source=${dataSource};"))
                  {
                    connection.Open();
                    connection.LogMessage(0, "TEST ${id}");
                  }
                }
                catch (Exception e)
                {
                  //
                  // NOTE: We caught an exception.  Since this will impact the
                  //       captured trace output, this will cause the test to
                  //       fail (just as it should).
                  //
                  Trace.WriteLine(String.Format("CAUGHT: {0}", e));
                }
              };

              //
              // NOTE: Create the array of thread objects.
              //
              Thread\[\] thread = new Thread\[count\];

              //
              // NOTE: Create each of the test threads with a suitable stack
              //       size.  We must specify a stack size here because the
              //       default one for the process would be the same as the
              //       parent executable (the Eagle shell), which is 16MB,
              //       too large to be useful.
              //
              for (int index = 0; index < count; index++)
              {
                thread\[index\] = new Thread(threadStart, 1048576);

                //
                // NOTE: Name each thread for a better debugging experience.
                //
                thread\[index\].Name = String.Format(
                    "[file rootname ${fileName}] #{0}", index);
              }

              //
              // NOTE: Force logging to be initialized now; otherwise, there is
              //       no way for the native SQLite library to impact the trace
              //       listener we are monitoring for output.
              //
              SQLiteLog.Initialize();

              //
              // NOTE: Start all the threads now.  They should not actually do
              //       any of the test "work" until we signal the event.
              //
              for (int index = 0; index < count; index++)
                thread\[index\].Start();

              //
              // NOTE: Send the signal that all threads should start doing
              //       their test "work" now.
              //
              goEvent.Set(); /* GO */

              //
              // NOTE: Wait forever for each thread to finish its test "work"
              //       and then die.
              //
              for (int index = 0; index < count; index++)
                thread\[index\].Join();
            }

            //
            // NOTE: *REQUIRED* Force all the trace listeners to be flushed to
            //       disk now so that we do not lose any output.  Without this
            //       method call, loss of trace output was observed.
            //
            Trace.Flush();

            //
            // NOTE: The trace listener used by this test can be removed now
            //       as all the trace output should have been flushed to the
            //       memory stream now.
            //
            Trace.Listeners.Remove(listener);

            //
            // NOTE: Return a string containing all the trace output we saw
            //       (from all threads) during the above test code.
            //
            return Encoding.UTF8.GetString(memoryStream.ToArray());
          }
        }

        ///////////////////////////////////////////////////////////////////////

        public static void Main()
        {
          // do nothing.
        }
      }
    }
  }] true true true results errors System.Data.SQLite.dll]

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} GetTraceOutput
      } result] : [set result ""]}] [string map [list \r\n \n] $result]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result code results errors dataSource fileName version
} -constraints \
{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-match regexp -result [appendArgs "^Ok\
System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{" [string repeat \
"SQLite message \\(0\\): TEST $id
" [expr {4 * [info processors]}]] "\\}\$"]}

###############################################################################

unset -nocomplain id

###############################################################################

runSQLiteTestEpilogue
runTestEpilogue
Changes to Tests/tkt-e30b820248.eagle.
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  set sql { \
    CREATE TABLE t1 (id1 INTEGER); \
    INSERT INTO t1 (id1) VALUES (1); \
    INSERT INTO t1 (id1) VALUES (2); \
    INSERT INTO t1 (id1) VALUES (?); \
    INSERT INTO t1 (id1) VALUES (?); \
    INSERT INTO t1 (id1) VALUES (?); \
    SELECT * FROM t1 ORDER BY id1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data.SQLite;
    using System.Diagnostics;







|







34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
  set sql { \
    CREATE TABLE t1 (id1 INTEGER); \
    INSERT INTO t1 (id1) VALUES (1); \
    INSERT INTO t1 (id1) VALUES (2); \
    INSERT INTO t1 (id1) VALUES (?); \
    INSERT INTO t1 (id1) VALUES (?); \
    INSERT INTO t1 (id1) VALUES (?); \
    SELECT id1 FROM t1 ORDER BY id1; \
  }

  unset -nocomplain results errors

  set code [compileCSharpWith [subst {
    using System.Data.SQLite;
    using System.Diagnostics;
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result \
      [reportSQLiteResources $test_channel true]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result code results errors sql dataSource id db fileName
} -constraints \
{eagle logFile monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-match regexp -result [appendArgs "^Ok\
System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\} " $memory_used \$]}

###############################################################################








|







103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} Main
      } result] : [set result ""]}] $result \
      [reportSQLiteResources $test_channel true]
} -cleanup {
  cleanupDb $fileName

  unset -nocomplain result code results errors sql name dataSource id fileName
} -constraints \
{eagle logFile monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
-match regexp -result [appendArgs "^Ok\
System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\} " $memory_used \$]}

###############################################################################

130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
    set sql { \
      CREATE TABLE t1 (id1 INTEGER); \
      INSERT INTO t1 (id1) VALUES (1); \
      INSERT INTO t1 (id1) VALUES (2); \
      INSERT INTO t1 (id1) VALUES (3); \
      INSERT INTO t1 (id1) VALUES (4); \
      INSERT INTO t1 (id1) VALUES (5); \
      SELECT * FROM t1 ORDER BY id1; \
    }

    unset -nocomplain results errors

    set code [compileCSharpWith [subst {
      using System;
      using System.Data.SQLite;







|







130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
    set sql { \
      CREATE TABLE t1 (id1 INTEGER); \
      INSERT INTO t1 (id1) VALUES (1); \
      INSERT INTO t1 (id1) VALUES (2); \
      INSERT INTO t1 (id1) VALUES (3); \
      INSERT INTO t1 (id1) VALUES (4); \
      INSERT INTO t1 (id1) VALUES (5); \
      SELECT id1 FROM t1 ORDER BY id1; \
    }

    unset -nocomplain results errors

    set code [compileCSharpWith [subst {
      using System;
      using System.Data.SQLite;
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
        [expr {$code eq "Ok" ? [catch {
          object invoke _Dynamic${id}.Test${id} Main
        } result] : [set result ""]}] $result \
        [reportSQLiteResources $test_channel true]
  } -cleanup {
    cleanupDb $fileName

    unset -nocomplain result code results errors sql name dataSource id db \
        fileName
  } -constraints {eagle logFile monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -match regexp -result [appendArgs "^Ok\
System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\} " $memory_used \$]}
}

###############################################################################







|







250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
        [expr {$code eq "Ok" ? [catch {
          object invoke _Dynamic${id}.Test${id} Main
        } result] : [set result ""]}] $result \
        [reportSQLiteResources $test_channel true]
  } -cleanup {
    cleanupDb $fileName

    unset -nocomplain result code results errors sql name dataSource id \
        fileName
  } -constraints {eagle logFile monoBug28 command.sql compile.DATA SQLite\
System.Data.SQLite} -match regexp -result [appendArgs "^Ok\
System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\} " $memory_used \$]}
}

###############################################################################