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# test setup 27function err_exit 28{ 29 print -u2 -n "\t" 30 print -u2 -r ${Command}[$1]: "${@:2}" 31 (( Errors < 127 && Errors++ )) 32} 33alias err_exit='err_exit $LINENO' 34 35# "nounset" disabled for now 36#set -o nounset 37Command=${0##*/} 38integer Errors=0 39 40compound bracketstat=( 41 integer bopen=0 42 integer bclose=0 43) 44 45function count_brackets 46{ 47 typeset x="$1" 48 typeset c 49 50 integer i 51 (( bracketstat.bopen=0 , bracketstat.bclose=0 )) 52 53 for (( i=0 ; i < ${#x} ; i++ )) ; do 54 c="${x:i:1}" 55 [[ "$c" == "(" ]] && (( bracketstat.bopen++ )) 56 [[ "$c" == ")" ]] && (( bracketstat.bclose++ )) 57 done 58 59 (( bracketstat.bopen != bracketstat.bclose )) && return 1 60 61 return 0 62} 63 64# compound variable "cat" nr.1, using $ print "%B\n" ... # 65function cpvcat1 66{ 67 set -o errexit 68 compound tmp 69 70 while read -C tmp ; do printf "%B\n" tmp ; done 71 return 0 72} 73 74# compound variable "cat" nr.2, using $ print "%#B\n" ... # 75function cpvcat2 76{ 77 set -o errexit 78 compound tmp 79 80 while read -C tmp ; do printf "%#B\n" tmp ; done 81 return 0 82} 83 84# compound variable "cat" nr.3, using $ print -C ... # 85function cpvcat3 86{ 87 set -o errexit 88 compound tmp 89 90 while read -C tmp ; do print -C tmp ; done 91 return 0 92} 93 94# compound variable "cat" nr.4, using $ print -v ... # 95function cpvcat4 96{ 97 set -o errexit 98 compound tmp 99 100 while read -C tmp ; do print -v tmp ; done 101 return 0 102} 103 104typeset s 105 106# Test 1: 107# Check whether "read -C" leaves the file pointer at the next line 108# (and does not read beyond that point). 109# Data layout is: 110# -- snip -- 111# <compound var> 112# hello 113# -- snip -- 114# (additionally we test some extra stuff like bracket count) 115s=${ 116 compound x=( 117 a=1 b=2 118 typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 ) 119 typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 ) 120 typeset -A myarray3=( 121 [a]=( 122 float m1=0.5 123 float m2=0.6 124 foo="hello" 125 ) 126 [b]=( 127 foo="bar" 128 ) 129 ["c d"]=( 130 integer at=90 131 ) 132 [e]=( 133 compound nested_cpv=( 134 typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 ) 135 typeset str=$'a \'string' 136 ) 137 ) 138 [f]=( 139 typeset g="f" 140 ) 141 [a_nan]=( 142 float my_nan=-nan 143 ) 144 [a_hexfloat]=( 145 typeset -X my_hexfloat=1.1 146 ) 147 ) 148 ) 149 150 { 151 printf "%B\n" x 152 print "hello" 153 } | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | { 154 read -C y 155 read s 156 } 157 print "x${s}x" 158} || err_exit "test returned exit code $?" 159 160[[ "${s}" == "xhellox" ]] || err_exit "Expected 'xhellox', got ${s}" 161count_brackets "$y" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 162count_brackets "$(print -v y)" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 163count_brackets "$(print -C y)" || err_exit "y: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 164 165# cleanup 166unset x y || err_exit "unset failed" 167[[ "$x" == "" ]] || err_exit "cleanup failed for x" 168[[ "$y" == "" ]] || err_exit "cleanup failed for y" 169 170 171# Test 2: 172# Same as test 1 except one more compound var following the "hello" 173# line. 174# Data layout is: 175# -- snip -- 176# <compound var> 177# hello 178# <compound var> 179# -- snip -- 180s=${ 181 compound x=( 182 a=1 b=2 183 typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 ) 184 typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 ) 185 compound -A myarray3=( 186 [a]=( 187 float m1=0.5 188 float m2=0.6 189 foo="hello" 190 ) 191 [b]=( 192 foo="bar" 193 ) 194 ["c d"]=( 195 integer at=90 196 ) 197 [e]=( 198 compound nested_cpv=( 199 typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 ) 200 typeset str=$'a \'string' 201 ) 202 ) 203 [f]=( 204 typeset g="f" 205 ) 206 [a_nan]=( 207 float my_nan=-nan 208 ) 209 [a_hexfloat]=( 210 typeset -X my_hexfloat=1.1 211 ) 212 ) 213 ) 214 215 { 216 printf "%B\n" x 217 print "hello" 218 printf "%B\n" x 219 } | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | { 220 read -C y1 221 read s 222 read -C y2 223 } 224 225 print "x${s}x" 226} || err_exit "test returned exit code $?" 227 228[[ "${s}" == "xhellox" ]] || err_exit "Expected 'xhellox', got ${s}." 229[[ "${y1.myarray3[b].foo}" == "bar" ]] || err_exit "y1.myarray3[b].foo != bar" 230[[ "${y2.myarray3[b].foo}" == "bar" ]] || err_exit "y2.myarray3[b].foo != bar" 231[[ "$y1" != "" ]] || err_exit "y1 is empty" 232[[ "$y2" != "" ]] || err_exit "y2 is empty" 233(( ${#y1.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in y1.myarray3[e].nested_cpv, got ${#y1.myarray3[e].nested_cpv[@]}" 234(( ${#y2.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in y2.myarray3[e].nested_cpv, got ${#y2.myarray3[e].nested_cpv[@]}" 235(( isnan(y1.myarray3[a_nan].my_nan) )) || err_exit "y1.myarray3[a_nan].my_nan not a NaN" 236(( isnan(y2.myarray3[a_nan].my_nan) )) || err_exit "y2.myarray3[a_nan].my_nan not a NaN" 237(( signbit(y1.myarray3[a_nan].my_nan) )) || err_exit "y1.myarray3[a_nan].my_nan not negative" 238(( signbit(y2.myarray3[a_nan].my_nan) )) || err_exit "y2.myarray3[a_nan].my_nan not negative" 239count_brackets "$y1" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 240count_brackets "$(print -v y1)" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 241count_brackets "$(print -C y1)" || err_exit "y1: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 242count_brackets "$y2" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 243count_brackets "$(print -v y2)" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 244count_brackets "$(print -C y2)" || err_exit "y2: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 245[[ "$y1" == "$y2" ]] || err_exit "Expected $(printf "%q\n" "${y1}") == $(printf "%q\n" "${y2}")." 246[[ "$x" == "$y1" ]] || err_exit "Expected $(printf "%q\n" "${x}") == $(printf "%q\n" "${y}")." 247 248# cleanup 249unset x y1 y2 || err_exit "unset failed" 250[[ "$x" == "" ]] || err_exit "cleanup failed for x" 251[[ "$y1" == "" ]] || err_exit "cleanup failed for y1" 252[[ "$y2" == "" ]] || err_exit "cleanup failed for y2" 253 254 255# Test 3: Test compound variable copy operator vs. "read -C" 256compound x=( 257 a=1 b=2 258 typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 ) 259 typeset -A myarray2=( [a]=1 [b]=2 ["c d"]=3 [e]=4 ["f"]=5 [g]=6 [h]=7 [i]=8 [j]=9 [k]=10 ) 260 compound -A myarray3=( 261 [a]=( 262 float m1=0.5 263 float m2=0.6 264 foo="hello" 265 ) 266 [b]=( 267 foo="bar" 268 ) 269 ["c d"]=( 270 integer at=90 271 ) 272 [e]=( 273 compound nested_cpv=( 274 typeset -a myarray=( 1 2 3 4 5 6 7 8 9 10 ) 275 typeset str=$'a \'string' 276 ) 277 ) 278 [f]=( 279 typeset g="f" 280 ) 281 [a_nan]=( 282 float my_nan=-nan 283 ) 284 [a_hexfloat]=( 285 typeset -X my_hexfloat=1.1 286 ) 287 ) 288) 289 290compound x_copy=x || err_exit "x_copy copy failed" 291[[ "${x_copy}" != "" ]] || err_exit "x_copy should not be empty" 292count_brackets "${x_copy}" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 293count_brackets "$(print -v x_copy)" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 294count_brackets "$(print -C x_copy)" || err_exit "x_copy: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 295 296compound nested_cpv_copy 297 298nested_cpv_copy=x.myarray3[e].nested_cpv || err_exit "x.myarray3[e].nested_cpv copy failed" 299(( ${#nested_cpv_copy.myarray[@]} == 10 )) || err_exit "Expected 10 elements in nested_cpv_copy.myarray, got ${#nested_cpv_copy.myarray[@]}" 300 301# unset branch "x.myarray3[e].nested_cpv" of the variable tree "x" ... 302unset x.myarray3[e].nested_cpv || err_exit "unset x.myarray3[e].nested_cpv failed" 303[[ "${x.myarray3[e].nested_cpv}" == "" ]] || err_exit "x.myarray3[e].nested_cpv still has a value" 304 305# ... and restore it from the saved copy 306printf "%B\n" nested_cpv_copy | cpvcat1 | cpvcat2 | cpvcat3 | cpvcat4 | read -C x.myarray3[e].nested_cpv || err_exit "read failed" 307 308# compare copy of the original tree and the modified one 309[[ "${x}" == "${x_copy}" ]] || err_exit "x != x_copy" 310count_brackets "${x}" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 311count_brackets "$(print -v x)" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 312count_brackets "$(print -C x)" || err_exit "x: bracket open ${bracketstat.bopen} != bracket close ${bracketstat.bclose}" 313(( ${#x.myarray3[e].nested_cpv.myarray[@]} == 10 )) || err_exit "Expected 10 elements in x.myarray3[e].nested_cpv, got ${#x.myarray3[e].nested_cpv[@]}" 314(( isnan(x.myarray3[a_nan].my_nan) )) || err_exit "x.myarray3[a_nan].my_nan not a NaN" 315(( signbit(x.myarray3[a_nan].my_nan) )) || err_exit "x.myarray3[a_nan].my_nan not negative" 316 317# cleanup 318unset x x_copy nested_cpv_copy || err_exit "unset failed" 319 320 321# Test 4: Test "read -C" failure for missing bracket at the end 322typeset s 323s=$($SHELL -c 'compound myvar ; print "( unfinished=1" | read -C myvar 2>/dev/null || print "error $?"') || err_exit "shell failed" 324[[ "$s" == "error 3" ]] || err_exit "compound_read: expected error 3, got ${s}" 325 326 327# Test 5: Test "read -C" failure for missing bracket at the beginning 328typeset s 329s=$($SHELL -c 'compound myvar ; print " unfinished=1 )" | read -C myvar 2>/dev/null || print "error $?"') || err_exit "shell failed" 330[[ "$s" == "error 3" ]] || err_exit "compound_read: expected error 3, got ${s}" 331 332 333# tests done 334exit $((Errors)) 335