OILS / spec / builtin-eval-source.test.sh View on Github | oilshell.org

345 lines, 177 significant
1## compare_shells: dash bash-4.4 mksh zsh
2## oils_failures_allowed: 0
3
4#### Eval
5eval "a=3"
6echo $a
7## stdout: 3
8
9#### eval accepts/ignores --
10eval -- echo hi
11## STDOUT:
12hi
13## END
14## BUG dash status: 127
15## BUG dash stdout-json: ""
16
17#### eval usage
18eval -
19echo $?
20eval -z
21echo $?
22## STDOUT:
23127
242
25## END
26## OK dash STDOUT:
27127
28127
29## END
30## OK mksh status: 1
31## OK mksh STDOUT:
32127
33## END
34## OK zsh STDOUT:
350
36127
37## END
38
39#### eval string with 'break continue return error'
40
41set -e
42
43sh_func_that_evals() {
44 local code_str=$1
45 for i in 1 2; do
46 echo $i
47 eval "$code_str"
48 done
49 echo 'end func'
50}
51
52for code_str in break continue return false; do
53 echo "--- $code_str"
54 sh_func_that_evals "$code_str"
55done
56echo status=$?
57
58## status: 1
59## STDOUT:
60--- break
611
62end func
63--- continue
641
652
66end func
67--- return
681
69--- false
701
71## END
72
73## BUG mksh STDOUT:
74--- break
751
762
77end func
78--- continue
791
802
81end func
82--- return
831
84--- false
851
86## END
87
88#### eval YSH block with 'break continue return error'
89case $SH in dash|bash*|mksh|zsh) exit ;; esac
90
91shopt -s ysh:all
92
93proc proc_that_evals(; ; ;b) {
94 for i in 1 2; do
95 echo $i
96 call io->eval(b)
97 done
98 echo 'end func'
99}
100
101var cases = [
102 ['break', ^(break)],
103 ['continue', ^(continue)],
104 ['return', ^(return)],
105 ['false', ^(false)],
106]
107
108for test_case in (cases) {
109 var code_str, block = test_case
110 echo "--- $code_str"
111 proc_that_evals (; ; block)
112}
113echo status=$?
114
115## status: 1
116## STDOUT:
117--- break
1181
119end func
120--- continue
1211
1222
123end func
124--- return
1251
126--- false
1271
128## END
129
130## N-I dash/bash/mksh/zsh status: 0
131## N-I dash/bash/mksh/zsh STDOUT:
132## END
133
134#### exit within eval (regression)
135eval 'exit 42'
136echo 'should not get here'
137## stdout-json: ""
138## status: 42
139
140#### exit within source (regression)
141cd $TMP
142echo 'exit 42' > lib.sh
143. ./lib.sh
144echo 'should not get here'
145## stdout-json: ""
146## status: 42
147
148#### Source
149lib=$TMP/spec-test-lib.sh
150echo 'LIBVAR=libvar' > $lib
151. $lib # dash doesn't have source
152echo $LIBVAR
153## stdout: libvar
154
155#### source accepts/ignores --
156echo 'echo foo' > $TMP/foo.sh
157source -- $TMP/foo.sh
158## STDOUT:
159foo
160## END
161## N-I dash stdout-json: ""
162## N-I dash status: 127
163
164#### Source nonexistent
165source /nonexistent/path
166echo status=$?
167## stdout: status=1
168## OK dash/zsh stdout: status=127
169
170#### Source with no arguments
171source
172echo status=$?
173## stdout: status=2
174## OK mksh/zsh stdout: status=1
175## N-I dash stdout: status=127
176
177#### Source with arguments
178. $REPO_ROOT/spec/testdata/show-argv.sh foo bar # dash doesn't have source
179## STDOUT:
180show-argv: foo bar
181## END
182## N-I dash STDOUT:
183show-argv:
184## END
185
186#### Source from a function, mutating argv and defining a local var
187f() {
188 . $REPO_ROOT/spec/testdata/source-argv.sh # no argv
189 . $REPO_ROOT/spec/testdata/source-argv.sh args to src # new argv
190 echo $@
191 echo foo=$foo # defined in source-argv.sh
192}
193f args to func
194echo foo=$foo # not defined
195## STDOUT:
196source-argv: args to func
197source-argv: args to src
198to func
199foo=foo_val
200foo=
201## END
202## N-I dash STDOUT:
203source-argv: args to func
204source-argv: to func
205func
206foo=foo_val
207foo=
208## END
209
210#### Source with syntax error
211# TODO: We should probably use dash behavior of a fatal error.
212# Although set-o errexit handles this. We don't want to break the invariant
213# that a builtin like 'source' behaves like an external program. An external
214# program can't halt the shell!
215echo 'echo >' > $TMP/syntax-error.sh
216. $TMP/syntax-error.sh
217echo status=$?
218## stdout: status=2
219## OK bash/mksh stdout: status=1
220## OK zsh stdout: status=126
221## OK dash stdout-json: ""
222## OK dash status: 2
223
224#### Eval with syntax error
225eval 'echo >'
226echo status=$?
227## stdout: status=2
228## OK bash/zsh stdout: status=1
229## OK dash stdout-json: ""
230## OK dash status: 2
231## OK mksh stdout-json: ""
232## OK mksh status: 1
233
234#### Eval in does tilde expansion
235
236x="~"
237eval y="$x" # scalar
238test "$x" = "$y" || echo FALSE
239[[ $x == /* ]] || echo FALSE # doesn't start with /
240[[ $y == /* ]] && echo TRUE
241
242#argv "$x" "$y"
243
244## STDOUT:
245FALSE
246FALSE
247TRUE
248## END
249## BUG dash status: 127
250## BUG dash stdout-json: "FALSE\n"
251## BUG mksh status: 1
252## BUG mksh stdout-json: "FALSE\n"
253
254#### Eval in bash does tilde expansion in array
255
256# the "make" plugin in bash-completion relies on this? wtf?
257x="~"
258
259# UPSTREAM CODE
260
261#eval array=( "$x" )
262
263# FIXED CODE -- proper quoting.
264
265eval 'array=(' "$x" ')' # array
266
267test "$x" = "${array[0]}" || echo FALSE
268[[ $x == /* ]] || echo FALSE # doesn't start with /
269[[ "${array[0]}" == /* ]] && echo TRUE
270## STDOUT:
271FALSE
272FALSE
273TRUE
274## END
275## N-I dash status: 2
276## N-I dash stdout-json: ""
277## BUG mksh status: 1
278## BUG mksh STDOUT:
279FALSE
280## END
281## BUG zsh status: 1
282## BUG zsh STDOUT:
283FALSE
284FALSE
285## END
286
287#### source works for files in current directory (bash only)
288cd $TMP
289echo "echo current dir" > cmd
290. cmd
291echo status=$?
292## STDOUT:
293current dir
294status=0
295## END
296## N-I zsh STDOUT:
297status=127
298## END
299
300# This is a special builtin so failure is fatal.
301
302## N-I dash stdout-json: ""
303## N-I dash status: 2
304## N-I mksh stdout-json: ""
305## N-I mksh status: 1
306
307#### source looks in PATH for files
308mkdir -p dir
309echo "echo hi" > dir/cmd
310PATH="dir:$PATH"
311. cmd
312rm dir/cmd
313## STDOUT:
314hi
315## END
316
317#### source finds files in PATH before current dir
318cd $TMP
319mkdir -p dir
320echo "echo path" > dir/cmd
321echo "echo current dir" > cmd
322PATH="dir:$PATH"
323. cmd
324echo status=$?
325## STDOUT:
326path
327status=0
328## END
329
330#### source works for files in subdirectory
331mkdir -p dir
332echo "echo path" > dir/cmd
333. dir/cmd
334rm dir/cmd
335## STDOUT:
336path
337## END
338
339#### source doesn't crash when targeting a directory
340cd $TMP
341mkdir -p dir
342. ./dir/
343echo status=$?
344## stdout: status=1
345## OK dash/zsh/mksh stdout: status=0