Fix portability issues in new amcheck test.
The tests added by commit 866e24d47 failed on big-endian machines due to lack of attention to endianness considerations. Fix that. While here, improve a few small cosmetic things, such as running it through perltidy. Mark Dilger Discussion: https://postgr.es/m/30B8E99A-2D9C-48D4-A55C-741C9D5F1563@enterprisedb.com
This commit is contained in:
parent
87a174c0e7
commit
860593ec3b
@ -4,7 +4,7 @@ use warnings;
|
|||||||
use PostgresNode;
|
use PostgresNode;
|
||||||
use TestLib;
|
use TestLib;
|
||||||
|
|
||||||
use Test::More tests => 65;
|
use Test::More tests => 55;
|
||||||
|
|
||||||
my ($node, $result);
|
my ($node, $result);
|
||||||
|
|
||||||
@ -28,19 +28,17 @@ check_all_options_uncorrupted('test', 'plain');
|
|||||||
#
|
#
|
||||||
fresh_test_table('test');
|
fresh_test_table('test');
|
||||||
corrupt_first_page('test');
|
corrupt_first_page('test');
|
||||||
detects_corruption(
|
detects_heap_corruption("verify_heapam('test')", "plain corrupted table");
|
||||||
"verify_heapam('test')",
|
detects_heap_corruption(
|
||||||
"plain corrupted table");
|
|
||||||
detects_corruption(
|
|
||||||
"verify_heapam('test', skip := 'all-visible')",
|
"verify_heapam('test', skip := 'all-visible')",
|
||||||
"plain corrupted table skipping all-visible");
|
"plain corrupted table skipping all-visible");
|
||||||
detects_corruption(
|
detects_heap_corruption(
|
||||||
"verify_heapam('test', skip := 'all-frozen')",
|
"verify_heapam('test', skip := 'all-frozen')",
|
||||||
"plain corrupted table skipping all-frozen");
|
"plain corrupted table skipping all-frozen");
|
||||||
detects_corruption(
|
detects_heap_corruption(
|
||||||
"verify_heapam('test', check_toast := false)",
|
"verify_heapam('test', check_toast := false)",
|
||||||
"plain corrupted table skipping toast");
|
"plain corrupted table skipping toast");
|
||||||
detects_corruption(
|
detects_heap_corruption(
|
||||||
"verify_heapam('test', startblock := 0, endblock := 0)",
|
"verify_heapam('test', startblock := 0, endblock := 0)",
|
||||||
"plain corrupted table checking only block zero");
|
"plain corrupted table checking only block zero");
|
||||||
|
|
||||||
@ -50,71 +48,12 @@ detects_corruption(
|
|||||||
fresh_test_table('test');
|
fresh_test_table('test');
|
||||||
$node->safe_psql('postgres', q(VACUUM FREEZE test));
|
$node->safe_psql('postgres', q(VACUUM FREEZE test));
|
||||||
corrupt_first_page('test');
|
corrupt_first_page('test');
|
||||||
detects_corruption(
|
detects_heap_corruption("verify_heapam('test')",
|
||||||
"verify_heapam('test')",
|
|
||||||
"all-frozen corrupted table");
|
"all-frozen corrupted table");
|
||||||
detects_no_corruption(
|
detects_no_corruption(
|
||||||
"verify_heapam('test', skip := 'all-frozen')",
|
"verify_heapam('test', skip := 'all-frozen')",
|
||||||
"all-frozen corrupted table skipping all-frozen");
|
"all-frozen corrupted table skipping all-frozen");
|
||||||
|
|
||||||
#
|
|
||||||
# Check a corrupt table with corrupt page header
|
|
||||||
#
|
|
||||||
fresh_test_table('test');
|
|
||||||
corrupt_first_page_and_header('test');
|
|
||||||
detects_corruption(
|
|
||||||
"verify_heapam('test')",
|
|
||||||
"corrupted test table with bad page header");
|
|
||||||
|
|
||||||
#
|
|
||||||
# Check an uncorrupted table with corrupt toast page header
|
|
||||||
#
|
|
||||||
fresh_test_table('test');
|
|
||||||
my $toast = get_toast_for('test');
|
|
||||||
corrupt_first_page_and_header($toast);
|
|
||||||
detects_corruption(
|
|
||||||
"verify_heapam('test', check_toast := true)",
|
|
||||||
"table with corrupted toast page header checking toast");
|
|
||||||
detects_no_corruption(
|
|
||||||
"verify_heapam('test', check_toast := false)",
|
|
||||||
"table with corrupted toast page header skipping toast");
|
|
||||||
detects_corruption(
|
|
||||||
"verify_heapam('$toast')",
|
|
||||||
"corrupted toast page header");
|
|
||||||
|
|
||||||
#
|
|
||||||
# Check an uncorrupted table with corrupt toast
|
|
||||||
#
|
|
||||||
fresh_test_table('test');
|
|
||||||
$toast = get_toast_for('test');
|
|
||||||
corrupt_first_page($toast);
|
|
||||||
detects_corruption(
|
|
||||||
"verify_heapam('test', check_toast := true)",
|
|
||||||
"table with corrupted toast checking toast");
|
|
||||||
detects_no_corruption(
|
|
||||||
"verify_heapam('test', check_toast := false)",
|
|
||||||
"table with corrupted toast skipping toast");
|
|
||||||
detects_corruption(
|
|
||||||
"verify_heapam('$toast')",
|
|
||||||
"corrupted toast table");
|
|
||||||
|
|
||||||
#
|
|
||||||
# Check an uncorrupted all-frozen table with corrupt toast
|
|
||||||
#
|
|
||||||
fresh_test_table('test');
|
|
||||||
$node->safe_psql('postgres', q(VACUUM FREEZE test));
|
|
||||||
$toast = get_toast_for('test');
|
|
||||||
corrupt_first_page($toast);
|
|
||||||
detects_corruption(
|
|
||||||
"verify_heapam('test', check_toast := true)",
|
|
||||||
"all-frozen table with corrupted toast checking toast");
|
|
||||||
detects_no_corruption(
|
|
||||||
"verify_heapam('test', check_toast := false)",
|
|
||||||
"all-frozen table with corrupted toast skipping toast");
|
|
||||||
detects_corruption(
|
|
||||||
"verify_heapam('$toast')",
|
|
||||||
"corrupted toast table of all-frozen table");
|
|
||||||
|
|
||||||
# Returns the filesystem path for the named relation.
|
# Returns the filesystem path for the named relation.
|
||||||
sub relation_filepath
|
sub relation_filepath
|
||||||
{
|
{
|
||||||
@ -131,7 +70,9 @@ sub relation_filepath
|
|||||||
sub get_toast_for
|
sub get_toast_for
|
||||||
{
|
{
|
||||||
my ($relname) = @_;
|
my ($relname) = @_;
|
||||||
$node->safe_psql('postgres', qq(
|
|
||||||
|
return $node->safe_psql(
|
||||||
|
'postgres', qq(
|
||||||
SELECT 'pg_toast.' || t.relname
|
SELECT 'pg_toast.' || t.relname
|
||||||
FROM pg_catalog.pg_class c, pg_catalog.pg_class t
|
FROM pg_catalog.pg_class c, pg_catalog.pg_class t
|
||||||
WHERE c.relname = '$relname'
|
WHERE c.relname = '$relname'
|
||||||
@ -142,7 +83,9 @@ sub get_toast_for
|
|||||||
sub fresh_test_table
|
sub fresh_test_table
|
||||||
{
|
{
|
||||||
my ($relname) = @_;
|
my ($relname) = @_;
|
||||||
$node->safe_psql('postgres', qq(
|
|
||||||
|
return $node->safe_psql(
|
||||||
|
'postgres', qq(
|
||||||
DROP TABLE IF EXISTS $relname CASCADE;
|
DROP TABLE IF EXISTS $relname CASCADE;
|
||||||
CREATE TABLE $relname (a integer, b text);
|
CREATE TABLE $relname (a integer, b text);
|
||||||
ALTER TABLE $relname SET (autovacuum_enabled=false);
|
ALTER TABLE $relname SET (autovacuum_enabled=false);
|
||||||
@ -154,55 +97,54 @@ sub fresh_test_table
|
|||||||
|
|
||||||
# Stops the test node, corrupts the first page of the named relation, and
|
# Stops the test node, corrupts the first page of the named relation, and
|
||||||
# restarts the node.
|
# restarts the node.
|
||||||
sub corrupt_first_page_internal
|
sub corrupt_first_page
|
||||||
{
|
{
|
||||||
my ($relname, $corrupt_header) = @_;
|
my ($relname) = @_;
|
||||||
my $relpath = relation_filepath($relname);
|
my $relpath = relation_filepath($relname);
|
||||||
|
|
||||||
$node->stop;
|
$node->stop;
|
||||||
|
|
||||||
my $fh;
|
my $fh;
|
||||||
open($fh, '+<', $relpath);
|
open($fh, '+<', $relpath)
|
||||||
|
or BAIL_OUT("open failed: $!");
|
||||||
binmode $fh;
|
binmode $fh;
|
||||||
|
|
||||||
# If we corrupt the header, postgres won't allow the page into the buffer.
|
# Corrupt two line pointers. To be stable across platforms, we use
|
||||||
syswrite($fh, '\xFF\xFF\xFF\xFF', 8) if ($corrupt_header);
|
# 0x55555555 and 0xAAAAAAAA for the two, which are bitwise reverses of each
|
||||||
|
# other.
|
||||||
|
seek($fh, 32, 0)
|
||||||
|
or BAIL_OUT("seek failed: $!");
|
||||||
|
syswrite($fh, pack("L*", 0x55555555, 0xAAAAAAAA))
|
||||||
|
or BAIL_OUT("syswrite failed: $!");
|
||||||
|
close($fh)
|
||||||
|
or BAIL_OUT("close failed: $!");
|
||||||
|
|
||||||
# Corrupt at least the line pointers. Exactly what this corrupts will
|
|
||||||
# depend on the page, as it may run past the line pointers into the user
|
|
||||||
# data. We stop short of writing 2048 bytes (2k), the smallest supported
|
|
||||||
# page size, as we don't want to corrupt the next page.
|
|
||||||
seek($fh, 32, 0);
|
|
||||||
syswrite($fh, '\x77\x77\x77\x77', 500);
|
|
||||||
close($fh);
|
|
||||||
$node->start;
|
$node->start;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub corrupt_first_page
|
sub detects_heap_corruption
|
||||||
{
|
{
|
||||||
corrupt_first_page_internal($_[0], undef);
|
my ($function, $testname) = @_;
|
||||||
}
|
|
||||||
|
|
||||||
sub corrupt_first_page_and_header
|
detects_corruption($function, $testname,
|
||||||
{
|
qr/line pointer redirection to item at offset \d+ exceeds maximum offset \d+/
|
||||||
corrupt_first_page_internal($_[0], 1);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub detects_corruption
|
sub detects_corruption
|
||||||
{
|
{
|
||||||
my ($function, $testname) = @_;
|
my ($function, $testname, $re) = @_;
|
||||||
|
|
||||||
my $result = $node->safe_psql('postgres',
|
my $result = $node->safe_psql('postgres', qq(SELECT * FROM $function));
|
||||||
qq(SELECT COUNT(*) > 0 FROM $function));
|
like($result, $re, $testname);
|
||||||
is($result, 't', $testname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub detects_no_corruption
|
sub detects_no_corruption
|
||||||
{
|
{
|
||||||
my ($function, $testname) = @_;
|
my ($function, $testname) = @_;
|
||||||
|
|
||||||
my $result = $node->safe_psql('postgres',
|
my $result = $node->safe_psql('postgres', qq(SELECT * FROM $function));
|
||||||
qq(SELECT COUNT(*) = 0 FROM $function));
|
is($result, '', $testname);
|
||||||
is($result, 't', $testname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# Check various options are stable (don't abort) and do not report corruption
|
# Check various options are stable (don't abort) and do not report corruption
|
||||||
@ -215,6 +157,7 @@ sub detects_no_corruption
|
|||||||
sub check_all_options_uncorrupted
|
sub check_all_options_uncorrupted
|
||||||
{
|
{
|
||||||
my ($relname, $prefix) = @_;
|
my ($relname, $prefix) = @_;
|
||||||
|
|
||||||
for my $stop (qw(true false))
|
for my $stop (qw(true false))
|
||||||
{
|
{
|
||||||
for my $check_toast (qw(true false))
|
for my $check_toast (qw(true false))
|
||||||
@ -225,11 +168,12 @@ sub check_all_options_uncorrupted
|
|||||||
{
|
{
|
||||||
for my $endblock (qw(NULL 0))
|
for my $endblock (qw(NULL 0))
|
||||||
{
|
{
|
||||||
my $opts = "on_error_stop := $stop, " .
|
my $opts =
|
||||||
"check_toast := $check_toast, " .
|
"on_error_stop := $stop, "
|
||||||
"skip := $skip, " .
|
. "check_toast := $check_toast, "
|
||||||
"startblock := $startblock, " .
|
. "skip := $skip, "
|
||||||
"endblock := $endblock";
|
. "startblock := $startblock, "
|
||||||
|
. "endblock := $endblock";
|
||||||
|
|
||||||
detects_no_corruption(
|
detects_no_corruption(
|
||||||
"verify_heapam('$relname', $opts)",
|
"verify_heapam('$relname', $opts)",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user