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

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