1 | ## oils_failures_allowed: 1
|
2 | ## compare_shells: dash bash mksh zsh
|
3 |
|
4 | #### exec builtin
|
5 | exec echo hi
|
6 | ## stdout: hi
|
7 |
|
8 | #### exec builtin with redirects
|
9 | exec 1>&2
|
10 | echo 'to stderr'
|
11 | ## stdout-json: ""
|
12 | ## stderr: to stderr
|
13 |
|
14 | #### exec builtin with here doc
|
15 | # This has in a separate file because both code and data can be read from
|
16 | # stdin.
|
17 | $SH $REPO_ROOT/spec/bin/builtins-exec-here-doc-helper.sh
|
18 | ## STDOUT:
|
19 | x=one
|
20 | y=two
|
21 | DONE
|
22 | ## END
|
23 |
|
24 | #### exec builtin accepts --
|
25 | exec -- echo hi
|
26 | ## STDOUT:
|
27 | hi
|
28 | ## END
|
29 | ## BUG dash status: 127
|
30 | ## BUG dash stdout-json: ""
|
31 |
|
32 | #### exec -- 2>&1
|
33 | exec -- 3>&1
|
34 | echo stdout 1>&3
|
35 | ## STDOUT:
|
36 | stdout
|
37 | ## END
|
38 | ## BUG dash status: 127
|
39 | ## BUG dash stdout-json: ""
|
40 | ## BUG mksh status: -11
|
41 | ## BUG mksh stdout-json: ""
|
42 |
|
43 | #### Exit out of function
|
44 | f() { exit 3; }
|
45 | f
|
46 | exit 4
|
47 | ## status: 3
|
48 |
|
49 | #### Exit builtin with invalid arg
|
50 | exit invalid
|
51 | # Rationale: runtime errors are 1
|
52 | ## status: 1
|
53 | ## OK dash/bash status: 2
|
54 | ## BUG zsh status: 0
|
55 |
|
56 | #### Exit builtin with too many args
|
57 | # This is a parse error in OSH.
|
58 | exit 7 8 9
|
59 | echo status=$?
|
60 | ## status: 2
|
61 | ## stdout-json: ""
|
62 | ## BUG bash/zsh status: 0
|
63 | ## BUG bash/zsh stdout: status=1
|
64 | ## BUG dash status: 7
|
65 | ## BUG dash stdout-json: ""
|
66 | ## OK mksh status: 1
|
67 | ## OK mksh stdout-json: ""
|
68 |
|
69 | #### time with brace group argument
|
70 |
|
71 | err=_tmp/time-$(basename $SH).txt
|
72 | {
|
73 | time {
|
74 | sleep 0.01
|
75 | sleep 0.02
|
76 | }
|
77 | } 2> $err
|
78 |
|
79 | grep --only-matching user $err
|
80 | echo result=$?
|
81 |
|
82 | # Regression: check fractional seconds
|
83 | gawk '
|
84 | BEGIN { ok = 0 }
|
85 | match( $0, /\.([0-9]+)/, m) {
|
86 | if (m[1] > 0) { # check fractional seconds
|
87 | ok = 1
|
88 | }
|
89 | }
|
90 | END { if (ok) { print "non-zero" } }
|
91 | ' $err
|
92 |
|
93 | ## status: 0
|
94 | ## STDOUT:
|
95 | user
|
96 | result=0
|
97 | non-zero
|
98 | ## END
|
99 |
|
100 | # time doesn't accept a block?
|
101 | ## BUG zsh STDOUT:
|
102 | result=1
|
103 | ## END
|
104 |
|
105 | # dash doesn't have time keyword
|
106 | ## N-I dash status: 2
|
107 | ## N-I dash stdout-json: ""
|
108 |
|
109 |
|
110 | #### get umask
|
111 | umask | grep '[0-9]\+' # check for digits
|
112 | ## status: 0
|
113 |
|
114 | #### set umask in octal
|
115 | rm -f $TMP/umask-one $TMP/umask-two
|
116 | umask 0002
|
117 | echo one > $TMP/umask-one
|
118 | umask 0022
|
119 | echo two > $TMP/umask-two
|
120 | stat -c '%a' $TMP/umask-one $TMP/umask-two
|
121 | ## status: 0
|
122 | ## stdout-json: "664\n644\n"
|
123 | ## stderr-json: ""
|
124 |
|
125 | #### set umask symbolically
|
126 | umask 0002 # begin in a known state for the test
|
127 | rm -f $TMP/umask-one $TMP/umask-two
|
128 | echo one > $TMP/umask-one
|
129 | umask g-w,o-w
|
130 | echo two > $TMP/umask-two
|
131 | stat -c '%a' $TMP/umask-one $TMP/umask-two
|
132 | ## status: 0
|
133 | ## STDOUT:
|
134 | 664
|
135 | 644
|
136 | ## END
|
137 | ## stderr-json: ""
|
138 |
|
139 | #### ulimit with no flags is like -f
|
140 |
|
141 | ulimit > no-flags.txt
|
142 | echo status=$?
|
143 |
|
144 | ulimit -f > f.txt
|
145 | echo status=$?
|
146 |
|
147 | diff -u no-flags.txt f.txt
|
148 | echo diff=$?
|
149 |
|
150 | # Print everything
|
151 | # ulimit -a
|
152 |
|
153 | ## STDOUT:
|
154 | status=0
|
155 | status=0
|
156 | diff=0
|
157 | ## END
|
158 |
|
159 |
|
160 | #### ulimit too many args
|
161 |
|
162 | ulimit 1 2
|
163 | if test $? -ne 0; then
|
164 | echo pass
|
165 | else
|
166 | echo fail
|
167 | fi
|
168 |
|
169 | #ulimit -f
|
170 |
|
171 | ## STDOUT:
|
172 | pass
|
173 | ## END
|
174 |
|
175 | ## BUG bash/zsh STDOUT:
|
176 | fail
|
177 | ## END
|
178 |
|
179 |
|
180 | #### ulimit negative flag
|
181 |
|
182 | ulimit -f
|
183 |
|
184 | # interpreted as a flag
|
185 | ulimit -f -42
|
186 | if test $? -ne 0; then
|
187 | echo pass
|
188 | else
|
189 | echo fail
|
190 | fi
|
191 |
|
192 | ## STDOUT:
|
193 | unlimited
|
194 | pass
|
195 | ## END
|
196 |
|
197 | #### ulimit negative arg
|
198 |
|
199 | ulimit -f
|
200 |
|
201 | # an arg
|
202 | ulimit -f -- -42
|
203 | if test $? -ne 0; then
|
204 | echo pass
|
205 | else
|
206 | echo fail
|
207 | fi
|
208 |
|
209 | ## STDOUT:
|
210 | unlimited
|
211 | pass
|
212 | ## END
|
213 |
|
214 | ## BUG mksh STDOUT:
|
215 | unlimited
|
216 | fail
|
217 | ## END
|
218 |
|
219 |
|
220 | #### ulimit -a doesn't take arg
|
221 | case $SH in bash) exit ;; esac
|
222 |
|
223 | ulimit -a 42
|
224 | if test $? -ne 0; then
|
225 | echo 'failure that was expected'
|
226 | fi
|
227 |
|
228 | ## STDOUT:
|
229 | failure that was expected
|
230 | ## END
|
231 | ## BUG bash STDOUT:
|
232 | ## END
|
233 |
|
234 |
|
235 | #### ulimit doesn't accept multiple flags - reduce confusion between shells
|
236 |
|
237 | # - bash, zsh, busybox ash accept multiple "commands", which requires custom
|
238 | # flag parsing, like
|
239 |
|
240 | # ulimit -f 999 -n
|
241 | # ulimit -f 999 -n 888
|
242 | #
|
243 | # - dash and mksh accept a single ARG
|
244 | #
|
245 | # we want to make it clear we're like the latter
|
246 |
|
247 | # can't print all and -f
|
248 | ulimit -f -a >/dev/null
|
249 | echo status=$?
|
250 |
|
251 | ulimit -f -n >/dev/null
|
252 | echo status=$?
|
253 |
|
254 | ulimit -f -n 999 >/dev/null
|
255 | echo status=$?
|
256 |
|
257 | ## STDOUT:
|
258 | status=2
|
259 | status=2
|
260 | status=2
|
261 | ## END
|
262 |
|
263 | ## BUG dash/bash/mksh STDOUT:
|
264 | status=0
|
265 | status=0
|
266 | status=0
|
267 | ## END
|
268 |
|
269 | # zsh is better - it checks that -a and -f are exclusive
|
270 |
|
271 | ## BUG zsh STDOUT:
|
272 | status=1
|
273 | status=0
|
274 | status=0
|
275 | ## END
|
276 |
|
277 |
|
278 | #### YSH readability: ulimit --all the same as ulimit -a
|
279 |
|
280 | case $SH in bash|dash|mksh|zsh) exit ;; esac
|
281 |
|
282 | ulimit -a > short.txt
|
283 | ulimit --all > long.txt
|
284 |
|
285 | wc -l short.txt long.txt
|
286 |
|
287 | diff -u short.txt long.txt
|
288 | echo status=$?
|
289 |
|
290 | ## STDOUT:
|
291 | 8 short.txt
|
292 | 8 long.txt
|
293 | 16 total
|
294 | status=0
|
295 | ## END
|
296 |
|
297 | ## N-I bash/dash/mksh/zsh STDOUT:
|
298 | ## END
|
299 |
|
300 | #### ulimit accepts 'unlimited'
|
301 |
|
302 | for arg in zz unlimited; do
|
303 | echo " arg $arg"
|
304 | ulimit -f
|
305 | echo status=$?
|
306 | ulimit -f $arg
|
307 | if test $? -ne 0; then
|
308 | echo 'FAILED'
|
309 | fi
|
310 | echo
|
311 | done
|
312 | ## STDOUT:
|
313 | arg zz
|
314 | unlimited
|
315 | status=0
|
316 | FAILED
|
317 |
|
318 | arg unlimited
|
319 | unlimited
|
320 | status=0
|
321 |
|
322 | ## END
|
323 |
|
324 |
|
325 | #### ulimit of 2**32, 2**31 (int overflow)
|
326 |
|
327 | echo -n 'one '; ulimit -f
|
328 |
|
329 |
|
330 | ulimit -f $(( 1 << 32 ))
|
331 |
|
332 | echo -n 'two '; ulimit -f
|
333 |
|
334 |
|
335 | # mksh fails because it overflows signed int, turning into negative number
|
336 | ulimit -f $(( 1 << 31 ))
|
337 |
|
338 | echo -n 'three '; ulimit -f
|
339 |
|
340 | ## STDOUT:
|
341 | one unlimited
|
342 | two 4294967296
|
343 | three 2147483648
|
344 | ## END
|
345 | ## BUG mksh STDOUT:
|
346 | one unlimited
|
347 | two 1
|
348 | three 1
|
349 | ## END
|
350 |
|
351 |
|
352 | #### ulimit that is 64 bits
|
353 |
|
354 | # no 64-bit integers
|
355 | case $SH in mksh) exit ;; esac
|
356 |
|
357 | echo -n 'before '; ulimit -f
|
358 |
|
359 | # 1 << 63 overflows signed int
|
360 |
|
361 | # 512 is 1 << 9, so make it 62-9 = 53 bits
|
362 |
|
363 | lim=$(( 1 << 53 ))
|
364 | #echo $lim
|
365 |
|
366 | # bash says this is out of range
|
367 | ulimit -f $lim
|
368 |
|
369 | echo -n 'after '; ulimit -f
|
370 |
|
371 | ## STDOUT:
|
372 | before unlimited
|
373 | after 9007199254740992
|
374 | ## END
|
375 |
|
376 | ## BUG mksh STDOUT:
|
377 | ## END
|
378 |
|
379 |
|
380 | #### arg that would overflow 64 bits is detected
|
381 |
|
382 | # no 64-bit integers
|
383 | case $SH in mksh) exit ;; esac
|
384 |
|
385 | echo -n 'before '; ulimit -f
|
386 |
|
387 | # 1 << 63 overflows signed int
|
388 |
|
389 | lim=$(( (1 << 62) + 1 ))
|
390 | #echo lim=$lim
|
391 |
|
392 | # bash detects that this is out of range
|
393 | # so does osh-cpp, but not osh-cpython
|
394 |
|
395 | ulimit -f $lim
|
396 | echo -n 'after '; ulimit -f
|
397 |
|
398 | ## STDOUT:
|
399 | before unlimited
|
400 | after unlimited
|
401 | ## END
|
402 |
|
403 | ## BUG dash/zsh STDOUT:
|
404 | before unlimited
|
405 | after 1
|
406 | ## END
|
407 |
|
408 | ## BUG mksh STDOUT:
|
409 | ## END
|
410 |
|
411 |
|
412 | #### ulimit -f 1 prevents files larger 512 bytes
|
413 |
|
414 | # dash and zsh give too much spew
|
415 | # mksh gives 512 byte files?
|
416 |
|
417 | #case $SH in dash|zsh|mksh) exit ;; esac
|
418 |
|
419 | rm -f err.txt
|
420 | touch err.txt
|
421 |
|
422 | bytes() {
|
423 | local n=$1
|
424 | local st=0
|
425 | for i in $(seq $n); do
|
426 | echo -n x
|
427 | st=$?
|
428 | if test $st -ne 0; then
|
429 | echo "ERROR: echo failed with status $st" >> err.txt
|
430 | fi
|
431 | done
|
432 | }
|
433 |
|
434 |
|
435 | ulimit -f 1
|
436 |
|
437 | bytes 512 > ok.txt
|
438 | echo 512 status=$?
|
439 |
|
440 | bytes 513 > too-big.txt
|
441 | echo 513 status=$?
|
442 | echo
|
443 |
|
444 | wc --bytes ok.txt too-big.txt
|
445 | echo
|
446 |
|
447 | cat err.txt
|
448 |
|
449 | ## STDOUT:
|
450 | 512 status=0
|
451 | 513 status=0
|
452 |
|
453 | 512 ok.txt
|
454 | 512 too-big.txt
|
455 | 1024 total
|
456 |
|
457 | ERROR: echo failed with status 1
|
458 | ## END
|
459 |
|
460 | ## BUG bash STDOUT:
|
461 | 512 status=0
|
462 | 513 status=0
|
463 |
|
464 | 512 ok.txt
|
465 | 513 too-big.txt
|
466 | 1025 total
|
467 |
|
468 | ## END
|
469 |
|
470 | #### write big file with ulimit
|
471 |
|
472 | # I think this will test write() errors, rather than the final flush() error
|
473 | # (which is currently skipped by C++
|
474 |
|
475 | { echo 'ulimit -f 1'
|
476 | # More than 8 KiB may cause a flush()
|
477 | python2 -c 'print("echo " + "X"*9000 + " >out.txt")'
|
478 | echo 'echo inner=$?'
|
479 | } > big.sh
|
480 |
|
481 | $SH big.sh
|
482 | echo outer=$?
|
483 |
|
484 | ## STDOUT:
|
485 | inner=1
|
486 | outer=0
|
487 | ## END
|
488 |
|
489 |
|
490 | #### ulimit -S for soft limit (default), -H for hard limit
|
491 | case $SH in dash|zsh) exit ;; esac
|
492 |
|
493 | # Note: ulimit -n -S 1111 is OK in osh/dash/mksh, but not bash/zsh
|
494 | # Mus be ulimit -S -n 1111
|
495 |
|
496 | show_state() {
|
497 | local msg=$1
|
498 | echo "$msg"
|
499 | echo -n ' '; ulimit -S -t
|
500 | echo -n ' '; ulimit -H -t
|
501 | echo
|
502 | }
|
503 |
|
504 | show_state 'init'
|
505 |
|
506 | ulimit -S -t 123456
|
507 | show_state '-S'
|
508 |
|
509 | ulimit -H -t 123457
|
510 | show_state '-H'
|
511 |
|
512 | ulimit -t 123455
|
513 | show_state 'no flag'
|
514 |
|
515 | echo 'GET'
|
516 |
|
517 | ulimit -S -t 123454
|
518 | echo -n ' '; ulimit -t
|
519 | echo -n ' '; ulimit -S -t
|
520 | echo -n ' '; ulimit -H -t
|
521 |
|
522 | ## STDOUT:
|
523 | init
|
524 | unlimited
|
525 | unlimited
|
526 |
|
527 | -S
|
528 | 123456
|
529 | unlimited
|
530 |
|
531 | -H
|
532 | 123456
|
533 | 123457
|
534 |
|
535 | no flag
|
536 | 123455
|
537 | 123455
|
538 |
|
539 | GET
|
540 | 123454
|
541 | 123454
|
542 | 123455
|
543 | ## END
|
544 |
|
545 | ## BUG dash/zsh STDOUT:
|
546 | ## END
|
547 |
|
548 | #### Changing resource limit is denied
|
549 |
|
550 | # Not sure why these don't work
|
551 | case $SH in dash|mksh) exit ;; esac
|
552 |
|
553 |
|
554 | flag=-t
|
555 |
|
556 | ulimit -S -H $flag 100
|
557 | echo both=$?
|
558 |
|
559 | ulimit -S $flag 90
|
560 | echo soft=$?
|
561 |
|
562 | ulimit -S $flag 95
|
563 | echo soft=$?
|
564 |
|
565 | ulimit -S $flag 105
|
566 | if test $? -ne 0; then
|
567 | echo soft OK
|
568 | else
|
569 | echo soft fail
|
570 | fi
|
571 |
|
572 | ulimit -H $flag 200
|
573 | if test $? -ne 0; then
|
574 | echo hard OK
|
575 | else
|
576 | echo hard fail
|
577 | fi
|
578 |
|
579 | ## STDOUT:
|
580 | both=0
|
581 | soft=0
|
582 | soft=0
|
583 | soft OK
|
584 | hard OK
|
585 | ## END
|
586 |
|
587 | ## BUG dash/mksh STDOUT:
|
588 | ## END
|