1 | #!/usr/bin/env bash
|
2 | #
|
3 | # Usage:
|
4 | # benchmarks/time-test.sh <function name>
|
5 |
|
6 | : ${LIB_OSH=stdlib/osh}
|
7 | source $LIB_OSH/bash-strict.sh
|
8 | source $LIB_OSH/no-quotes.sh
|
9 | source $LIB_OSH/task-five.sh
|
10 |
|
11 | REPO_ROOT=$(cd "$(dirname $0)/.."; pwd)
|
12 |
|
13 | source test/common.sh
|
14 | source test/tsv-lib.sh
|
15 |
|
16 | # TODO: This would be a nice little program for Oil
|
17 | count-lines-and-cols() {
|
18 | python2 -c '
|
19 | import sys
|
20 |
|
21 | expected_num_lines = int(sys.argv[1])
|
22 | expected_num_cols = int(sys.argv[2])
|
23 | try:
|
24 | sep = sys.argv[3]
|
25 | except IndexError:
|
26 | sep = "\t"
|
27 |
|
28 | num_lines = 0
|
29 | tab_counts = []
|
30 | for line in sys.stdin:
|
31 | tab_counts.append(line.count(sep))
|
32 | num_lines += 1
|
33 | # Show what we get
|
34 | sys.stdout.write(line)
|
35 |
|
36 | if any(tab_counts[0] != n for n in tab_counts):
|
37 | raise AssertionError(tab_counts)
|
38 |
|
39 | num_tabs = tab_counts[0]
|
40 |
|
41 | assert expected_num_lines == num_lines, \
|
42 | "expected %d lines, got %d" % (expected_num_lines, num_lines)
|
43 | assert expected_num_cols == num_tabs + 1, \
|
44 | "expected %d cols, got %d" % (expected_num_cols, num_tabs + 1)
|
45 | ' "$@"
|
46 | }
|
47 |
|
48 | time-tool() {
|
49 | $(dirname $0)/time_.py "$@"
|
50 | }
|
51 |
|
52 | test-csv() {
|
53 | local out=_tmp/time.csv
|
54 |
|
55 | time-tool -o $out -- echo hi
|
56 | cat $out | count-lines-and-cols 1 2 ,
|
57 |
|
58 | time-tool -o $out --field a --field b -- echo hi
|
59 | cat $out | count-lines-and-cols 1 4 ,
|
60 | echo csv fields=$?
|
61 |
|
62 | time-tool -o $out --rusage -- echo hi
|
63 | cat $out | count-lines-and-cols 1 5 ,
|
64 | echo csv rusage=$?
|
65 |
|
66 | time-tool -o $out --rusage --field a --field b -- echo hi
|
67 | cat $out | count-lines-and-cols 1 7 ,
|
68 | echo csv rusage fields=$?
|
69 | }
|
70 |
|
71 | test-tsv() {
|
72 | local out=_tmp/time.tsv
|
73 | rm -f $out
|
74 |
|
75 | for i in 1 2 3; do
|
76 | time-tool --tsv -o $out --append --time-fmt '%.2f' -- sleep 0.0${i}
|
77 | done
|
78 | cat $out | count-lines-and-cols 3 2
|
79 |
|
80 | time-tool --tsv -o $out --field a --field b -- echo hi
|
81 | cat $out | count-lines-and-cols 1 4
|
82 | echo fields=$?
|
83 |
|
84 | time-tool --tsv -o $out --rusage --field a --field b -- echo hi
|
85 | cat $out | count-lines-and-cols 1 7
|
86 | echo rusage=$?
|
87 |
|
88 | time-tool --tsv -o $out --print-header \
|
89 | --rusage-2
|
90 | time-tool --tsv -o $out --append \
|
91 | --rusage-2 -- echo hi
|
92 | cat $out | count-lines-and-cols 2 10
|
93 | echo rusage-2=$?
|
94 | }
|
95 |
|
96 | test-append() {
|
97 | local out=_tmp/overwrite.tsv
|
98 | for i in 4 5; do
|
99 | time-tool --tsv -o $out -- sleep 0.0${i}
|
100 | done
|
101 | cat $out | count-lines-and-cols 1 2
|
102 |
|
103 | echo ---
|
104 |
|
105 | local out=_tmp/append.tsv
|
106 | rm -f $out
|
107 |
|
108 | for i in 4 5; do
|
109 | time-tool --tsv -o $out --append -- sleep 0.0${i}
|
110 | done
|
111 | cat $out | count-lines-and-cols 2 2
|
112 | }
|
113 |
|
114 | test-usage() {
|
115 | local status
|
116 | nq-run status \
|
117 | time-tool
|
118 | nq-assert $status -eq 2
|
119 |
|
120 | nq-run status \
|
121 | time-tool --output
|
122 | nq-assert $status -eq 2
|
123 |
|
124 | nq-run status \
|
125 | time-tool sleep 0.1
|
126 | nq-assert $status -eq 0
|
127 |
|
128 | nq-run status \
|
129 | time-tool --append sleep 0.1
|
130 | nq-assert $status -eq 0
|
131 | }
|
132 |
|
133 | test-bad-tsv-chars() {
|
134 | local status
|
135 | local out=_tmp/time2.tsv
|
136 | rm -f $out
|
137 |
|
138 | # Newline should fail
|
139 | nq-run status \
|
140 | time-tool --tsv -o $out --field $'\n' -- sleep 0.001
|
141 | nq-assert $status = 1
|
142 |
|
143 | # Tab should fail
|
144 | nq-run status \
|
145 | time-tool --tsv -o $out --field $'\t' -- sleep 0.001
|
146 | nq-assert $status = 1
|
147 |
|
148 | # Quote should fail
|
149 | nq-run status \
|
150 | time-tool --tsv -o $out --field '"' -- sleep 0.001
|
151 | nq-assert $status = 1
|
152 |
|
153 | # Backslash is OK
|
154 | nq-run status \
|
155 | time-tool --tsv -o $out --field '\' -- sleep 0.001
|
156 | nq-assert $status = 0
|
157 |
|
158 | # Space is OK, although canonical form would be " "
|
159 | nq-run status \
|
160 | time-tool --tsv -o $out --field ' ' -- sleep 0.001
|
161 | nq-assert $status = 0
|
162 |
|
163 | cat $out
|
164 | }
|
165 |
|
166 | test-stdout() {
|
167 | local out=_tmp/time-stdout.csv
|
168 | time-tool -o $out --stdout _tmp/stdout.txt -- seq 3
|
169 |
|
170 | diff _tmp/stdout.txt - <<EOF
|
171 | 1
|
172 | 2
|
173 | 3
|
174 | EOF
|
175 |
|
176 | # No assertions here yet
|
177 | md5sum _tmp/stdout.txt
|
178 | cat $out | count-lines-and-cols 1 3 ,
|
179 |
|
180 | time-tool -o $out --rusage --stdout _tmp/stdout.txt -- seq 3
|
181 | cat $out | count-lines-and-cols 1 6 ,
|
182 | }
|
183 |
|
184 | test-rusage() {
|
185 | local out=_tmp/time-rusage.csv
|
186 | time-tool --tsv -o $out --rusage -- bash -c 'echo bash'
|
187 | cat $out | count-lines-and-cols 1 5
|
188 |
|
189 | #time-tool --tsv -o $out --rusage -- dash -c 'echo dash'
|
190 | #cat $out
|
191 |
|
192 | # Blow up memory size for testing
|
193 | local py='a=[42]*500000; print "python"'
|
194 |
|
195 | time-tool --tsv -o $out --rusage -- python2 -c "$py"
|
196 | cat $out | count-lines-and-cols 1 5
|
197 |
|
198 | #time-tool --tsv -o $out --rusage -- bin/osh -c 'echo osh'
|
199 | #cat $out
|
200 | }
|
201 |
|
202 | test-time-span() {
|
203 | local out=_tmp/time-span.csv
|
204 |
|
205 | time-tool --tsv -o $out --time-span --print-header
|
206 | cat $out | count-lines-and-cols 1 4
|
207 |
|
208 | time-tool --tsv -o $out --time-span -- bash -c 'echo bash'
|
209 | cat $out | count-lines-and-cols 1 4
|
210 | }
|
211 |
|
212 | # Compare vs. /usr/bin/time.
|
213 | test-maxrss() {
|
214 | if which time; then # Ignore this on continuous build
|
215 | command time --format '%x %U %M' -- seq 1
|
216 | fi
|
217 |
|
218 | # Showing a discrepancy. FIXED!
|
219 | time-tool -o _tmp/maxrss --tsv --rusage -- seq 1
|
220 | cat _tmp/maxrss
|
221 | }
|
222 |
|
223 | test-print-header() {
|
224 | local status
|
225 |
|
226 | # no arguments allowed
|
227 | nq-run status \
|
228 | time-tool --tsv --print-header foo bar
|
229 | nq-assert $status = 2
|
230 |
|
231 | nq-run status \
|
232 | time-tool --tsv --print-header --field name
|
233 | nq-assert $status = 0
|
234 |
|
235 | nq-run status \
|
236 | time-tool --tsv --print-header --rusage --field name
|
237 | nq-assert $status = 0
|
238 |
|
239 | nq-run status \
|
240 | time-tool --print-header --rusage --field foo --field bar
|
241 | nq-assert $status = 0
|
242 |
|
243 | nq-run status \
|
244 | time-tool -o _tmp/time-test-1 \
|
245 | --print-header --rusage --stdout DUMMY --tsv --field a --field b
|
246 | nq-assert $status = 0
|
247 |
|
248 | head _tmp/time-test-1
|
249 |
|
250 | echo OK
|
251 | }
|
252 |
|
253 | test-time-helper() {
|
254 | local status
|
255 | local tmp=_tmp/time-helper.txt
|
256 | local th=_devbuild/bin/time-helper
|
257 |
|
258 | # Make some work show up
|
259 | local cmd='{ md5sum */*.md; sleep 0.15; exit 42; } > /dev/null'
|
260 |
|
261 | echo 'will be overwritten' > $tmp
|
262 | cat $tmp
|
263 |
|
264 | nq-run status \
|
265 | $th
|
266 | nq-assert $status != 0 # it's 1, but could be 2
|
267 |
|
268 | nq-run status \
|
269 | $th /bad
|
270 | nq-assert $status = 1
|
271 |
|
272 | nq-run status \
|
273 | $th -o $tmp -d $'\t' -x -e -- sh -c "$cmd"
|
274 | nq-assert $status = 42
|
275 | cat $tmp
|
276 | echo
|
277 |
|
278 | # Now append
|
279 |
|
280 | nq-run status \
|
281 | $th -o $tmp -a -d , -x -e -U -S -M -- sh -c "$cmd"
|
282 | nq-assert $status = 42
|
283 | cat $tmp
|
284 | echo
|
285 |
|
286 | # Error case
|
287 | nq-run status \
|
288 | $th -q
|
289 | nq-assert $status -eq 2
|
290 | }
|
291 |
|
292 | test-time-tsv() {
|
293 | local status
|
294 |
|
295 | local out=_tmp/time-test-zz
|
296 | rm -f -v $out
|
297 |
|
298 | # Similar to what soil/worker.sh does
|
299 | nq-run status \
|
300 | time-tsv -o $out --append -- zz
|
301 | nq-assert $status -eq 1
|
302 |
|
303 | cat $out
|
304 | echo
|
305 | }
|
306 |
|
307 | test-grandchild-memory() {
|
308 | local -a use_mem=( python2 -c 'import sys; ["X" * int(sys.argv[1])]' 10000000 )
|
309 |
|
310 | time-tsv -o /dev/stdout --rusage -- "${use_mem[@]}"
|
311 |
|
312 | # RUSAGE_CHILDREN includes grandchildren!
|
313 | time-tsv -o /dev/stdout --rusage -- sh -c 'echo; "$@"' dummy "${use_mem[@]}"
|
314 |
|
315 | # 'exec' doesn't make a consistent difference, because /bin/sh doesn't use
|
316 | # much memory
|
317 | time-tsv -o /dev/stdout --rusage -- sh -c 'echo; exec "$@"' dummy "${use_mem[@]}"
|
318 | }
|
319 |
|
320 | soil-run() {
|
321 | devtools/byo.sh test $0
|
322 | }
|
323 |
|
324 | task-five "$@"
|