1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
|
# vim: ft=perl
use Test::More;
use strict;
use warnings;
use FindBin qw($Bin);
if ( $Bin =~ /(.*)/ ) {
$Bin = $1;
}
## Test that failover happens when a server is unavailable.
use DBI;
use DBD::SQLite;
use DBD::Multi;
use Data::Dumper;
use Sys::SigAction qw( timeout_call );
use Test::TCP ();
eval { require DBD::Pg; };
if ( $@ ) { plan skip_all => 'DBD::Pg unavailable'; exit; }
# Start a TCP server that will provide timing-out Pg server
my $host = '127.0.0.1';
my $server = Test::TCP->new(
listen => 1,
host => $host,
code => sub { while (1) { sleep 10; } }
);
if (!$server) { plan skip_all => 'Could not start a TCP server'; exit; }
plan tests => 7;
pass 'DBD::Pg is installed';
my @PG_CONNECT = ('dbi:Pg:dbname=fake;host=' . $host . ';port=' . $server->port,
'fakeuser','fakepass') ;
my $SQ_TABLE = "$Bin/one.db";
cleanup();
my @SQ_CONNECT = ("dbi:SQLite:$SQ_TABLE");
unlink( $SQ_TABLE );
# Set up the first DB with a value of 1
my $dbh_1 = DBI->connect( @SQ_CONNECT );
is $dbh_1->do("CREATE TABLE multi(id int)"), '0E0', 'do create successful';
is($dbh_1->do("INSERT INTO multi VALUES(1)"), 1, 'insert via do works');
## Verify a normal connect attempt to the non-existant pg server fails:
ok(
timeout_call(
5,
sub {
my $ctest = DBI->connect(@PG_CONNECT);
}
),
'Direct connection timed out' );
my $c = DBI->connect('DBI:Multi:', undef, undef, {
dsns => [
1 => \@PG_CONNECT,
50 => \@SQ_CONNECT,
],
});
ok( !timeout_call( 0, sub{ sleep 2 } ), "Timeout 0 should never time out" );
diag "Pausing up to 10 seconds to test timeout...";
my $val;
ok(
# Note: Since DBD::Multi is using timeout_call, and since you can't nest
#calls to timeout_call, the timeout period here is really irrelevant as long
#as Multi is doing what it should. What's important is that a value is
#eventually returned. The only reason timeout_call is used at all is in
#case Multi turns out to be broken.
!timeout_call( 10,
sub { $val = $c->selectrow_array("SELECT id FROM multi") }
),
"Value should have been returned" );
is($val, 1, "Query failed over to the second DB");
cleanup();
$server->stop();
sub cleanup {
-e $SQ_TABLE and unlink( $SQ_TABLE );
}
|