1*eac174f2Safresh1use strict; 2*eac174f2Safresh1use warnings; 343003dfeSmillertuse Test::More; 443003dfeSmillert 543003dfeSmillertuse Hash::Util::FieldHash; 6*eac174f2Safresh1no warnings 'experimental::builtin'; 7*eac174f2Safresh1use builtin qw(weaken); 843003dfeSmillert 9b8851fccSafresh1sub numbers_first { # Sort helper: All digit entries sort in front of others 10b8851fccSafresh1 # Makes sorting portable across ASCII/EBCDIC 11b8851fccSafresh1 return $a cmp $b if ($a =~ /^\d+$/) == ($b =~ /^\d+$/); 12b8851fccSafresh1 return -1 if $a =~ /^\d+$/; 13b8851fccSafresh1 return 1; 14b8851fccSafresh1} 15b8851fccSafresh1 1643003dfeSmillert# The functions in Hash::Util::FieldHash 1743003dfeSmillert# _test_uvar_get, _test_uvar_get and _test_uvar_both 1843003dfeSmillert 1943003dfeSmillert# _test_uvar_get( $anyref, \ $counter) makes the referent of $anyref 2043003dfeSmillert# "uvar"-magical with get magic only. $counter is reset if the magic 2143003dfeSmillert# could be established. $counter will be incremented each time the 2243003dfeSmillert# magic "get" function is called. 2343003dfeSmillert 2443003dfeSmillert# _test_uvar_set does the same for "set" magic. _test_uvar_both 2543003dfeSmillert# sets both magic functions identically. Both use the same counter. 2643003dfeSmillert 2743003dfeSmillert# magical weak ref (patch to sv.c) 2843003dfeSmillert{ 2943003dfeSmillert my( $magref, $counter); 3043003dfeSmillert 3143003dfeSmillert $counter = 123; 3243003dfeSmillert Hash::Util::FieldHash::_test_uvar_set( \ $magref, \ $counter); 3343003dfeSmillert is( $counter, 0, "got magical scalar"); 3443003dfeSmillert 3543003dfeSmillert my $ref = []; 3643003dfeSmillert $magref = $ref; 3743003dfeSmillert is( $counter, 1, "store triggers magic"); 3843003dfeSmillert 3943003dfeSmillert weaken $magref; 4043003dfeSmillert is( $counter, 1, "weaken doesn't trigger magic"); 4143003dfeSmillert 4243003dfeSmillert { my $x = $magref } 4343003dfeSmillert is( $counter, 1, "read doesn't trigger magic"); 4443003dfeSmillert 4543003dfeSmillert undef $ref; 4643003dfeSmillert is( $counter, 2, "ref expiry triggers magic (weakref patch worked)"); 4743003dfeSmillert 4843003dfeSmillert is( $magref, undef, "weak ref works normally"); 4943003dfeSmillert 5043003dfeSmillert # same, but overwrite weakref before expiry 5143003dfeSmillert $counter = 0; 5243003dfeSmillert weaken( $magref = $ref = []); 5343003dfeSmillert is( $counter, 1, "setup for overwrite"); 5443003dfeSmillert 5543003dfeSmillert $magref = my $other_ref = []; 5643003dfeSmillert is( $counter, 2, "overwrite triggers"); 5743003dfeSmillert 5843003dfeSmillert undef $ref; 5943003dfeSmillert is( $counter, 2, "ref expiry doesn't trigger after overwrite"); 6043003dfeSmillert 6143003dfeSmillert is( $magref, $other_ref, "weak ref doesn't kill overwritten value"); 6243003dfeSmillert} 6343003dfeSmillert 6443003dfeSmillert# magical hash (patches to mg.c and hv.c) 6543003dfeSmillert{ 6643003dfeSmillert # the hook is only sensitive if the set function is NULL 6743003dfeSmillert my ( %h, $counter); 6843003dfeSmillert $counter = 123; 6943003dfeSmillert Hash::Util::FieldHash::_test_uvar_get( \ %h, \ $counter); 7043003dfeSmillert is( $counter, 0, "got magical hash"); 7143003dfeSmillert 7243003dfeSmillert %h = ( abc => 123); 7343003dfeSmillert is( $counter, 1, "list assign triggers"); 7443003dfeSmillert 7543003dfeSmillert 7643003dfeSmillert my $x = keys %h; 7743003dfeSmillert is( $counter, 1, "scalar keys doesn't trigger"); 7843003dfeSmillert is( $x, 1, "there is one key"); 7943003dfeSmillert 8043003dfeSmillert my (@x) = keys %h; 8143003dfeSmillert is( $counter, 1, "list keys doesn't trigger"); 8243003dfeSmillert is( "@x", "abc", "key is correct"); 8343003dfeSmillert 8443003dfeSmillert $x = values %h; 8543003dfeSmillert is( $counter, 1, "scalar values doesn't trigger"); 8643003dfeSmillert is( $x, 1, "the value is correct"); 8743003dfeSmillert 8843003dfeSmillert (@x) = values %h; 8943003dfeSmillert is( $counter, 1, "list values doesn't trigger"); 9043003dfeSmillert is( "@x", "123", "the value is correct"); 9143003dfeSmillert 9243003dfeSmillert $x = each %h; 9343003dfeSmillert is( $counter, 1, "scalar each doesn't trigger"); 9443003dfeSmillert is( $x, "abc", "the return is correct"); 9543003dfeSmillert 9643003dfeSmillert $x = each %h; 9743003dfeSmillert is( $counter, 1, "scalar each doesn't trigger"); 9843003dfeSmillert is( $x, undef, "the return is correct"); 9943003dfeSmillert 10043003dfeSmillert (@x) = each %h; 10143003dfeSmillert is( $counter, 1, "list each doesn't trigger"); 10243003dfeSmillert is( "@x", "abc 123", "the return is correct"); 10343003dfeSmillert 1049f11ffb7Safresh1 $x = scalar %h; 10543003dfeSmillert is( $counter, 1, "hash in scalar context doesn't trigger"); 1069f11ffb7Safresh1 is( $x, 1, "correct result"); 10743003dfeSmillert 10843003dfeSmillert (@x) = %h; 10943003dfeSmillert is( $counter, 1, "hash in list context doesn't trigger"); 11043003dfeSmillert is( "@x", "abc 123", "correct result"); 11143003dfeSmillert 11243003dfeSmillert 11343003dfeSmillert $h{ def} = 456; 11443003dfeSmillert is( $counter, 2, "lvalue assign triggers"); 11543003dfeSmillert 116b8851fccSafresh1 (@x) = sort numbers_first %h; 11743003dfeSmillert is( $counter, 2, "hash in list context doesn't trigger"); 11843003dfeSmillert is( "@x", "123 456 abc def", "correct result"); 11943003dfeSmillert 12043003dfeSmillert exists $h{ def}; 12143003dfeSmillert is( $counter, 3, "good exists triggers"); 12243003dfeSmillert 12343003dfeSmillert exists $h{ xyz}; 12443003dfeSmillert is( $counter, 4, "bad exists triggers"); 12543003dfeSmillert 12643003dfeSmillert delete $h{ def}; 12743003dfeSmillert is( $counter, 5, "good delete triggers"); 12843003dfeSmillert 129b8851fccSafresh1 (@x) = sort numbers_first %h; 13043003dfeSmillert is( $counter, 5, "hash in list context doesn't trigger"); 13143003dfeSmillert is( "@x", "123 abc", "correct result"); 13243003dfeSmillert 13343003dfeSmillert delete $h{ xyz}; 13443003dfeSmillert is( $counter, 6, "bad delete triggers"); 13543003dfeSmillert 136b8851fccSafresh1 (@x) = sort numbers_first %h; 13743003dfeSmillert is( $counter, 6, "hash in list context doesn't trigger"); 13843003dfeSmillert is( "@x", "123 abc", "correct result"); 13943003dfeSmillert 14043003dfeSmillert $x = $h{ abc}; 14143003dfeSmillert is( $counter, 7, "good read triggers"); 14243003dfeSmillert 14343003dfeSmillert $x = $h{ xyz}; 14443003dfeSmillert is( $counter, 8, "bad read triggers"); 14543003dfeSmillert 146b8851fccSafresh1 (@x) = sort numbers_first %h; 14743003dfeSmillert is( $counter, 8, "hash in list context doesn't trigger"); 14843003dfeSmillert is( "@x", "123 abc", "correct result"); 14943003dfeSmillert 15043003dfeSmillert 15143003dfeSmillert bless \ %h; 15243003dfeSmillert is( $counter, 8, "bless doesn't trigger"); 15343003dfeSmillert 15443003dfeSmillert bless \ %h, 'xyz'; 15543003dfeSmillert is( $counter, 8, "bless doesn't trigger"); 15643003dfeSmillert 15743003dfeSmillert # see that normal set magic doesn't trigger (identity condition) 15843003dfeSmillert my %i; 15943003dfeSmillert Hash::Util::FieldHash::_test_uvar_set( \ %i, \ $counter); 16043003dfeSmillert is( $counter, 0, "got magical hash"); 16143003dfeSmillert 16243003dfeSmillert %i = ( abc => 123); 16343003dfeSmillert $i{ def} = 456; 16443003dfeSmillert exists $i{ def}; 16543003dfeSmillert exists $i{ xyz}; 16643003dfeSmillert delete $i{ def}; 16743003dfeSmillert delete $i{ xyz}; 16843003dfeSmillert $x = $i{ abc}; 16943003dfeSmillert $x = $i{ xyz}; 17043003dfeSmillert $x = keys %i; 17143003dfeSmillert () = keys %i; 17243003dfeSmillert $x = values %i; 17343003dfeSmillert () = values %i; 17443003dfeSmillert $x = each %i; 17543003dfeSmillert () = each %i; 17643003dfeSmillert 17743003dfeSmillert is( $counter, 0, "normal set magic never triggers"); 17843003dfeSmillert 17943003dfeSmillert bless \ %i, 'abc'; 18043003dfeSmillert is( $counter, 1, "...except with bless"); 18143003dfeSmillert 18243003dfeSmillert # see that magic with both set and get doesn't trigger 18343003dfeSmillert $counter = 123; 18443003dfeSmillert my %j; 18543003dfeSmillert Hash::Util::FieldHash::_test_uvar_same( \ %j, \ $counter); 18643003dfeSmillert is( $counter, 0, "got magical hash"); 18743003dfeSmillert 18843003dfeSmillert %j = ( abc => 123); 18943003dfeSmillert $j{ def} = 456; 19043003dfeSmillert exists $j{ def}; 19143003dfeSmillert exists $j{ xyz}; 19243003dfeSmillert delete $j{ def}; 19343003dfeSmillert delete $j{ xyz}; 19443003dfeSmillert $x = $j{ abc}; 19543003dfeSmillert $x = $j{ xyz}; 19643003dfeSmillert $x = keys %j; 19743003dfeSmillert () = keys %j; 19843003dfeSmillert $x = values %j; 19943003dfeSmillert () = values %j; 20043003dfeSmillert $x = each %j; 20143003dfeSmillert () = each %j; 20243003dfeSmillert 20343003dfeSmillert is( $counter, 0, "get/set magic never triggers"); 20443003dfeSmillert 20543003dfeSmillert bless \ %j, 'abc'; 20643003dfeSmillert is( $counter, 1, "...except for bless"); 20743003dfeSmillert} 20843003dfeSmillert 209*eac174f2Safresh1done_testing; 210