Consolidate pg/mysql and standalone SQLite savepoint tests to run on all 3
Peter Rabbitson [Tue, 27 May 2014 06:29:46 +0000 (08:29 +0200)]
A larger consolidation will take place later with T::WV, but all in due time

t/752sqlite.t
t/storage/savepoints.t [moved from t/98savepoints.t with 53% similarity]

index 273a1ed..008b7f1 100644 (file)
@@ -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
similarity index 53%
rename from t/98savepoints.t
rename to t/storage/savepoints.t
index a195b85..fab7036 100644 (file)
@@ -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");
 }}