xref: /onnv-gate/usr/src/cmd/perl/5.8.4/distrib/t/op/hashassign.t (revision 0:68f95e015346)
1*0Sstevel@tonic-gate#!./perl -w
2*0Sstevel@tonic-gate
3*0Sstevel@tonic-gateBEGIN {
4*0Sstevel@tonic-gate    chdir 't' if -d 't';
5*0Sstevel@tonic-gate    @INC = '../lib';
6*0Sstevel@tonic-gate    require './test.pl';
7*0Sstevel@tonic-gate}
8*0Sstevel@tonic-gate
9*0Sstevel@tonic-gate# use strict;
10*0Sstevel@tonic-gate
11*0Sstevel@tonic-gateplan tests => 213;
12*0Sstevel@tonic-gate
13*0Sstevel@tonic-gatemy @comma = ("key", "value");
14*0Sstevel@tonic-gate
15*0Sstevel@tonic-gate# The peephole optimiser already knows that it should convert the string in
16*0Sstevel@tonic-gate# $foo{string} into a shared hash key scalar. It might be worth making the
17*0Sstevel@tonic-gate# tokeniser build the LHS of => as a shared hash key scalar too.
18*0Sstevel@tonic-gate# And so there's the possiblility of it going wrong
19*0Sstevel@tonic-gate# And going right on 8 bit but wrong on utf8 keys.
20*0Sstevel@tonic-gate# And really we should also try utf8 literals in {} and => in utf8.t
21*0Sstevel@tonic-gate
22*0Sstevel@tonic-gate# Some of these tests are (effectively) duplicated in each.t
23*0Sstevel@tonic-gatemy %comma = @comma;
24*0Sstevel@tonic-gateok (keys %comma == 1, 'keys on comma hash');
25*0Sstevel@tonic-gateok (values %comma == 1, 'values on comma hash');
26*0Sstevel@tonic-gate# defeat any tokeniser or optimiser cunning
27*0Sstevel@tonic-gatemy $key = 'ey';
28*0Sstevel@tonic-gateis ($comma{"k" . $key}, "value", 'is key present? (unoptimised)');
29*0Sstevel@tonic-gate# now with cunning:
30*0Sstevel@tonic-gateis ($comma{key}, "value", 'is key present? (maybe optimised)');
31*0Sstevel@tonic-gate#tokeniser may treat => differently.
32*0Sstevel@tonic-gatemy @temp = (key=>undef);
33*0Sstevel@tonic-gateis ($comma{$temp[0]}, "value", 'is key present? (using LHS of =>)');
34*0Sstevel@tonic-gate
35*0Sstevel@tonic-gate@temp = %comma;
36*0Sstevel@tonic-gateok (eq_array (\@comma, \@temp), 'list from comma hash');
37*0Sstevel@tonic-gate
38*0Sstevel@tonic-gate@temp = each %comma;
39*0Sstevel@tonic-gateok (eq_array (\@comma, \@temp), 'first each from comma hash');
40*0Sstevel@tonic-gate@temp = each %comma;
41*0Sstevel@tonic-gateok (eq_array ([], \@temp), 'last each from comma hash');
42*0Sstevel@tonic-gate
43*0Sstevel@tonic-gatemy %temp = %comma;
44*0Sstevel@tonic-gate
45*0Sstevel@tonic-gateok (keys %temp == 1, 'keys on copy of comma hash');
46*0Sstevel@tonic-gateok (values %temp == 1, 'values on copy of comma hash');
47*0Sstevel@tonic-gateis ($temp{'k' . $key}, "value", 'is key present? (unoptimised)');
48*0Sstevel@tonic-gate# now with cunning:
49*0Sstevel@tonic-gateis ($temp{key}, "value", 'is key present? (maybe optimised)');
50*0Sstevel@tonic-gate@temp = (key=>undef);
51*0Sstevel@tonic-gateis ($comma{$temp[0]}, "value", 'is key present? (using LHS of =>)');
52*0Sstevel@tonic-gate
53*0Sstevel@tonic-gate@temp = %temp;
54*0Sstevel@tonic-gateok (eq_array (\@temp, \@temp), 'list from copy of comma hash');
55*0Sstevel@tonic-gate
56*0Sstevel@tonic-gate@temp = each %temp;
57*0Sstevel@tonic-gateok (eq_array (\@temp, \@temp), 'first each from copy of comma hash');
58*0Sstevel@tonic-gate@temp = each %temp;
59*0Sstevel@tonic-gateok (eq_array ([], \@temp), 'last each from copy of comma hash');
60*0Sstevel@tonic-gate
61*0Sstevel@tonic-gatemy @arrow = (Key =>"Value");
62*0Sstevel@tonic-gate
63*0Sstevel@tonic-gatemy %arrow = @arrow;
64*0Sstevel@tonic-gateok (keys %arrow == 1, 'keys on arrow hash');
65*0Sstevel@tonic-gateok (values %arrow == 1, 'values on arrow hash');
66*0Sstevel@tonic-gate# defeat any tokeniser or optimiser cunning
67*0Sstevel@tonic-gate$key = 'ey';
68*0Sstevel@tonic-gateis ($arrow{"K" . $key}, "Value", 'is key present? (unoptimised)');
69*0Sstevel@tonic-gate# now with cunning:
70*0Sstevel@tonic-gateis ($arrow{Key}, "Value", 'is key present? (maybe optimised)');
71*0Sstevel@tonic-gate#tokeniser may treat => differently.
72*0Sstevel@tonic-gate@temp = ('Key', undef);
73*0Sstevel@tonic-gateis ($arrow{$temp[0]}, "Value", 'is key present? (using LHS of =>)');
74*0Sstevel@tonic-gate
75*0Sstevel@tonic-gate@temp = %arrow;
76*0Sstevel@tonic-gateok (eq_array (\@arrow, \@temp), 'list from arrow hash');
77*0Sstevel@tonic-gate
78*0Sstevel@tonic-gate@temp = each %arrow;
79*0Sstevel@tonic-gateok (eq_array (\@arrow, \@temp), 'first each from arrow hash');
80*0Sstevel@tonic-gate@temp = each %arrow;
81*0Sstevel@tonic-gateok (eq_array ([], \@temp), 'last each from arrow hash');
82*0Sstevel@tonic-gate
83*0Sstevel@tonic-gate%temp = %arrow;
84*0Sstevel@tonic-gate
85*0Sstevel@tonic-gateok (keys %temp == 1, 'keys on copy of arrow hash');
86*0Sstevel@tonic-gateok (values %temp == 1, 'values on copy of arrow hash');
87*0Sstevel@tonic-gateis ($temp{'K' . $key}, "Value", 'is key present? (unoptimised)');
88*0Sstevel@tonic-gate# now with cunning:
89*0Sstevel@tonic-gateis ($temp{Key}, "Value", 'is key present? (maybe optimised)');
90*0Sstevel@tonic-gate@temp = ('Key', undef);
91*0Sstevel@tonic-gateis ($arrow{$temp[0]}, "Value", 'is key present? (using LHS of =>)');
92*0Sstevel@tonic-gate
93*0Sstevel@tonic-gate@temp = %temp;
94*0Sstevel@tonic-gateok (eq_array (\@temp, \@temp), 'list from copy of arrow hash');
95*0Sstevel@tonic-gate
96*0Sstevel@tonic-gate@temp = each %temp;
97*0Sstevel@tonic-gateok (eq_array (\@temp, \@temp), 'first each from copy of arrow hash');
98*0Sstevel@tonic-gate@temp = each %temp;
99*0Sstevel@tonic-gateok (eq_array ([], \@temp), 'last each from copy of arrow hash');
100*0Sstevel@tonic-gate
101*0Sstevel@tonic-gatemy %direct = ('Camel', 2, 'Dromedary', 1);
102*0Sstevel@tonic-gatemy %slow;
103*0Sstevel@tonic-gate$slow{Dromedary} = 1;
104*0Sstevel@tonic-gate$slow{Camel} = 2;
105*0Sstevel@tonic-gate
106*0Sstevel@tonic-gateok (eq_hash (\%slow, \%direct), "direct list assignment to hash");
107*0Sstevel@tonic-gate%direct = (Camel => 2, 'Dromedary' => 1);
108*0Sstevel@tonic-gateok (eq_hash (\%slow, \%direct), "direct list assignment to hash using =>");
109*0Sstevel@tonic-gate
110*0Sstevel@tonic-gate$slow{Llama} = 0; # A llama is not a camel :-)
111*0Sstevel@tonic-gateok (!eq_hash (\%direct, \%slow), "different hashes should not be equal!");
112*0Sstevel@tonic-gate
113*0Sstevel@tonic-gatemy (%names, %names_copy);
114*0Sstevel@tonic-gate%names = ('$' => 'Scalar', '@' => 'Array', # Grr '
115*0Sstevel@tonic-gate          '%', 'Hash', '&', 'Code');
116*0Sstevel@tonic-gate%names_copy = %names;
117*0Sstevel@tonic-gateok (eq_hash (\%names, \%names_copy), "check we can copy our hash");
118*0Sstevel@tonic-gate
119*0Sstevel@tonic-gatesub in {
120*0Sstevel@tonic-gate  my %args = @_;
121*0Sstevel@tonic-gate  return eq_hash (\%names, \%args);
122*0Sstevel@tonic-gate}
123*0Sstevel@tonic-gate
124*0Sstevel@tonic-gateok (in (%names), "pass hash into a method");
125*0Sstevel@tonic-gate
126*0Sstevel@tonic-gatesub in_method {
127*0Sstevel@tonic-gate  my $self = shift;
128*0Sstevel@tonic-gate  my %args = @_;
129*0Sstevel@tonic-gate  return eq_hash (\%names, \%args);
130*0Sstevel@tonic-gate}
131*0Sstevel@tonic-gate
132*0Sstevel@tonic-gateok (main->in_method (%names), "pass hash into a method");
133*0Sstevel@tonic-gate
134*0Sstevel@tonic-gatesub out {
135*0Sstevel@tonic-gate  return %names;
136*0Sstevel@tonic-gate}
137*0Sstevel@tonic-gate%names_copy = out ();
138*0Sstevel@tonic-gate
139*0Sstevel@tonic-gateok (eq_hash (\%names, \%names_copy), "pass hash from a subroutine");
140*0Sstevel@tonic-gate
141*0Sstevel@tonic-gatesub out_method {
142*0Sstevel@tonic-gate  my $self = shift;
143*0Sstevel@tonic-gate  return %names;
144*0Sstevel@tonic-gate}
145*0Sstevel@tonic-gate%names_copy = main->out_method ();
146*0Sstevel@tonic-gate
147*0Sstevel@tonic-gateok (eq_hash (\%names, \%names_copy), "pass hash from a method");
148*0Sstevel@tonic-gate
149*0Sstevel@tonic-gatesub in_out {
150*0Sstevel@tonic-gate  my %args = @_;
151*0Sstevel@tonic-gate  return %args;
152*0Sstevel@tonic-gate}
153*0Sstevel@tonic-gate%names_copy = in_out (%names);
154*0Sstevel@tonic-gate
155*0Sstevel@tonic-gateok (eq_hash (\%names, \%names_copy), "pass hash to and from a subroutine");
156*0Sstevel@tonic-gate
157*0Sstevel@tonic-gatesub in_out_method {
158*0Sstevel@tonic-gate  my $self = shift;
159*0Sstevel@tonic-gate  my %args = @_;
160*0Sstevel@tonic-gate  return %args;
161*0Sstevel@tonic-gate}
162*0Sstevel@tonic-gate%names_copy = main->in_out_method (%names);
163*0Sstevel@tonic-gate
164*0Sstevel@tonic-gateok (eq_hash (\%names, \%names_copy), "pass hash to and from a method");
165*0Sstevel@tonic-gate
166*0Sstevel@tonic-gatemy %names_copy2 = %names;
167*0Sstevel@tonic-gateok (eq_hash (\%names, \%names_copy2), "check copy worked");
168*0Sstevel@tonic-gate
169*0Sstevel@tonic-gate# This should get ignored.
170*0Sstevel@tonic-gate%names_copy = ('%', 'Associative Array', %names);
171*0Sstevel@tonic-gate
172*0Sstevel@tonic-gateok (eq_hash (\%names, \%names_copy), "duplicates at the start of a list");
173*0Sstevel@tonic-gate
174*0Sstevel@tonic-gate# This should not
175*0Sstevel@tonic-gate%names_copy = ('*', 'Typeglob', %names);
176*0Sstevel@tonic-gate
177*0Sstevel@tonic-gate$names_copy2{'*'} = 'Typeglob';
178*0Sstevel@tonic-gateok (eq_hash (\%names_copy, \%names_copy2), "duplicates at the end of a list");
179*0Sstevel@tonic-gate
180*0Sstevel@tonic-gate%names_copy = ('%', 'Associative Array', '*', 'Endangered species', %names,
181*0Sstevel@tonic-gate              '*', 'Typeglob',);
182*0Sstevel@tonic-gate
183*0Sstevel@tonic-gateok (eq_hash (\%names_copy, \%names_copy2), "duplicates at both ends");
184*0Sstevel@tonic-gate
185*0Sstevel@tonic-gate# And now UTF8
186*0Sstevel@tonic-gate
187*0Sstevel@tonic-gateforeach my $chr (60, 200, 600, 6000, 60000) {
188*0Sstevel@tonic-gate  # This little game may set a UTF8 flag internally. Or it may not. :-)
189*0Sstevel@tonic-gate  my ($key, $value) = (chr ($chr) . "\x{ABCD}", "$chr\x{ABCD}");
190*0Sstevel@tonic-gate  chop ($key, $value);
191*0Sstevel@tonic-gate  my @utf8c = ($key, $value);
192*0Sstevel@tonic-gate  my %utf8c = @utf8c;
193*0Sstevel@tonic-gate
194*0Sstevel@tonic-gate  ok (keys %utf8c == 1, 'keys on utf8 comma hash');
195*0Sstevel@tonic-gate  ok (values %utf8c == 1, 'values on utf8 comma hash');
196*0Sstevel@tonic-gate  # defeat any tokeniser or optimiser cunning
197*0Sstevel@tonic-gate  is ($utf8c{"" . $key}, $value, 'is key present? (unoptimised)');
198*0Sstevel@tonic-gate  my $tempval = sprintf '$utf8c{"\x{%x}"}', $chr;
199*0Sstevel@tonic-gate  is (eval $tempval, $value, "is key present? (maybe $tempval is optimised)");
200*0Sstevel@tonic-gate  $tempval = sprintf '@temp = ("\x{%x}" => undef)', $chr;
201*0Sstevel@tonic-gate  eval $tempval or die "'$tempval' gave $@";
202*0Sstevel@tonic-gate  is ($utf8c{$temp[0]}, $value, 'is key present? (using LHS of $tempval)');
203*0Sstevel@tonic-gate
204*0Sstevel@tonic-gate  @temp = %utf8c;
205*0Sstevel@tonic-gate  ok (eq_array (\@utf8c, \@temp), 'list from utf8 comma hash');
206*0Sstevel@tonic-gate
207*0Sstevel@tonic-gate  @temp = each %utf8c;
208*0Sstevel@tonic-gate  ok (eq_array (\@utf8c, \@temp), 'first each from utf8 comma hash');
209*0Sstevel@tonic-gate  @temp = each %utf8c;
210*0Sstevel@tonic-gate  ok (eq_array ([], \@temp), 'last each from utf8 comma hash');
211*0Sstevel@tonic-gate
212*0Sstevel@tonic-gate  %temp = %utf8c;
213*0Sstevel@tonic-gate
214*0Sstevel@tonic-gate  ok (keys %temp == 1, 'keys on copy of utf8 comma hash');
215*0Sstevel@tonic-gate  ok (values %temp == 1, 'values on copy of utf8 comma hash');
216*0Sstevel@tonic-gate  is ($temp{"" . $key}, $value, 'is key present? (unoptimised)');
217*0Sstevel@tonic-gate  $tempval = sprintf '$temp{"\x{%x}"}', $chr;
218*0Sstevel@tonic-gate  is (eval $tempval, $value, "is key present? (maybe $tempval is optimised)");
219*0Sstevel@tonic-gate  $tempval = sprintf '@temp = ("\x{%x}" => undef)', $chr;
220*0Sstevel@tonic-gate  eval $tempval or die "'$tempval' gave $@";
221*0Sstevel@tonic-gate  is ($temp{$temp[0]}, $value, "is key present? (using LHS of $tempval)");
222*0Sstevel@tonic-gate
223*0Sstevel@tonic-gate  @temp = %temp;
224*0Sstevel@tonic-gate  ok (eq_array (\@temp, \@temp), 'list from copy of utf8 comma hash');
225*0Sstevel@tonic-gate
226*0Sstevel@tonic-gate  @temp = each %temp;
227*0Sstevel@tonic-gate  ok (eq_array (\@temp, \@temp), 'first each from copy of utf8 comma hash');
228*0Sstevel@tonic-gate  @temp = each %temp;
229*0Sstevel@tonic-gate  ok (eq_array ([], \@temp), 'last each from copy of utf8 comma hash');
230*0Sstevel@tonic-gate
231*0Sstevel@tonic-gate  my $assign = sprintf '("\x{%x}" => "%d")', $chr, $chr;
232*0Sstevel@tonic-gate  print "# $assign\n";
233*0Sstevel@tonic-gate  my (@utf8a) = eval $assign;
234*0Sstevel@tonic-gate
235*0Sstevel@tonic-gate  my %utf8a = @utf8a;
236*0Sstevel@tonic-gate  ok (keys %utf8a == 1, 'keys on utf8 arrow hash');
237*0Sstevel@tonic-gate  ok (values %utf8a == 1, 'values on utf8 arrow hash');
238*0Sstevel@tonic-gate  # defeat any tokeniser or optimiser cunning
239*0Sstevel@tonic-gate  is ($utf8a{$key . ""}, $value, 'is key present? (unoptimised)');
240*0Sstevel@tonic-gate  $tempval = sprintf '$utf8a{"\x{%x}"}', $chr;
241*0Sstevel@tonic-gate  is (eval $tempval, $value, "is key present? (maybe $tempval is optimised)");
242*0Sstevel@tonic-gate  $tempval = sprintf '@temp = ("\x{%x}" => undef)', $chr;
243*0Sstevel@tonic-gate  eval $tempval or die "'$tempval' gave $@";
244*0Sstevel@tonic-gate  is ($utf8a{$temp[0]}, $value, "is key present? (using LHS of $tempval)");
245*0Sstevel@tonic-gate
246*0Sstevel@tonic-gate  @temp = %utf8a;
247*0Sstevel@tonic-gate  ok (eq_array (\@utf8a, \@temp), 'list from utf8 arrow hash');
248*0Sstevel@tonic-gate
249*0Sstevel@tonic-gate  @temp = each %utf8a;
250*0Sstevel@tonic-gate  ok (eq_array (\@utf8a, \@temp), 'first each from utf8 arrow hash');
251*0Sstevel@tonic-gate  @temp = each %utf8a;
252*0Sstevel@tonic-gate  ok (eq_array ([], \@temp), 'last each from utf8 arrow hash');
253*0Sstevel@tonic-gate
254*0Sstevel@tonic-gate  %temp = %utf8a;
255*0Sstevel@tonic-gate
256*0Sstevel@tonic-gate  ok (keys %temp == 1, 'keys on copy of utf8 arrow hash');
257*0Sstevel@tonic-gate  ok (values %temp == 1, 'values on copy of utf8 arrow hash');
258*0Sstevel@tonic-gate  is ($temp{'' . $key}, $value, 'is key present? (unoptimised)');
259*0Sstevel@tonic-gate  $tempval = sprintf '$temp{"\x{%x}"}', $chr;
260*0Sstevel@tonic-gate  is (eval $tempval, $value, "is key present? (maybe $tempval is optimised)");
261*0Sstevel@tonic-gate  $tempval = sprintf '@temp = ("\x{%x}" => undef)', $chr;
262*0Sstevel@tonic-gate  eval $tempval or die "'$tempval' gave $@";
263*0Sstevel@tonic-gate  is ($temp{$temp[0]}, $value, "is key present? (using LHS of $tempval)");
264*0Sstevel@tonic-gate
265*0Sstevel@tonic-gate  @temp = %temp;
266*0Sstevel@tonic-gate  ok (eq_array (\@temp, \@temp), 'list from copy of utf8 arrow hash');
267*0Sstevel@tonic-gate
268*0Sstevel@tonic-gate  @temp = each %temp;
269*0Sstevel@tonic-gate  ok (eq_array (\@temp, \@temp), 'first each from copy of utf8 arrow hash');
270*0Sstevel@tonic-gate  @temp = each %temp;
271*0Sstevel@tonic-gate  ok (eq_array ([], \@temp), 'last each from copy of utf8 arrow hash');
272*0Sstevel@tonic-gate
273*0Sstevel@tonic-gate}
274*0Sstevel@tonic-gate
275*0Sstevel@tonic-gate# now some tests for hash assignment in scalar and list context with
276*0Sstevel@tonic-gate# duplicate keys [perl #24380]
277*0Sstevel@tonic-gate{
278*0Sstevel@tonic-gate    my %h; my $x; my $ar;
279*0Sstevel@tonic-gate    is( (join ':', %h = (1) x 8), '1:1',
280*0Sstevel@tonic-gate	'hash assignment in list context removes duplicates' );
281*0Sstevel@tonic-gate    is( scalar( %h = (1,2,1,3,1,4,1,5) ), 2,
282*0Sstevel@tonic-gate	'hash assignment in scalar context' );
283*0Sstevel@tonic-gate    is( scalar( ($x,%h) = (0,1,2,1,3,1,4,1,5) ), 3,
284*0Sstevel@tonic-gate	'scalar + hash assignment in scalar context' );
285*0Sstevel@tonic-gate    $ar = [ %h = (1,2,1,3,1,4,1,5) ];
286*0Sstevel@tonic-gate    is( $#$ar, 1, 'hash assignment in list context' );
287*0Sstevel@tonic-gate    is( "@$ar", "1 5", '...gets the last values' );
288*0Sstevel@tonic-gate    $ar = [ ($x,%h) = (0,1,2,1,3,1,4,1,5) ];
289*0Sstevel@tonic-gate    is( $#$ar, 2, 'scalar + hash assignment in list context' );
290*0Sstevel@tonic-gate    is( "@$ar", "0 1 5", '...gets the last values' );
291*0Sstevel@tonic-gate}
292