9 my $schema = DBICTest->init_schema();
14 my ($artist, @cd_titles) = @_;
16 $artist->create_related('cds', {
19 }) foreach (@cd_titles);
21 return $artist->cds->all;
24 # Test checking of parameters
27 (ref $schema)->txn_do(sub{});
29 like($@, qr/storage/, "can't call txn_do without storage");
33 like($@, qr/must be a CODE reference/, '$coderef parameter check ok');
36 # Test successful txn_do() - scalar context
38 is( $schema->storage->{transaction_depth}, 0, 'txn depth starts at 0');
40 my @titles = map {'txn_do test CD ' . $_} (1..5);
41 my $artist = $schema->resultset('Artist')->find(1);
42 my $count_before = $artist->cds->count;
43 my $count_after = $schema->txn_do($code, $artist, @titles);
44 is($count_after, $count_before+5, 'successful txn added 5 cds');
46 title => "txn_do test CD $_",
47 })->first->year, 2006, "new CD $_ year correct") for (1..5);
49 is( $schema->storage->{transaction_depth}, 0, 'txn depth has been reset');
52 # Test successful txn_do() - list context
54 is( $schema->storage->{transaction_depth}, 0, 'txn depth starts at 0');
56 my @titles = map {'txn_do test CD ' . $_} (6..10);
57 my $artist = $schema->resultset('Artist')->find(1);
58 my $count_before = $artist->cds->count;
59 my @cds = $schema->txn_do($code, $artist, @titles);
60 is(scalar @cds, $count_before+5, 'added 5 CDs and returned in list context');
62 title => "txn_do test CD $_",
63 })->first->year, 2006, "new CD $_ year correct") for (6..10);
65 is( $schema->storage->{transaction_depth}, 0, 'txn depth has been reset');
68 # Test nested successful txn_do()
70 is( $schema->storage->{transaction_depth}, 0, 'txn depth starts at 0');
72 my $nested_code = sub {
73 my ($schema, $artist, $code) = @_;
75 my @titles1 = map {'nested txn_do test CD ' . $_} (1..5);
76 my @titles2 = map {'nested txn_do test CD ' . $_} (6..10);
78 $schema->txn_do($code, $artist, @titles1);
79 $schema->txn_do($code, $artist, @titles2);
82 my $artist = $schema->resultset('Artist')->find(2);
83 my $count_before = $artist->cds->count;
86 $schema->txn_do($nested_code, $schema, $artist, $code);
91 ok(!$error, 'nested txn_do succeeded');
93 title => 'nested txn_do test CD '.$_,
94 })->first->year, 2006, qq{nested txn_do CD$_ year ok}) for (1..10);
95 is($artist->cds->count, $count_before+10, 'nested txn_do added all CDs');
97 is( $schema->storage->{transaction_depth}, 0, 'txn depth has been reset');
100 my $fail_code = sub {
102 $artist->create_related('cds', {
103 title => 'this should not exist',
106 die "the sky is falling";
109 # Test failed txn_do()
112 is( $schema->storage->{transaction_depth}, 0, 'txn depth starts at 0');
114 my $artist = $schema->resultset('Artist')->find(3);
117 $schema->txn_do($fail_code, $artist);
122 like($error, qr/the sky is falling/, 'failed txn_do threw an exception');
123 my $cd = $artist->cds({
124 title => 'this should not exist',
127 ok(!defined($cd), q{failed txn_do didn't change the cds table});
129 is( $schema->storage->{transaction_depth}, 0, 'txn depth has been reset');
132 # do the same transaction again
134 is( $schema->storage->{transaction_depth}, 0, 'txn depth starts at 0');
136 my $artist = $schema->resultset('Artist')->find(3);
139 $schema->txn_do($fail_code, $artist);
144 like($error, qr/the sky is falling/, 'failed txn_do threw an exception');
145 my $cd = $artist->cds({
146 title => 'this should not exist',
149 ok(!defined($cd), q{failed txn_do didn't change the cds table});
151 is( $schema->storage->{transaction_depth}, 0, 'txn depth has been reset');
154 # Test failed txn_do() with failed rollback
156 is( $schema->storage->{transaction_depth}, 0, 'txn depth starts at 0');
158 my $artist = $schema->resultset('Artist')->find(3);
160 # Force txn_rollback() to throw an exception
161 no warnings 'redefine';
164 # die in rollback, but maintain sanity for further tests ...
165 local *{"DBIx::Class::Storage::DBI::SQLite::txn_rollback"} = sub{
167 $storage->{transaction_depth}--;
172 $schema->txn_do($fail_code, $artist);
177 like($error, qr/Rollback failed/, 'failed txn_do with a failed '.
178 'txn_rollback threw a rollback exception');
179 like($error, qr/the sky is falling/, 'failed txn_do with a failed '.
180 'txn_rollback included the original exception');
182 my $cd = $artist->cds({
183 title => 'this should not exist',
186 isa_ok($cd, 'DBICTest::CD', q{failed txn_do with a failed txn_rollback }.
187 q{changed the cds table});
188 $cd->delete; # Rollback failed
190 title => 'this should not exist',
193 ok(!defined($cd), q{deleted the failed txn's cd});
194 $schema->storage->_dbh->rollback;
197 # Test nested failed txn_do()
199 is( $schema->storage->{transaction_depth}, 0, 'txn depth starts at 0');
201 my $nested_fail_code = sub {
202 my ($schema, $artist, $code1, $code2) = @_;
204 my @titles = map {'nested txn_do test CD ' . $_} (1..5);
206 $schema->txn_do($code1, $artist, @titles); # successful txn
207 $schema->txn_do($code2, $artist); # failed txn
210 my $artist = $schema->resultset('Artist')->find(3);
213 $schema->txn_do($nested_fail_code, $schema, $artist, $code, $fail_code);
218 like($error, qr/the sky is falling/, 'nested failed txn_do threw exception');
219 ok(!defined($artist->cds({
220 title => 'nested txn_do test CD '.$_,
222 })->first), qq{failed txn_do didn't add first txn's cd $_}) for (1..5);
223 my $cd = $artist->cds({
224 title => 'this should not exist',
227 ok(!defined($cd), q{failed txn_do didn't add failed txn's cd});
230 # Grab a new schema to test txn before connect
232 my $schema2 = DBICTest->init_schema(no_deploy => 1);
234 $schema2->txn_begin();
235 $schema2->txn_begin();
238 ok(($err eq ''), 'Pre-connection nested transactions.');
241 # Test txn_rollback with nested
243 local $TODO = "Work out how this should work";
244 my $local_schema = DBICTest->init_schema();
246 my $artist_rs = $local_schema->resultset('Artist');
249 $local_schema->txn_begin;
250 $artist_rs->create({ name => 'Test artist rollback 1'});
251 $local_schema->txn_begin;
252 is($local_schema->storage->transaction_depth, 2, "Correct transaction depth");
253 $artist_rs->create({ name => 'Test artist rollback 2'});
254 $local_schema->txn_rollback;
255 } qr/Not sure what this should be.... something tho/, "Rolled back okay";
256 is($local_schema->storage->transaction_depth, 0, "Correct transaction depth");
258 ok(!$artist_rs->find({ name => 'Test artist rollback 1'}), "Test Artist not created")
259 || $artist_rs->find({ name => 'Test artist rollback 1'})->delete;
262 # Test txn_scope_guard
264 local $TODO = "Work out how this should work";
265 my $schema = DBICTest->init_schema();
267 is($schema->storage->transaction_depth, 0, "Correct transaction depth");
268 my $artist_rs = $schema->resultset('Artist');
270 my $guard = $schema->txn_scope_guard;
274 name => 'Death Cab for Cutie',
279 } qr/No such column made_up_column.*?line 16/, "Error propogated okay";
281 ok(!$artist_rs->find({name => 'Death Cab for Cutie'}), "Artist not created");
287 is($@, $inner_exception, "Nested exceptions propogated");
289 ok(!$artist_rs->find({name => 'Death Cab for Cutie'}), "Artist not created");
293 # The 0 arg says done die, just let the scope guard go out of scope
294 # forcing a txn_rollback to happen
297 is($@, "Not sure what we want here, but something", "Rollback okay");
299 ok(!$artist_rs->find({name => 'Death Cab for Cutie'}), "Artist not created");
304 my $guard = $schema->txn_scope_guard;
305 $schema->resultset('Artist')->create({
306 name => 'Death Cab for Cutie',
313 my ($schema, $fatal) = @_;
314 my $guard = $schema->txn_scope_guard;
316 my $artist = $artist_rs->find({ name => 'Death Cab for Cutie' });
318 is($schema->storage->transaction_depth, 2, "Correct transaction depth");
321 $artist->cds->create({
324 $fatal ? ( foo => 'bar' ) : ()
328 # Record what got thrown so we can test it propgates out properly.
329 $inner_exception = $@;
333 # See what happens if we dont $guard->commit;