A-tisket a-tasket a little perl hash basket
Well Bucket actually.
It has been bugging me for a while why my silly little Orignal mod if failing CPAN Testers in all sorts of odd ways. In one version of perl nothing the next something dies and it is just basic code.
Finally had a few mins today and no Idea of what to blog on so I worked on finding the answer.
The tests would usually fail here
# Failed test 'correct value of '6/8'!'
# at t/03_hash.t line 53.
# got: '3/8'
# expected: '6/8'
# Looks like you failed 1 test of 62.
t/03_hash.t ..........
Dubious, test returned 1 (wstat 256, 0x100)
Failed 1/62 subtests
and here is the test in question
ok($key_count = $hash_test->h1($value{h3}),"Ok set by hash x->hash({'xx','xx'}) in scalar");
cmp_ok($key_count,'eq','6/8',"correct value of '6/8'!");
On most perls I would get '6/8' while on some other perls I got '3/8', '4/8', and even '5/6'. So what gives?
Well as most of us know (well I didn't until just now) calling a hash in scalar context will return a value that is
# of used buckets/# of buckets allocated
buckets being the reserved space for the hash. '6/8' meaning 6 buckets filled of 8 allocated. Like the perl doc says calling a hash in scalar context is is normally just a way to test if a hash is empty.
So it seems that both different versions of perl and the same version of on differing platforms implement 'Hashes' differently. This does make some sort of sense as compilers differ, some brainiac comes up with a better way to store something or something new is added in and it moves something about in the source code.
So it comes down to
- My code bad or
- My test is bad
Well in my 'POD' I state this
'in scalar context is will return the hash key pair string'
So it does return what it is suppose to it is just what returns changes between perls and platforms so like this test below my test is not very well though out.
Lets look at the test
my $key_count = 0;
ok($key_count = $hash_test->h1($value{h3}),"Ok set by hash x->hash({'xx','xx'}) in scalar");
cmp_ok($key_count,'eq','6/8',"correct value of '6/8'!");
well easy enough to fix as all I really want to know is if when called in scalar with values in the hash I get something back.
my $key_count = 0;
ok($key_count = $hash_test->h1($value{h3}),"Ok set by hash x->hash({'xx','xx'}) in scalar");
ok($key_count,"Not Empty!");
So now rather than doing a compare I just check to make sure it is not empty, and sure enough;
...
t/01_base.t .......... ok
t/02_scalar.t ........ # Scalar Testing
t/02_scalar.t ........ ok
t/03_hash.t .......... # Hash testing
t/03_hash.t .......... ok
t/04_ordered_hash.t .. # Ordered Hashes
...
Fortunately in my old age I am getting good at the perl thing and used a little gem called perlbrew and tested a whole bunch of perls at once like this
perlbrew exec make test
and I found the same bug again but in a different spot, though this test did not fail until I changed perl version version.
...
t/04_ordered_hash.t .. # Ordered Hash testing
t/04_ordered_hash.t .. 1/82
# Failed test 'correct value of '6/8'!'
# at t/04_ordered_hash.t line 57.
# got: '5/8'
# expected: '6/8'
# Looks like you failed 1 test of 82.
...
So one more quick fix and then they all pass, package and stick on CPAN.
All in all a good day cleaning up code.
The pod abstract is still wrong (though it claims to be fixed in the changelog). It needs to be:
So the section heading is "NAME" in upper-case.
Also, you might want to change the test to something like this:
Hmm!
__END__
=pod
=head1 Orignal
Orignal - Very simple properties/attributes/fields for Perl
is on CPAN which one are you talking about??
and yes the regex would improve the test a little but it was getting late last night when I wrote this up
The heading must be literally =head1 NAME, not =head1 Orignal.
I agree with Toby on this one: if you're checking the scalar value of a hash, it's almost guaranteed to keep changing. Better to test for a "reasonable" value - \d+/\d+ - instead of a specific one.