xref: /openbsd-src/gnu/usr.bin/perl/ext/Hash-Util-FieldHash/t/05_perlhook.t (revision eac174f2741a08d8deb8aae59a7f778ef9b5d770)
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