OILS / spec / builtin-process.test.sh View on Github | oilshell.org

593 lines, 265 significant
1## oils_failures_allowed: 1
2## compare_shells: dash bash mksh zsh
3
4#### exec builtin
5exec echo hi
6## stdout: hi
7
8#### exec builtin with redirects
9exec 1>&2
10echo '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:
19x=one
20y=two
21DONE
22## END
23
24#### exec builtin accepts --
25exec -- echo hi
26## STDOUT:
27hi
28## END
29## BUG dash status: 127
30## BUG dash stdout-json: ""
31
32#### exec -- 2>&1
33exec -- 3>&1
34echo stdout 1>&3
35## STDOUT:
36stdout
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
44f() { exit 3; }
45f
46exit 4
47## status: 3
48
49#### Exit builtin with invalid arg
50exit 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.
58exit 7 8 9
59echo 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
71err=_tmp/time-$(basename $SH).txt
72{
73 time {
74 sleep 0.01
75 sleep 0.02
76 }
77} 2> $err
78
79grep --only-matching user $err
80echo result=$?
81
82# Regression: check fractional seconds
83gawk '
84BEGIN { ok = 0 }
85match( $0, /\.([0-9]+)/, m) {
86 if (m[1] > 0) { # check fractional seconds
87 ok = 1
88 }
89}
90END { if (ok) { print "non-zero" } }
91' $err
92
93## status: 0
94## STDOUT:
95user
96result=0
97non-zero
98## END
99
100# time doesn't accept a block?
101## BUG zsh STDOUT:
102result=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
111umask | grep '[0-9]\+' # check for digits
112## status: 0
113
114#### set umask in octal
115rm -f $TMP/umask-one $TMP/umask-two
116umask 0002
117echo one > $TMP/umask-one
118umask 0022
119echo two > $TMP/umask-two
120stat -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
126umask 0002 # begin in a known state for the test
127rm -f $TMP/umask-one $TMP/umask-two
128echo one > $TMP/umask-one
129umask g-w,o-w
130echo two > $TMP/umask-two
131stat -c '%a' $TMP/umask-one $TMP/umask-two
132## status: 0
133## STDOUT:
134664
135644
136## END
137## stderr-json: ""
138
139#### ulimit with no flags is like -f
140
141ulimit > no-flags.txt
142echo status=$?
143
144ulimit -f > f.txt
145echo status=$?
146
147diff -u no-flags.txt f.txt
148echo diff=$?
149
150# Print everything
151# ulimit -a
152
153## STDOUT:
154status=0
155status=0
156diff=0
157## END
158
159
160#### ulimit too many args
161
162ulimit 1 2
163if test $? -ne 0; then
164 echo pass
165else
166 echo fail
167fi
168
169#ulimit -f
170
171## STDOUT:
172pass
173## END
174
175## BUG bash/zsh STDOUT:
176fail
177## END
178
179
180#### ulimit negative flag
181
182ulimit -f
183
184# interpreted as a flag
185ulimit -f -42
186if test $? -ne 0; then
187 echo pass
188else
189 echo fail
190fi
191
192## STDOUT:
193unlimited
194pass
195## END
196
197#### ulimit negative arg
198
199ulimit -f
200
201# an arg
202ulimit -f -- -42
203if test $? -ne 0; then
204 echo pass
205else
206 echo fail
207fi
208
209## STDOUT:
210unlimited
211pass
212## END
213
214## BUG mksh STDOUT:
215unlimited
216fail
217## END
218
219## BUG bash STDOUT:
220unlimited
221unlimited
222fail
223## END
224
225#### ulimit -a doesn't take arg
226case $SH in bash) exit ;; esac
227
228ulimit -a 42
229if test $? -ne 0; then
230 echo 'failure that was expected'
231fi
232
233## STDOUT:
234failure 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
253ulimit -f -a >/dev/null
254echo status=$?
255
256ulimit -f -n >/dev/null
257echo status=$?
258
259ulimit -f -n 999 >/dev/null
260echo status=$?
261
262## STDOUT:
263status=2
264status=2
265status=2
266## END
267
268## BUG dash/bash/mksh STDOUT:
269status=0
270status=0
271status=0
272## END
273
274# zsh is better - it checks that -a and -f are exclusive
275
276## BUG zsh STDOUT:
277status=1
278status=0
279status=0
280## END
281
282
283#### YSH readability: ulimit --all the same as ulimit -a
284
285case $SH in bash|dash|mksh|zsh) exit ;; esac
286
287ulimit -a > short.txt
288ulimit --all > long.txt
289
290wc -l short.txt long.txt
291
292diff -u short.txt long.txt
293echo status=$?
294
295## STDOUT:
296 8 short.txt
297 8 long.txt
298 16 total
299status=0
300## END
301
302## N-I bash/dash/mksh/zsh STDOUT:
303## END
304
305#### ulimit accepts 'unlimited'
306
307for 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
316done
317## STDOUT:
318 arg zz
319unlimited
320status=0
321FAILED
322
323 arg unlimited
324unlimited
325status=0
326
327## END
328
329
330#### ulimit of 2**32, 2**31 (int overflow)
331
332echo -n 'one '; ulimit -f
333
334
335ulimit -f $(( 1 << 32 ))
336
337echo -n 'two '; ulimit -f
338
339
340# mksh fails because it overflows signed int, turning into negative number
341ulimit -f $(( 1 << 31 ))
342
343echo -n 'three '; ulimit -f
344
345## STDOUT:
346one unlimited
347two 4294967296
348three 2147483648
349## END
350## BUG mksh STDOUT:
351one unlimited
352two 1
353three 1
354## END
355
356
357#### ulimit that is 64 bits
358
359# no 64-bit integers
360case $SH in mksh) exit ;; esac
361
362echo -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
368lim=$(( 1 << 53 ))
369#echo $lim
370
371# bash says this is out of range
372ulimit -f $lim
373
374echo -n 'after '; ulimit -f
375
376## STDOUT:
377before unlimited
378after 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
388case $SH in mksh) exit ;; esac
389
390echo -n 'before '; ulimit -f
391
392# 1 << 63 overflows signed int
393
394lim=$(( (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
400ulimit -f $lim
401echo -n 'after '; ulimit -f
402
403## STDOUT:
404before unlimited
405after unlimited
406## END
407
408## BUG dash/zsh STDOUT:
409before unlimited
410after 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
424rm -f err.txt
425touch err.txt
426
427bytes() {
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
440ulimit -f 1
441
442bytes 512 > ok.txt
443echo 512 status=$?
444
445bytes 513 > too-big.txt
446echo 513 status=$?
447echo
448
449wc --bytes ok.txt too-big.txt
450echo
451
452cat err.txt
453
454## STDOUT:
455512 status=0
456513 status=0
457
458 512 ok.txt
459 512 too-big.txt
4601024 total
461
462ERROR: echo failed with status 1
463## END
464
465## BUG bash STDOUT:
466512 status=0
467513 status=0
468
469 512 ok.txt
470 513 too-big.txt
4711025 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
487echo outer=$?
488
489## STDOUT:
490inner=1
491outer=0
492## END
493
494
495#### ulimit -S for soft limit (default), -H for hard limit
496case $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
501show_state() {
502 local msg=$1
503 echo "$msg"
504 echo -n ' '; ulimit -S -t
505 echo -n ' '; ulimit -H -t
506 echo
507}
508
509show_state 'init'
510
511ulimit -S -t 123456
512show_state '-S'
513
514ulimit -H -t 123457
515show_state '-H'
516
517ulimit -t 123455
518show_state 'no flag'
519
520echo 'GET'
521
522ulimit -S -t 123454
523echo -n ' '; ulimit -t
524echo -n ' '; ulimit -S -t
525echo -n ' '; ulimit -H -t
526
527## STDOUT:
528init
529 unlimited
530 unlimited
531
532-S
533 123456
534 unlimited
535
536-H
537 123456
538 123457
539
540no flag
541 123455
542 123455
543
544GET
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
556case $SH in dash|mksh) exit ;; esac
557
558
559flag=-t
560
561ulimit -S -H $flag 100
562echo both=$?
563
564ulimit -S $flag 90
565echo soft=$?
566
567ulimit -S $flag 95
568echo soft=$?
569
570ulimit -S $flag 105
571if test $? -ne 0; then
572 echo soft OK
573else
574 echo soft fail
575fi
576
577ulimit -H $flag 200
578if test $? -ne 0; then
579 echo hard OK
580else
581 echo hard fail
582fi
583
584## STDOUT:
585both=0
586soft=0
587soft=0
588soft OK
589hard OK
590## END
591
592## BUG dash/mksh STDOUT:
593## END