1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-03 00:26:59 +02:00
Files
pgbackrest/test/src/module/command/backupCommonTest.c

316 lines
15 KiB
C
Raw Normal View History

/***********************************************************************************************************************************
Test Common Functions and Definitions for Backup and Expire Commands
***********************************************************************************************************************************/
#include "common/io/bufferWrite.h"
#include "common/regExp.h"
#include "common/type/json.h"
#include "postgres/interface.h"
#include "postgres/interface/static.vendor.h"
#include "storage/posix/storage.h"
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
void
testRun(void)
{
FUNCTION_HARNESS_VOID();
// *****************************************************************************************************************************
if (testBegin("backupRegExp()"))
{
const String *full = STRDEF("20181119-152138F");
const String *incr = STRDEF("20181119-152138F_20181119-152152I");
const String *diff = STRDEF("20181119-152138F_20181119-152152D");
// -------------------------------------------------------------------------------------------------------------------------
TEST_ERROR(
backupRegExpP(0),
AssertError, "assertion 'param.full || param.differential || param.incremental' failed");
// -------------------------------------------------------------------------------------------------------------------------
2019-12-19 16:25:46 -05:00
String *filter = backupRegExpP(.full = true);
TEST_RESULT_STR_Z(filter, "^[0-9]{8}\\-[0-9]{6}F$", "full backup regex with anchors");
TEST_RESULT_BOOL(regExpMatchOne(filter, incr), false, " does not exactly match incr");
TEST_RESULT_BOOL(regExpMatchOne(filter, diff), false, " does not exactly match diff");
TEST_RESULT_BOOL(regExpMatchOne(filter, full), true, " exactly matches full");
// -------------------------------------------------------------------------------------------------------------------------
filter = backupRegExpP(.full = true, .incremental = true);
2019-05-16 09:56:48 -04:00
TEST_RESULT_STR_Z(
filter, "^[0-9]{8}\\-[0-9]{6}F(\\_[0-9]{8}\\-[0-9]{6}I){0,1}$", "full and optional incr backup regex with anchors");
TEST_RESULT_BOOL(regExpMatchOne(filter, incr), true, " match incr");
TEST_RESULT_BOOL(regExpMatchOne(filter, diff), false, " does not match diff");
TEST_RESULT_BOOL(regExpMatchOne(filter, full), true, " match full");
TEST_RESULT_BOOL(
regExpMatchOne(
filter, STRDEF("12341234-123123F_12341234-123123IG")), false, " does not match with trailing character");
TEST_RESULT_BOOL(
regExpMatchOne(
filter, STRDEF("A12341234-123123F_12341234-123123I")), false, " does not match with leading character");
// -------------------------------------------------------------------------------------------------------------------------
filter = backupRegExpP(.full = true, .differential = true);
2019-05-16 09:56:48 -04:00
TEST_RESULT_STR_Z(
filter, "^[0-9]{8}\\-[0-9]{6}F(\\_[0-9]{8}\\-[0-9]{6}D){0,1}$", "full and optional diff backup regex with anchors");
TEST_RESULT_BOOL(regExpMatchOne(filter, incr), false, " does not match incr");
TEST_RESULT_BOOL(regExpMatchOne(filter, diff), true, " match diff");
TEST_RESULT_BOOL(regExpMatchOne(filter, full), true, " match full");
// -------------------------------------------------------------------------------------------------------------------------
filter = backupRegExpP(.full = true, .incremental = true, .differential = true);
2019-05-16 09:56:48 -04:00
TEST_RESULT_STR_Z(
filter, "^[0-9]{8}\\-[0-9]{6}F(\\_[0-9]{8}\\-[0-9]{6}(D|I)){0,1}$",
"full, optional diff and incr backup regex with anchors");
TEST_RESULT_BOOL(regExpMatchOne(filter, incr), true, " match incr");
TEST_RESULT_BOOL(regExpMatchOne(filter, diff), true, " match diff");
TEST_RESULT_BOOL(regExpMatchOne(filter, full), true, " match full");
// -------------------------------------------------------------------------------------------------------------------------
filter = backupRegExpP(.incremental = true, .differential = true, .noAnchorEnd = true);
2019-05-16 09:56:48 -04:00
TEST_RESULT_STR_Z(filter, "^[0-9]{8}\\-[0-9]{6}F\\_[0-9]{8}\\-[0-9]{6}(D|I)", "diff and incr backup regex with anchors");
TEST_RESULT_BOOL(regExpMatchOne(filter, incr), true, " match incr");
TEST_RESULT_BOOL(regExpMatchOne(filter, diff), true, " match diff");
TEST_RESULT_BOOL(regExpMatchOne(filter, full), false, " does not match full");
TEST_RESULT_BOOL(
regExpMatchOne(
filter, STRDEF("A12341234-123123F_12341234-123123I")), false, " does not match with leading character");
// -------------------------------------------------------------------------------------------------------------------------
filter = backupRegExpP(.incremental = true);
2019-05-16 09:56:48 -04:00
TEST_RESULT_STR_Z(filter, "^[0-9]{8}\\-[0-9]{6}F\\_[0-9]{8}\\-[0-9]{6}I$", "incr backup regex with anchors");
TEST_RESULT_BOOL(regExpMatchOne(filter, incr), true, " match incr");
TEST_RESULT_BOOL(regExpMatchOne(filter, diff), false, " does not match diff");
TEST_RESULT_BOOL(regExpMatchOne(filter, full), false, " does not match full");
// -------------------------------------------------------------------------------------------------------------------------
filter = backupRegExpP(.differential = true);
2019-05-16 09:56:48 -04:00
TEST_RESULT_STR_Z(filter, "^[0-9]{8}\\-[0-9]{6}F\\_[0-9]{8}\\-[0-9]{6}D$", "diff backup regex with anchors");
TEST_RESULT_BOOL(regExpMatchOne(filter, incr), false, " does not match incr");
TEST_RESULT_BOOL(regExpMatchOne(filter, diff), true, " match diff");
TEST_RESULT_BOOL(regExpMatchOne(filter, full), false, " does not match full");
}
// *****************************************************************************************************************************
if (testBegin("PageChecksum"))
{
TEST_RESULT_UINT(PG_SEGMENT_PAGE_DEFAULT, 131072, "check pages per segment");
// Test pages with all zeros (these are considered valid)
// -------------------------------------------------------------------------------------------------------------------------
Buffer *buffer = bufNew(PG_PAGE_SIZE_DEFAULT * 3);
Buffer *bufferOut = bufNew(0);
bufUsedSet(buffer, bufSize(buffer));
memset(bufPtr(buffer), 0, bufSize(buffer));
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0};
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x01)) = (PageHeaderData){.pd_upper = 0};
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x02)) = (PageHeaderData){.pd_upper = 0};
IoWrite *write = ioBufferWriteNew(bufferOut);
ioFilterGroupAdd(ioWriteFilterGroup(write), pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, 0));
ioWriteOpen(write);
ioWrite(write, buffer);
ioWriteClose(write);
TEST_RESULT_STR_Z(
jsonFromVar(ioFilterGroupResult(ioWriteFilterGroup(write), PAGE_CHECKSUM_FILTER_TYPE_STR)),
"{\"align\":true,\"valid\":true}", "all zero pages");
// Single valid page
// -------------------------------------------------------------------------------------------------------------------------
buffer = bufNew(PG_PAGE_SIZE_DEFAULT * 1);
bufUsedSet(buffer, bufSize(buffer));
memset(bufPtr(buffer), 0, bufSize(buffer));
// Page 0 has good checksum
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageXLogRecPtr)
{
.xlogid = 0xF0F0F0F0,
.xrecoff = 0xF0F0F0F0,
},
};
((PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)))->pd_checksum = pgPageChecksum(
bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00), 0);
write = ioBufferWriteNew(bufferOut);
ioFilterGroupAdd(
ioWriteFilterGroup(write),
pageChecksumNewVar(varVarLst(jsonToVar(
strNewFmt("[0,%u,%" PRIu64 "]", PG_SEGMENT_PAGE_DEFAULT, (uint64_t)0xFACEFACE00000000)))));
ioWriteOpen(write);
ioWrite(write, buffer);
ioWriteClose(write);
TEST_RESULT_STR_Z(
jsonFromVar(ioFilterGroupResult(ioWriteFilterGroup(write), PAGE_CHECKSUM_FILTER_TYPE_STR)),
"{\"align\":true,\"valid\":true}", "single valid page");
// Single checksum error
// -------------------------------------------------------------------------------------------------------------------------
buffer = bufNew(PG_PAGE_SIZE_DEFAULT * 1);
bufUsedSet(buffer, bufSize(buffer));
memset(bufPtr(buffer), 0, bufSize(buffer));
// Page 0 has bogus checksum
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageXLogRecPtr)
{
.xlogid = 0xF0F0F0F0,
.xrecoff = 0xF0F0F0F0,
},
};
write = ioBufferWriteNew(bufferOut);
ioFilterGroupAdd(
ioWriteFilterGroup(write),
pageChecksumNewVar(varVarLst(jsonToVar(
strNewFmt("[0,%u,%" PRIu64 "]", PG_SEGMENT_PAGE_DEFAULT, (uint64_t)0xFACEFACE00000000)))));
ioWriteOpen(write);
ioWrite(write, buffer);
ioWriteClose(write);
TEST_RESULT_STR_Z(
jsonFromVar(ioFilterGroupResult(ioWriteFilterGroup(write), PAGE_CHECKSUM_FILTER_TYPE_STR)),
"{\"align\":true,\"error\":[0],\"valid\":false}", "single checksum error");
// Various checksum errors some of which will be skipped because of the LSN
// -------------------------------------------------------------------------------------------------------------------------
buffer = bufNew(PG_PAGE_SIZE_DEFAULT * 8 - (PG_PAGE_SIZE_DEFAULT - 512));
bufUsedSet(buffer, bufSize(buffer));
memset(bufPtr(buffer), 0, bufSize(buffer));
// Page 0 has bogus checksum
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageXLogRecPtr)
{
.xlogid = 0xF0F0F0F0,
.xrecoff = 0xF0F0F0F0,
},
};
// Page 1 has bogus checksum but lsn above the limit
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x01)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageXLogRecPtr)
{
.xlogid = 0xFACEFACE,
.xrecoff = 0x00000000,
},
};
// Page 2 has bogus checksum
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x02)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageXLogRecPtr)
{
.xrecoff = 0x2,
},
};
// Page 3 has bogus checksum
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x03)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageXLogRecPtr)
{
.xrecoff = 0x3,
},
};
// Page 4 has bogus checksum
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x04)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageXLogRecPtr)
{
.xrecoff = 0x4,
},
};
// Page 5 is zero
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x05)) = (PageHeaderData){.pd_upper = 0x00};
// Page 6 has bogus checksum
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x06)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageXLogRecPtr)
{
.xrecoff = 0x6,
},
};
// Page 7 has bogus checksum (and is misaligned but large enough to test)
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x07)) = (PageHeaderData)
{
.pd_upper = 0x01,
.pd_lsn = (PageXLogRecPtr)
{
.xrecoff = 0x7,
},
};
write = ioBufferWriteNew(bufferOut);
ioFilterGroupAdd(ioWriteFilterGroup(write), pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, 0xFACEFACE00000000));
ioWriteOpen(write);
ioWrite(write, buffer);
ioWriteClose(write);
TEST_RESULT_STR_Z(
jsonFromVar(ioFilterGroupResult(ioWriteFilterGroup(write), PAGE_CHECKSUM_FILTER_TYPE_STR)),
"{\"align\":false,\"error\":[0,[2,4],[6,7]],\"valid\":false}", "various checksum errors");
// Impossibly misaligned page
// -------------------------------------------------------------------------------------------------------------------------
buffer = bufNew(256);
bufUsedSet(buffer, bufSize(buffer));
memset(bufPtr(buffer), 0, bufSize(buffer));
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0};
write = ioBufferWriteNew(bufferOut);
ioFilterGroupAdd(ioWriteFilterGroup(write), pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, 0xFACEFACE00000000));
ioWriteOpen(write);
ioWrite(write, buffer);
ioWriteClose(write);
TEST_RESULT_STR_Z(
jsonFromVar(ioFilterGroupResult(ioWriteFilterGroup(write), PAGE_CHECKSUM_FILTER_TYPE_STR)),
"{\"align\":false,\"valid\":false}", "misalignment");
// Two misaligned buffers in a row
// -------------------------------------------------------------------------------------------------------------------------
buffer = bufNew(513);
bufUsedSet(buffer, bufSize(buffer));
memset(bufPtr(buffer), 0, bufSize(buffer));
*(PageHeaderData *)(bufPtr(buffer) + (PG_PAGE_SIZE_DEFAULT * 0x00)) = (PageHeaderData){.pd_upper = 0};
write = ioBufferWriteNew(bufferOut);
ioFilterGroupAdd(ioWriteFilterGroup(write), pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, 0xFACEFACE00000000));
ioWriteOpen(write);
ioWrite(write, buffer);
TEST_ERROR(ioWrite(write, buffer), AssertError, "should not be possible to see two misaligned pages in a row");
}
FUNCTION_HARNESS_RETURN_VOID();
}