System.Data.SQLite
Check-in [09c5128542]
Not logged in

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

Overview
Comment:Add the ability for the test suite to track counts of CriticalHandle derived object instances. Also, slightly simplify test for ticket [6c6ecccc5f].
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 09c51285424e6eed03d7aaccdb0f834884215e74
User & Date: mistachkin 2012-10-26 20:37:04
Context
2012-10-26
20:47
Simplify critical handle count result matching by the threading test. check-in: be3b5a073a user: mistachkin tags: trunk
20:37
Add the ability for the test suite to track counts of CriticalHandle derived object instances. Also, slightly simplify test for ticket [6c6ecccc5f]. check-in: 09c5128542 user: mistachkin tags: trunk
18:16
Improvements to threading test. check-in: 3e3ebf10da user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to SQLite.NET.Settings.targets.

110
111
112
113
114
115
116













117
118
119
120
121
122
123
    <!--
        NOTE: Enable extra internal state checking for the public members of
              several key classes that use a connection.  By default, this is
              disabled.
    -->
    <CheckState Condition="'$(CheckState)' == ''">false</CheckState>














    <!--
        NOTE: For interaction with the native SQLite implementation, use the
              custom built interop DLL (i.e. "SQLite.Interop.dll")?  By default,
              this is enabled.  This property is mutually exclusive with the
              "UseSqliteStandard" one, below.  This should always be disabled in
              the project file that builds the NetModule target.
    -->







>
>
>
>
>
>
>
>
>
>
>
>
>







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
    <!--
        NOTE: Enable extra internal state checking for the public members of
              several key classes that use a connection.  By default, this is
              disabled.
    -->
    <CheckState Condition="'$(CheckState)' == ''">false</CheckState>

    <!--
        NOTE: Enable counting of all object instances for the CriticalHandle
              derived classes?  By default, this is disabled.  If this is
              enabled, this library will keep count of all non-disposed object
              instances for all the CriticalHandle derived classes.  Each
              counter will be incremented when an instance of the associated
              critical handle class is constructed and decremented when the
              ReleaseHandle method is completed successfully on an instance.
              These counts are intended to be used by the test suite to detect
              possible resource leaks.
    -->
    <CountHandle Condition="'$(CountHandle)' == ''">false</CountHandle>

    <!--
        NOTE: For interaction with the native SQLite implementation, use the
              custom built interop DLL (i.e. "SQLite.Interop.dll")?  By default,
              this is enabled.  This property is mutually exclusive with the
              "UseSqliteStandard" one, below.  This should always be disabled in
              the project file that builds the NetModule target.
    -->

Changes to Setup/set_user_mistachkin_Debug.bat.

9
10
11
12
13
14
15

16
17
18
:: Released to the public domain, use at your own risk!
::

REM
REM NOTE: Enables the extra debug code helpful in troubleshooting issues.
REM
SET MSBUILD_ARGS=/p:CheckState=true

SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceConnection=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceHandle=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceStatement=true







>



9
10
11
12
13
14
15
16
17
18
19
:: Released to the public domain, use at your own risk!
::

REM
REM NOTE: Enables the extra debug code helpful in troubleshooting issues.
REM
SET MSBUILD_ARGS=/p:CheckState=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:CountHandle=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceConnection=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceHandle=true
SET MSBUILD_ARGS=%MSBUILD_ARGS% /p:TraceStatement=true

Changes to System.Data.SQLite/SQLiteDefineConstants.cs.

11
12
13
14
15
16
17




18
19
20
21
22
23
24
{
    internal static class SQLiteDefineConstants
    {
        public static readonly IList<string> OptionList = new List<string>(new string[] {
#if CHECK_STATE
            "CHECK_STATE",
#endif





#if DEBUG
            "DEBUG",
#endif

#if INTEROP_CODEC
            "INTEROP_CODEC",







>
>
>
>







11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
{
    internal static class SQLiteDefineConstants
    {
        public static readonly IList<string> OptionList = new List<string>(new string[] {
#if CHECK_STATE
            "CHECK_STATE",
#endif

#if COUNT_HANDLE
            "COUNT_HANDLE",
#endif

#if DEBUG
            "DEBUG",
#endif

#if INTEROP_CODEC
            "INTEROP_CODEC",

Changes to System.Data.SQLite/System.Data.SQLite.Properties.targets.

66
67
68
69
70
71
72







73
74
75
76
77
78
79
  <!--
      NOTE: Enable extra internal state checking?
  -->
  <PropertyGroup Condition="'$(CheckState)' != 'false'">
    <DefineConstants>$(DefineConstants);CHECK_STATE</DefineConstants>
  </PropertyGroup>








  <!--
      NOTE: For interaction with the native SQLite implementation, use the
            custom build interop DLL (i.e. "SQLite.Interop.DLL")?
  -->
  <PropertyGroup Condition="'$(UseInteropDll)' != 'false'">
    <DefineConstants>$(DefineConstants);USE_INTEROP_DLL</DefineConstants>
  </PropertyGroup>







>
>
>
>
>
>
>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
  <!--
      NOTE: Enable extra internal state checking?
  -->
  <PropertyGroup Condition="'$(CheckState)' != 'false'">
    <DefineConstants>$(DefineConstants);CHECK_STATE</DefineConstants>
  </PropertyGroup>

  <!--
      NOTE: Enable counting of the CriticalHandle derived object instances?
  -->
  <PropertyGroup Condition="'$(CountHandle)' != 'false'">
    <DefineConstants>$(DefineConstants);COUNT_HANDLE</DefineConstants>
  </PropertyGroup>

  <!--
      NOTE: For interaction with the native SQLite implementation, use the
            custom build interop DLL (i.e. "SQLite.Interop.DLL")?
  -->
  <PropertyGroup Condition="'$(UseInteropDll)' != 'false'">
    <DefineConstants>$(DefineConstants);USE_INTEROP_DLL</DefineConstants>
  </PropertyGroup>

Changes to System.Data.SQLite/UnsafeNativeMethods.cs.

31
32
33
34
35
36
37



















38
39
40
41
42
43
44
....
1518
1519
1520
1521
1522
1523
1524




1525
1526
1527
1528
1529
1530
1531
....
1558
1559
1560
1561
1562
1563
1564




1565
1566
1567
1568
1569
1570
1571
....
1676
1677
1678
1679
1680
1681
1682




1683
1684
1685
1686
1687
1688
1689
....
1711
1712
1713
1714
1715
1716
1717




1718
1719
1720
1721
1722
1723
1724
....
1829
1830
1831
1832
1833
1834
1835




1836
1837
1838
1839
1840
1841
1842
....
1864
1865
1866
1867
1868
1869
1870




1871
1872
1873
1874
1875
1876
1877
#endif

#if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
  [SuppressUnmanagedCodeSecurity]
#endif
  internal static class UnsafeNativeMethods
  {



















      #region Optional Native SQLite Library Pre-Loading Code
      //
      // NOTE: If we are looking for the standard SQLite DLL ("sqlite3.dll"),
      //       the interop DLL ("SQLite.Interop.dll"), or we are running on the
      //       .NET Compact Framework, we should include this code (only if the
      //       feature has actually been enabled).  This code would be totally
      //       redundant if this module has been bundled into the mixed-mode
................................................................................
        }

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

        private SQLiteConnectionHandle()
            : base(IntPtr.Zero)
        {




        }

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

        protected override bool ReleaseHandle()
        {
            try
................................................................................
                    if (handle != IntPtr.Zero)
                    {
                        SQLiteBase.CloseConnection(this, handle);
                        SetHandle(IntPtr.Zero);
                    }
                }
#endif




#if DEBUG
                return true;
#endif
            }
#if !NET_COMPACT_20 && TRACE_HANDLE
            catch (SQLiteException e)
#else
................................................................................
        }

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

        private SQLiteStatementHandle()
            : base(IntPtr.Zero)
        {




        }

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

        protected override bool ReleaseHandle()
        {
            try
................................................................................
                    if (handle != IntPtr.Zero)
                    {
                        SQLiteBase.FinalizeStatement(cnn, handle);
                        SetHandle(IntPtr.Zero);
                    }
                }
#endif




#if DEBUG
                return true;
#endif
            }
#if !NET_COMPACT_20 && TRACE_HANDLE
            catch (SQLiteException e)
#else
................................................................................
        }

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

        private SQLiteBackupHandle()
            : base(IntPtr.Zero)
        {




        }

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

        protected override bool ReleaseHandle()
        {
            try
................................................................................
                    if (handle != IntPtr.Zero)
                    {
                        SQLiteBase.FinishBackup(cnn, handle);
                        SetHandle(IntPtr.Zero);
                    }
                }
#endif




#if DEBUG
                return true;
#endif
            }
#if !NET_COMPACT_20 && TRACE_HANDLE
            catch (SQLiteException e)
#else







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







 







>
>
>
>







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
....
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
....
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
....
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
....
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
....
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
....
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
#endif

#if !PLATFORM_COMPACTFRAMEWORK && !DEBUG
  [SuppressUnmanagedCodeSecurity]
#endif
  internal static class UnsafeNativeMethods
  {
      #region Critical Handle Counts (Debug Build Only)
#if COUNT_HANDLE
      //
      // NOTE: These counts represent the total number of outstanding
      //       (non-disposed) CriticalHandle derived object instances
      //       created by this library and are primarily for use by
      //       the test suite.  These counts are incremented by the
      //       associated constructors and are decremented upon the
      //       successful completion of the associated ReleaseHandle
      //       methods.
      //
      internal static int connectionCount;
      internal static int statementCount;
      internal static int backupCount;
#endif
      #endregion

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

      #region Optional Native SQLite Library Pre-Loading Code
      //
      // NOTE: If we are looking for the standard SQLite DLL ("sqlite3.dll"),
      //       the interop DLL ("SQLite.Interop.dll"), or we are running on the
      //       .NET Compact Framework, we should include this code (only if the
      //       feature has actually been enabled).  This code would be totally
      //       redundant if this module has been bundled into the mixed-mode
................................................................................
        }

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

        private SQLiteConnectionHandle()
            : base(IntPtr.Zero)
        {
#if COUNT_HANDLE
            Interlocked.Increment(
                ref UnsafeNativeMethods.connectionCount);
#endif
        }

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

        protected override bool ReleaseHandle()
        {
            try
................................................................................
                    if (handle != IntPtr.Zero)
                    {
                        SQLiteBase.CloseConnection(this, handle);
                        SetHandle(IntPtr.Zero);
                    }
                }
#endif
#if COUNT_HANDLE
                Interlocked.Decrement(
                    ref UnsafeNativeMethods.connectionCount);
#endif
#if DEBUG
                return true;
#endif
            }
#if !NET_COMPACT_20 && TRACE_HANDLE
            catch (SQLiteException e)
#else
................................................................................
        }

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

        private SQLiteStatementHandle()
            : base(IntPtr.Zero)
        {
#if COUNT_HANDLE
            Interlocked.Increment(
                ref UnsafeNativeMethods.statementCount);
#endif
        }

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

        protected override bool ReleaseHandle()
        {
            try
................................................................................
                    if (handle != IntPtr.Zero)
                    {
                        SQLiteBase.FinalizeStatement(cnn, handle);
                        SetHandle(IntPtr.Zero);
                    }
                }
#endif
#if COUNT_HANDLE
                Interlocked.Decrement(
                    ref UnsafeNativeMethods.statementCount);
#endif
#if DEBUG
                return true;
#endif
            }
#if !NET_COMPACT_20 && TRACE_HANDLE
            catch (SQLiteException e)
#else
................................................................................
        }

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

        private SQLiteBackupHandle()
            : base(IntPtr.Zero)
        {
#if COUNT_HANDLE
            Interlocked.Increment(
                ref UnsafeNativeMethods.backupCount);
#endif
        }

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

        protected override bool ReleaseHandle()
        {
            try
................................................................................
                    if (handle != IntPtr.Zero)
                    {
                        SQLiteBase.FinishBackup(cnn, handle);
                        SetHandle(IntPtr.Zero);
                    }
                }
#endif
#if COUNT_HANDLE
                Interlocked.Decrement(
                    ref UnsafeNativeMethods.backupCount);
#endif
#if DEBUG
                return true;
#endif
            }
#if !NET_COMPACT_20 && TRACE_HANDLE
            catch (SQLiteException e)
#else

Changes to Tests/common.eagle.

1098
1099
1100
1101
1102
1103
1104










































1105
1106
1107
1108
1109
1110
1111
....
1474
1475
1476
1477
1478
1479
1480



1481
1482
1483
1484
1485
1486
1487
      #
      if {[catch {object invoke GC GetTotalMemory true} error]} then {
        tputs $channel [appendArgs \
            "==== WARNING: failed full garbage collection, error: " \
            \n\t $error \n]
      }
    }










































 
    proc shutdownSQLite { channel {force false} {quiet false} } {
      #
      # NOTE: Make sure that SQLite core library is completely shutdown.  This
      #       is used by tests that change configuration options and/or those
      #       that need to make sure logging is initialized (i.e. just in case
      #       the SQLite core library was initialized in the process prior to
................................................................................

        #
        # NOTE: Attempt to determine if the custom extension functions were
        #       compiled into the SQLite interop assembly.
        #
        checkForSQLiteDefineConstant $::test_channel \
            CHECK_STATE




        checkForSQLiteDefineConstant $::test_channel \
            USE_INTEROP_DLL

        checkForSQLiteDefineConstant $::test_channel \
            INTEROP_EXTENSION_FUNCTIONS








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>







1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
....
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
      #
      if {[catch {object invoke GC GetTotalMemory true} error]} then {
        tputs $channel [appendArgs \
            "==== WARNING: failed full garbage collection, error: " \
            \n\t $error \n]
      }
    }
 
    proc getSQLiteHandleCounts { channel {zero false} {quiet false} } {
      set result [list]

      if {[haveConstraint \
              defineConstant.System.Data.SQLite.COUNT_HANDLE]} then {
        #
        # NOTE: Add each critical handle count to the resulting list.
        #
        foreach name [list connectionCount statementCount backupCount] {
          set value [object invoke -flags +NonPublic \
              System.Data.SQLite.UnsafeNativeMethods $name]

          if {!$quiet} then {
            tputs $channel [appendArgs \
                "---- critical handle count \"" $name "\" is " $value \n]
          }

          lappend result $value
        }
      } elseif {$zero} then {
        #
        # NOTE: The actual handle counts are not available; therefore, just
        #       return all zeros because the caller appears to need it for
        #       test result matching purposes.
        #
        if {!$quiet} then {
          tputs $channel \
              "---- critical handle counts unavailable, returning zeros...\n"
        }

        lappend result 0 0 0
      } elseif {!$quiet} then {
        #
        # NOTE: The actual handle counts are not available; therefore, just
        #       return an empty list.
        #
        tputs $channel "---- critical handle counts unavailable\n"
      }

      return $result
    }
 
    proc shutdownSQLite { channel {force false} {quiet false} } {
      #
      # NOTE: Make sure that SQLite core library is completely shutdown.  This
      #       is used by tests that change configuration options and/or those
      #       that need to make sure logging is initialized (i.e. just in case
      #       the SQLite core library was initialized in the process prior to
................................................................................

        #
        # NOTE: Attempt to determine if the custom extension functions were
        #       compiled into the SQLite interop assembly.
        #
        checkForSQLiteDefineConstant $::test_channel \
            CHECK_STATE

        checkForSQLiteDefineConstant $::test_channel \
            COUNT_HANDLE

        checkForSQLiteDefineConstant $::test_channel \
            USE_INTEROP_DLL

        checkForSQLiteDefineConstant $::test_channel \
            INTEROP_EXTENSION_FUNCTIONS

Changes to Tests/thread.eagle.

17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
...
445
446
447
448
449
450
451

452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

checkForSQLiteDirectories $test_channel true

set memory_used [reportSQLiteResources $test_channel true]

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

#
# NOTE: How many test threads should be created and used for these tests?  This
#       value must be at least two.  The first test thread (at index 0) is
#       always the "master thread" and just repeatedly calls the Thread.Abort()
................................................................................

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} RunTestThreads
      } result] : [set result ""]}] $result \
      [collectGarbage $test_channel] \

      [reportSQLiteResources $test_channel true]
} -cleanup {
  cleanupDb $fileName

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

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

unset -nocomplain count

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

unset -nocomplain memory_used

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

runSQLiteTestEpilogue
runTestEpilogue







>
|







 







>
|







|







|





17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
...
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475

package require System.Data.SQLite.Test
runSQLiteTestPrologue

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

checkForSQLiteDirectories $test_channel true
set handle_counts [getSQLiteHandleCounts $test_channel true]
set memory_used [reportSQLiteResources $test_channel]

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

#
# NOTE: How many test threads should be created and used for these tests?  This
#       value must be at least two.  The first test thread (at index 0) is
#       always the "master thread" and just repeatedly calls the Thread.Abort()
................................................................................

  list $code $results \
      [expr {[info exists errors] ? $errors : ""}] \
      [expr {$code eq "Ok" ? [catch {
        object invoke _Dynamic${id}.Test${id} RunTestThreads
      } result] : [set result ""]}] $result \
      [collectGarbage $test_channel] \
      [getSQLiteHandleCounts $test_channel true] \
      [reportSQLiteResources $test_channel]
} -cleanup {
  cleanupDb $fileName

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

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

unset -nocomplain count

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

unset -nocomplain memory_used handle_counts

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

runSQLiteTestEpilogue
runTestEpilogue

Changes to Tests/tkt-6c6ecccc5f.eagle.

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    CREATE VIRTUAL TABLE t1 USING fts4(x TEXT);
    INSERT INTO t1 (x) VALUES('one');
    INSERT INTO t1 (x) VALUES('two');
  }

  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]
  set sql "SELECT x FROM t1 WHERE x MATCH 'one' ORDER BY x;"

  unset -nocomplain results errors

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








|







27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
    CREATE VIRTUAL TABLE t1 USING fts4(x TEXT);
    INSERT INTO t1 (x) VALUES('one');
    INSERT INTO t1 (x) VALUES('two');
  }

  set id [object invoke Interpreter.GetActive NextId]
  set dataSource [file join [getDatabaseDirectory] $fileName]
  set sql "SELECT x FROM t1 WHERE x MATCH 'one';"

  unset -nocomplain results errors

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