Skip to content

Commit 084bab1

Browse files
author
Maksim Milyutin
committed
Add perl tests for xlog timestamp
1 parent cf89b25 commit 084bab1

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed

src/bin/pg_xlogdump/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ install: all installdirs
3333
installdirs:
3434
$(MKDIR_P) '$(DESTDIR)$(bindir)'
3535

36+
check:
37+
$(prove_check)
38+
3639
uninstall:
3740
rm -f '$(DESTDIR)$(bindir)/pg_xlogdump$(X)'
3841

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
use strict;
2+
use warnings;
3+
4+
use PostgresNode;
5+
use TestLib;
6+
use Test::More tests => 22;
7+
8+
# Test pg_xlogdump for timestamp output.
9+
10+
sub command_output
11+
{
12+
my ($cmd, $expected_stdout, $test_name) = @_;
13+
my ($stdout, $stderr);
14+
print("# Running: " . join(" ", @{$cmd}) . "\n");
15+
my $result = IPC::Run::run $cmd, '>', \$stdout, '2>', \$stderr;
16+
ok($result, "@$cmd exit code 0");
17+
is($stderr, '', "@$cmd no stderr");
18+
return $stdout;
19+
}
20+
21+
my $node = get_new_node('main');
22+
$node->init;
23+
$node->start;
24+
my $pgdata = $node->data_dir;
25+
my $xlogfilename0 = $node->safe_psql('postgres',
26+
"SELECT pg_xlogfile_name(pg_current_xlog_location())");
27+
my $startseg = "$pgdata/pg_xlog/$xlogfilename0";
28+
my $endseg = $startseg;
29+
$node->command_like(
30+
[ 'pg_xlogdump', '-S', "$pgdata/pg_xlog/$xlogfilename0" ],
31+
qr/pg_xlogdump: start timestamp:/,
32+
'pg_xlogdump prints start timestamp');
33+
$node->command_like(
34+
[ 'pg_xlogdump', '-S', "$pgdata/pg_xlog/$xlogfilename0" ],
35+
qr/start timestamp[^\n]*\n((?!end timestamp).)*$/m,
36+
'pg_xlogdump does not print end timestamp by default');
37+
$node->command_fails(
38+
[ 'pg_xlogdump', '-E', "$pgdata/pg_xlog/$xlogfilename0" ],
39+
'pg_xlogdump requires -S argument for printing start/end timestamps');
40+
$node->command_fails(
41+
[ 'pg_xlogdump', '-S', '-F', 'XXX', "$pgdata/pg_xlog/$xlogfilename0" ],
42+
'pg_xlogdump fails with invalid filter');
43+
$node->command_like(
44+
[ 'pg_xlogdump', '-S', '-F', 'XLOG_XACT_COMMIT,XLOG_XACT_ABORT', "$pgdata/pg_xlog/$xlogfilename0" ],
45+
qr/pg_xlogdump: start timestamp:/,
46+
'pg_xlogdump accepts filter "XLOG_XACT_COMMIT,XLOG_XACT_ABORT"');
47+
48+
open CONF, ">>$pgdata/postgresql.conf";
49+
print CONF "track_commit_timestamp = on\n";
50+
close CONF;
51+
$node->restart;
52+
53+
# create test tables and move to a new segment
54+
$node->safe_psql('postgres',
55+
"CREATE TABLE test1 (a int); CREATE TABLE test2 (a int); SELECT pg_switch_xlog()");
56+
57+
# get initial commit_timestamp and logfile_name
58+
$node->safe_psql('postgres',
59+
"INSERT INTO test1 VALUES (1)");
60+
my $tx1_timestamp = $node->safe_psql('postgres',
61+
"SELECT pg_xact_commit_timestamp(xmin) FROM test1"
62+
);
63+
print("# transaction 1 commit timestamp: $tx1_timestamp\n");
64+
my $xlogfilename1 = $node->safe_psql('postgres',
65+
"SELECT pg_xlogfile_name(pg_current_xlog_location())"
66+
);
67+
68+
# produce some xlog segments
69+
for (my $i = 0; $i < 10; $i++) {
70+
$node->safe_psql('postgres',
71+
"BEGIN; INSERT INTO test2 VALUES ($i); COMMIT; SELECT pg_switch_xlog()");
72+
}
73+
74+
# get a segment from the middle of the sequence
75+
my $xlogfilenameM = $node->safe_psql('postgres',
76+
"SELECT pg_xlogfile_name(pg_current_xlog_location())");
77+
78+
# produce last segment
79+
$node->safe_psql('postgres',
80+
"SELECT pg_sleep(2); DELETE FROM test2; INSERT INTO test2 VALUES (1)");
81+
82+
# insert XLOG_XACT_ABORT to make sure that the default bahaviour is to show only COMMIT TIMESTAMP
83+
$node->safe_psql('postgres',
84+
"SELECT pg_sleep(2); BEGIN TRANSACTION; DELETE FROM test2; ROLLBACK TRANSACTION");
85+
86+
# get final logfile_name and commit_timestamp (and switch segment)
87+
my $xlogfilenameN = $node->safe_psql('postgres',
88+
"SELECT pg_xlogfile_name(pg_current_xlog_location())");
89+
$node->safe_psql('postgres',
90+
"SELECT pg_switch_xlog()");
91+
my $tx2_timestamp = $node->safe_psql('postgres',
92+
"SELECT pg_xact_commit_timestamp(xmin) FROM test2"
93+
);
94+
print("# transaction N commit timestamp: $tx2_timestamp\n");
95+
96+
# remove a file from the middle to make sure that the modified pg_xlogdump reads only necessary files
97+
unlink "$pgdata/pg_xlog/$xlogfilenameM";
98+
99+
# run pg_xlogdump to check it's output
100+
my $xld_output = command_output(
101+
[ 'pg_xlogdump', '-S', '-E', "$pgdata/pg_xlog/$xlogfilename1", "$pgdata/pg_xlog/$xlogfilenameN" ]);
102+
ok($xld_output =~ qr/pg_xlogdump: start timestamp: ([^,]+), lsn: (.*)/, "start timestamp and lsn found");
103+
my ($startts, $startlsn) = ($1, $2);
104+
ok($xld_output =~ qr/pg_xlogdump: end timestamp: ([^,]+), lsn: (.*)/, "end timestamp and lsn found");
105+
106+
# check commit timestamps for first and last commits
107+
my ($endts, $endlsn) = ($1, $2);
108+
my $timediff1 = $node->safe_psql('postgres',
109+
"SELECT EXTRACT(EPOCH FROM pg_xact_commit_timestamp(xmin) - \'$startts\'::timestamp) FROM test1");
110+
ok($timediff1 >= 0 && $timediff1 < 1, "xlog start timestamp ($startts) equals to transaction 1 timestamp ($tx1_timestamp)");
111+
my $timediff2 = $node->safe_psql('postgres',
112+
"SELECT EXTRACT(EPOCH FROM \'$endts\'::timestamp - pg_xact_commit_timestamp(xmin)) FROM test2");
113+
ok($timediff2 >= 0 && $timediff2 < 1, "xlog end timestamp ($endts) equals to transaction N timestamp ($tx2_timestamp)");
114+
115+
# check lsns
116+
my $lsndiff1 = $node->safe_psql('postgres',
117+
"SELECT \'$endlsn\'::pg_lsn - \'$startlsn\'::pg_lsn");
118+
print("lsndiff1: $lsndiff1\n");
119+
ok($lsndiff1 > 0, "xlog end lsn ($endlsn) greater than xlog start lsn ($startlsn)");
120+
my $lsndiff2 = $node->safe_psql('postgres',
121+
"SELECT pg_current_xlog_location() - \'$endlsn\'::pg_lsn");
122+
ok($lsndiff2 >= 0, "xlog current lsn greater than or equal to xlog end lsn");
123+
124+
# check search for non-existing record types
125+
$node->command_like(
126+
[ 'pg_xlogdump', '-S', '-F', 'XLOG_RESTORE_POINT', "$pgdata/pg_xlog/$xlogfilename0" ],
127+
qr/xlog record with timestamp is not found/,
128+
'pg_xlogdump accepts filter XLOG_RESTORE_POINT and processes a segment without such records');

0 commit comments

Comments
 (0)