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

347 lines, 162 significant
1## oils_failures_allowed: 0
2## compare_shells: bash dash mksh zsh ash yash
3
4#### true is not special; prefix assignments don't persist, it can be redefined
5foo=bar true
6echo foo=$foo
7
8true() {
9 echo true func
10}
11foo=bar true
12echo foo=$foo
13
14## STDOUT:
15foo=
16true func
17foo=
18## END
19
20## BUG mksh STDOUT:
21foo=
22true func
23foo=bar
24## END
25
26# POSIX rule about special builtins pointed at:
27#
28# https://www.reddit.com/r/oilshell/comments/5ykpi3/oildev_is_alive/
29
30#### Prefix assignments persist after special builtins, like : (set -o posix)
31case $SH in
32 bash) set -o posix ;;
33esac
34
35foo=bar :
36echo foo=$foo
37
38# Not true when you use 'builtin'
39z=Z builtin :
40echo z=$Z
41
42## STDOUT:
43foo=bar
44z=
45## END
46
47## BUG zsh STDOUT:
48foo=
49z=
50## END
51
52#### Prefix assignments persist after readonly, but NOT exported (set -o posix)
53
54# Bash only implements it behind the posix option
55case $SH in
56 bash) set -o posix ;;
57esac
58foo=bar readonly spam=eggs
59echo foo=$foo
60echo spam=$spam
61
62# should NOT be exported
63printenv.py foo
64printenv.py spam
65
66## STDOUT:
67foo=bar
68spam=eggs
69None
70None
71## END
72
73## BUG bash/yash STDOUT:
74foo=bar
75spam=eggs
76bar
77None
78## END
79
80#### Prefix binding to exec - adapted from toysh
81cat > snork << 'EOF'
82#!/bin/sh
83echo hello $BLAH
84EOF
85chmod +x snork
86
87$SH -c 'BLAH=123; ./snork'
88$SH -c 'BLAH=123 ./snork'
89echo
90
91$SH -c 'BLAH=123; exec ./snork'
92$SH -c 'BLAH=123 exec ./snork'
93echo
94
95# WHY different?
96$SH -c 'BLAH=123; readonly foo; exec ./snork'
97$SH -c 'BLAH=123 readonly foo; ./snork'
98echo
99
100$SH -c 'BLAH=123; : foo; exec ./snork'
101$SH -c 'BLAH=123 : foo; ./snork'
102
103## STDOUT:
104hello
105hello 123
106
107hello
108hello 123
109
110hello
111hello
112
113hello
114hello
115## END
116
117## BUG yash STDOUT:
118hello
119hello 123
120
121hello
122hello 123
123
124hello
125hello 123
126
127hello
128hello 123
129## END
130
131#### Prefix binding for readonly vs. exec
132
133pre1=pre1 readonly x=x
134pre2=pre2 exec sh -c 'echo pre1=$pre1 x=$x pre2=$pre2'
135
136## STDOUT:
137pre1= x= pre2=pre2
138## END
139## BUG yash STDOUT:
140pre1=pre1 x= pre2=pre2
141## END
142
143#### Which shells allow special builtins to be redefined?
144eval() {
145 echo 'eval func' "$@"
146}
147eval 'echo hi'
148
149# we allow redefinition, but the definition is NOT used!
150## status: 0
151## STDOUT:
152hi
153## END
154
155# we PREVENT redefinition
156## OK dash/ash status: 2
157## OK dash/ash STDOUT:
158## END
159
160# should not allow redefinition
161## BUG bash/zsh status: 0
162## BUG bash/zsh STDOUT:
163eval func echo hi
164## END
165
166
167#### Special builtins can't be redefined as shell functions (set -o posix)
168case $SH in
169 bash) set -o posix ;;
170esac
171
172eval 'echo hi'
173
174eval() {
175 echo 'sh func' "$@"
176}
177
178eval 'echo hi'
179
180## status: 0
181## STDOUT:
182hi
183hi
184## END
185
186## OK bash/dash/ash status: 2
187## OK bash/dash/ash STDOUT:
188hi
189## END
190
191## BUG zsh status: 0
192## BUG zsh STDOUT:
193hi
194sh func echo hi
195## END
196
197#### Non-special builtins CAN be redefined as functions
198test -n "$BASH_VERSION" && set -o posix
199true() {
200 echo 'true func'
201}
202true hi
203echo status=$?
204## STDOUT:
205true func
206status=0
207## END
208
209#### Shift is special and fails whole script
210
211# https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_14
212#
213# 2.8.1 - Consequences of shell errors
214#
215# Special built-ins should exit a non-interactive shell
216# bash and busybox dont't implement this even with set -o posix, so it seems risky
217# dash and mksh do it; so does AT&T ksh
218
219$SH -c '
220if test -n "$BASH_VERSION"; then
221 set -o posix
222fi
223set -- a b
224shift 3
225echo status=$?
226'
227if test "$?" != 0; then
228 echo 'non-zero status'
229fi
230
231## STDOUT:
232non-zero status
233## END
234
235## N-I bash/zsh/ash/yash/osh status: 0
236## N-I bash/zsh/ash/yash/osh STDOUT:
237status=1
238## END
239
240#### set is special and fails whole script, even if using || true
241$SH -c '
242if test -n "$BASH_VERSION"; then
243 set -o posix
244fi
245
246shopt -s invalid_ || true
247echo ok
248set -o invalid_ || true
249echo should not get here
250'
251if test "$?" != 0; then
252 echo 'non-zero status'
253fi
254
255## STDOUT:
256ok
257non-zero status
258## END
259
260## N-I bash/ash/yash/osh status: 0
261## N-I bash/ash/yash/osh STDOUT:
262ok
263should not get here
264## END
265
266#### bash 'type' gets confused - says 'function', but runs builtin
267case $SH in dash|mksh|zsh|ash|yash) exit ;; esac
268
269echo TRUE
270type -t true # builtin
271true() { echo true func; }
272type -t true # now a function
273echo ---
274
275echo EVAL
276
277type -t eval # builtin
278# define function before set -o posix
279eval() { echo "shell function: $1"; }
280# bash runs the FUNCTION, but OSH finds the special builtin
281# OSH doesn't need set -o posix
282eval 'echo before posix'
283
284if test -n "$BASH_VERSION"; then
285 # this makes the eval definition invisible!
286 set -o posix
287fi
288
289eval 'echo after posix' # this is the builtin eval
290# bash claims it's a function, but it's a builtin
291type -t eval
292
293# it finds the function and the special builtin
294#type -a eval
295
296## BUG bash STDOUT:
297TRUE
298builtin
299function
300---
301EVAL
302builtin
303shell function: echo before posix
304after posix
305function
306## END
307
308## STDOUT:
309TRUE
310builtin
311function
312---
313EVAL
314builtin
315before posix
316after posix
317builtin
318## END
319
320## N-I dash/mksh/zsh/ash/yash STDOUT:
321## END
322
323#### command, builtin - both can be redefined, not special (regression)
324case $SH in dash|ash|yash) exit ;; esac
325
326builtin echo b
327command echo c
328
329builtin() {
330 echo builtin-redef "$@"
331}
332
333command() {
334 echo command-redef "$@"
335}
336
337builtin echo b
338command echo c
339
340## STDOUT:
341b
342c
343builtin-redef echo b
344command-redef echo c
345## END
346## N-I dash/ash/yash STDOUT:
347## END