X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2F84serialize.t;h=55aa74bdb0630e1b4e08a6a5e6c8eebcc57a8af5;hb=3d98c75e2c45cbd5ddd995cbeb48810f6ad7e1ca;hp=76e18c2258513dfcdf4a5ab43ede38b6ba2a5749;hpb=3a81f59b557a2152f0c62d552469582fa56df8a7;p=dbsrgits%2FDBIx-Class.git diff --git a/t/84serialize.t b/t/84serialize.t index 76e18c2..55aa74b 100644 --- a/t/84serialize.t +++ b/t/84serialize.t @@ -1,60 +1,154 @@ use strict; -use warnings; +use warnings; use Test::More; +use Test::Exception; use lib qw(t/lib); use DBICTest; -use Storable qw(dclone freeze thaw); +use Storable qw(dclone freeze nfreeze thaw); +use Scalar::Util qw/refaddr/; -my $schema = DBICTest->init_schema(); +sub ref_ne { + my ($refa, $refb) = map { refaddr $_ or die "$_ is not a reference!" } @_[0,1]; + cmp_ok ( + $refa, + '!=', + $refb, + sprintf ('%s (0x%07x != 0x%07x)', + $_[2], + $refa, + $refb, + ), + ); +} + +my $schema = DBICTest->init_schema; my %stores = ( dclone_method => sub { return $schema->dclone($_[0]) }, - dclone_func => sub { return dclone($_[0]) }, + dclone_func => sub { + local $DBIx::Class::ResultSourceHandle::thaw_schema = $schema; + return dclone($_[0]) + }, "freeze/thaw_method" => sub { - my $ice = $schema->freeze($_[0]); - return $schema->thaw($ice); + my $ice = $schema->freeze($_[0]); + return $schema->thaw($ice); }, - "freeze/thaw_func" => sub { - thaw(freeze($_[0])); + "nfreeze/thaw_func" => sub { + my $ice = freeze($_[0]); + local $DBIx::Class::ResultSourceHandle::thaw_schema = $schema; + return thaw($ice); + }, + + "freeze/thaw_func (cdbi legacy)" => sub { + # this one is special-cased to leak the $schema all over + # the same way as cdbi-compat does + DBICTest::Artist->result_source_instance->schema($schema); + DBICTest::CD->result_source_instance->schema($schema); + + my $fire = thaw(freeze($_[0])); + + # clean up the mess + $_->result_source_instance->schema(undef) + for map { $schema->class ($_) } $schema->sources; + + return $fire; }, -); -plan tests => (7 * keys %stores); + ($ENV{DBICTEST_MEMCACHED}) + ? do { + require Cache::Memcached; + my $memcached = Cache::Memcached->new( + { servers => [ $ENV{DBICTEST_MEMCACHED} ] } ); + + my $key = 'tmp_dbic_84serialize_memcached_test'; + + ( memcached => sub { + $memcached->set( $key, $_[0], 60 ); + local $DBIx::Class::ResultSourceHandle::thaw_schema = $schema; + return $memcached->get($key); + }); + } : () + , +); for my $name (keys %stores) { + my $store = $stores{$name}; + my $copy; my $artist = $schema->resultset('Artist')->find(1); - - # Test that the procedural versions will work if there's a registered - # schema as with CDBICompat objects and that the methods work - # without. - if( $name =~ /func/ ) { - $artist->result_source_instance->schema($schema); - DBICTest::CD->result_source_instance->schema($schema); - } - else { - $artist->result_source_instance->schema(undef); - DBICTest::CD->result_source_instance->schema(undef); - } - my $copy = eval { $store->($artist) }; + lives_ok { $copy = $store->($artist) } "serialize row object lives: $name"; + ref_ne($copy, $artist, 'Simple row cloned'); is_deeply($copy, $artist, "serialize row object works: $name"); - # Test that an object with a related_resultset can be serialized. - my @cds = $artist->related_resultset("cds"); + my $cd_rs = $artist->search_related("cds"); + + # test that a live result source can be serialized as well + is( $cd_rs->count, 3, '3 CDs in database'); + ok( $cd_rs->next, 'Advance cursor' ); + lives_ok { + $copy = $store->($cd_rs); + + ref_ne($copy, $artist, 'Simple row cloned'); + + is_deeply ( + [ $copy->all ], + [ $cd_rs->all ], + "serialize resultset works: $name", + ); + } "serialize resultset lives: $name"; + + # Test that an object with a related_resultset can be serialized. ok $artist->{related_resultsets}, 'has key: related_resultsets'; - $copy = eval { $store->($artist) }; + lives_ok { $copy = $store->($artist) } "serialize row object with related_resultset lives: $name"; for my $key (keys %$artist) { next if $key eq 'related_resultsets'; next if $key eq '_inflated_column'; + + ref_ne($copy->{$key}, $artist->{$key}, "Simple row internals cloned '$key'") + if ref $artist->{$key}; + is_deeply($copy->{$key}, $artist->{$key}, - qq[serialize with related_resultset "$key"]); + qq[serialize with related_resultset '$key']); } - - ok eval { $copy->discard_changes; 1 } or diag $@; + + lives_ok( + sub { $copy->discard_changes }, "Discard changes works: $name" + ) or diag $@; is($copy->id, $artist->id, "IDs still match "); + + + # Test resultsource with cached rows + my $query_count; + $cd_rs = $cd_rs->search ({}, { cache => 1 }); + + my $orig_debug = $schema->storage->debug; + $schema->storage->debug(1); + $schema->storage->debugcb(sub { $query_count++ } ); + + # this will hit the database once and prime the cache + my @cds = $cd_rs->all; + + lives_ok { + $copy = $store->($cd_rs); + ref_ne($copy, $cd_rs, 'Cached resultset cloned'); + is_deeply ( + [ $copy->all ], + [ $cd_rs->all ], + "serialize cached resultset works: $name", + ); + + is ($copy->count, $cd_rs->count, 'Cached count identical'); + } "serialize cached resultset lives: $name"; + + is ($query_count, 1, 'Only one db query fired'); + + $schema->storage->debug($orig_debug); + $schema->storage->debugcb(undef); } + +done_testing;