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