Truly fix t[/pt-fifo-split/pt-fifo-split.t.

This commit is contained in:
Daniel Nichter
2013-03-02 17:02:08 -07:00
parent 882defb1cc
commit 21efb4dd7e

View File

@@ -11,7 +11,8 @@ use warnings FATAL => 'all';
use English qw(-no_match_vars); use English qw(-no_match_vars);
use Test::More; use Test::More;
use File::Temp qw(tempfile); use File::Temp qw(tempfile);
use IO::File; use Data::Dumper;
use Time::HiRes qw(sleep);
use PerconaTest; use PerconaTest;
require "$trunk/bin/pt-fifo-split"; require "$trunk/bin/pt-fifo-split";
@@ -27,24 +28,60 @@ like($output, qr/Options and values/, 'It lives');
my ($fh, $filename) = tempfile("pt-fifo-split-data.XXXXXXXXX", OPEN => 1, TMPDIR => 1, UNLINK => 1); my ($fh, $filename) = tempfile("pt-fifo-split-data.XXXXXXXXX", OPEN => 1, TMPDIR => 1, UNLINK => 1);
$fh->autoflush(1); $fh->autoflush(1);
print { $fh } "$_\n" for 1..9; print { $fh } "$_\n" for 1..9;
close $fh;
# WARNING: This can "deadlock" if not done correctly. First, for Perl open():
# "When you open a fifo, the program will block until there's something on
# the other end." So pt-fifo-split needs to mkfifo and open() it first,
# then we open it. That's ok, but the problem is: after we read everything,
# pt-fifo-split will close, rm, mkfifo, and open() it again. That can take
# a few microseconds longer than the test closing and trying to read the
# fifo again. In fact, the test can close, -p $fifo, and open() before
# pt-fifo-split has done rm (unlink). When this happens, the test holds
# open the fifo it just read, then pt-fifo-split creates a new fifo and
# open()s it and blocks because there's no program on the other end--
# because the test is reading a phantom fifo. Rather make the tool sleep
# some arbitrary time before re-open()ing the fifo, we check for a new
# file inode which ensures the fifo is new.
sub read_fifo {
my ($n_reads) = @_;
my $last_inode = 0;
my @data;
for (1..$n_reads) {
PerconaTest::wait_until(sub {
my $inode;
(undef, $inode) = stat($fifo) if -p $fifo;
if ( $inode && $inode != $last_inode ) {
$last_inode = $inode;
return 1;
}
return;
});
open my $read_fifo_fh, '<', $fifo
or die "Cannot open $fifo: $OS_ERROR";
my $data = '';
while ( <$read_fifo_fh> ) {
$data .= $_;
}
close $read_fifo_fh;
push @data, $data;
}
return \@data;
}
local $SIG{CHLD} = 'IGNORE'; local $SIG{CHLD} = 'IGNORE';
my $pid = fork(); my $pid = fork();
die "Cannot fork: $OS_ERROR" unless defined $pid; die "Cannot fork: $OS_ERROR" unless defined $pid;
if ( !$pid ) { if ( !$pid ) {
exec { $cmd } $cmd, qw(--lines 2), $filename; exec { $cmd } $cmd, qw(--lines 2), $filename;
exit 1;
} }
PerconaTest::wait_until(sub { -p $fifo }); my $data = read_fifo(5);
my @fifo;
while (kill 0, $pid) {
push @fifo, slurp_file($fifo) if -e $fifo;
}
waitpid($pid, 0); waitpid($pid, 0);
is_deeply( is_deeply(
\@fifo, $data,
[ [
"1\n2\n", "1\n2\n",
"3\n4\n", "3\n4\n",
@@ -53,53 +90,53 @@ is_deeply(
"9\n", "9\n",
], ],
"--lines=2 with 9 lines works as expected" "--lines=2 with 9 lines works as expected"
); ) or diag(Dumper($data));
$pid = fork(); $pid = fork();
die "Cannot fork: $OS_ERROR" unless defined $pid; die "Cannot fork: $OS_ERROR" unless defined $pid;
if ( !$pid ) { if ( !$pid ) {
exec { $cmd } $cmd, qw(--lines 15), $filename; exec { $cmd } $cmd, qw(--lines 15), $filename;
exit 1;
} }
PerconaTest::wait_until(sub { -p $fifo });
@fifo = (); $data = read_fifo(1);
while (kill 0, $pid) {
push @fifo, slurp_file($fifo) if -e $fifo;
}
waitpid($pid, 0); waitpid($pid, 0);
is_deeply( is_deeply(
\@fifo, $data,
[ [ "1\n2\n3\n4\n5\n6\n7\n8\n9\n" ],
"1\n2\n3\n4\n5\n6\n7\n8\n9\n",
],
"--lines=15 with 9 lines works as expected" "--lines=15 with 9 lines works as expected"
); ) or diag(Dumper($data));
close $fh or die "Cannot close $filename: $OS_ERROR";
system("($cmd --lines 10000 $trunk/bin/pt-fifo-split > /dev/null 2>&1 < /dev/null)&"); system("($cmd --lines 10000 $trunk/bin/pt-fifo-split > /dev/null 2>&1 < /dev/null)&");
PerconaTest::wait_until(sub { -p $fifo });
my $contents = slurp_file($fifo); $data = read_fifo(1);
my $contents2 = load_file('bin/pt-fifo-split'); my $contents2 = load_file('bin/pt-fifo-split');
is($contents, $contents2, 'I read the file'); is_deeply(
$data,
[ $contents2 ],
'I read the file'
);
system("($cmd $trunk/t/pt-fifo-split/samples/file_with_lines --offset 2 > /dev/null 2>&1 < /dev/null)&"); system("($cmd $trunk/t/pt-fifo-split/samples/file_with_lines --offset 2 > /dev/null 2>&1 < /dev/null)&");
PerconaTest::wait_until(sub { -p $fifo });
$contents = slurp_file($fifo); $data = read_fifo(1);
is($contents, <<EOF is_deeply(
$data,
[
<<EOF
2 hi 2 hi
3 there 3 there
4 b 4 b
5 c 5 c
6 d 6 d
EOF EOF
, 'Offset works'); ],
'Offset works'
);
# ######################################################################### # #########################################################################
# Issue 391: Add --pid option to all scripts # Issue 391: Add --pid option to all scripts