System.Data.SQLite
Check-in [5e6b70f411]
Not logged in

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

Overview
Comment:Add threading test to the Windows CE test application. Also, some cleanup and refactoring work to make adding new tests easier.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 5e6b70f411677578f5d98ee80ebbd690d330dcc5
User & Date: mistachkin 2012-10-09 11:33:36
Context
2012-10-09
13:07
For Visual Studio 2012 only, run the design-time installer tool twice for both install and uninstall to make sure the settings are present in the per-user and per-machine registry hives. check-in: c1187b14fb user: mistachkin tags: trunk
11:33
Add threading test to the Windows CE test application. Also, some cleanup and refactoring work to make adding new tests easier. check-in: 5e6b70f411 user: mistachkin tags: trunk
09:40
Add wrapper batch file for the Windows CE test automation and update the version history docs. check-in: 305bd4b0ab user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to testce/Program.cs.

    14     14   
    15     15   namespace test
    16     16   {
    17     17     class Program
    18     18     {
    19     19       private static readonly string DefaultConnectionString =
    20     20           "Data Source={DataDirectory}\\test.db;Password=yVXL39etehPX;";
           21  +
           22  +    internal static DbConnection NewConnection()
           23  +    {
           24  +        return new SQLiteConnection();
           25  +    }
    21     26   
    22     27       [MTAThread]
    23     28       static int Main(string[] args)
    24     29       {
    25     30         bool autoClose = false;
    26     31         int exitCode = 2; /* INCOMPLETE */
    27     32         Assembly assembly = Assembly.GetExecutingAssembly();
................................................................................
    33     38   
    34     39         try { File.Delete(directory + "\\test.db"); } catch { }
    35     40   
    36     41         SQLiteFunction.RegisterFunction(typeof(TestFunc));
    37     42         SQLiteFunction.RegisterFunction(typeof(MyCount));
    38     43         SQLiteFunction.RegisterFunction(typeof(MySequence));
    39     44   
    40         -      using (DbConnection cnn = new SQLiteConnection())
           45  +      using (DbConnection cnn = NewConnection())
    41     46         {
    42     47           string connectionString = DefaultConnectionString;
    43     48   
    44     49           try
    45     50           {
    46     51             //
    47     52             // NOTE: Attempt to open the configuration file associated with
................................................................................
    73     78             //
    74     79             connectionString = connectionString.Replace(
    75     80               "{DataDirectory}", directory);
    76     81   
    77     82             cnn.ConnectionString = connectionString;
    78     83             cnn.Open();
    79     84   
    80         -          TestCases tests = new TestCases(autoClose);
           85  +          TestCases tests = new TestCases(connectionString, cnn, autoClose);
    81     86   
    82         -          tests.Run(cnn);
           87  +          tests.Run();
    83     88   
    84     89             Application.Run(tests.frm);
    85     90   
    86     91             if (tests.Succeeded())
    87     92                 exitCode = 0; /* SUCCESS */
    88     93             else
    89     94                 exitCode = 1; /* FAILURE */

Changes to testce/TestCases.cs.

     5      5    * Released to the public domain, use at your own risk!
     6      6    ********************************************************/
     7      7   
     8      8   using System;
     9      9   using System.Data.Common;
    10     10   using System.Data;
    11     11   using System.Data.SQLite;
           12  +using System.Threading;
    12     13   
    13     14   namespace test
    14     15   {
    15     16   
    16     17     /// <summary>
    17     18     /// Scalar user-defined function.  In this example, the same class is declared twice with 
    18     19     /// different function names to demonstrate how to use alias names for user-defined functions.
................................................................................
    69     70       }
    70     71     }
    71     72   
    72     73     internal class TestCases
    73     74     {
    74     75       internal Form1 frm;
    75     76   
           77  +    private string connectionString;
           78  +    private DbConnection cnn;
    76     79       private bool autoClose;
    77     80       private int total;
    78     81       private int passed;
    79     82       private int failed;
    80     83   
    81         -    internal TestCases(bool autoExit)
           84  +    internal TestCases(
           85  +        string connectionString,
           86  +        DbConnection cnn,
           87  +        bool autoExit
           88  +        )
    82     89       {
           90  +        this.connectionString = connectionString;
           91  +        this.cnn = cnn;
    83     92           this.autoClose = autoExit;
    84     93       }
    85     94   
    86     95       internal bool Succeeded()
    87     96       {
    88     97           return (failed == 0) && (passed == total);
    89     98       }
    90     99   
    91         -    internal void Run(DbConnection cnn)
          100  +    internal void Run()
    92    101       {
    93    102         frm = new Form1();
    94         -
    95    103         frm.Show();
    96    104   
    97    105         Type type = cnn.GetType();
    98    106         frm.WriteLine("\r\nBeginning Test on " + type.ToString());
    99    107   
   100    108         SQLiteConnection cnn2 = cnn as SQLiteConnection;
   101    109         if (cnn2 != null)
................................................................................
   177    185         try { UserAggregate(cnn); frm.WriteLine("SUCCESS - UserAggregate"); passed++; }
   178    186         catch (Exception) { frm.WriteLine("FAIL - UserAggregate"); failed++; }
   179    187   
   180    188         total++;
   181    189         try { UserCollation(cnn); frm.WriteLine("SUCCESS - UserCollation"); passed++; }
   182    190         catch (Exception) { frm.WriteLine("FAIL - UserCollation"); failed++; }
   183    191   
          192  +      total++;
          193  +      try { MultipleThreadStress(cnn); frm.WriteLine("SUCCESS - MultipleThreadStress"); passed++; }
          194  +      catch (Exception) { frm.WriteLine("FAIL - MultipleThreadStress"); failed++; }
          195  +
   184    196         total++;
   185    197         try { DropTable(cnn); frm.WriteLine("SUCCESS - DropTable"); passed++; }
   186    198         catch (Exception) { frm.WriteLine("FAIL - DropTable"); failed++; }
   187    199   
   188    200         frm.WriteLine("\r\nTests Finished.");
   189    201         frm.WriteLine(String.Format("\r\nCounts: {0} total, {1} passed, {2} failed", total, passed, failed));
   190    202         frm.WriteLine(String.Format("Result: {0}", Succeeded() ? "SUCCESS" : "FAILURE"));
................................................................................
   404    416           //cmd.CommandText = "CREATE TABLE TestCase (ID bigint primary key identity, Field1 Integer, Field2 Float, Field3 VARCHAR(50), Field4 CHAR(10), Field5 DateTime, Field6 Image)";
   405    417           cmd.ExecuteNonQuery();
   406    418         }
   407    419       }
   408    420   
   409    421       internal void DropTable(DbConnection cnn)
   410    422       {
   411         -      using (DbCommand cmd = cnn.CreateCommand())
          423  +      string[] tables = {
          424  +        "TestCase", "keyinfotest", "datatypetest", "TestThreads"
          425  +      };
          426  +      foreach (string table in tables)
   412    427         {
   413         -        cmd.CommandText = "DROP TABLE TestCase";
   414         -        cmd.ExecuteNonQuery();
          428  +        using (DbCommand cmd = cnn.CreateCommand())
          429  +        {
          430  +          cmd.CommandText = String.Format("DROP TABLE {0};", table);
          431  +          cmd.ExecuteNonQuery();
          432  +        }
   415    433         }
   416    434       }
   417    435   
   418    436       internal void InsertTable(DbConnection cnn)
   419    437       {
   420    438         using (DbCommand cmd = cnn.CreateCommand())
   421    439         {
................................................................................
   876    894           // and "Field3" will be next, followed by a NULL.  Our user-defined collating sequence will 
   877    895           // deliberately place them out of order so Field3 is first.
   878    896           cmd.CommandText = "SELECT Field3 FROM TestCase ORDER BY Field3 COLLATE MYSEQUENCE DESC";
   879    897           string s = (string)cmd.ExecuteScalar();
   880    898           if (s != "Field3") throw new ArgumentOutOfRangeException("MySequence didn't sort properly");
   881    899         }
   882    900       }
          901  +
          902  +    private int nextId = 0;
          903  +    private const int MAX_THREADS = 3;
          904  +    private const int MAX_ITERATIONS = 100;
          905  +    private ManualResetEvent goEvent = new ManualResetEvent(false);
          906  +
          907  +    private static int GetThreadId()
          908  +    {
          909  +        return Thread.CurrentThread.ManagedThreadId;
          910  +    }
          911  +
          912  +    // Mutli-threading test.
          913  +    internal void MultipleThreadStress(DbConnection cnn)
          914  +    {
          915  +        string[] commands = {
          916  +            "CREATE TABLE TestThreads(Id INTEGER PRIMARY KEY, Data INTEGER);",
          917  +            "INSERT INTO TestThreads (Id, Data) VALUES (" +
          918  +                Interlocked.Increment(ref nextId).ToString() + ", " +
          919  +                GetThreadId().ToString() + ");"
          920  +        };
          921  +
          922  +        foreach (string command in commands)
          923  +        {
          924  +            using (DbCommand cmd = cnn.CreateCommand())
          925  +            {
          926  +                cmd.CommandText = command;
          927  +                cmd.ExecuteNonQuery();
          928  +            }
          929  +        }
          930  +
          931  +        Thread[] threads = new Thread[MAX_THREADS];
          932  +
          933  +        for (int index = 0; index < threads.Length; index++)
          934  +            threads[index] = new Thread(TestThreadStart);
          935  +
          936  +        for (int index = 0; index < threads.Length; index++)
          937  +            threads[index].Start();
          938  +
          939  +        goEvent.Set(); /* GO */
          940  +
          941  +        for (int index = 0; index < threads.Length; index++)
          942  +            threads[index].Join();
          943  +
          944  +        int count;
          945  +
          946  +        using (DbCommand cmd = cnn.CreateCommand())
          947  +        {
          948  +            cmd.CommandText = "SELECT COUNT(*) FROM TestThreads;";
          949  +            object value = cmd.ExecuteScalar();
          950  +            count = (value is int) ? (int)value : 0;
          951  +        }
          952  +
          953  +        if ((count >= MAX_THREADS) &&
          954  +            (count <= (MAX_THREADS * MAX_ITERATIONS)))
          955  +        {
          956  +            throw new ArgumentOutOfRangeException("Unexpected thread count");
          957  +        }
          958  +    }
          959  +
          960  +    private void TestThreadStart()
          961  +    {
          962  +        goEvent.WaitOne();
          963  +
          964  +        using (DbConnection cnn = Program.NewConnection())
          965  +        {
          966  +            Random random = new Random();
          967  +
          968  +            cnn.ConnectionString = this.connectionString;
          969  +            cnn.Open();
          970  +
          971  +            for (int index = 0; index < MAX_ITERATIONS; index++)
          972  +            {
          973  +                try
          974  +                {
          975  +                    using (DbTransaction trans = cnn.BeginTransaction())
          976  +                    {
          977  +                        string[] commands = {
          978  +                            "INSERT INTO TestThreads (Id, Data) VALUES (" +
          979  +                                Interlocked.Increment(ref nextId).ToString() + ", " +
          980  +                                GetThreadId().ToString() + ");"
          981  +                        };
          982  +
          983  +                        foreach (string command in commands)
          984  +                        {
          985  +                            using (DbCommand cmd = cnn.CreateCommand())
          986  +                            {
          987  +                                cmd.CommandText = command;
          988  +                                cmd.ExecuteNonQuery();
          989  +                            }
          990  +                        }
          991  +
          992  +                        if ((index > 0) && (random.Next() % 2 == 0))
          993  +                            throw new Exception("test exception");
          994  +
          995  +                        trans.Commit();
          996  +                    }
          997  +                }
          998  +                catch
          999  +                {
         1000  +                    // do nothing.
         1001  +                }
         1002  +            }
         1003  +        }
         1004  +    }
   883   1005     }
   884   1006   }