System.Data.SQLite
Check-in [15e0be2ffb]
Not logged in

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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 15e0be2ffb3578d1dde11f68a462d6b84d386d9b
User & Date: mistachkin 2012-03-11 06:51:03
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
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Tests/basic.eagle.

   174    174             {
   175    175               connection.Open();
   176    176   
   177    177               return connection.GetSchema("ReservedWords");
   178    178             }
   179    179           }
   180    180   
          181  +        ///////////////////////////////////////////////////////////////////////
          182  +
   181    183           public static void Main()
   182    184           {
   183    185             // do nothing.
   184    186           }
   185    187         }
   186    188       }
   187    189     }] true true true results errors System.Data.SQLite.dll]
................................................................................
   233    235                 "Data Source=${dataSource};"))
   234    236             {
   235    237               connection.Open();
   236    238   
   237    239               return connection.GetSchema("ForeignKeys").Rows;
   238    240             }
   239    241           }
          242  +
          243  +        ///////////////////////////////////////////////////////////////////////
   240    244   
   241    245           public static void Main()
   242    246           {
   243    247             // do nothing.
   244    248           }
   245    249         }
   246    250       }
................................................................................
   331    335               //
   332    336               // NOTE: Make sure the retry parameter values were set.
   333    337               //
   334    338               return (newCount == count && newInterval == interval);
   335    339             }
   336    340           }
   337    341   
          342  +        ///////////////////////////////////////////////////////////////////////
          343  +
   338    344           public static void Main()
   339    345           {
   340    346             // do nothing.
   341    347           }
   342    348         }
   343    349       }
   344    350     }] true true true results errors System.Data.SQLite.dll]
................................................................................
   394    400     set id [object invoke Interpreter.GetActive NextId]
   395    401     set dataSource [file join [getDatabaseDirectory] $fileName]
   396    402   
   397    403     set sql { \
   398    404       BEGIN EXCLUSIVE TRANSACTION; \
   399    405       CREATE TABLE t1(x INTEGER); \
   400    406       INSERT INTO t1 (x) VALUES(1); \
   401         -    SELECT * FROM t1; \
          407  +    SELECT x FROM t1; \
   402    408     }
   403    409   
   404    410     unset -nocomplain results errors
   405    411   
   406    412     set code [compileCSharpWith [subst {
   407    413       using System.Data;
   408    414       using System.Data.SQLite;
................................................................................
   452    458     set id [object invoke Interpreter.GetActive NextId]
   453    459     set dataSource [file join [getDatabaseDirectory] $fileName]
   454    460   
   455    461     set sql { \
   456    462       BEGIN EXCLUSIVE TRANSACTION; \
   457    463       CREATE TABLE t1(x INTEGER); \
   458    464       INSERT INTO t1 (x) VALUES(1); \
   459         -    SELECT * FROM t1; \
          465  +    SELECT x FROM t1; \
   460    466     }
   461    467   
   462    468     unset -nocomplain results errors
   463    469   
   464    470     set code [compileCSharpWith [subst {
   465    471       using System.Data;
   466    472       using System.Data.SQLite;
................................................................................
   513    519     set id [object invoke Interpreter.GetActive NextId]
   514    520     set dataSource [file join [getDatabaseDirectory] $fileName]
   515    521   
   516    522     set sql { \
   517    523       BEGIN EXCLUSIVE TRANSACTION; \
   518    524       CREATE TABLE t1(x INTEGER); \
   519    525       INSERT INTO t1 (x) VALUES(1); \
   520         -    SELECT * FROM t1; \
          526  +    SELECT x FROM t1; \
   521    527     }
   522    528   
   523    529     unset -nocomplain results errors
   524    530   
   525    531     set code [compileCSharpWith [subst {
   526    532       using System.Data;
   527    533       using System.Data.SQLite;
................................................................................
   864    870             builder.Add("Date Source", "test.db");
   865    871             builder.Add("DateTimeFormat", format);
   866    872             builder.Add("DateTimeKind", kind);
   867    873   
   868    874             return builder.ToString();
   869    875           }
   870    876   
          877  +        ///////////////////////////////////////////////////////////////////////
          878  +
   871    879           public static void Main()
   872    880           {
   873    881             // do nothing.
   874    882           }
   875    883         }
   876    884       }
   877    885     }] true true true results errors System.Data.SQLite.dll]
................................................................................
   938    946               propertyValue = typeof(SQLiteConnectionStringBuilder).InvokeMember(
   939    947                   propertyName, BindingFlags.Instance | BindingFlags.Public |
   940    948                   BindingFlags.GetProperty, null, builder, null);
   941    949             }
   942    950   
   943    951             return String.Format("{0}, {1}", propertyValue, builder);
   944    952           }
          953  +
          954  +        ///////////////////////////////////////////////////////////////////////
   945    955   
   946    956           public static void Main()
   947    957           {
   948    958             // do nothing.
   949    959           }
   950    960         }
   951    961       }

Added Tests/tkt-72905c9a77.eagle.

            1  +###############################################################################
            2  +#
            3  +# tkt-72905c9a77.eagle --
            4  +#
            5  +# Written by Joe Mistachkin.
            6  +# Released to the public domain, use at your own risk!
            7  +#
            8  +###############################################################################
            9  +
           10  +package require Eagle
           11  +package require EagleLibrary
           12  +package require EagleTest
           13  +
           14  +runTestPrologue
           15  +
           16  +###############################################################################
           17  +
           18  +package require System.Data.SQLite.Test
           19  +runSQLiteTestPrologue
           20  +
           21  +###############################################################################
           22  +
           23  +#
           24  +# NOTE: This value is needed as part of the test result; therefore, it must be
           25  +#       set outside of the test setup.
           26  +#
           27  +set id [object invoke Interpreter.GetActive NextId]
           28  +
           29  +###############################################################################
           30  +
           31  +#
           32  +# NOTE: *WARNING* This test has been extremely carefully designed; however, it
           33  +#       is still quite sensitive to machine timing, resource availability, etc.
           34  +#       This test MAY pass even if the bug under test has not been fixed (or
           35  +#       has been regressed somehow).  However, due to the unpredictable nature
           36  +#       of race conditions, it really is the best that can be done.
           37  +#
           38  +runTest {test tkt-72905c9a77-1.1 {StaticIsInitialized race condition} -setup {
           39  +  set version [file version [getBinaryFileName System.Data.SQLite.dll]]
           40  +  set fileName tkt-72905c9a77-1.1.db
           41  +} -body {
           42  +  set dataSource [file join [getDatabaseDirectory] $fileName]
           43  +
           44  +  unset -nocomplain results errors
           45  +
           46  +  set code [compileCSharpWith [subst {
           47  +    using System;
           48  +    using System.Data.SQLite;
           49  +    using System.Diagnostics;
           50  +    using System.IO;
           51  +    using System.Reflection;
           52  +    using System.Text;
           53  +    using System.Threading;
           54  +
           55  +    namespace _Dynamic${id}
           56  +    {
           57  +      public class Test${id}
           58  +      {
           59  +        public static string GetTraceOutput()
           60  +        {
           61  +          //
           62  +          // NOTE: Create a memory stream to capture all the trace output for
           63  +          //       this test.
           64  +          //
           65  +          MemoryStream memoryStream = new MemoryStream();
           66  +
           67  +          //
           68  +          // NOTE: Create the trace listener using the memory stream we just
           69  +          //       created.
           70  +          //
           71  +          using (TraceListener listener = new TextWriterTraceListener(
           72  +              memoryStream))
           73  +          {
           74  +            //
           75  +            // NOTE: Add the trace listener to the collection of active trace
           76  +            //       listeners (for this application domain).
           77  +            //
           78  +            Trace.Listeners.Add(listener);
           79  +
           80  +            //
           81  +            // NOTE: Lookup the type for the private SQLite3 class in the
           82  +            //       System.Data.SQLite assembly.  We need the type in order to
           83  +            //       lookup the method used in this test (via reflection).
           84  +            //       This is only necessary because the method under test is
           85  +            //       private and cannot normally be executed from C#.
           86  +            //
           87  +            Type type = Type.GetType(
           88  +                "System.Data.SQLite.SQLite3, System.Data.SQLite, " +
           89  +                "Version=${version}, Culture=neutral, " +
           90  +                "PublicKeyToken=db937bc2d44ff139");
           91  +
           92  +            //
           93  +            // NOTE: Grab the method object for the private method we need for
           94  +            //       this test.
           95  +            //
           96  +            MethodInfo methodInfo = type.GetMethod("StaticIsInitialized",
           97  +                BindingFlags.Static | BindingFlags.NonPublic);
           98  +
           99  +            //
          100  +            // NOTE: Create the event that will be used to synchronize all the
          101  +            //       created threads so that they start doing their actual test
          102  +            //       "work" at approximately the same time.
          103  +            //
          104  +            using (ManualResetEvent goEvent = new ManualResetEvent(false))
          105  +            {
          106  +              //
          107  +              // NOTE: Create 4 threads for each processor on the machine.
          108  +              //       Under normal circumstances, this should give us a good
          109  +              //       chance of triggering the race condition being tested.
          110  +              //
          111  +              int count = 4 * Environment.ProcessorCount;
          112  +
          113  +              //
          114  +              // NOTE: Create a random number generator suitable for waiting a
          115  +              //       random number of milliseconds between each attempt to
          116  +              //       cause the race condition on a given thread.
          117  +              //
          118  +              Random random = new Random();
          119  +
          120  +              //
          121  +              // NOTE: Create a (reusable) delegate that will contain the code
          122  +              //       that each created thread is to execute.
          123  +              //
          124  +              ThreadStart threadStart = delegate()
          125  +              {
          126  +                try
          127  +                {
          128  +                  //
          129  +                  // NOTE: Wait forever for the "GO" signal so that all threads
          130  +                  //       can start working at approximately the same time.
          131  +                  //
          132  +                  goEvent.WaitOne();
          133  +
          134  +                  //
          135  +                  // NOTE: Force the SQLiteLog.StaticIsInitialized method to
          136  +                  //       be repeatedly called on every thread right away to
          137  +                  //       thoroughly test its locking semantics.  Also, use a
          138  +                  //       random delay, in milliseconds, between zero and the
          139  +                  //       number of test threads squared after each attempt.
          140  +                  //
          141  +                  for (int index = 0; index < (count * count); index++)
          142  +                  {
          143  +                    methodInfo.Invoke(null, null);
          144  +                    Thread.Sleep(random.Next(0, (count * count)));
          145  +                  }
          146  +
          147  +                  //
          148  +                  // NOTE: Create and open a connection and use it to log a
          149  +                  //       test message just to make sure that the logging
          150  +                  //       system is initialized and in working order.
          151  +                  //
          152  +                  using (SQLiteConnection connection = new SQLiteConnection(
          153  +                      "Data Source=${dataSource};"))
          154  +                  {
          155  +                    connection.Open();
          156  +                    connection.LogMessage(0, "TEST ${id}");
          157  +                  }
          158  +                }
          159  +                catch (Exception e)
          160  +                {
          161  +                  //
          162  +                  // NOTE: We caught an exception.  Since this will impact the
          163  +                  //       captured trace output, this will cause the test to
          164  +                  //       fail (just as it should).
          165  +                  //
          166  +                  Trace.WriteLine(String.Format("CAUGHT: {0}", e));
          167  +                }
          168  +              };
          169  +
          170  +              //
          171  +              // NOTE: Create the array of thread objects.
          172  +              //
          173  +              Thread\[\] thread = new Thread\[count\];
          174  +
          175  +              //
          176  +              // NOTE: Create each of the test threads with a suitable stack
          177  +              //       size.  We must specify a stack size here because the
          178  +              //       default one for the process would be the same as the
          179  +              //       parent executable (the Eagle shell), which is 16MB,
          180  +              //       too large to be useful.
          181  +              //
          182  +              for (int index = 0; index < count; index++)
          183  +              {
          184  +                thread\[index\] = new Thread(threadStart, 1048576);
          185  +
          186  +                //
          187  +                // NOTE: Name each thread for a better debugging experience.
          188  +                //
          189  +                thread\[index\].Name = String.Format(
          190  +                    "[file rootname ${fileName}] #{0}", index);
          191  +              }
          192  +
          193  +              //
          194  +              // NOTE: Force logging to be initialized now; otherwise, there is
          195  +              //       no way for the native SQLite library to impact the trace
          196  +              //       listener we are monitoring for output.
          197  +              //
          198  +              SQLiteLog.Initialize();
          199  +
          200  +              //
          201  +              // NOTE: Start all the threads now.  They should not actually do
          202  +              //       any of the test "work" until we signal the event.
          203  +              //
          204  +              for (int index = 0; index < count; index++)
          205  +                thread\[index\].Start();
          206  +
          207  +              //
          208  +              // NOTE: Send the signal that all threads should start doing
          209  +              //       their test "work" now.
          210  +              //
          211  +              goEvent.Set(); /* GO */
          212  +
          213  +              //
          214  +              // NOTE: Wait forever for each thread to finish its test "work"
          215  +              //       and then die.
          216  +              //
          217  +              for (int index = 0; index < count; index++)
          218  +                thread\[index\].Join();
          219  +            }
          220  +
          221  +            //
          222  +            // NOTE: *REQUIRED* Force all the trace listeners to be flushed to
          223  +            //       disk now so that we do not lose any output.  Without this
          224  +            //       method call, loss of trace output was observed.
          225  +            //
          226  +            Trace.Flush();
          227  +
          228  +            //
          229  +            // NOTE: The trace listener used by this test can be removed now
          230  +            //       as all the trace output should have been flushed to the
          231  +            //       memory stream now.
          232  +            //
          233  +            Trace.Listeners.Remove(listener);
          234  +
          235  +            //
          236  +            // NOTE: Return a string containing all the trace output we saw
          237  +            //       (from all threads) during the above test code.
          238  +            //
          239  +            return Encoding.UTF8.GetString(memoryStream.ToArray());
          240  +          }
          241  +        }
          242  +
          243  +        ///////////////////////////////////////////////////////////////////////
          244  +
          245  +        public static void Main()
          246  +        {
          247  +          // do nothing.
          248  +        }
          249  +      }
          250  +    }
          251  +  }] true true true results errors System.Data.SQLite.dll]
          252  +
          253  +  list $code $results \
          254  +      [expr {[info exists errors] ? $errors : ""}] \
          255  +      [expr {$code eq "Ok" ? [catch {
          256  +        object invoke _Dynamic${id}.Test${id} GetTraceOutput
          257  +      } result] : [set result ""]}] [string map [list \r\n \n] $result]
          258  +} -cleanup {
          259  +  cleanupDb $fileName
          260  +
          261  +  unset -nocomplain result code results errors dataSource fileName version
          262  +} -constraints \
          263  +{eagle monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
          264  +-match regexp -result [appendArgs "^Ok\
          265  +System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{" [string repeat \
          266  +"SQLite message \\(0\\): TEST $id
          267  +" [expr {4 * [info processors]}]] "\\}\$"]}
          268  +
          269  +###############################################################################
          270  +
          271  +unset -nocomplain id
          272  +
          273  +###############################################################################
          274  +
          275  +runSQLiteTestEpilogue
          276  +runTestEpilogue

Changes to Tests/tkt-e30b820248.eagle.

    34     34     set sql { \
    35     35       CREATE TABLE t1 (id1 INTEGER); \
    36     36       INSERT INTO t1 (id1) VALUES (1); \
    37     37       INSERT INTO t1 (id1) VALUES (2); \
    38     38       INSERT INTO t1 (id1) VALUES (?); \
    39     39       INSERT INTO t1 (id1) VALUES (?); \
    40     40       INSERT INTO t1 (id1) VALUES (?); \
    41         -    SELECT * FROM t1 ORDER BY id1; \
           41  +    SELECT id1 FROM t1 ORDER BY id1; \
    42     42     }
    43     43   
    44     44     unset -nocomplain results errors
    45     45   
    46     46     set code [compileCSharpWith [subst {
    47     47       using System.Data.SQLite;
    48     48       using System.Diagnostics;
................................................................................
   103    103         [expr {$code eq "Ok" ? [catch {
   104    104           object invoke _Dynamic${id}.Test${id} Main
   105    105         } result] : [set result ""]}] $result \
   106    106         [reportSQLiteResources $test_channel true]
   107    107   } -cleanup {
   108    108     cleanupDb $fileName
   109    109   
   110         -  unset -nocomplain result code results errors sql dataSource id db fileName
          110  +  unset -nocomplain result code results errors sql name dataSource id fileName
   111    111   } -constraints \
   112    112   {eagle logFile monoBug28 command.sql compile.DATA SQLite System.Data.SQLite} \
   113    113   -match regexp -result [appendArgs "^Ok\
   114    114   System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\} " $memory_used \$]}
   115    115   
   116    116   ###############################################################################
   117    117   
................................................................................
   130    130       set sql { \
   131    131         CREATE TABLE t1 (id1 INTEGER); \
   132    132         INSERT INTO t1 (id1) VALUES (1); \
   133    133         INSERT INTO t1 (id1) VALUES (2); \
   134    134         INSERT INTO t1 (id1) VALUES (3); \
   135    135         INSERT INTO t1 (id1) VALUES (4); \
   136    136         INSERT INTO t1 (id1) VALUES (5); \
   137         -      SELECT * FROM t1 ORDER BY id1; \
          137  +      SELECT id1 FROM t1 ORDER BY id1; \
   138    138       }
   139    139   
   140    140       unset -nocomplain results errors
   141    141   
   142    142       set code [compileCSharpWith [subst {
   143    143         using System;
   144    144         using System.Data.SQLite;
................................................................................
   250    250           [expr {$code eq "Ok" ? [catch {
   251    251             object invoke _Dynamic${id}.Test${id} Main
   252    252           } result] : [set result ""]}] $result \
   253    253           [reportSQLiteResources $test_channel true]
   254    254     } -cleanup {
   255    255       cleanupDb $fileName
   256    256   
   257         -    unset -nocomplain result code results errors sql name dataSource id db \
          257  +    unset -nocomplain result code results errors sql name dataSource id \
   258    258           fileName
   259    259     } -constraints {eagle logFile monoBug28 command.sql compile.DATA SQLite\
   260    260   System.Data.SQLite} -match regexp -result [appendArgs "^Ok\
   261    261   System#CodeDom#Compiler#CompilerResults#\\d+ \\{\\} 0 \\{\\} " $memory_used \$]}
   262    262   }
   263    263   
   264    264   ###############################################################################