1 #!/usr/bin/env bash
2
3 #### Eval
4 eval "a=3"
5 echo $a
6 ## stdout: 3
7
8 #### Source
9 lib=$TMP/spec-test-lib.sh
10 echo 'LIBVAR=libvar' > $lib
11 . $lib # dash doesn't have source
12 echo $LIBVAR
13 ## stdout: libvar
14
15 #### Source nonexistent
16 source /nonexistent/path
17 echo status=$?
18 ## stdout: status=1
19 ## OK dash/zsh stdout: status=127
20
21 #### Source with no arguments
22 source
23 echo status=$?
24 ## stdout: status=2
25 ## OK mksh/zsh stdout: status=1
26 ## N-I dash stdout: status=127
27
28 #### Source with arguments
29 . spec/testdata/show-argv.sh foo bar # dash doesn't have source
30 ## STDOUT:
31 show-argv: foo bar
32 ## END
33 ## N-I dash STDOUT:
34 show-argv:
35 ## END
36
37 #### Source from a function, mutating argv and defining a local var
38 f() {
39 . spec/testdata/source-argv.sh # no argv
40 . spec/testdata/source-argv.sh args to src # new argv
41 echo $@
42 echo foo=$foo # defined in source-argv.sh
43 }
44 f args to func
45 echo foo=$foo # not defined
46 ## STDOUT:
47 source-argv: args to func
48 source-argv: args to src
49 to func
50 foo=foo_val
51 foo=
52 ## END
53 ## N-I dash STDOUT:
54 source-argv: args to func
55 source-argv: to func
56 func
57 foo=foo_val
58 foo=
59 ## END
60
61 #### Source with syntax error
62 # TODO: We should probably use dash behavior of a fatal error.
63 # Although set-o errexit handles this. We don't want to break the invariant
64 # that a builtin like 'source' behaves like an external program. An external
65 # program can't halt the shell!
66 echo 'echo >' > $TMP/syntax-error.sh
67 . $TMP/syntax-error.sh
68 echo status=$?
69 ## stdout: status=2
70 ## OK bash/mksh stdout: status=1
71 ## OK zsh stdout: status=126
72 ## OK dash stdout-json: ""
73 ## OK dash status: 2
74
75 #### Eval with syntax error
76 eval 'echo >'
77 echo status=$?
78 ## stdout: status=2
79 ## OK bash/zsh stdout: status=1
80 ## OK dash stdout-json: ""
81 ## OK dash status: 2
82 ## OK mksh stdout-json: ""
83 ## OK mksh status: 1
84
85 #### Eval in does tilde expansion
86
87 x="~"
88 eval y="$x" # scalar
89 test "$x" = "$y" || echo FALSE
90 [[ $x == /* ]] || echo FALSE # doesn't start with /
91 [[ $y == /* ]] && echo TRUE
92
93 #argv "$x" "$y"
94
95 ## STDOUT:
96 FALSE
97 FALSE
98 TRUE
99 ## END
100 ## BUG dash status: 127
101 ## BUG dash stdout-json: "FALSE\n"
102 ## BUG mksh status: 1
103 ## BUG mksh stdout-json: "FALSE\n"
104
105 #### Eval in bash does tilde expansion in array
106
107 # the "make" plugin in bash-completion relies on this? wtf?
108 x="~"
109
110 # UPSTREAM CODE
111
112 #eval array=( "$x" )
113
114 # FIXED CODE -- proper quoting.
115
116 eval 'array=(' "$x" ')' # array
117
118 test "$x" = "${array[0]}" || echo FALSE
119 [[ $x == /* ]] || echo FALSE # doesn't start with /
120 [[ "${array[0]}" == /* ]] && echo TRUE
121 ## STDOUT:
122 FALSE
123 FALSE
124 TRUE
125 ## END
126 ## N-I dash status: 2
127 ## N-I dash stdout-json: ""
128 ## BUG mksh status: 1
129 ## BUG mksh STDOUT:
130 FALSE
131 ## END
132 ## BUG zsh status: 1
133 ## BUG zsh STDOUT:
134 FALSE
135 FALSE
136 ## END
137
138 #### source works for files in current directory (bash only)
139 cd $TMP
140 echo "echo current dir" > cmd
141 . cmd
142 echo status=$?
143 ## STDOUT:
144 current dir
145 status=0
146 ## END
147 ## N-I zsh STDOUT:
148 status=127
149 ## END
150
151 # This is a special builtin so failure is fatal.
152
153 ## N-I dash stdout-json: ""
154 ## N-I dash status: 2
155 ## N-I mksh stdout-json: ""
156 ## N-I mksh status: 1
157
158 #### source looks in PATH for files
159 mkdir -p dir
160 echo "echo hi" > dir/cmd
161 PATH="dir:$PATH"
162 . cmd
163 rm dir/cmd
164 ## STDOUT:
165 hi
166 ## END
167
168 #### source finds files in PATH before current dir
169 cd $TMP
170 mkdir -p dir
171 echo "echo path" > dir/cmd
172 echo "echo current dir" > cmd
173 PATH="dir:$PATH"
174 . cmd
175 echo status=$?
176 ## STDOUT:
177 path
178 status=0
179 ## END
180
181 #### source works for files in subdirectory
182 mkdir -p dir
183 echo "echo path" > dir/cmd
184 . dir/cmd
185 rm dir/cmd
186 ## STDOUT:
187 path
188 ## END
189
190 #### exit within eval (regression)
191 eval 'exit 42'
192 echo 'should not get here'
193 ## stdout-json: ""
194 ## status: 42
195
196
197 #### exit within source (regression)
198 cd $TMP
199 echo 'exit 42' > lib.sh
200 . ./lib.sh
201 echo 'should not get here'
202 ## stdout-json: ""
203 ## status: 42