1#!./perl -w 2 3BEGIN { 4 chdir 't' if -d 't'; 5 @INC = '../lib'; 6 require './test.pl'; 7} 8 9# use strict; 10 11plan tests => 44; 12 13# simple use cases 14{ 15 my %h = map { $_ => uc $_ } 'a'..'z'; 16 17 is( join(':', %h{'c','d','e'}), 'c:C:d:D:e:E', "correct result and order"); 18 is( join(':', %h{'e','d','c'}), 'e:E:d:D:c:C', "correct result and order"); 19 is( join(':', %h{'e','c','d'}), 'e:E:c:C:d:D', "correct result and order"); 20 21 ok( eq_hash( { %h{'q','w'} }, { q => 'Q', w => 'W' } ), "correct hash" ); 22 23 is( join(':', %h{()}), '', "correct result for empty slice"); 24} 25 26# not existing elements 27{ 28 my %h = map { $_ => uc $_ } 'a'..'d'; 29 ok( eq_hash( { %h{qw(e d)} }, { e => undef, d => 'D' } ), 30 "not existing returned with undef value" ); 31 32 ok( !exists $h{e}, "no autovivification" ); 33} 34 35# repeated keys 36{ 37 my %h = map { $_ => uc $_ } 'a'..'d'; 38 my @a = %h{ ('c') x 3 }; 39 ok eq_array( \@a, [ ('c', 'C') x 3 ]), "repetead keys end with repeated results"; 40} 41 42# scalar context 43{ 44 my @warn; 45 local $SIG{__WARN__} = sub {push @warn, "@_"}; 46 47 my %h = map { $_ => uc $_ } 'a'..'z'; 48 is scalar eval"%h{'c','d','e'}", 'E', 'last element in scalar context'; 49 50 like ($warn[0], 51 qr/^\%h\{\.\.\.\} in scalar context better written as \$h\{\.\.\.\}/); 52 53 eval 'is( scalar %h{i}, "I", "correct value");'; 54 55 is (scalar @warn, 2); 56 like ($warn[1], 57 qr/^\%h\{"i"\} in scalar context better written as \$h\{"i"\}/); 58} 59 60# autovivification 61{ 62 my %h = map { $_ => uc $_ } 'a'..'b'; 63 64 my @a = %h{'c','d'}; 65 is( join(':', map {$_//'undef'} @a), 'c:undef:d:undef', "correct result"); 66 ok( eq_hash( \%h, { a => 'A', b => 'B' } ), "correct hash" ); 67} 68 69# hash refs 70{ 71 my $h = { map { $_ => uc $_ } 'a'..'z' }; 72 73 is( join(':', %$h{'c','d','e'}), 'c:C:d:D:e:E', "correct result and order"); 74 is( join(':', %{$h}{'c','d','e'}), 'c:C:d:D:e:E', "correct result and order"); 75} 76 77# no interpolation 78{ 79 my %h = map { $_ => uc $_ } 'a'..'b'; 80 is( "%h{'a','b'}", q{%h{'a','b'}}, 'no interpolation within strings' ); 81} 82 83# ref of a slice produces list 84{ 85 my %h = map { $_ => uc $_ } 'a'..'z'; 86 my @a = \%h{ qw'c d e' }; 87 88 my $ok = 1; 89 $ok = 0 if grep !ref, @a; 90 ok $ok, "all elements are refs"; 91 92 is join( ':', map{ $$_ } @a ), 'c:C:d:D:e:E' 93} 94 95# lvalue usage in foreach 96{ 97 my %h = qw(a 1 b 2 c 3); 98 $_++ foreach %h{'b', 'c'}; 99 ok( eq_hash( \%h, { a => 1, b => 3, c => 4 } ), "correct hash" ); 100} 101 102# lvalue subs in foreach 103{ 104 my %h = qw(a 1 b 2 c 3); 105 sub foo:lvalue{ %h{qw(a b)} }; 106 $_++ foreach foo(); 107 ok( eq_hash( \%h, { a => 2, b => 3, c => 3 } ), "correct hash" ); 108} 109 110# errors 111{ 112 my %h = map { $_ => uc $_ } 'a'..'b'; 113 # no local 114 { 115 local $@; 116 eval 'local %h{qw(a b)}'; 117 like $@, qr{^Can't modify key/value hash slice in local at}, 118 'local dies'; 119 } 120 # no delete 121 { 122 local $@; 123 eval 'delete %h{qw(a b)}'; 124 like $@, qr{^delete argument is key/value hash slice, use hash slice}, 125 'delete dies'; 126 } 127 # no assign 128 { 129 local $@; 130 eval '%h{qw(a b)} = qw(B A)'; 131 like $@, qr{^Can't modify key/value hash slice in list assignment}, 132 'assign dies'; 133 } 134 # lvalue subs in assignment 135 { 136 local $@; 137 eval 'sub bar:lvalue{ %h{qw(a b)} }; bar() = "1"'; 138 like $@, qr{^Can't modify key/value hash slice in list assignment}, 139 'not allowed as result of lvalue sub'; 140 } 141} 142 143# warnings 144{ 145 my @warn; 146 local $SIG{__WARN__} = sub {push @warn, "@_"}; 147 148 my %h = map { $_ => uc $_ } 'a'..'c'; 149 { 150 @warn = (); 151 my $v = eval '%h{a}'; 152 is (scalar @warn, 1, 'warning in scalar context'); 153 like $warn[0], 154 qr{^%h{"a"} in scalar context better written as \$h{"a"}}, 155 "correct warning text"; 156 } 157 { 158 @warn = (); 159 my ($k,$v) = eval '%h{a}'; 160 is ($k, 'a'); 161 is ($v, 'A'); 162 is (scalar @warn, 0, 'no warning in list context'); 163 } 164 165 # deprecated syntax 166 { 167 my $h = \%h; 168 @warn = (); 169 ok( eq_array([eval '%$h->{a}'], ['A']), 'works, but deprecated' ); 170 is (scalar @warn, 1, 'one warning'); 171 like $warn[0], qr{^Using a hash as a reference is deprecated}, 172 "correct warning text"; 173 174 @warn = (); 175 ok( eq_array([eval '%$h->{"b","c"}'], [undef]), 'works, but deprecated' ); 176 is (scalar @warn, 1, 'one warning'); 177 like $warn[0], qr{^Using a hash as a reference is deprecated}, 178 "correct warning text"; 179 } 180} 181 182# simple case with tied 183{ 184 require Tie::Hash; 185 tie my %h, 'Tie::StdHash'; 186 %h = map { $_ => uc $_ } 'a'..'c'; 187 188 ok( eq_array( [%h{'b','a', 'e'}], [qw(b B a A e), undef] ), 189 "works on tied" ); 190 191 ok( !exists $h{e}, "no autovivification" ); 192} 193 194# keys/value/each treat argument as scalar 195{ 196 my %h = 'a'..'b'; 197 my %i = (foo => \%h); 198 no warnings 'syntax', 'experimental::autoderef'; 199 my ($k,$v) = each %i{foo=>}; 200 is $k, 'a', 'key returned by each %hash{key}'; 201 is $v, 'b', 'val returned by each %hash{key}'; 202 %h = 1..10; 203 is join('-', sort keys %i{foo=>}), '1-3-5-7-9', 'keys %hash{key}'; 204 is join('-', sort values %i{foo=>}), '10-2-4-6-8', 'values %hash{key}'; 205} 206 207# \% prototype expects hash deref 208sub nowt_but_hash(\%) {} 209eval 'nowt_but_hash %INC{bar}'; 210like $@, qr`^Type of arg 1 to main::nowt_but_hash must be hash \(not(?x: 211 ) key/value hash slice\) at `, 212 '\% prototype'; 213