1#
2# CDDL HEADER START
3#
4# The contents of this file are subject to the terms of the
5# Common Development and Distribution License (the "License").
6# You may not use this file except in compliance with the License.
7#
8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9# or http://www.opensolaris.org/os/licensing.
10# See the License for the specific language governing permissions
11# and limitations under the License.
12#
13# When distributing Covered Code, include this CDDL HEADER in each
14# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15# If applicable, add the following below this CDDL HEADER, with the
16# fields enclosed by brackets "[]" replaced with your own identifying
17# information: Portions Copyright [yyyy] [name of copyright owner]
18#
19# CDDL HEADER END
20#
21
22#
23# Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
24#
25
26#
27# This test module checks whether indexed+associative arrays
28# set the default datatype correctly if someone uses the "+="
29# operator to add a value to an array element which does not
30# exist yet.
31#
32
33# test setup
34function err_exit
35{
36	print -u2 -n "\t"
37	print -u2 -r ${Command}[$1]: "${@:2}"
38	(( Errors < 127 && Errors++ ))
39}
40alias err_exit='err_exit $LINENO'
41
42# the test cannot use "nounset"
43Command=${0##*/}
44integer Errors=0
45
46compound bracketstat=(
47	integer bopen=0
48	integer bclose=0
49)
50
51function count_brackets
52{
53	typeset x="$1"
54	typeset c
55
56	integer i
57	(( bracketstat.bopen=0 , bracketstat.bclose=0 ))
58
59	for (( i=0 ; i < ${#x} ; i++ )) ; do
60	        c="${x:i:1}"
61		[[ "$c" == "(" ]] && (( bracketstat.bopen++ ))
62		[[ "$c" == ")" ]] && (( bracketstat.bclose++ ))
63	done
64
65	(( bracketstat.bopen != bracketstat.bclose )) && return 1
66
67	return 0
68}
69
70# function to add the floating-point value 1.1 to array element "34"
71# floating-point datatypes should increment by 1.1, integers by 1
72function add_float
73{
74	nameref arr=$1
75
76	arr[34]+=1.1
77
78	return 0
79}
80
81# function to add a compound variable called "val" to array element arr[34]
82function add_compound
83{
84	nameref arr=$1
85
86	arr[34]+=( float val=1.1 )
87
88	return 0
89}
90
91# We run the tests in multiple cyles:
92# First cycle uses a normal compound variable as basis
93# Second cycle uses a nameref to a compound variable as basis
94# Third cycle uses a nameref to a nameref to a compound variable as basis
95for cycle in \
96	c1 c2 c3 c4 \
97	c2_sub c3_sub c4_sub \
98	c2_indexed_array c3_indexed_array c4_indexed_array \
99	c2_associative_array c3_associative_array c4_associative_array; do
100	case ${cycle} in
101		c1)
102			compound mycpv
103			;;
104		c2)
105			compound rootcpv
106			nameref mycpv=rootcpv
107			;;
108		c3)
109			compound rootcpv
110			nameref namereftoroot=rootcpv
111			nameref mycpv=namereftoroot
112			;;
113		c4)
114			compound rootcpv
115			nameref namereftoroot0=rootcpv
116			nameref namereftoroot1=namereftoroot0
117			nameref mycpv=namereftoroot1
118			;;
119		# same as cX but uses a subvariable of rootcpv
120		c2_sub)
121			compound rootcpv
122			compound rootcpv.sub
123			nameref mycpv=rootcpv.sub
124			;;
125		c3_sub)
126			compound rootcpv
127			compound rootcpv.sub
128			nameref namereftoroot=rootcpv.sub
129			nameref mycpv=namereftoroot
130			;;
131		c4_sub)
132			compound rootcpv
133			compound rootcpv.sub
134			nameref namereftoroot0=rootcpv.sub
135			nameref namereftoroot1=namereftoroot0
136			nameref mycpv=namereftoroot1
137			;;
138		# same as cX but uses a subvariable of an indexed array
139		c2_indexed_array)
140			compound -a rootcpv
141			nameref mycpv=rootcpv[4]
142			;;
143		c3_indexed_array)
144			compound -a rootcpv
145			nameref namereftoroot=rootcpv[4]
146			nameref mycpv=namereftoroot
147			;;
148		c4_indexed_array)
149			compound -a rootcpv
150			nameref namereftoroot0=rootcpv[4]
151			nameref namereftoroot1=namereftoroot0
152			nameref mycpv=namereftoroot1
153			;;
154		# same as cX but uses a subvariable of an indexed array
155		c2_associative_array)
156			compound -A rootcpv
157			nameref mycpv=rootcpv["hello world"]
158			;;
159		c3_associative_array)
160			compound -A rootcpv
161			nameref namereftoroot=rootcpv["hello world"]
162			nameref mycpv=namereftoroot
163			;;
164		c4_associative_array)
165			compound -A rootcpv
166			nameref namereftoroot0=rootcpv["hello world"]
167			nameref namereftoroot1=namereftoroot0
168			nameref mycpv=namereftoroot1
169			;;
170		*)
171			err_exit "${cycle}: Should not happen."
172			;;
173	esac
174
175
176	# Test 001: Test indexed floating-point array
177	float -a mycpv.myindexedfloatarray
178
179	add_float mycpv.myindexedfloatarray
180	(( mycpv.myindexedfloatarray[34] == 1.1 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 1.1"
181	add_float mycpv.myindexedfloatarray
182	(( mycpv.myindexedfloatarray[34] == 2.2 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 2.2"
183	unset mycpv.myindexedfloatarray[34]
184	(( mycpv.myindexedfloatarray[34] == 0.0 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 0.0"
185
186	# 2nd try (we do this to check whether "unset" works properly)
187	add_float mycpv.myindexedfloatarray
188	(( mycpv.myindexedfloatarray[34] == 1.1 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 1.1"
189	add_float mycpv.myindexedfloatarray
190	(( mycpv.myindexedfloatarray[34] == 2.2 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 2.2"
191	unset mycpv.myindexedfloatarray[34]
192	(( mycpv.myindexedfloatarray[34] == 0.0 )) || err_exit "${cycle}: mycpv.myindexedfloatarray[34] == ${mycpv.myindexedfloatarray[34]}, expected 0.0"
193
194
195
196	# Test 002: Test associative floating-point array
197	float -A mycpv.myassociativefloatarray
198	add_float mycpv.myassociativefloatarray
199	(( mycpv.myassociativefloatarray[34] == 1.1 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 1.1"
200	add_float mycpv.myassociativefloatarray
201	(( mycpv.myassociativefloatarray[34] == 2.2 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 2.2"
202	unset mycpv.myassociativefloatarray[34]
203	(( mycpv.myassociativefloatarray[34] == 0.0 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 0.0"
204
205	# 2nd try (we do this to check whether "unset" works properly)
206	add_float mycpv.myassociativefloatarray
207	(( mycpv.myassociativefloatarray[34] == 1.1 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 1.1"
208	add_float mycpv.myassociativefloatarray
209	(( mycpv.myassociativefloatarray[34] == 2.2 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 2.2"
210	unset mycpv.myassociativefloatarray[34]
211	(( mycpv.myassociativefloatarray[34] == 0.0 )) || err_exit "${cycle}: mycpv.myassociativefloatarray[34] == ${mycpv.myassociativefloatarray[34]}, expected 0.0"
212
213
214
215	# Test 003: Test indexed integer array
216	integer -a mycpv.myindexedintegerarray
217
218	add_float mycpv.myindexedintegerarray
219	(( mycpv.myindexedintegerarray[34] == 1 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 1"
220	add_float mycpv.myindexedintegerarray
221	(( mycpv.myindexedintegerarray[34] == 2 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 2"
222	unset mycpv.myindexedintegerarray[34]
223	(( mycpv.myindexedintegerarray[34] == 0 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 0"
224
225	# 2nd try (we do this to check whether "unset" works properly)
226	add_float mycpv.myindexedintegerarray
227	(( mycpv.myindexedintegerarray[34] == 1 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 1"
228	add_float mycpv.myindexedintegerarray
229	(( mycpv.myindexedintegerarray[34] == 2 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 2"
230	unset mycpv.myindexedintegerarray[34]
231	(( mycpv.myindexedintegerarray[34] == 0 )) || err_exit "${cycle}: mycpv.myindexedintegerarray[34] == ${mycpv.myindexedintegerarray[34]}, expected 0"
232
233
234
235	# Test 004: Test associative integer array
236	integer -A mycpv.myassociativeintegerarray
237
238	add_float mycpv.myassociativeintegerarray
239	(( mycpv.myassociativeintegerarray[34] == 1 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 1"
240	add_float mycpv.myassociativeintegerarray
241	(( mycpv.myassociativeintegerarray[34] == 2 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 2"
242	unset mycpv.myassociativeintegerarray[34]
243	(( mycpv.myassociativeintegerarray[34] == 0 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 0"
244
245	# 2nd try (we do this to check whether "unset" works properly)
246	add_float mycpv.myassociativeintegerarray
247	(( mycpv.myassociativeintegerarray[34] == 1 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 1"
248	add_float mycpv.myassociativeintegerarray
249	(( mycpv.myassociativeintegerarray[34] == 2 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 2"
250	unset mycpv.myassociativeintegerarray[34]
251	(( mycpv.myassociativeintegerarray[34] == 0 )) || err_exit "${cycle}: mycpv.myassociativeintegerarray[34] == ${mycpv.myassociativeintegerarray[34]}, expected 0"
252
253
254
255	# Test 005: Tested indexed compound variable array
256	compound -a mycpv.myindexedcompoundarray
257	add_compound mycpv.myindexedcompoundarray
258	(( mycpv.myindexedcompoundarray[34].val == 1.1 )) || err_exit "${cycle}: mycpv.myindexedcompoundarray[34].val == ${mycpv.myindexedcompoundarray[34].val}, expected 1.1"
259	# try to add it a 2nd time - since the new element will replace the old
260	# one the value will _not_ be incremented (or better: The compound
261	# variable value "val" will be added, not the value of the "val"
262	# variable)
263	add_compound mycpv.myindexedcompoundarray
264	(( mycpv.myindexedcompoundarray[34].val == 1.1 )) || err_exit "${cycle}: mycpv.myindexedcompoundarray[34].val == ${mycpv.myindexedcompoundarray[34].val}, expected 1.1"
265	unset mycpv.myindexedcompoundarray[34]
266	[[ ! -v mycpv.myindexedcompoundarray[34].val ]] || err_exit "${cycle}: [[ ! -v mycpv.myindexedcompoundarray[34].val ]] should return failure, got $?"
267	(( mycpv.myindexedcompoundarray[34].val == 0.0 )) || err_exit "${cycle}: mycpv.myindexedcompoundarray[34].val == ${mycpv.myindexedcompoundarray[34].val}, expected 0.0"
268	[[ "${mycpv.myindexedcompoundarray[34]}" == "" ]] || err_exit "${cycle}: mycpv.myindexedcompoundarray[34] expected to be equal to an empty string but contains |${mycpv.myindexedcompoundarray[34]}|"
269
270
271
272	# Test 006: Tested associative compound variable array
273	compound -A mycpv.myassociativecompoundarray
274	add_compound mycpv.myassociativecompoundarray
275	(( mycpv.myassociativecompoundarray[34].val == 1.1 )) || err_exit "${cycle}: mycpv.myassociativecompoundarray[34].val == ${mycpv.myassociativecompoundarray[34].val}, expected 1.1"
276	# try to add it a 2nd time - since the new element will replace the old
277	# one the value will _not_ be incremented (or better: The compound
278	# variable value "val" will be added, not the value of the "val"
279	# variable)
280	add_compound mycpv.myassociativecompoundarray
281	(( mycpv.myassociativecompoundarray[34].val == 1.1 )) || err_exit "${cycle}: mycpv.myassociativecompoundarray[34].val == ${mycpv.myassociativecompoundarray[34].val}, expected 1.1"
282	unset mycpv.myassociativecompoundarray[34]
283	[[ ! -v mycpv.myassociativecompoundarray[34].val ]] || err_exit "${cycle}: [[ ! -v mycpv.myassociativecompoundarray[34].val ]] should return failure, got $?"
284	(( mycpv.myassociativecompoundarray[34].val == 0.0 )) || err_exit "${cycle}: mycpv.myassociativecompoundarray[34].val == ${mycpv.myassociativecompoundarray[34].val}, expected 0.0"
285	[[ "${mycpv.myassociativecompoundarray[34]}" == "" ]] || err_exit "${cycle}: mycpv.myassociativecompoundarray[34] expected to be equal to an empty string but contains |${mycpv.myassociativecompoundarray[34]}|"
286
287
288	# check whether the compound variable output is still Ok
289	count_brackets "${mycpv}" || err_exit "${cycle}: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
290	count_brackets "$(print -v mycpv)" || err_exit "${cycle}: print -v mycpy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
291	count_brackets "$(print -C mycpv)" || err_exit "${cycle}: print -C mycpy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}"
292
293
294	# reset
295	unset mycpv
296	[[ ! -v mycpv ]] || err_exit "${cycle}: mycpy should not exist"
297	[[ "${mycpv}" == "" ]] || err_exit "${cycle}: mycpv expected to be empty"
298done
299
300
301# tests done
302exit $((Errors))
303