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

571 lines, 296 significant
1## compare_shells: bash dash mksh zsh
2
3
4# Alias is in POSIX.
5#
6# http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_03_01
7#
8# Bash is the only one that doesn't support aliases by default!
9
10#### Usage of builtins
11shopt -s expand_aliases || true
12alias -- foo=echo
13echo status=$?
14foo x
15unalias -- foo
16foo x
17## status: 127
18## STDOUT:
19status=0
20x
21## END
22# dash doesn't accept --
23## BUG dash STDOUT:
24status=1
25x
26## END
27
28#### Basic alias
29shopt -s expand_aliases # bash requires this
30alias hi='echo hello world'
31hi || echo 'should not run this'
32echo hi # second word is not
33'hi' || echo 'expected failure'
34## STDOUT:
35hello world
36hi
37expected failure
38## END
39
40#### define and use alias on a single line
41shopt -s expand_aliases
42alias e=echo; e one # this is not alias-expanded because we parse lines at once
43e two; e three
44## STDOUT:
45two
46three
47## END
48
49#### alias can override builtin
50shopt -s expand_aliases
51alias echo='echo foo'
52echo bar
53## stdout: foo bar
54
55#### defining multiple aliases, then unalias
56shopt -s expand_aliases # bash requires this
57x=x
58y=y
59alias echo-x='echo $x' echo-y='echo $y'
60echo status=$?
61echo-x X
62echo-y Y
63unalias echo-x echo-y
64echo status=$?
65echo-x X || echo undefined
66echo-y Y || echo undefined
67## STDOUT:
68status=0
69x X
70y Y
71status=0
72undefined
73undefined
74## END
75
76#### alias not defined
77alias e='echo' nonexistentZ
78echo status=$?
79## STDOUT:
80status=1
81## END
82## OK mksh STDOUT:
83nonexistentZ alias not found
84status=1
85## END
86
87#### unalias not defined
88alias e=echo ll='ls -l'
89unalias e nonexistentZ ll
90echo status=$?
91## STDOUT:
92status=1
93## END
94
95#### unalias -a
96
97alias foo=bar
98alias spam=eggs
99
100alias | egrep 'foo|spam' | wc -l
101
102unalias -a
103
104alias
105echo status=$?
106
107## STDOUT:
1082
109status=0
110## END
111
112#### List aliases by providing names
113
114alias e=echo ll='ls -l'
115alias e ll
116
117## STDOUT:
118alias e='echo'
119alias ll='ls -l'
120## END
121## OK mksh/zsh STDOUT:
122e=echo
123ll='ls -l'
124## END
125## OK dash STDOUT:
126e='echo'
127ll='ls -l'
128## END
129
130#### alias without args lists all aliases
131alias ex=exit ll='ls -l'
132alias | grep -E 'ex=|ll=' # need to grep because mksh/zsh have builtin aliases
133echo status=$?
134## STDOUT:
135alias ex='exit'
136alias ll='ls -l'
137status=0
138## END
139## OK dash STDOUT:
140ex='exit'
141ll='ls -l'
142status=0
143## END
144## OK mksh/zsh STDOUT:
145ex=exit
146ll='ls -l'
147status=0
148## END
149
150#### unalias without args is a usage error
151unalias
152echo status=$?
153## stdout: status=2
154## BUG mksh/dash stdout: status=0
155## BUG zsh stdout: status=1
156
157#### alias with trailing space causes alias expansion on second word
158shopt -s expand_aliases # bash requires this
159
160alias hi='echo hello world '
161alias punct='!!!'
162
163hi punct
164
165alias hi='echo hello world' # No trailing space
166
167hi punct
168
169## STDOUT:
170hello world !!!
171hello world punct
172## END
173
174#### Recursive alias expansion of first word
175shopt -s expand_aliases # bash requires this
176alias hi='e_ hello world'
177alias e_='echo __'
178hi # first hi is expanded to echo hello world; then echo is expanded. gah.
179## STDOUT:
180__ hello world
181## END
182
183#### Recursive alias expansion of SECOND word
184shopt -s expand_aliases # bash requires this
185alias one='ONE '
186alias two='TWO '
187alias e_='echo one '
188e_ two hello world
189## STDOUT:
190one TWO hello world
191## END
192
193#### Expansion of alias with variable
194shopt -s expand_aliases # bash requires this
195x=x
196alias echo-x='echo $x' # nothing is evaluated here
197x=y
198echo-x hi
199## STDOUT:
200y hi
201## END
202
203#### Alias must be an unquoted word, no expansions allowed
204shopt -s expand_aliases # bash requires this
205alias echo_alias_='echo'
206cmd=echo_alias_
207echo_alias_ X # this works
208$cmd X # this fails because it's quoted
209echo status=$?
210## STDOUT:
211X
212status=127
213## END
214
215#### first and second word are the same alias, but no trailing space
216shopt -s expand_aliases # bash requires this
217x=x
218alias echo-x='echo $x' # nothing is evaluated here
219echo-x echo-x
220## STDOUT:
221x echo-x
222## END
223
224#### first and second word are the same alias, with trailing space
225shopt -s expand_aliases # bash requires this
226x=x
227alias echo-x='echo $x ' # nothing is evaluated here
228echo-x echo-x
229## STDOUT:
230x echo x
231## END
232
233#### Invalid syntax of alias
234shopt -s expand_aliases # bash requires this
235alias echo_alias_= 'echo --; echo' # bad space here
236echo_alias_ x
237## status: 127
238
239#### Dynamic alias definition
240shopt -s expand_aliases # bash requires this
241x=x
242name='echo_alias_'
243val='=echo'
244alias "$name$val"
245echo_alias_ X
246## stdout: X
247
248#### Alias name with punctuation
249# NOTE: / is not OK in bash, but OK in other shells. Must less restrictive
250# than var names.
251shopt -s expand_aliases # bash requires this
252alias e_+.~x='echo'
253e_+.~x X
254## stdout: X
255
256#### Syntax error after expansion
257shopt -s expand_aliases # bash requires this
258alias e_=';; oops'
259e_ x
260## status: 2
261## OK mksh/zsh status: 1
262
263#### Loop split across alias and arg works
264shopt -s expand_aliases # bash requires this
265alias e_='for i in 1 2 3; do echo $i;'
266e_ done
267## STDOUT:
2681
2692
2703
271## END
272
273#### Loop split across alias in another way
274shopt -s expand_aliases
275alias e_='for i in 1 2 3; do echo '
276e_ $i; done
277## STDOUT:
2781
2792
2803
281## END
282## OK osh stdout-json: ""
283## OK osh status: 2
284
285#### Loop split across both iterative and recursive aliases
286shopt -s expand_aliases # bash requires this
287alias FOR1='for '
288alias FOR2='FOR1 '
289alias eye1='i '
290alias eye2='eye1 '
291alias IN='in '
292alias onetwo='$one "2" ' # NOTE: this does NOT work in any shell except bash.
293one=1
294FOR2 eye2 IN onetwo 3; do echo $i; done
295## STDOUT:
2961
2972
2983
299## END
300## OK osh stdout-json: ""
301## OK osh status: 2
302## BUG zsh stdout-json: ""
303
304#### Alias with a quote in the middle is a syntax error
305shopt -s expand_aliases
306alias e_='echo "'
307var=x
308e_ '${var}"'
309## status: 2
310## OK mksh/zsh status: 1
311
312#### Alias with internal newlines
313shopt -s expand_aliases
314alias e_='echo 1
315echo 2
316echo 3'
317var='echo foo'
318e_ ${var}
319## STDOUT:
3201
3212
3223 echo foo
323## END
324
325#### Alias trailing newline
326shopt -s expand_aliases
327alias e_='echo 1
328echo 2
329echo 3
330'
331var='echo foo'
332e_ ${var}
333## STDOUT:
3341
3352
3363
337foo
338## END
339## OK zsh STDOUT:
3401
3412
3423
343## END
344## OK zsh status: 127
345
346#### Two aliases in pipeline
347shopt -s expand_aliases
348alias SEQ='seq '
349alias THREE='3 '
350alias WC='wc '
351SEQ THREE | WC -l
352## stdout: 3
353
354#### Alias not respected inside $()
355# This could be parsed correctly, but it is only defined in a child process.
356shopt -s expand_aliases
357echo $(alias sayhi='echo hello')
358sayhi
359## status: 127
360
361#### Alias can be defined and used on a single line
362shopt -s expand_aliases
363alias sayhi='echo hello'; sayhi same line
364sayhi other line
365## STDOUT:
366hello other line
367## END
368
369#### Alias is respected inside eval
370shopt -s expand_aliases
371eval "alias sayhi='echo hello'
372sayhi inside"
373sayhi outside
374## STDOUT:
375hello inside
376hello outside
377## END
378## BUG zsh STDOUT:
379hello outside
380## END
381
382#### alias with redirects works
383shopt -s expand_aliases
384alias e_=echo
385>$TMP/alias1.txt e_ 1
386e_ >$TMP/alias2.txt 2
387e_ 3 >$TMP/alias3.txt
388cat $TMP/alias1.txt $TMP/alias2.txt $TMP/alias3.txt
389## STDOUT:
3901
3912
3923
393## END
394
395#### alias with environment bindings works
396shopt -s expand_aliases
397alias p_=printenv.py
398FOO=1 printenv.py FOO
399FOO=2 p_ FOO
400## STDOUT:
4011
4022
403## END
404
405#### alias with line continuation in the middle
406shopt -s expand_aliases
407alias e_='echo '
408alias one='ONE '
409alias two='TWO '
410alias three='THREE' # no trailing space
411e_ one \
412 two one \
413 two three two \
414 one
415## stdout: ONE TWO ONE TWO THREE two one
416
417#### alias for left brace
418shopt -s expand_aliases
419alias LEFT='{'
420LEFT echo one; echo two; }
421## STDOUT:
422one
423two
424## END
425## OK osh stdout-json: ""
426## OK osh status: 2
427
428#### alias for left paren
429shopt -s expand_aliases
430alias LEFT='('
431LEFT echo one; echo two )
432## STDOUT:
433one
434two
435## END
436## OK osh stdout-json: ""
437## OK osh status: 2
438
439#### alias used in subshell and command sub
440# This spec seems to be contradictoary?
441# http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_03_01
442# "When used as specified by this volume of POSIX.1-2017, alias definitions
443# shall not be inherited by separate invocations of the shell or by the utility
444# execution environments invoked by the shell; see Shell Execution
445# Environment."
446shopt -s expand_aliases
447alias echo_='echo [ '
448( echo_ subshell; )
449echo $(echo_ commandsub)
450## STDOUT:
451[ subshell
452[ commandsub
453## END
454
455#### alias used in here doc
456shopt -s expand_aliases
457alias echo_='echo [ '
458cat <<EOF
459$(echo_ ])
460EOF
461## STDOUT:
462[ ]
463## END
464
465#### here doc inside alias
466shopt -s expand_aliases
467alias c='cat <<EOF
468$(echo hi)
469EOF
470'
471c
472## STDOUT:
473hi
474## END
475## BUG bash stdout-json: ""
476## BUG bash status: 127
477
478#### Corner case: alias inside LHS array arithmetic expression
479shopt -s expand_aliases
480alias zero='echo 0'
481a[$(zero)]=ZERO
482a[1]=ONE
483argv.py "${a[@]}"
484## STDOUT:
485['ZERO', 'ONE']
486## END
487## N-I dash stdout-json: ""
488## N-I dash status: 2
489## N-I zsh stdout-json: ""
490## N-I zsh status: 1
491
492#### Alias that is pipeline
493shopt -s expand_aliases
494alias t1='echo hi|wc -c'
495t1
496## STDOUT:
4973
498## END
499
500#### Alias that is && || ;
501shopt -s expand_aliases
502alias t1='echo one && echo two && echo 3 | wc -l;
503echo four'
504t1
505## STDOUT:
506one
507two
5081
509four
510## END
511
512#### Alias and command sub (bug regression)
513cd $TMP
514shopt -s expand_aliases
515echo foo bar > tmp.txt
516alias a=argv.py
517a `cat tmp.txt`
518## stdout: ['foo', 'bar']
519
520#### Alias and arithmetic
521shopt -s expand_aliases
522alias a=argv.py
523a $((1 + 2))
524## stdout: ['3']
525
526#### Alias and PS4
527# dash enters an infinite loop!
528case $SH in
529 dash)
530 exit 1
531 ;;
532esac
533
534set -x
535PS4='+$(echo trace) '
536shopt -s expand_aliases
537alias a=argv.py
538a foo bar
539## stdout: ['foo', 'bar']
540## BUG dash status: 1
541## BUG dash stdout-json: ""
542
543#### alias with keywords
544# from issue #299
545shopt -s expand_aliases
546alias a=
547
548# both of these fail to parse in OSH
549# this is because of our cleaner evaluation model
550
551a (( var = 0 ))
552#a case x in x) true;; esac
553
554echo done
555## stdout: done
556## OK osh status: 2
557## OK osh stdout-json: ""
558
559
560#### alias with word of multiple lines
561shopt -s expand_aliases
562
563alias ll='ls -l'
564ll '1
565 2
566 3'
567echo status=$?
568
569## STDOUT:
570status=2
571## END