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.

preben 2023-12-11 20:26 testing-improvements
Commit 0424384328fe54e04140f3ed9f3441e6a55375fc838ef737297a1855e3a2a4ac
1 file changed +602 -85
--- test/rewrite-test-output.tcl
+++ test/rewrite-test-output.tcl
@@ -1,103 +1,620 @@
11
#!/usr/bin/env tclsh
22
33
# Script to anonymise test results for comparison.
44
# - Replaces hashes, pids and similar with fixed strings
55
# - 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
+}
615
716
# With no arguments or "-", use stdin.
817
set fname "-"
9
-if { $argc > 0 } {
18
+if { [llength $argv] > 0 } {
1019
set fname [lindex $argv 0]
1120
}
1221
1322
# 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"
1626
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."
1729
exit 1
1830
} elseif { $fname ne "-" && ! [file exists $fname] } {
1931
puts stderr "File does not exist: '$fname'"
2032
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"
103620
}
104621
--- 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

Keyboard Shortcuts

Open search /
Next entry (timeline) j
Previous entry (timeline) k
Open focused entry Enter
Show this help ?
Toggle theme Top nav button