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