OILS / spec / builtin-process.test.sh View on Github | oils.pub

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