System.Data.SQLite
Check-in [e791e34148]
Not logged in

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

Overview
Comment:Add automation capable of deploying and running the .NET Compact Framework test application.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e791e34148b8e4609df3bbccf65b178d01211555
User & Date: mistachkin 2012-10-09 08:45:23
Context
2012-10-09
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
08:45
Add automation capable of deploying and running the .NET Compact Framework test application. check-in: e791e34148 user: mistachkin tags: trunk
03:26
Enhancements to the 'testce' project that allow it to be automated. check-in: 3c8aa6ed17 user: mistachkin tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Added Setup/deployAndTestCe.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
###############################################################################
#
# deployAndTestCe.eagle -- Windows CE Deployment & Testing Tool
#
# Written by Joe Mistachkin.
# Released to the public domain, use at your own risk!
#
###############################################################################

package require Eagle
 
proc usage { error } {
  if {[string length $error] > 0} then {puts stdout $error}

  puts stdout "usage:\
[file tail [info nameofexecutable]]\
[file tail [info script]] \[year\] \[platform\] \[configuration\]\
\[culture\] \[platformId\] \[deviceId\] \[quiet\]"

  #
  # NOTE: Indicate to the caller, if any, that we have failed.
  #
  exit 1
}
 
#
# NOTE: This procedure will output a diagnostic message, typically to the
#       standard output channel, using the [puts] command unless the global
#       variable "quiet" is non-zero.
#
proc qputs { args } {
  if {!$::quiet} then {
    eval puts $args; flush stdout
  }
}
 
#
# NOTE: This procedure looks up and returns the target device based on the
#       locale, platform Id, and device Id.
#
proc getDevice { cultureInfo platformId deviceId } {
  set datastoreManager [object create -alias \
      Microsoft.SmartDevice.Connectivity.DatastoreManager \
      [$cultureInfo LCID]]

  set platform [$datastoreManager -alias GetPlatform [object create \
      Microsoft.SmartDevice.Connectivity.ObjectId $platformId]]

  if {[string length $deviceId] == 0} then {
    set deviceId [$platform GetDefaultDeviceId]
  }

  set device [$platform -alias GetDevice $deviceId]

  qputs stdout [appendArgs \
      "returning device \"" [$device Name] "\" of platform \"" \
      [$device Platform.ToString] "\" with Id \"" [$device Id.ToString] \
      \"...]

  return $device
}
 
#
# NOTE: This procedure starts a process on the target device and optionally
#       waits for it to complete.
#
proc startRemoteProcess { device fileName arguments {wait true} } {
  set remoteProcess [$device -alias GetRemoteProcess]

  if {![$remoteProcess Start $fileName $arguments]} then {
    error [appendArgs "could not start remote process \"" $fileName \"]
  }

  if {$wait} then {
    qputs stdout [appendArgs \
        "waiting for remote process " [$remoteProcess GetId] ...]

    while {![$remoteProcess HasExited]} {
      qputs -nonewline stdout .
      after 1000
    }

    qputs stdout ""
    return [$remoteProcess GetExitCode]
  }

  return -1
}
 
set argc [llength $argv]

if {$argc >= 0 && $argc <= 7} then {
  #
  # NOTE: Setup the default values for all command line options.
  #
  array set default {
            year 2008
        platform {Pocket PC 2003 (ARMV4)}
   configuration Release
         culture en-US
      platformId 3c41c503-53ef-4c2a-8dd4-a8217cad115e
        deviceId {}
           quiet false
  }

  #
  # NOTE: Process all the command line options.  If a command line option
  #       is not present, use the default value.
  #
  set names [list \
      year platform configuration culture platformId deviceId quiet]

  for {set index 0} {$index < [llength $names]} {incr index} {
    set name [lindex $names $index]; set value ""

    if {$argc > $index} then {
      set value [string trim [lindex $argv $index]]
    }

    if {[string length $value] > 0} then {
      set $name $value
    } else {
      set $name $default($name)
    }
  }

  #
  # NOTE: Grab the culture instance based on the configured culture name.
  #
  set cultureInfo [object invoke -alias System.Globalization.CultureInfo \
      GetCultureInfo $culture]

  #
  # NOTE: Build the list of .NET Compact Framework packages that need to be
  #       deployed to the target device.
  #
  if {![info exists packages]} then {
    #
    # NOTE: The two letter ISO language name is needed when building the
    #       default list of .NET Compact Framework packages because one of
    #       them is a localized resource package.
    #
    set language [string toupper [$cultureInfo TwoLetterISOLanguageName]]

    #
    # NOTE: The default list of .NET Compact Framework packages contains the
    #       .NET Compact Framework 3.5 installation CAB file for ARMV4 on the
    #       Pocket PC and its associated resource installation CAB file.
    #
    set packages [list abd785f0-cda7-41c5-8375-2451a7cbff37 \
        \\windows\\NETCFv35.ppc.armv4.cab c0ccf48e-4bfb-4d84-827c-981a595e40c5 \
        [appendArgs \\windows\\NETCFv35.Messages. $language .cab]]
  }

  #
  # NOTE: Save the path where this script is running from.
  #
  set path [file dirname [info script]]

  #
  # NOTE: The base path should be the project root directory, which should
  #       be one level above the one containing this script.
  #
  set base_path [file dirname $path]

  #
  # NOTE: The managed binaries to be deployed to the target device should
  #       be located in the "<base>\bin\<year>\<configuration>Compact\bin"
  #       directory.
  #
  set managed_directory [file join \
      $base_path bin $year [appendArgs $configuration Compact] bin]

  #
  # NOTE: The native binaries to be deployed to the target device should
  #       be located in the "<base>\bin\<year>\<platform>\<configuration>"
  #       directory.
  #
  set native_directory [file join \
      $base_path bin $year $platform $configuration]

  #
  # NOTE: Build the list of all application files that need to be deployed to
  #       the target device, including all the native and managed binaries.
  #
  if {![info exists fileNames]} then {
    #
    # NOTE: Grab the assembly name instance based on the primary managed
    #       assembly file name.  This is needed because the build portion of
    #       the assembly version is used when building the default list of
    #       application files to be deployed to the target device.
    #
    set assemblyName [object invoke -alias System.Reflection.AssemblyName \
        GetAssemblyName [file join $managed_directory System.Data.SQLite.dll]]

    #
    # NOTE: The default list of application files includes the test application
    #       itself, the System.Data.SQLite managed assembly, the SQLite interop
    #       assembly, and the test application configuration file.
    #
    set fileNames [list [file join $managed_directory testce.exe] [file \
        join $managed_directory System.Data.SQLite.dll] [file join \
        $native_directory [appendArgs SQLite.Interop. [format %03d \
        [$assemblyName Version.Build]] .dll]] [file join $managed_directory \
        test.cfg]]
  }

  #
  # NOTE: Setup the directory on the target device where the application files
  #       should be deployed to.
  #
  if {![info exists device_directory]} then {
    set device_directory "\\Program Files\\testce\\"
  }

  #
  # NOTE: Load the managed assembly that allows us to communicate with the
  #       target device.  If this fails, the necessary SDK components are
  #       probably not available on this system.
  #
  object load Microsoft.Smartdevice.Connectivity

  #
  # NOTE: Lookup the necessary device based on the platform and device Ids.
  #
  set device [getDevice $cultureInfo $platformId $deviceId]

  #
  # NOTE: Attempt to connect to the target device, which may be an emulator.
  #       By default, we attempt to connect to the "Pocket PC 2003 SE Emulator"
  #       device of the "Pocket PC 2003" platform (English).  If this fails,
  #       the target device is probably unavailable, either because it is not
  #       connected or some SDK components are missing.
  #
  $device Connect

  #
  # NOTE: Grab the file deployer instance for the target device.  This will
  #       be used to download packages and send files to the target device.
  #
  set fileDeployer [$device -alias GetFileDeployer]

  #
  # NOTE: Process each entry in the list of packages to be downloaded to the
  #       target device.  The package list must contain the package Id and the
  #       file name (relative to the target device), in that order, for each
  #       package to be downloaded to the target device.
  #
  foreach {packageId packageFileName} $packages {
    qputs stdout [appendArgs \
        "downloading package \"" $packageId "\" to device..."]

    $fileDeployer DownloadPackage [object create \
        Microsoft.SmartDevice.Connectivity.ObjectId $packageId]

    qputs stdout [appendArgs \
        "installing package file \"" $packageFileName "\" on device..."]

    startRemoteProcess $device wceload.exe [appendArgs "/noui " \
        $packageFileName]
  }

  #
  # NOTE: Process each application file to be sent to the target device.
  #
  foreach fileName $fileNames {
    qputs stdout [appendArgs \
        "sending file \"" $fileName "\" to device..."]

    #
    # NOTE: All the application files are sent to the same directory on the
    #       target device and the SendFile method requires a fully qualified
    #       file name; therefore, grab the file name only from the source file
    #       name and append that to the directory name on the target device.
    #       Using [file join] and/or [file normalize] should be avoided here
    #       because the directory name on the target device is not necessarily
    #       valid a file name on this system and vice versa.
    #
    $fileDeployer SendFile $fileName [appendArgs $device_directory \
        [file tail $fileName]] true false
  }

  #
  # NOTE: Run the test application on the target device in "automatic" mode
  #       (i.e. no user interaction is required) and capture the exit code.
  #       The exit code will be zero upon success (i.e. all tests passed) or
  #       non-zero otherwise.
  #
  set testFileName [file nativename [file join $device_directory testce.exe]]
  set exitCode [startRemoteProcess $device $testFileName true]

  #
  # NOTE: Is the target device actually an emulator running on this system?
  #
  set isEmulator [$device IsEmulator]

  #
  # NOTE: We no longer need to be connected to the target device.
  #
  $device Disconnect

  #
  # NOTE: Also, if the device is an emulator, attempt to shutdown the process
  #       containing it now (since we probably caused it to start).
  #
  if {$isEmulator} then {
    #
    # NOTE: Try to find the top-level window for the device emulator process
    #       based on the "LCDDisplay" window class name.  Using this method
    #       of finding the target window is somewhat fragile and may not work
    #       reliably in the future.
    #
    set hWnd [lindex [lindex [info windows LCDDisplay] 0] 0]; # FIXME: ???

    #
    # NOTE: Make sure we found it before trying to lookup the parent process.
    #
    if {[string is integer -strict $hWnd] && $hWnd != 0} then {
      #
      # NOTE: Attempt to lookup the parent process for the target window.
      #
      qputs stdout [appendArgs "found device emulator window handle " $hWnd \
          ", looking up the process Id..."]

      set processId 0; set threadId 0; set error null

      if {[object invoke -flags +NonPublic \
          Eagle._Components.Private.WindowOps GetWindowThreadProcessId \
          [object create IntPtr $hWnd] processId threadId error] eq "Ok" && \
          [string is integer -strict $processId] && $processId != 0} then {
        #
        # NOTE: This is not ideal; however, if we simply try to close the
        #       target window, it will prompt to save state changes and that
        #       requires user interaction.  We never want to save the state;
        #       therefore, just forcibly kill the process containing the
        #       emulator.
        #
        qputs stdout [appendArgs "found device emulator process Id " \
            $processId ", killing..."]

        kill -force $processId
      }
    }
  }

  #
  # NOTE: Print the overall result of running the test application and exit
  #       using the exit code from the test application on the target device.
  #
  qputs stdout [expr {$exitCode == 0 ? "SUCCESS" : "FAILURE"}]
  exit $exitCode
} else {
  usage ""
}

Changes to Setup/verify.lst.

503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
###############################################################################
#
# NOTE: This is the list of interop and other files that should be present in
#       the standard "PocketPC" binary archives (i.e. for the .NET Compact
#       Framework).
#
set sds_manifests(binaryCompact) {
  "SQLite.Interop.[format %03d $build].dll"
  "SQLite.Interop.[format %03d $build].pdb"
  test.cfg
  testce.exe
  testce.pdb
}
 
###############################################################################
#







|
|







503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
###############################################################################
#
# NOTE: This is the list of interop and other files that should be present in
#       the standard "PocketPC" binary archives (i.e. for the .NET Compact
#       Framework).
#
set sds_manifests(binaryCompact) {
  [appendArgs SQLite.Interop. [format %03d $build] .dll]
  [appendArgs SQLite.Interop. [format %03d $build] .pdb]
  test.cfg
  testce.exe
  testce.pdb
}
 
###############################################################################
#

Changes to testce/TestCases.cs.

67
68
69
70
71
72
73
74
75


76
77
78
79
80
81
82
83
84
85
      if (param2 == "Field3") return -1;
      return String.Compare(param1, param2, true);
    }
  }

  internal class TestCases
  {
    private bool autoClose;
    internal Form1 frm;


    internal int total;
    internal int passed;
    internal int failed;

    internal TestCases(bool autoExit)
    {
        this.autoClose = autoExit;
    }

    internal bool Succeeded()







<

>
>
|
|
|







67
68
69
70
71
72
73

74
75
76
77
78
79
80
81
82
83
84
85
86
      if (param2 == "Field3") return -1;
      return String.Compare(param1, param2, true);
    }
  }

  internal class TestCases
  {

    internal Form1 frm;

    private bool autoClose;
    private int total;
    private int passed;
    private int failed;

    internal TestCases(bool autoExit)
    {
        this.autoClose = autoExit;
    }

    internal bool Succeeded()