1#!perl 2use strict; use warnings; 3use Test::More; 4my $n_tests; 5 6use Hash::Util::FieldHash; 7use Scalar::Util qw( weaken); 8 9# The functions in Hash::Util::FieldHash 10# _test_uvar_get, _test_uvar_get and _test_uvar_both 11 12# _test_uvar_get( $anyref, \ $counter) makes the referent of $anyref 13# "uvar"-magical with get magic only. $counter is reset if the magic 14# could be established. $counter will be incremented each time the 15# magic "get" function is called. 16 17# _test_uvar_set does the same for "set" magic. _test_uvar_both 18# sets both magic functions identically. Both use the same counter. 19 20# magical weak ref (patch to sv.c) 21{ 22 my( $magref, $counter); 23 24 $counter = 123; 25 Hash::Util::FieldHash::_test_uvar_set( \ $magref, \ $counter); 26 is( $counter, 0, "got magical scalar"); 27 28 my $ref = []; 29 $magref = $ref; 30 is( $counter, 1, "store triggers magic"); 31 32 weaken $magref; 33 is( $counter, 1, "weaken doesn't trigger magic"); 34 35 { my $x = $magref } 36 is( $counter, 1, "read doesn't trigger magic"); 37 38 undef $ref; 39 is( $counter, 2, "ref expiry triggers magic (weakref patch worked)"); 40 41 is( $magref, undef, "weak ref works normally"); 42 43 # same, but overwrite weakref before expiry 44 $counter = 0; 45 weaken( $magref = $ref = []); 46 is( $counter, 1, "setup for overwrite"); 47 48 $magref = my $other_ref = []; 49 is( $counter, 2, "overwrite triggers"); 50 51 undef $ref; 52 is( $counter, 2, "ref expiry doesn't trigger after overwrite"); 53 54 is( $magref, $other_ref, "weak ref doesn't kill overwritten value"); 55 56 BEGIN { $n_tests += 10 } 57} 58 59# magical hash (patches to mg.c and hv.c) 60{ 61 # the hook is only sensitive if the set function is NULL 62 my ( %h, $counter); 63 $counter = 123; 64 Hash::Util::FieldHash::_test_uvar_get( \ %h, \ $counter); 65 is( $counter, 0, "got magical hash"); 66 67 %h = ( abc => 123); 68 is( $counter, 1, "list assign triggers"); 69 70 71 my $x = keys %h; 72 is( $counter, 1, "scalar keys doesn't trigger"); 73 is( $x, 1, "there is one key"); 74 75 my (@x) = keys %h; 76 is( $counter, 1, "list keys doesn't trigger"); 77 is( "@x", "abc", "key is correct"); 78 79 $x = values %h; 80 is( $counter, 1, "scalar values doesn't trigger"); 81 is( $x, 1, "the value is correct"); 82 83 (@x) = values %h; 84 is( $counter, 1, "list values doesn't trigger"); 85 is( "@x", "123", "the value is correct"); 86 87 $x = each %h; 88 is( $counter, 1, "scalar each doesn't trigger"); 89 is( $x, "abc", "the return is correct"); 90 91 $x = each %h; 92 is( $counter, 1, "scalar each doesn't trigger"); 93 is( $x, undef, "the return is correct"); 94 95 (@x) = each %h; 96 is( $counter, 1, "list each doesn't trigger"); 97 is( "@x", "abc 123", "the return is correct"); 98 99 $x = %h; 100 is( $counter, 1, "hash in scalar context doesn't trigger"); 101 like( $x, qr!^\d+/\d+$!, "correct result"); 102 103 (@x) = %h; 104 is( $counter, 1, "hash in list context doesn't trigger"); 105 is( "@x", "abc 123", "correct result"); 106 107 108 $h{ def} = 456; 109 is( $counter, 2, "lvalue assign triggers"); 110 111 (@x) = sort %h; 112 is( $counter, 2, "hash in list context doesn't trigger"); 113 is( "@x", "123 456 abc def", "correct result"); 114 115 exists $h{ def}; 116 is( $counter, 3, "good exists triggers"); 117 118 exists $h{ xyz}; 119 is( $counter, 4, "bad exists triggers"); 120 121 delete $h{ def}; 122 is( $counter, 5, "good delete triggers"); 123 124 (@x) = sort %h; 125 is( $counter, 5, "hash in list context doesn't trigger"); 126 is( "@x", "123 abc", "correct result"); 127 128 delete $h{ xyz}; 129 is( $counter, 6, "bad delete triggers"); 130 131 (@x) = sort %h; 132 is( $counter, 6, "hash in list context doesn't trigger"); 133 is( "@x", "123 abc", "correct result"); 134 135 $x = $h{ abc}; 136 is( $counter, 7, "good read triggers"); 137 138 $x = $h{ xyz}; 139 is( $counter, 8, "bad read triggers"); 140 141 (@x) = sort %h; 142 is( $counter, 8, "hash in list context doesn't trigger"); 143 is( "@x", "123 abc", "correct result"); 144 145 146 bless \ %h; 147 is( $counter, 8, "bless doesn't trigger"); 148 149 bless \ %h, 'xyz'; 150 is( $counter, 8, "bless doesn't trigger"); 151 152 # see that normal set magic doesn't trigger (identity condition) 153 my %i; 154 Hash::Util::FieldHash::_test_uvar_set( \ %i, \ $counter); 155 is( $counter, 0, "got magical hash"); 156 157 %i = ( abc => 123); 158 $i{ def} = 456; 159 exists $i{ def}; 160 exists $i{ xyz}; 161 delete $i{ def}; 162 delete $i{ xyz}; 163 $x = $i{ abc}; 164 $x = $i{ xyz}; 165 $x = keys %i; 166 () = keys %i; 167 $x = values %i; 168 () = values %i; 169 $x = each %i; 170 () = each %i; 171 172 is( $counter, 0, "normal set magic never triggers"); 173 174 bless \ %i, 'abc'; 175 is( $counter, 1, "...except with bless"); 176 177 # see that magic with both set and get doesn't trigger 178 $counter = 123; 179 my %j; 180 Hash::Util::FieldHash::_test_uvar_same( \ %j, \ $counter); 181 is( $counter, 0, "got magical hash"); 182 183 %j = ( abc => 123); 184 $j{ def} = 456; 185 exists $j{ def}; 186 exists $j{ xyz}; 187 delete $j{ def}; 188 delete $j{ xyz}; 189 $x = $j{ abc}; 190 $x = $j{ xyz}; 191 $x = keys %j; 192 () = keys %j; 193 $x = values %j; 194 () = values %j; 195 $x = each %j; 196 () = each %j; 197 198 is( $counter, 0, "get/set magic never triggers"); 199 200 bless \ %j, 'abc'; 201 is( $counter, 1, "...except for bless"); 202 203 BEGIN { $n_tests += 43 } 204} 205 206BEGIN { plan tests => $n_tests } 207 208