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 | ## BUG bash STDOUT:
|
220 | unlimited
|
221 | unlimited
|
222 | fail
|
223 | ## END
|
224 |
|
225 | #### ulimit -a doesn't take arg
|
226 | case $SH in bash) exit ;; esac
|
227 |
|
228 | ulimit -a 42
|
229 | if test $? -ne 0; then
|
230 | echo 'failure that was expected'
|
231 | fi
|
232 |
|
233 | ## STDOUT:
|
234 | failure that was expected
|
235 | ## END
|
236 | ## BUG bash STDOUT:
|
237 | ## END
|
238 |
|
239 |
|
240 | #### ulimit doesn't accept multiple flags - reduce confusion between shells
|
241 |
|
242 | # - bash, zsh, busybox ash accept multiple "commands", which requires custom
|
243 | # flag parsing, like
|
244 |
|
245 | # ulimit -f 999 -n
|
246 | # ulimit -f 999 -n 888
|
247 | #
|
248 | # - dash and mksh accept a single ARG
|
249 | #
|
250 | # we want to make it clear we're like the latter
|
251 |
|
252 | # can't print all and -f
|
253 | ulimit -f -a >/dev/null
|
254 | echo status=$?
|
255 |
|
256 | ulimit -f -n >/dev/null
|
257 | echo status=$?
|
258 |
|
259 | ulimit -f -n 999 >/dev/null
|
260 | echo status=$?
|
261 |
|
262 | ## STDOUT:
|
263 | status=2
|
264 | status=2
|
265 | status=2
|
266 | ## END
|
267 |
|
268 | ## BUG dash/bash/mksh STDOUT:
|
269 | status=0
|
270 | status=0
|
271 | status=0
|
272 | ## END
|
273 |
|
274 | # zsh is better - it checks that -a and -f are exclusive
|
275 |
|
276 | ## BUG zsh STDOUT:
|
277 | status=1
|
278 | status=0
|
279 | status=0
|
280 | ## END
|
281 |
|
282 |
|
283 | #### YSH readability: ulimit --all the same as ulimit -a
|
284 |
|
285 | case $SH in bash|dash|mksh|zsh) exit ;; esac
|
286 |
|
287 | ulimit -a > short.txt
|
288 | ulimit --all > long.txt
|
289 |
|
290 | wc -l short.txt long.txt
|
291 |
|
292 | diff -u short.txt long.txt
|
293 | echo status=$?
|
294 |
|
295 | ## STDOUT:
|
296 | 8 short.txt
|
297 | 8 long.txt
|
298 | 16 total
|
299 | status=0
|
300 | ## END
|
301 |
|
302 | ## N-I bash/dash/mksh/zsh STDOUT:
|
303 | ## END
|
304 |
|
305 | #### ulimit accepts 'unlimited'
|
306 |
|
307 | for arg in zz unlimited; do
|
308 | echo " arg $arg"
|
309 | ulimit -f
|
310 | echo status=$?
|
311 | ulimit -f $arg
|
312 | if test $? -ne 0; then
|
313 | echo 'FAILED'
|
314 | fi
|
315 | echo
|
316 | done
|
317 | ## STDOUT:
|
318 | arg zz
|
319 | unlimited
|
320 | status=0
|
321 | FAILED
|
322 |
|
323 | arg unlimited
|
324 | unlimited
|
325 | status=0
|
326 |
|
327 | ## END
|
328 |
|
329 |
|
330 | #### ulimit of 2**32, 2**31 (int overflow)
|
331 |
|
332 | echo -n 'one '; ulimit -f
|
333 |
|
334 |
|
335 | ulimit -f $(( 1 << 32 ))
|
336 |
|
337 | echo -n 'two '; ulimit -f
|
338 |
|
339 |
|
340 | # mksh fails because it overflows signed int, turning into negative number
|
341 | ulimit -f $(( 1 << 31 ))
|
342 |
|
343 | echo -n 'three '; ulimit -f
|
344 |
|
345 | ## STDOUT:
|
346 | one unlimited
|
347 | two 4294967296
|
348 | three 2147483648
|
349 | ## END
|
350 | ## BUG mksh STDOUT:
|
351 | one unlimited
|
352 | two 1
|
353 | three 1
|
354 | ## END
|
355 |
|
356 |
|
357 | #### ulimit that is 64 bits
|
358 |
|
359 | # no 64-bit integers
|
360 | case $SH in mksh) exit ;; esac
|
361 |
|
362 | echo -n 'before '; ulimit -f
|
363 |
|
364 | # 1 << 63 overflows signed int
|
365 |
|
366 | # 512 is 1 << 9, so make it 62-9 = 53 bits
|
367 |
|
368 | lim=$(( 1 << 53 ))
|
369 | #echo $lim
|
370 |
|
371 | # bash says this is out of range
|
372 | ulimit -f $lim
|
373 |
|
374 | echo -n 'after '; ulimit -f
|
375 |
|
376 | ## STDOUT:
|
377 | before unlimited
|
378 | after 9007199254740992
|
379 | ## END
|
380 |
|
381 | ## BUG mksh STDOUT:
|
382 | ## END
|
383 |
|
384 |
|
385 | #### arg that would overflow 64 bits is detected
|
386 |
|
387 | # no 64-bit integers
|
388 | case $SH in mksh) exit ;; esac
|
389 |
|
390 | echo -n 'before '; ulimit -f
|
391 |
|
392 | # 1 << 63 overflows signed int
|
393 |
|
394 | lim=$(( (1 << 62) + 1 ))
|
395 | #echo lim=$lim
|
396 |
|
397 | # bash detects that this is out of range
|
398 | # so does osh-cpp, but not osh-cpython
|
399 |
|
400 | ulimit -f $lim
|
401 | echo -n 'after '; ulimit -f
|
402 |
|
403 | ## STDOUT:
|
404 | before unlimited
|
405 | after unlimited
|
406 | ## END
|
407 |
|
408 | ## BUG dash/zsh STDOUT:
|
409 | before unlimited
|
410 | after 1
|
411 | ## END
|
412 |
|
413 | ## BUG mksh STDOUT:
|
414 | ## END
|
415 |
|
416 |
|
417 | #### ulimit -f 1 prevents files larger 512 bytes
|
418 |
|
419 | # dash and zsh give too much spew
|
420 | # mksh gives 512 byte files?
|
421 |
|
422 | #case $SH in dash|zsh|mksh) exit ;; esac
|
423 |
|
424 | rm -f err.txt
|
425 | touch err.txt
|
426 |
|
427 | bytes() {
|
428 | local n=$1
|
429 | local st=0
|
430 | for i in $(seq $n); do
|
431 | echo -n x
|
432 | st=$?
|
433 | if test $st -ne 0; then
|
434 | echo "ERROR: echo failed with status $st" >> err.txt
|
435 | fi
|
436 | done
|
437 | }
|
438 |
|
439 |
|
440 | ulimit -f 1
|
441 |
|
442 | bytes 512 > ok.txt
|
443 | echo 512 status=$?
|
444 |
|
445 | bytes 513 > too-big.txt
|
446 | echo 513 status=$?
|
447 | echo
|
448 |
|
449 | wc --bytes ok.txt too-big.txt
|
450 | echo
|
451 |
|
452 | cat err.txt
|
453 |
|
454 | ## STDOUT:
|
455 | 512 status=0
|
456 | 513 status=0
|
457 |
|
458 | 512 ok.txt
|
459 | 512 too-big.txt
|
460 | 1024 total
|
461 |
|
462 | ERROR: echo failed with status 1
|
463 | ## END
|
464 |
|
465 | ## BUG bash STDOUT:
|
466 | 512 status=0
|
467 | 513 status=0
|
468 |
|
469 | 512 ok.txt
|
470 | 513 too-big.txt
|
471 | 1025 total
|
472 |
|
473 | ## END
|
474 |
|
475 | #### write big file with ulimit
|
476 |
|
477 | # I think this will test write() errors, rather than the final flush() error
|
478 | # (which is currently skipped by C++
|
479 |
|
480 | { echo 'ulimit -f 1'
|
481 | # More than 8 KiB may cause a flush()
|
482 | python2 -c 'print("echo " + "X"*9000 + " >out.txt")'
|
483 | echo 'echo inner=$?'
|
484 | } > big.sh
|
485 |
|
486 | $SH big.sh
|
487 | echo outer=$?
|
488 |
|
489 | ## STDOUT:
|
490 | inner=1
|
491 | outer=0
|
492 | ## END
|
493 |
|
494 |
|
495 | #### ulimit -S for soft limit (default), -H for hard limit
|
496 | case $SH in dash|zsh) exit ;; esac
|
497 |
|
498 | # Note: ulimit -n -S 1111 is OK in osh/dash/mksh, but not bash/zsh
|
499 | # Mus be ulimit -S -n 1111
|
500 |
|
501 | show_state() {
|
502 | local msg=$1
|
503 | echo "$msg"
|
504 | echo -n ' '; ulimit -S -t
|
505 | echo -n ' '; ulimit -H -t
|
506 | echo
|
507 | }
|
508 |
|
509 | show_state 'init'
|
510 |
|
511 | ulimit -S -t 123456
|
512 | show_state '-S'
|
513 |
|
514 | ulimit -H -t 123457
|
515 | show_state '-H'
|
516 |
|
517 | ulimit -t 123455
|
518 | show_state 'no flag'
|
519 |
|
520 | echo 'GET'
|
521 |
|
522 | ulimit -S -t 123454
|
523 | echo -n ' '; ulimit -t
|
524 | echo -n ' '; ulimit -S -t
|
525 | echo -n ' '; ulimit -H -t
|
526 |
|
527 | ## STDOUT:
|
528 | init
|
529 | unlimited
|
530 | unlimited
|
531 |
|
532 | -S
|
533 | 123456
|
534 | unlimited
|
535 |
|
536 | -H
|
537 | 123456
|
538 | 123457
|
539 |
|
540 | no flag
|
541 | 123455
|
542 | 123455
|
543 |
|
544 | GET
|
545 | 123454
|
546 | 123454
|
547 | 123455
|
548 | ## END
|
549 |
|
550 | ## BUG dash/zsh STDOUT:
|
551 | ## END
|
552 |
|
553 | #### Changing resource limit is denied
|
554 |
|
555 | # Not sure why these don't work
|
556 | case $SH in dash|mksh) exit ;; esac
|
557 |
|
558 |
|
559 | flag=-t
|
560 |
|
561 | ulimit -S -H $flag 100
|
562 | echo both=$?
|
563 |
|
564 | ulimit -S $flag 90
|
565 | echo soft=$?
|
566 |
|
567 | ulimit -S $flag 95
|
568 | echo soft=$?
|
569 |
|
570 | ulimit -S $flag 105
|
571 | if test $? -ne 0; then
|
572 | echo soft OK
|
573 | else
|
574 | echo soft fail
|
575 | fi
|
576 |
|
577 | ulimit -H $flag 200
|
578 | if test $? -ne 0; then
|
579 | echo hard OK
|
580 | else
|
581 | echo hard fail
|
582 | fi
|
583 |
|
584 | ## STDOUT:
|
585 | both=0
|
586 | soft=0
|
587 | soft=0
|
588 | soft OK
|
589 | hard OK
|
590 | ## END
|
591 |
|
592 | ## BUG dash/mksh STDOUT:
|
593 | ## END
|