Fix building on perls with no . in @INC
[dbsrgits/DBIx-Class.git] / t / 84serialize.t
index a8cedf0..021c44e 100644 (file)
+BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }
+
 use strict;
-use warnings;  
+use warnings;
 
 use Test::More;
-use lib qw(t/lib);
+use Test::Exception;
+
 use DBICTest;
-use Storable;
+use Storable qw(dclone freeze nfreeze thaw);
+use Scalar::Util qw/refaddr/;
+use Carp;
+
+sub ref_ne {
+  my ($refa, $refb) = map { refaddr $_ or croak "$_ 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 {
+      local $DBIx::Class::ResultSourceHandle::thaw_schema = $schema;
+      return dclone($_[0])
+    },
+    "freeze/thaw_method"    => sub {
+      my $ice = $schema->freeze($_[0]);
+      return $schema->thaw($ice);
+    },
+    "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;
+    },
+
+);
+
+SKIP: {
+    require DBIx::Class::Optional::Dependencies;
+    DBIx::Class::Optional::Dependencies->skip_without('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 )
+        or die "Unable to insert into $ENV{DBICTEST_MEMCACHED} - is server running?";
+      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);
+
+    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 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';
+
+    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']);
+    }
+
+    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
+    $schema->is_executed_querycount( sub {
+      $cd_rs = $cd_rs->search ({}, { cache => 1 });
+
+      # this will hit the database once and prime the cache
+      my @cds = $cd_rs->all;
+
+      $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');
+    }, 1, 'Only one db query fired');
+}
+
+# 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/;
 
-my $schema = DBICTest->init_schema();
+  throws_ok { $artist->update }
+    $exc,
+    'Correct exception on row op'
+  ;
 
-plan tests => 1;
+  throws_ok { $artist->discard_changes }
+    $exc,
+    'Correct exception on row op'
+  ;
 
-my $artist = $schema->resultset('Artist')->find(1);
-my $copy = eval { Storable::dclone($artist) };
-is_deeply($copy, $artist, 'serialize row object works');
+  throws_ok { $rs->find(1) }
+    $exc,
+    'Correct exception on rs op'
+  ;
+}
 
+done_testing;