Fossil SCM
More thorough test output rewrite script. Add an -extra option that cleans up further to make comparisons between e.g. Windows and Unix like systems easier. When testing with -verbose, this gives easy comparable results across Unix like and Windows systems.
Commit
0424384328fe54e04140f3ed9f3441e6a55375fc838ef737297a1855e3a2a4ac
Parent
b3f89945a51be60…
1 file changed
+602
-85
+602
-85
| --- test/rewrite-test-output.tcl | ||
| +++ test/rewrite-test-output.tcl | ||
| @@ -1,103 +1,620 @@ | ||
| 1 | 1 | #!/usr/bin/env tclsh |
| 2 | 2 | |
| 3 | 3 | # Script to anonymise test results for comparison. |
| 4 | 4 | # - Replaces hashes, pids and similar with fixed strings |
| 5 | 5 | # - Rewrites temporary paths to standardise them in output |
| 6 | + | |
| 7 | +# Pick up options | |
| 8 | +set EXTRA 0 | |
| 9 | +set i [lsearch $argv -extra] | |
| 10 | +while { $i >= 0 } { | |
| 11 | + incr EXTRA | |
| 12 | + set argv [lreplace $argv $i $i] | |
| 13 | + set i [lsearch $argv -extra] | |
| 14 | +} | |
| 6 | 15 | |
| 7 | 16 | # With no arguments or "-", use stdin. |
| 8 | 17 | set fname "-" |
| 9 | -if { $argc > 0 } { | |
| 18 | +if { [llength $argv] > 0 } { | |
| 10 | 19 | set fname [lindex $argv 0] |
| 11 | 20 | } |
| 12 | 21 | |
| 13 | 22 | # Any -options, or an empty first argument, is an error. |
| 14 | -if { $argc > 1 || [regexp {^-.+} $fname] } { | |
| 15 | - puts stderr "usage: [file tail $argv0] ?FILE" | |
| 23 | +if { [llength $argv] > 1 || [regexp {^-.+} $fname] } { | |
| 24 | + puts stderr "Error: argument error" | |
| 25 | + puts stderr "usage: \[-extra\] [file tail $argv0] ?FILE" | |
| 16 | 26 | puts stderr " Rewrite test output to ease comparison of outputs." |
| 27 | + puts stderr " With -extra, more output is rewritten as is summaries" | |
| 28 | + puts stderr " to make diff(1) mor euseful across runs and platforms." | |
| 17 | 29 | exit 1 |
| 18 | 30 | } elseif { $fname ne "-" && ! [file exists $fname] } { |
| 19 | 31 | puts stderr "File does not exist: '$fname'" |
| 20 | 32 | exit 1 |
| 21 | -} else { | |
| 22 | - if { $fname eq "-" } { | |
| 23 | - set fd stdin | |
| 24 | - } else { | |
| 25 | - set fd [open $fname r] | |
| 26 | - } | |
| 27 | - | |
| 28 | - set first_f13_line "fossil wiki create {timestamp of 2399999} f13 --technote 2399999" | |
| 29 | - set collecting_f3 0 | |
| 30 | - | |
| 31 | - set testname "" | |
| 32 | - while { [gets $fd line] >= 0 } { | |
| 33 | - if { [regsub {^\*{5} ([^ ]+) \*{6}$} $line {\1} new_testname] } { | |
| 34 | - # Pick up test naeme for special handling below | |
| 35 | - set testname "$new_testname" | |
| 36 | - } elseif { [regexp {^\*{5} End of } $line] } { | |
| 37 | - # Test done | |
| 38 | - set testname "" | |
| 39 | - } elseif { [regsub {^/.*?/(fossil )} $line {\1} line] } { | |
| 40 | - # Handle all fossil commands in one place | |
| 41 | - | |
| 42 | - # We get varying amounts of lines for wiki "f13" | |
| 43 | - if { $collecting_f3 > 2 } { | |
| 44 | - # Already collected | |
| 45 | - } elseif { $collecting_f3 > 0 } { | |
| 46 | - if { $collecting_f3 == 1 } { | |
| 47 | - # Print a continuation line here. | |
| 48 | - # The line is printed, but works as end line then. | |
| 49 | - puts "\[...\]" | |
| 50 | - } elseif [regexp {^fossil wiki (?:create .* f13|list --technote --show-technote-ids)} $line] { | |
| 51 | - continue | |
| 52 | - } | |
| 53 | - incr collecting_f3 | |
| 54 | - } elseif { $first_f13_line eq $line } { | |
| 55 | - incr collecting_f3 | |
| 56 | - } | |
| 57 | - | |
| 58 | - # Hashes | |
| 59 | - regsub {^(fossil .*) [0-9a-f]{40}($| )} $line {\1 HASH\2} line | |
| 60 | - regsub {^(fossil artifact) [0-9a-f]{64}} $line {\1 HASH} line | |
| 61 | - regsub {^(fossil artifact) [0-9a-f]{10}} $line {\1 HASH} line | |
| 62 | - regsub {^(fossil (?:attachment|wiki) .*--technote )[0-9a-f]{21}$} $line {\1HASH} line | |
| 63 | - regsub {^(fossil json artifact) [0-9a-f]{64}} $line {\1 HASH} line | |
| 64 | - regsub {^(fossil json wiki diff) [0-9a-f]{64} [0-9a-f]{64}} $line {\1 HASH1 HASH2} line | |
| 65 | - | |
| 66 | - # PIDs, Sequence numbers and seconds | |
| 67 | - regsub {^(fossil test-th-source .*/th1-)\d+([.]th1)$} $line {\1PID\2} line | |
| 68 | - if { [regexp {^fossil http --in } $line] } { | |
| 69 | - regsub -all {/(test-http-(?:in|out))-\d+-\d+-\d+(\.txt)} $line {/\1-PID-SEQ-SEC\2} line | |
| 70 | - } | |
| 71 | - | |
| 72 | - # Tech notes ids | |
| 73 | - regsub {^(fossil (?:attachment|wiki) .* (?:a13|f15|fa) --technote )[0-9a-f]+$} $line {\1ID} line | |
| 74 | - | |
| 75 | - # Special technote timestamp (mostly they are fixed) | |
| 76 | - regsub {^(fossil attachment add f11 --technote) [{]\d{4}-\d\d-\d\d \d\d:\d\d:\d\d[}]} $line {\1 {YYYY-mm-dd HH:MM:SS}} line | |
| 77 | - | |
| 78 | - # Unversioned test has passowrds and ports | |
| 79 | - regsub {^(fossil user new uvtester.*) \d+$} $line {\1 PASSWORD} line | |
| 80 | - regsub {^(fossil .*http://uvtester:)\d+(@localhost:)\d+} $line {\1PASSWORD\2PORT} line | |
| 81 | - } elseif { $testname eq "json" } { | |
| 82 | - regsub {^(Content-Length) \d+$} $line {\1 LENGTH} line | |
| 83 | - regsub {^( \"authToken\":\")[0-9a-f]{40}/\d+\.\d+/(anonymous\")$} $line {\1SHA1/NOW/\2} line | |
| 84 | - regsub {^(Cookie: fossil-)[0-9a-f]{16}\=[0-9a-f]{40}%2F\d+\.\d+%2F(anonymous)$} $line {\1CODE=SHA1%2FNOW%2F\2} line | |
| 85 | - regsub {^(GET /json/cap\?authToken\=)[0-9a-f]{40}/\d+\.\d+/(anonymous )} $line {\1SHA1/NOW/\2} line | |
| 86 | - regsub {^(Cookie: fossil-)[0-9a-f]{16}\=[0-9A-F]{50}%2F[0-9a-f]{16}%2F(.*)$} $line {\1CODE=SHA1%2FCODE%2F\2} line | |
| 87 | - } elseif { $testname eq "merge_renames" } { | |
| 88 | - regsub {^( (?:MERGED_WITH|BACKOUT)) [0-9a-f]{64}$} $line {\1 HASH} line | |
| 89 | - } elseif { $testname eq "unversioned" } { | |
| 90 | - regsub {^(Started Fossil server, pid \")\d+(\", port \")\d+} $line {\1PID\2PORT} line | |
| 91 | - regsub {^(Now in client directory \")/.*?/uvtest_\d+_\d+\"} $line {\1/TMP/uvtest_SEC_SEQ} line | |
| 92 | - regsub {^(Stopped Fossil server, pid \")\d+(\", using argument \")\d+} $line {\1PID\2PID} line | |
| 93 | - } | |
| 94 | - | |
| 95 | - # Some common lines not tied to fossil or specific tests. | |
| 96 | - regsub {^((?:ERROR \(1\): )?/[*]{5} Subprocess) \d+ (exit)} $line {\1 PID \2} line | |
| 97 | - | |
| 98 | - # Temporary directories | |
| 99 | - regsub -all {/.*?/repo_\d+/\d+_\d+} $line {/TMP/repo_PID/SEC_SEQ} line | |
| 100 | - | |
| 101 | - puts "$line" | |
| 102 | - } | |
| 33 | +} | |
| 34 | + | |
| 35 | +proc common_rewrites { line testname } { | |
| 36 | + # Normalise the fossil commands with path as just fossil | |
| 37 | + regsub {^(?:[A-Z]:)?/.*?/fossil(?:\.exe)? } $line {fossil } line | |
| 38 | + | |
| 39 | + # Accept 40 and 64 byte hashes as such | |
| 40 | + regsub -all {[[:<:]][0-9a-f]{40}[[:>:]]} $line HASH line | |
| 41 | + regsub -all {[[:<:]][0-9a-f]{64}[[:>:]]} $line HASH line | |
| 42 | + | |
| 43 | + # Date and time | |
| 44 | + regsub -all {[[:<:]]\d{4}-\d\d-\d\d \d\d:\d\d:\d\d[[:>:]]} $line {YYYY-mm-dd HH:MM:SS} line | |
| 45 | + if { [lsearch -exact {"amend" "wiki"} $testname] >= 0 } { | |
| 46 | + # With embedded T and milliseconds | |
| 47 | + regsub { \d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}$} $line { YYYY-mm-ddTHH:MM:SS.NNN} line | |
| 48 | + } | |
| 49 | + if { [lsearch -exact {"amend" "th1-hooks" "wiki"} $testname] >= 0 } { | |
| 50 | + regsub {[[:<:]]\d{4}-\d\d-\d\d[[:>:]]} $line {YYYY-mm-dd} line | |
| 51 | + } | |
| 52 | + | |
| 53 | + # Timelines have HH:MM:SS [HASH], but don't mess with the zero'ed version. | |
| 54 | + regsub {^(?!00:00:00 \[0000000000\])\d\d:\d\d:\d\d \[[0-9a-f]{10}\] } $line {HH:MM:SS [HASH] } line | |
| 55 | + | |
| 56 | + # Temporary directories | |
| 57 | + regsub -all {(?:[A-Z]:)?/.*?/repo_\d+/\d+_\d+} $line {/TMP/repo_PID/SEC_SEQ} line | |
| 58 | + # Home directories only seem present with .fossil or _fossil. Simplify to .fossil. | |
| 59 | + regsub -all {(?:[A-Z]:)?/.*?/home_\d+/[._]fossil[[:>:]]} $line {/TMP/home_PID/.fossil} line | |
| 60 | + | |
| 61 | + # Users in output | |
| 62 | + regsub { (\(user: )[^\)]*\)$} $line { \1USER)} line | |
| 63 | + | |
| 64 | + return $line | |
| 65 | +} | |
| 66 | + | |
| 67 | +# | |
| 68 | +# tests/tests_unix/tests_windows contain tuples of | |
| 69 | +# | |
| 70 | +# 1. A regular expression to match current line | |
| 71 | +# 2. A substitution for the current line | |
| 72 | +# | |
| 73 | +# Some common patterns applicable to multiples tests are appended below. | |
| 74 | +# | |
| 75 | +# The common_rewrites procedure is run first, so use e.g. HASH as needed. | |
| 76 | +# | |
| 77 | + | |
| 78 | +dict set tests "amend" { | |
| 79 | + {^(fossil artifact) [0-9a-f]{10}} | |
| 80 | + {\1 HASH} | |
| 81 | + {^U [^ ]+$} | |
| 82 | + {U USER} | |
| 83 | + {^Z [0-9a-f]{32}$} | |
| 84 | + {Z CHECKSUM} | |
| 85 | + {^(ed -s \./ci-comment-).*?(\.txt)$} | |
| 86 | + {\1UNIQ\2} | |
| 87 | + {^(fossil amend HASH -date \{?)\d\d/\d\d/\d{4}} | |
| 88 | + {\1dd/mm/YYYY} | |
| 89 | + {^(fossil amend HASH -date \{.* )\d{4}(\})$} | |
| 90 | + {\1YYYY\2} | |
| 91 | + {^(fossil amend HASH -date \{.* )\d\d:} | |
| 92 | + {\1HH:} | |
| 93 | + {^(fossil amend HASH -date \{)[A-Z][a-z]{2} [A-Z][a-z]{2} [ 0-9]\d } | |
| 94 | + {\1Day Mon dd } | |
| 95 | + {(\] Edit \[)[0-9a-f]{16}.[0-9a-f]{10}(\]: )} | |
| 96 | + {\1HASH1|HASH2\2} | |
| 97 | + {(\] Edit \[.*?&dp=)[0-9a-f]{16}} | |
| 98 | + {\1dp=HASH} | |
| 99 | +} | |
| 100 | + | |
| 101 | +dict set tests "cmdline" { | |
| 102 | + {^(fossil test-echo --args) .*/} | |
| 103 | + {\1 /TMP/} | |
| 104 | + {^(g\.nameOfExe =) \[[^\]]+[/\\]fossil(?:\.exe)?\]$} | |
| 105 | + {\1 [/PATH/FOSSILCMD]} | |
| 106 | + {^(argv\[0\] =) \[[^\]]+[/\\]fossil(?:\.exe)?\]$} | |
| 107 | + {\1 [/PATH/FOSSILCMD]} | |
| 108 | +} | |
| 109 | + | |
| 110 | +dict set tests "contains-selector" { | |
| 111 | + {^(fossil test-contains-selector) .*?/(compare-selector.css )} | |
| 112 | + {\1 /TMP/\2} | |
| 113 | +} | |
| 114 | + | |
| 115 | +dict set tests "json" { | |
| 116 | + {^(Content-Length) \d+$} | |
| 117 | + {\1 LENGTH} | |
| 118 | + {^(Cookie: fossil-)[0-9a-f]{16}(\=HASH%2F)\d+\.\d+(%2Fanonymous)$} | |
| 119 | + {\1CODE\2NOW\3} | |
| 120 | + {^(GET /json/cap\?authToken\=HASH)/\d+\.\d+/(anonymous )} | |
| 121 | + {\1/NOW/\2} | |
| 122 | + {^(Cookie: fossil-)[0-9a-f]{16}\=[0-9A-F]{50}%2F[0-9a-f]{16}%2F(.*)$} | |
| 123 | + {\1CODE=SHA1%2FCODE%2F\2} | |
| 124 | + {("authToken":").+?(")} | |
| 125 | + {\1AUTHTOKEN\2} | |
| 126 | + {("averageArtifactSize":)\d+()} | |
| 127 | + {\1SIZE\2} | |
| 128 | + {("compiler":").+?(")} | |
| 129 | + {\1COMPILER\2} | |
| 130 | + {("loginCookieName":").+?(")} | |
| 131 | + {\1COOKIE\2} | |
| 132 | + {("manifestVersion":"\[)[0-9a-f]{10}(\]")} | |
| 133 | + {\1HASH\2} | |
| 134 | + {("manifestYear":")\d{4}(")} | |
| 135 | + {\1YYYY\2} | |
| 136 | + {("name":").+?(")} | |
| 137 | + {\1NAME\2} | |
| 138 | + {("password":")[0-9a-f]+(")} | |
| 139 | + {\1PASSWORD\2} | |
| 140 | + {("projectCode":")[0-9a-f]{40}(")} | |
| 141 | + {\1HASH\2} | |
| 142 | + {("procTimeMs":)\d+} | |
| 143 | + {\1MSEC} | |
| 144 | + {("procTimeUs":)\d+} | |
| 145 | + {\1USEC} | |
| 146 | + {("releaseVersion":")\d+\.\d+(")} | |
| 147 | + {\1VERSION\2} | |
| 148 | + {("releaseVersionNumber":")\d+(")} | |
| 149 | + {\1VERSION_NUMBER\2} | |
| 150 | + {("timestamp":)\d+} | |
| 151 | + {\1SEC} | |
| 152 | + {("seed":)\d+()} | |
| 153 | + {\1SEED\2} | |
| 154 | + {("uid":)\d+()} | |
| 155 | + {\1UID\2} | |
| 156 | + {("uncompressedArtifactSize":)\d+()} | |
| 157 | + {\1SIZE\2} | |
| 158 | + {("user":").+?(")} | |
| 159 | + {\1USER\2} | |
| 160 | + {^(Date:) [A-Z][a-z]{2}, \d\d? [A-Z][a-z]{2} \d{4} \d\d:\d\d:\d\d [-+]\d{4}$} | |
| 161 | + {\1 Day, dd Mon YYYY HH:MM:SS TZ} | |
| 162 | +} | |
| 163 | + | |
| 164 | +dict set tests "merge_renames" { | |
| 165 | + {^(size: {7})\d+( bytes)$} | |
| 166 | + {\1N\2} | |
| 167 | + {^(type: {7}Check-in by ).+?( on YYYY-mm-dd HH:MM:SS)$} | |
| 168 | + {\1USER\2} | |
| 169 | +} | |
| 170 | + | |
| 171 | +dict set tests "set-manifest" { | |
| 172 | + {^(project-code: )[0-9a-f]{40}$} | |
| 173 | + {\1HASH} line | |
| 174 | +} | |
| 175 | + | |
| 176 | +dict set tests "stash" { | |
| 177 | + {^(---|\+\+\+) NUL$} | |
| 178 | + {\1 /dev/null} | |
| 179 | + {(^ 1: \[)[0-9a-f]{14}(\] on YYYY-mm-dd HH:MM:SS)$} | |
| 180 | + {\1HASH\2} | |
| 181 | + {(^ 1: \[)[0-9a-f]{14}(\] from YYYY-mm-dd HH:MM:SS)$} | |
| 182 | + {\1HASH\2} | |
| 183 | +} | |
| 184 | + | |
| 185 | +dict set tests "th1" { | |
| 186 | + {^(fossil test-th-source) (?:[A-Z]:)?.*?/(th1-)\d+([.]th1)$} | |
| 187 | + {\1 /TMP/\2PID\3} | |
| 188 | + {^(?:[A-Z]:)?[/\\].*?[/\\]fossil(?:\.exe)?$} | |
| 189 | + {/PATH/FOSSILCMD} | |
| 190 | + {[[:<:]](Content-Security-Policy[[:>:]].*'nonce-)[0-9a-f]{48}(';)} | |
| 191 | + {\1NONCE\2} | |
| 192 | + {^(<link rel="stylesheet" href="/style.css\?id=)[0-9a-f]+(" type="text/css">)$} | |
| 193 | + {\1ID\2} | |
| 194 | + {^\d+\.\d{3}(s by)$} | |
| 195 | + {N.MMM\1} | |
| 196 | + {^(Fossil) \d+\.\d+ \[[0-9a-f]{10}\] (YYYY-mm-dd HH:MM:SS)$} | |
| 197 | + {\1 N.M [HASH] \2} | |
| 198 | + {^(<script nonce=")[0-9a-f]{48}(">/\* style\.c:)\d+} | |
| 199 | + {\1NONCE\2LINENO} | |
| 200 | +} | |
| 201 | + | |
| 202 | +dict set tests "th1-docs" { | |
| 203 | + {^(check-ins: ).*} | |
| 204 | + {\1COUNT} | |
| 205 | + {^(local-root: ).*} | |
| 206 | + {\1/PATH/} | |
| 207 | + {^(repository: ).*} | |
| 208 | + {\1/PATH/REPO} | |
| 209 | + {^(comment: ).*} | |
| 210 | + {\1/COMMENT/} | |
| 211 | + {^(tags: ).*} | |
| 212 | + {\1/TAGS/} | |
| 213 | + {(--ipaddr 127\.0\.0\.1) .*? (--localauth)} | |
| 214 | + {\1 REPO \2} | |
| 215 | +} | |
| 216 | + | |
| 217 | +dict set tests "th1-hooks" { | |
| 218 | + {^(?:/[^:]*/fossil|[A-Z]:\\[^:]*\\fossil\.exe): (unknown command:|use \"help\")} | |
| 219 | + {fossil: \1} | |
| 220 | + {^(project-code: )[0-9a-f]{40}$} | |
| 221 | + {\1HASH} | |
| 222 | +} | |
| 223 | + | |
| 224 | +dict set tests "th1-tcl" { | |
| 225 | + {^(fossil test-th-render --open-config) \{?.*?[/\\]test[/\\]([^/\\]*?)\}?$} | |
| 226 | + {\1 /CHECKOUT/test/\2} | |
| 227 | + {^(fossil)(?:\.exe)?( 3 \{test-th-render --open-config )(?:\{[A-Z]:)?[/\\].*?[/\\]test[/\\](th1-tcl9.txt\})\}?$} | |
| 228 | + {\1\2/CHECKOUT/test/\3} | |
| 229 | + {^\d{10}$} | |
| 230 | + {SEC} | |
| 231 | +} | |
| 232 | + | |
| 233 | +dict set tests "unversioned" { | |
| 234 | + {^(fossil user new uvtester.*) \d+$} | |
| 235 | + {\1 PASSWORD} | |
| 236 | + {^(fossil .*http://uvtester:)\d+(@localhost:)\d+} | |
| 237 | + {\1PASSWORD\2PORT} | |
| 238 | + {^(Pull from http://uvtester@localhost:)\d+} | |
| 239 | + {\1PORT} | |
| 240 | + {^(ERROR \(1\): Usage:) .*?[/\\]fossil(?:\.exe)? (unversioned)} | |
| 241 | + {\1 /PATH/fossil \2} | |
| 242 | + {^(Started Fossil server, pid \")\d+(\", port \")\d+} | |
| 243 | + {\1PID\2PORT} | |
| 244 | + {^(Now in client directory \")(?:[A-Z]:)?/.*?/uvtest_\d+_\d+\"} | |
| 245 | + {\1/TMP/uvtest_SEC_SEQ} | |
| 246 | + {^(Stopped Fossil server, pid \")\d+(\", using argument \")(?:\d+|[^\"]*\.stopper)(\")} | |
| 247 | + {\1PID\2PID_OR_SCRIPT\3} | |
| 248 | + {^(This is unversioned file #4\.) \d+ \d+} | |
| 249 | + {\1 PID SEC} | |
| 250 | + {^(This is unversioned file #4\. PID SEC) \d+ \d+} | |
| 251 | + {\1 PID SEC} | |
| 252 | + {^[0-9a-f]{12}( YYYY-mm-dd HH:MM:SS *)(\d+)( *)\2( unversioned4.txt)$} | |
| 253 | + {HASH \1SZ\3SZ\4} | |
| 254 | + {^[0-9a-f]{40}$} | |
| 255 | + {\1HASH} | |
| 256 | + {^((?:Clone|Pull)? done, wire bytes sent: )\d+( received: )\d+( remote: )(?:127\.0.0\.1|::1)$} | |
| 257 | + {\1SENT\2RECV\3LOCALIP} | |
| 258 | + {^(project-id: )[0-9a-f]{40}$} | |
| 259 | + {\1HASH} | |
| 260 | + {^(server-id: )[0-9a-f]{40}$} | |
| 261 | + {\1HASH} | |
| 262 | + {^(admin-user: uvtester \(password is ").*("\))$} | |
| 263 | + {\1PASSWORD\2} | |
| 264 | + {^(repository: ).*?/uvtest_\d+_\d+/(uvrepo.fossil)$} | |
| 265 | + {\1/TMP/uvtest_SEC_SEQ/\2} | |
| 266 | + {^(local-root: ).*?/uvtest_\d+_\d+/$} | |
| 267 | + {\1/TMP/uvtest_SEC_SEQ/} | |
| 268 | + {^(project-code: )[0-9a-f]{40}$} | |
| 269 | + {\1HASH} | |
| 270 | +} | |
| 271 | + | |
| 272 | +dict set tests "utf" { | |
| 273 | + {^(fossil test-looks-like-utf) (?:[A-Z]:)?/.*?/([^/\\]*?)\}?$} | |
| 274 | + {\1 /TMP/test/\2} | |
| 275 | + {^(File ")(?:[A-Z]:)?/.*?/(utf-check-\d+-\d+-\d+-\d+.jnk" has \d+ bytes\.)$} | |
| 276 | + {\1/TMP/\2} | |
| 277 | +} | |
| 278 | + | |
| 279 | +dict set tests "wiki" { | |
| 280 | + {^(fossil (?:attachment|wiki) .*--technote )[0-9a-f]{21}$} | |
| 281 | + {\1HASH} | |
| 282 | + {^(fossil (?:attachment|wiki) .* (?:a13|f15|fa) --technote )[0-9a-f]+$} | |
| 283 | + {\1ID} | |
| 284 | + {^[0-9a-f]{40}( YYYY-mm-dd HH:MM:SS)} | |
| 285 | + {HASH\1} | |
| 286 | + {(\] Add attachment \[/artifact/)[0-9a-f]{16}(|)} | |
| 287 | + {\1HASH\2} | |
| 288 | + { (to tech note \[/technote/)[0-9a-f]{16}\|[0-9a-f]{10}(\] \(user:)} | |
| 289 | + {\1HASH1|HASH2\2} | |
| 290 | + {^(ambiguous tech note id: )[0-9a-f]+$} | |
| 291 | + {\1ID} | |
| 292 | + {^(Attached fa to tech note )[0-9a-f]{21}(?:[0-9a-f]{19})?\.$} | |
| 293 | + {\1HASH.} | |
| 294 | + {^(Date:) [A-Z][a-z]{2}, \d\d? [A-Z][a-z]{2} \d{4} \d\d:\d\d:\d\d [-+]\d{4}$} | |
| 295 | + {\1 Day, dd Mon YYYY HH:MM:SS TZ} | |
| 296 | + {(Content-Security-Policy.*'nonce-)[0-9a-f]{48}(';)} | |
| 297 | + {\1NONCE\2} | |
| 298 | + {^(<link rel="stylesheet" href="/style.css\?id=)[0-9a-f]+(" type="text/css">)$} | |
| 299 | + {\1ID\2} | |
| 300 | + {^(added by )[^ ]*( on)$} | |
| 301 | + {\1USER\2} | |
| 302 | + {^(<script nonce=['\"])[0-9a-f]{48}(['\"]>/\* [a-z]+\.c:)\d+} | |
| 303 | + {\1NONCE\2LINENO} | |
| 304 | + {^(<script nonce=['\"])[0-9a-f]{48}(['\"]>)$} | |
| 305 | + {\1NONCE\2} | |
| 306 | + {^(projectCode: ")[0-9a-f]{40}(",)$} | |
| 307 | + {\1HASH\2} | |
| 308 | + {^\d+\.\d+(s by)$} | |
| 309 | + {N.SUB\1} | |
| 310 | + {^(window\.fossil.version = ")\d+\.\d+ \[[0-9a-f]{10}\] (YYYY-mm-dd HH:MM:SS(?: UTC";)?)$} | |
| 311 | + {\1N.M [HASH] \2} | |
| 312 | + {^(Fossil) \d+\.\d+ \[[0-9a-f]{10}\]( YYYY-mm-dd HH:MM:SS)$} | |
| 313 | + {\1 N.M [HASH]\2} | |
| 314 | + {^(type: Wiki-edit by ).+?( on YYYY-mm-dd HH:MM:SS)$$} | |
| 315 | + {\1USER\2} | |
| 316 | + {^(size: )\d+( bytes)$} | |
| 317 | + {\1N\2} | |
| 318 | + {^U [^ ]+$} | |
| 319 | + {U USER} | |
| 320 | + {^Z [0-9a-f]{32}$} | |
| 321 | + {Z CHECKSUM} | |
| 322 | +} | |
| 323 | + | |
| 324 | +# | |
| 325 | +# Some pattersn are used in multiple groups | |
| 326 | +# | |
| 327 | + | |
| 328 | +set testnames {"th1" "th1-docs" "th1-hooks"} | |
| 329 | +set pat {^((?:ERROR \(1\): )?/[*]{5} Subprocess) \d+ (exit)} | |
| 330 | +set sub {\1 PID \2} | |
| 331 | +foreach testname $testnames { | |
| 332 | + dict lappend tests $testname $pat $sub | |
| 333 | +} | |
| 334 | + | |
| 335 | +set testnames {"th1-docs" "th1-hooks"} | |
| 336 | +set pat {(?:[A-Z]:)?/.*?/(test-http-(?:in|out))-\d+-\d+-\d+(\.txt)} | |
| 337 | +set sub {/TMP/\1-PID-SEQ-SEC\2} | |
| 338 | +foreach testname $testnames { | |
| 339 | + dict lappend tests $testname $pat $sub | |
| 340 | +} | |
| 341 | + | |
| 342 | +set testnames {"json" "th1" "wiki"} | |
| 343 | +set pat {^(Content-Length:) \d+$} | |
| 344 | +set sub {\1 LENGTH} | |
| 345 | +foreach testname $testnames { | |
| 346 | + dict lappend tests $testname $pat $sub | |
| 347 | +} | |
| 348 | + | |
| 349 | +set testnames {"th1" "wiki"} | |
| 350 | +set pat {^\d+\.\d+(s by)$} | |
| 351 | +set sub {N.SUB\1} | |
| 352 | +foreach testname $testnames { | |
| 353 | + dict lappend tests $testname $pat $sub | |
| 354 | +} | |
| 355 | + | |
| 356 | +# | |
| 357 | +# Main | |
| 358 | +# | |
| 359 | + | |
| 360 | +if { $fname eq "-" } { | |
| 361 | + set fd stdin | |
| 362 | +} else { | |
| 363 | + set fd [open $fname r] | |
| 364 | +} | |
| 365 | + | |
| 366 | +# Platforms we detect | |
| 367 | +set UNKOWN_PLATFORM 0 | |
| 368 | +set UNIX 1 | |
| 369 | +set WINDOWS 2 | |
| 370 | + | |
| 371 | +# One specific wiki test creates repetitive output of varying length | |
| 372 | +set wiki_f13_cmd1 "fossil wiki create {timestamp of 2399999} f13 --technote 2399999" | |
| 373 | +set wiki_f13_cmd2 "fossil wiki list --technote --show-technote-ids" | |
| 374 | +set wiki_f13_cmd3 "fossil wiki export a13 --technote ID" | |
| 375 | +set collecting_f3 0 | |
| 376 | +set collecting_f3_verbose 0 | |
| 377 | + | |
| 378 | +# Collected lines for summaries in --extra mode | |
| 379 | +set amend_ed_lines [list] | |
| 380 | +set amend_ed_failed 0 | |
| 381 | +set symlinks_lines [list] | |
| 382 | +set symlinks_failed 0 | |
| 383 | +set test_simplify_name_lines [list] | |
| 384 | +set test_simplify_name_failed 0 | |
| 385 | + | |
| 386 | +# State information s we progress | |
| 387 | +set check_json_empty_line 0 | |
| 388 | +set lineno 0 | |
| 389 | +set platform $UNKOWN_PLATFORM | |
| 390 | +set prev_line "" | |
| 391 | +set testname "" | |
| 392 | + | |
| 393 | +while { [gets $fd line] >= 0 } { | |
| 394 | + incr lineno | |
| 395 | + | |
| 396 | + if { $lineno == 1 } { | |
| 397 | + if { [string index $line 0] in {"\UFFEF" "\UFEFF"} } { | |
| 398 | + set line [string range $line 1 end] | |
| 399 | + } | |
| 400 | + } | |
| 401 | + | |
| 402 | + # Remove RESULT status while matching (inserted again in output). | |
| 403 | + # If collecting lines of output, include $result_prefix as needed. | |
| 404 | + regexp {^(RESULT \([01]\): )?(.*)} $line match result_prefix line | |
| 405 | + | |
| 406 | + if { [regsub {^\*{5} ([^ ]+) \*{6}$} $line {\1} new_testname] } { | |
| 407 | + # Pick up test name for special handling below | |
| 408 | + set testname "$new_testname" | |
| 409 | + } elseif { [regexp {^\*{5} End of } $line] } { | |
| 410 | + # Test done. Handle --extra before resetting. | |
| 411 | + if { $EXTRA } { | |
| 412 | + if { $testname eq "symlinks" } { | |
| 413 | + if { $symlinks_failed } { | |
| 414 | + foreach l $symlinks_lines { | |
| 415 | + puts "$l" | |
| 416 | + } | |
| 417 | + } else { | |
| 418 | + puts "All symlinks tests OK (not run on Windows)" | |
| 419 | + } | |
| 420 | + } | |
| 421 | + regsub {(: )\d+( errors so far)} $line {\1N\2} line | |
| 422 | + } | |
| 423 | + set testname "" | |
| 424 | + } elseif { $testname ne "" } { | |
| 425 | + if { $platform == $UNKOWN_PLATFORM } { | |
| 426 | + if { [regexp {^[A-Z]:/.*?/fossil\.exe } $line] } { | |
| 427 | + set platform $WINDOWS | |
| 428 | + } elseif { [regexp {^/.*?/fossil } $line] } { | |
| 429 | + set platform $UNIX | |
| 430 | + } | |
| 431 | + } | |
| 432 | + | |
| 433 | + # Do common and per testname rewrites | |
| 434 | + set line [common_rewrites $line $testname] | |
| 435 | + if { [dict exists $tests $testname] } { | |
| 436 | + foreach {pat sub} [dict get $tests $testname] { | |
| 437 | + regsub $pat $line $sub line | |
| 438 | + } | |
| 439 | + } | |
| 440 | + | |
| 441 | + # On Windows, HTTP headers may get printed with an extra newline | |
| 442 | + if { $testname eq "json" } { | |
| 443 | + if { $check_json_empty_line == 1 } { | |
| 444 | + if { "$result_prefix$line" eq "" } { | |
| 445 | + set check_json_empty_line 2 | |
| 446 | + continue | |
| 447 | + } | |
| 448 | + set check_json_empty_line 0 | |
| 449 | + } elseif { [regexp {^(?:$|GET |POST |[A-Z][A-Za-z]*(?:-[A-Z][A-Za-z]*)*: )} $line] } { | |
| 450 | + set check_json_empty_line 1 | |
| 451 | + } else { | |
| 452 | + if { $check_json_empty_line == 2 } { | |
| 453 | + # The empty line we skipped was meant to be followed by a new | |
| 454 | + # HTTP header or empty line, but it was not. | |
| 455 | + puts "" | |
| 456 | + } | |
| 457 | + set check_json_empty_line 0 | |
| 458 | + } | |
| 459 | + } | |
| 460 | + | |
| 461 | + # Summarise repetitive output of varying length for f13 in wiki test | |
| 462 | + if { $testname eq "wiki" } { | |
| 463 | + if { $collecting_f3 == 2 } { | |
| 464 | + if { $collecting_f3_verbose == 1 && [regexp {^HASH } $line] } { | |
| 465 | + incr collecting_f3_verbose | |
| 466 | + } elseif { $line eq $wiki_f13_cmd3 } { | |
| 467 | + incr collecting_f3 | |
| 468 | + puts "\[...\]" | |
| 469 | + } else { | |
| 470 | + continue | |
| 471 | + } | |
| 472 | + } elseif { $collecting_f3 == 1 } { | |
| 473 | + if { $line eq $wiki_f13_cmd2 } { | |
| 474 | + incr collecting_f3 | |
| 475 | + } elseif { $collecting_f3_verbose == 0 } { | |
| 476 | + incr collecting_f3_verbose | |
| 477 | + } | |
| 478 | + } elseif { $line eq $wiki_f13_cmd1 } { | |
| 479 | + incr collecting_f3 | |
| 480 | + } | |
| 481 | + } | |
| 482 | + | |
| 483 | + if { $EXTRA } { | |
| 484 | + if { $testname eq "amend" } { | |
| 485 | + # The amend-comment-5.N tests are not run on Windows | |
| 486 | + if { $line eq "fossil amend {} -close" } { | |
| 487 | + if { $amend_ed_failed } { | |
| 488 | + foreach l $amend_ed_lines { | |
| 489 | + puts "$l" | |
| 490 | + } | |
| 491 | + } else { | |
| 492 | + puts "All amend tests based on ed -s OK (not run on Windows)" | |
| 493 | + } | |
| 494 | + set amend_ed_lines [list] | |
| 495 | + } elseif { [llength $amend_ed_lines] } { | |
| 496 | + if { [regexp {^test amend-comment-5\.\d+ (.*)} $line match status] } { | |
| 497 | + lappend amend_ed_lines "$result_prefix$line" | |
| 498 | + if { $status ne "OK" } { | |
| 499 | + incr amend_ed_failed | |
| 500 | + } | |
| 501 | + continue | |
| 502 | + } elseif { [string range $line 0 4] eq "test " } { | |
| 503 | + # Handle change in tests by simply emitting what we got | |
| 504 | + foreach l $amend_ed_lines { | |
| 505 | + puts "$l" | |
| 506 | + } | |
| 507 | + set amend_ed_lines [list] | |
| 508 | + } else { | |
| 509 | + lappend amend_ed_lines "$result_prefix$line" | |
| 510 | + continue | |
| 511 | + } | |
| 512 | + } elseif { $line eq "fossil settings editor {ed -s}" } { | |
| 513 | + lappend amend_ed_lines "$result_prefix$line" | |
| 514 | + continue | |
| 515 | + } | |
| 516 | + } elseif { $testname eq "cmdline" } { | |
| 517 | + if { [regexp {^(fossil test-echo) (.*)} $line match test args] } { | |
| 518 | + if { ($platform == $UNIX && $args in {"*" "*.*"}) | |
| 519 | + || ($platform == $WINDOWS && $args eq "--args /TMP/fossil-cmd-line-101.txt") } { | |
| 520 | + set line "$test ARG_FOR_PLATFORM" | |
| 521 | + } | |
| 522 | + } | |
| 523 | + } elseif { $testname eq "commit-warning" } { | |
| 524 | + if { [regexp {^(micro-smile|pale facepalm) .*} $line match desc] } { | |
| 525 | + set line "$desc PLATFORM_SPECIFIC_BYTES" | |
| 526 | + } | |
| 527 | + } elseif { $testname eq "file1" } { | |
| 528 | + # test-simplify-name with question marks is specific to Windows | |
| 529 | + # They all immediately preceed "fossil test-relative-name --chdir . ." | |
| 530 | + if { $line eq "fossil test-relative-name --chdir . ." } { | |
| 531 | + if { $test_simplify_name_failed } { | |
| 532 | + foreach l $test_simplify_name_lines { | |
| 533 | + puts "$l" | |
| 534 | + } | |
| 535 | + } else { | |
| 536 | + puts "ALL Windows specific test-relative-name tests OK (if on Windows)" | |
| 537 | + } | |
| 538 | + set test_simplify_name_lines [list] | |
| 539 | + } elseif { [regexp {^fossil test-simplify-name .*([/\\])\?\1} $line] } { | |
| 540 | + lappend test_simplify_name_lines $line | |
| 541 | + continue | |
| 542 | + } elseif { [llength $test_simplify_name_lines] } { | |
| 543 | + if { [regexp {^test simplify-name-\d+ (.*)} $line match status] } { | |
| 544 | + if { $status ne "OK" } { | |
| 545 | + incr test_simplify_name_failed | |
| 546 | + } | |
| 547 | + } | |
| 548 | + lappend test_simplify_name_lines "$result_prefix$line" | |
| 549 | + continue | |
| 550 | + } | |
| 551 | + } elseif { $testname eq "settings-repo" } { | |
| 552 | + if { [regexp {^fossil test-th-eval (?:--open-config )?\{setting case-sensitive\}$} $prev_line] } { | |
| 553 | + if { ($platform == $UNIX && $line eq "on") || ($platform == $WINDOWS && $line eq "off") } { | |
| 554 | + set line "EXPECTED_FOR_PLATFORM" | |
| 555 | + } | |
| 556 | + } | |
| 557 | + } elseif { $testname eq "symlinks" } { | |
| 558 | + # Collect all lines and post-process at the end | |
| 559 | + lappend symlinks_lines "$result_prefix$line" | |
| 560 | + if { [regexp {^test symlinks-[^ ]* (.*)} $line match status] } { | |
| 561 | + if { $status ne "OK" } { | |
| 562 | + #TODO: incr symlinks_failed | |
| 563 | + } | |
| 564 | + } | |
| 565 | + continue | |
| 566 | + } elseif { $testname in {"th1" "th1-docs" "th1-hooks"} } { | |
| 567 | + # Special case that spans a couple of tests | |
| 568 | + # "Subprocess PID exit(0)" is sent on stderr on Unix. On Windows, there is no output | |
| 569 | + if { [regexp {^(ERROR \(1\): )?/\*{5} Subprocess PID exit\(0\) \*{5}/$} $line match prefix] } { | |
| 570 | + if { $prefix eq "" } { | |
| 571 | + continue | |
| 572 | + } elseif { $prefix eq "ERROR (1): " } { | |
| 573 | + set line "RESULT (0): " | |
| 574 | + } | |
| 575 | + } elseif { $testname eq "th1" } { | |
| 576 | + if { [regexp {^fossil test-th-eval --vfs ([^ ]+) \{globalState vfs\}$} $line match vfs] } { | |
| 577 | + if { ($platform == $UNIX && $vfs == "unix-dotfile") | |
| 578 | + || ($platform == $WINDOWS && $vfs == "win32-longpath") } { | |
| 579 | + regsub $vfs $line {EXEPECTED_VFS} line | |
| 580 | + } | |
| 581 | + } elseif { $prev_line eq "fossil test-th-eval --vfs EXEPECTED_VFS {globalState vfs}" } { | |
| 582 | + # Replace $vfs from previous line | |
| 583 | + regsub "^$vfs\$" $line {EXEPECTED_VFS} line | |
| 584 | + } elseif { $prev_line eq "fossil test-th-eval {set tcl_platform(platform)}" } { | |
| 585 | + if { $platform == $UNIX } { | |
| 586 | + regsub {^unix$} $line {EXPECTED_PLATFORM} line | |
| 587 | + } elseif { $platform == $WINDOWS } { | |
| 588 | + regsub {^windows$} $line {EXPECTED_PLATFORM} line | |
| 589 | + } | |
| 590 | + } elseif { $line eq "ERROR (1): " } { | |
| 591 | + # Some output goes to stderr on Unix but stdout on Windows | |
| 592 | + set line "RESULT (0): " | |
| 593 | + } | |
| 594 | + } elseif { $testname eq "th1-docs" } { | |
| 595 | + # In th1-docs, the fossil check-out is exposed in various states. | |
| 596 | + regsub {(^project-code:) CE59BB9F186226D80E49D1FA2DB29F935CCA0333} $line {\1 HASH} line | |
| 597 | + if { [regexp {^merged-from: HASH YYYY-mm-dd HH:MM:SS UTC$} $line] } { | |
| 598 | + continue | |
| 599 | + } | |
| 600 | + } | |
| 601 | + } | |
| 602 | + } | |
| 603 | + } elseif { $EXTRA } { | |
| 604 | + # Fix up summaries to be generic and easy to diff(1) | |
| 605 | + if { [regsub {(^\*{5} (Final|Ignored) results: )\d+} $line {\1N} line] } { | |
| 606 | + regsub {\d+} $line {N} line | |
| 607 | + } elseif { [regexp {^(\*{5} (?:Considered failure|Ignored failure|Skipped test))s: (.*)} $line match desc vals] } { | |
| 608 | + if { $vals ne ""} { | |
| 609 | + foreach val [split $vals " "] { | |
| 610 | + puts "$desc: $val" | |
| 611 | + } | |
| 612 | + continue | |
| 613 | + } | |
| 614 | + } | |
| 615 | + } | |
| 616 | + | |
| 617 | + # Not exactly correct if we continue'd, but OK for the purpose | |
| 618 | + set prev_line "$result_prefix$line" | |
| 619 | + puts "$prev_line" | |
| 103 | 620 | } |
| 104 | 621 |
| --- test/rewrite-test-output.tcl | |
| +++ test/rewrite-test-output.tcl | |
| @@ -1,103 +1,620 @@ | |
| 1 | #!/usr/bin/env tclsh |
| 2 | |
| 3 | # Script to anonymise test results for comparison. |
| 4 | # - Replaces hashes, pids and similar with fixed strings |
| 5 | # - Rewrites temporary paths to standardise them in output |
| 6 | |
| 7 | # With no arguments or "-", use stdin. |
| 8 | set fname "-" |
| 9 | if { $argc > 0 } { |
| 10 | set fname [lindex $argv 0] |
| 11 | } |
| 12 | |
| 13 | # Any -options, or an empty first argument, is an error. |
| 14 | if { $argc > 1 || [regexp {^-.+} $fname] } { |
| 15 | puts stderr "usage: [file tail $argv0] ?FILE" |
| 16 | puts stderr " Rewrite test output to ease comparison of outputs." |
| 17 | exit 1 |
| 18 | } elseif { $fname ne "-" && ! [file exists $fname] } { |
| 19 | puts stderr "File does not exist: '$fname'" |
| 20 | exit 1 |
| 21 | } else { |
| 22 | if { $fname eq "-" } { |
| 23 | set fd stdin |
| 24 | } else { |
| 25 | set fd [open $fname r] |
| 26 | } |
| 27 | |
| 28 | set first_f13_line "fossil wiki create {timestamp of 2399999} f13 --technote 2399999" |
| 29 | set collecting_f3 0 |
| 30 | |
| 31 | set testname "" |
| 32 | while { [gets $fd line] >= 0 } { |
| 33 | if { [regsub {^\*{5} ([^ ]+) \*{6}$} $line {\1} new_testname] } { |
| 34 | # Pick up test naeme for special handling below |
| 35 | set testname "$new_testname" |
| 36 | } elseif { [regexp {^\*{5} End of } $line] } { |
| 37 | # Test done |
| 38 | set testname "" |
| 39 | } elseif { [regsub {^/.*?/(fossil )} $line {\1} line] } { |
| 40 | # Handle all fossil commands in one place |
| 41 | |
| 42 | # We get varying amounts of lines for wiki "f13" |
| 43 | if { $collecting_f3 > 2 } { |
| 44 | # Already collected |
| 45 | } elseif { $collecting_f3 > 0 } { |
| 46 | if { $collecting_f3 == 1 } { |
| 47 | # Print a continuation line here. |
| 48 | # The line is printed, but works as end line then. |
| 49 | puts "\[...\]" |
| 50 | } elseif [regexp {^fossil wiki (?:create .* f13|list --technote --show-technote-ids)} $line] { |
| 51 | continue |
| 52 | } |
| 53 | incr collecting_f3 |
| 54 | } elseif { $first_f13_line eq $line } { |
| 55 | incr collecting_f3 |
| 56 | } |
| 57 | |
| 58 | # Hashes |
| 59 | regsub {^(fossil .*) [0-9a-f]{40}($| )} $line {\1 HASH\2} line |
| 60 | regsub {^(fossil artifact) [0-9a-f]{64}} $line {\1 HASH} line |
| 61 | regsub {^(fossil artifact) [0-9a-f]{10}} $line {\1 HASH} line |
| 62 | regsub {^(fossil (?:attachment|wiki) .*--technote )[0-9a-f]{21}$} $line {\1HASH} line |
| 63 | regsub {^(fossil json artifact) [0-9a-f]{64}} $line {\1 HASH} line |
| 64 | regsub {^(fossil json wiki diff) [0-9a-f]{64} [0-9a-f]{64}} $line {\1 HASH1 HASH2} line |
| 65 | |
| 66 | # PIDs, Sequence numbers and seconds |
| 67 | regsub {^(fossil test-th-source .*/th1-)\d+([.]th1)$} $line {\1PID\2} line |
| 68 | if { [regexp {^fossil http --in } $line] } { |
| 69 | regsub -all {/(test-http-(?:in|out))-\d+-\d+-\d+(\.txt)} $line {/\1-PID-SEQ-SEC\2} line |
| 70 | } |
| 71 | |
| 72 | # Tech notes ids |
| 73 | regsub {^(fossil (?:attachment|wiki) .* (?:a13|f15|fa) --technote )[0-9a-f]+$} $line {\1ID} line |
| 74 | |
| 75 | # Special technote timestamp (mostly they are fixed) |
| 76 | regsub {^(fossil attachment add f11 --technote) [{]\d{4}-\d\d-\d\d \d\d:\d\d:\d\d[}]} $line {\1 {YYYY-mm-dd HH:MM:SS}} line |
| 77 | |
| 78 | # Unversioned test has passowrds and ports |
| 79 | regsub {^(fossil user new uvtester.*) \d+$} $line {\1 PASSWORD} line |
| 80 | regsub {^(fossil .*http://uvtester:)\d+(@localhost:)\d+} $line {\1PASSWORD\2PORT} line |
| 81 | } elseif { $testname eq "json" } { |
| 82 | regsub {^(Content-Length) \d+$} $line {\1 LENGTH} line |
| 83 | regsub {^( \"authToken\":\")[0-9a-f]{40}/\d+\.\d+/(anonymous\")$} $line {\1SHA1/NOW/\2} line |
| 84 | regsub {^(Cookie: fossil-)[0-9a-f]{16}\=[0-9a-f]{40}%2F\d+\.\d+%2F(anonymous)$} $line {\1CODE=SHA1%2FNOW%2F\2} line |
| 85 | regsub {^(GET /json/cap\?authToken\=)[0-9a-f]{40}/\d+\.\d+/(anonymous )} $line {\1SHA1/NOW/\2} line |
| 86 | regsub {^(Cookie: fossil-)[0-9a-f]{16}\=[0-9A-F]{50}%2F[0-9a-f]{16}%2F(.*)$} $line {\1CODE=SHA1%2FCODE%2F\2} line |
| 87 | } elseif { $testname eq "merge_renames" } { |
| 88 | regsub {^( (?:MERGED_WITH|BACKOUT)) [0-9a-f]{64}$} $line {\1 HASH} line |
| 89 | } elseif { $testname eq "unversioned" } { |
| 90 | regsub {^(Started Fossil server, pid \")\d+(\", port \")\d+} $line {\1PID\2PORT} line |
| 91 | regsub {^(Now in client directory \")/.*?/uvtest_\d+_\d+\"} $line {\1/TMP/uvtest_SEC_SEQ} line |
| 92 | regsub {^(Stopped Fossil server, pid \")\d+(\", using argument \")\d+} $line {\1PID\2PID} line |
| 93 | } |
| 94 | |
| 95 | # Some common lines not tied to fossil or specific tests. |
| 96 | regsub {^((?:ERROR \(1\): )?/[*]{5} Subprocess) \d+ (exit)} $line {\1 PID \2} line |
| 97 | |
| 98 | # Temporary directories |
| 99 | regsub -all {/.*?/repo_\d+/\d+_\d+} $line {/TMP/repo_PID/SEC_SEQ} line |
| 100 | |
| 101 | puts "$line" |
| 102 | } |
| 103 | } |
| 104 |
| --- test/rewrite-test-output.tcl | |
| +++ test/rewrite-test-output.tcl | |
| @@ -1,103 +1,620 @@ | |
| 1 | #!/usr/bin/env tclsh |
| 2 | |
| 3 | # Script to anonymise test results for comparison. |
| 4 | # - Replaces hashes, pids and similar with fixed strings |
| 5 | # - Rewrites temporary paths to standardise them in output |
| 6 | |
| 7 | # Pick up options |
| 8 | set EXTRA 0 |
| 9 | set i [lsearch $argv -extra] |
| 10 | while { $i >= 0 } { |
| 11 | incr EXTRA |
| 12 | set argv [lreplace $argv $i $i] |
| 13 | set i [lsearch $argv -extra] |
| 14 | } |
| 15 | |
| 16 | # With no arguments or "-", use stdin. |
| 17 | set fname "-" |
| 18 | if { [llength $argv] > 0 } { |
| 19 | set fname [lindex $argv 0] |
| 20 | } |
| 21 | |
| 22 | # Any -options, or an empty first argument, is an error. |
| 23 | if { [llength $argv] > 1 || [regexp {^-.+} $fname] } { |
| 24 | puts stderr "Error: argument error" |
| 25 | puts stderr "usage: \[-extra\] [file tail $argv0] ?FILE" |
| 26 | puts stderr " Rewrite test output to ease comparison of outputs." |
| 27 | puts stderr " With -extra, more output is rewritten as is summaries" |
| 28 | puts stderr " to make diff(1) mor euseful across runs and platforms." |
| 29 | exit 1 |
| 30 | } elseif { $fname ne "-" && ! [file exists $fname] } { |
| 31 | puts stderr "File does not exist: '$fname'" |
| 32 | exit 1 |
| 33 | } |
| 34 | |
| 35 | proc common_rewrites { line testname } { |
| 36 | # Normalise the fossil commands with path as just fossil |
| 37 | regsub {^(?:[A-Z]:)?/.*?/fossil(?:\.exe)? } $line {fossil } line |
| 38 | |
| 39 | # Accept 40 and 64 byte hashes as such |
| 40 | regsub -all {[[:<:]][0-9a-f]{40}[[:>:]]} $line HASH line |
| 41 | regsub -all {[[:<:]][0-9a-f]{64}[[:>:]]} $line HASH line |
| 42 | |
| 43 | # Date and time |
| 44 | regsub -all {[[:<:]]\d{4}-\d\d-\d\d \d\d:\d\d:\d\d[[:>:]]} $line {YYYY-mm-dd HH:MM:SS} line |
| 45 | if { [lsearch -exact {"amend" "wiki"} $testname] >= 0 } { |
| 46 | # With embedded T and milliseconds |
| 47 | regsub { \d{4}-\d\d-\d\dT\d\d:\d\d:\d\d\.\d{3}$} $line { YYYY-mm-ddTHH:MM:SS.NNN} line |
| 48 | } |
| 49 | if { [lsearch -exact {"amend" "th1-hooks" "wiki"} $testname] >= 0 } { |
| 50 | regsub {[[:<:]]\d{4}-\d\d-\d\d[[:>:]]} $line {YYYY-mm-dd} line |
| 51 | } |
| 52 | |
| 53 | # Timelines have HH:MM:SS [HASH], but don't mess with the zero'ed version. |
| 54 | regsub {^(?!00:00:00 \[0000000000\])\d\d:\d\d:\d\d \[[0-9a-f]{10}\] } $line {HH:MM:SS [HASH] } line |
| 55 | |
| 56 | # Temporary directories |
| 57 | regsub -all {(?:[A-Z]:)?/.*?/repo_\d+/\d+_\d+} $line {/TMP/repo_PID/SEC_SEQ} line |
| 58 | # Home directories only seem present with .fossil or _fossil. Simplify to .fossil. |
| 59 | regsub -all {(?:[A-Z]:)?/.*?/home_\d+/[._]fossil[[:>:]]} $line {/TMP/home_PID/.fossil} line |
| 60 | |
| 61 | # Users in output |
| 62 | regsub { (\(user: )[^\)]*\)$} $line { \1USER)} line |
| 63 | |
| 64 | return $line |
| 65 | } |
| 66 | |
| 67 | # |
| 68 | # tests/tests_unix/tests_windows contain tuples of |
| 69 | # |
| 70 | # 1. A regular expression to match current line |
| 71 | # 2. A substitution for the current line |
| 72 | # |
| 73 | # Some common patterns applicable to multiples tests are appended below. |
| 74 | # |
| 75 | # The common_rewrites procedure is run first, so use e.g. HASH as needed. |
| 76 | # |
| 77 | |
| 78 | dict set tests "amend" { |
| 79 | {^(fossil artifact) [0-9a-f]{10}} |
| 80 | {\1 HASH} |
| 81 | {^U [^ ]+$} |
| 82 | {U USER} |
| 83 | {^Z [0-9a-f]{32}$} |
| 84 | {Z CHECKSUM} |
| 85 | {^(ed -s \./ci-comment-).*?(\.txt)$} |
| 86 | {\1UNIQ\2} |
| 87 | {^(fossil amend HASH -date \{?)\d\d/\d\d/\d{4}} |
| 88 | {\1dd/mm/YYYY} |
| 89 | {^(fossil amend HASH -date \{.* )\d{4}(\})$} |
| 90 | {\1YYYY\2} |
| 91 | {^(fossil amend HASH -date \{.* )\d\d:} |
| 92 | {\1HH:} |
| 93 | {^(fossil amend HASH -date \{)[A-Z][a-z]{2} [A-Z][a-z]{2} [ 0-9]\d } |
| 94 | {\1Day Mon dd } |
| 95 | {(\] Edit \[)[0-9a-f]{16}.[0-9a-f]{10}(\]: )} |
| 96 | {\1HASH1|HASH2\2} |
| 97 | {(\] Edit \[.*?&dp=)[0-9a-f]{16}} |
| 98 | {\1dp=HASH} |
| 99 | } |
| 100 | |
| 101 | dict set tests "cmdline" { |
| 102 | {^(fossil test-echo --args) .*/} |
| 103 | {\1 /TMP/} |
| 104 | {^(g\.nameOfExe =) \[[^\]]+[/\\]fossil(?:\.exe)?\]$} |
| 105 | {\1 [/PATH/FOSSILCMD]} |
| 106 | {^(argv\[0\] =) \[[^\]]+[/\\]fossil(?:\.exe)?\]$} |
| 107 | {\1 [/PATH/FOSSILCMD]} |
| 108 | } |
| 109 | |
| 110 | dict set tests "contains-selector" { |
| 111 | {^(fossil test-contains-selector) .*?/(compare-selector.css )} |
| 112 | {\1 /TMP/\2} |
| 113 | } |
| 114 | |
| 115 | dict set tests "json" { |
| 116 | {^(Content-Length) \d+$} |
| 117 | {\1 LENGTH} |
| 118 | {^(Cookie: fossil-)[0-9a-f]{16}(\=HASH%2F)\d+\.\d+(%2Fanonymous)$} |
| 119 | {\1CODE\2NOW\3} |
| 120 | {^(GET /json/cap\?authToken\=HASH)/\d+\.\d+/(anonymous )} |
| 121 | {\1/NOW/\2} |
| 122 | {^(Cookie: fossil-)[0-9a-f]{16}\=[0-9A-F]{50}%2F[0-9a-f]{16}%2F(.*)$} |
| 123 | {\1CODE=SHA1%2FCODE%2F\2} |
| 124 | {("authToken":").+?(")} |
| 125 | {\1AUTHTOKEN\2} |
| 126 | {("averageArtifactSize":)\d+()} |
| 127 | {\1SIZE\2} |
| 128 | {("compiler":").+?(")} |
| 129 | {\1COMPILER\2} |
| 130 | {("loginCookieName":").+?(")} |
| 131 | {\1COOKIE\2} |
| 132 | {("manifestVersion":"\[)[0-9a-f]{10}(\]")} |
| 133 | {\1HASH\2} |
| 134 | {("manifestYear":")\d{4}(")} |
| 135 | {\1YYYY\2} |
| 136 | {("name":").+?(")} |
| 137 | {\1NAME\2} |
| 138 | {("password":")[0-9a-f]+(")} |
| 139 | {\1PASSWORD\2} |
| 140 | {("projectCode":")[0-9a-f]{40}(")} |
| 141 | {\1HASH\2} |
| 142 | {("procTimeMs":)\d+} |
| 143 | {\1MSEC} |
| 144 | {("procTimeUs":)\d+} |
| 145 | {\1USEC} |
| 146 | {("releaseVersion":")\d+\.\d+(")} |
| 147 | {\1VERSION\2} |
| 148 | {("releaseVersionNumber":")\d+(")} |
| 149 | {\1VERSION_NUMBER\2} |
| 150 | {("timestamp":)\d+} |
| 151 | {\1SEC} |
| 152 | {("seed":)\d+()} |
| 153 | {\1SEED\2} |
| 154 | {("uid":)\d+()} |
| 155 | {\1UID\2} |
| 156 | {("uncompressedArtifactSize":)\d+()} |
| 157 | {\1SIZE\2} |
| 158 | {("user":").+?(")} |
| 159 | {\1USER\2} |
| 160 | {^(Date:) [A-Z][a-z]{2}, \d\d? [A-Z][a-z]{2} \d{4} \d\d:\d\d:\d\d [-+]\d{4}$} |
| 161 | {\1 Day, dd Mon YYYY HH:MM:SS TZ} |
| 162 | } |
| 163 | |
| 164 | dict set tests "merge_renames" { |
| 165 | {^(size: {7})\d+( bytes)$} |
| 166 | {\1N\2} |
| 167 | {^(type: {7}Check-in by ).+?( on YYYY-mm-dd HH:MM:SS)$} |
| 168 | {\1USER\2} |
| 169 | } |
| 170 | |
| 171 | dict set tests "set-manifest" { |
| 172 | {^(project-code: )[0-9a-f]{40}$} |
| 173 | {\1HASH} line |
| 174 | } |
| 175 | |
| 176 | dict set tests "stash" { |
| 177 | {^(---|\+\+\+) NUL$} |
| 178 | {\1 /dev/null} |
| 179 | {(^ 1: \[)[0-9a-f]{14}(\] on YYYY-mm-dd HH:MM:SS)$} |
| 180 | {\1HASH\2} |
| 181 | {(^ 1: \[)[0-9a-f]{14}(\] from YYYY-mm-dd HH:MM:SS)$} |
| 182 | {\1HASH\2} |
| 183 | } |
| 184 | |
| 185 | dict set tests "th1" { |
| 186 | {^(fossil test-th-source) (?:[A-Z]:)?.*?/(th1-)\d+([.]th1)$} |
| 187 | {\1 /TMP/\2PID\3} |
| 188 | {^(?:[A-Z]:)?[/\\].*?[/\\]fossil(?:\.exe)?$} |
| 189 | {/PATH/FOSSILCMD} |
| 190 | {[[:<:]](Content-Security-Policy[[:>:]].*'nonce-)[0-9a-f]{48}(';)} |
| 191 | {\1NONCE\2} |
| 192 | {^(<link rel="stylesheet" href="/style.css\?id=)[0-9a-f]+(" type="text/css">)$} |
| 193 | {\1ID\2} |
| 194 | {^\d+\.\d{3}(s by)$} |
| 195 | {N.MMM\1} |
| 196 | {^(Fossil) \d+\.\d+ \[[0-9a-f]{10}\] (YYYY-mm-dd HH:MM:SS)$} |
| 197 | {\1 N.M [HASH] \2} |
| 198 | {^(<script nonce=")[0-9a-f]{48}(">/\* style\.c:)\d+} |
| 199 | {\1NONCE\2LINENO} |
| 200 | } |
| 201 | |
| 202 | dict set tests "th1-docs" { |
| 203 | {^(check-ins: ).*} |
| 204 | {\1COUNT} |
| 205 | {^(local-root: ).*} |
| 206 | {\1/PATH/} |
| 207 | {^(repository: ).*} |
| 208 | {\1/PATH/REPO} |
| 209 | {^(comment: ).*} |
| 210 | {\1/COMMENT/} |
| 211 | {^(tags: ).*} |
| 212 | {\1/TAGS/} |
| 213 | {(--ipaddr 127\.0\.0\.1) .*? (--localauth)} |
| 214 | {\1 REPO \2} |
| 215 | } |
| 216 | |
| 217 | dict set tests "th1-hooks" { |
| 218 | {^(?:/[^:]*/fossil|[A-Z]:\\[^:]*\\fossil\.exe): (unknown command:|use \"help\")} |
| 219 | {fossil: \1} |
| 220 | {^(project-code: )[0-9a-f]{40}$} |
| 221 | {\1HASH} |
| 222 | } |
| 223 | |
| 224 | dict set tests "th1-tcl" { |
| 225 | {^(fossil test-th-render --open-config) \{?.*?[/\\]test[/\\]([^/\\]*?)\}?$} |
| 226 | {\1 /CHECKOUT/test/\2} |
| 227 | {^(fossil)(?:\.exe)?( 3 \{test-th-render --open-config )(?:\{[A-Z]:)?[/\\].*?[/\\]test[/\\](th1-tcl9.txt\})\}?$} |
| 228 | {\1\2/CHECKOUT/test/\3} |
| 229 | {^\d{10}$} |
| 230 | {SEC} |
| 231 | } |
| 232 | |
| 233 | dict set tests "unversioned" { |
| 234 | {^(fossil user new uvtester.*) \d+$} |
| 235 | {\1 PASSWORD} |
| 236 | {^(fossil .*http://uvtester:)\d+(@localhost:)\d+} |
| 237 | {\1PASSWORD\2PORT} |
| 238 | {^(Pull from http://uvtester@localhost:)\d+} |
| 239 | {\1PORT} |
| 240 | {^(ERROR \(1\): Usage:) .*?[/\\]fossil(?:\.exe)? (unversioned)} |
| 241 | {\1 /PATH/fossil \2} |
| 242 | {^(Started Fossil server, pid \")\d+(\", port \")\d+} |
| 243 | {\1PID\2PORT} |
| 244 | {^(Now in client directory \")(?:[A-Z]:)?/.*?/uvtest_\d+_\d+\"} |
| 245 | {\1/TMP/uvtest_SEC_SEQ} |
| 246 | {^(Stopped Fossil server, pid \")\d+(\", using argument \")(?:\d+|[^\"]*\.stopper)(\")} |
| 247 | {\1PID\2PID_OR_SCRIPT\3} |
| 248 | {^(This is unversioned file #4\.) \d+ \d+} |
| 249 | {\1 PID SEC} |
| 250 | {^(This is unversioned file #4\. PID SEC) \d+ \d+} |
| 251 | {\1 PID SEC} |
| 252 | {^[0-9a-f]{12}( YYYY-mm-dd HH:MM:SS *)(\d+)( *)\2( unversioned4.txt)$} |
| 253 | {HASH \1SZ\3SZ\4} |
| 254 | {^[0-9a-f]{40}$} |
| 255 | {\1HASH} |
| 256 | {^((?:Clone|Pull)? done, wire bytes sent: )\d+( received: )\d+( remote: )(?:127\.0.0\.1|::1)$} |
| 257 | {\1SENT\2RECV\3LOCALIP} |
| 258 | {^(project-id: )[0-9a-f]{40}$} |
| 259 | {\1HASH} |
| 260 | {^(server-id: )[0-9a-f]{40}$} |
| 261 | {\1HASH} |
| 262 | {^(admin-user: uvtester \(password is ").*("\))$} |
| 263 | {\1PASSWORD\2} |
| 264 | {^(repository: ).*?/uvtest_\d+_\d+/(uvrepo.fossil)$} |
| 265 | {\1/TMP/uvtest_SEC_SEQ/\2} |
| 266 | {^(local-root: ).*?/uvtest_\d+_\d+/$} |
| 267 | {\1/TMP/uvtest_SEC_SEQ/} |
| 268 | {^(project-code: )[0-9a-f]{40}$} |
| 269 | {\1HASH} |
| 270 | } |
| 271 | |
| 272 | dict set tests "utf" { |
| 273 | {^(fossil test-looks-like-utf) (?:[A-Z]:)?/.*?/([^/\\]*?)\}?$} |
| 274 | {\1 /TMP/test/\2} |
| 275 | {^(File ")(?:[A-Z]:)?/.*?/(utf-check-\d+-\d+-\d+-\d+.jnk" has \d+ bytes\.)$} |
| 276 | {\1/TMP/\2} |
| 277 | } |
| 278 | |
| 279 | dict set tests "wiki" { |
| 280 | {^(fossil (?:attachment|wiki) .*--technote )[0-9a-f]{21}$} |
| 281 | {\1HASH} |
| 282 | {^(fossil (?:attachment|wiki) .* (?:a13|f15|fa) --technote )[0-9a-f]+$} |
| 283 | {\1ID} |
| 284 | {^[0-9a-f]{40}( YYYY-mm-dd HH:MM:SS)} |
| 285 | {HASH\1} |
| 286 | {(\] Add attachment \[/artifact/)[0-9a-f]{16}(|)} |
| 287 | {\1HASH\2} |
| 288 | { (to tech note \[/technote/)[0-9a-f]{16}\|[0-9a-f]{10}(\] \(user:)} |
| 289 | {\1HASH1|HASH2\2} |
| 290 | {^(ambiguous tech note id: )[0-9a-f]+$} |
| 291 | {\1ID} |
| 292 | {^(Attached fa to tech note )[0-9a-f]{21}(?:[0-9a-f]{19})?\.$} |
| 293 | {\1HASH.} |
| 294 | {^(Date:) [A-Z][a-z]{2}, \d\d? [A-Z][a-z]{2} \d{4} \d\d:\d\d:\d\d [-+]\d{4}$} |
| 295 | {\1 Day, dd Mon YYYY HH:MM:SS TZ} |
| 296 | {(Content-Security-Policy.*'nonce-)[0-9a-f]{48}(';)} |
| 297 | {\1NONCE\2} |
| 298 | {^(<link rel="stylesheet" href="/style.css\?id=)[0-9a-f]+(" type="text/css">)$} |
| 299 | {\1ID\2} |
| 300 | {^(added by )[^ ]*( on)$} |
| 301 | {\1USER\2} |
| 302 | {^(<script nonce=['\"])[0-9a-f]{48}(['\"]>/\* [a-z]+\.c:)\d+} |
| 303 | {\1NONCE\2LINENO} |
| 304 | {^(<script nonce=['\"])[0-9a-f]{48}(['\"]>)$} |
| 305 | {\1NONCE\2} |
| 306 | {^(projectCode: ")[0-9a-f]{40}(",)$} |
| 307 | {\1HASH\2} |
| 308 | {^\d+\.\d+(s by)$} |
| 309 | {N.SUB\1} |
| 310 | {^(window\.fossil.version = ")\d+\.\d+ \[[0-9a-f]{10}\] (YYYY-mm-dd HH:MM:SS(?: UTC";)?)$} |
| 311 | {\1N.M [HASH] \2} |
| 312 | {^(Fossil) \d+\.\d+ \[[0-9a-f]{10}\]( YYYY-mm-dd HH:MM:SS)$} |
| 313 | {\1 N.M [HASH]\2} |
| 314 | {^(type: Wiki-edit by ).+?( on YYYY-mm-dd HH:MM:SS)$$} |
| 315 | {\1USER\2} |
| 316 | {^(size: )\d+( bytes)$} |
| 317 | {\1N\2} |
| 318 | {^U [^ ]+$} |
| 319 | {U USER} |
| 320 | {^Z [0-9a-f]{32}$} |
| 321 | {Z CHECKSUM} |
| 322 | } |
| 323 | |
| 324 | # |
| 325 | # Some pattersn are used in multiple groups |
| 326 | # |
| 327 | |
| 328 | set testnames {"th1" "th1-docs" "th1-hooks"} |
| 329 | set pat {^((?:ERROR \(1\): )?/[*]{5} Subprocess) \d+ (exit)} |
| 330 | set sub {\1 PID \2} |
| 331 | foreach testname $testnames { |
| 332 | dict lappend tests $testname $pat $sub |
| 333 | } |
| 334 | |
| 335 | set testnames {"th1-docs" "th1-hooks"} |
| 336 | set pat {(?:[A-Z]:)?/.*?/(test-http-(?:in|out))-\d+-\d+-\d+(\.txt)} |
| 337 | set sub {/TMP/\1-PID-SEQ-SEC\2} |
| 338 | foreach testname $testnames { |
| 339 | dict lappend tests $testname $pat $sub |
| 340 | } |
| 341 | |
| 342 | set testnames {"json" "th1" "wiki"} |
| 343 | set pat {^(Content-Length:) \d+$} |
| 344 | set sub {\1 LENGTH} |
| 345 | foreach testname $testnames { |
| 346 | dict lappend tests $testname $pat $sub |
| 347 | } |
| 348 | |
| 349 | set testnames {"th1" "wiki"} |
| 350 | set pat {^\d+\.\d+(s by)$} |
| 351 | set sub {N.SUB\1} |
| 352 | foreach testname $testnames { |
| 353 | dict lappend tests $testname $pat $sub |
| 354 | } |
| 355 | |
| 356 | # |
| 357 | # Main |
| 358 | # |
| 359 | |
| 360 | if { $fname eq "-" } { |
| 361 | set fd stdin |
| 362 | } else { |
| 363 | set fd [open $fname r] |
| 364 | } |
| 365 | |
| 366 | # Platforms we detect |
| 367 | set UNKOWN_PLATFORM 0 |
| 368 | set UNIX 1 |
| 369 | set WINDOWS 2 |
| 370 | |
| 371 | # One specific wiki test creates repetitive output of varying length |
| 372 | set wiki_f13_cmd1 "fossil wiki create {timestamp of 2399999} f13 --technote 2399999" |
| 373 | set wiki_f13_cmd2 "fossil wiki list --technote --show-technote-ids" |
| 374 | set wiki_f13_cmd3 "fossil wiki export a13 --technote ID" |
| 375 | set collecting_f3 0 |
| 376 | set collecting_f3_verbose 0 |
| 377 | |
| 378 | # Collected lines for summaries in --extra mode |
| 379 | set amend_ed_lines [list] |
| 380 | set amend_ed_failed 0 |
| 381 | set symlinks_lines [list] |
| 382 | set symlinks_failed 0 |
| 383 | set test_simplify_name_lines [list] |
| 384 | set test_simplify_name_failed 0 |
| 385 | |
| 386 | # State information s we progress |
| 387 | set check_json_empty_line 0 |
| 388 | set lineno 0 |
| 389 | set platform $UNKOWN_PLATFORM |
| 390 | set prev_line "" |
| 391 | set testname "" |
| 392 | |
| 393 | while { [gets $fd line] >= 0 } { |
| 394 | incr lineno |
| 395 | |
| 396 | if { $lineno == 1 } { |
| 397 | if { [string index $line 0] in {"\UFFEF" "\UFEFF"} } { |
| 398 | set line [string range $line 1 end] |
| 399 | } |
| 400 | } |
| 401 | |
| 402 | # Remove RESULT status while matching (inserted again in output). |
| 403 | # If collecting lines of output, include $result_prefix as needed. |
| 404 | regexp {^(RESULT \([01]\): )?(.*)} $line match result_prefix line |
| 405 | |
| 406 | if { [regsub {^\*{5} ([^ ]+) \*{6}$} $line {\1} new_testname] } { |
| 407 | # Pick up test name for special handling below |
| 408 | set testname "$new_testname" |
| 409 | } elseif { [regexp {^\*{5} End of } $line] } { |
| 410 | # Test done. Handle --extra before resetting. |
| 411 | if { $EXTRA } { |
| 412 | if { $testname eq "symlinks" } { |
| 413 | if { $symlinks_failed } { |
| 414 | foreach l $symlinks_lines { |
| 415 | puts "$l" |
| 416 | } |
| 417 | } else { |
| 418 | puts "All symlinks tests OK (not run on Windows)" |
| 419 | } |
| 420 | } |
| 421 | regsub {(: )\d+( errors so far)} $line {\1N\2} line |
| 422 | } |
| 423 | set testname "" |
| 424 | } elseif { $testname ne "" } { |
| 425 | if { $platform == $UNKOWN_PLATFORM } { |
| 426 | if { [regexp {^[A-Z]:/.*?/fossil\.exe } $line] } { |
| 427 | set platform $WINDOWS |
| 428 | } elseif { [regexp {^/.*?/fossil } $line] } { |
| 429 | set platform $UNIX |
| 430 | } |
| 431 | } |
| 432 | |
| 433 | # Do common and per testname rewrites |
| 434 | set line [common_rewrites $line $testname] |
| 435 | if { [dict exists $tests $testname] } { |
| 436 | foreach {pat sub} [dict get $tests $testname] { |
| 437 | regsub $pat $line $sub line |
| 438 | } |
| 439 | } |
| 440 | |
| 441 | # On Windows, HTTP headers may get printed with an extra newline |
| 442 | if { $testname eq "json" } { |
| 443 | if { $check_json_empty_line == 1 } { |
| 444 | if { "$result_prefix$line" eq "" } { |
| 445 | set check_json_empty_line 2 |
| 446 | continue |
| 447 | } |
| 448 | set check_json_empty_line 0 |
| 449 | } elseif { [regexp {^(?:$|GET |POST |[A-Z][A-Za-z]*(?:-[A-Z][A-Za-z]*)*: )} $line] } { |
| 450 | set check_json_empty_line 1 |
| 451 | } else { |
| 452 | if { $check_json_empty_line == 2 } { |
| 453 | # The empty line we skipped was meant to be followed by a new |
| 454 | # HTTP header or empty line, but it was not. |
| 455 | puts "" |
| 456 | } |
| 457 | set check_json_empty_line 0 |
| 458 | } |
| 459 | } |
| 460 | |
| 461 | # Summarise repetitive output of varying length for f13 in wiki test |
| 462 | if { $testname eq "wiki" } { |
| 463 | if { $collecting_f3 == 2 } { |
| 464 | if { $collecting_f3_verbose == 1 && [regexp {^HASH } $line] } { |
| 465 | incr collecting_f3_verbose |
| 466 | } elseif { $line eq $wiki_f13_cmd3 } { |
| 467 | incr collecting_f3 |
| 468 | puts "\[...\]" |
| 469 | } else { |
| 470 | continue |
| 471 | } |
| 472 | } elseif { $collecting_f3 == 1 } { |
| 473 | if { $line eq $wiki_f13_cmd2 } { |
| 474 | incr collecting_f3 |
| 475 | } elseif { $collecting_f3_verbose == 0 } { |
| 476 | incr collecting_f3_verbose |
| 477 | } |
| 478 | } elseif { $line eq $wiki_f13_cmd1 } { |
| 479 | incr collecting_f3 |
| 480 | } |
| 481 | } |
| 482 | |
| 483 | if { $EXTRA } { |
| 484 | if { $testname eq "amend" } { |
| 485 | # The amend-comment-5.N tests are not run on Windows |
| 486 | if { $line eq "fossil amend {} -close" } { |
| 487 | if { $amend_ed_failed } { |
| 488 | foreach l $amend_ed_lines { |
| 489 | puts "$l" |
| 490 | } |
| 491 | } else { |
| 492 | puts "All amend tests based on ed -s OK (not run on Windows)" |
| 493 | } |
| 494 | set amend_ed_lines [list] |
| 495 | } elseif { [llength $amend_ed_lines] } { |
| 496 | if { [regexp {^test amend-comment-5\.\d+ (.*)} $line match status] } { |
| 497 | lappend amend_ed_lines "$result_prefix$line" |
| 498 | if { $status ne "OK" } { |
| 499 | incr amend_ed_failed |
| 500 | } |
| 501 | continue |
| 502 | } elseif { [string range $line 0 4] eq "test " } { |
| 503 | # Handle change in tests by simply emitting what we got |
| 504 | foreach l $amend_ed_lines { |
| 505 | puts "$l" |
| 506 | } |
| 507 | set amend_ed_lines [list] |
| 508 | } else { |
| 509 | lappend amend_ed_lines "$result_prefix$line" |
| 510 | continue |
| 511 | } |
| 512 | } elseif { $line eq "fossil settings editor {ed -s}" } { |
| 513 | lappend amend_ed_lines "$result_prefix$line" |
| 514 | continue |
| 515 | } |
| 516 | } elseif { $testname eq "cmdline" } { |
| 517 | if { [regexp {^(fossil test-echo) (.*)} $line match test args] } { |
| 518 | if { ($platform == $UNIX && $args in {"*" "*.*"}) |
| 519 | || ($platform == $WINDOWS && $args eq "--args /TMP/fossil-cmd-line-101.txt") } { |
| 520 | set line "$test ARG_FOR_PLATFORM" |
| 521 | } |
| 522 | } |
| 523 | } elseif { $testname eq "commit-warning" } { |
| 524 | if { [regexp {^(micro-smile|pale facepalm) .*} $line match desc] } { |
| 525 | set line "$desc PLATFORM_SPECIFIC_BYTES" |
| 526 | } |
| 527 | } elseif { $testname eq "file1" } { |
| 528 | # test-simplify-name with question marks is specific to Windows |
| 529 | # They all immediately preceed "fossil test-relative-name --chdir . ." |
| 530 | if { $line eq "fossil test-relative-name --chdir . ." } { |
| 531 | if { $test_simplify_name_failed } { |
| 532 | foreach l $test_simplify_name_lines { |
| 533 | puts "$l" |
| 534 | } |
| 535 | } else { |
| 536 | puts "ALL Windows specific test-relative-name tests OK (if on Windows)" |
| 537 | } |
| 538 | set test_simplify_name_lines [list] |
| 539 | } elseif { [regexp {^fossil test-simplify-name .*([/\\])\?\1} $line] } { |
| 540 | lappend test_simplify_name_lines $line |
| 541 | continue |
| 542 | } elseif { [llength $test_simplify_name_lines] } { |
| 543 | if { [regexp {^test simplify-name-\d+ (.*)} $line match status] } { |
| 544 | if { $status ne "OK" } { |
| 545 | incr test_simplify_name_failed |
| 546 | } |
| 547 | } |
| 548 | lappend test_simplify_name_lines "$result_prefix$line" |
| 549 | continue |
| 550 | } |
| 551 | } elseif { $testname eq "settings-repo" } { |
| 552 | if { [regexp {^fossil test-th-eval (?:--open-config )?\{setting case-sensitive\}$} $prev_line] } { |
| 553 | if { ($platform == $UNIX && $line eq "on") || ($platform == $WINDOWS && $line eq "off") } { |
| 554 | set line "EXPECTED_FOR_PLATFORM" |
| 555 | } |
| 556 | } |
| 557 | } elseif { $testname eq "symlinks" } { |
| 558 | # Collect all lines and post-process at the end |
| 559 | lappend symlinks_lines "$result_prefix$line" |
| 560 | if { [regexp {^test symlinks-[^ ]* (.*)} $line match status] } { |
| 561 | if { $status ne "OK" } { |
| 562 | #TODO: incr symlinks_failed |
| 563 | } |
| 564 | } |
| 565 | continue |
| 566 | } elseif { $testname in {"th1" "th1-docs" "th1-hooks"} } { |
| 567 | # Special case that spans a couple of tests |
| 568 | # "Subprocess PID exit(0)" is sent on stderr on Unix. On Windows, there is no output |
| 569 | if { [regexp {^(ERROR \(1\): )?/\*{5} Subprocess PID exit\(0\) \*{5}/$} $line match prefix] } { |
| 570 | if { $prefix eq "" } { |
| 571 | continue |
| 572 | } elseif { $prefix eq "ERROR (1): " } { |
| 573 | set line "RESULT (0): " |
| 574 | } |
| 575 | } elseif { $testname eq "th1" } { |
| 576 | if { [regexp {^fossil test-th-eval --vfs ([^ ]+) \{globalState vfs\}$} $line match vfs] } { |
| 577 | if { ($platform == $UNIX && $vfs == "unix-dotfile") |
| 578 | || ($platform == $WINDOWS && $vfs == "win32-longpath") } { |
| 579 | regsub $vfs $line {EXEPECTED_VFS} line |
| 580 | } |
| 581 | } elseif { $prev_line eq "fossil test-th-eval --vfs EXEPECTED_VFS {globalState vfs}" } { |
| 582 | # Replace $vfs from previous line |
| 583 | regsub "^$vfs\$" $line {EXEPECTED_VFS} line |
| 584 | } elseif { $prev_line eq "fossil test-th-eval {set tcl_platform(platform)}" } { |
| 585 | if { $platform == $UNIX } { |
| 586 | regsub {^unix$} $line {EXPECTED_PLATFORM} line |
| 587 | } elseif { $platform == $WINDOWS } { |
| 588 | regsub {^windows$} $line {EXPECTED_PLATFORM} line |
| 589 | } |
| 590 | } elseif { $line eq "ERROR (1): " } { |
| 591 | # Some output goes to stderr on Unix but stdout on Windows |
| 592 | set line "RESULT (0): " |
| 593 | } |
| 594 | } elseif { $testname eq "th1-docs" } { |
| 595 | # In th1-docs, the fossil check-out is exposed in various states. |
| 596 | regsub {(^project-code:) CE59BB9F186226D80E49D1FA2DB29F935CCA0333} $line {\1 HASH} line |
| 597 | if { [regexp {^merged-from: HASH YYYY-mm-dd HH:MM:SS UTC$} $line] } { |
| 598 | continue |
| 599 | } |
| 600 | } |
| 601 | } |
| 602 | } |
| 603 | } elseif { $EXTRA } { |
| 604 | # Fix up summaries to be generic and easy to diff(1) |
| 605 | if { [regsub {(^\*{5} (Final|Ignored) results: )\d+} $line {\1N} line] } { |
| 606 | regsub {\d+} $line {N} line |
| 607 | } elseif { [regexp {^(\*{5} (?:Considered failure|Ignored failure|Skipped test))s: (.*)} $line match desc vals] } { |
| 608 | if { $vals ne ""} { |
| 609 | foreach val [split $vals " "] { |
| 610 | puts "$desc: $val" |
| 611 | } |
| 612 | continue |
| 613 | } |
| 614 | } |
| 615 | } |
| 616 | |
| 617 | # Not exactly correct if we continue'd, but OK for the purpose |
| 618 | set prev_line "$result_prefix$line" |
| 619 | puts "$prev_line" |
| 620 | } |
| 621 |