Snapshot of upstream SQLite 3.40.1
[sqlcipher.git] / test / wapptest.tcl
blobd37b2e48c6e2f95de2bcaf0c6302d4c5cf89d69a
1 #!/bin/sh
2 # \
3 exec wapptclsh "$0" ${1+"$@"}
5 # package required wapp
6 source [file join [file dirname [info script]] wapp.tcl]
8 # Variables set by the "control" form:
10 # G(platform) - User selected platform.
11 # G(cfgglob) - Glob pattern that all configurations must match
12 # G(test) - Set to "Normal", "Veryquick", "Smoketest" or "Build-Only".
13 # G(keep) - Boolean. True to delete no files after each test.
14 # G(msvc) - Boolean. True to use MSVC as the compiler.
15 # G(tcl) - Use Tcl from this directory for builds.
16 # G(jobs) - How many sub-processes to run simultaneously.
18 set G(platform) $::tcl_platform(os)-$::tcl_platform(machine)
19 set G(cfgglob) *
20 set G(test) Normal
21 set G(keep) 1
22 set G(msvc) 0
23 set G(tcl) [::tcl::pkgconfig get libdir,install]
24 set G(jobs) 3
25 set G(debug) 0
27 set G(noui) 0
28 set G(stdout) 0
31 proc wapptest_init {} {
32 global G
34 set lSave [list platform test keep msvc tcl jobs debug noui stdout cfgglob]
35 foreach k $lSave { set A($k) $G($k) }
36 array unset G
37 foreach k $lSave { set G($k) $A($k) }
39 # The root of the SQLite source tree.
40 set G(srcdir) [file dirname [file dirname [info script]]]
42 set G(sqlite_version) "unknown"
44 # Either "config", "running" or "stopped":
45 set G(state) "config"
47 set G(hostname) "(unknown host)"
48 catch { set G(hostname) [exec hostname] }
49 set G(host) $G(hostname)
50 append G(host) " $::tcl_platform(os) $::tcl_platform(osVersion)"
51 append G(host) " $::tcl_platform(machine) $::tcl_platform(byteOrder)"
54 proc wapptest_run {} {
55 global G
56 set_test_array
57 set G(state) "running"
59 wapptest_openlog
61 wapptest_output "Running the following for $G(platform). $G(jobs) jobs."
62 foreach t $G(test_array) {
63 set config [dict get $t config]
64 set target [dict get $t target]
65 wapptest_output [format " %-25s%s" $config $target]
67 wapptest_output [string repeat * 70]
70 proc releasetest_data {args} {
71 global G
72 set rtd [file join $G(srcdir) test releasetest_data.tcl]
73 set fd [open "|[info nameofexecutable] $rtd $args" r+]
74 set ret [read $fd]
75 close $fd
76 return $ret
79 # Generate the text for the box at the top of the UI. The current SQLite
80 # version, according to fossil, along with a warning if there are
81 # uncommitted changes in the checkout.
83 proc generate_fossil_info {} {
84 global G
85 set pwd [pwd]
86 cd $G(srcdir)
87 set rc [catch {
88 set r1 [exec fossil info]
89 set r2 [exec fossil changes]
91 cd $pwd
92 if {$rc} return
94 foreach line [split $r1 "\n"] {
95 if {[regexp {^checkout: *(.*)$} $line -> co]} {
96 wapp-trim { <br> %html($co) }
100 if {[string trim $r2]!=""} {
101 wapp-trim {
102 <br><span class=warning>
103 WARNING: Uncommitted changes in checkout
104 </span>
109 # If the application is in "config" state, set the contents of the
110 # ::G(test_array) global to reflect the tests that will be run. If the
111 # app is in some other state ("running" or "stopped"), this command
112 # is a no-op.
114 proc set_test_array {} {
115 global G
116 if { $G(state)=="config" } {
117 set G(test_array) [list]
118 set debug "-debug"
119 if {$G(debug)==0} { set debug "-nodebug"}
120 foreach {config target} [releasetest_data tests $debug $G(platform)] {
122 # All configuration names must match $g(cfgglob), which defaults to *
124 if {![string match -nocase $G(cfgglob) $config]} continue
126 # If using MSVC, do not run sanitize or valgrind tests. Or the
127 # checksymbols test.
128 if {$G(msvc) && (
129 "Sanitize" == $config
130 || "checksymbols" in $target
131 || "valgrindtest" in $target
132 )} {
133 continue
136 # If the test mode is not "Normal", override the target.
138 if {$target!="checksymbols" && $G(platform)!="Failure-Detection"} {
139 switch -- $G(test) {
140 Veryquick { set target quicktest }
141 Smoketest { set target smoketest }
142 Build-Only {
143 set target testfixture
144 if {$::tcl_platform(platform)=="windows"} {
145 set target testfixture.exe
151 lappend G(test_array) [dict create config $config target $target]
156 proc count_tests_and_errors {name logfile} {
157 global G
159 set fd [open $logfile rb]
160 set seen 0
161 while {![eof $fd]} {
162 set line [gets $fd]
163 if {[regexp {(\d+) errors out of (\d+) tests} $line all nerr ntest]} {
164 incr G(test.$name.nError) $nerr
165 incr G(test.$name.nTest) $ntest
166 set seen 1
167 if {$nerr>0} {
168 set G(test.$name.errmsg) $line
171 if {[regexp {runtime error: +(.*)} $line all msg]} {
172 # skip over "value is outside range" errors
173 if {[regexp {.* is outside the range of representable} $line]} {
174 # noop
175 } else {
176 incr G(test.$name.nError)
177 if {$G(test.$name.errmsg)==""} {
178 set G(test.$name.errmsg) $msg
182 if {[regexp {fatal error +(.*)} $line all msg]} {
183 incr G(test.$name.nError)
184 if {$G(test.$name.errmsg)==""} {
185 set G(test.$name.errmsg) $msg
188 if {[regexp {ERROR SUMMARY: (\d+) errors.*} $line all cnt] && $cnt>0} {
189 incr G(test.$name.nError)
190 if {$G(test.$name.errmsg)==""} {
191 set G(test.$name.errmsg) $all
194 if {[regexp {^VERSION: 3\.\d+.\d+} $line]} {
195 set v [string range $line 9 end]
196 if {$G(sqlite_version) eq "unknown"} {
197 set G(sqlite_version) $v
198 } elseif {$G(sqlite_version) ne $v} {
199 set G(test.$name.errmsg) "version conflict: {$G(sqlite_version)} vs. {$v}"
203 close $fd
204 if {$G(test) == "Build-Only"} {
205 incr G(test.$name.nTest)
206 if {$G(test.$name.nError)>0} {
207 set errmsg "Build failed"
209 } elseif {!$seen} {
210 set G(test.$name.errmsg) "Test did not complete"
211 if {[file readable core]} {
212 append G(test.$name.errmsg) " - core file exists"
217 proc wapptest_output {str} {
218 global G
219 if {$G(stdout)} { puts $str }
220 if {[info exists G(log)]} {
221 puts $G(log) $str
222 flush $G(log)
225 proc wapptest_openlog {} {
226 global G
227 set G(log) [open wapptest-out.txt w+]
229 proc wapptest_closelog {} {
230 global G
231 close $G(log)
232 unset G(log)
235 proc format_seconds {seconds} {
236 set min [format %.2d [expr ($seconds / 60) % 60]]
237 set hr [format %.2d [expr $seconds / 3600]]
238 set sec [format %.2d [expr $seconds % 60]]
239 return "$hr:$min:$sec"
242 # This command is invoked once a slave process has finished running its
243 # tests, successfully or otherwise. Parameter $name is the name of the
244 # test, $rc the exit code returned by the slave process.
246 proc slave_test_done {name rc} {
247 global G
248 set G(test.$name.done) [clock seconds]
249 set G(test.$name.nError) 0
250 set G(test.$name.nTest) 0
251 set G(test.$name.errmsg) ""
252 if {$rc} {
253 incr G(test.$name.nError)
255 if {[file exists $G(test.$name.log)]} {
256 count_tests_and_errors $name $G(test.$name.log)
259 # If the "keep files" checkbox is clear, delete all files except for
260 # the executables and test logs. And any core file that is present.
261 if {$G(keep)==0} {
262 set keeplist {
263 testfixture testfixture.exe
264 sqlite3 sqlite3.exe
265 test.log test-out.txt
266 core
267 wapptest_make.sh
268 wapptest_configure.sh
269 wapptest_run.tcl
271 foreach f [glob -nocomplain [file join $G(test.$name.dir) *]] {
272 set t [file tail $f]
273 if {[lsearch $keeplist $t]<0} {
274 catch { file delete -force $f }
279 # Format a message regarding the success or failure of hte test.
280 set t [format_seconds [expr $G(test.$name.done) - $G(test.$name.start)]]
281 set res "OK"
282 if {$G(test.$name.nError)} { set res "FAILED" }
283 set dots [string repeat . [expr 60 - [string length $name]]]
284 set msg "$name $dots $res ($t)"
286 wapptest_output $msg
287 if {[info exists G(test.$name.errmsg)] && $G(test.$name.errmsg)!=""} {
288 wapptest_output " $G(test.$name.errmsg)"
292 # This is a fileevent callback invoked each time a file-descriptor that
293 # connects this process to a slave process is readable.
295 proc slave_fileevent {name} {
296 global G
297 set fd $G(test.$name.channel)
299 if {[eof $fd]} {
300 fconfigure $fd -blocking 1
301 set rc [catch { close $fd }]
302 unset G(test.$name.channel)
303 slave_test_done $name $rc
304 } else {
305 set line [gets $fd]
306 if {[string trim $line] != ""} { puts "Trace : $name - \"$line\"" }
309 do_some_stuff
312 # Return the contents of the "slave script" - the script run by slave
313 # processes to actually perform the test. All it does is execute the
314 # test script already written to disk (wapptest_cmd.sh or wapptest_cmd.bat).
316 proc wapptest_slave_script {} {
317 global G
318 if {$G(msvc)==0} {
319 set dir [file join .. $G(srcdir)]
320 set res [subst -nocommands {
321 set rc [catch "exec sh wapptest_cmd.sh {$dir} >>& test.log" ]
322 exit [set rc]
324 } else {
325 set dir [file nativename [file normalize $G(srcdir)]]
326 set dir [string map [list "\\" "\\\\"] $dir]
327 set res [subst -nocommands {
328 set rc [catch "exec wapptest_cmd.bat {$dir} >>& test.log" ]
329 exit [set rc]
333 set res
337 # Launch a slave process to run a test.
339 proc slave_launch {name target dir} {
340 global G
342 catch { file mkdir $dir } msg
343 foreach f [glob -nocomplain [file join $dir *]] {
344 catch { file delete -force $f }
346 set G(test.$name.dir) $dir
348 # Write the test command to wapptest_cmd.sh|bat.
350 set ext sh
351 if {$G(msvc)} { set ext bat }
352 set fd1 [open [file join $dir wapptest_cmd.$ext] w]
353 if {$G(msvc)} {
354 puts $fd1 [releasetest_data script -msvc $name $target]
355 } else {
356 puts $fd1 [releasetest_data script $name $target]
358 close $fd1
360 # Write the wapptest_run.tcl script to the test directory. To run the
361 # commands in the other two files.
363 set fd3 [open [file join $dir wapptest_run.tcl] w]
364 puts $fd3 [wapptest_slave_script]
365 close $fd3
367 set pwd [pwd]
368 cd $dir
369 set fd [open "|[info nameofexecutable] wapptest_run.tcl" r+]
370 cd $pwd
372 set G(test.$name.channel) $fd
373 fconfigure $fd -blocking 0
374 fileevent $fd readable [list slave_fileevent $name]
377 proc do_some_stuff {} {
378 global G
380 # Count the number of running jobs. A running job has an entry named
381 # "channel" in its dictionary.
382 set nRunning 0
383 set bFinished 1
384 foreach j $G(test_array) {
385 set name [dict get $j config]
386 if { [info exists G(test.$name.channel)]} { incr nRunning }
387 if {![info exists G(test.$name.done)]} { set bFinished 0 }
390 if {$bFinished} {
391 set nError 0
392 set nTest 0
393 set nConfig 0
394 foreach j $G(test_array) {
395 set name [dict get $j config]
396 incr nError $G(test.$name.nError)
397 incr nTest $G(test.$name.nTest)
398 incr nConfig
400 set G(result) "$nError errors from $nTest tests in $nConfig configurations."
401 wapptest_output [string repeat * 70]
402 wapptest_output $G(result)
403 catch {
404 append G(result) " SQLite version $G(sqlite_version)"
405 wapptest_output " SQLite version $G(sqlite_version)"
407 set G(state) "stopped"
408 wapptest_closelog
409 if {$G(noui)} { exit 0 }
410 } else {
411 set nLaunch [expr $G(jobs) - $nRunning]
412 foreach j $G(test_array) {
413 if {$nLaunch<=0} break
414 set name [dict get $j config]
415 if { ![info exists G(test.$name.channel)]
416 && ![info exists G(test.$name.done)]
419 set target [dict get $j target]
420 set dir [string tolower [string map {" " _ "-" _} $name]]
421 set G(test.$name.start) [clock seconds]
422 set G(test.$name.log) [file join $dir test.log]
424 slave_launch $name $target $dir
426 incr nLaunch -1
432 proc generate_select_widget {label id lOpt opt} {
433 wapp-trim {
434 <label> %string($label) </label>
435 <select id=%string($id) name=%string($id)>
437 foreach o $lOpt {
438 set selected ""
439 if {$o==$opt} { set selected " selected=1" }
440 wapp-subst "<option $selected>$o</option>"
442 wapp-trim { </select> }
445 proc generate_main_page {{extra {}}} {
446 global G
447 set_test_array
449 set hostname $G(hostname)
450 wapp-trim {
451 <html>
452 <head>
453 <title> %html($hostname): wapptest.tcl </title>
454 <link rel="stylesheet" type="text/css" href="style.css"/>
455 </head>
456 <body>
459 set host $G(host)
460 wapp-trim {
461 <div class="border">%string($host)
463 generate_fossil_info
464 wapp-trim {
465 </div>
466 <div class="border" id=controls>
467 <form action="control" method="post" name="control">
470 # Build the "platform" select widget.
471 set lOpt [releasetest_data platforms]
472 generate_select_widget Platform control_platform $lOpt $G(platform)
474 # Build the "test" select widget.
475 set lOpt [list Normal Veryquick Smoketest Build-Only]
476 generate_select_widget Test control_test $lOpt $G(test)
478 # Build the "jobs" select widget. Options are 1 to 8.
479 generate_select_widget Jobs control_jobs {1 2 3 4 5 6 7 8 12 16} $G(jobs)
481 switch $G(state) {
482 config {
483 set txt "Run Tests!"
484 set id control_run
486 running {
487 set txt "STOP Tests!"
488 set id control_stop
490 stopped {
491 set txt "Reset!"
492 set id control_reset
495 wapp-trim {
496 <div class=right>
497 <input id=%string($id) name=%string($id) type=submit value="%string($txt)">
498 </input>
499 </div>
502 wapp-trim {
503 <br><br>
504 <label> Tcl: </label>
505 <input id="control_tcl" name="control_tcl"></input>
506 <label> Keep files: </label>
507 <input id="control_keep" name="control_keep" type=checkbox value=1>
508 </input>
509 <label> Use MSVC: </label>
510 <input id="control_msvc" name="control_msvc" type=checkbox value=1>
511 <label> Debug tests: </label>
512 <input id="control_debug" name="control_debug" type=checkbox value=1>
513 </input>
515 wapp-trim {
516 </form>
518 wapp-trim {
519 </div>
520 <div id=tests>
522 wapp-page-tests
524 set script "script/$G(state).js"
525 wapp-trim {
526 </div>
527 <script src=%string($script)></script>
528 </body>
529 </html>
533 proc wapp-default {} {
534 generate_main_page
537 proc wapp-page-tests {} {
538 global G
539 wapp-trim { <table class="border" width=100%> }
540 foreach t $G(test_array) {
541 set config [dict get $t config]
542 set target [dict get $t target]
544 set class "testwait"
545 set seconds ""
547 if {[info exists G(test.$config.log)]} {
548 if {[info exists G(test.$config.channel)]} {
549 set class "testrunning"
550 set seconds [expr [clock seconds] - $G(test.$config.start)]
551 } elseif {[info exists G(test.$config.done)]} {
552 if {$G(test.$config.nError)>0} {
553 set class "testfail"
554 } else {
555 set class "testdone"
557 set seconds [expr $G(test.$config.done) - $G(test.$config.start)]
559 set seconds [format_seconds $seconds]
562 wapp-trim {
563 <tr class=%string($class)>
564 <td class="nowrap"> %html($config)
565 <td class="padleft nowrap"> %html($target)
566 <td class="padleft nowrap"> %html($seconds)
567 <td class="padleft nowrap">
569 if {[info exists G(test.$config.log)]} {
570 set log $G(test.$config.log)
571 set uri "log/$log"
572 wapp-trim {
573 <a href=%url($uri)> %html($log) </a>
576 if {[info exists G(test.$config.errmsg)] && $G(test.$config.errmsg)!=""} {
577 set errmsg $G(test.$config.errmsg)
578 wapp-trim {
579 <tr class=testfail>
580 <td> <td class="padleft" colspan=3> %html($errmsg)
585 wapp-trim { </table> }
587 if {[info exists G(result)]} {
588 set res $G(result)
589 wapp-trim {
590 <div class=border id=result> %string($res) </div>
595 # URI: /control
597 # Whenever the form at the top of the application page is submitted, it
598 # is submitted here.
600 proc wapp-page-control {} {
601 global G
602 if {$::G(state)=="config"} {
603 set lControls [list platform test tcl jobs keep msvc debug]
604 set G(msvc) 0
605 set G(keep) 0
606 set G(debug) 0
607 } else {
608 set lControls [list jobs]
610 foreach v $lControls {
611 if {[wapp-param-exists control_$v]} {
612 set G($v) [wapp-param control_$v]
616 if {[wapp-param-exists control_run]} {
617 # This is a "run test" command.
618 wapptest_run
621 if {[wapp-param-exists control_stop]} {
622 # A "STOP tests" command.
623 set G(state) "stopped"
624 set G(result) "Test halted by user"
625 foreach j $G(test_array) {
626 set name [dict get $j config]
627 if { [info exists G(test.$name.channel)] } {
628 close $G(test.$name.channel)
629 unset G(test.$name.channel)
630 slave_test_done $name 1
633 wapptest_closelog
636 if {[wapp-param-exists control_reset]} {
637 # A "reset app" command.
638 set G(state) "config"
639 wapptest_init
642 if {$::G(state) == "running"} {
643 do_some_stuff
645 wapp-redirect /
648 # URI: /style.css
650 # Return the stylesheet for the application main page.
652 proc wapp-page-style.css {} {
653 wapp-subst {
655 /* The boxes with black borders use this class */
656 .border {
657 border: 3px groove #444444;
658 padding: 1em;
659 margin-top: 1em;
660 margin-bottom: 1em;
663 /* Float to the right (used for the Run/Stop/Reset button) */
664 .right { float: right; }
666 /* Style for the large red warning at the top of the page */
667 .warning {
668 color: red;
669 font-weight: bold;
672 /* Styles used by cells in the test table */
673 .padleft { padding-left: 5ex; }
674 .nowrap { white-space: nowrap; }
676 /* Styles for individual tests, depending on the outcome */
677 .testwait { }
678 .testrunning { color: blue }
679 .testdone { color: green }
680 .testfail { color: red }
684 # URI: /script/${state}.js
686 # The last part of this URI is always "config.js", "running.js" or
687 # "stopped.js", depending on the state of the application. It returns
688 # the javascript part of the front-end for the requested state to the
689 # browser.
691 proc wapp-page-script {} {
692 regexp {[^/]*$} [wapp-param REQUEST_URI] script
694 set tcl $::G(tcl)
695 set keep $::G(keep)
696 set msvc $::G(msvc)
697 set debug $::G(debug)
699 wapp-subst {
700 var lElem = \["control_platform", "control_test", "control_msvc",
701 "control_jobs", "control_debug"
703 lElem.forEach(function(e) {
704 var elem = document.getElementById(e);
705 elem.addEventListener("change", function() { control.submit() } );
708 elem = document.getElementById("control_tcl");
709 elem.value = "%string($tcl)"
711 elem = document.getElementById("control_keep");
712 elem.checked = %string($keep);
714 elem = document.getElementById("control_msvc");
715 elem.checked = %string($msvc);
717 elem = document.getElementById("control_debug");
718 elem.checked = %string($debug);
721 if {$script != "config.js"} {
722 wapp-subst {
723 var lElem = \["control_platform", "control_test",
724 "control_tcl", "control_keep", "control_msvc",
725 "control_debug"
727 lElem.forEach(function(e) {
728 var elem = document.getElementById(e);
729 elem.disabled = true;
734 if {$script == "running.js"} {
735 wapp-subst {
736 function reload_tests() {
737 fetch('tests')
738 .then( data => data.text() )
739 .then( data => {
740 document.getElementById("tests").innerHTML = data;
742 .then( data => {
743 if( document.getElementById("result") ){
744 document.location = document.location;
745 } else {
746 setTimeout(reload_tests, 1000)
751 setTimeout(reload_tests, 1000)
756 # URI: /env
758 # This is for debugging only. Serves no other purpose.
760 proc wapp-page-env {} {
761 wapp-allow-xorigin-params
762 wapp-trim {
763 <h1>Wapp Environment</h1>\n<pre>
764 <pre>%html([wapp-debug-env])</pre>
768 # URI: /log/dirname/test.log
770 # This URI reads file "dirname/test.log" from disk, wraps it in a <pre>
771 # block, and returns it to the browser. Use for viewing log files.
773 proc wapp-page-log {} {
774 set log [string range [wapp-param REQUEST_URI] 5 end]
775 set fd [open $log]
776 set data [read $fd]
777 close $fd
778 wapp-trim {
779 <pre>
780 %html($data)
781 </pre>
785 # Print out a usage message. Then do [exit 1].
787 proc wapptest_usage {} {
788 puts stderr {
789 This Tcl script is used to test various configurations of SQLite. By
790 default it uses "wapp" to provide an interactive interface. Supported
791 command line options (all optional) are:
793 --platform PLATFORM (which tests to run)
794 --config GLOB (only run configurations matching GLOB)
795 --smoketest (run "make smoketest" only)
796 --veryquick (run veryquick.test only)
797 --buildonly (build executables, do not run tests)
798 --jobs N (number of concurrent jobs)
799 --tcl DIR (where to find tclConfig.sh)
800 --deletefiles (delete extra files after each test)
801 --msvc (Use MS Visual C)
802 --debug (Also run [n]debugging versions of tests)
803 --noui (do not use wapp)
805 exit 1
808 # Sort command line arguments into two groups: those that belong to wapp,
809 # and those that belong to the application.
810 set WAPPARG(-server) 1
811 set WAPPARG(-local) 1
812 set WAPPARG(-scgi) 1
813 set WAPPARG(-remote-scgi) 1
814 set WAPPARG(-fromip) 1
815 set WAPPARG(-nowait) 0
816 set WAPPARG(-cgi) 0
817 set lWappArg [list]
818 set lTestArg [list]
819 for {set i 0} {$i < [llength $argv]} {incr i} {
820 set arg [lindex $argv $i]
821 if {[string range $arg 0 1]=="--"} {
822 set arg [string range $arg 1 end]
824 if {[info exists WAPPARG($arg)]} {
825 lappend lWappArg $arg
826 if {$WAPPARG($arg)} {
827 incr i
828 lappend lWappArg [lindex $argv $i]
830 } else {
831 lappend lTestArg $arg
835 wapptest_init
836 for {set i 0} {$i < [llength $lTestArg]} {incr i} {
837 set opt [lindex $lTestArg $i]
838 if {[string range $opt 0 1]=="--"} {
839 set opt [string range $opt 1 end]
841 switch -- $opt {
842 -platform {
843 if {$i==[llength $lTestArg]-1} { wapptest_usage }
844 incr i
845 set arg [lindex $lTestArg $i]
846 set lPlatform [releasetest_data platforms]
847 if {[lsearch $lPlatform $arg]<0} {
848 puts stderr "No such platform: $arg. Platforms are: $lPlatform"
849 exit -1
851 set G(platform) $arg
854 -smoketest { set G(test) Smoketest }
855 -veryquick { set G(test) Veryquick }
856 -buildonly { set G(test) Build-Only }
857 -jobs {
858 if {$i==[llength $lTestArg]-1} { wapptest_usage }
859 incr i
860 set G(jobs) [lindex $lTestArg $i]
863 -tcl {
864 if {$i==[llength $lTestArg]-1} { wapptest_usage }
865 incr i
866 set G(tcl) [lindex $lTestArg $i]
869 -deletefiles {
870 set G(keep) 0
873 -msvc {
874 set G(msvc) 1
877 -debug {
878 set G(debug) 1
881 -noui {
882 set G(noui) 1
883 set G(stdout) 1
886 -config {
887 if {$i==[llength $lTestArg]-1} { wapptest_usage }
888 incr i
889 set G(cfgglob) [lindex $lTestArg $i]
892 -stdout {
893 set G(stdout) 1
896 default {
897 puts stderr "Unrecognized option: [lindex $lTestArg $i]"
898 wapptest_usage
903 if {$G(noui)==0} {
904 wapp-start $lWappArg
905 } else {
906 wapptest_run
907 do_some_stuff
908 vwait forever