X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2F84serialize.t;h=04e16cb857df407b2ecc3276cdd9bb4c4fe939ba;hb=5815ffb0e34dcd74af49581f65e1d5aa71779a6b;hp=99449d4d165d6c7f8604ff42f49d4721f9b1a820;hpb=7d7d697500011de9ac151b6303f27e56f696cec6;p=dbsrgits%2FDBIx-Class.git diff --git a/t/84serialize.t b/t/84serialize.t index 99449d4..04e16cb 100644 --- a/t/84serialize.t +++ b/t/84serialize.t @@ -1,57 +1,112 @@ 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 => (11 * keys %stores); +if ($ENV{DBICTEST_MEMCACHED}) { + if (DBIx::Class::Optional::Dependencies->req_ok_for ('test_memcached')) { + my $memcached = Cache::Memcached->new( + { servers => [ $ENV{DBICTEST_MEMCACHED} ] } + ); + + my $key = 'tmp_dbic_84serialize_memcached_test'; + + $stores{memcached} = sub { + $memcached->set( $key, $_[0], 60 ); + local $DBIx::Class::ResultSourceHandle::thaw_schema = $schema; + return $memcached->get($key); + }; + } + else { + SKIP: { + skip 'Memcached tests need ' . DBIx::Class::Optional::Dependencies->req_missing_for ('test_memcached'), 1; + } + } +} +else { + SKIP: { + skip 'Set $ENV{DBICTEST_MEMCACHED} to run the memcached serialization tests', 1; + } +} + + 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); - } 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"); my $cd_rs = $artist->search_related("cds"); - # test that a result source can be serialized as well - - $cd_rs->_resolved_attrs; # this builds up the {from} attr + # 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 ], @@ -66,10 +121,85 @@ for my $name (keys %stores) { 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); +} + +# test schema-less detached thaw +{ + my $artist = $schema->resultset('Artist')->find(1); + + $artist = dclone $artist; + + is( $artist->name, 'Caterwauler McCrae', 'getting column works' ); + + ok( $artist->update, 'Non-dirty update noop' ); + + ok( $artist->name( 'Beeeeeeees' ), 'setting works' ); + + ok( $artist->is_column_changed( 'name' ), 'Column dirtyness works' ); + ok( $artist->is_changed, 'object dirtyness works' ); + + my $rs = $artist->result_source->resultset; + $rs->set_cache([ $artist ]); + + is( $rs->count, 1, 'Synthetic resultset count works' ); + + my $exc = qr/Unable to perform storage-dependent operations with a detached result source.+use \$schema->thaw/; + + throws_ok { $artist->update } + $exc, + 'Correct exception on row op' + ; + + throws_ok { $artist->discard_changes } + $exc, + 'Correct exception on row op' + ; + + throws_ok { $rs->find(1) } + $exc, + 'Correct exception on rs op' + ; } + +done_testing;