summaryrefslogtreecommitdiffstats
path: root/test/testrunner_data.tcl
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--test/testrunner_data.tcl640
1 files changed, 640 insertions, 0 deletions
diff --git a/test/testrunner_data.tcl b/test/testrunner_data.tcl
new file mode 100644
index 0000000..984c6d8
--- /dev/null
+++ b/test/testrunner_data.tcl
@@ -0,0 +1,640 @@
+
+
+
+namespace eval trd {
+ variable tcltest
+ variable extra
+ variable all_configs
+ variable build
+
+
+ # Tcl tests to run for various builds.
+ #
+ set tcltest(linux.Fast-One) veryquick
+ set tcltest(linux.Debug-One) veryquick
+ set tcltest(linux.Debug-Two) veryquick
+ set tcltest(linux.Have-Not) veryquick
+ set tcltest(linux.Secure-Delete) veryquick
+ set tcltest(linux.Unlock-Notify) veryquick
+ set tcltest(linux.User-Auth) veryquick
+ set tcltest(linux.Update-Delete-Limit) veryquick
+ set tcltest(linux.Extra-Robustness) veryquick
+ set tcltest(linux.Device-Two) veryquick
+ set tcltest(linux.No-lookaside) veryquick
+ set tcltest(linux.Devkit) veryquick
+ set tcltest(linux.Apple) veryquick
+ set tcltest(linux.Sanitize) veryquick
+ set tcltest(linux.Device-One) all
+ set tcltest(linux.Default) all_plus_autovacuum_crash
+ set tcltest(linux.Valgrind) valgrind
+
+ set tcltest(osx.Locking-Style) veryquick
+ set tcltest(osx.Have-Not) veryquick
+ set tcltest(osx.Apple) all_less_no_mutex_try
+
+ set tcltest(win.Stdcall) veryquick
+ set tcltest(win.Have-Not) veryquick
+ set tcltest(win.Windows-Memdebug) veryquick
+ set tcltest(win.Windows-Win32Heap) veryquick
+ set tcltest(win.Windows-Sanitize) veryquick
+ set tcltest(win.Default) full
+
+ # Extra [make xyz] tests that should be run for various builds.
+ #
+ set extra(linux.Check-Symbols) checksymbols
+ set extra(linux.Fast-One) {fuzztest sourcetest}
+ set extra(linux.Debug-One) {fuzztest sourcetest mptest}
+ set extra(linux.Debug-Two) {fuzztest sourcetest}
+ set extra(linux.Have-Not) {fuzztest sourcetest}
+ set extra(linux.Secure-Delete) {fuzztest sourcetest}
+ set extra(linux.Unlock-Notify) {fuzztest sourcetest}
+ set extra(linux.Update-Delete-Limit) {fuzztest sourcetest}
+ set extra(linux.Extra-Robustness) {fuzztest sourcetest}
+ set extra(linux.Device-Two) {fuzztest sourcetest threadtest}
+ set extra(linux.No-lookaside) {fuzztest sourcetest}
+ set extra(linux.Devkit) {fuzztest sourcetest}
+ set extra(linux.Apple) {fuzztest sourcetest}
+ set extra(linux.Sanitize) {fuzztest sourcetest}
+ set extra(linux.Default) {fuzztest sourcetest threadtest}
+
+ set extra(osx.Apple) {fuzztest threadtest}
+ set extra(osx.Have-Not) {fuzztest sourcetest}
+ set extra(osx.Locking-Style) {mptest fuzztest sourcetest}
+
+ set extra(win.Default) mptest
+ set extra(win.Stdcall) {fuzztest sourcetest}
+ set extra(win.Windows-Memdebug) {fuzztest sourcetest}
+ set extra(win.Windows-Win32Heap) {fuzztest sourcetest}
+ set extra(win.Windows-Sanitize) fuzztest
+ set extra(win.Have-Not) {fuzztest sourcetest}
+
+ # The following mirrors the set of test suites invoked by "all.test".
+ #
+ set all_configs {
+ full no_optimization memsubsys1 memsubsys2 singlethread
+ multithread onefile utf16 exclusive persistent_journal
+ persistent_journal_error no_journal no_journal_error
+ autovacuum_ioerr no_mutex_try fullmutex journaltest
+ inmemory_journal pcache0 pcache10 pcache50 pcache90
+ pcache100 prepare mmap
+ }
+
+ #-----------------------------------------------------------------------
+ # Start of build() definitions.
+ #
+ set build(Default) {
+ -O2
+ --disable-amalgamation --disable-shared
+ --enable-session
+ -DSQLITE_ENABLE_RBU
+ }
+
+ # These two are used by [testrunner.tcl mdevtest] (All-O0) and
+ # [testrunner.tcl sdevtest] (All-Sanitize).
+ #
+ set build(All-Debug) {
+ --enable-debug --enable-all
+ }
+ set build(All-O0) {
+ -O0 --enable-all
+ }
+ set build(All-Sanitize) {
+ -DSQLITE_OMIT_LOOKASIDE=1
+ --enable-all -fsanitize=address,undefined -fno-sanitize-recover=undefined
+ }
+
+ set build(Sanitize) {
+ CC=clang -fsanitize=address,undefined -fno-sanitize-recover=undefined
+ -DSQLITE_ENABLE_STAT4
+ -DSQLITE_OMIT_LOOKASIDE=1
+ -DCONFIG_SLOWDOWN_FACTOR=5.0
+ --enable-debug
+ --enable-all
+ }
+ set build(Stdcall) {
+ -DUSE_STDCALL=1
+ -O2
+ }
+
+ # The "Have-Not" configuration sets all possible -UHAVE_feature options
+ # in order to verify that the code works even on platforms that lack
+ # these support services.
+ set build(Have-Not) {
+ -DHAVE_FDATASYNC=0
+ -DHAVE_GMTIME_R=0
+ -DHAVE_ISNAN=0
+ -DHAVE_LOCALTIME_R=0
+ -DHAVE_LOCALTIME_S=0
+ -DHAVE_MALLOC_USABLE_SIZE=0
+ -DHAVE_STRCHRNUL=0
+ -DHAVE_USLEEP=0
+ -DHAVE_UTIME=0
+ }
+ set build(Unlock-Notify) {
+ -O2
+ -DSQLITE_ENABLE_UNLOCK_NOTIFY
+ -DSQLITE_THREADSAFE
+ -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
+ }
+ set build(User-Auth) {
+ -O2
+ -DSQLITE_USER_AUTHENTICATION=1
+ }
+ set build(Secure-Delete) {
+ -O2
+ -DSQLITE_SECURE_DELETE=1
+ -DSQLITE_SOUNDEX=1
+ }
+ set build(Update-Delete-Limit) {
+ -O2
+ -DSQLITE_DEFAULT_FILE_FORMAT=4
+ -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
+ -DSQLITE_ENABLE_STMT_SCANSTATUS
+ -DSQLITE_LIKE_DOESNT_MATCH_BLOBS
+ -DSQLITE_ENABLE_CURSOR_HINTS
+ }
+ set build(Check-Symbols) {
+ -DSQLITE_MEMDEBUG=1
+ -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
+ -DSQLITE_ENABLE_FTS3=1
+ -DSQLITE_ENABLE_RTREE=1
+ -DSQLITE_ENABLE_MEMSYS5=1
+ -DSQLITE_ENABLE_MEMSYS3=1
+ -DSQLITE_ENABLE_COLUMN_METADATA=1
+ -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
+ -DSQLITE_SECURE_DELETE=1
+ -DSQLITE_SOUNDEX=1
+ -DSQLITE_ENABLE_ATOMIC_WRITE=1
+ -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
+ -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
+ -DSQLITE_ENABLE_STAT4
+ -DSQLITE_ENABLE_STMT_SCANSTATUS
+ --enable-fts5 --enable-session
+ }
+ set build(Debug-One) {
+ --disable-shared
+ -O2 -funsigned-char
+ -DSQLITE_DEBUG=1
+ -DSQLITE_MEMDEBUG=1
+ -DSQLITE_MUTEX_NOOP=1
+ -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
+ -DSQLITE_ENABLE_FTS3=1
+ -DSQLITE_ENABLE_RTREE=1
+ -DSQLITE_ENABLE_MEMSYS5=1
+ -DSQLITE_ENABLE_COLUMN_METADATA=1
+ -DSQLITE_ENABLE_STAT4
+ -DSQLITE_ENABLE_HIDDEN_COLUMNS
+ -DSQLITE_MAX_ATTACHED=125
+ -DSQLITE_MUTATION_TEST
+ --enable-fts5
+ }
+ set build(Debug-Two) {
+ -DSQLITE_DEFAULT_MEMSTATUS=0
+ -DSQLITE_MAX_EXPR_DEPTH=0
+ --enable-debug
+ }
+ set build(Fast-One) {
+ -O6
+ -DSQLITE_ENABLE_FTS4=1
+ -DSQLITE_ENABLE_RTREE=1
+ -DSQLITE_ENABLE_STAT4
+ -DSQLITE_ENABLE_RBU
+ -DSQLITE_MAX_ATTACHED=125
+ -DSQLITE_MAX_MMAP_SIZE=12884901888
+ -DSQLITE_ENABLE_SORTER_MMAP=1
+ -DLONGDOUBLE_TYPE=double
+ --enable-session
+ }
+ set build(Device-One) {
+ -O2
+ -DSQLITE_DEBUG=1
+ -DSQLITE_DEFAULT_AUTOVACUUM=1
+ -DSQLITE_DEFAULT_CACHE_SIZE=64
+ -DSQLITE_DEFAULT_PAGE_SIZE=1024
+ -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=32
+ -DSQLITE_DISABLE_LFS=1
+ -DSQLITE_ENABLE_ATOMIC_WRITE=1
+ -DSQLITE_ENABLE_IOTRACE=1
+ -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
+ -DSQLITE_MAX_PAGE_SIZE=4096
+ -DSQLITE_OMIT_LOAD_EXTENSION=1
+ -DSQLITE_OMIT_PROGRESS_CALLBACK=1
+ -DSQLITE_OMIT_VIRTUALTABLE=1
+ -DSQLITE_ENABLE_HIDDEN_COLUMNS
+ -DSQLITE_TEMP_STORE=3
+ }
+ set build(Device-Two) {
+ -DSQLITE_4_BYTE_ALIGNED_MALLOC=1
+ -DSQLITE_DEFAULT_AUTOVACUUM=1
+ -DSQLITE_DEFAULT_CACHE_SIZE=1000
+ -DSQLITE_DEFAULT_LOCKING_MODE=0
+ -DSQLITE_DEFAULT_PAGE_SIZE=1024
+ -DSQLITE_DEFAULT_TEMP_CACHE_SIZE=1000
+ -DSQLITE_DISABLE_LFS=1
+ -DSQLITE_ENABLE_FTS3=1
+ -DSQLITE_ENABLE_MEMORY_MANAGEMENT=1
+ -DSQLITE_ENABLE_RTREE=1
+ -DSQLITE_MAX_COMPOUND_SELECT=50
+ -DSQLITE_MAX_PAGE_SIZE=32768
+ -DSQLITE_OMIT_TRACE=1
+ -DSQLITE_TEMP_STORE=3
+ -DSQLITE_THREADSAFE=2
+ --enable-fts5 --enable-session
+ }
+ set build(Locking-Style) {
+ -O2
+ -DSQLITE_ENABLE_LOCKING_STYLE=1
+ }
+ set build(Apple) {
+ -Os
+ -DHAVE_GMTIME_R=1
+ -DHAVE_ISNAN=1
+ -DHAVE_LOCALTIME_R=1
+ -DHAVE_PREAD=1
+ -DHAVE_PWRITE=1
+ -DHAVE_UTIME=1
+ -DSQLITE_DEFAULT_CACHE_SIZE=1000
+ -DSQLITE_DEFAULT_CKPTFULLFSYNC=1
+ -DSQLITE_DEFAULT_MEMSTATUS=1
+ -DSQLITE_DEFAULT_PAGE_SIZE=1024
+ -DSQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS=1
+ -DSQLITE_ENABLE_API_ARMOR=1
+ -DSQLITE_ENABLE_AUTO_PROFILE=1
+ -DSQLITE_ENABLE_FLOCKTIMEOUT=1
+ -DSQLITE_ENABLE_FTS3=1
+ -DSQLITE_ENABLE_FTS3_PARENTHESIS=1
+ -DSQLITE_ENABLE_FTS3_TOKENIZER=1
+ -DSQLITE_ENABLE_PERSIST_WAL=1
+ -DSQLITE_ENABLE_PURGEABLE_PCACHE=1
+ -DSQLITE_ENABLE_RTREE=1
+ -DSQLITE_ENABLE_SETLK_TIMEOUT=2
+ -DSQLITE_ENABLE_SNAPSHOT=1
+ -DSQLITE_ENABLE_UPDATE_DELETE_LIMIT=1
+ -DSQLITE_MAX_LENGTH=2147483645
+ -DSQLITE_MAX_VARIABLE_NUMBER=500000
+ -DSQLITE_NO_SYNC=1
+ -DSQLITE_OMIT_AUTORESET=1
+ -DSQLITE_OMIT_LOAD_EXTENSION=1
+ -DSQLITE_PREFER_PROXY_LOCKING=1
+ -DSQLITE_SERIES_CONSTRAINT_VERIFY=1
+ -DSQLITE_THREADSAFE=2
+ -DSQLITE_USE_URI=1
+ -DSQLITE_WRITE_WALFRAME_PREBUFFERED=1
+ -DUSE_GUARDED_FD=1
+ -DUSE_PREAD=1
+ --enable-fts5
+ }
+ set build(Extra-Robustness) {
+ -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
+ -DSQLITE_MAX_ATTACHED=62
+ }
+ set build(Devkit) {
+ -DSQLITE_DEFAULT_FILE_FORMAT=4
+ -DSQLITE_MAX_ATTACHED=30
+ -DSQLITE_ENABLE_COLUMN_METADATA
+ -DSQLITE_ENABLE_FTS4
+ -DSQLITE_ENABLE_FTS5
+ -DSQLITE_ENABLE_FTS4_PARENTHESIS
+ -DSQLITE_DISABLE_FTS4_DEFERRED
+ -DSQLITE_ENABLE_RTREE
+ --enable-fts5
+ }
+ set build(No-lookaside) {
+ -DSQLITE_TEST_REALLOC_STRESS=1
+ -DSQLITE_OMIT_LOOKASIDE=1
+ }
+ set build(Valgrind) {
+ -DSQLITE_ENABLE_STAT4
+ -DSQLITE_ENABLE_FTS4
+ -DSQLITE_ENABLE_RTREE
+ -DSQLITE_ENABLE_HIDDEN_COLUMNS
+ -DLONGDOUBLE_TYPE=double
+ -DCONFIG_SLOWDOWN_FACTOR=8.0
+ }
+
+ set build(Windows-Memdebug) {
+ MEMDEBUG=1
+ DEBUG=3
+ }
+ set build(Windows-Win32Heap) {
+ WIN32HEAP=1
+ DEBUG=4
+ }
+ set build(Windows-Sanitize) {
+ ASAN=1
+ }
+
+}
+
+
+#-------------------------------------------------------------------------
+proc trd_import {} {
+ uplevel {
+ variable ::trd::tcltest
+ variable ::trd::extra
+ variable ::trd::all_configs
+ variable ::trd::build
+ }
+}
+
+proc trd_builds {platform} {
+ trd_import
+
+ set klist [lsort -uniq [concat \
+ [array names tcltest ${platform}.*] \
+ [array names extra ${platform}.*] \
+ ]]
+ if {[llength $klist]==0} {
+ error "no such platform: $platform"
+ }
+
+ set ret ""
+ foreach k $klist {
+ foreach {p c} [split $k "."] {}
+ lappend ret $c
+ }
+ set ret
+}
+
+proc trd_configs {platform bld} {
+ trd_import
+
+ set clist [list]
+
+ if {[info exists tcltest($platform.$bld)]} {
+ set clist $tcltest($platform.$bld)
+ if {$clist=="all"} {
+ set clist $all_configs
+ } elseif {$clist=="all_plus_autovacuum_crash"} {
+ set clist [concat $all_configs autovacuum_crash]
+ } elseif {$clist=="all_less_no_mutex_try"} {
+ set idx [lsearch $all_configs no_mutex_try]
+ set clist [lreplace $all_configs $idx $idx]
+ }
+ }
+
+ set clist
+}
+
+proc trd_extras {platform bld} {
+ trd_import
+ if {[info exists extra($platform.$bld)]==0} { return [list] }
+ return $extra($platform.$bld)
+}
+
+# Usage:
+#
+# trd_fuzztest_data
+#
+# This returns data used by testrunner.tcl to run commands equivalent
+# to [make fuzztest]. The returned value is a list, which should be
+# interpreted as a sequence of pairs. The first element of each pair
+# is an interpreter name. The second element is a list of files.
+# testrunner.tcl automatically creates one job to build each interpreter,
+# and one to run each of the files with it once it has been built.
+#
+# In practice, the returned value looks like this:
+#
+# {
+# {fuzzcheck {$testdir/fuzzdata1.db $testdir/fuzzdata2.db ...}}
+# {{sessionfuzz run} $testdir/sessionfuzz-data1.db}
+# }
+#
+# where $testdir is replaced by the full-path to the test-directory (the
+# directory containing this file). "fuzzcheck" and "sessionfuzz" have .exe
+# extensions on windows.
+#
+proc trd_fuzztest_data {} {
+ set EXE ""
+ set lFuzzDb [glob [file join $::testdir fuzzdata*.db]]
+ set lSessionDb [glob [file join $::testdir sessionfuzz-data*.db]]
+
+ if {$::tcl_platform(platform)=="windows"} {
+ return [list fuzzcheck.exe $lFuzzDb]
+ }
+
+ return [list fuzzcheck $lFuzzDb {sessionfuzz run} $lSessionDb]
+}
+
+
+proc trd_all_configs {} {
+ trd_import
+ set all_configs
+}
+
+proc trimscript {text} {
+ set text [string map {"\n " "\n"} [string trim $text]]
+}
+
+proc make_sh_script {srcdir opts cflags makeOpts configOpts} {
+
+ set tcldir [::tcl::pkgconfig get libdir,install]
+ set myopts ""
+ if {[info exists ::env(OPTS)]} {
+ append myopts "# From environment variable:\n"
+ append myopts "OPTS=$::env(OPTS)\n\n"
+ }
+ foreach o [lsort $opts] {
+ append myopts "OPTS=\"\$OPTS $o\"\n"
+ }
+
+ return [trimscript [subst -nocommands {
+ set -e
+ if [ "\$#" -ne 1 ] ; then
+ echo "Usage: \$0 <target>"
+ exit -1
+ fi
+
+ SRCDIR="$srcdir"
+ TCLDIR="$tcldir"
+
+ if [ ! -f Makefile ] ; then
+ \$SRCDIR/configure --with-tcl=\$TCL $configOpts
+ fi
+
+ $myopts
+ CFLAGS="$cflags"
+
+ make \$1 "CFLAGS=\$CFLAGS" "OPTS=\$OPTS" $makeOpts
+ }]]
+}
+
+# Generate the text of a *.bat script.
+#
+proc make_bat_file {srcdir opts cflags makeOpts} {
+ set srcdir [file nativename [file normalize $srcdir]]
+
+ return [trimscript [subst -nocommands {
+ set TARGET=%1
+ set TMP=%CD%
+ nmake /f $srcdir\\Makefile.msc TOP="$srcdir" %TARGET% "CCOPTS=$cflags" "OPTS=$opts" $makeOpts
+ }]]
+}
+
+
+# Generate the text of a shell script.
+#
+proc make_script {cfg srcdir bMsvc} {
+ 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]
+
+ # Define either SQLITE_OS_WIN or SQLITE_OS_UNIX, as appropriate.
+ if {$::tcl_platform(platform)=="windows"} {
+ lappend opts -DSQLITE_OS_WIN=1
+ } else {
+ lappend opts -DSQLITE_OS_UNIX=1
+ }
+
+ # Unless the configuration specifies -DHAVE_USLEEP=0, set -DHAVE_USLEEP=1.
+ #
+ if {[lsearch $cfg "-DHAVE_USLEEP=0"]<0} {
+ lappend cfg -DHAVE_USLEEP=1
+ }
+
+ # Loop through the parameters of the nominated configuration, updating
+ # $opts, $cflags, $makeOpts and $configOpts along the way. Rules are as
+ # follows:
+ #
+ # 1. If the parameter begins with "-D", add it to $opts.
+ #
+ # 2. 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.
+ #
+ # 3. If the parameter begins with "-" add it to $cflags. If in MSVC
+ # mode and the parameter is an -O<integer> option, instead add
+ # an OPTIMIZATIONS=<integer> switch to $makeOpts.
+ #
+ # 4. If none of the above apply, add the parameter to $makeOpts
+ #
+ foreach param $cfg {
+
+ if {[string range $param 0 1]=="-D"} {
+ lappend opts $param
+ continue
+ }
+
+ if {[string range $param 0 1]=="--"} {
+ if {$bMsvc==0} {
+ lappend configOpts $param
+ } else {
+
+ 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-shared {
+ lappend makeOpts USE_CRT_DLL=1 DYNAMIC_SHELL=1
+ }
+ --enable-session {
+ lappend opts -DSQLITE_ENABLE_PREUPDATE_HOOK
+ lappend opts -DSQLITE_ENABLE_SESSION
+ }
+ --enable-all {
+ }
+ --enable-debug {
+ # lappend makeOpts OPTIMIZATIONS=0
+ lappend opts -DSQLITE_DEBUG
+ }
+ default {
+ error "Cannot translate $param for MSVC"
+ }
+ }
+ }
+
+ continue
+ }
+
+ if {[string range $param 0 0]=="-"} {
+
+ if {$bMsvc} {
+ if {[regexp -- {^-O(\d+)$} $param -> level]} {
+ lappend makeOpts OPTIMIZATIONS=$level
+ continue
+ }
+ if {$param eq "-fsanitize=address,undefined"} {
+ lappend makeOpts ASAN=1
+ continue
+ }
+ }
+
+ lappend cflags $param
+ continue
+ }
+
+ lappend makeOpts $param
+ }
+
+ if {$bMsvc==0} {
+ set zRet [make_sh_script $srcdir $opts $cflags $makeOpts $configOpts]
+ } else {
+ set zRet [make_bat_file $srcdir $opts $cflags $makeOpts]
+ }
+}
+
+# Usage:
+#
+# trd_buildscript CONFIG SRCDIR MSVC
+#
+# This command returns the full text of a script (either a shell script or
+# an ms-dos bat file) that may be used to build SQLite source code according
+# to a nominated configuration.
+#
+# Parameter CONFIG must be a configuration defined above in the ::trd::build
+# array. SRCDIR is the root directory of an SQLite source tree (the parent
+# directory of that containing this script). MSVC is a boolean - true to
+# use the MSVC compiler, false otherwise.
+#
+proc trd_buildscript {config srcdir bMsvc} {
+ trd_import
+
+ # Ensure that the named configuration exists.
+ if {![info exists build($config)]} {
+ error "No such build config: $config"
+ }
+
+ # Generate and return the script.
+ return [make_script $build($config) $srcdir $bMsvc]
+}
+
+# Usage:
+#
+# trd_test_script_properties PATH
+#
+# The argument must be a path to a Tcl test script. This function scans the
+# first 100 lines of the script for lines that look like:
+#
+# TESTRUNNER: <properties>
+#
+# where <properties> is a list of identifiers, each of which defines a
+# property of the test script. Example properties are "slow" or "superslow".
+#
+proc trd_test_script_properties {path} {
+ # Use this global array as a cache:
+ global trd_test_script_properties_cache
+
+ if {![info exists trd_test_script_properties_cache($path)]} {
+ set fd [open $path]
+ set ret [list]
+ for {set line 0} {$line < 100 && ![eof $fd]} {incr line} {
+ set text [gets $fd]
+ if {[string match -nocase *testrunner:* $text]} {
+ regexp -nocase {.*testrunner:(.*)} $text -> properties
+ lappend ret {*}$properties
+ }
+ }
+ set trd_test_script_properties_cache($path) $ret
+ close $fd
+ }
+
+ set trd_test_script_properties_cache($path)
+}
+