From: dan Date: Wed, 31 Jul 2019 21:08:55 +0000 (+0000) Subject: Update "releasetest_data.tcl" so that it is a standalone script that generates sh... X-Git-Tag: version-3.30.0~179 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=45cb2aa98cb1a082b90b4ff7f880a9b07050a09b;p=thirdparty%2Fsqlite.git Update "releasetest_data.tcl" so that it is a standalone script that generates sh or batch scripts to run each tcl test run at release time. Update wapptest.tcl to use it. FossilOrigin-Name: 559c2dd6724b2fc238760863d4be7132b591457e72ca5758fdd4002fbf7df4bc --- diff --git a/manifest b/manifest index 55d600d31d..0bde094361 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C New\stest\scases\sin\stest/fuzzdata8.db. -D 2019-07-31T15:16:14.758 +C Update\s"releasetest_data.tcl"\sso\sthat\sit\sis\sa\sstandalone\sscript\sthat\sgenerates\ssh\sor\sbatch\sscripts\sto\srun\seach\stcl\stest\srun\sat\srelease\stime.\sUpdate\swapptest.tcl\sto\suse\sit. +D 2019-07-31T21:08:55.220 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -1245,7 +1245,7 @@ F test/regexp1.test 497ea812f264d12b6198d6e50a76be4a1973a9d8 F test/regexp2.test 40e894223b3d6672655481493f1be12012f2b33c F test/reindex.test cd9d6021729910ece82267b4f5e1b5ac2911a7566c43b43c176a6a4732e2118d F test/releasetest.tcl 968fc1e8fd23e113fb8a04379747f3a9f2c12d207b2de85aeff5a825962e1cd7 x -F test/releasetest_data.tcl 146a73e8c8212f962b6558fee0711b895f11b607ee0610e6910781dc8f83797d +F test/releasetest_data.tcl 9dc6b01c986826a9e362bb8d1cc4289e558012dc618e98dff8b6f77dc472d129 F test/resetdb.test 8062cf10a09d8c048f8de7711e94571c38b38168db0e5877ba7561789e5eeb2b F test/resolver01.test f4022acafda7f4d40eca94dbf16bc5fc4ac30ceb F test/rollback.test 06680159bc6746d0f26276e339e3ae2f951c64812468308838e0a3362d911eaa @@ -1670,7 +1670,7 @@ F test/walslow.test c05c68d4dc2700a982f89133ce103a1a84cc285f F test/walthread.test 14b20fcfa6ae152f5d8e12f5dc8a8a724b7ef189f5d8ef1e2ceab79f2af51747 F test/walvfs.test c0faffda13d045a96dfc541347886bb1a3d6f3205857fc98e683edfab766ea88 F test/wapp.tcl b440cd8cf57953d3a49e7ee81e6a18f18efdaf113b69f7d8482b0710a64566ec -F test/wapptest.tcl 56d2b7974ecd8cca3189a670f757306d5ff3334cc9fe3744f7a6ad7ae4380e8c x +F test/wapptest.tcl b02f882a545191375e7ea452d351e32bfa1225da5005d5c41a20a6c0c91e30c3 x F test/where.test 0607caa5a1fbfe7b93b95705981b463a3a0408038f22ae6e9dc11b36902b0e95 F test/where2.test 478d2170637b9211f593120648858593bf2445a1 F test/where3.test 2341a294e17193a6b1699ea7f192124a5286ca6acfcc3f4b06d16c931fbcda2c @@ -1838,7 +1838,8 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P f237f60e4fa9171dfe9a77c8637595c2701e971034d41bd6018944e8b2b27a6f -R 22845c42decd0c34a7c752ff5adc7373 -U drh -Z 002ffc2c9d2b7953ffcbe175234492ba +P 6e92d71c24c6039e7116f02fc5f39b2b87efcd3674ea828077c03d760bf49c45 +R 8d98008b874d874a1ef71d33d67987f5 +T +closed f0b7d3b9a08a17081f312215bcb6cb778e02a9bb2de4b359b9e7aecff23d258b +U dan +Z 27d723c03ce07f3864426e28004404f2 diff --git a/manifest.uuid b/manifest.uuid index 47a4cb1d23..779006ab8f 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -6e92d71c24c6039e7116f02fc5f39b2b87efcd3674ea828077c03d760bf49c45 \ No newline at end of file +559c2dd6724b2fc238760863d4be7132b591457e72ca5758fdd4002fbf7df4bc \ No newline at end of file diff --git a/test/releasetest_data.tcl b/test/releasetest_data.tcl index 6b6c2a8efe..e28719aacf 100644 --- a/test/releasetest_data.tcl +++ b/test/releasetest_data.tcl @@ -2,6 +2,22 @@ # This file contains Configuration data used by "wapptest.tcl" and # "releasetest.tcl". # +set USAGE { +$argv0 configurations + List available configurations. + +$argv0 script ?-msvc? CONFIGURATION TARGET + Given a configuration and make target, return a bash (or, if -msvc + is specified, batch) script to execute the test. The first argument + passed to the script must be a directory containing SQLite source code. + +$argv0 platforms + List available platforms. + +$argv0 tests ?-nodebug? PLATFORM + List tests in a specified platform. If the -nodebug switch is + specified, synthetic debug/ndebug configurations are omitted. +} # Omit comments (text between # and \n) in a long multi-line string. # @@ -158,8 +174,6 @@ array set ::Configs [strip_comments { -DHAVE_LOCALTIME_R=1 -DHAVE_PREAD=1 -DHAVE_PWRITE=1 - -DHAVE_USLEEP=1 - -DHAVE_USLEEP=1 -DHAVE_UTIME=1 -DSQLITE_DEFAULT_CACHE_SIZE=1000 -DSQLITE_DEFAULT_CKPTFULLFSYNC=1 @@ -172,7 +186,6 @@ array set ::Configs [strip_comments { -DSQLITE_ENABLE_FTS3=1 -DSQLITE_ENABLE_FTS3_PARENTHESIS=1 -DSQLITE_ENABLE_FTS3_TOKENIZER=1 - if:os=="Darwin" -DSQLITE_ENABLE_LOCKING_STYLE=1 -DSQLITE_ENABLE_PERSIST_WAL=1 -DSQLITE_ENABLE_PURGEABLE_PCACHE=1 -DSQLITE_ENABLE_RTREE=1 @@ -212,7 +225,6 @@ array set ::Configs [strip_comments { "No-lookaside" { -DSQLITE_TEST_REALLOC_STRESS=1 -DSQLITE_OMIT_LOOKASIDE=1 - -DHAVE_USLEEP=1 } "Valgrind" { -DSQLITE_ENABLE_STAT4 @@ -234,6 +246,9 @@ array set ::Configs [strip_comments { FuzzFail1 {-O0} FuzzFail2 {-O0} }] +if {$tcl_platform(os)=="Darwin"} { + lappend Configs(Apple -DSQLITE_ENABLE_LOCKING_STYLE=1 +} array set ::Platforms [strip_comments { Linux-x86_64 { @@ -299,114 +314,250 @@ array set ::Platforms [strip_comments { } }] -proc make_test_suite {msvc withtcl name testtarget config} { +# Configuration verification: Check that each entry in the list of configs +# specified for each platforms exists. +# +foreach {key value} [array get ::Platforms] { + foreach {v t} $value { + if {0==[info exists ::Configs($v)]} { + puts stderr "No such configuration: \"$v\"" + exit -1 + } + } +} + +proc usage {} { + global argv0 + puts stderr [subst $::USAGE] + exit 1 +} + +proc is_prefix {p str min} { + set n [string length $p] + if {$n<$min} { return 0 } + if {[string range $str 0 [expr $n-1]]!=$p} { return 0 } + return 1 +} + +proc main_configurations {} { + foreach k [lsort [array names ::Configs]] { + puts $k + } +} + +proc main_platforms {} { + foreach k [lsort [array names ::Platforms]] { + puts "\"$k\"" + } +} + +proc main_script {args} { + set bMsvc 0 + set nArg [llength $args] + if {$nArg==3} { + if {![is_prefix [lindex $args 0] -msvc 2]} usage + set bMsvc 1 + } elseif {$nArg<2 || $nArg>3} { + usage + } + set config [lindex $args end-1] + set target [lindex $args end] + + set opts [list] ;# OPTS value + set cflags [expr {$bMsvc ? "-Zi" : "-g"}] ;# CFLAGS value + set makeOpts [list] ;# Extra args for [make] + set configOpts [list] ;# Extra args for [configure] + + if {$::tcl_platform(platform)=="windows"} { + lappend opts -DSQLITE_OS_WIN=1 + } else { + lappend opts -DSQLITE_OS_UNIX=1 + } - # Tcl variable $opts is used to build up the value used to set the - # OPTS Makefile variable. Variable $cflags holds the value for - # CFLAGS. The makefile will pass OPTS to both gcc and lemon, but - # CFLAGS is only passed to gcc. + # Figure out if this is a synthetic ndebug or debug configuration. + # + set bRemoveDebug 0 + if {[string match *-ndebug $config]} { + set bRemoveDebug 1 + set config [string range $config 0 end-7] + } + if {[string match *-debug $config]} { + lappend opts -DSQLITE_DEBUG + lappend opts -DSQLITE_EXTRA_IFNULLROW + set config [string range $config 0 end-6] + } + + # Ensure that the named configuration exists. + # + if {![info exists ::Configs($config)]} { + puts stderr "No such config: $config" + exit 1 + } + + # Loop through the parameters of the nominated configuration, updating + # $opts, $cflags, $makeOpts and $configOpts along the way. Rules are as + # follows: + # + # 1. If $bRemoveDebug is set and the parameter is -DSQLITE_DEBUG or + # -DSQLITE_DEBUG=1, discard it. + # + # 2. If the parameter begins with "-D", add it to $opts. + # + # 3. If the parameter begins with "--" add it to $configOpts. Unless + # this command is preparing a script for MSVC - then add an + # equivalent to $makeOpts or $opts. + # + # 4. If the parameter begins with "-" add it to $cflags. If in MSVC + # mode and the parameter is an -O option, instead add + # an OPTIMIZATIONS= switch to $makeOpts. # - set makeOpts "" - set cflags [expr {$msvc ? "-Zi" : "-g"}] - set opts "" - set title ${name}($testtarget) - set configOpts $withtcl - set skip 0 - - regsub -all {#[^\n]*\n} $config \n config - foreach arg $config { - if {$skip} { - set skip 0 + # 5. If none of the above apply, add the parameter to $makeOpts + # + foreach param $::Configs($config) { + if {$bRemoveDebug} { + if {$param=="-DSQLITE_DEBUG" || $param=="-DSQLITE_DEBUG=1" + || $param=="-DSQLITE_MEMDEBUG" || $param=="-DSQLITE_MEMDEBUG=1" + } { + continue + } + } + + if {[string range $param 0 1]=="-D"} { + lappend opts $param continue } - if {[regexp {^-[UD]} $arg]} { - lappend opts $arg - } elseif {[regexp {^[A-Z]+=} $arg]} { - lappend testtarget $arg - } elseif {[regexp {^if:([a-z]+)(.*)} $arg all key tail]} { - # Arguments of the form 'if:os=="Linux"' will cause the subsequent - # argument to be skipped if the $tcl_platform(os) is not "Linux", for - # example... - set skip [expr !(\$::tcl_platform($key)$tail)] - } elseif {[regexp {^--(enable|disable)-} $arg]} { - if {$msvc} { - if {$arg eq "--disable-amalgamation"} { - lappend makeOpts USE_AMALGAMATION=0 - continue - } - if {$arg eq "--disable-shared"} { - lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0 - continue - } - if {$arg eq "--enable-fts5"} { - lappend opts -DSQLITE_ENABLE_FTS5 - continue - } - if {$arg eq "--enable-json1"} { - lappend opts -DSQLITE_ENABLE_JSON1 - continue - } - if {$arg eq "--enable-shared"} { - lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1 - continue + + if {[string range $param 0 1]=="--"} { + if {$bMsvc} { + switch -- $param { + --disable-amalgamation { + lappend makeOpts USE_AMALGAMATION=0 + } + --disable-shared { + lappend makeOpts USE_CRT_DLL=0 DYNAMIC_SHELL=0 + } + --enable-fts5 { + lappend opts -DSQLITE_ENABLE_FTS5 + } + --enable-json1 { + lappend opts -DSQLITE_ENABLE_JSON1 + } + --enable-shared { + lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1 + } + --enable-session { + lappend opts -DSQLITE_ENABLE_PREUPDATE_HOOK + lappend opts -DSQLITE_ENABLE_SESSION + } + default { + error "Cannot translate $param for MSVC" + } } + } else { + lappend configOpts $param } - lappend configOpts $arg - } else { - if {$msvc} { - if {$arg eq "-g"} { - lappend cflags -Zi - continue - } - if {[regexp -- {^-O(\d+)$} $arg all level]} then { - lappend makeOpts OPTIMIZATIONS=$level - continue - } + + continue + } + + if {[string range $param 0 0]=="-"} { + if {$bMsvc && [regexp -- {^-O(\d+)$} $param -> level]} { + lappend makeOpts OPTIMIZATIONS=$level + } else { + lappend cflags $param } - lappend cflags $arg + continue } - } - # Disable sync to make testing faster. - # - lappend opts -DSQLITE_NO_SYNC=1 + lappend makeOpts $param + } - # Some configurations already set HAVE_USLEEP; in that case, skip it. + # Some configurations specify -DHAVE_USLEEP=0. For all others, add + # -DHAVE_USLEEP=1. # - if {[lsearch -regexp $opts {^-DHAVE_USLEEP(?:=|$)}]==-1} { + if {[lsearch $opts "-DHAVE_USLEEP=0"]<0} { lappend opts -DHAVE_USLEEP=1 } - # Add the define for this platform. - # - if {$::tcl_platform(platform)=="windows"} { - lappend opts -DSQLITE_OS_WIN=1 - } else { - lappend opts -DSQLITE_OS_UNIX=1 - } + if {$bMsvc==0} { + puts {set -e} + puts {} + puts {if [ "$#" -ne 1 ] ; then} + puts { echo "Usage: $0 " } + puts { exit -1 } + puts {fi } + puts {SRCDIR=$1} + puts {} + puts "TCL=\"[::tcl::pkgconfig get libdir,install]\"" - # Set the sub-directory to use. - # - set dir [string tolower [string map {- _ " " _ "(" _ ")" _} $name]] + puts "\$SRCDIR/configure --with-tcl=\$TCL $configOpts" + puts {} + puts {OPTS=" -DSQLITE_NO_SYNC=1"} + foreach o $opts { + puts "OPTS=\"\$OPTS $o\"" + } + puts {} + puts "CFLAGS=\"$cflags\"" + puts {} + puts "make $target \"CFLAGS=\$CFLAGS\" \"OPTS=\$OPTS\" $makeOpts" + } else { - # Join option lists into strings, using space as delimiter. - # - set makeOpts [join $makeOpts " "] - set cflags [join $cflags " "] - set opts [join $opts " "] + puts {set SRCDIR=%1} + set makecmd "nmake /f %SRCDIR%\\Makefile.msc TOP=%SRCDIR% $target " + append makecmd "\"CFLAGS=$cflags\" \"OPTS=$opts\" $makeOpts" - return [list $title $dir $configOpts $testtarget $makeOpts $cflags $opts] + puts $makecmd + } } -# Configuration verification: Check that each entry in the list of configs -# specified for each platforms exists. -# -foreach {key value} [array get ::Platforms] { - foreach {v t} $value { - if {0==[info exists ::Configs($v)]} { - puts stderr "No such configuration: \"$v\"" - exit -1 +proc main_tests {args} { + set bNodebug 0 + set nArg [llength $args] + if {$nArg==2} { + if {[is_prefix [lindex $args 0] -nodebug 2]} { + set bNodebug 1 + } elseif {[is_prefix [lindex $args 0] -debug 2]} { + set bNodebug 0 + } else usage + } elseif {$nArg==0 || $nArg>2} { + usage + } + set p [lindex $args end] + if {![info exists ::Platforms($p)]} { + puts stderr "No such platform: $p" + exit 1 + } + + foreach {config target} $::Platforms($p) { + puts "$config \"$target\"" + if {$bNodebug==0} { + if {$target!="checksymbols" && $target!="valgrindtest" + && $target!="fuzzoomtest" + } { + set iHas [string first SQLITE_DEBUG $::Configs($config)] + if {$iHas>=0} { + puts "$config-ndebug \"test\"" + } else { + puts "$config-debug \"test\"" + } + } } } } +if {[llength $argv]==0} { usage } +set cmd [lindex $argv 0] +set n [expr [llength $argv]-1] +if {[string match ${cmd}* configurations] && $n==0} { + main_configurations +} elseif {[string match ${cmd}* script]} { + main_script {*}[lrange $argv 1 end] +} elseif {[string match ${cmd}* platforms] && $n==0} { + main_platforms +} elseif {[string match ${cmd}* tests]} { + main_tests {*}[lrange $argv 1 end] +} else { + usage +} + + diff --git a/test/wapptest.tcl b/test/wapptest.tcl index 65bf98891c..dae2052ffc 100755 --- a/test/wapptest.tcl +++ b/test/wapptest.tcl @@ -5,10 +5,6 @@ exec wapptclsh "$0" ${1+"$@"} # package required wapp source [file join [file dirname [info script]] wapp.tcl] -# Read the data from the releasetest_data.tcl script. -# -source [file join [file dirname [info script]] releasetest_data.tcl] - # Variables set by the "control" form: # # G(platform) - User selected platform. @@ -69,6 +65,15 @@ proc wapptest_run {} { wapptest_output [string repeat * 70] } +proc releasetest_data {args} { + global G + set rtd [file join $G(srcdir) test releasetest_data.tcl] + set fd [open "|[info nameofexecutable] $rtd $args" r+] + set ret [read $fd] + close $fd + return $ret +} + # Generate the text for the box at the top of the UI. The current SQLite # version, according to fossil, along with a warning if there are # uncommitted changes in the checkout. @@ -108,7 +113,9 @@ proc set_test_array {} { global G if { $G(state)=="config" } { set G(test_array) [list] - foreach {config target} $::Platforms($G(platform)) { + set debug "-debug" + if {$G(debug)==0} { set debug "-nodebug"} + foreach {config target} [releasetest_data tests $debug $G(platform)] { # If using MSVC, do not run sanitize or valgrind tests. Or the # checksymbols test. @@ -136,22 +143,6 @@ proc set_test_array {} { } lappend G(test_array) [dict create config $config target $target] - - set exclude [list checksymbols valgrindtest fuzzoomtest] - if {$G(debug) && !($target in $exclude)} { - set debug_idx [lsearch -glob $::Configs($config) -DSQLITE_DEBUG*] - set xtarget $target - regsub -all {fulltest[a-z]*} $xtarget test xtarget - if {$debug_idx<0} { - lappend G(test_array) [ - dict create config $config-(Debug) target $xtarget - ] - } else { - lappend G(test_array) [ - dict create config $config-(NDebug) target $xtarget - ] - } - } } } } @@ -322,42 +313,28 @@ proc slave_fileevent {name} { # proc wapptest_slave_script {} { global G - set res { - proc readfile {filename} { - set fd [open $filename] - set data [read $fd] - close $fd - return $data - } - } - - if {$G(msvc)==0} { - append res { - set cfg [readfile wapptest_configure.sh] - set rc [catch { exec {*}$cfg >& test.log } msg] - if {$rc==0} { - set make [readfile wapptest_make.sh] - set rc [catch { exec {*}$make >>& test.log }] - } - } - } else { - append res { - set make [readfile wapptest_make.sh] - set rc [catch { exec {*}$make >>& test.log }] - } + if {$G(msvc)==0} { + set dir [file join .. $G(srcdir)] + set res [subst -nocommands { + set rc [catch "exec sh wapptest_cmd.sh {$dir} >>& test.log" ] + exit [set rc] + }] + } else { + set dir [file nativename [file normalize $G(srcdir)]] + set dir [string map [list "\\" "\\\\"] $dir] + set res [subst -nocommands { + set rc [catch "exec wapptest_cmd.bat {$dir} >>& test.log" ] + exit [set rc] + }] } - append res { exit $rc } - set res } # Launch a slave process to run a test. # -proc slave_launch { - name wtcl title dir configOpts testtarget makeOpts cflags opts -} { +proc slave_launch {name target dir} { global G catch { file mkdir $dir } msg @@ -366,28 +343,18 @@ proc slave_launch { } set G(test.$name.dir) $dir - # Write the configure command to wapptest_configure.sh. This file - # is empty if using MSVC - MSVC does not use configure. + # Write the test command to wapptest_cmd.sh|bat. # - set fd1 [open [file join $dir wapptest_configure.sh] w] - if {$G(msvc)==0} { - puts $fd1 "[file join .. $G(srcdir) configure] $wtcl $configOpts" + set ext sh + if {$G(msvc)} { set ext bat } + set fd1 [open [file join $dir wapptest_cmd.$ext] w] + if {$G(msvc)} { + puts $fd1 [releasetest_data script -msvc $name $target] + } else { + puts $fd1 [releasetest_data script $name $target] } close $fd1 - # Write the make command to wapptest_make.sh. Using nmake for MSVC and - # make for all other systems. - # - set makecmd "make" - if {$G(msvc)} { - set nativedir [file nativename $G(srcdir)] - set nativedir [string map [list "\\" "\\\\"] $nativedir] - set makecmd "nmake /f [file join $nativedir Makefile.msc] TOP=$nativedir" - } - set fd2 [open [file join $dir wapptest_make.sh] w] - puts $fd2 "$makecmd $makeOpts $testtarget \"CFLAGS=$cflags\" \"OPTS=$opts\"" - close $fd2 - # Write the wapptest_run.tcl script to the test directory. To run the # commands in the other two files. # @@ -448,30 +415,12 @@ proc do_some_stuff {} { } { set target [dict get $j target] + set dir [string tolower [string map {" " _ "-" _} $name]] set G(test.$name.start) [clock seconds] - set wtcl "" - if {$G(tcl)!=""} { set wtcl "--with-tcl=$G(tcl)" } - - # If this configuration is named -(Debug) or -(NDebug), - # then add or remove the SQLITE_DEBUG option from the base - # configuration before running the test. - if {[regexp -- {(.*)-(\(.*\))} $name -> head tail]} { - set opts $::Configs($head) - if {$tail=="(Debug)"} { - append opts " -DSQLITE_DEBUG=1 -DSQLITE_EXTRA_IFNULLROW=1" - } else { - regsub { *-DSQLITE_MEMDEBUG[^ ]* *} $opts { } opts - regsub { *-DSQLITE_DEBUG[^ ]* *} $opts { } opts - } - } else { - set opts $::Configs($name) - } + set G(test.$name.log) [file join $dir test.log] - set L [make_test_suite $G(msvc) $wtcl $name $target $opts] - set G(test.$name.log) [file join [lindex $L 1] test.log] - slave_launch $name $wtcl {*}$L + slave_launch $name $target $dir - set G(test.$name.log) [file join [lindex $L 1] test.log] incr nLaunch -1 } } @@ -517,7 +466,7 @@ proc generate_main_page {{extra {}}} { } # Build the "platform" select widget. - set lOpt [array names ::Platforms] + set lOpt [releasetest_data platforms] generate_select_widget Platform control_platform $lOpt $G(platform) # Build the "test" select widget. @@ -886,7 +835,7 @@ for {set i 0} {$i < [llength $lTestArg]} {incr i} { if {$i==[llength $lTestArg]-1} { wapptest_usage } incr i set arg [lindex $lTestArg $i] - set lPlatform [array names ::Platforms] + set lPlatform [releasetest_data platforms] if {[lsearch $lPlatform $arg]<0} { puts stderr "No such platform: $arg. Platforms are: $lPlatform" exit -1