X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=t%2Flib%2FDBICTest%2FBaseSchema.pm;h=726ce10f26f6627695fadbed625f969a5a6e0f8f;hb=44c1a75dd318ee6d943c91939c1b595ecc1d625b;hp=0214933cdecac1c914a4787cc1bdfa9b44989079;hpb=e48635f7178f8527ec3cc230f1cf869e8876dc39;p=dbsrgits%2FDBIx-Class.git diff --git a/t/lib/DBICTest/BaseSchema.pm b/t/lib/DBICTest/BaseSchema.pm index 0214933..726ce10 100644 --- a/t/lib/DBICTest/BaseSchema.pm +++ b/t/lib/DBICTest/BaseSchema.pm @@ -13,13 +13,28 @@ use DBICTest::Util qw( local_umask tmpdir await_flock dbg DEBUG_TEST_CONCURRENCY use namespace::clean; if( $ENV{DBICTEST_ASSERT_NO_SPURIOUS_EXCEPTION_ACTION} ) { - __PACKAGE__->exception_action( sub { + my $ea = __PACKAGE__->exception_action( sub { - my ( $fr_num, $disarmed, $throw_exception_fr_num ); + # Can not rely on $^S here at all - the exception_action + # itself is always called in an eval so that the goto-guard + # can work (see 7cb35852) + + my ( $fr_num, $disarmed, $throw_exception_fr_num, $eval_fr_num ); while( ! $disarmed and my @fr = caller(++$fr_num) ) { $throw_exception_fr_num ||= ( - $fr[3] eq 'DBIx::Class::ResultSource::throw_exception' + $fr[3] =~ /^DBIx::Class::(?:ResultSource|Schema|Storage|Exception)::throw(?:_exception)?$/ + and + # there may be evals in the throwers themselves - skip those + ( $eval_fr_num ) = ( undef ) + and + $fr_num + ); + + # now that the above stops un-setting us, we can find the first + # ineresting eval + $eval_fr_num ||= ( + $fr[3] eq '(eval)' and $fr_num ); @@ -52,10 +67,41 @@ if( $ENV{DBICTEST_ASSERT_NO_SPURIOUS_EXCEPTION_ACTION} ) { '', ' You almost certainly used eval/try instead of dbic_internal_try()', " Adjust *one* of the eval-ish constructs in the callstack starting" . DBICTest::Util::stacktrace($throw_exception_fr_num||()) - ) unless $disarmed; + ) if ( + ! $disarmed + and + ( + $eval_fr_num + or + ! $throw_exception_fr_num + ) + ); DBIx::Class::Exception->throw( $_[0] ); - }) + }); + + my $interesting_ns_rx = qr/^ (?: main$ | DBIx::Class:: | DBICTest:: ) /x; + + # hard-set $SIG{__DIE__} to the class-wide exception_action + # with a little escape preceeding it + $SIG{__DIE__} = sub { + + # without this there would be false positives everywhere :( + die @_ if ( + # blindly rethrow if nobody is waiting for us + ( defined $^S and ! $^S ) + or + (caller(0))[0] !~ $interesting_ns_rx + or + ( + caller(0) eq 'main' + and + (caller(1))[0] !~ $interesting_ns_rx + ) + ); + + &$ea; + }; } sub capture_executed_sql_bind { @@ -204,7 +250,7 @@ sub connection { and ref($_[0]) ne 'CODE' and - ($_[0]||'') !~ /^ (?i:dbi) \: SQLite \: (?: dbname\= )? (?: \:memory\: | t [\/\\] var [\/\\] DBIxClass\-) /x + ($_[0]||'') !~ /^ (?i:dbi) \: SQLite (?: \: | \W ) .*? (?: dbname\= )? (?: \:memory\: | t [\/\\] var [\/\\] DBIxClass\-) /x ) { my $locktype; @@ -216,12 +262,18 @@ sub connection { # we need to work with a forced fresh clone so that we do not upset any state # of the main $schema (some tests examine it quite closely) local $SIG{__WARN__} = sub {}; + local $SIG{__DIE__}; local $@; # this will either give us an undef $locktype or will determine things # properly with a default ( possibly connecting in the process ) eval { - my $s = ref($self)->connect(@{$self->storage->connect_info})->storage; + my $cur_storage = $self->storage; + + $cur_storage = $cur_storage->master + if $cur_storage->isa('DBIx::Class::Storage::DBI::Replicated'); + + my $s = ref($self)->connect(@{$cur_storage->connect_info})->storage; $locktype = $s->sqlt_type || 'generic';