DBIx-QuickORM
view release on metacpan or search on metacpan
t/AI/connection_audit.t view on Meta::CPAN
use Test2::V0;
use DBI;
use File::Temp qw/tempdir/;
# Regression tests for Connection fixes: reconnect rebuilding the dialect,
# reconnect guard rails, auto_retry behavior, source(no_fatal), handle(undef),
# and row-manager validation.
BEGIN {
skip_all "DBD::SQLite is required for these tests"
unless eval { require DBD::SQLite; 1 };
}
require DBIx::QuickORM;
my $dir = tempdir(CLEANUP => 1);
my $file = "$dir/connection_audit.sqlite";
my $dsn = "dbi:SQLite:dbname=$file";
{
my $dbh = DBI->connect($dsn, '', '', {RaiseError => 1, PrintError => 0});
$dbh->do('CREATE TABLE users (user_id INTEGER PRIMARY KEY, name TEXT NOT NULL)');
$dbh->do('INSERT INTO users (user_id, name) VALUES (1, ?)', undef, 'bob');
$dbh->disconnect;
}
sub connect_orm { DBIx::QuickORM->quick(credentials => {dsn => $dsn}, @_) }
sub raw_names {
my $dbh = DBI->connect($dsn, '', '', {RaiseError => 1, PrintError => 0});
my $names = $dbh->selectcol_arrayref('SELECT name FROM users ORDER BY name');
$dbh->disconnect;
return $names;
}
subtest reconnect_rebuilds_dialect => sub {
my $con = connect_orm();
my $old_dialect = $con->dialect;
$con->reconnect;
ref_is_not($con->dialect, $old_dialect, "reconnect built a fresh dialect instance");
ref_is($con->dialect->dbh, $con->dbh, "the new dialect is bound to the new dbh");
# Transactions must actually function on the new handle.
my $ok = eval {
$con->txn(sub {
ok($con->in_txn, "in_txn true inside a post-reconnect txn");
$con->handle('users')->insert({name => 'post-reconnect-commit'});
});
1;
};
my $err = $@;
ok($ok, "post-reconnect transaction committed without error") or diag $err;
ok((grep { $_ eq 'post-reconnect-commit' } @{raw_names()}), "committed row visible to an independent connection");
my $ok2 = eval {
$con->txn(sub {
$con->handle('users')->insert({name => 'post-reconnect-rollback'});
die "force rollback\n";
});
1;
};
ok(!$ok2, "post-reconnect transaction rolled back via exception");
ok(!(grep { $_ eq 'post-reconnect-rollback' } @{raw_names()}), "rolled back row really was rolled back on the new handle");
};
subtest reconnect_guards => sub {
my $con = connect_orm();
my $txn = $con->txn();
my $err = dies { $con->reconnect };
like($err, qr/Cannot reconnect while there are active ORM-managed transactions/, "reconnect croaks with an open managed transaction");
$txn->rollback;
# Simulate a previously failed reconnect that left no dbh behind.
delete $con->{dbh};
ok(lives { $con->reconnect }, "reconnect survives a missing dbh from a prior failed reconnect");
ok($con->dbh->ping, "fresh dbh works");
};
subtest source_no_fatal => sub {
my $con = connect_orm();
ok($con->source('users'), "source() resolves a known table");
is($con->source('no_such_table', no_fatal => 1), undef, "no_fatal => 1 returns undef for an unknown table");
( run in 0.475 second using v1.01-cache-2.11-cpan-f4a522933cf )