1 # spec/append.test.sh: Test +=
2
3 #### Append string to string
4 s='abc'
5 s+=d
6 echo $s
7 ## stdout: abcd
8
9 #### Append array to array
10 a=(x y )
11 a+=(t 'u v')
12 argv.py "${a[@]}"
13 ## stdout: ['x', 'y', 't', 'u v']
14
15 #### Append string to undefined variable
16
17 s+=foo
18 echo s=$s
19
20 # bash and mksh agree that this does NOT respect set -u.
21 # I think that's a mistake, but += is a legacy construct, so let's copy it.
22
23 set -u
24
25 t+=foo
26 echo t=$t
27 t+=foo
28 echo t=$t
29 ## STDOUT:
30 s=foo
31 t=foo
32 t=foofoo
33 ## END
34
35 #### Append to array to undefined variable
36
37 # I wonder if Oil should have accumulators:
38 # auto y += %(c d) or something
39
40 y+=(c d)
41 argv.py "${y[@]}"
42 ## STDOUT:
43 ['c', 'd']
44 ## END
45
46 #### error: s+=(my array)
47 s='abc'
48 s+=(d e f)
49 echo $s
50 ## status: 1
51 ## stdout-json: ""
52 ## BUG bash/mksh status: 0
53 ## BUG bash/mksh stdout: abc
54 ## OK zsh status: 0
55 ## OK zsh stdout: abc d e f
56
57 #### error: myarray+=s
58
59 # They treat this as implicit index 0. We disallow this on the LHS, so we will
60 # also disallow it on the RHS.
61 a=(x y )
62 a+=z
63 argv.py "${a[@]}"
64 ## status: 1
65 ## stdout-json: ""
66 ## OK bash/mksh status: 0
67 ## OK bash/mksh stdout: ['xz', 'y']
68 ## OK zsh status: 0
69 ## OK zsh stdout: ['x', 'y', 'z']
70
71 #### typeset s+=(my array)
72 typeset s='abc'
73 echo $s
74
75 typeset s+=(d e f)
76 echo status=$?
77 argv.py "${s[@]}"
78
79 ## status: 1
80 ## STDOUT:
81 abc
82 ## END
83 ## OK bash status: 0
84 ## OK bash STDOUT:
85 abc
86 status=0
87 ['abc', 'd', 'e', 'f']
88 ## END
89
90 #### error: typeset myarray+=s
91 typeset a=(x y)
92 argv.py "${a[@]}"
93 typeset a+=s
94 argv.py "${a[@]}"
95
96 ## status: 1
97 ## STDOUT:
98 ['x', 'y']
99 ## END
100 ## BUG bash status: 0
101 ## BUG bash STDOUT:
102 ['x', 'y']
103 ['xs', 'y']
104 ## END
105 ## N-I mksh STDOUT:
106 ## END
107
108 #### error: append used like env prefix
109 # This should be an error in other shells but it's not.
110 A=a
111 A+=a printenv.py A
112 ## status: 2
113 ## BUG bash/zsh status: 0
114 ## BUG bash/zsh stdout: aa
115 ## BUG mksh status: 0
116 ## BUG mksh stdout: a
117
118 #### myarray[1]+=s - Append to element
119 # They treat this as implicit index 0. We disallow this on the LHS, so we will
120 # also disallow it on the RHS.
121 a=(x y )
122 a[1]+=z
123 argv.py "${a[@]}"
124 ## status: 0
125 ## stdout: ['x', 'yz']
126 ## BUG zsh stdout: ['xz', 'y']
127
128 #### myarray[-1]+=s - Append to last element
129 # Works in bash, but not mksh. It seems like bash is doing the right thing.
130 # a[-1] is allowed on the LHS. mksh doesn't have negative indexing?
131 a=(1 '2 3')
132 a[-1]+=' 4'
133 argv.py "${a[@]}"
134 ## stdout: ['1', '2 3 4']
135 ## BUG mksh stdout: ['1', '2 3', ' 4']
136
137 #### Try to append list to element
138 # bash - runtime error: cannot assign list to array number
139 # mksh - a[-1]+: is not an identifier
140 # osh - parse error -- could be better!
141 a=(1 '2 3')
142 a[-1]+=(4 5)
143 argv.py "${a[@]}"
144 ## OK bash STDOUT:
145 ['1', '2 3']
146 ## END
147 ## OK bash status: 0
148 ## N-I mksh stdout-json: ""
149 ## N-I mksh status: 1
150 ## OK stdout-json: ""
151 ## OK osh status: 2
152
153 #### Strings have value semantics, not reference semantics
154 s1='abc'
155 s2=$s1
156 s1+='d'
157 echo $s1 $s2
158 ## stdout: abcd abc
159
160 #### typeset s+=
161
162 typeset s+=foo
163 echo s=$s
164
165 # bash and mksh agree that this does NOT respect set -u.
166 # I think that's a mistake, but += is a legacy construct, so let's copy it.
167
168 set -u
169
170 typeset t+=foo
171 echo t=$t
172 typeset t+=foo
173 echo t=$t
174 ## STDOUT:
175 s=foo
176 t=foo
177 t=foofoo
178 ## END
179 ## N-I zsh status: 1
180 ## N-I zsh stdout-json: ""
181
182 #### typeset s${dyn}+=
183
184 dyn=x
185
186 typeset s${dyn}+=foo
187 echo sx=$sx
188
189 # bash and mksh agree that this does NOT respect set -u.
190 # I think that's a mistake, but += is a legacy construct, so let's copy it.
191
192 set -u
193
194 typeset t${dyn}+=foo
195 echo tx=$tx
196 typeset t${dyn}+=foo
197 echo tx=$tx
198 ## STDOUT:
199 sx=foo
200 tx=foo
201 tx=foofoo
202 ## END
203 ## N-I zsh status: 1
204 ## N-I zsh stdout-json: ""
205
206 #### export readonly +=
207
208 export e+=foo
209 echo e=$e
210
211 readonly r+=bar
212 echo r=$r
213
214 set -u
215
216 export e+=foo
217 echo e=$e
218
219 #readonly r+=foo
220 #echo r=$e
221
222 ## STDOUT:
223 e=foo
224 r=bar
225 e=foofoo
226 ## END
227 ## N-I zsh status: 1
228 ## N-I zsh stdout-json: ""
229
230 #### local +=
231
232 f() {
233 local s+=foo
234 echo s=$s
235
236 set -u
237 local s+=foo
238 echo s=$s
239 }
240
241 f
242 ## STDOUT:
243 s=foo
244 s=foofoo
245 ## END
246 ## N-I zsh status: 1
247 ## N-I zsh stdout-json: ""
248
249 #### assign builtin appending array: declare d+=(d e)
250
251 declare d+=(d e)
252 echo "${d[@]}"
253 declare d+=(c l)
254 echo "${d[@]}"
255
256 readonly r+=(r e)
257 echo "${r[@]}"
258 # can't do this again
259
260 f() {
261 local l+=(l o)
262 echo "${l[@]}"
263
264 local l+=(c a)
265 echo "${l[@]}"
266 }
267
268 f
269
270 ## STDOUT:
271 d e
272 d e c l
273 r e
274 l o
275 l o c a
276 ## END
277 ## N-I mksh status: 1
278 ## N-I mksh stdout-json: ""
279 ## N-I zsh status: 1
280 ## N-I zsh stdout-json: ""
281
282 #### export+=array disallowed
283
284 export e+=(e x)
285 echo "${e[@]}"
286
287 ## status: 1
288 ## STDOUT:
289 ## END
290 ## BUG bash status: 0
291 ## BUG bash STDOUT:
292 e x
293 ## END