use lib qw(t/lib);
use DBICTest::RunMode;
+use DBICTest::Util qw/populate_weakregistry assert_empty_weakregistry/;
use DBIx::Class;
use B 'svref_2object';
BEGIN {
if DBIx::Class::_ENV_::PEEPEENESS;
}
-use Scalar::Util qw/refaddr reftype weaken/;
-
# this is what holds all weakened refs to be checked for leakage
my $weak_registry = {};
# Skip the heavy-duty leak tracing when just doing an install
unless (DBICTest::RunMode->is_plain) {
- # have our own little stack maker - Carp infloops due to the bless override
- my $trace = sub {
- my $depth = 1;
- my (@stack, @frame);
-
- while (@frame = caller($depth++)) {
- push @stack, [@frame[3,1,2]];
- }
-
- $stack[0][0] = '';
- return join "\tinvoked as ", map { sprintf ("%s at %s line %d\n", @$_ ) } @stack;
- };
-
# redefine the bless override so that we can catch each and every object created
no warnings qw/redefine once/;
no strict qw/refs/;
}
);
- my $slot = (sprintf '%s=%s(0x%x)', # so we don't trigger stringification
- ref $obj,
- reftype $obj,
- refaddr $obj,
- );
-
# weaken immediately to avoid weird side effects
- $weak_registry->{$slot} = { weakref => $obj, strace => $trace->() };
- weaken $weak_registry->{$slot}{weakref};
-
- return $obj;
+ return populate_weakregistry ($weak_registry, $obj );
};
require Try::Tiny;
for my $func (qw/try catch finally/) {
my $orig = \&{"Try::Tiny::$func"};
*{"Try::Tiny::$func"} = sub (&;@) {
-
- my $slot = sprintf ('CODE(0x%x)', refaddr $_[0]);
-
- $weak_registry->{$slot} = { weakref => $_[0], strace => $trace->() };
- weaken $weak_registry->{$slot}{weakref};
-
+ populate_weakregistry( $weak_registry, $_[0] );
goto $orig;
}
}
# txn_do to invoke more codepaths
my ($mc_row_obj, $pager, $pager_explicit_count) = $schema->txn_do (sub {
- my $artist = $rs->create ({
+ my $artist = $schema->resultset('Artist')->create ({
name => 'foo artist',
cds => [{
title => 'foo cd',
return ($artist, $pg, $pg_wcount);
});
- # same for dbh_do
+ # more codepaths - error handling in txn_do
+ {
+ eval { $schema->txn_do ( sub {
+ $storage->_dbh->begin_work;
+ fail ('how did we get so far?!');
+ } ) };
+
+ eval { $schema->txn_do ( sub {
+ $schema->txn_do ( sub {
+ die "It's called EXCEPTION";
+ fail ('how did we get so far?!');
+ } );
+ fail ('how did we get so far?!');
+ } ) };
+ like( $@, qr/It\'s called EXCEPTION/, 'Exception correctly propagated in nested txn_do' );
+ }
+
+ # dbh_do codepath
my ($rs_bind_circref, $cond_rowobj) = $schema->storage->dbh_do ( sub {
my $row = $_[0]->schema->resultset('Artist')->new({});
my $rs = $_[0]->schema->resultset('Artist')->search({
}
}
- for (keys %$base_collection) {
- $weak_registry->{"basic $_"} = { weakref => $base_collection->{$_} };
- weaken $weak_registry->{"basic $_"}{weakref};
- }
+ populate_weakregistry ($weak_registry, $base_collection->{$_}, "basic $_")
+ for keys %$base_collection;
}
# check that "phantom-chaining" works - we never lose track of the original $schema
{
my $phantom;
for (
- sub { DBICTest->init_schema },
+ sub { DBICTest->init_schema( sqlite_use_file => 0 ) },
sub { shift->source('Artist') },
sub { shift->resultset },
sub { shift->result_source },
sub { shift->delete },
sub { shift->insert },
) {
- $phantom = $_->($phantom);
-
- my $slot = (sprintf 'phantom %s=%s(0x%x)', # so we don't trigger stringification
- ref $phantom,
- reftype $phantom,
- refaddr $phantom,
- );
-
- $weak_registry->{$slot} = $phantom;
- weaken $weak_registry->{$slot};
+ $phantom = populate_weakregistry ( $weak_registry, scalar $_->($phantom) );
}
ok( $phantom->in_storage, 'Properly deleted/reinserted' );
# T::B 2.0 has result objects and other fancyness
delete $weak_registry->{$slot};
}
+ elsif ($slot =~ /^Method::Generate::(?:Accessor|Constructor)/) {
+ # Moo keeps globals around, this is normal
+ delete $weak_registry->{$slot};
+ }
elsif ($slot =~ /^SQL::Translator/) {
# SQLT is a piece of shit, leaks all over
delete $weak_registry->{$slot};
or $r->result_source(undef);
}
-for my $slot (sort keys %$weak_registry) {
-
- ok (! defined $weak_registry->{$slot}{weakref}, "No leaks of $slot") or do {
- my $diag = '';
-
- $diag .= Devel::FindRef::track ($weak_registry->{$slot}{weakref}, 20) . "\n"
- if ( $ENV{TEST_VERBOSE} && eval { require Devel::FindRef });
-
- if (my $stack = $weak_registry->{$slot}{strace}) {
- $diag .= " Reference first seen$stack";
- }
-
- diag $diag if $diag;
- };
-}
+assert_empty_weakregistry ($weak_registry);
# we got so far without a failure - this is a good thing
# now let's try to rerun this script under a "persistent" environment