OILS / spec / builtins2.test.sh View on Github | oilshell.org

444 lines, 246 significant
1## oils_failures_allowed: 0
2## compare_shells: dash bash mksh zsh
3
4
5#### Print shell strings with weird chars: set and printf %q and ${x@Q}
6
7# bash declare -p will print binary data, which makes this invalid UTF-8!
8foo=$(/bin/echo -e 'a\nb\xffc'\'d)
9
10# let's test the easier \x01, which doesn't give bash problems
11foo=$(/bin/echo -e 'a\nb\x01c'\'d)
12
13# dash:
14# only supports 'set'; prints it on multiple lines with binary data
15# switches to "'" for single quotes, not \'
16# zsh:
17# print binary data all the time, except for printf %q
18# does print $'' strings
19# mksh:
20# prints binary data for @Q
21# prints $'' strings
22
23# All are very inconsistent.
24
25case $SH in dash|mksh|zsh) return ;; esac
26
27
28set | grep -A1 foo
29
30# Will print multi-line and binary data literally!
31#declare -p foo
32
33printf 'pf %q\n' "$foo"
34
35echo '@Q ' ${foo@Q}
36
37## STDOUT:
38foo=$'a\nb\u0001c\'d'
39pf $'a\nb\u0001c\'d'
40@Q $'a\nb\u0001c\'d'
41## END
42
43## OK bash STDOUT:
44foo=$'a\nb\001c\'d'
45pf $'a\nb\001c\'d'
46@Q $'a\nb\001c\'d'
47## END
48
49## OK dash/mksh/zsh STDOUT:
50## END
51
52#### Print shell strings with normal chars: set and printf %q and ${x@Q}
53
54# There are variations on whether quotes are printed
55
56case $SH in dash|zsh) return ;; esac
57
58foo=spam
59
60set | grep -A1 foo
61
62# Will print multi-line and binary data literally!
63typeset -p foo
64
65printf 'pf %q\n' "$foo"
66
67echo '@Q ' ${foo@Q}
68
69## STDOUT:
70foo=spam
71declare -- foo=spam
72pf spam
73@Q spam
74## END
75
76
77## OK bash STDOUT:
78foo=spam
79declare -- foo="spam"
80pf spam
81@Q 'spam'
82## END
83
84## OK mksh STDOUT:
85foo=spam
86typeset foo=spam
87pf spam
88@Q spam
89## END
90
91## N-I dash/zsh STDOUT:
92## END
93
94
95
96#### command -v
97myfunc() { echo x; }
98command -v echo
99echo $?
100command -v myfunc
101echo $?
102command -v nonexistent # doesn't print anything
103echo $?
104command -v for
105echo $?
106## STDOUT:
107echo
1080
109myfunc
1100
1111
112for
1130
114## OK dash STDOUT:
115echo
1160
117myfunc
1180
119127
120for
1210
122## END
123
124#### command -v with multiple names
125# ALL FOUR SHELLS behave differently here!
126#
127# bash chooses to swallow the error! We agree with zsh if ANY word lookup
128# fails, then the whole thing fails.
129
130myfunc() { echo x; }
131command -v echo myfunc ZZZ for
132echo status=$?
133
134## STDOUT:
135echo
136myfunc
137for
138status=1
139## BUG bash STDOUT:
140echo
141myfunc
142for
143status=0
144## BUG dash STDOUT:
145echo
146status=0
147## OK mksh STDOUT:
148echo
149myfunc
150status=1
151## END
152
153#### command -v doesn't find non-executable file
154# PATH resolution is different
155
156PATH="_tmp:$PATH"
157touch _tmp/non-executable _tmp/executable
158chmod +x _tmp/executable
159
160command -v _tmp/non-executable
161echo status=$?
162
163command -v _tmp/executable
164echo status=$?
165
166## STDOUT:
167status=1
168_tmp/executable
169status=0
170## END
171
172## BUG dash STDOUT:
173_tmp/non-executable
174status=0
175_tmp/executable
176status=0
177## END
178
179#### command -V
180myfunc() { echo x; }
181
182shopt -s expand_aliases
183alias ll='ls -l'
184
185backtick=\`
186command -V ll | sed "s/$backtick/'/g"
187echo status=$?
188
189command -V echo
190echo status=$?
191
192command -V myfunc
193echo status=$?
194
195command -V nonexistent # doesn't print anything
196echo status=$?
197
198command -V for
199echo status=$?
200
201## STDOUT:
202ll is an alias for "ls -l"
203status=0
204echo is a shell builtin
205status=0
206myfunc is a shell function
207status=0
208status=1
209for is a shell keyword
210status=0
211## END
212
213## OK zsh STDOUT:
214ll is an alias for ls -l
215status=0
216echo is a shell builtin
217status=0
218myfunc is a shell function
219status=0
220nonexistent not found
221status=1
222for is a reserved word
223status=0
224## END
225
226## OK bash STDOUT:
227ll is aliased to 'ls -l'
228status=0
229echo is a shell builtin
230status=0
231myfunc is a function
232myfunc ()
233{
234 echo x
235}
236status=0
237status=1
238for is a shell keyword
239status=0
240## END
241
242## OK mksh STDOUT:
243ll is an alias for 'ls -l'
244status=0
245echo is a shell builtin
246status=0
247myfunc is a function
248status=0
249nonexistent not found
250status=1
251for is a reserved word
252status=0
253## END
254
255## OK dash STDOUT:
256ll is an alias for ls -l
257status=0
258echo is a shell builtin
259status=0
260myfunc is a shell function
261status=0
262nonexistent: not found
263status=127
264for is a shell keyword
265status=0
266## END
267
268#### command -V nonexistent
269command -V nonexistent 2>err.txt
270echo status=$?
271fgrep -o 'nonexistent: not found' err.txt || true
272
273## STDOUT:
274status=1
275nonexistent: not found
276## END
277
278## OK zsh/mksh STDOUT:
279nonexistent not found
280status=1
281## END
282
283## BUG dash STDOUT:
284nonexistent: not found
285status=127
286## END
287
288
289#### command skips function lookup
290seq() {
291 echo "$@"
292}
293command # no-op
294seq 3
295command seq 3
296# subshell shouldn't fork another process (but we don't have a good way of
297# testing it)
298( command seq 3 )
299## STDOUT:
3003
3011
3022
3033
3041
3052
3063
307## END
308
309#### command command seq 3
310command command seq 3
311## STDOUT:
3121
3132
3143
315## END
316## N-I zsh stdout-json: ""
317## N-I zsh status: 127
318
319#### command command -v seq
320seq() {
321 echo 3
322}
323command command -v seq
324## stdout: seq
325## N-I zsh stdout-json: ""
326## N-I zsh status: 127
327
328#### history usage
329history
330echo status=$?
331history +5 # hm bash considers this valid
332echo status=$?
333history -5 # invalid flag
334echo status=$?
335history f
336echo status=$?
337history too many args
338echo status=$?
339## status: 0
340## STDOUT:
341status=0
342status=0
343status=2
344status=2
345status=2
346## END
347## OK bash STDOUT:
348status=0
349status=0
350status=2
351status=1
352status=1
353## END
354## BUG zsh/mksh STDOUT:
355status=1
356status=1
357status=1
358status=1
359status=1
360## END
361## N-I dash STDOUT:
362status=127
363status=127
364status=127
365status=127
366status=127
367## END
368
369#### command -p (override existing program)
370# Tests whether command -p overrides the path
371# tr chosen because we need a simple non-builtin
372mkdir -p $TMP/bin
373echo "echo wrong" > $TMP/bin/tr
374chmod +x $TMP/bin/tr
375PATH="$TMP/bin:$PATH"
376echo aaa | tr "a" "b"
377echo aaa | command -p tr "a" "b"
378rm $TMP/bin/tr
379## STDOUT:
380wrong
381bbb
382## END
383
384#### command -p (hide tool in custom path)
385mkdir -p $TMP/bin
386echo "echo hello" > $TMP/bin/hello
387chmod +x $TMP/bin/hello
388export PATH=$TMP/bin
389command -p hello
390## status: 127
391
392#### command -p (find hidden tool in default path)
393export PATH=''
394command -p ls
395## status: 0
396
397
398#### $(command type ls)
399type() { echo FUNCTION; }
400type
401s=$(command type echo)
402echo $s | grep builtin > /dev/null
403echo status=$?
404## STDOUT:
405FUNCTION
406status=0
407## END
408## N-I zsh STDOUT:
409FUNCTION
410status=1
411## END
412## N-I mksh STDOUT:
413status=1
414## END
415
416#### builtin
417cd () { echo "hi"; }
418cd
419builtin cd / && pwd
420unset -f cd
421## STDOUT:
422hi
423/
424## END
425## N-I dash STDOUT:
426hi
427## END
428
429#### builtin ls not found
430builtin ls
431## status: 1
432## N-I dash status: 127
433
434#### builtin no args
435builtin
436## status: 0
437## N-I dash status: 127
438
439#### builtin command echo hi
440builtin command echo hi
441## status: 0
442## stdout: hi
443## N-I dash status: 127
444## N-I dash stdout-json: ""