blob: b7e16e72276b175d8725f0aacbeccb900ac75206 [file] [log] [blame]
dane6391282019-04-11 19:03:15 +00001#!/bin/sh
dana3020dc2019-04-09 19:53:32 +00002# \
3exec wapptclsh "$0" ${1+"$@"}
4
dan523fb532019-04-10 18:56:30 +00005# package required wapp
6source [file join [file dirname [info script]] wapp.tcl]
7
dana3020dc2019-04-09 19:53:32 +00008# Variables set by the "control" form:
9#
10# G(platform) - User selected platform.
11# G(test) - Set to "Normal", "Veryquick", "Smoketest" or "Build-Only".
12# G(keep) - Boolean. True to delete no files after each test.
13# G(msvc) - Boolean. True to use MSVC as the compiler.
14# G(tcl) - Use Tcl from this directory for builds.
15# G(jobs) - How many sub-processes to run simultaneously.
16#
17set G(platform) $::tcl_platform(os)-$::tcl_platform(machine)
18set G(test) Normal
danc97001f2019-05-01 15:25:38 +000019set G(keep) 1
danee253f72019-05-02 17:06:01 +000020set G(msvc) 0
dane6391282019-04-11 19:03:15 +000021set G(tcl) [::tcl::pkgconfig get libdir,install]
dana3020dc2019-04-09 19:53:32 +000022set G(jobs) 3
dane6391282019-04-11 19:03:15 +000023set G(debug) 0
dana3020dc2019-04-09 19:53:32 +000024
danee253f72019-05-02 17:06:01 +000025set G(noui) 0
26set G(stdout) 0
27
28
dan523fb532019-04-10 18:56:30 +000029proc wapptest_init {} {
30 global G
dana3020dc2019-04-09 19:53:32 +000031
danee253f72019-05-02 17:06:01 +000032 set lSave [list platform test keep msvc tcl jobs debug noui stdout]
dan523fb532019-04-10 18:56:30 +000033 foreach k $lSave { set A($k) $G($k) }
34 array unset G
35 foreach k $lSave { set G($k) $A($k) }
dana3020dc2019-04-09 19:53:32 +000036
dan523fb532019-04-10 18:56:30 +000037 # The root of the SQLite source tree.
38 set G(srcdir) [file dirname [file dirname [info script]]]
dana3020dc2019-04-09 19:53:32 +000039
dan523fb532019-04-10 18:56:30 +000040 set G(sqlite_version) "unknown"
dana3020dc2019-04-09 19:53:32 +000041
dan523fb532019-04-10 18:56:30 +000042 # Either "config", "running" or "stopped":
43 set G(state) "config"
dan93673622019-04-10 19:45:19 +000044
dane6391282019-04-11 19:03:15 +000045 set G(hostname) "(unknown host)"
46 catch { set G(hostname) [exec hostname] }
47 set G(host) $G(hostname)
dan93673622019-04-10 19:45:19 +000048 append G(host) " $::tcl_platform(os) $::tcl_platform(osVersion)"
49 append G(host) " $::tcl_platform(machine) $::tcl_platform(byteOrder)"
dan523fb532019-04-10 18:56:30 +000050}
dana3020dc2019-04-09 19:53:32 +000051
danee253f72019-05-02 17:06:01 +000052proc wapptest_run {} {
53 global G
54 set_test_array
55 set G(state) "running"
56
57 wapptest_openlog
58
59 wapptest_output "Running the following for $G(platform). $G(jobs) jobs."
60 foreach t $G(test_array) {
61 set config [dict get $t config]
62 set target [dict get $t target]
63 wapptest_output [format " %-25s%s" $config $target]
64 }
65 wapptest_output [string repeat * 70]
66}
67
dan45cb2aa2019-07-31 21:08:55 +000068proc releasetest_data {args} {
69 global G
70 set rtd [file join $G(srcdir) test releasetest_data.tcl]
71 set fd [open "|[info nameofexecutable] $rtd $args" r+]
72 set ret [read $fd]
73 close $fd
74 return $ret
75}
76
dan91945892019-04-30 20:43:10 +000077# Generate the text for the box at the top of the UI. The current SQLite
78# version, according to fossil, along with a warning if there are
79# uncommitted changes in the checkout.
dana3020dc2019-04-09 19:53:32 +000080#
dane6391282019-04-11 19:03:15 +000081proc generate_fossil_info {} {
82 global G
83 set pwd [pwd]
84 cd $G(srcdir)
dan91945892019-04-30 20:43:10 +000085 set rc [catch {
86 set r1 [exec fossil info]
87 set r2 [exec fossil changes]
88 }]
dane6391282019-04-11 19:03:15 +000089 cd $pwd
dan91945892019-04-30 20:43:10 +000090 if {$rc} return
dane6391282019-04-11 19:03:15 +000091
92 foreach line [split $r1 "\n"] {
93 if {[regexp {^checkout: *(.*)$} $line -> co]} {
94 wapp-trim { <br> %html($co) }
95 }
96 }
97
98 if {[string trim $r2]!=""} {
99 wapp-trim {
100 <br><span class=warning>
101 WARNING: Uncommitted changes in checkout
102 </span>
103 }
104 }
105}
106
dana3020dc2019-04-09 19:53:32 +0000107# If the application is in "config" state, set the contents of the
108# ::G(test_array) global to reflect the tests that will be run. If the
109# app is in some other state ("running" or "stopped"), this command
110# is a no-op.
111#
112proc set_test_array {} {
113 global G
114 if { $G(state)=="config" } {
115 set G(test_array) [list]
dan45cb2aa2019-07-31 21:08:55 +0000116 set debug "-debug"
117 if {$G(debug)==0} { set debug "-nodebug"}
118 foreach {config target} [releasetest_data tests $debug $G(platform)] {
dana3020dc2019-04-09 19:53:32 +0000119
120 # If using MSVC, do not run sanitize or valgrind tests. Or the
121 # checksymbols test.
122 if {$G(msvc) && (
123 "Sanitize" == $config
124 || "checksymbols" in $target
125 || "valgrindtest" in $target
126 )} {
127 continue
128 }
129
130 # If the test mode is not "Normal", override the target.
131 #
132 if {$target!="checksymbols" && $G(platform)!="Failure-Detection"} {
133 switch -- $G(test) {
134 Veryquick { set target quicktest }
135 Smoketest { set target smoketest }
136 Build-Only {
137 set target testfixture
138 if {$::tcl_platform(platform)=="windows"} {
139 set target testfixture.exe
140 }
141 }
142 }
143 }
144
145 lappend G(test_array) [dict create config $config target $target]
146 }
147 }
148}
149
150proc count_tests_and_errors {name logfile} {
151 global G
152
153 set fd [open $logfile rb]
154 set seen 0
155 while {![eof $fd]} {
156 set line [gets $fd]
157 if {[regexp {(\d+) errors out of (\d+) tests} $line all nerr ntest]} {
158 incr G(test.$name.nError) $nerr
159 incr G(test.$name.nTest) $ntest
160 set seen 1
161 if {$nerr>0} {
162 set G(test.$name.errmsg) $line
163 }
164 }
165 if {[regexp {runtime error: +(.*)} $line all msg]} {
166 # skip over "value is outside range" errors
drhc08716a2020-08-11 21:53:42 +0000167 if {[regexp {.* is outside the range of representable} $line]} {
dana3020dc2019-04-09 19:53:32 +0000168 # noop
169 } else {
170 incr G(test.$name.nError)
171 if {$G(test.$name.errmsg)==""} {
172 set G(test.$name.errmsg) $msg
173 }
174 }
175 }
176 if {[regexp {fatal error +(.*)} $line all msg]} {
177 incr G(test.$name.nError)
178 if {$G(test.$name.errmsg)==""} {
179 set G(test.$name.errmsg) $msg
180 }
181 }
182 if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
183 incr G(test.$name.nError)
184 if {$G(test.$name.errmsg)==""} {
185 set G(test.$name.errmsg) $all
186 }
187 }
188 if {[regexp {^VERSION: 3\.\d+.\d+} $line]} {
189 set v [string range $line 9 end]
190 if {$G(sqlite_version) eq "unknown"} {
191 set G(sqlite_version) $v
192 } elseif {$G(sqlite_version) ne $v} {
193 set G(test.$name.errmsg) "version conflict: {$G(sqlite_version)} vs. {$v}"
194 }
195 }
196 }
197 close $fd
198 if {$G(test) == "Build-Only"} {
199 incr G(test.$name.nTest)
200 if {$G(test.$name.nError)>0} {
201 set errmsg "Build failed"
202 }
203 } elseif {!$seen} {
204 set G(test.$name.errmsg) "Test did not complete"
205 if {[file readable core]} {
206 append G(test.$name.errmsg) " - core file exists"
207 }
208 }
209}
210
danee253f72019-05-02 17:06:01 +0000211proc wapptest_output {str} {
212 global G
213 if {$G(stdout)} { puts $str }
214 if {[info exists G(log)]} {
215 puts $G(log) $str
216 flush $G(log)
217 }
218}
219proc wapptest_openlog {} {
220 global G
221 set G(log) [open wapptest-out.txt w+]
222}
223proc wapptest_closelog {} {
224 global G
225 close $G(log)
226 unset G(log)
227}
228
229proc format_seconds {seconds} {
230 set min [format %.2d [expr ($seconds / 60) % 60]]
231 set hr [format %.2d [expr $seconds / 3600]]
232 set sec [format %.2d [expr $seconds % 60]]
233 return "$hr:$min:$sec"
234}
235
danc97001f2019-05-01 15:25:38 +0000236# This command is invoked once a slave process has finished running its
237# tests, successfully or otherwise. Parameter $name is the name of the
238# test, $rc the exit code returned by the slave process.
239#
dan523fb532019-04-10 18:56:30 +0000240proc slave_test_done {name rc} {
241 global G
242 set G(test.$name.done) [clock seconds]
243 set G(test.$name.nError) 0
244 set G(test.$name.nTest) 0
245 set G(test.$name.errmsg) ""
246 if {$rc} {
247 incr G(test.$name.nError)
248 }
249 if {[file exists $G(test.$name.log)]} {
250 count_tests_and_errors $name $G(test.$name.log)
251 }
danc97001f2019-05-01 15:25:38 +0000252
253 # If the "keep files" checkbox is clear, delete all files except for
254 # the executables and test logs. And any core file that is present.
255 if {$G(keep)==0} {
256 set keeplist {
257 testfixture testfixture.exe
258 sqlite3 sqlite3.exe
259 test.log test-out.txt
260 core
dan0de0ab82019-05-01 17:32:36 +0000261 wapptest_make.sh
262 wapptest_configure.sh
263 wapptest_run.tcl
danc97001f2019-05-01 15:25:38 +0000264 }
265 foreach f [glob -nocomplain [file join $G(test.$name.dir) *]] {
266 set t [file tail $f]
267 if {[lsearch $keeplist $t]<0} {
268 catch { file delete -force $f }
269 }
270 }
271 }
danee253f72019-05-02 17:06:01 +0000272
273 # Format a message regarding the success or failure of hte test.
274 set t [format_seconds [expr $G(test.$name.done) - $G(test.$name.start)]]
275 set res "OK"
276 if {$G(test.$name.nError)} { set res "FAILED" }
277 set dots [string repeat . [expr 60 - [string length $name]]]
278 set msg "$name $dots $res ($t)"
279
280 wapptest_output $msg
281 if {[info exists G(test.$name.errmsg)] && $G(test.$name.errmsg)!=""} {
dan79d8aa22019-07-04 16:30:41 +0000282 wapptest_output " $G(test.$name.errmsg)"
danee253f72019-05-02 17:06:01 +0000283 }
dan523fb532019-04-10 18:56:30 +0000284}
285
danc97001f2019-05-01 15:25:38 +0000286# This is a fileevent callback invoked each time a file-descriptor that
287# connects this process to a slave process is readable.
288#
dana3020dc2019-04-09 19:53:32 +0000289proc slave_fileevent {name} {
290 global G
291 set fd $G(test.$name.channel)
292
293 if {[eof $fd]} {
294 fconfigure $fd -blocking 1
295 set rc [catch { close $fd }]
296 unset G(test.$name.channel)
dan523fb532019-04-10 18:56:30 +0000297 slave_test_done $name $rc
dana3020dc2019-04-09 19:53:32 +0000298 } else {
299 set line [gets $fd]
300 if {[string trim $line] != ""} { puts "Trace : $name - \"$line\"" }
301 }
302
303 do_some_stuff
304}
305
danc97001f2019-05-01 15:25:38 +0000306# Return the contents of the "slave script" - the script run by slave
dan401593e2019-08-01 15:18:51 +0000307# processes to actually perform the test. All it does is execute the
308# test script already written to disk (wapptest_cmd.sh or wapptest_cmd.bat).
danc97001f2019-05-01 15:25:38 +0000309#
dan91945892019-04-30 20:43:10 +0000310proc wapptest_slave_script {} {
311 global G
dan45cb2aa2019-07-31 21:08:55 +0000312 if {$G(msvc)==0} {
313 set dir [file join .. $G(srcdir)]
314 set res [subst -nocommands {
315 set rc [catch "exec sh wapptest_cmd.sh {$dir} >>& test.log" ]
316 exit [set rc]
317 }]
318 } else {
319 set dir [file nativename [file normalize $G(srcdir)]]
320 set dir [string map [list "\\" "\\\\"] $dir]
321 set res [subst -nocommands {
322 set rc [catch "exec wapptest_cmd.bat {$dir} >>& test.log" ]
323 exit [set rc]
324 }]
dan91945892019-04-30 20:43:10 +0000325 }
326
dan91945892019-04-30 20:43:10 +0000327 set res
328}
329
330
331# Launch a slave process to run a test.
332#
dan45cb2aa2019-07-31 21:08:55 +0000333proc slave_launch {name target dir} {
dan91945892019-04-30 20:43:10 +0000334 global G
335
336 catch { file mkdir $dir } msg
337 foreach f [glob -nocomplain [file join $dir *]] {
338 catch { file delete -force $f }
339 }
danc97001f2019-05-01 15:25:38 +0000340 set G(test.$name.dir) $dir
dan91945892019-04-30 20:43:10 +0000341
dan45cb2aa2019-07-31 21:08:55 +0000342 # Write the test command to wapptest_cmd.sh|bat.
dan91945892019-04-30 20:43:10 +0000343 #
dan45cb2aa2019-07-31 21:08:55 +0000344 set ext sh
345 if {$G(msvc)} { set ext bat }
346 set fd1 [open [file join $dir wapptest_cmd.$ext] w]
347 if {$G(msvc)} {
348 puts $fd1 [releasetest_data script -msvc $name $target]
349 } else {
350 puts $fd1 [releasetest_data script $name $target]
dan91945892019-04-30 20:43:10 +0000351 }
352 close $fd1
353
dan91945892019-04-30 20:43:10 +0000354 # Write the wapptest_run.tcl script to the test directory. To run the
355 # commands in the other two files.
356 #
357 set fd3 [open [file join $dir wapptest_run.tcl] w]
358 puts $fd3 [wapptest_slave_script]
359 close $fd3
360
361 set pwd [pwd]
362 cd $dir
363 set fd [open "|[info nameofexecutable] wapptest_run.tcl" r+]
364 cd $pwd
365
366 set G(test.$name.channel) $fd
367 fconfigure $fd -blocking 0
368 fileevent $fd readable [list slave_fileevent $name]
369}
370
dana3020dc2019-04-09 19:53:32 +0000371proc do_some_stuff {} {
372 global G
373
374 # Count the number of running jobs. A running job has an entry named
375 # "channel" in its dictionary.
376 set nRunning 0
377 set bFinished 1
378 foreach j $G(test_array) {
379 set name [dict get $j config]
380 if { [info exists G(test.$name.channel)]} { incr nRunning }
381 if {![info exists G(test.$name.done)]} { set bFinished 0 }
382 }
383
384 if {$bFinished} {
385 set nError 0
386 set nTest 0
387 set nConfig 0
388 foreach j $G(test_array) {
389 set name [dict get $j config]
390 incr nError $G(test.$name.nError)
391 incr nTest $G(test.$name.nTest)
392 incr nConfig
393 }
394 set G(result) "$nError errors from $nTest tests in $nConfig configurations."
danee253f72019-05-02 17:06:01 +0000395 wapptest_output [string repeat * 70]
396 wapptest_output $G(result)
dana3020dc2019-04-09 19:53:32 +0000397 catch {
398 append G(result) " SQLite version $G(sqlite_version)"
danee253f72019-05-02 17:06:01 +0000399 wapptest_output " SQLite version $G(sqlite_version)"
dana3020dc2019-04-09 19:53:32 +0000400 }
dan523fb532019-04-10 18:56:30 +0000401 set G(state) "stopped"
danee253f72019-05-02 17:06:01 +0000402 wapptest_closelog
403 if {$G(noui)} { exit 0 }
dana3020dc2019-04-09 19:53:32 +0000404 } else {
405 set nLaunch [expr $G(jobs) - $nRunning]
406 foreach j $G(test_array) {
407 if {$nLaunch<=0} break
408 set name [dict get $j config]
409 if { ![info exists G(test.$name.channel)]
410 && ![info exists G(test.$name.done)]
411 } {
dan91945892019-04-30 20:43:10 +0000412
dana3020dc2019-04-09 19:53:32 +0000413 set target [dict get $j target]
dan45cb2aa2019-07-31 21:08:55 +0000414 set dir [string tolower [string map {" " _ "-" _} $name]]
dana3020dc2019-04-09 19:53:32 +0000415 set G(test.$name.start) [clock seconds]
dan45cb2aa2019-07-31 21:08:55 +0000416 set G(test.$name.log) [file join $dir test.log]
dane6391282019-04-11 19:03:15 +0000417
dan45cb2aa2019-07-31 21:08:55 +0000418 slave_launch $name $target $dir
dane6391282019-04-11 19:03:15 +0000419
dana3020dc2019-04-09 19:53:32 +0000420 incr nLaunch -1
421 }
422 }
423 }
424}
425
dan523fb532019-04-10 18:56:30 +0000426proc generate_select_widget {label id lOpt opt} {
427 wapp-trim {
428 <label> %string($label) </label>
429 <select id=%string($id) name=%string($id)>
430 }
431 foreach o $lOpt {
432 set selected ""
433 if {$o==$opt} { set selected " selected=1" }
434 wapp-subst "<option $selected>$o</option>"
435 }
436 wapp-trim { </select> }
437}
438
dana3020dc2019-04-09 19:53:32 +0000439proc generate_main_page {{extra {}}} {
440 global G
441 set_test_array
442
dane6391282019-04-11 19:03:15 +0000443 set hostname $G(hostname)
dana3020dc2019-04-09 19:53:32 +0000444 wapp-trim {
445 <html>
446 <head>
dane6391282019-04-11 19:03:15 +0000447 <title> %html($hostname): wapptest.tcl </title>
dana3020dc2019-04-09 19:53:32 +0000448 <link rel="stylesheet" type="text/css" href="style.css"/>
449 </head>
450 <body>
451 }
452
dan93673622019-04-10 19:45:19 +0000453 set host $G(host)
dana3020dc2019-04-09 19:53:32 +0000454 wapp-trim {
dane6391282019-04-11 19:03:15 +0000455 <div class="border">%string($host)
456 }
457 generate_fossil_info
458 wapp-trim {
459 </div>
460 <div class="border" id=controls>
461 <form action="control" method="post" name="control">
dana3020dc2019-04-09 19:53:32 +0000462 }
dan523fb532019-04-10 18:56:30 +0000463
464 # Build the "platform" select widget.
dan45cb2aa2019-07-31 21:08:55 +0000465 set lOpt [releasetest_data platforms]
dan523fb532019-04-10 18:56:30 +0000466 generate_select_widget Platform control_platform $lOpt $G(platform)
467
468 # Build the "test" select widget.
469 set lOpt [list Normal Veryquick Smoketest Build-Only]
470 generate_select_widget Test control_test $lOpt $G(test)
471
472 # Build the "jobs" select widget. Options are 1 to 8.
473 generate_select_widget Jobs control_jobs {1 2 3 4 5 6 7 8} $G(jobs)
474
475 switch $G(state) {
476 config {
477 set txt "Run Tests!"
478 set id control_run
479 }
480 running {
481 set txt "STOP Tests!"
482 set id control_stop
483 }
484 stopped {
485 set txt "Reset!"
486 set id control_reset
487 }
dana3020dc2019-04-09 19:53:32 +0000488 }
489 wapp-trim {
dan523fb532019-04-10 18:56:30 +0000490 <div class=right>
491 <input id=%string($id) name=%string($id) type=submit value="%string($txt)">
492 </input>
493 </div>
dana3020dc2019-04-09 19:53:32 +0000494 }
dan523fb532019-04-10 18:56:30 +0000495
496 wapp-trim {
497 <br><br>
dana3020dc2019-04-09 19:53:32 +0000498 <label> Tcl: </label>
499 <input id="control_tcl" name="control_tcl"></input>
dana3020dc2019-04-09 19:53:32 +0000500 <label> Keep files: </label>
501 <input id="control_keep" name="control_keep" type=checkbox value=1>
502 </input>
503 <label> Use MSVC: </label>
504 <input id="control_msvc" name="control_msvc" type=checkbox value=1>
dane6391282019-04-11 19:03:15 +0000505 <label> Debug tests: </label>
506 <input id="control_debug" name="control_debug" type=checkbox value=1>
dana3020dc2019-04-09 19:53:32 +0000507 </input>
dana3020dc2019-04-09 19:53:32 +0000508 }
509 wapp-trim {
dana3020dc2019-04-09 19:53:32 +0000510 </form>
dana3020dc2019-04-09 19:53:32 +0000511 }
dan523fb532019-04-10 18:56:30 +0000512 wapp-trim {
513 </div>
dane6391282019-04-11 19:03:15 +0000514 <div id=tests>
dan523fb532019-04-10 18:56:30 +0000515 }
516 wapp-page-tests
517
518 set script "script/$G(state).js"
519 wapp-trim {
520 </div>
521 <script src=%string($script)></script>
522 </body>
523 </html>
524 }
525}
526
527proc wapp-default {} {
528 generate_main_page
529}
530
531proc wapp-page-tests {} {
532 global G
dane6391282019-04-11 19:03:15 +0000533 wapp-trim { <table class="border" width=100%> }
dana3020dc2019-04-09 19:53:32 +0000534 foreach t $G(test_array) {
535 set config [dict get $t config]
536 set target [dict get $t target]
537
538 set class "testwait"
539 set seconds ""
540
541 if {[info exists G(test.$config.log)]} {
542 if {[info exists G(test.$config.channel)]} {
543 set class "testrunning"
544 set seconds [expr [clock seconds] - $G(test.$config.start)]
545 } elseif {[info exists G(test.$config.done)]} {
546 if {$G(test.$config.nError)>0} {
547 set class "testfail"
548 } else {
549 set class "testdone"
550 }
551 set seconds [expr $G(test.$config.done) - $G(test.$config.start)]
552 }
danee253f72019-05-02 17:06:01 +0000553 set seconds [format_seconds $seconds]
dana3020dc2019-04-09 19:53:32 +0000554 }
555
556 wapp-trim {
557 <tr class=%string($class)>
dane6391282019-04-11 19:03:15 +0000558 <td class="nowrap"> %html($config)
559 <td class="padleft nowrap"> %html($target)
560 <td class="padleft nowrap"> %html($seconds)
561 <td class="padleft nowrap">
dana3020dc2019-04-09 19:53:32 +0000562 }
563 if {[info exists G(test.$config.log)]} {
564 set log $G(test.$config.log)
565 set uri "log/$log"
566 wapp-trim {
567 <a href=%url($uri)> %html($log) </a>
568 }
569 }
570 if {[info exists G(test.$config.errmsg)] && $G(test.$config.errmsg)!=""} {
571 set errmsg $G(test.$config.errmsg)
572 wapp-trim {
573 <tr class=testfail>
dane6391282019-04-11 19:03:15 +0000574 <td> <td class="padleft" colspan=3> %html($errmsg)
dana3020dc2019-04-09 19:53:32 +0000575 }
576 }
577 }
578
dan523fb532019-04-10 18:56:30 +0000579 wapp-trim { </table> }
580
dana3020dc2019-04-09 19:53:32 +0000581 if {[info exists G(result)]} {
582 set res $G(result)
583 wapp-trim {
dan523fb532019-04-10 18:56:30 +0000584 <div class=border id=result> %string($res) </div>
dana3020dc2019-04-09 19:53:32 +0000585 }
586 }
dana3020dc2019-04-09 19:53:32 +0000587}
588
dan523fb532019-04-10 18:56:30 +0000589# URI: /control
590#
591# Whenever the form at the top of the application page is submitted, it
592# is submitted here.
593#
dana3020dc2019-04-09 19:53:32 +0000594proc wapp-page-control {} {
595 global G
dan523fb532019-04-10 18:56:30 +0000596 if {$::G(state)=="config"} {
dane6391282019-04-11 19:03:15 +0000597 set lControls [list platform test tcl jobs keep msvc debug]
dan523fb532019-04-10 18:56:30 +0000598 set G(msvc) 0
599 set G(keep) 0
dane6391282019-04-11 19:03:15 +0000600 set G(debug) 0
dan523fb532019-04-10 18:56:30 +0000601 } else {
602 set lControls [list jobs]
603 }
604 foreach v $lControls {
dana3020dc2019-04-09 19:53:32 +0000605 if {[wapp-param-exists control_$v]} {
606 set G($v) [wapp-param control_$v]
dana3020dc2019-04-09 19:53:32 +0000607 }
608 }
609
dan523fb532019-04-10 18:56:30 +0000610 if {[wapp-param-exists control_run]} {
611 # This is a "run test" command.
danee253f72019-05-02 17:06:01 +0000612 wapptest_run
dana3020dc2019-04-09 19:53:32 +0000613 }
614
dan523fb532019-04-10 18:56:30 +0000615 if {[wapp-param-exists control_stop]} {
616 # A "STOP tests" command.
617 set G(state) "stopped"
618 set G(result) "Test halted by user"
619 foreach j $G(test_array) {
620 set name [dict get $j config]
621 if { [info exists G(test.$name.channel)] } {
622 close $G(test.$name.channel)
623 unset G(test.$name.channel)
624 slave_test_done $name 1
625 }
626 }
danee253f72019-05-02 17:06:01 +0000627 wapptest_closelog
dan523fb532019-04-10 18:56:30 +0000628 }
629
630 if {[wapp-param-exists control_reset]} {
631 # A "reset app" command.
632 set G(state) "config"
633 wapptest_init
634 }
635
dana3020dc2019-04-09 19:53:32 +0000636 if {$::G(state) == "running"} {
637 do_some_stuff
638 }
dana3020dc2019-04-09 19:53:32 +0000639 wapp-redirect /
640}
641
dan523fb532019-04-10 18:56:30 +0000642# URI: /style.css
643#
644# Return the stylesheet for the application main page.
645#
dana3020dc2019-04-09 19:53:32 +0000646proc wapp-page-style.css {} {
647 wapp-subst {
dana3020dc2019-04-09 19:53:32 +0000648
dane6391282019-04-11 19:03:15 +0000649 /* The boxes with black borders use this class */
dan523fb532019-04-10 18:56:30 +0000650 .border {
651 border: 3px groove #444444;
652 padding: 1em;
653 margin-top: 1em;
654 margin-bottom: 1em;
655 }
656
dane6391282019-04-11 19:03:15 +0000657 /* Float to the right (used for the Run/Stop/Reset button) */
658 .right { float: right; }
dan523fb532019-04-10 18:56:30 +0000659
dane6391282019-04-11 19:03:15 +0000660 /* Style for the large red warning at the top of the page */
dana3020dc2019-04-09 19:53:32 +0000661 .warning {
dana3020dc2019-04-09 19:53:32 +0000662 color: red;
dana3020dc2019-04-09 19:53:32 +0000663 font-weight: bold;
664 }
665
dane6391282019-04-11 19:03:15 +0000666 /* Styles used by cells in the test table */
667 .padleft { padding-left: 5ex; }
668 .nowrap { white-space: nowrap; }
dana3020dc2019-04-09 19:53:32 +0000669
dane6391282019-04-11 19:03:15 +0000670 /* Styles for individual tests, depending on the outcome */
671 .testwait { }
672 .testrunning { color: blue }
673 .testdone { color: green }
674 .testfail { color: red }
dana3020dc2019-04-09 19:53:32 +0000675 }
676}
677
dan523fb532019-04-10 18:56:30 +0000678# URI: /script/${state}.js
679#
680# The last part of this URI is always "config.js", "running.js" or
681# "stopped.js", depending on the state of the application. It returns
682# the javascript part of the front-end for the requested state to the
683# browser.
684#
685proc wapp-page-script {} {
686 regexp {[^/]*$} [wapp-param REQUEST_URI] script
dana3020dc2019-04-09 19:53:32 +0000687
688 set tcl $::G(tcl)
689 set keep $::G(keep)
690 set msvc $::G(msvc)
dane6391282019-04-11 19:03:15 +0000691 set debug $::G(debug)
dana3020dc2019-04-09 19:53:32 +0000692
693 wapp-subst {
dan523fb532019-04-10 18:56:30 +0000694 var lElem = \["control_platform", "control_test", "control_msvc",
dane6391282019-04-11 19:03:15 +0000695 "control_jobs", "control_debug"
dan523fb532019-04-10 18:56:30 +0000696 \];
dana3020dc2019-04-09 19:53:32 +0000697 lElem.forEach(function(e) {
698 var elem = document.getElementById(e);
699 elem.addEventListener("change", function() { control.submit() } );
700 })
701
702 elem = document.getElementById("control_tcl");
703 elem.value = "%string($tcl)"
704
705 elem = document.getElementById("control_keep");
706 elem.checked = %string($keep);
707
708 elem = document.getElementById("control_msvc");
709 elem.checked = %string($msvc);
dane6391282019-04-11 19:03:15 +0000710
711 elem = document.getElementById("control_debug");
712 elem.checked = %string($debug);
dana3020dc2019-04-09 19:53:32 +0000713 }
714
dan523fb532019-04-10 18:56:30 +0000715 if {$script != "config.js"} {
dana3020dc2019-04-09 19:53:32 +0000716 wapp-subst {
717 var lElem = \["control_platform", "control_test",
dan37eca052019-04-12 13:40:54 +0000718 "control_tcl", "control_keep", "control_msvc",
719 "control_debug"
dana3020dc2019-04-09 19:53:32 +0000720 \];
721 lElem.forEach(function(e) {
722 var elem = document.getElementById(e);
723 elem.disabled = true;
724 })
725 }
726 }
dan523fb532019-04-10 18:56:30 +0000727
728 if {$script == "running.js"} {
729 wapp-subst {
730 function reload_tests() {
731 fetch('tests')
732 .then( data => data.text() )
733 .then( data => {
734 document.getElementById("tests").innerHTML = data;
735 })
736 .then( data => {
737 if( document.getElementById("result") ){
738 document.location = document.location;
739 } else {
740 setTimeout(reload_tests, 1000)
741 }
742 });
743 }
744
745 setTimeout(reload_tests, 1000)
746 }
747 }
dana3020dc2019-04-09 19:53:32 +0000748}
749
dan523fb532019-04-10 18:56:30 +0000750# URI: /env
751#
752# This is for debugging only. Serves no other purpose.
753#
dana3020dc2019-04-09 19:53:32 +0000754proc wapp-page-env {} {
755 wapp-allow-xorigin-params
756 wapp-trim {
757 <h1>Wapp Environment</h1>\n<pre>
758 <pre>%html([wapp-debug-env])</pre>
759 }
760}
761
dan523fb532019-04-10 18:56:30 +0000762# URI: /log/dirname/test.log
763#
764# This URI reads file "dirname/test.log" from disk, wraps it in a <pre>
765# block, and returns it to the browser. Use for viewing log files.
766#
dana3020dc2019-04-09 19:53:32 +0000767proc wapp-page-log {} {
768 set log [string range [wapp-param REQUEST_URI] 5 end]
769 set fd [open $log]
770 set data [read $fd]
771 close $fd
772 wapp-trim {
773 <pre>
774 %html($data)
775 </pre>
776 }
777}
778
danee253f72019-05-02 17:06:01 +0000779# Print out a usage message. Then do [exit 1].
780#
781proc wapptest_usage {} {
782 puts stderr {
783This Tcl script is used to test various configurations of SQLite. By
784default it uses "wapp" to provide an interactive interface. Supported
785command line options (all optional) are:
786
787 --platform PLATFORM (which tests to run)
788 --smoketest (run "make smoketest" only)
789 --veryquick (run veryquick.test only)
790 --buildonly (build executables, do not run tests)
791 --jobs N (number of concurrent jobs)
792 --tcl DIR (where to find tclConfig.sh)
793 --deletefiles (delete extra files after each test)
794 --msvc (Use MS Visual C)
795 --debug (Also run [n]debugging versions of tests)
796 --noui (do not use wapp)
797 }
798 exit 1
799}
800
801# Sort command line arguments into two groups: those that belong to wapp,
802# and those that belong to the application.
803set WAPPARG(-server) 1
804set WAPPARG(-local) 1
805set WAPPARG(-scgi) 1
806set WAPPARG(-remote-scgi) 1
807set WAPPARG(-fromip) 1
808set WAPPARG(-nowait) 0
809set WAPPARG(-cgi) 0
810set lWappArg [list]
811set lTestArg [list]
812for {set i 0} {$i < [llength $argv]} {incr i} {
813 set arg [lindex $argv $i]
814 if {[string range $arg 0 1]=="--"} {
815 set arg [string range $arg 1 end]
816 }
817 if {[info exists WAPPARG($arg)]} {
818 lappend lWappArg $arg
819 if {$WAPPARG($arg)} {
820 incr i
821 lappend lWappArg [lindex $argv $i]
822 }
823 } else {
824 lappend lTestArg $arg
825 }
826}
827
dan367b8d72019-10-03 13:44:08 +0000828wapptest_init
danee253f72019-05-02 17:06:01 +0000829for {set i 0} {$i < [llength $lTestArg]} {incr i} {
dan367b8d72019-10-03 13:44:08 +0000830 set opt [lindex $lTestArg $i]
831 if {[string range $opt 0 1]=="--"} {
832 set opt [string range $opt 1 end]
833 }
834 switch -- $opt {
danee253f72019-05-02 17:06:01 +0000835 -platform {
836 if {$i==[llength $lTestArg]-1} { wapptest_usage }
837 incr i
838 set arg [lindex $lTestArg $i]
dan45cb2aa2019-07-31 21:08:55 +0000839 set lPlatform [releasetest_data platforms]
danee253f72019-05-02 17:06:01 +0000840 if {[lsearch $lPlatform $arg]<0} {
841 puts stderr "No such platform: $arg. Platforms are: $lPlatform"
842 exit -1
843 }
844 set G(platform) $arg
845 }
846
847 -smoketest { set G(test) Smoketest }
848 -veryquick { set G(test) Veryquick }
849 -buildonly { set G(test) Build-Only }
850 -jobs {
851 if {$i==[llength $lTestArg]-1} { wapptest_usage }
852 incr i
853 set G(jobs) [lindex $lTestArg $i]
854 }
855
856 -tcl {
857 if {$i==[llength $lTestArg]-1} { wapptest_usage }
858 incr i
859 set G(tcl) [lindex $lTestArg $i]
860 }
861
862 -deletefiles {
863 set G(keep) 0
864 }
865
866 -msvc {
867 set G(msvc) 1
868 }
869
870 -debug {
871 set G(debug) 1
872 }
873
874 -noui {
875 set G(noui) 1
876 set G(stdout) 1
877 }
878
879 -stdout {
880 set G(stdout) 1
881 }
882
883 default {
884 puts stderr "Unrecognized option: [lindex $lTestArg $i]"
885 wapptest_usage
886 }
887 }
888}
889
danee253f72019-05-02 17:06:01 +0000890if {$G(noui)==0} {
891 wapp-start $lWappArg
892} else {
893 wapptest_run
894 do_some_stuff
895 vwait forever
896}