DBD-KB
view release on metacpan or search on metacpan
t/dbdpg_test_setup.pl view on Meta::CPAN
## We may want to force an initdb call
if ((!$helpconnect and $ENV{DBDPG_TESTINITDB})
or (exists $ENV{DBDPG_INITDB} and $initdb ne $ENV{DBDPG_INITDB})) {
$debug and Test::More::diag 'Jumping to INITDB';
goto INITDB;
}
## Got a working DSN? Give it an attempt
if ($testdsn and $testuser) {
$debug and Test::More::diag "Trying with $testuser and $testdsn";
## Used by t/01connect.t
if ($arg->{dbreplace}) {
$testdsn =~ s/$alias\s*=/$arg->{dbreplace}=/;
}
if ($arg->{dbquotes}) {
$testdsn =~ s/$alias\s*=([\-\w]+)/'db="'.lc $2.'"'/e;
}
goto GOTDBH if eval {
$dbh = DBI->connect($testdsn, $testuser, $ENV{DBI_PASS},
{RaiseError => 1, PrintError => 0, AutoCommit => 1});
1;
};
$debug and Test::More::diag "Connection failed: $@";
if ($@ =~ /invalid connection option/ or $@ =~ /dbbarf/) {
return $helpconnect, $@, undef;
}
if ($arg->{nocreate}) {
return $helpconnect, '', undef;
}
## If this was created by us, try and restart it
if (16 == $helpconnect) {
## Bypass if the testdir has been removed
if (! -e $testdir) {
$arg->{nocreate} and return $helpconnect, '', undef;
warn "Test directory $testdir has been removed, will create a new one\n";
}
else {
if (-e "$testdir/data/postmaster.pid") {
## Assume it's up, and move on
}
else {
if ($arg->{norestart}) {
return $helpconnect, '', undef;
}
warn "Restarting test database $testdsn at $testdir\n";
if ($^O !~ /Win32/) {
my $sockdir = "$testdir/data/socket";
if (! -e $sockdir) {
mkdir $sockdir;
if ($uid) {
if (! chown $uid, -1, $sockdir) {
warn "chown of $sockdir failed!\n";
}
}
}
}
my $COM = qq{$pg_ctl -o '-k $testdir/data/socket' -l $testdir/dbdpg_test.logfile -D $testdir/data start};
if ($su) {
$COM = qq{su -m $su -c "$COM"};
chdir $testdir;
}
$info = '';
eval { $info = qx{$COM}; };
my $err = $@;
$su and chdir $olddir;
if ($err or $info !~ /\w/) {
$err = "Could not startup new database ($err) ($info)";
return $helpconnect, $err, undef;
}
## Wait for it to startup and verify the connection
sleep 1;
}
my $loop = 1;
STARTUP: {
eval {
$dbh = DBI->connect($testdsn, $testuser, '',
{RaiseError => 1, PrintError => 0, AutoCommit => 1});
};
if ($@ =~ /starting up/ or $@ =~ /PGSQL\.[0-9]+/) {
if ($loop++ < 20) {
sleep 1;
redo STARTUP;
}
}
}
if ($@) {
return $helpconnect, $@, $dbh;
}
## We've got a good connection, so do final tweaks and return
goto GOTDBH;
} ## end testdir exists
} ## end error and we created this database
} ## end got testdsn and testuser
## No previous info (or failed attempt), so try to connect and possible create our own cluster
$testdsn ||= $ENV{DBI_DSN};
$testuser ||= $ENV{DBI_USER};
if (! $testdsn) {
$helpconnect = 1;
$testdsn = $^O =~ /Win32/ ? 'dbi:Pg:host=localhost' : 'dbi:Pg:dbname=postgres';
}
if (! $testuser) {
$testuser = 'postgres';
}
t/dbdpg_test_setup.pl view on Meta::CPAN
else {
die "No version from initdb?! ($info)\n";
}
## Make sure pg_ctl is available as well before we go further
if (! -e $pg_ctl) {
$pg_ctl = 'pg_ctl';
}
$info = '';
eval {
$info = qx{$pg_ctl --help 2>&1};
};
last GETHANDLE if $@; ## Fail - pg_ctl bad
if (!defined $info or ($info !~ /\@(?:[a-z.-]*?postgresql\.org|enterprisedb\.com)/ and $info !~ /run as root/)) {
$@ = defined $initdb ? "Bad pg_ctl output: $info" : 'Bad pg_ctl output';
last GETHANDLE; ## Fail - pg_ctl bad
}
## initdb and pg_ctl seems to be available, let's use them to fire up a cluster
warn "Please wait, creating new database (version $version) for testing\n";
$info = '';
eval {
my $com = "$initdb --locale=C -E UTF8 -D $testdir/data";
$debug and warn" Attempting: $com\n";
$info = qx{$com 2>&1};
};
last GETHANDLE if $@; ## Fail - initdb bad
## initdb and pg_ctl cannot be run as root, so let's handle that
if ($info =~ /run as root/ or $info =~ /unprivilegierte/) {
my $founduser = 0;
$su = $testuser = '';
$testdir = exists $ENV{DBDPG_TEMPDIR} ?
File::Temp::tempdir("$ENV{DBDPG_TEMPDIR}/dbdpg_testdatabase_XXXXXX", TMPDIR => 1, CLEANUP => 0) :
File::Temp::tempdir('dbdpg_testdatabase_XXXXXX', TMPDIR => 1, CLEANUP => 0);
my $readme = "$testdir/README";
if (open $fh, '>', $readme) {
print {$fh} "This is a test directory for DBD::Pg and may be removed\n";
print {$fh} "You may want to ensure the postmaster has been stopped first.\n";
print {$fh} "Check the data/postmaster.pid file\n";
close $fh or die qq{Could not close "$readme": $!\n};
}
## Likely candidates for running this
my @userlist = (qw/postgres postgresql pgsql _postgres/);
## Start with whoever owns this file, unless it's us
my $username = getpwuid ((stat($0))[4]);
unshift @userlist, $username if defined $username and $username ne getpwent;
my %doneuser;
for (@userlist) {
$testuser = $_;
next if $doneuser{$testuser}++;
$uid = (getpwnam $testuser)[2];
next if !defined $uid;
next unless chown $uid, -1, $testdir;
next unless chown $uid, -1, $readme;
$su = $testuser;
$founduser++;
$info = '';
$olddir = getcwd;
eval {
chdir $testdir;
$info = qx{su -m $testuser -c "/bin/sh -c '$initdb --locale=C -E UTF8 -D $testdir/data 2>&1'"};
};
my $err = $@;
chdir $olddir;
last if !$err;
}
if (!$founduser) {
$@ = 'Unable to find a user to run initdb as';
last GETHANDLE; ## Fail - no user
}
if (! -e "$testdir/data") {
$@ = 'Could not create a test database via initdb';
last GETHANDLE; ## Fail - no datadir created
}
## At this point, both $su and $testuser are set
}
if ($info =~ /FATAL/) {
$@ = "initdb gave a FATAL error: $info";
last GETHANDLE; ## Fail - FATAL
}
if ($info =~ /but is not empty/) {
## Assume this is already good to go
}
elsif ($info !~ /pg_ctl/) {
$@ = "initdb did not give a pg_ctl string: $info";
last GETHANDLE; ## Fail - bad output
}
## Which user do we connect as?
if (!$su and $info =~ /owned by user "(.+?)"/) {
$testuser = $1;
}
## Attempt to boost the system oids above an int for certain testing
(my $resetxlog = $initdb) =~ s/initdb/pg_resetxlog/;
if ($version >= 10) {
$resetxlog =~ s/pg_resetxlog/pg_resetwal/;
}
eval {
if ($su) {
$info = qx{su -m "$testuser" -c "$resetxlog --help"};
}
else {
$info = qx{$resetxlog --help};
}
};
if (! $@ and $info =~ /XID/) {
if (! -e "$testdir/data/postmaster.pid") {
eval {
if ($su) {
$info = qx{ su -m "$testuser" -c "$resetxlog -o 2222333344 $testdir/data" };
}
t/dbdpg_test_setup.pl view on Meta::CPAN
open my $cfh, '<', $conf or die qq{Could not open "$conf": $!\n};
while (<$cfh>) {
if (/^\s*port\s*=\s*([0-9]+)/) {
$testport = $1;
$debug and Test::More::diag qq{Found port $testport inside conf file\n};
}
}
close $cfh or die qq{Could not close "$conf": $!\n};
## Assume it's up, and move on
}
else {
## Change to this new port and fire it up
if (! open $cfh, '>>', $conf) {
$@ = qq{Could not open "$conf": $!};
$debug and Test::More::diag qq{Failed to open "$conf"};
last GETHANDLE; ## Fail - no conf file
}
$debug and Test::More::diag qq{Writing to "$conf"};
print {$cfh} "\n\n## DBD::Pg testing parameters\n";
print {$cfh} "port=$testport\n";
print {$cfh} "max_connections=11\n";
print {$cfh} "log_statement = 'all'\n";
print {$cfh} "log_min_duration_statement = 0\n";
print {$cfh} "log_line_prefix = '%m [%p] '\n";
print {$cfh} "log_filename = 'postgres%Y-%m-%d.log'\n";
print {$cfh} "log_rotation_size = 0\n";
if (8.1 == $version) {
print {$cfh} "redirect_stderr = on\n";
}
if ($version >= 8.3) {
print {$cfh} "logging_collector = on\n";
}
if ($version >= 9.4) {
print {$cfh} "wal_level = logical\n";
print {$cfh} "max_replication_slots = 1\n";
print {$cfh} "max_wal_senders = 1\n";
open my $hba, '>>', "$testdir/data/pg_hba.conf"
or die qq{Could not open "$testdir/data/pg_hba.conf": $!\n};
print {$hba} "local\treplication\tall\ttrust\n";
print {$hba} "host\treplication\tall\t127.0.0.1/32\ttrust\n";
print {$hba} "host\treplication\tall\t::1/128\ttrust\n";
close $hba or die qq{Could not close "$testdir/data/pg_hba.conf": $!\n};
}
print {$cfh} "listen_addresses='127.0.0.1'\n" if $^O =~ /Win32/;
print {$cfh} "\n";
close $cfh or die qq{Could not close "$conf": $!\n};
## Attempt to start up the test server
$info = '';
if ($^O !~ /Win32/) {
my $sockdir = "$testdir/data/socket";
if (! -e $sockdir) {
mkdir $sockdir;
if ($su) {
if (! chown $uid, -1, $sockdir) {
warn "chown of $sockdir failed!\n";
}
}
}
}
my $COM = qq{$pg_ctl -o '-k $testdir/data/socket' -l $testdir/dbdpg_test.logfile -D $testdir/data start};
$olddir = getcwd;
if ($su) {
chdir $testdir;
$COM = qq{su -m $su -c "$COM"};
}
$debug and Test::More::diag qq{Running: $COM};
eval {
$info = qx{$COM};
};
my $err = $@;
$su and chdir $olddir;
if ($err or $info !~ /\.\.\./) {
$@ = "Could not startup new database ($COM) ($err) ($info)";
last GETHANDLE; ## Fail - startup failed
}
sleep 1;
}
## Attempt to connect to this server
$testdsn = "dbi:Pg:dbname=postgres;port=$testport";
if ($^O =~ /Win32/) {
$testdsn .= ';host=localhost';
}
else {
$testdsn .= ";host=$testdir/data/socket";
}
$debug and Test::More::diag qq{Test DSN: $testdsn};
my $loop = 1;
STARTUP: {
eval {
$dbh = DBI->connect($testdsn, $testuser, '',
{RaiseError => 1, PrintError => 0, AutoCommit => 1});
};
## Regardless of the error, try again.
## We used to check the message, but LANG problems may complicate that.
if ($@) {
$debug and Test::More::diag qq{Connection error: $@\n};
if ($@ =~ /database "postgres" does not exist/) {
## Old server, so let's create a postgres database manually
sleep 2;
(my $tempdsn = $testdsn) =~ s/postgres/template1/;
eval {
$dbh = DBI->connect($tempdsn, $testuser, '',
{RaiseError => 1, PrintError => 0, AutoCommit => 1});
};
if ($@) {
die "Could not connect: $@\n";
}
$dbh->do('CREATE DATABASE postgres');
$dbh->disconnect();
}
( run in 2.889 seconds using v1.01-cache-2.11-cpan-71847e10f99 )