X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2Fstorage%2Ftxn_scope_guard.t;h=09efcd7f6a83a774f1a6e2813d8c801cdb7e3ddb;hb=c40b5744f85a8ffc2da494464655936387c04251;hp=ca67c9874fa21b216cb8a51c5ce935b235469acb;hpb=153a6b389e6886920ff69ce0dab0ea7ee1df2fe0;p=dbsrgits%2FDBIx-Class-Historic.git diff --git a/t/storage/txn_scope_guard.t b/t/storage/txn_scope_guard.t index ca67c98..09efcd7 100644 --- a/t/storage/txn_scope_guard.t +++ b/t/storage/txn_scope_guard.t @@ -1,10 +1,16 @@ +BEGIN { do "./t/lib/ANFANG.pm" or die ( $@ || $! ) } + use strict; use warnings; use Test::More; use Test::Warn; use Test::Exception; -use lib qw(t/lib); + +use List::Util 'shuffle'; +use DBIx::Class::_Util 'sigwarn_silencer'; + + use DBICTest; # Test txn_scope_guard @@ -90,10 +96,8 @@ use DBICTest; { my $schema = DBICTest->init_schema; - no strict 'refs'; no warnings 'redefine'; - - local *{DBIx::Class::Storage::DBI::txn_rollback} = sub { die 'die die my darling' }; + local *DBIx::Class::Storage::DBI::txn_rollback = sub { die 'die die my darling' }; Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO; throws_ok (sub { @@ -106,7 +110,7 @@ use DBICTest; #$schema->storage->_dbh( $schema->storage->_dbh->clone ); die 'Deliberate exception'; - }, ($] >= 5.013008 ) + }, ( "$]" >= 5.013008 ) ? qr/Deliberate exception/s # temporary until we get the generic exception wrapper rolling : qr/Deliberate exception.+Rollback failed/s ); @@ -117,37 +121,9 @@ use DBICTest; # make sure it warns *big* on failed rollbacks # test with and without a poisoned $@ -for my $pre_poison (0,1) { -for my $post_poison (0,1) { - - my $schema = DBICTest->init_schema(no_populate => 1); - - no strict 'refs'; - no warnings 'redefine'; - local *{DBIx::Class::Storage::DBI::txn_rollback} = sub { die 'die die my darling' }; - Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO; - -#The warn from within a DESTROY callback freaks out Test::Warn, do it old-school -=begin - warnings_exist ( - sub { - my $guard = $schema->txn_scope_guard; - $schema->resultset ('Artist')->create ({ name => 'bohhoo'}); - - # this should freak out the guard rollback - # but it won't work because DBD::SQLite is buggy - # instead just install a toxic rollback above - #$schema->storage->_dbh( $schema->storage->_dbh->clone ); - }, - [ - qr/A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or error. Rolling back./, - qr/\*+ ROLLBACK FAILED\!\!\! \*+/, - ], - 'proper warnings generated on out-of-scope+rollback failure' - ); -=cut - -# delete this once the above works properly (same test) +require DBICTest::AntiPattern::TrueZeroLen; +require DBICTest::AntiPattern::NullObject; +{ my @want = ( qr/A DBIx::Class::Storage::TxnScopeGuard went out of scope without explicit commit or error. Rolling back./, qr/\*+ ROLLBACK FAILED\!\!\! \*+/, @@ -163,85 +139,104 @@ for my $post_poison (0,1) { } }; - { - eval { die 'pre-GIFT!' if $pre_poison }; - my $guard = $schema->txn_scope_guard; - eval { die 'post-GIFT!' if $post_poison }; - $schema->resultset ('Artist')->create ({ name => 'bohhoo'}); - } - - local $TODO = 'Do not know how to deal with trapped exceptions occuring after guard instantiation...' - if ( $post_poison and ( - # take no chances on installation - ( DBICTest::RunMode->is_plain and ($ENV{TRAVIS}||'') ne 'true' ) - or - # this always fails - ! $pre_poison - or - # I do not underdtand why but on <= 5.8.8 and $pre_poison && $post_poison passes... - $] > 5.008008 - )); - is (@w, 2, "Both expected warnings found - \$\@ pre-poison: $pre_poison, post-poison: $post_poison" ); + # we are driving manually here, do not allow interference + local $SIG{__DIE__} if $SIG{__DIE__}; - # just to mask off warning since we could not disconnect above - $schema->storage->_dbh->disconnect; -}} -# add a TODO to catch when Text::Balanced is finally fixed -# https://rt.cpan.org/Public/Bug/Display.html?id=74994 -# -# while it doesn't matter much for DBIC itself, this particular bug -# is a *BANE*, and DBIC is to bump its dep as soon as possible -{ + no warnings 'redefine'; + local *DBIx::Class::Storage::DBI::txn_rollback = sub { die 'die die my darling' }; + Class::C3->reinitialize() if DBIx::Class::_ENV_::OLD_MRO; - require Text::Balanced; + my @poisons = shuffle ( + undef, + DBICTest::AntiPattern::TrueZeroLen->new, + DBICTest::AntiPattern::NullObject->new, + 'GIFT!', + ); - my $great_success; - { - local $TODO = 'RT#74994 *STILL* not fixed'; + for my $pre_poison (@poisons) { + for my $post_poison (@poisons) { - lives_ok { - # this is what poisons $@ - Text::Balanced::extract_bracketed( '(foo', '()' ); + @w = (); - my $s = DBICTest->init_schema( deploy => 0 ); - my $g = $s->txn_scope_guard; - $g->commit; - $great_success++; - } 'Text::Balanced is no longer screwing up $@'; - } + my $schema = DBICTest->init_schema(no_populate => 1); - # delete all of this when T::B dep is bumped - unless ($great_success) { + # the actual scope where the guard is created/freed + { + # in this particular case these are not the warnings we are looking for + local $SIG{__WARN__} = sigwarn_silencer qr/implementing the so called null-object-pattern/; -# hacky workaround for desperate folk -# intended to be copypasted into your app - { - require Text::Balanced; - require overload; + # if is inside the eval, to clear $@ in the undef case + eval { die $pre_poison if defined $pre_poison }; - local $@; + my $guard = $schema->txn_scope_guard; - # this is what poisons $@ - Text::Balanced::extract_bracketed( '(foo', '()' ); + eval { die $post_poison if defined $post_poison }; - if ($@ and overload::Overloaded($@) and ! overload::Method($@,'fallback') ) { - my $class = ref $@; - eval "package $class; overload->import(fallback => 1);" + $schema->resultset ('Artist')->create ({ name => "bohhoo, too bad we'll roll you back"}); } + + local $TODO = 'Do not know how to deal with trapped exceptions occuring after guard instantiation...' + if ( defined $post_poison and ( + # take no chances on installation + DBICTest::RunMode->is_plain + or + # I do not understand why but on <= 5.8.8 and on 5.10.0 + # "$pre_poison == $post_poison == string" passes... + # so todoify 5.8.9 and 5.10.1+, and deal with the rest below + ( ( "$]" > 5.008008 and "$]" < 5.010000 ) or "$]" > 5.010000 ) + or + ! defined $pre_poison + or + length ref $pre_poison + or + length ref $post_poison + )); + + is (@w, 2, sprintf 'Both expected warnings found - $@ poisonstate: pre-poison:%s post-poison:%s', + map { + ! defined $_ ? 'UNDEF' + : ! length ref $_ ? $_ + : ref $_ + + } ($pre_poison, $post_poison) + ); + + # just to mask off warning since we could not disconnect above + $schema->storage->_dbh->disconnect; } -# end of hacky workaround + } +} + +# add a TODO to catch when Text::Balanced is finally fixed +# https://rt.cpan.org/Public/Bug/Display.html?id=74994 +# +# while it doesn't matter much for DBIC itself, this particular bug +# is a *BANE*, and DBIC is to bump its dep as soon as possible +{ - lives_ok { - # this is what poisons $@ - Text::Balanced::extract_bracketed( '(foo', '()' ); + require Text::Balanced; - my $s = DBICTest->init_schema( deploy => 0 ); - my $g = $s->txn_scope_guard; - $g->commit; - } 'Monkeypatched Text::Balanced is no longer screwing up $@'; - } + my @w; + local $SIG{__WARN__} = sub { + $_[0] =~ /External exception class .+? \Qimplements partial (broken) overloading/ + ? push @w, @_ + : warn @_ + }; + + lives_ok { + # this is what poisons $@ + Text::Balanced::extract_bracketed( '(foo', '()' ); + DBIx::Class::_Util::is_exception($@); + + my $s = DBICTest::Schema->connect('dbi:SQLite::memory:'); + my $g = $s->txn_scope_guard; + $g->commit; + } 'Broken Text::Balanced is not screwing up txn_guard'; + + local $TODO = 'RT#74994 *STILL* not fixed'; + is(scalar @w, 0, 'no warnings \o/'); } done_testing;