|
Packit |
14c646 |
#!./perl
|
|
Packit |
14c646 |
#
|
|
Packit |
14c646 |
# Copyright (c) 1995-2000, Raphael Manfredi
|
|
Packit |
14c646 |
#
|
|
Packit |
14c646 |
# You may redistribute only under the same terms as Perl 5, as specified
|
|
Packit |
14c646 |
# in the README file that comes with the distribution.
|
|
Packit |
14c646 |
#
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
sub BEGIN {
|
|
Packit |
14c646 |
unshift @INC, 't';
|
|
Packit |
14c646 |
unshift @INC, 't/compat' if $] < 5.006002;
|
|
Packit |
14c646 |
require Config; import Config;
|
|
Packit |
14c646 |
if ($ENV{PERL_CORE} and $Config{'extensions'} !~ /\bStorable\b/) {
|
|
Packit |
14c646 |
print "1..0 # Skip: Storable was not built\n";
|
|
Packit |
14c646 |
exit 0;
|
|
Packit |
14c646 |
}
|
|
Packit |
14c646 |
}
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
use Storable qw(freeze thaw dclone);
|
|
Packit |
14c646 |
our ($debugging, $verbose);
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
use Test::More tests => 8;
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# Uncomment the following line to get a dump of the constructed data structure
|
|
Packit |
14c646 |
# (you may want to reduce the size of the hashes too)
|
|
Packit |
14c646 |
# $debugging = 1;
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
$hashsize = 100;
|
|
Packit |
14c646 |
$maxhash2size = 100;
|
|
Packit |
14c646 |
$maxarraysize = 100;
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# Use Digest::MD5 if its available to make random string keys
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
eval { require Digest::MD5; };
|
|
Packit |
14c646 |
$gotmd5 = !$@;
|
|
Packit |
14c646 |
diag "Will use Digest::MD5" if $gotmd5;
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# Use Data::Dumper if debugging and it is available to create an ASCII dump
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
if ($debugging) {
|
|
Packit |
14c646 |
eval { require "Data/Dumper.pm" };
|
|
Packit |
14c646 |
$gotdd = !$@;
|
|
Packit |
14c646 |
}
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
@fixed_strings = ("January", "February", "March", "April", "May", "June",
|
|
Packit |
14c646 |
"July", "August", "September", "October", "November", "December" );
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# Build some arbitrarily complex data structure starting with a top level hash
|
|
Packit |
14c646 |
# (deeper levels contain scalars, references to hashes or references to arrays);
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
for (my $i = 0; $i < $hashsize; $i++) {
|
|
Packit |
14c646 |
my($k) = int(rand(1_000_000));
|
|
Packit |
14c646 |
$k = Digest::MD5::md5_hex($k) if $gotmd5 and int(rand(2));
|
|
Packit |
14c646 |
$a1{$k} = { key => "$k", "value" => $i };
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# A third of the elements are references to further hashes
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
if (int(rand(1.5))) {
|
|
Packit |
14c646 |
my($hash2) = {};
|
|
Packit |
14c646 |
my($hash2size) = int(rand($maxhash2size));
|
|
Packit |
14c646 |
while ($hash2size--) {
|
|
Packit |
14c646 |
my($k2) = $k . $i . int(rand(100));
|
|
Packit |
14c646 |
$hash2->{$k2} = $fixed_strings[rand(int(@fixed_strings))];
|
|
Packit |
14c646 |
}
|
|
Packit |
14c646 |
$a1{$k}->{value} = $hash2;
|
|
Packit |
14c646 |
}
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# A further third are references to arrays
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
elsif (int(rand(2))) {
|
|
Packit |
14c646 |
my($arr_ref) = [];
|
|
Packit |
14c646 |
my($arraysize) = int(rand($maxarraysize));
|
|
Packit |
14c646 |
while ($arraysize--) {
|
|
Packit |
14c646 |
push(@$arr_ref, $fixed_strings[rand(int(@fixed_strings))]);
|
|
Packit |
14c646 |
}
|
|
Packit |
14c646 |
$a1{$k}->{value} = $arr_ref;
|
|
Packit |
14c646 |
}
|
|
Packit |
14c646 |
}
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
print STDERR Data::Dumper::Dumper(\%a1) if ($verbose and $gotdd);
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# Copy the hash, element by element in order of the keys
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
foreach $k (sort keys %a1) {
|
|
Packit |
14c646 |
$a2{$k} = { key => "$k", "value" => $a1{$k}->{value} };
|
|
Packit |
14c646 |
}
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# Deep clone the hash
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
$a3 = dclone(\%a1);
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# In canonical mode the frozen representation of each of the hashes
|
|
Packit |
14c646 |
# should be identical
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
$Storable::canonical = 1;
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
$x1 = freeze(\%a1);
|
|
Packit |
14c646 |
$x2 = freeze(\%a2);
|
|
Packit |
14c646 |
$x3 = freeze($a3);
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
cmp_ok(length $x1, '>', $hashsize); # sanity check
|
|
Packit |
14c646 |
is(length $x1, length $x2); # idem
|
|
Packit |
14c646 |
is($x1, $x2);
|
|
Packit |
14c646 |
is($x1, $x3);
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# In normal mode it is exceedingly unlikely that the frozen
|
|
Packit |
14c646 |
# representations of all the hashes will be the same (normally the hash
|
|
Packit |
14c646 |
# elements are frozen in the order they are stored internally,
|
|
Packit |
14c646 |
# i.e. pseudo-randomly).
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
$Storable::canonical = 0;
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
$x1 = freeze(\%a1);
|
|
Packit |
14c646 |
$x2 = freeze(\%a2);
|
|
Packit |
14c646 |
$x3 = freeze($a3);
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# Two out of three the same may be a coincidence, all three the same
|
|
Packit |
14c646 |
# is much, much more unlikely. Still it could happen, so this test
|
|
Packit |
14c646 |
# may report a false negative.
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
ok(($x1 ne $x2) || ($x1 ne $x3));
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
# Ensure refs to "undef" values are properly shared
|
|
Packit |
14c646 |
# Same test as in t/dclone.t to ensure the "canonical" code is also correct
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
my $hash;
|
|
Packit |
14c646 |
push @{$$hash{''}}, \$$hash{a};
|
|
Packit |
14c646 |
is($$hash{''}[0], \$$hash{a});
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
my $cloned = dclone(dclone($hash));
|
|
Packit |
14c646 |
is($$cloned{''}[0], \$$cloned{a});
|
|
Packit |
14c646 |
|
|
Packit |
14c646 |
$$cloned{a} = "blah";
|
|
Packit |
14c646 |
is($$cloned{''}[0], \$$cloned{a});
|