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

588 lines, 262 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
220#### ulimit -a doesn't take arg
221case $SH in bash) exit ;; esac
222
223ulimit -a 42
224if test $? -ne 0; then
225 echo 'failure that was expected'
226fi
227
228## STDOUT:
229failure 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
248ulimit -f -a >/dev/null
249echo status=$?
250
251ulimit -f -n >/dev/null
252echo status=$?
253
254ulimit -f -n 999 >/dev/null
255echo status=$?
256
257## STDOUT:
258status=2
259status=2
260status=2
261## END
262
263## BUG dash/bash/mksh STDOUT:
264status=0
265status=0
266status=0
267## END
268
269# zsh is better - it checks that -a and -f are exclusive
270
271## BUG zsh STDOUT:
272status=1
273status=0
274status=0
275## END
276
277
278#### YSH readability: ulimit --all the same as ulimit -a
279
280case $SH in bash|dash|mksh|zsh) exit ;; esac
281
282ulimit -a > short.txt
283ulimit --all > long.txt
284
285wc -l short.txt long.txt
286
287diff -u short.txt long.txt
288echo status=$?
289
290## STDOUT:
291 8 short.txt
292 8 long.txt
293 16 total
294status=0
295## END
296
297## N-I bash/dash/mksh/zsh STDOUT:
298## END
299
300#### ulimit accepts 'unlimited'
301
302for 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
311done
312## STDOUT:
313 arg zz
314unlimited
315status=0
316FAILED
317
318 arg unlimited
319unlimited
320status=0
321
322## END
323
324
325#### ulimit of 2**32, 2**31 (int overflow)
326
327echo -n 'one '; ulimit -f
328
329
330ulimit -f $(( 1 << 32 ))
331
332echo -n 'two '; ulimit -f
333
334
335# mksh fails because it overflows signed int, turning into negative number
336ulimit -f $(( 1 << 31 ))
337
338echo -n 'three '; ulimit -f
339
340## STDOUT:
341one unlimited
342two 4294967296
343three 2147483648
344## END
345## BUG mksh STDOUT:
346one unlimited
347two 1
348three 1
349## END
350
351
352#### ulimit that is 64 bits
353
354# no 64-bit integers
355case $SH in mksh) exit ;; esac
356
357echo -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
363lim=$(( 1 << 53 ))
364#echo $lim
365
366# bash says this is out of range
367ulimit -f $lim
368
369echo -n 'after '; ulimit -f
370
371## STDOUT:
372before unlimited
373after 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
383case $SH in mksh) exit ;; esac
384
385echo -n 'before '; ulimit -f
386
387# 1 << 63 overflows signed int
388
389lim=$(( (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
395ulimit -f $lim
396echo -n 'after '; ulimit -f
397
398## STDOUT:
399before unlimited
400after unlimited
401## END
402
403## BUG dash/zsh STDOUT:
404before unlimited
405after 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
419rm -f err.txt
420touch err.txt
421
422bytes() {
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
435ulimit -f 1
436
437bytes 512 > ok.txt
438echo 512 status=$?
439
440bytes 513 > too-big.txt
441echo 513 status=$?
442echo
443
444wc --bytes ok.txt too-big.txt
445echo
446
447cat err.txt
448
449## STDOUT:
450512 status=0
451513 status=0
452
453 512 ok.txt
454 512 too-big.txt
4551024 total
456
457ERROR: echo failed with status 1
458## END
459
460## BUG bash STDOUT:
461512 status=0
462513 status=0
463
464 512 ok.txt
465 513 too-big.txt
4661025 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
482echo outer=$?
483
484## STDOUT:
485inner=1
486outer=0
487## END
488
489
490#### ulimit -S for soft limit (default), -H for hard limit
491case $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
496show_state() {
497 local msg=$1
498 echo "$msg"
499 echo -n ' '; ulimit -S -t
500 echo -n ' '; ulimit -H -t
501 echo
502}
503
504show_state 'init'
505
506ulimit -S -t 123456
507show_state '-S'
508
509ulimit -H -t 123457
510show_state '-H'
511
512ulimit -t 123455
513show_state 'no flag'
514
515echo 'GET'
516
517ulimit -S -t 123454
518echo -n ' '; ulimit -t
519echo -n ' '; ulimit -S -t
520echo -n ' '; ulimit -H -t
521
522## STDOUT:
523init
524 unlimited
525 unlimited
526
527-S
528 123456
529 unlimited
530
531-H
532 123456
533 123457
534
535no flag
536 123455
537 123455
538
539GET
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
551case $SH in dash|mksh) exit ;; esac
552
553
554flag=-t
555
556ulimit -S -H $flag 100
557echo both=$?
558
559ulimit -S $flag 90
560echo soft=$?
561
562ulimit -S $flag 95
563echo soft=$?
564
565ulimit -S $flag 105
566if test $? -ne 0; then
567 echo soft OK
568else
569 echo soft fail
570fi
571
572ulimit -H $flag 200
573if test $? -ne 0; then
574 echo hard OK
575else
576 echo hard fail
577fi
578
579## STDOUT:
580both=0
581soft=0
582soft=0
583soft OK
584hard OK
585## END
586
587## BUG dash/mksh STDOUT:
588## END