bbb5f4ea0de793b9e5ccc3cb8740ad0ffa91c3d0
[dbsrgits/DBIx-Class-Historic.git] / t / 84serialize.t
1 BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) }
2
3 use strict;
4 use warnings;
5
6 use Test::More;
7 use Test::Exception;
8
9 use DBICTest;
10 use Storable qw(dclone freeze nfreeze thaw);
11 use Scalar::Util qw/refaddr/;
12 use Carp;
13
14 sub ref_ne {
15   my ($refa, $refb) = map { refaddr $_ or croak "$_ is not a reference!" } @_[0,1];
16   cmp_ok (
17     $refa,
18       '!=',
19     $refb,
20     sprintf ('%s (0x%07x != 0x%07x)',
21       $_[2],
22       $refa,
23       $refb,
24     ),
25   );
26 }
27
28 my $schema = DBICTest->init_schema;
29
30 my %stores = (
31     dclone_method           => sub { return $schema->dclone($_[0]) },
32     dclone_func             => sub {
33       local $DBIx::Class::ResultSourceHandle::thaw_schema = $schema;
34       return dclone($_[0])
35     },
36     "freeze/thaw_method"    => sub {
37       my $ice = $schema->freeze($_[0]);
38       return $schema->thaw($ice);
39     },
40     "nfreeze/thaw_func"      => sub {
41       my $ice = freeze($_[0]);
42       local $DBIx::Class::ResultSourceHandle::thaw_schema = $schema;
43       return thaw($ice);
44     },
45
46     "freeze/thaw_func (cdbi legacy)" => sub {
47       # this one is special-cased to leak the $schema all over
48       # the same way as cdbi-compat does
49       DBICTest::Artist->result_source_instance->schema($schema);
50       DBICTest::CD->result_source_instance->schema($schema);
51
52       my $fire = thaw(freeze($_[0]));
53
54       # clean up the mess
55       $_->result_source_instance->schema(undef)
56         for map { $schema->class ($_) } $schema->sources;
57
58       return $fire;
59     },
60
61 );
62
63 SKIP: {
64     DBIx::Class::Optional::Dependencies->skip_without('test_memcached');
65
66     my $memcached = Cache::Memcached->new(
67       { servers => [ $ENV{DBICTEST_MEMCACHED} ] }
68     );
69
70     my $key = 'tmp_dbic_84serialize_memcached_test';
71
72     $stores{memcached} = sub {
73       $memcached->set( $key, $_[0], 60 )
74         or die "Unable to insert into $ENV{DBICTEST_MEMCACHED} - is server running?";
75       local $DBIx::Class::ResultSourceHandle::thaw_schema = $schema;
76       return $memcached->get($key);
77     };
78 }
79
80 for my $name (keys %stores) {
81
82     my $store = $stores{$name};
83     my $copy;
84
85     my $artist = $schema->resultset('Artist')->find(1);
86
87     lives_ok { $copy = $store->($artist) } "serialize row object lives: $name";
88     ref_ne($copy, $artist, 'Simple row cloned');
89     is_deeply($copy, $artist, "serialize row object works: $name");
90
91     my $cd_rs = $artist->search_related("cds");
92
93     # test that a live result source can be serialized as well
94     is( $cd_rs->count, 3, '3 CDs in database');
95     ok( $cd_rs->next, 'Advance cursor' );
96
97     lives_ok {
98       $copy = $store->($cd_rs);
99
100       ref_ne($copy, $artist, 'Simple row cloned');
101
102       is_deeply (
103         [ $copy->all ],
104         [ $cd_rs->all ],
105         "serialize resultset works: $name",
106       );
107     } "serialize resultset lives: $name";
108
109     # Test that an object with a related_resultset can be serialized.
110     ok $artist->{related_resultsets}, 'has key: related_resultsets';
111
112     lives_ok { $copy = $store->($artist) } "serialize row object with related_resultset lives: $name";
113     for my $key (keys %$artist) {
114         next if $key eq 'related_resultsets';
115         next if $key eq '_inflated_column';
116
117         ref_ne($copy->{$key}, $artist->{$key}, "Simple row internals cloned '$key'")
118           if ref $artist->{$key};
119
120         is_deeply($copy->{$key}, $artist->{$key},
121                   qq[serialize with related_resultset '$key']);
122     }
123
124     lives_ok(
125       sub { $copy->discard_changes }, "Discard changes works: $name"
126     ) or diag $@;
127     is($copy->id, $artist->id, "IDs still match ");
128
129
130     # Test resultsource with cached rows
131     $schema->is_executed_querycount( sub {
132       $cd_rs = $cd_rs->search ({}, { cache => 1 });
133
134       # this will hit the database once and prime the cache
135       my @cds = $cd_rs->all;
136
137       $copy = $store->($cd_rs);
138       ref_ne($copy, $cd_rs, 'Cached resultset cloned');
139       is_deeply (
140         [ $copy->all ],
141         [ $cd_rs->all ],
142         "serialize cached resultset works: $name",
143       );
144
145       is ($copy->count, $cd_rs->count, 'Cached count identical');
146     }, 1, 'Only one db query fired');
147 }
148
149 # test schema-less detached thaw
150 {
151   my $artist = $schema->resultset('Artist')->find(1);
152
153   $artist = dclone $artist;
154
155   is( $artist->name, 'Caterwauler McCrae', 'getting column works' );
156
157   ok( $artist->update, 'Non-dirty update noop' );
158
159   ok( $artist->name( 'Beeeeeeees' ), 'setting works' );
160
161   ok( $artist->is_column_changed( 'name' ), 'Column dirtyness works' );
162   ok( $artist->is_changed, 'object dirtyness works' );
163
164   my $rs = $artist->result_source->resultset;
165   $rs->set_cache([ $artist ]);
166
167   is( $rs->count, 1, 'Synthetic resultset count works' );
168
169   my $exc = qr/Unable to perform storage-dependent operations with a detached result source.+use \$schema->thaw/;
170
171   throws_ok { $artist->update }
172     $exc,
173     'Correct exception on row op'
174   ;
175
176   throws_ok { $artist->discard_changes }
177     $exc,
178     'Correct exception on row op'
179   ;
180
181   throws_ok { $rs->find(1) }
182     $exc,
183     'Correct exception on rs op'
184   ;
185 }
186
187 done_testing;