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