1 | ## oils_failures_allowed: 2
|
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=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:
|
123 | 664
|
124 | 644
|
125 | ## END
|
126 | ## stderr-json: ""
|
127 |
|
128 | #### set umask symbolically
|
129 | umask 0002 # begin in a known state for the test
|
130 | rm -f $TMP/umask-one $TMP/umask-two
|
131 | echo one > $TMP/umask-one
|
132 | umask g-w,o-w
|
133 | echo two > $TMP/umask-two
|
134 | stat -c '%a' $TMP/umask-one $TMP/umask-two
|
135 | ## status: 0
|
136 | ## STDOUT:
|
137 | 664
|
138 | 644
|
139 | ## END
|
140 | ## stderr-json: ""
|
141 |
|
142 | #### ulimit with no flags is like -f
|
143 |
|
144 | ulimit > no-flags.txt
|
145 | echo status=$?
|
146 |
|
147 | ulimit -f > f.txt
|
148 | echo status=$?
|
149 |
|
150 | diff -u no-flags.txt f.txt
|
151 | echo diff=$?
|
152 |
|
153 | # Print everything
|
154 | # ulimit -a
|
155 |
|
156 | ## STDOUT:
|
157 | status=0
|
158 | status=0
|
159 | diff=0
|
160 | ## END
|
161 |
|
162 |
|
163 | #### ulimit too many args
|
164 |
|
165 | ulimit 1 2
|
166 | if test $? -ne 0; then
|
167 | echo pass
|
168 | else
|
169 | echo fail
|
170 | fi
|
171 |
|
172 | #ulimit -f
|
173 |
|
174 | ## STDOUT:
|
175 | pass
|
176 | ## END
|
177 |
|
178 | ## BUG bash/zsh STDOUT:
|
179 | fail
|
180 | ## END
|
181 |
|
182 |
|
183 | #### ulimit negative flag
|
184 |
|
185 | ulimit -f
|
186 |
|
187 | # interpreted as a flag
|
188 | ulimit -f -42
|
189 | if test $? -ne 0; then
|
190 | echo pass
|
191 | else
|
192 | echo fail
|
193 | fi
|
194 |
|
195 | ## STDOUT:
|
196 | unlimited
|
197 | pass
|
198 | ## END
|
199 |
|
200 | #### ulimit negative arg
|
201 |
|
202 | ulimit -f
|
203 |
|
204 | # an arg
|
205 | ulimit -f -- -42
|
206 | if test $? -ne 0; then
|
207 | echo pass
|
208 | else
|
209 | echo fail
|
210 | fi
|
211 |
|
212 | ## STDOUT:
|
213 | unlimited
|
214 | pass
|
215 | ## END
|
216 |
|
217 | ## BUG mksh STDOUT:
|
218 | unlimited
|
219 | fail
|
220 | ## END
|
221 |
|
222 |
|
223 | #### ulimit -a doesn't take arg
|
224 | case $SH in bash) exit ;; esac
|
225 |
|
226 | ulimit -a 42
|
227 | if test $? -ne 0; then
|
228 | echo 'failure that was expected'
|
229 | fi
|
230 |
|
231 | ## STDOUT:
|
232 | failure that was expected
|
233 | ## END
|
234 | ## BUG bash STDOUT:
|
235 | ## END
|
236 |
|
237 |
|
238 | #### ulimit doesn't accept multiple flags - reduce confusion between shells
|
239 |
|
240 | # - bash, zsh, busybox ash accept multiple "commands", which requires custom
|
241 | # flag parsing, like
|
242 |
|
243 | # ulimit -f 999 -n
|
244 | # ulimit -f 999 -n 888
|
245 | #
|
246 | # - dash and mksh accept a single ARG
|
247 | #
|
248 | # we want to make it clear we're like the latter
|
249 |
|
250 | # can't print all and -f
|
251 | ulimit -f -a >/dev/null
|
252 | echo status=$?
|
253 |
|
254 | ulimit -f -n >/dev/null
|
255 | echo status=$?
|
256 |
|
257 | ulimit -f -n 999 >/dev/null
|
258 | echo status=$?
|
259 |
|
260 | ## STDOUT:
|
261 | status=2
|
262 | status=2
|
263 | status=2
|
264 | ## END
|
265 |
|
266 | ## BUG dash/bash/mksh STDOUT:
|
267 | status=0
|
268 | status=0
|
269 | status=0
|
270 | ## END
|
271 |
|
272 | # zsh is better - it checks that -a and -f are exclusive
|
273 |
|
274 | ## BUG zsh STDOUT:
|
275 | status=1
|
276 | status=0
|
277 | status=0
|
278 | ## END
|
279 |
|
280 |
|
281 | #### YSH readability: ulimit --all the same as ulimit -a
|
282 |
|
283 | case $SH in bash|dash|mksh|zsh) exit ;; esac
|
284 |
|
285 | ulimit -a > short.txt
|
286 | ulimit --all > long.txt
|
287 |
|
288 | wc -l short.txt long.txt
|
289 |
|
290 | diff -u short.txt long.txt
|
291 | echo status=$?
|
292 |
|
293 | ## STDOUT:
|
294 | 8 short.txt
|
295 | 8 long.txt
|
296 | 16 total
|
297 | status=0
|
298 | ## END
|
299 |
|
300 | ## N-I bash/dash/mksh/zsh STDOUT:
|
301 | ## END
|
302 |
|
303 | #### ulimit accepts 'unlimited'
|
304 |
|
305 | for arg in zz unlimited; do
|
306 | echo " arg $arg"
|
307 | ulimit -f
|
308 | echo status=$?
|
309 | ulimit -f $arg
|
310 | if test $? -ne 0; then
|
311 | echo 'FAILED'
|
312 | fi
|
313 | echo
|
314 | done
|
315 | ## STDOUT:
|
316 | arg zz
|
317 | unlimited
|
318 | status=0
|
319 | FAILED
|
320 |
|
321 | arg unlimited
|
322 | unlimited
|
323 | status=0
|
324 |
|
325 | ## END
|
326 |
|
327 |
|
328 | #### ulimit of 2**32, 2**31 (int overflow)
|
329 |
|
330 | echo -n 'one '; ulimit -f
|
331 |
|
332 |
|
333 | ulimit -f $(( 1 << 32 ))
|
334 |
|
335 | echo -n 'two '; ulimit -f
|
336 |
|
337 |
|
338 | # mksh fails because it overflows signed int, turning into negative number
|
339 | ulimit -f $(( 1 << 31 ))
|
340 |
|
341 | echo -n 'three '; ulimit -f
|
342 |
|
343 | ## STDOUT:
|
344 | one unlimited
|
345 | two 4294967296
|
346 | three 2147483648
|
347 | ## END
|
348 | ## BUG mksh STDOUT:
|
349 | one unlimited
|
350 | two 1
|
351 | three 1
|
352 | ## END
|
353 |
|
354 |
|
355 | #### ulimit that is 64 bits
|
356 |
|
357 | # no 64-bit integers
|
358 | case $SH in mksh) exit ;; esac
|
359 |
|
360 | echo -n 'before '; ulimit -f
|
361 |
|
362 | # 1 << 63 overflows signed int
|
363 |
|
364 | # 512 is 1 << 9, so make it 62-9 = 53 bits
|
365 |
|
366 | lim=$(( 1 << 53 ))
|
367 | #echo $lim
|
368 |
|
369 | # bash says this is out of range
|
370 | ulimit -f $lim
|
371 |
|
372 | echo -n 'after '; ulimit -f
|
373 |
|
374 | ## STDOUT:
|
375 | before unlimited
|
376 | after 9007199254740992
|
377 | ## END
|
378 |
|
379 | ## BUG mksh STDOUT:
|
380 | ## END
|
381 |
|
382 |
|
383 | #### arg that would overflow 64 bits is detected
|
384 |
|
385 | # no 64-bit integers
|
386 | case $SH in mksh) exit ;; esac
|
387 |
|
388 | echo -n 'before '; ulimit -f
|
389 |
|
390 | # 1 << 63 overflows signed int
|
391 |
|
392 | lim=$(( (1 << 62) + 1 ))
|
393 | #echo lim=$lim
|
394 |
|
395 | # bash detects that this is out of range
|
396 | # so does osh-cpp, but not osh-cpython
|
397 |
|
398 | ulimit -f $lim
|
399 | echo -n 'after '; ulimit -f
|
400 |
|
401 | ## STDOUT:
|
402 | before unlimited
|
403 | after unlimited
|
404 | ## END
|
405 |
|
406 | ## BUG dash/zsh STDOUT:
|
407 | before unlimited
|
408 | after 1
|
409 | ## END
|
410 |
|
411 | ## BUG mksh STDOUT:
|
412 | ## END
|
413 |
|
414 |
|
415 | #### ulimit -f 1 prevents files larger 512 bytes
|
416 |
|
417 | # dash and zsh give too much spew
|
418 | # mksh gives 512 byte files?
|
419 |
|
420 | #case $SH in dash|zsh|mksh) exit ;; esac
|
421 |
|
422 | rm -f err.txt
|
423 | touch err.txt
|
424 |
|
425 | bytes() {
|
426 | local n=$1
|
427 | local st=0
|
428 | for i in $(seq $n); do
|
429 | echo -n x
|
430 | st=$?
|
431 | if test $st -ne 0; then
|
432 | echo "ERROR: echo failed with status $st" >> err.txt
|
433 | fi
|
434 | done
|
435 | }
|
436 |
|
437 |
|
438 | ulimit -f 1
|
439 |
|
440 | bytes 512 > ok.txt
|
441 | echo 512 status=$?
|
442 |
|
443 | bytes 513 > too-big.txt
|
444 | echo 513 status=$?
|
445 | echo
|
446 |
|
447 | wc --bytes ok.txt too-big.txt
|
448 | echo
|
449 |
|
450 | cat err.txt
|
451 |
|
452 | ## STDOUT:
|
453 | 512 status=0
|
454 | 513 status=0
|
455 |
|
456 | 512 ok.txt
|
457 | 512 too-big.txt
|
458 | 1024 total
|
459 |
|
460 | ERROR: echo failed with status 1
|
461 | ## END
|
462 |
|
463 | ## BUG bash STDOUT:
|
464 | 512 status=0
|
465 | 513 status=0
|
466 |
|
467 | 512 ok.txt
|
468 | 513 too-big.txt
|
469 | 1025 total
|
470 |
|
471 | ## END
|
472 |
|
473 | #### write big file with ulimit
|
474 |
|
475 | # I think this will test write() errors, rather than the final flush() error
|
476 | # (which is currently skipped by C++
|
477 |
|
478 | { echo 'ulimit -f 1'
|
479 | # More than 8 KiB may cause a flush()
|
480 | python2 -c 'print("echo " + "X"*9000 + " >out.txt")'
|
481 | echo 'echo inner=$?'
|
482 | } > big.sh
|
483 |
|
484 | $SH big.sh
|
485 | echo outer=$?
|
486 |
|
487 | ## STDOUT:
|
488 | inner=1
|
489 | outer=0
|
490 | ## END
|
491 |
|
492 |
|
493 | #### ulimit -S for soft limit (default), -H for hard limit
|
494 | case $SH in dash|zsh) exit ;; esac
|
495 |
|
496 | # Note: ulimit -n -S 1111 is OK in osh/dash/mksh, but not bash/zsh
|
497 | # Mus be ulimit -S -n 1111
|
498 |
|
499 | show_state() {
|
500 | local msg=$1
|
501 | echo "$msg"
|
502 | echo -n ' '; ulimit -S -t
|
503 | echo -n ' '; ulimit -H -t
|
504 | echo
|
505 | }
|
506 |
|
507 | show_state 'init'
|
508 |
|
509 | ulimit -S -t 123456
|
510 | show_state '-S'
|
511 |
|
512 | ulimit -H -t 123457
|
513 | show_state '-H'
|
514 |
|
515 | ulimit -t 123455
|
516 | show_state 'no flag'
|
517 |
|
518 | echo 'GET'
|
519 |
|
520 | ulimit -S -t 123454
|
521 | echo -n ' '; ulimit -t
|
522 | echo -n ' '; ulimit -S -t
|
523 | echo -n ' '; ulimit -H -t
|
524 |
|
525 | ## STDOUT:
|
526 | init
|
527 | unlimited
|
528 | unlimited
|
529 |
|
530 | -S
|
531 | 123456
|
532 | unlimited
|
533 |
|
534 | -H
|
535 | 123456
|
536 | 123457
|
537 |
|
538 | no flag
|
539 | 123455
|
540 | 123455
|
541 |
|
542 | GET
|
543 | 123454
|
544 | 123454
|
545 | 123455
|
546 | ## END
|
547 |
|
548 | ## BUG dash/zsh STDOUT:
|
549 | ## END
|
550 |
|
551 | #### Changing resource limit is denied
|
552 |
|
553 | # Not sure why these don't work
|
554 | case $SH in dash|mksh) exit ;; esac
|
555 |
|
556 |
|
557 | flag=-t
|
558 |
|
559 | ulimit -S -H $flag 100
|
560 | echo both=$?
|
561 |
|
562 | ulimit -S $flag 90
|
563 | echo soft=$?
|
564 |
|
565 | ulimit -S $flag 95
|
566 | echo soft=$?
|
567 |
|
568 | ulimit -S $flag 105
|
569 | if test $? -ne 0; then
|
570 | echo soft OK
|
571 | else
|
572 | echo soft fail
|
573 | fi
|
574 |
|
575 | ulimit -H $flag 200
|
576 | if test $? -ne 0; then
|
577 | echo hard OK
|
578 | else
|
579 | echo hard fail
|
580 | fi
|
581 |
|
582 | ## STDOUT:
|
583 | both=0
|
584 | soft=0
|
585 | soft=0
|
586 | soft OK
|
587 | hard OK
|
588 | ## END
|
589 |
|
590 | ## BUG dash/mksh STDOUT:
|
591 | ## END
|
592 |
|
593 | #### ulimit -n limits file descriptors
|
594 |
|
595 | # OSH bug
|
596 | # https://oilshell.zulipchat.com/#narrow/channel/502349-osh/topic/alpine.20build.20failures.20-.20make.20-.20ulimit.20-n.2064/with/519691301
|
597 |
|
598 | $SH -c 'ulimit -n 64; echo hi >out'
|
599 | echo status=$?
|
600 |
|
601 | $SH -c 'ulimit -n 0; echo hi >out'
|
602 | echo status=$?
|
603 |
|
604 | ## STDOUT:
|
605 | status=0
|
606 | status=1
|
607 | ## END
|
608 |
|
609 | ## OK dash STDOUT:
|
610 | status=0
|
611 | status=2
|
612 | ## END
|