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

  1. My code bad or

  2. 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.

test-fails-14.jpg

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.

5 Comments

The pod abstract is still wrong (though it claims to be fixed in the changelog). It needs to be:

=head1 NAME
 
Orignal - Very simple properties/attributes/fields for Perl

So the section heading is "NAME" in upper-case.

Also, you might want to change the test to something like this:

like($key_count, qr{ \A [0-9]+ / [0-9]+ \z }x, 'key count looks sane');

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.

Leave a comment

About byterock

user-pic Long time Perl guy, a few CPAN mods allot of work on DBD::Oracle and a few YAPC presentations