From: Peter Rabbitson Date: Tue, 27 May 2014 06:29:46 +0000 (+0200) Subject: Consolidate pg/mysql and standalone SQLite savepoint tests to run on all 3 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=cf1d16d808be1dc3d7270f9f6072b832d0dbb327;p=dbsrgits%2FDBIx-Class-Historic.git Consolidate pg/mysql and standalone SQLite savepoint tests to run on all 3 A larger consolidation will take place later with T::WV, but all in due time --- diff --git a/t/752sqlite.t b/t/752sqlite.t index 273a1ed..008b7f1 100644 --- a/t/752sqlite.t +++ b/t/752sqlite.t @@ -11,40 +11,6 @@ use lib qw(t/lib); use DBICTest; use DBIx::Class::_Util qw(sigwarn_silencer modver_gt_or_eq); -# savepoints test -{ - my $schema = DBICTest->init_schema(auto_savepoint => 1); - - my $ars = $schema->resultset('Artist'); - - # test two-phase commit and inner transaction rollback from nested transactions - $schema->txn_do(sub { - $ars->create({ name => 'in_outer_transaction' }); - $schema->txn_do(sub { - $ars->create({ name => 'in_inner_transaction' }); - }); - ok($ars->search({ name => 'in_inner_transaction' })->first, - 'commit from inner transaction visible in outer transaction'); - throws_ok { - $schema->txn_do(sub { - $ars->create({ name => 'in_inner_transaction_rolling_back' }); - die 'rolling back inner transaction'; - }); - } qr/rolling back inner transaction/, 'inner transaction rollback executed'; - $ars->create({ name => 'in_outer_transaction2' }); - }); - - ok($ars->search({ name => 'in_outer_transaction' })->first, - 'commit from outer transaction'); - ok($ars->search({ name => 'in_outer_transaction2' })->first, - 'second commit from outer transaction'); - ok($ars->search({ name => 'in_inner_transaction' })->first, - 'commit from inner transaction'); - is $ars->search({ name => 'in_inner_transaction_rolling_back' })->first, - undef, - 'rollback from inner transaction'; -} - # check that we work somewhat OK with braindead SQLite transaction handling # # As per https://metacpan.org/source/ADAMK/DBD-SQLite-1.37/lib/DBD/SQLite.pm#L921 diff --git a/t/98savepoints.t b/t/storage/savepoints.t similarity index 53% rename from t/98savepoints.t rename to t/storage/savepoints.t index a195b85..fab7036 100644 --- a/t/98savepoints.t +++ b/t/storage/savepoints.t @@ -2,45 +2,56 @@ use strict; use warnings; use Test::More; +use Test::Exception; use DBIx::Class::Optional::Dependencies (); my $env2optdep = { - DBICTEST_PG => 'rdbms_pg', + DBICTEST_PG => 'test_rdbms_pg', DBICTEST_MYSQL => 'test_rdbms_mysql', }; -plan skip_all => join (' ', - 'Set $ENV{DBICTEST_PG_DSN} and/or $ENV{DBICTEST_MYSQL_DSN} _USER and _PASS to run these tests.', -) unless grep { $ENV{"${_}_DSN"} } keys %$env2optdep; - use lib qw(t/lib); use DBICTest; use DBICTest::Stats; my $schema; -for my $prefix (keys %$env2optdep) { SKIP: { - my ($dsn, $user, $pass) = map { $ENV{"${prefix}_$_"} } qw/DSN USER PASS/; +for ('', keys %$env2optdep) { SKIP: { - skip ("Skipping tests with $prefix: set \$ENV{${prefix}_DSN} _USER and _PASS", 1) - unless $dsn; + my $prefix; - skip ("Testing with ${prefix}_DSN needs " . DBIx::Class::Optional::Dependencies->req_missing_for( $env2optdep->{$prefix} ), 1) - unless DBIx::Class::Optional::Dependencies->req_ok_for($env2optdep->{$prefix}); + if ($prefix = $_) { + my ($dsn, $user, $pass) = map { $ENV{"${prefix}_$_"} } qw/DSN USER PASS/; - $schema = DBICTest::Schema->connect ($dsn,$user,$pass,{ auto_savepoint => 1 }); + skip ("Skipping tests with $prefix: set \$ENV{${prefix}_DSN} _USER and _PASS", 1) + unless $dsn; - my $create_sql; - $schema->storage->ensure_connected; - if ($schema->storage->isa('DBIx::Class::Storage::DBI::Pg')) { - $create_sql = "CREATE TABLE artist (artistid serial PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10))"; - $schema->storage->dbh->do('SET client_min_messages=WARNING'); - } - elsif ($schema->storage->isa('DBIx::Class::Storage::DBI::mysql')) { - $create_sql = "CREATE TABLE artist (artistid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10)) ENGINE=InnoDB"; + skip ("Testing with ${prefix}_DSN needs " . DBIx::Class::Optional::Dependencies->req_missing_for( $env2optdep->{$prefix} ), 1) + unless DBIx::Class::Optional::Dependencies->req_ok_for($env2optdep->{$prefix}); + + $schema = DBICTest::Schema->connect ($dsn,$user,$pass,{ auto_savepoint => 1 }); + + my $create_sql; + $schema->storage->ensure_connected; + if ($schema->storage->isa('DBIx::Class::Storage::DBI::Pg')) { + $create_sql = "CREATE TABLE artist (artistid serial PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10))"; + $schema->storage->dbh->do('SET client_min_messages=WARNING'); + } + elsif ($schema->storage->isa('DBIx::Class::Storage::DBI::mysql')) { + $create_sql = "CREATE TABLE artist (artistid INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100), rank INTEGER NOT NULL DEFAULT '13', charfield CHAR(10)) ENGINE=InnoDB"; + } + else { + skip( 'Untested driver ' . $schema->storage, 1 ); + } + + $schema->storage->dbh_do (sub { + $_[1]->do('DROP TABLE IF EXISTS artist'); + $_[1]->do($create_sql); + }); } else { - skip( 'Untested driver ' . $schema->storage, 1 ); + $prefix = 'SQLite Internal DB'; + $schema = DBICTest->init_schema( no_populate => 1, auto_savepoint => 1 ); } note "Testing $prefix"; @@ -49,9 +60,6 @@ for my $prefix (keys %$env2optdep) { SKIP: { $schema->storage->debugobj($stats); $schema->storage->debug(1); - $schema->storage->dbh->do ('DROP TABLE IF EXISTS artist'); - $schema->storage->dbh->do ($create_sql); - $schema->resultset('Artist')->create({ name => 'foo' }); $schema->txn_begin; @@ -94,6 +102,7 @@ for my $prefix (keys %$env2optdep) { SKIP: { $arty->update({ name => 'gphat' }); $arty->discard_changes; cmp_ok($arty->name, 'eq', 'gphat', 'name changed'); + # Active: 0 1 2 # Rollback doesn't DESTROY the savepoint, it just rolls back to the value # at its conception @@ -104,6 +113,7 @@ for my $prefix (keys %$env2optdep) { SKIP: { # Active: 0 1 2 3 $schema->svp_begin('testing3'); $arty->update({ name => 'coryg' }); + # Active: 0 1 2 3 4 $schema->svp_begin('testing4'); $arty->update({ name => 'watson' }); @@ -111,11 +121,14 @@ for my $prefix (keys %$env2optdep) { SKIP: { # Release 3, which implicitly releases 4 # Active: 0 1 2 $schema->svp_release('testing3'); + $arty->discard_changes; cmp_ok($arty->name, 'eq', 'watson', 'release left data'); + # This rolls back savepoint 2 # Active: 0 1 2 $schema->svp_rollback; + $arty->discard_changes; cmp_ok($arty->name, 'eq', 'yourmom', 'rolled back to 2'); @@ -127,6 +140,8 @@ for my $prefix (keys %$env2optdep) { SKIP: { $schema->txn_commit; + is_deeply( $schema->storage->savepoints, [], 'All savepoints forgotten' ); + # And now to see if txn_do will behave correctly $schema->txn_do (sub { my $artycp = $arty; @@ -157,6 +172,8 @@ for my $prefix (keys %$env2optdep) { SKIP: { $arty->update; }); + is_deeply( $schema->storage->savepoints, [], 'All savepoints forgotten' ); + $arty->discard_changes; is($arty->name,'Miff','auto_savepoint worked'); @@ -167,6 +184,39 @@ for my $prefix (keys %$env2optdep) { SKIP: { cmp_ok($stats->{'SVP_ROLLBACK'},'==',5,'Correct number of savepoint rollbacks'); +### test originally written for SQLite exclusively (git blame -w -C -M) + # test two-phase commit and inner transaction rollback from nested transactions + my $ars = $schema->resultset('Artist'); + + $schema->txn_do(sub { + $ars->create({ name => 'in_outer_transaction' }); + $schema->txn_do(sub { + $ars->create({ name => 'in_inner_transaction' }); + }); + ok($ars->search({ name => 'in_inner_transaction' })->first, + 'commit from inner transaction visible in outer transaction'); + throws_ok { + $schema->txn_do(sub { + $ars->create({ name => 'in_inner_transaction_rolling_back' }); + die 'rolling back inner transaction'; + }); + } qr/rolling back inner transaction/, 'inner transaction rollback executed'; + $ars->create({ name => 'in_outer_transaction2' }); + }); + + is_deeply( $schema->storage->savepoints, [], 'All savepoints forgotten' ); + + ok($ars->search({ name => 'in_outer_transaction' })->first, + 'commit from outer transaction'); + ok($ars->search({ name => 'in_outer_transaction2' })->first, + 'second commit from outer transaction'); + ok($ars->search({ name => 'in_inner_transaction' })->first, + 'commit from inner transaction'); + is $ars->search({ name => 'in_inner_transaction_rolling_back' })->first, + undef, + 'rollback from inner transaction'; + +### cleanupz $schema->storage->dbh->do ("DROP TABLE artist"); }}