summaryrefslogtreecommitdiff
path: root/test/rewrite-test-output.tcl
diff options
context:
space:
mode:
authorcashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
committercashmere <cashmere@autistici.org>2026-09-04 09:05:24 +0200
commit4f49b16079b27d7ce633619e4cddfdf2bffbc952 (patch)
treec296c1e7f3c3e2f6859c6d3a1b1b208779b89679 /test/rewrite-test-output.tcl
downloadrelic-4f49b16079b27d7ce633619e4cddfdf2bffbc952.tar.gz
initial commitHEADmaster
Diffstat (limited to 'test/rewrite-test-output.tcl')
-rw-r--r--test/rewrite-test-output.tcl645
1 files changed, 645 insertions, 0 deletions
diff --git a/test/rewrite-test-output.tcl b/test/rewrite-test-output.tcl
new file mode 100644
index 0000000..600b43a
--- /dev/null
+++ b/test/rewrite-test-output.tcl
@@ -0,0 +1,645 @@
+#!/usr/bin/env tclsh
+
+# Script to anonymise test results for comparison.
+# - Replaces hashes, pids and similar with fixed strings
+# - Rewrites temporary paths to standardise them in output
+
+# Pick up options
+set EXTRA 0
+set i [lsearch $argv -extra]
+while { $i >= 0 } {
+ incr EXTRA
+ set argv [lreplace $argv $i $i]
+ set i [lsearch $argv -extra]
+}
+
+# With no arguments or "-", use stdin.
+set fname "-"
+if { [llength $argv] > 0 } {
+ set fname [lindex $argv 0]
+}
+
+# Any -options, or an empty first argument, is an error.
+if { [llength $argv] > 1 || [regexp {^-.+} $fname] } {
+ puts stderr "Error: argument error"
+ puts stderr "usage: \[-extra\] [file tail $argv0] ?FILE"
+ puts stderr " Rewrite test output to ease comparison of outputs."
+ puts stderr " With -extra, more output is rewritten as is summaries"
+ puts stderr " to make diff(1) mor euseful across runs and platforms."
+ exit 1
+} elseif { $fname ne "-" && ! [file exists $fname] } {
+ puts stderr "File does not exist: '$fname'"
+ exit 1
+}
+
+proc common_rewrites { line testname } {
+ # Normalise the fossil commands with path as just fossil
+ regsub {^(?:[A-Z]:)?/.*?/fossil(?:\.exe)? } $line {fossil } line
+ if {[string match "Usage: *" $line]} {
+ regsub {^(Usage: )/.*?/fossil(?:\.exe)? } $line {\1fossil } line
+ regsub {^(Usage: )[A-Z]:\\.*?\\fossil(?:\.exe)? } $line {\1fossil } line
+ }
+
+ # Accept 40 and 64 byte hashes as such
+ regsub -all {[[:<:]][0-9a-f]{40}[[:>:]]} $line HASH line
+ regsub -all {[[:<:]][0-9a-f]{64}[[:>:]]} $line HASH line
+
+ # Date and time
+ regsub -all {[[:<:]]\d{4}-\d\d-\d\d \d\d:\d\d:\d\d[[:>:]]} $line {YYYY-mm-dd HH:MM:SS} line
+ if { [lsearch -exact {"amend" "wiki"} $testname] >= 0 } {
+ # With embedded T and milliseconds
+ regsub { \d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}$} $line { YYYY-mm-ddTHH:MM:SS.NNN} line
+ }
+ if { [lsearch -exact {"amend" "th1-hooks" "wiki"} $testname] >= 0 } {
+ regsub {[[:<:]]\d{4}-\d\d-\d\d[[:>:]]} $line {YYYY-mm-dd} line
+ }
+
+ # Timelines have HH:MM:SS [HASH], but don't mess with the zero'ed version.
+ regsub {^(?!00:00:00 \[0000000000\])\d\d:\d\d:\d\d \[[0-9a-f]{10}\] } $line {HH:MM:SS [HASH] } line
+
+ # Temporary directories
+ regsub -all {(?:[A-Z]:)?/.*?/repo_\d+/\d+_\d+} $line {/TMP/repo_PID/SEC_SEQ} line
+ # Home directories only seem present with .fossil or _fossil. Simplify to .fossil.
+ regsub -all {(?:[A-Z]:)?/.*?/home_\d+/[._]fossil[[:>:]]} $line {/TMP/home_PID/.fossil} line
+
+ # Users in output
+ regsub { (\(user: )[^\)]*\)$} $line { \1USER)} line
+
+ return $line
+}
+
+#
+# tests/tests_unix/tests_windows contain tuples of
+#
+# 1. A regular expression to match current line
+# 2. A substitution for the current line
+#
+# Some common patterns applicable to multiples tests are appended below.
+#
+# The common_rewrites procedure is run first, so use e.g. HASH as needed.
+#
+
+dict set tests "amend" {
+ {^(fossil artifact) [0-9a-f]{10}}
+ {\1 HASH}
+ {^U [^ ]+$}
+ {U USER}
+ {^Z [0-9a-f]{32}$}
+ {Z CHECKSUM}
+ {^(ed -s \./ci-comment-).*?(\.txt)$}
+ {\1UNIQ\2}
+ {^(fossil amend HASH -date \{?)\d\d/\d\d/\d{4}}
+ {\1dd/mm/YYYY}
+ {^(fossil amend HASH -date \{.* )\d{4}(\})$}
+ {\1YYYY\2}
+ {^(fossil amend HASH -date \{.* )\d\d:}
+ {\1HH:}
+ {^(fossil amend HASH -date \{)[A-Z][a-z]{2} [A-Z][a-z]{2} [ 0-9]\d }
+ {\1Day Mon dd }
+ {(\] Edit \[)[0-9a-f]{16}.[0-9a-f]{10}(\]: )}
+ {\1HASH1|HASH2\2}
+ {(\] Edit \[.*?&dp=)[0-9a-f]{16}}
+ {\1dp=HASH}
+}
+
+dict set tests "cmdline" {
+ {^(fossil test-echo --args) .*/}
+ {\1 /TMP/}
+ {^(g\.nameOfExe =) \[[^\]]+[/\\]fossil(?:\.exe)?\]$}
+ {\1 [/PATH/FOSSILCMD]}
+ {^(argv\[0\] =) \[[^\]]+[/\\]fossil(?:\.exe)?\]$}
+ {\1 [/PATH/FOSSILCMD]}
+}
+
+dict set tests "contains-selector" {
+ {^(fossil test-contains-selector) .*?/(compare-selector.css )}
+ {\1 /TMP/\2}
+}
+
+dict set tests "json" {
+ {^(Content-Length) \d+$}
+ {\1 LENGTH}
+ {^(Cookie: fossil-)[0-9a-f]{16}(\=HASH%2F)\d+\.\d+(%2Fanonymous)$}
+ {\1CODE\2NOW\3}
+ {^(GET /json/cap\?authToken\=HASH)/\d+\.\d+/(anonymous )}
+ {\1/NOW/\2}
+ {^(Cookie: fossil-)[0-9a-f]{16}\=[0-9A-F]{50}%2F[0-9a-f]{16}%2F(.*)$}
+ {\1CODE=SHA1%2FCODE%2F\2}
+ {("authToken":").+?(")}
+ {\1AUTHTOKEN\2}
+ {("averageArtifactSize":)\d+()}
+ {\1SIZE\2}
+ {("compiler":").+?(")}
+ {\1COMPILER\2}
+ {("loginCookieName":").+?(")}
+ {\1COOKIE\2}
+ {("manifestVersion":"\[)[0-9a-f]{10}(\]")}
+ {\1HASH\2}
+ {("manifestYear":")\d{4}(")}
+ {\1YYYY\2}
+ {("name":").+?(")}
+ {\1NAME\2}
+ {("password":")[0-9a-f]+(")}
+ {\1PASSWORD\2}
+ {("projectCode":")[0-9a-f]{40}(")}
+ {\1HASH\2}
+ {("procTimeMs":)\d+}
+ {\1MSEC}
+ {("procTimeUs":)\d+}
+ {\1USEC}
+ {("releaseVersion":")\d+\.\d+(")}
+ {\1VERSION\2}
+ {("releaseVersionNumber":")\d+(")}
+ {\1VERSION_NUMBER\2}
+ {("timestamp":)\d+}
+ {\1SEC}
+ {("seed":)\d+()}
+ {\1SEED\2}
+ {("uid":)\d+()}
+ {\1UID\2}
+ {("uncompressedArtifactSize":)\d+()}
+ {\1SIZE\2}
+ {("user":").+?(")}
+ {\1USER\2}
+ {("version":"YYYY-mm-dd HH:MM:SS )\[[0-9a-f]{10}\] \(\d+\.\d+\.\d+\)"}
+ {\1[HASH] (major.minor.patch)}
+ {^(Date:) [A-Z][a-z]{2}, \d\d? [A-Z][a-z]{2} \d{4} \d\d:\d\d:\d\d [-+]\d{4}$}
+ {\1 Day, dd Mon YYYY HH:MM:SS TZ}
+}
+
+dict set tests "merge_renames" {
+ {^(size: {7})\d+( bytes)$}
+ {\1N\2}
+ {^(type: {7}Check-in by ).+?( on YYYY-mm-dd HH:MM:SS)$}
+ {\1USER\2}
+}
+
+dict set tests "set-manifest" {
+ {^(project-code: )[0-9a-f]{40}$}
+ {\1HASH} line
+}
+
+dict set tests "stash" {
+ {^(---|\+\+\+) NUL$}
+ {\1 /dev/null}
+ {(^ 1: \[)[0-9a-f]{14}(\] on YYYY-mm-dd HH:MM:SS)$}
+ {\1HASH\2}
+ {(^ 1: \[)[0-9a-f]{14}(\] from YYYY-mm-dd HH:MM:SS)$}
+ {\1HASH\2}
+}
+
+dict set tests "th1" {
+ {^(fossil test-th-source) (?:[A-Z]:)?.*?/(th1-)\d+([.]th1)$}
+ {\1 /TMP/\2PID\3}
+ {^(?:[A-Z]:)?[/\\].*?[/\\]fossil(?:\.exe)?$}
+ {/PATH/FOSSILCMD}
+ {[[:<:]](Content-Security-Policy[[:>:]].*'nonce-)[0-9a-f]{48}(';)}
+ {\1NONCE\2}
+ {^(<link rel="stylesheet" href="/style.css\?id=)[0-9a-f]+(" type="text/css">)$}
+ {\1ID\2}
+ {^\d+\.\d{3}(s by)$}
+ {N.MMM\1}
+ {^(Fossil) \d+\.\d+ \[[0-9a-f]{10}\] (YYYY-mm-dd HH:MM:SS)$}
+ {\1 N.M [HASH] \2}
+ {^(<script nonce=")[0-9a-f]{48}(">/\* style\.c:)\d+}
+ {\1NONCE\2LINENO}
+}
+
+dict set tests "th1-docs" {
+ {^(check-ins: ).*}
+ {\1COUNT}
+ {^(local-root: ).*}
+ {\1/PATH/}
+ {^(repository: ).*}
+ {\1/PATH/REPO}
+ {^(comment: ).*}
+ {\1/COMMENT/}
+ {^(tags: ).*}
+ {\1/TAGS/}
+ {(--ipaddr 127\.0\.0\.1) .*? (--localauth)}
+ {\1 REPO \2}
+}
+
+dict set tests "th1-hooks" {
+ {^(?:/[^:]*/fossil|[A-Z]:\\[^:]*\\fossil\.exe): (unknown command:|use \"help\")}
+ {fossil: \1}
+ {^(project-code: )[0-9a-f]{40}$}
+ {\1HASH}
+}
+
+dict set tests "th1-tcl" {
+ {^(fossil test-th-render --open-config) \{?.*?[/\\]test[/\\]([^/\\]*?)\}?$}
+ {\1 /CHECKOUT/test/\2}
+ {^(fossil)(?:\.exe)?( 3 \{test-th-render --open-config )(?:\{[A-Z]:)?[/\\].*?[/\\]test[/\\](th1-tcl9.txt\})\}?$}
+ {\1\2/CHECKOUT/test/\3}
+ {^\d{10}$}
+ {SEC}
+}
+
+dict set tests "unversioned" {
+ {^(fossil user new uvtester.*) \d+$}
+ {\1 PASSWORD}
+ {^(fossil .*http://uvtester:)\d+(@localhost:)\d+}
+ {\1PASSWORD\2PORT}
+ {^(Pull from http://uvtester@localhost:)\d+}
+ {\1PORT}
+ {^(ERROR \(1\): Usage:) .*?[/\\]fossil(?:\.exe)? (unversioned)}
+ {\1 /PATH/fossil \2}
+ {^(Started Fossil server, pid \")\d+(\", port \")\d+}
+ {\1PID\2PORT}
+ {^(Now in client directory \")(?:[A-Z]:)?/.*?/uvtest_\d+_\d+\"}
+ {\1/TMP/uvtest_SEC_SEQ}
+ {^(Stopped Fossil server, pid \")\d+(\", using argument \")(?:\d+|[^\"]*\.stopper)(\")}
+ {\1PID\2PID_OR_SCRIPT\3}
+ {^(This is unversioned file #4\.) \d+ \d+}
+ {\1 PID SEC}
+ {^(This is unversioned file #4\. PID SEC) \d+ \d+}
+ {\1 PID SEC}
+ {^[0-9a-f]{12}( YYYY-mm-dd HH:MM:SS *)(\d+)( *)\2( unversioned4.txt)$}
+ {HASH \1SZ\3SZ\4}
+ {^[0-9a-f]{40}$}
+ {\1HASH}
+ {^((?:Clone|Pull)? done, wire bytes sent: )\d+( received: )\d+( remote: )(?:127\.0.0\.1|::1)$}
+ {\1SENT\2RECV\3LOCALIP}
+ {^(project-id: )[0-9a-f]{40}$}
+ {\1HASH}
+ {^(server-id: )[0-9a-f]{40}$}
+ {\1HASH}
+ {^(admin-user: uvtester \(password is ").*("\))$}
+ {\1PASSWORD\2}
+ {^(repository: ).*?/uvtest_\d+_\d+/(uvrepo.fossil)$}
+ {\1/TMP/uvtest_SEC_SEQ/\2}
+ {^(local-root: ).*?/uvtest_\d+_\d+/$}
+ {\1/TMP/uvtest_SEC_SEQ/}
+ {^(project-code: )[0-9a-f]{40}$}
+ {\1HASH}
+}
+
+dict set tests "utf" {
+ {^(fossil test-looks-like-utf) (?:[A-Z]:)?/.*?/([^/\\]*?)\}?$}
+ {\1 /TMP/test/\2}
+ {^(File ")(?:[A-Z]:)?/.*?/(utf-check-\d+-\d+-\d+-\d+.jnk" has \d+ bytes\.)$}
+ {\1/TMP/\2}
+}
+
+dict set tests "wiki" {
+ {^(fossil (?:attachment|wiki) .*--technote )[0-9a-f]{21}$}
+ {\1HASH}
+ {^(fossil (?:attachment|wiki) .* (?:a13|f15|fa) --technote )[0-9a-f]+$}
+ {\1ID}
+ {^[0-9a-f]{40}( YYYY-mm-dd HH:MM:SS)}
+ {HASH\1}
+ {(\] Add attachment \[/artifact/)[0-9a-f]{16}(|)}
+ {\1HASH\2}
+ { (to tech note \[/technote/)[0-9a-f]{16}\|[0-9a-f]{10}(\] \(user:)}
+ {\1HASH1|HASH2\2}
+ {^(ambiguous tech note id: )[0-9a-f]+$}
+ {\1ID}
+ {^(Attached fa to tech note )[0-9a-f]{21}(?:[0-9a-f]{19})?\.$}
+ {\1HASH.}
+ {^(Date:) [A-Z][a-z]{2}, \d\d? [A-Z][a-z]{2} \d{4} \d\d:\d\d:\d\d [-+]\d{4}$}
+ {\1 Day, dd Mon YYYY HH:MM:SS TZ}
+ {(Content-Security-Policy.*'nonce-)[0-9a-f]{48}(';)}
+ {\1NONCE\2}
+ {^(<link rel="stylesheet" href="/style.css\?id=)[0-9a-f]+(" type="text/css">)$}
+ {\1ID\2}
+ {^(added by )[^ ]*( on)$}
+ {\1USER\2}
+ {^(<script nonce=['\"])[0-9a-f]{48}(['\"]>/\* [a-z]+\.c:)\d+}
+ {\1NONCE\2LINENO}
+ {^(<script nonce=['\"])[0-9a-f]{48}(['\"]>)$}
+ {\1NONCE\2}
+ {^(projectCode: ")[0-9a-f]{40}(",)$}
+ {\1HASH\2}
+ {^\d+\.\d+(s by)$}
+ {N.SUB\1}
+ {^(window\.fossil.version = ")\d+\.\d+ \[[0-9a-f]{10}\] (YYYY-mm-dd HH:MM:SS(?: UTC";)?)$}
+ {\1N.M [HASH] \2}
+ {^(Fossil) \d+\.\d+ \[[0-9a-f]{10}\]( YYYY-mm-dd HH:MM:SS)$}
+ {\1 N.M [HASH]\2}
+ {^(type: Wiki-edit by ).+?( on YYYY-mm-dd HH:MM:SS)$$}
+ {\1USER\2}
+ {^(size: )\d+( bytes)$}
+ {\1N\2}
+ {^U [^ ]+$}
+ {U USER}
+ {^Z [0-9a-f]{32}$}
+ {Z CHECKSUM}
+}
+
+#
+# Some pattersn are used in multiple groups
+#
+
+set testnames {"th1" "th1-docs" "th1-hooks"}
+set pat {^((?:ERROR \(1\): )?/[*]{5} Subprocess) \d+ (exit)}
+set sub {\1 PID \2}
+foreach testname $testnames {
+ dict lappend tests $testname $pat $sub
+}
+
+set testnames {"th1-docs" "th1-hooks"}
+set pat {(?:[A-Z]:)?/.*?/(test-http-(?:in|out))-\d+-\d+-\d+(\.txt)}
+set sub {/TMP/\1-PID-SEQ-SEC\2}
+foreach testname $testnames {
+ dict lappend tests $testname $pat $sub
+}
+
+set testnames {"json" "th1" "wiki"}
+set pat {^(Content-Length:) \d+$}
+set sub {\1 LENGTH}
+foreach testname $testnames {
+ dict lappend tests $testname $pat $sub
+}
+
+set testnames {"th1" "wiki"}
+set pat {^\d+\.\d+(s by)$}
+set sub {N.SUB\1}
+foreach testname $testnames {
+ dict lappend tests $testname $pat $sub
+}
+
+#
+# Main
+#
+
+if { $fname eq "-" } {
+ set fd stdin
+} else {
+ set fd [open $fname r]
+}
+
+# Platforms we detect
+set UNKOWN_PLATFORM 0
+set UNIX 1
+set WINDOWS 2
+set CYGWIN 3
+
+# One specific wiki test creates repetitive output of varying length
+set wiki_f13_cmd1 "fossil wiki create {timestamp of 2399999} f13 --technote 2399999"
+set wiki_f13_cmd2 "fossil wiki list --technote --show-technote-ids"
+set wiki_f13_cmd3 "fossil wiki export a13 --technote ID"
+set collecting_f3 0
+set collecting_f3_verbose 0
+
+# Collected lines for summaries in --extra mode
+set amend_ed_lines [list]
+set amend_ed_failed 0
+set symlinks_lines [list]
+set symlinks_failed 0
+set test_simplify_name_lines [list]
+set test_simplify_name_failed 0
+
+# State information s we progress
+set check_json_empty_line 0
+set lineno 0
+set platform $UNKOWN_PLATFORM
+set prev_line ""
+set testname ""
+
+while { [gets $fd line] >= 0 } {
+ incr lineno
+
+ if { $lineno == 1 } {
+ if { [string index $line 0] in {"\UFFEF" "\UFEFF"} } {
+ set line [string range $line 1 end]
+ }
+ }
+
+ # Remove RESULT status while matching (inserted again in output).
+ # If collecting lines of output, include $result_prefix as needed.
+ regexp {^(RESULT \([01]\): )?(.*)} $line match result_prefix line
+
+ if { [regsub {^\*{5} ([^ ]+) \*{6}$} $line {\1} new_testname] } {
+ # Pick up test name for special handling below
+ set testname "$new_testname"
+ } elseif { [regexp {^\*{5} End of } $line] } {
+ # Test done. Handle --extra before resetting.
+ if { $EXTRA } {
+ if { $testname eq "symlinks" } {
+ if { $symlinks_failed } {
+ foreach l $symlinks_lines {
+ puts "$l"
+ }
+ } else {
+ puts "All symlinks tests OK (not run on Windows)"
+ }
+ }
+ regsub {(: )\d+( errors so far)} $line {\1N\2} line
+ }
+ set testname ""
+ } elseif { $testname ne "" } {
+ if { $platform == $UNKOWN_PLATFORM } {
+ if { [regexp {^[A-Z]:/.*?/fossil\.exe } $line] } {
+ set platform $WINDOWS
+ } elseif { [regexp {^/.*?/fossil\.exe } $line] } {
+ # No drive, but still .exe - must be CYGWIN
+ set platform $CYGWIN
+ } elseif { [regexp {^/.*?/fossil } $line] } {
+ set platform $UNIX
+ }
+ }
+
+ # Do common and per testname rewrites
+ set line [common_rewrites $line $testname]
+ if { [dict exists $tests $testname] } {
+ foreach {pat sub} [dict get $tests $testname] {
+ regsub $pat $line $sub line
+ }
+ }
+
+ # On Windows, HTTP headers may get printed with an extra newline
+ if { $testname eq "json" } {
+ if { $check_json_empty_line == 1 } {
+ if { "$result_prefix$line" eq "" } {
+ set check_json_empty_line 2
+ continue
+ }
+ set check_json_empty_line 0
+ } elseif { [regexp {^(?:$|GET |POST |[A-Z][A-Za-z]*(?:-[A-Z][A-Za-z]*)*: )} $line] } {
+ set check_json_empty_line 1
+ } else {
+ if { $check_json_empty_line == 2 } {
+ # The empty line we skipped was meant to be followed by a new
+ # HTTP header or empty line, but it was not.
+ puts ""
+ }
+ set check_json_empty_line 0
+ }
+ }
+
+ # Summarise repetitive output of varying length for f13 in wiki test
+ if { $testname eq "wiki" } {
+ if { $collecting_f3 == 2 } {
+ if { $collecting_f3_verbose == 1 && [regexp {^HASH } $line] } {
+ incr collecting_f3_verbose
+ } elseif { $line eq $wiki_f13_cmd3 } {
+ incr collecting_f3
+ puts "\[...\]"
+ } else {
+ continue
+ }
+ } elseif { $collecting_f3 == 1 } {
+ if { $line eq $wiki_f13_cmd2 } {
+ incr collecting_f3
+ } elseif { $collecting_f3_verbose == 0 } {
+ incr collecting_f3_verbose
+ }
+ } elseif { $line eq $wiki_f13_cmd1 } {
+ incr collecting_f3
+ }
+ }
+
+ if { $EXTRA } {
+ if { $line eq "ERROR (0): " && $platform == $WINDOWS } {
+ if { [string match "fossil http --in *" $prev_line] } {
+ continue
+ }
+ }
+ if { $testname eq "amend" } {
+ # The amend-comment-5.N tests are not run on Windows
+ if { $line eq "fossil amend {} -close" } {
+ if { $amend_ed_failed } {
+ foreach l $amend_ed_lines {
+ puts "$l"
+ }
+ } else {
+ puts "All amend tests based on ed -s OK (not run on Windows)"
+ }
+ set amend_ed_lines [list]
+ } elseif { [llength $amend_ed_lines] } {
+ if { [regexp {^test amend-comment-5\.\d+ (.*)} $line match status] } {
+ lappend amend_ed_lines "$result_prefix$line"
+ if { $status ne "OK" } {
+ incr amend_ed_failed
+ }
+ continue
+ } elseif { [string range $line 0 4] eq "test " } {
+ # Handle change in tests by simply emitting what we got
+ foreach l $amend_ed_lines {
+ puts "$l"
+ }
+ set amend_ed_lines [list]
+ } else {
+ lappend amend_ed_lines "$result_prefix$line"
+ continue
+ }
+ } elseif { $line eq "fossil settings editor {ed -s}" } {
+ lappend amend_ed_lines "$result_prefix$line"
+ continue
+ }
+ } elseif { $testname eq "cmdline" } {
+ if { [regexp {^(fossil test-echo) (.*)} $line match test args] } {
+ if { ($platform == $UNIX && $args in {"*" "*.*"})
+ || ($platform == $WINDOWS && $args eq "--args /TMP/fossil-cmd-line-101.txt")
+ || ($platform == $CYGWIN && $args in {"*" "*.*"}) } {
+ set line "$test ARG_FOR_PLATFORM"
+ }
+ }
+ } elseif { $testname eq "commit-warning" } {
+ if { [regexp {^(micro-smile|pale facepalm) .*} $line match desc] } {
+ set line "$desc PLATFORM_SPECIFIC_BYTES"
+ }
+ } elseif { $testname eq "file1" } {
+ # test-simplify-name with question marks is specific to Windows
+ # They all immediately preceed "fossil test-relative-name --chdir . ."
+ if { $line eq "fossil test-relative-name --chdir . ." } {
+ if { $test_simplify_name_failed } {
+ foreach l $test_simplify_name_lines {
+ puts "$l"
+ }
+ } else {
+ puts "ALL Windows specific test-relative-name tests OK (if on Windows)"
+ }
+ set test_simplify_name_lines [list]
+ } elseif { [regexp {^fossil test-simplify-name .*([/\\])\?\1} $line] } {
+ lappend test_simplify_name_lines $line
+ continue
+ } elseif { [llength $test_simplify_name_lines] } {
+ if { [regexp {^test simplify-name-\d+ (.*)} $line match status] } {
+ if { $status ne "OK" } {
+ incr test_simplify_name_failed
+ }
+ }
+ lappend test_simplify_name_lines "$result_prefix$line"
+ continue
+ }
+ } elseif { $testname eq "settings-repo" } {
+ if { [regexp {^fossil test-th-eval (?:--open-config )?\{setting case-sensitive\}$} $prev_line] } {
+ if { ($platform == $UNIX && $line eq "on")
+ || ($platform == $WINDOWS && $line eq "off")
+ || ($platform == $CYGWIN && $line eq "off")
+ } {
+ set line "EXPECTED_FOR_PLATFORM"
+ }
+ }
+ } elseif { $testname eq "symlinks" } {
+ # Collect all lines and post-process at the end
+ lappend symlinks_lines "$result_prefix$line"
+ if { [regexp {^test symlinks-[^ ]* (.*)} $line match status] } {
+ if { $status ne "OK" } {
+ #TODO: incr symlinks_failed
+ }
+ }
+ continue
+ } elseif { $testname in {"th1" "th1-docs" "th1-hooks"} } {
+ # Special case that spans a couple of tests
+ # "Subprocess PID exit(0)" is sent on stderr on Unix. On Windows, there is no output
+ if { [regexp {^(ERROR \(1\): )?/\*{5} Subprocess PID exit\(0\) \*{5}/$} $line match prefix] } {
+ if { $prefix eq "" } {
+ continue
+ } elseif { $prefix eq "ERROR (1): " } {
+ set line "RESULT (0): "
+ }
+ } elseif { $testname eq "th1" } {
+ if { [regexp {^fossil test-th-eval --vfs ([^ ]+) \{globalState vfs\}$} $line match vfs] } {
+ if { ($platform == $UNIX && $vfs == "unix-dotfile")
+ || ($platform == $WINDOWS && $vfs == "win32-longpath")
+ || ($platform == $CYGWIN && $vfs == "win32-longpath") } {
+ regsub $vfs $line {EXEPECTED_VFS} line
+ }
+ } elseif { $prev_line eq "fossil test-th-eval --vfs EXEPECTED_VFS {globalState vfs}" } {
+ # Replace $vfs from previous line
+ regsub "^$vfs\$" $line {EXEPECTED_VFS} line
+ } elseif { $prev_line eq "fossil test-th-eval {set tcl_platform(platform)}" } {
+ if { $platform == $UNIX } {
+ regsub {^unix$} $line {EXPECTED_PLATFORM} line
+ } elseif { $platform == $WINDOWS } {
+ regsub {^windows$} $line {EXPECTED_PLATFORM} line
+ } elseif { $platform == $CYGWIN } {
+ regsub {^unix$} $line {EXPECTED_PLATFORM} line
+ }
+ } elseif { [string match "fossil test-th-eval --th-trace *" $prev_line] } {
+ if { ($result_prefix eq "RESULT (1): " && $line eq "")
+ || ($result_prefix eq "" && $line eq "ERROR (0): ") } {
+ set result_prefix ""
+ set line "RESULT (0): / ERROR (1): "
+ }
+ }
+ } elseif { $testname eq "th1-docs" } {
+ # In th1-docs, the fossil check-out is exposed in various states.
+ regsub {(^project-code:) CE59BB9F186226D80E49D1FA2DB29F935CCA0333} $line {\1 HASH} line
+ if { [regexp {^merged-from: HASH YYYY-mm-dd HH:MM:SS UTC$} $line] } {
+ continue
+ }
+ }
+ }
+ }
+ } elseif { $EXTRA } {
+ # Fix up summaries to be generic and easy to diff(1)
+ if { [regsub {(^\*{5} (Final|Ignored) results: )\d+} $line {\1N} line] } {
+ regsub {\d+} $line {N} line
+ } elseif { [regexp {^(\*{5} (?:Considered failure|Ignored failure|Skipped test))s: (.*)} $line match desc vals] } {
+ if { $vals ne ""} {
+ foreach val [split $vals " "] {
+ puts "$desc: $val"
+ }
+ continue
+ }
+ }
+ }
+
+ # Not exactly correct if we continue'd, but OK for the purpose
+ set prev_line "$result_prefix$line"
+ puts "$prev_line"
+}