xref: /titanic_44/usr/src/lib/libshell/common/tests/nameref.sh (revision 4a16f9a6c1cc74aeed5ff36b4723c3e43bc67666)
1########################################################################
2#                                                                      #
3#               This software is part of the ast package               #
4#          Copyright (c) 1982-2010 AT&T Intellectual Property          #
5#                      and is licensed under the                       #
6#                  Common Public License, Version 1.0                  #
7#                    by AT&T Intellectual Property                     #
8#                                                                      #
9#                A copy of the License is available at                 #
10#            http://www.opensource.org/licenses/cpl1.0.txt             #
11#         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         #
12#                                                                      #
13#              Information and Software Systems Research               #
14#                            AT&T Research                             #
15#                           Florham Park NJ                            #
16#                                                                      #
17#                  David Korn <dgk@research.att.com>                   #
18#                                                                      #
19########################################################################
20function err_exit
21{
22	print -u2 -n "\t"
23	print -u2 -r ${Command}[$1]: "${@:2}"
24	let Errors+=1
25}
26alias err_exit='err_exit $LINENO'
27
28Command=${0##*/}
29integer Errors=0
30
31tmp=$(mktemp -dt) || { err_exit mktemp -dt failed; exit 1; }
32trap "cd /; rm -rf $tmp" EXIT
33
34function checkref
35{
36	nameref foo=$1 bar=$2
37	if	[[ $foo !=  $bar ]]
38	then	err_exit "foo=$foo != bar=$bar"
39	fi
40	foo=hello
41	if	[[ $foo !=  $bar ]]
42	then	err_exit "foo=$foo != bar=$bar"
43	fi
44	foo.child=child
45	if	[[ ${foo.child} !=  ${bar.child} ]]
46	then	err_exit "foo.child=${foo.child} != bar=${bar.child}"
47	fi
48}
49
50name=first
51checkref name name
52name.child=second
53checkref name name
54.foo=top
55.foo.bar=next
56checkref .foo.bar .foo.bar
57if	[[ ${.foo.bar} !=  hello ]]
58then	err_exit ".foo.bar=${.foo.bar} != hello"
59fi
60if	[[ ${.foo.bar.child} !=  child ]]
61then	err_exit ".foo.bar.child=${.foo.bar.child} != child"
62fi
63function func1
64{
65        nameref color=$1
66        func2 color
67}
68
69function func2
70{
71        nameref color=$1
72        set -s -- ${!color[@]}
73	print -r -- "$@"
74}
75
76typeset -A color
77color[apple]=red
78color[grape]=purple
79color[banana]=yellow
80if	[[ $(func1 color) != 'apple banana grape' ]]
81then	err_exit "nameref or nameref not working"
82fi
83nameref x=.foo.bar
84if	[[ ${!x} != .foo.bar ]]
85then	err_exit "${!x} not working"
86fi
87typeset +n x $(typeset +n)
88unset x
89nameref x=.foo.bar
90function x.set
91{
92	[[ ${.sh.value} ]] && print hello
93}
94if	[[ $(.foo.bar.set) != $(x.set) ]]
95then	err_exit "function references  not working"
96fi
97if	[[ $(typeset +n) != x ]]
98then	err_exit "typeset +n doesn't list names of reference variables"
99fi
100if	[[ $(typeset -n) != x=.foo.bar ]]
101then	err_exit "typeset +n doesn't list values of reference variables"
102fi
103file=$tmp/test
104typeset +n foo bar 2> /dev/null
105unset foo bar
106export bar=foo
107nameref foo=bar
108if	[[ $foo != foo ]]
109then	err_exit "value of nameref foo !=  $foo"
110fi
111cat > $file <<\!
112print -r -- $foo
113!
114chmod +x "$file"
115y=$( $file)
116if	[[ $y != '' ]]
117then	err_exit "reference variable not cleared"
118fi
119{
120	command nameref xx=yy
121	command nameref yy=xx
122} 2> /dev/null && err_exit "self reference not detected"
123typeset +n foo bar
124unset foo bar
125set foo
126nameref bar=$1
127foo=hello
128if	[[ $bar !=  hello ]]
129then	err_exit 'nameref of positional paramters outside of function not working'
130fi
131unset foo bar
132bar=123
133function foobar
134{
135	typeset -n foo=bar
136	typeset -n foo=bar
137}
138foobar 2> /dev/null || err_exit 'nameref not unsetting previous reference'
139(
140	nameref short=verylong
141	short=( A=a B=b )
142	if	[[ ${verylong.A} != a ]]
143	then	err_exit 'nameref short to longname compound assignment error'
144	fi
145) 2> /dev/null|| err_exit 'nameref short to longname compound assignment error'
146unset x
147if	[[	$(var1=1 var2=2
148		for i in var1 var2
149		do	nameref x=$i
150			print $x
151		done) != $'1\n2' ]]
152then	err_exit 'for loop nameref optimization error'
153fi
154if	[[	$(typeset -A var1 var2
155		var1[sub1]=1 var2[sub2]=1
156		for i in var1 var2
157		do
158		        typeset -n array=$i
159		        print ${!array[*]}
160		done) != $'sub1\nsub2' ]]
161then 	err_exit 'for loop nameref optimization test2 error'
162fi
163
164unset -n x foo bar
165if	[[ $(nameref x=foo;for x in foo bar;do print ${!x};done) != $'foo\nbar' ]]
166then	err_exit 'for loop optimization with namerefs not working'
167fi
168if	[[ $(
169	p=(x=(r=3) y=(r=4))
170	for i in x y
171	do	nameref x=p.$i
172		print ${x.r}
173	done
174) != $'3\n4' ]]
175then	err_exit 'nameref optimization error'
176fi
177[[ $(
178unset x y var
179var=(foo=bar)
180for i in y var
181do	typeset -n x=$i
182	if	[[ ${!x.@} ]]
183	then	print ok
184	fi
185	typeset +n x
186done) != ok ]] && err_exit 'invalid for loop optimization of name references'
187function setval # name value
188{
189        nameref arg=$1
190	nameref var=arg.bar
191	var=$2
192}
193foo=( integer bar=0)
194setval foo 5
195(( foo.bar == 5)) || err_exit 'nested nameref not working'
196function selfref
197{
198        typeset -n ps=$1
199        print -r -- "${ps}"
200}
201ps=(a=1 b=2)
202[[ $(selfref ps) == *a=1* ]] ||  err_exit 'local nameref cannot reference global variable of the same name'
203function subref
204{
205	typeset -n foo=$1
206	print -r -- ${foo.a}
207}
208[[ $(subref ps) == 1 ]] ||  err_exit 'local nameref cannot reference global variable child'
209
210function local
211{
212	typeset ps=(typeset -i a=3 b=4)
213	[[ $(subref ps) == 3 ]] ||  err_exit 'local nameref cannot reference caller compound variable'
214}
215local
216unset -f local
217function local
218{
219	qs=(integer  a=3; integer b=4)
220}
221local 2> /dev/null || err_exit 'function local has non-zero exit status'
222[[ ${qs.a} == 3 ]] || err_exit 'function cannot set compound global variable'
223unset fun i
224foo=(x=hi)
225function fun
226{
227        nameref i=$1
228        print -r -- "${i.x}"
229}
230i=foo
231[[ $(fun $i) == hi ]] || err_exit 'nameref for compound variable with in function name of caller fails'
232unset -n foo bar
233typeset -A foo
234foo[x.y]=(x=3 y=4)
235nameref bar=foo[x.y]
236[[ ${bar.x} == 3 ]] || err_exit 'nameref to subscript containing . fails'
237[[ ${!bar} == 'foo[x.y]' ]] || err_exit '${!var} not correct for nameref to an array instance'
238typeset +n bar
239nameref bar=foo
240[[ ${!bar} == foo ]] || err_exit '${!var} not correct for nameref to array variable'
241$SHELL -c 'function bar { nameref x=foo[++];};typeset -A foo;bar' 2> /dev/null ||err_exit 'nameref of associative array tries to evaluate subscript'
242i=$($SHELL -c 'nameref foo=bar; bar[2]=(x=3 y=4); nameref x=foo[2].y;print -r -- $x' 2> /dev/null)
243[[ $i == 4 ]] || err_exit 'creating reference from subscripted variable whose name is a reference failed'
244[[ $($SHELL 2> /dev/null <<- '+++EOF'
245	function bar
246	{
247	 	nameref x=$1
248	 	print -r -- "$x"
249	}
250	function foo
251	{
252	 	typeset var=( foo=hello)
253	 	bar var
254	}
255	foo
256+++EOF
257) ==  *foo=hello* ]] || err_exit 'unable to display compound variable from name reference of local variable'
258#set -x
259for c in '=' '[' ']' '\' "'" '"' '<' '=' '('
260do	[[ $($SHELL 2> /dev/null <<- ++EOF++
261	x;i=\\$c;typeset -A a; a[\$i]=foo;typeset -n x=a[\$i]; print "\$x"
262	++EOF++
263) != foo ]] && err_exit 'nameref x=[$c] '"not working for c=$c"
264done
265unset -n foo x
266unset foo x
267typeset -A foo
268nameref x=foo[xyz]
269foo[xyz]=ok
270[[ $x == ok ]] || err_exit 'nameref to unset subscript not working'
271function function2
272{
273	nameref v=$1
274	v.x=19 v.y=20
275}
276function function1
277{
278	typeset compound_var=()
279	function2 compound_var
280	printf "x=%d, y=%d\n" compound_var.x compound_var.y
281}
282x="$(function1)"
283[[ "$x" != 'x=19, y=20' ]] && err_exit "expected 'x=19, y=20', got '${x}'"
284typeset +n bar
285unset foo bar
286[[ $(function a
287{
288	for i in  foo bar
289	do	typeset -n v=$i
290		print $v
291	done | cat
292}
293foo=1 bar=2;a) == $'1\n2' ]] 2> /dev/null || err_exit 'nameref in pipeline broken'
294function a
295{
296	typeset -n v=vars.data._1
297	print "${v.a} ${v.b}"
298}
299vars=(data=())
300vars.data._1.a=a.1
301vars.data._1.b=b.1
302[[ $(a) == 'a.1 b.1' ]] || err_exit 'nameref choosing wrong scope -- '
303typeset +n bam zip foo
304unset bam zip foo
305typeset -A foo
306foo[2]=bar
307typeset -n bam=foo[2]
308typeset -n zip=bam
309[[ $zip == bar ]] || err_exit 'nameref to another nameref to array element fails'
310[[ -R zip ]] || err_exit '[[ -R zip ]] should detect that zip is a reference'
311[[ -R bam ]] || err_exit '[[ -R bam ]] should detect that bam is a reference'
312[[ -R zip ]] || err_exit '[[ -v zip ]] should detect that zip is set'
313[[ -v bam ]] || err_exit '[[ -v bam ]] should detect that bam is set'
314[[ -R 123 ]] && err_exit '[[ -R 123 ]] should detect that 123 is not a reference'
315[[ -v 123 ]] && err_exit '[[ -v 123 ]] should detect that 123 is not set'
316
317unset ref x
318typeset -n ref
319x=3
320function foobar
321{
322	typeset xxx=3
323	ref=xxx
324	return 0
325}
326foobar 2> /dev/null && err_exit 'invalid reference should cause foobar to fail'
327[[ -v ref ]] && err_exit '$ref should be unset'
328ref=x
329[[ $ref == 3 ]] || err_exit "\$ref is $ref, it should be 3"
330function foobar
331{
332        typeset fvar=()
333        typeset -n ref=fvar.foo
334        ref=ok
335        print -r $ref
336}
337[[ $(foobar) ==  ok ]] 2> /dev/null  || err_exit 'nameref in function not creating variable in proper scope'
338function foobar
339{
340        nameref doc=docs
341        nameref bar=doc.num
342	[[ $bar == 2 ]] || err_exit 'nameref scoping error'
343}
344
345docs=(num=2)
346foobar
347
348typeset +n x y
349unset x y
350typeset -A x
351x[a]=(b=c)
352typeset -n y=x[a]
353[[ ${!y.@} == 'x[a].b' ]] || err_exit 'reference to array element not expanded with ${!y.@}'
354
355typeset +n v
356v=()
357k=a.b.c/d
358command typeset -n n=v.${k//['./']/_} 2> /dev/null || err_exit 'patterns with quotes not handled correctly with name reference assignment'
359
360typeset _n sp
361nameref sp=addrsp
362sp[14]=( size=1 )
363[[ -v sp[19] ]]  && err_exit '[[ -v sp[19] ]] where sp is a nameref should not be set'
364
365exit $((Errors))
366