System.Data.SQLite

Check-in [b2c3d6de86]
Login

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

Overview
Comment:Modify the unit test infrastructure to transform it into a formal Eagle package.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: b2c3d6de86298a252ba2df3bf336245d9019bead
User & Date: mistachkin 2011-09-28 22:48:10.850
Context
2011-09-29
00:37
Finish converting the unit test infrastructure to a full-fledged Eagle package. Also, update Eagle in externals to the latest beta 18 release candidate. check-in: b8b02007c6 user: mistachkin tags: trunk
2011-09-28
22:48
Modify the unit test infrastructure to transform it into a formal Eagle package. check-in: b2c3d6de86 user: mistachkin tags: trunk
2011-09-24
08:09
Fix optimized DbType lookup for database type names that contain parenthesis. check-in: 9d9fa54984 user: mistachkin tags: trunk
Changes
Unified Diff Ignore Whitespace Patch
Changes to Tests/common.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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390










391
###############################################################################
#
# common.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################







if {[isEagle]} then {




  proc getBuildYear {} {
    #
    # NOTE: See if the "year" setting has been overridden by the user (e.g. on
    #       the command line).  This helps control exactly which set of
    #       binaries we are testing, those produced using either the Visual
    #       Studio 2008 or Visual Studio 2010 build systems.  To override this
    #       value via the command line, enter a command similar to one of the
    #       following (all on one line):
    #
    #       EagleShell.exe -preInitialize "set test_year 2008"
    #         -file .\path\to\all.eagle
    #
    #       EagleShell.exe -preInitialize "set test_year 2010"
    #         -file .\path\to\all.eagle
    #
    #       EagleShell.exe -preInitialize "unset -nocomplain test_year"
    #         -file .\path\to\all.eagle
    #
    if {[info exists ::test_year] && [string length $::test_year] > 0} then {
      #
      # NOTE: Use the specified test year.  If this variable is not set, the
      #       default value will be based on whether or not Eagle has been
      #       compiled against the .NET Framework 2.0 or 4.0.
      #
      return $::test_year
    } else {
      #
      # NOTE: If Eagle has been compiled against the .NET Framework 4.0, use
      #       "2010" as the test year; otherwise, use "2008".  If another major
      #       [incompatible] version of the .NET Framework is released, this
      #       check will have to be changed.
      #
      return [expr {[haveConstraint imageRuntime40] ? "2010" : "2008"}]
    }
  }

  proc getBuildConfiguration {} {
    #
    # NOTE: See if the "configuration" setting has been overridden by the user
    #       (e.g. on the command line).  This helps control exactly which set
    #       of binaries we are testing (i.e. those built in the "Debug" or
    #       "Release" build configurations).  To override this value via the
    #       command line, enter a command similar to one of the following (all
    #       on one line):
    #
    #       EagleShell.exe -preInitialize "set test_configuration Debug"
    #         -file .\path\to\all.eagle
    #
    #       EagleShell.exe -preInitialize "set test_configuration Release"
    #         -file .\path\to\all.eagle
    #
    #       EagleShell.exe -file .\path\to\all.eagle -preTest
    #         "unset -nocomplain test_configuration"
    #
    if {[info exists ::test_configuration] && \
        [string length $::test_configuration] > 0} then {
      #
      # NOTE: Use the specified test configuration.  The default value used
      #       for this variable is "Release", as set by the test suite itself.
      #
      return $::test_configuration
    } else {
      #
      # NOTE: Normally, we will never hit this case because the value of the
      #       test configuration variable is always set by the test suite
      #       itself; however, it can be overridden using the unset command
      #       from the -preTest option to the test suite.
      #
      return $::eagle_platform(configuration)
    }
  }

  proc getBuildDirectory {} {
    #
    # NOTE: See if the "native" runtime option has been added.  If so, use the
    #       directory for the mixed-mode assembly (a.k.a. the native interop
    #       assembly).  To enable this option via the command line, enter a
    #       command similar to one of the following (all on one line):
    #
    #       EagleShell.exe -initialize -runtimeOption native
    #         -file .\path\to\all.eagle
    #
    #       To enable this option via the command line prior to the "beta 16"
    #       release of Eagle, the following command must be used instead (also
    #       all on one line):
    #
    #       EagleShell.exe -initialize -postInitialize
    #         "object invoke Interpreter.GetActive AddRuntimeOption native"
    #         -file .\path\to\all.eagle
    #
    if {[hasRuntimeOption native]} then {
      return [file join [file dirname $::path] bin [getBuildYear] \
          [machineToPlatform $::tcl_platform(machine)] [getBuildConfiguration]]

    } else {
      return [file join [file dirname $::path] bin [getBuildYear] \
          [getBuildConfiguration] bin]
    }
  }

  proc getBuildFileName { fileName } {
    return [file nativename \
        [file join [getBuildDirectory] [file tail $fileName]]]
  }

  proc getBinaryDirectory {} {
    #
    # NOTE: This procedure returns the directory where the test application
    #       itself (i.e. the Eagle shell) is located.  This will be used as
    #       the destination for the copied System.Data.SQLite native and
    #       managed assemblies (i.e. because this is one of the few places
    #       where the CLR will actually find and load them properly).
    #
    return [info binary]
  }

  proc getBinaryFileName { fileName } {
    return [file nativename \
        [file join [getBinaryDirectory] [file tail $fileName]]]
  }

  proc tryCopyBuildFile { fileName } {
    #
    # NOTE: If we cannot copy the assembly then it is probably already loaded.
    #
    set sourceFileName [getBuildFileName $fileName]

    if {![file exists $sourceFileName]} then {
      tputs $::test_channel [appendArgs \
          "---- skipped copying build file \"" $sourceFileName \
          "\", it does not exist\n"]

      return
    }

    set targetFileName [getBinaryFileName $fileName]


    if {[catch {file copy -force $sourceFileName $targetFileName}] == 0} then {
      tputs $::test_channel [appendArgs \
          "---- copied build file from \"" $sourceFileName "\" to \"" \
          $targetFileName \"\n]
    } else {
      tputs $::test_channel [appendArgs \
          "---- failed to copy build file from \"" $sourceFileName "\" to \"" \
          $targetFileName \"\n]
    }
  }

  proc tryDeleteBinaryFile { fileName } {
    set fileName [getBinaryFileName $fileName]

    if {![file exists $fileName]} then {
      tputs $::test_channel [appendArgs \
          "---- skipped deleting binary file \"" $fileName \
          "\", it does not exist\n"]

      return
    }

    if {[catch {file delete $fileName}] == 0} then {
      tputs $::test_channel [appendArgs \
          "---- deleted binary file \"" $fileName \"\n]
    } else {
      tputs $::test_channel [appendArgs \
          "---- failed to delete binary file \"" $fileName \"\n]
    }
  }

  proc tryCopyAssembly { fileName {pdb true} } {
    tryCopyBuildFile $fileName

    if {$pdb} then {
      tryCopyBuildFile [appendArgs [file rootname $fileName] .pdb]
    }
  }

  proc tryDeleteAssembly { fileName {pdb true} } {
    tryDeleteBinaryFile $fileName

    if {$pdb} then {
      tryDeleteBinaryFile [appendArgs [file rootname $fileName] .pdb]
    }
  }

  proc tryLoadAssembly { fileName } {
    set fileName [getBuildFileName $fileName]

    if {[catch {set assembly \
        [object load -loadtype File $fileName]}] == 0} then {
      #
      # NOTE: Now, add the necessary test constraint.
      #
      addConstraint [file rootname [file tail $fileName]]

      #
      # NOTE: Return the full path of the loaded file.
      #
      return $fileName
    }

    return ""
  }

  proc enumerableToList { enumerable } {
    set result [list]

    if {[string length $enumerable] == 0 || $enumerable eq "null"} then {
      return $result
    }

    object foreach -alias item $enumerable {
      if {[string length $item] > 0} then {
        lappend result [$item ToString]
      }
    }

    return $result
  }


  proc compileCSharpWith { text resultsVarName errorsVarName fileNames args } {
    #
    # NOTE: Create the base command to evaluate and add the property settings
    #       that are almost always needed by our unit tests (i.e. the System
    #       and System.Data assembly references).
    #
    set command [list compileCSharp $text results errors \
        ReferencedAssemblies.Add System.dll ReferencedAssemblies.Add \
        System.Data.dll ReferencedAssemblies.Add System.Xml.dll]

    #
    # NOTE: Add all the provided file names as assembly references.
    #
    foreach fileName $fileNames {
      lappend command ReferencedAssemblies.Add [getBuildFileName $fileName]
    }

    #
    # NOTE: Add the extra arguments, if any, to the command to evaluate.
    #
    eval lappend command $args

    #
    # NOTE: Alias the compiler local results and errors variables to the
    #       variable names provided by our caller.
    #
    upvar 1 $resultsVarName results
    upvar 1 $errorsVarName errors

    #
    # NOTE: Evaluate the constructed [compileCSharp] command and return the
    #       result.
    #
    eval $command
  }

  proc setupDb {fileName {mode ""} {delete ""} {extra ""} {varName db}} {
    #
    # NOTE: For now, all test databases used by the test suite are placed into
    #       the temporary directory.  Each database used by a test should be
    #       cleaned up by that test using the "cleanupDb" procedure, below.
    #
    set fileName [file join [getTemporaryPath] [file tail $fileName]]

    #
    # NOTE: By default, delete any pre-existing database with the same file
    #       name.
    #
    if {[string length $delete] == 0 || $delete} then {
      catch {file delete $fileName}
    }

    #
    # NOTE: Refer to the specified variable (e.g. "db") in the context of the
    #       caller.  The handle to the opened database will be stored there.
    #
    upvar 1 $varName db

    #
    # NOTE: Start building the connection string.  The only required portion
    #       of the connection string is the database file name itself.
    #
    set connection {Data Source=${fileName}}

    #
    # NOTE: If the caller specified a journal mode, add the necessary portion
    #       of the connection string now.
    #
    if {[string length $mode] > 0} then {
      append connection {;Journal Mode=${mode}}
    }

    #
    # NOTE: If the caller specified an extra payload to the connection string,
    #       append it now.
    #
    if {[string length $extra] > 0} then {
      append connection \; $extra
    }

    #
    # NOTE: Open the database connection now, placing the opaque handle value
    #       into the variable specified by the caller.
    #
    set db [sql open -type SQLite [subst $connection]]
  }

  proc cleanupDb {fileName {varName db}} {
    #
    # NOTE: Refer to the specified variable (e.g. "db") in the context of the
    #       caller.  The handle to the opened database is stored there.
    #
    upvar 1 $varName db

    #
    # NOTE: Close the connection to the database now.  This should allow us to
    #       delete the underlying database file.
    #
    catch {sql close $db}

    #
    # NOTE: Delete the test database file now.  For now, all test database
    #       files are stored in the temporary directory.
    #
    catch {file delete [file join [getTemporaryPath] [file tail $fileName]]}
  }

  proc runSQLiteTestPrologue {} {
    #
    # NOTE: Skip running our custom prologue if the main one has been skipped.
    #
    if {![info exists ::no(prologue.eagle)]} then {
      tryDeleteAssembly SQLite.Interop.dll
      tryDeleteAssembly System.Data.SQLite.dll
      tryDeleteAssembly System.Data.SQLite.Linq.dll

      tryCopyAssembly SQLite.Interop.dll
      tryCopyAssembly System.Data.SQLite.dll
      tryCopyAssembly System.Data.SQLite.Linq.dll

      tryLoadAssembly System.Data.SQLite.dll
      tryLoadAssembly System.Data.SQLite.Linq.dll

      catch {
        tputs $::test_channel [appendArgs \
            "---- file version of \"SQLite.Interop.dll\"... " \
            [file version [getBinaryFileName SQLite.Interop.dll]] \n]
      }

      catch {
        tputs $::test_channel [appendArgs \
            "---- file version of \"System.Data.SQLite.dll\"... " \
            [file version [getBinaryFileName System.Data.SQLite.dll]] \n]
      }

      catch {
        tputs $::test_channel [appendArgs \
            "---- file version of \"System.Data.SQLite.Linq.dll\"... " \
            [file version [getBinaryFileName System.Data.SQLite.Linq.dll]] \n]
      }

      set assemblies [object invoke AppDomain.CurrentDomain GetAssemblies]

      object foreach assembly $assemblies {
        if {[string match \{System.Data.SQLite* $assembly]} then {
          tputs $::test_channel [appendArgs \
              "---- found assembly: " $assembly \n]
        }
      }
    }
  }

  proc runSQLiteTestEpilogue {} {
    #
    # NOTE: Skip running our custom epilogue if the main one has been skipped.
    #
    if {![info exists ::no(epilogue.eagle)]} then {
      #
      # NOTE: For now, nothing is done here.
      #
    }
  }










}









>
>
>
>
>
>
|
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|
|
|
|
|

|
|
|
|

|
|
|
|
|

|
|
|
|

|
|

|

>
|
|
|
|
|
|
|
|
|
|

|
|

|
|
|
|

|
|

|
|
|
|
|
|
|
|

|
|

|
|
|
|

|
|

|
|
|
|

|
|

|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|
|

|
|
|
|
|

|
|

>
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|

|
|
|
|
|
|

|
|
|
|
|
|
|
|

|
|
|

|
|

|
|
|
|
|

|
|
|
|
|

|
|
|
|
|

|

|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
>
>
>
>
>
>
>
>
>
>

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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
###############################################################################
#
# common.eagle --
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

#
# NOTE: Use our own namespace here because even though we do not directly
#       support namespaces ourselves, we do not want to pollute the global
#       namespace if this script actually ends up being evaluated in Tcl.
#
namespace eval ::Eagle {
  if {[isEagle]} then {
    ###########################################################################
    ############################ BEGIN Eagle ONLY #############################
    ###########################################################################

    proc getBuildYear {} {
      #
      # NOTE: See if the "year" setting has been overridden by the user (e.g. on
      #       the command line).  This helps control exactly which set of
      #       binaries we are testing, those produced using either the Visual
      #       Studio 2008 or Visual Studio 2010 build systems.  To override this
      #       value via the command line, enter a command similar to one of the
      #       following (all on one line):
      #
      #       EagleShell.exe -preInitialize "set test_year 2008"
      #         -file .\path\to\all.eagle
      #
      #       EagleShell.exe -preInitialize "set test_year 2010"
      #         -file .\path\to\all.eagle
      #
      #       EagleShell.exe -preInitialize "unset -nocomplain test_year"
      #         -file .\path\to\all.eagle
      #
      if {[info exists ::test_year] && [string length $::test_year] > 0} then {
        #
        # NOTE: Use the specified test year.  If this variable is not set, the
        #       default value will be based on whether or not Eagle has been
        #       compiled against the .NET Framework 2.0 or 4.0.
        #
        return $::test_year
      } else {
        #
        # NOTE: If Eagle has been compiled against the .NET Framework 4.0, use
        #       "2010" as the test year; otherwise, use "2008".  If another
        #       major [incompatible] version of the .NET Framework is released,
        #       this check will have to be changed.
        #
        return [expr {[haveConstraint imageRuntime40] ? "2010" : "2008"}]
      }
    }

    proc getBuildConfiguration {} {
      #
      # NOTE: See if the "configuration" setting has been overridden by the user
      #       (e.g. on the command line).  This helps control exactly which set
      #       of binaries we are testing (i.e. those built in the "Debug" or
      #       "Release" build configurations).  To override this value via the
      #       command line, enter a command similar to one of the following (all
      #       on one line):
      #
      #       EagleShell.exe -preInitialize "set test_configuration Debug"
      #         -file .\path\to\all.eagle
      #
      #       EagleShell.exe -preInitialize "set test_configuration Release"
      #         -file .\path\to\all.eagle
      #
      #       EagleShell.exe -file .\path\to\all.eagle -preTest
      #         "unset -nocomplain test_configuration"
      #
      if {[info exists ::test_configuration] && \
          [string length $::test_configuration] > 0} then {
        #
        # NOTE: Use the specified test configuration.  The default value used
        #       for this variable is "Release", as set by the test suite itself.
        #
        return $::test_configuration
      } else {
        #
        # NOTE: Normally, we will never hit this case because the value of the
        #       test configuration variable is always set by the test suite
        #       itself; however, it can be overridden using the unset command
        #       from the -preTest option to the test suite.
        #
        return $::eagle_platform(configuration)
      }
    }

    proc getBuildDirectory {} {
      #
      # NOTE: See if the "native" runtime option has been added.  If so, use the
      #       directory for the mixed-mode assembly (a.k.a. the native interop
      #       assembly).  To enable this option via the command line, enter a
      #       command similar to one of the following (all on one line):
      #
      #       EagleShell.exe -initialize -runtimeOption native
      #         -file .\path\to\all.eagle
      #
      #       To enable this option via the command line prior to the "beta 16"
      #       release of Eagle, the following command must be used instead
      #       (also all on one line):
      #
      #       EagleShell.exe -initialize -postInitialize
      #         "object invoke Interpreter.GetActive AddRuntimeOption native"
      #         -file .\path\to\all.eagle
      #
      if {[hasRuntimeOption native]} then {
        return [file join [file dirname $::path] bin [getBuildYear] \
            [machineToPlatform $::tcl_platform(machine)] \
            [getBuildConfiguration]]
      } else {
        return [file join [file dirname $::path] bin [getBuildYear] \
            [getBuildConfiguration] bin]
      }
    }

    proc getBuildFileName { fileName } {
      return [file nativename \
          [file join [getBuildDirectory] [file tail $fileName]]]
    }

    proc getBinaryDirectory {} {
      #
      # NOTE: This procedure returns the directory where the test application
      #       itself (i.e. the Eagle shell) is located.  This will be used as
      #       the destination for the copied System.Data.SQLite native and
      #       managed assemblies (i.e. because this is one of the few places
      #       where the CLR will actually find and load them properly).
      #
      return [info binary]
    }

    proc getBinaryFileName { fileName } {
      return [file nativename \
          [file join [getBinaryDirectory] [file tail $fileName]]]
    }

    proc tryCopyBuildFile { fileName } {
      #
      # NOTE: If we cannot copy the assembly then it is probably already loaded.
      #
      set sourceFileName [getBuildFileName $fileName]

      if {![file exists $sourceFileName]} then {
        tputs $::test_channel [appendArgs \
            "---- skipped copying build file \"" $sourceFileName \
            "\", it does not exist\n"]

        return
      }

      set targetFileName [getBinaryFileName $fileName]

      if {[catch {
          file copy -force $sourceFileName $targetFileName}] == 0} then {
        tputs $::test_channel [appendArgs \
            "---- copied build file from \"" $sourceFileName "\" to \"" \
            $targetFileName \"\n]
      } else {
        tputs $::test_channel [appendArgs \
            "---- failed to copy build file from \"" $sourceFileName \
            "\" to \"" $targetFileName \"\n]
      }
    }

    proc tryDeleteBinaryFile { fileName } {
      set fileName [getBinaryFileName $fileName]

      if {![file exists $fileName]} then {
        tputs $::test_channel [appendArgs \
            "---- skipped deleting binary file \"" $fileName \
            "\", it does not exist\n"]

        return
      }

      if {[catch {file delete $fileName}] == 0} then {
        tputs $::test_channel [appendArgs \
            "---- deleted binary file \"" $fileName \"\n]
      } else {
        tputs $::test_channel [appendArgs \
            "---- failed to delete binary file \"" $fileName \"\n]
      }
    }

    proc tryCopyAssembly { fileName {pdb true} } {
      tryCopyBuildFile $fileName

      if {$pdb} then {
        tryCopyBuildFile [appendArgs [file rootname $fileName] .pdb]
      }
    }

    proc tryDeleteAssembly { fileName {pdb true} } {
      tryDeleteBinaryFile $fileName

      if {$pdb} then {
        tryDeleteBinaryFile [appendArgs [file rootname $fileName] .pdb]
      }
    }

    proc tryLoadAssembly { fileName } {
      set fileName [getBuildFileName $fileName]

      if {[catch {set assembly \
          [object load -loadtype File $fileName]}] == 0} then {
        #
        # NOTE: Now, add the necessary test constraint.
        #
        addConstraint [file rootname [file tail $fileName]]

        #
        # NOTE: Return the full path of the loaded file.
        #
        return $fileName
      }

      return ""
    }
  
    proc enumerableToList { enumerable } {
      set result [list]

      if {[string length $enumerable] == 0 || $enumerable eq "null"} then {
        return $result
      }

      object foreach -alias item $enumerable {
        if {[string length $item] > 0} then {
          lappend result [$item ToString]
        }
      }

      return $result
    }

    proc compileCSharpWith {
            text resultsVarName errorsVarName fileNames args } {
      #
      # NOTE: Create the base command to evaluate and add the property settings
      #       that are almost always needed by our unit tests (i.e. the System
      #       and System.Data assembly references).
      #
      set command [list compileCSharp $text results errors \
          ReferencedAssemblies.Add System.dll ReferencedAssemblies.Add \
          System.Data.dll ReferencedAssemblies.Add System.Xml.dll]

      #
      # NOTE: Add all the provided file names as assembly references.
      #
      foreach fileName $fileNames {
        lappend command ReferencedAssemblies.Add [getBuildFileName $fileName]
      }

      #
      # NOTE: Add the extra arguments, if any, to the command to evaluate.
      #
      eval lappend command $args

      #
      # NOTE: Alias the compiler local results and errors variables to the
      #       variable names provided by our caller.
      #
      upvar 1 $resultsVarName results
      upvar 1 $errorsVarName errors

      #
      # NOTE: Evaluate the constructed [compileCSharp] command and return the
      #       result.
      #
      eval $command
    }

    proc setupDb {fileName {mode ""} {delete ""} {extra ""} {varName db}} {
      #
      # NOTE: For now, all test databases used by the test suite are placed into
      #       the temporary directory.  Each database used by a test should be
      #       cleaned up by that test using the "cleanupDb" procedure, below.
      #
      set fileName [file join [getTemporaryPath] [file tail $fileName]]

      #
      # NOTE: By default, delete any pre-existing database with the same file
      #       name.
      #
      if {[string length $delete] == 0 || $delete} then {
        catch {file delete $fileName}
      }

      #
      # NOTE: Refer to the specified variable (e.g. "db") in the context of the
      #       caller.  The handle to the opened database will be stored there.
      #
      upvar 1 $varName db

      #
      # NOTE: Start building the connection string.  The only required portion
      #       of the connection string is the database file name itself.
      #
      set connection {Data Source=${fileName}}

      #
      # NOTE: If the caller specified a journal mode, add the necessary portion
      #       of the connection string now.
      #
      if {[string length $mode] > 0} then {
        append connection {;Journal Mode=${mode}}
      }

      #
      # NOTE: If the caller specified an extra payload to the connection string,
      #       append it now.
      #
      if {[string length $extra] > 0} then {
        append connection \; $extra
      }

      #
      # NOTE: Open the database connection now, placing the opaque handle value
      #       into the variable specified by the caller.
      #
      set db [sql open -type SQLite [subst $connection]]
    }

    proc cleanupDb {fileName {varName db}} {
      #
      # NOTE: Refer to the specified variable (e.g. "db") in the context of the
      #       caller.  The handle to the opened database is stored there.
      #
      upvar 1 $varName db

      #
      # NOTE: Close the connection to the database now.  This should allow us to
      #       delete the underlying database file.
      #
      catch {sql close $db}

      #
      # NOTE: Delete the test database file now.  For now, all test database
      #       files are stored in the temporary directory.
      #
      catch {file delete [file join [getTemporaryPath] [file tail $fileName]]}
    }

    proc runSQLiteTestPrologue {} {
      #
      # NOTE: Skip running our custom prologue if the main one has been skipped.
      #
      if {![info exists ::no(prologue.eagle)]} then {
        tryDeleteAssembly SQLite.Interop.dll
        tryDeleteAssembly System.Data.SQLite.dll
        tryDeleteAssembly System.Data.SQLite.Linq.dll

        tryCopyAssembly SQLite.Interop.dll
        tryCopyAssembly System.Data.SQLite.dll
        tryCopyAssembly System.Data.SQLite.Linq.dll

        tryLoadAssembly System.Data.SQLite.dll
        tryLoadAssembly System.Data.SQLite.Linq.dll

        catch {
          tputs $::test_channel [appendArgs \
              "---- file version of \"SQLite.Interop.dll\"... " \
              [file version [getBinaryFileName SQLite.Interop.dll]] \n]
        }

        catch {
          tputs $::test_channel [appendArgs \
              "---- file version of \"System.Data.SQLite.dll\"... " \
              [file version [getBinaryFileName System.Data.SQLite.dll]] \n]
        }

        catch {
          tputs $::test_channel [appendArgs \
              "---- file version of \"System.Data.SQLite.Linq.dll\"... " \
              [file version [getBinaryFileName System.Data.SQLite.Linq.dll]] \n]
        }

        set assemblies [object invoke AppDomain.CurrentDomain GetAssemblies]

        object foreach assembly $assemblies {
          if {[string match \{System.Data.SQLite* $assembly]} then {
            tputs $::test_channel [appendArgs \
                "---- found assembly: " $assembly \n]
          }
        }
      }
    }

    proc runSQLiteTestEpilogue {} {
      #
      # NOTE: Skip running our custom epilogue if the main one has been skipped.
      #
      if {![info exists ::no(epilogue.eagle)]} then {
        #
        # NOTE: For now, nothing is done here.
        #
      }
    }

    ###########################################################################
    ############################# END Eagle ONLY ##############################
    ###########################################################################
  }

  #
  # NOTE: Provide the System.Data.SQLite test package to the interpreter.
  #
  package provide System.Data.SQLite.Test 1.0
}