X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2Fstorage%2Freconnect.t;h=fc97ebd403a582756145467b96ba65a97606e70b;hb=d85ef5e2867bc0360a72090aeaea4308792651e8;hp=784a2457c117ce412e22698cd69e2263c6fdaeb2;hpb=8d1fb3e2db62af871fa19e9d632c317021a356a5;p=dbsrgits%2FDBIx-Class.git diff --git a/t/storage/reconnect.t b/t/storage/reconnect.t index 784a245..fc97ebd 100644 --- a/t/storage/reconnect.t +++ b/t/storage/reconnect.t @@ -2,7 +2,9 @@ use strict; use warnings; use FindBin; +use B::Deparse; use File::Copy 'move'; +use Scalar::Util 'weaken'; use Test::More; use Test::Exception; use lib qw(t/lib); @@ -14,8 +16,14 @@ my $db_tmp = "$db_orig.tmp"; # Set up the "usual" sqlite for DBICTest my $schema = DBICTest->init_schema( sqlite_use_file => 1 ); +my $exception_action_count; +$schema->exception_action(sub { + $exception_action_count++; + die @_; +}); + # Make sure we're connected by doing something -my @art = $schema->resultset("Artist")->search({ }, { order_by => 'name DESC'}); +my @art = $schema->resultset("Artist")->search({ }, { order_by => { -desc => 'name' }}); cmp_ok(@art, '==', 3, "Three artists returned"); # Disconnect the dbh, and be sneaky about it @@ -32,7 +40,7 @@ cmp_ok(@art, '==', 3, "Three artists returned"); # 2. It catches the exception, checks ->{Active}/->ping, sees the disconnected state... # 3. Reconnects, and retries the operation # 4. Success! -my @art_two = $schema->resultset("Artist")->search({ }, { order_by => 'name DESC'}); +my @art_two = $schema->resultset("Artist")->search({ }, { order_by => { -desc => 'name' }}); cmp_ok(@art_two, '==', 3, "Three artists returned"); ### Now, disconnect the dbh, and move the db file; @@ -49,7 +57,7 @@ close $db_file; # Catch the DBI connection error local $SIG{__WARN__} = sub {}; throws_ok { - my @art_three = $schema->resultset("Artist")->search( {}, { order_by => 'name DESC' } ); + $schema->resultset("Artist")->create({ name => 'not gonna happen' }); } qr/not a database/, 'The operation failed'; } @@ -63,7 +71,7 @@ move( $db_tmp, $db_orig ) ### Try the operation again... this time, it should succeed my @art_four; lives_ok { - @art_four = $schema->resultset("Artist")->search( {}, { order_by => 'name DESC' } ); + @art_four = $schema->resultset("Artist")->search( {}, { order_by => { -desc => 'name' } } ); } 'The operation succeeded'; cmp_ok( @art_four, '==', 3, "Three artists returned" ); @@ -90,6 +98,8 @@ for my $ctx (keys %$ctx_map) { # start disconnected and then connected $schema->storage->disconnect; + $exception_action_count = 0; + for (1, 2) { my $disarmed; @@ -104,6 +114,86 @@ for my $ctx (keys %$ctx_map) { isa_ok ($schema->resultset('Artist')->next, 'DBICTest::Artist'); }, @$args) }); } + + is( $exception_action_count, 0, 'exception_action never called' ); }; +# make sure RT#110429 does not recur on manual DBI-side disconnect +for my $cref ( + sub { + my $schema = shift; + + my $g = $schema->txn_scope_guard; + + is( $schema->storage->transaction_depth, 1, "Expected txn depth" ); + + $schema->storage->_dbh->disconnect; + + $schema->storage->dbh_do(sub { $_[1]->do('SELECT 1') } ); + }, + sub { + my $schema = shift; + $schema->txn_do(sub { + $schema->storage->_dbh->disconnect + } ); + }, + sub { + my $schema = shift; + $schema->txn_do(sub { + $schema->storage->disconnect; + die "VIOLENCE"; + } ); + }, +) { + + note( "Testing with " . B::Deparse->new->coderef2text($cref) ); + + $schema->storage->disconnect; + $exception_action_count = 0; + + ok( !$schema->storage->connected, 'Not connected' ); + + is( $schema->storage->transaction_depth, undef, "Start with unknown txn depth" ); + + # messages vary depending on version and whether txn or do, whatever + dies_ok { + $cref->($schema) + } 'Threw *something*'; + + ok( !$schema->storage->connected, 'Not connected as a result of failed rollback' ); + + is( $schema->storage->transaction_depth, undef, "Depth expectedly unknown after failed rollbacks" ); + + is( $exception_action_count, 1, "exception_action called only once" ); +} + +# check exception_action under tenacious disconnect +{ + $schema->storage->disconnect; + $exception_action_count = 0; + + throws_ok { $schema->txn_do(sub { + $schema->storage->_dbh->disconnect; + + $schema->resultset('Artist')->next; + })} qr/prepare on inactive database handle/; + + is( $exception_action_count, 1, "exception_action called only once" ); +} + +# check that things aren't crazy with a non-violent disconnect +{ + my $schema = DBICTest->init_schema( sqlite_use_file => 0, no_deploy => 1 ); + weaken( my $ws = $schema ); + + $schema->is_executed_sql_bind( sub { + $ws->txn_do(sub { $ws->storage->disconnect } ); + }, [ [ 'BEGIN' ] ], 'Only one BEGIN statement' ); + + $schema->is_executed_sql_bind( sub { + my $g = $ws->txn_scope_guard; + $ws->storage->disconnect; + }, [ [ 'BEGIN' ] ], 'Only one BEGIN statement' ); +} + done_testing;