diff options
-rw-r--r-- | pp_sys.c | 1 | ||||
-rw-r--r-- | t/op/tiehash.t | 78 |
2 files changed, 79 insertions, 0 deletions
@@ -881,6 +881,7 @@ PP(pp_tie) hv_free_ent((HV *)varsv, entry); } HvEITER_set(MUTABLE_HV(varsv), 0); + HvRITER_set(MUTABLE_HV(varsv), -1); break; } case SVt_PVAV: diff --git a/t/op/tiehash.t b/t/op/tiehash.t index 6cce114e29..daa0c30c16 100644 --- a/t/op/tiehash.t +++ b/t/op/tiehash.t @@ -72,4 +72,82 @@ package TestIterators { is(each %h, undef, "third iterator is undef"); } +{ + require Tie::Hash; + + my %h = ( + lolcat => "OH HAI!", + lolrus => "I HAS A BUCKET", + ); + + my @want = sort keys %h; + + my @have; + while (1) { + my $k = each %h; + last + unless defined $k; + push @have, $k; + } + @have = sort @have; + + # This is a sanity test: + is("@have", "@want", "get all keys from a loop"); + + @have = (); + keys %h; + + my $k1 = each %h; + + ok(defined $k1, "Got a key"); + + # no tie/untie here + + while(1) { + my $k = each %h; + last + unless defined $k; + push @have, $k; + } + + # As are these: + is(scalar @have, 1, "just 1 key from the loop this time"); + isnt($k1, $have[0], "two different keys"); + + @have = sort @have, $k1; + is("@have", "@want", "get all keys just once"); + + # And this is the real test. + # + # Previously pp_tie would mangle the hash iterator state - it would reset + # EITER but not RITER, meaning that if the iterator happened to be partway + # down a chain of entries, the rest of that chain would be skipped, but if + # the iterator's next position was the start of a (new) chain, nothing would + # be skipped. + # We don't have space to store the complete older iterator state (and really + # nothing should be relying on it), so it seems better to correctly reset + # the iterator (every time), than leave it in a mess just occasionally. + + @have = (); + keys %h; + + my $k1 = each %h; + + ok(defined $k1, "Got a key"); + + tie %h, 'Tie::StdHash'; + untie %h; + + while(1) { + my $k = each %h; + last + unless defined $k; + push @have, $k; + } + + @have = sort @have; + is(scalar @have, 2, "2 keys from the loop this time"); + is("@have", "@want", "tie/untie resets the hash iterator"); +} + done_testing(); |