1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-05 00:28:52 +02:00
Files
pgbackrest/test/src/module/command/verifyTest.c
David Steele 8c062e1af8 Remove primary flag from manifest.
This flag was only being used by the backup command after manifestNewBuild() and had no other uses. There was a time when it was important for integration testing but the unit tests now fulfill this role.

Since backup is the only code concerned with the primary flag, move the code into the backup module.

We don't have any cross-version testing but this change was tested manually with the most recent version of pgBackRest to make sure it was tolerant of the missing primary info. When an older version of pgBackRest loads a newer manifest the primary flag will always be set to false, which is fine since it is not used.
2022-01-20 14:01:10 -05:00

1443 lines
92 KiB
C

/***********************************************************************************************************************************
Test Stanza Commands
***********************************************************************************************************************************/
#include "common/io/bufferRead.h"
#include "postgres/interface.h"
#include "postgres/version.h"
#include "storage/posix/storage.h"
#include "common/harnessConfig.h"
#include "common/harnessInfo.h"
#include "common/harnessPostgres.h"
#include "common/harnessPq.h"
#include "common/harnessProtocol.h"
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
static void
testRun(void)
{
FUNCTION_HARNESS_VOID();
// Install local command handler shim
static const ProtocolServerHandler testLocalHandlerList[] = {PROTOCOL_SERVER_HANDLER_VERIFY_LIST};
hrnProtocolLocalShimInstall(testLocalHandlerList, PROTOCOL_SERVER_HANDLER_LIST_SIZE(testLocalHandlerList));
StringList *argListBase = strLstNew();
hrnCfgArgRawZ(argListBase, cfgOptStanza, "db");
hrnCfgArgRawZ(argListBase, cfgOptRepoPath, TEST_PATH "/repo");
const char *fileContents = "acefile";
uint64_t fileSize = 7;
const String *fileChecksum = STRDEF("d1cd8a7d11daa26814b93eb604e1d49ab4b43770");
#define TEST_BACKUP_DB1_94 \
"db-catalog-version=201409291\n" \
"db-control-version=942\n" \
"db-id=1\n" \
"db-system-id=" HRN_PG_SYSTEMID_94_Z "\n" \
"db-version=\"9.4\"\n"
#define TEST_BACKUP_DB2_11 \
"db-catalog-version=201707211\n" \
"db-control-version=1100\n" \
"db-id=2\n" \
"db-system-id=" HRN_PG_SYSTEMID_11_Z "\n" \
"db-version=\"11\"\n"
#define TEST_BACKUP_DB1_CURRENT_FULL1 \
"20181119-152138F={" \
"\"backrest-format\":5,\"backrest-version\":\"2.28dev\"," \
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000002\"," \
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186," \
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900," \
"\"backup-timestamp-start\":1482182846,\"backup-timestamp-stop\":1482182861,\"backup-type\":\"full\"," \
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false," \
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
#define TEST_BACKUP_DB1_CURRENT_FULL2 \
"20181119-152800F={" \
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\"," \
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186," \
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900," \
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\"," \
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false," \
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
#define TEST_BACKUP_DB1_CURRENT_FULL3 \
"20181119-152900F={" \
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\"," \
"\"backup-archive-start\":\"000000010000000000000004\",\"backup-archive-stop\":\"000000010000000000000004\"," \
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186," \
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900," \
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\"," \
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false," \
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
#define TEST_BACKUP_DB1_HISTORY \
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":" HRN_PG_SYSTEMID_94_Z "," \
"\"db-version\":\"9.4\"}"
#define TEST_BACKUP_DB2_HISTORY \
"2={\"db-catalog-version\":201707211,\"db-control-version\":1100,\"db-system-id\":" HRN_PG_SYSTEMID_11_Z "," \
"\"db-version\":\"11\"}"
#define TEST_BACKUP_INFO_MULTI_HISTORY_BASE \
"[backup:current]\n" \
TEST_BACKUP_DB1_CURRENT_FULL1 \
TEST_BACKUP_DB1_CURRENT_FULL2 \
TEST_BACKUP_DB1_CURRENT_FULL3 \
"\n" \
"[db]\n" \
TEST_BACKUP_DB2_11 \
"\n" \
"[db:history]\n" \
TEST_BACKUP_DB1_HISTORY \
"\n" \
TEST_BACKUP_DB2_HISTORY
#define TEST_ARCHIVE_INFO_BASE \
"[db]\n" \
"db-id=1\n" \
"db-system-id=" HRN_PG_SYSTEMID_94_Z "\n" \
"db-version=\"9.4\"\n" \
"\n" \
"[db:history]\n" \
"1={\"db-id\":" HRN_PG_SYSTEMID_94_Z ",\"db-version\":\"9.4\"}"
#define TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE \
"[db]\n" \
"db-id=2\n" \
"db-system-id=" HRN_PG_SYSTEMID_11_Z "\n" \
"db-version=\"11\"\n" \
"\n" \
"[db:history]\n" \
"1={\"db-id\":" HRN_PG_SYSTEMID_94_Z ",\"db-version\":\"9.4\"}\n" \
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"
#define TEST_MANIFEST_HEADER \
"[backup]\n" \
"backup-label=null\n" \
"backup-timestamp-copy-start=0\n" \
"backup-timestamp-start=0\n" \
"backup-timestamp-stop=0\n" \
"backup-type=\"full\"\n"
#define TEST_MANIFEST_DB_92 \
"\n" \
"[backup:db]\n" \
"db-catalog-version=201204301\n" \
"db-control-version=922\n" \
"db-id=1\n" \
"db-system-id=" HRN_PG_SYSTEMID_94_Z "\n" \
"db-version=\"9.2\"\n"
#define TEST_MANIFEST_DB_94 \
"\n" \
"[backup:db]\n" \
"db-catalog-version=201409291\n" \
"db-control-version=942\n" \
"db-id=1\n" \
"db-system-id=" HRN_PG_SYSTEMID_94_Z "\n" \
"db-version=\"9.4\"\n"
#define TEST_MANIFEST_OPTION_ALL \
"\n" \
"[backup:option]\n" \
"option-archive-check=false\n" \
"option-archive-copy=false\n" \
"option-checksum-page=false\n" \
"option-compress=false\n" \
"option-compress-type=\"none\"\n" \
"option-hardlink=false\n" \
"option-online=false\n"
#define TEST_MANIFEST_OPTION_ARCHIVE_TRUE \
"\n" \
"[backup:option]\n" \
"option-archive-check=true\n" \
"option-archive-copy=true\n"
#define TEST_MANIFEST_TARGET \
"\n" \
"[backup:target]\n" \
"pg_data={\"path\":\"/pg/base\",\"type\":\"path\"}\n"
#define TEST_MANIFEST_DB \
"\n" \
"[db]\n" \
"postgres={\"db-id\":12173,\"db-last-system-id\":12168}\n"
#define TEST_MANIFEST_FILE \
"\n" \
"[target:file]\n" \
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"size\":4,\"timestamp\":1565282114}\n"
#define TEST_MANIFEST_FILE_DEFAULT \
"\n" \
"[target:file:default]\n" \
"group=\"group1\"\n" \
"mode=\"0600\"\n" \
"user=\"user1\"\n"
#define TEST_MANIFEST_LINK \
"\n" \
"[target:link]\n" \
"pg_data/pg_stat={\"destination\":\"../pg_stat\"}\n"
#define TEST_MANIFEST_LINK_DEFAULT \
"\n" \
"[target:link:default]\n" \
"group=\"group1\"\n" \
"user=false\n"
#define TEST_MANIFEST_PATH \
"\n" \
"[target:path]\n" \
"pg_data={\"user\":\"user1\"}\n" \
#define TEST_MANIFEST_PATH_DEFAULT \
"\n" \
"[target:path:default]\n" \
"group=false\n" \
"mode=\"0700\"\n" \
"user=\"user1\"\n"
#define TEST_INVALID_BACKREST_INFO \
"[backrest]\n" \
"backrest-checksum=\"BOGUS\"\n" \
"backrest-format=5\n" \
"backrest-version=\"2.28\"\n"
// *****************************************************************************************************************************
if (testBegin("verifyManifestFile()"))
{
// Load Parameters
StringList *argList = strLstDup(argListBase);
HRN_CFG_LOAD(cfgCmdVerify, argList);
#define TEST_BACKUP_LABEL_FULL "20181119-152138F"
Manifest *manifest = NULL;
unsigned int jobErrorTotal = 0;
VerifyBackupResult backupResult = {.backupLabel = strNewZ(TEST_BACKUP_LABEL_FULL)};
InfoPg *infoPg = NULL;
TEST_ASSIGN(
infoPg, infoArchivePg(infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_ARCHIVE_INFO_BASE)))),
"infoPg from archive.info");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("manifest.copy exists, no manifest main, manifest db version not in history, not current db");
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE,
TEST_MANIFEST_HEADER
TEST_MANIFEST_DB_92
TEST_MANIFEST_OPTION_ALL
TEST_MANIFEST_TARGET
TEST_MANIFEST_DB
TEST_MANIFEST_FILE
TEST_MANIFEST_FILE_DEFAULT
TEST_MANIFEST_LINK
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT,
.comment = "manifest db section mismatch");
backupResult.status = backupValid;
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_PTR(manifest, NULL, "manifest not set - pg version mismatch");
TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid");
TEST_RESULT_LOG(
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/20181119-152138F/backup.manifest.copy'"
" for read\n"
"P00 ERROR: [028]: '20181119-152138F' may not be recoverable - PG data (id 1, version 9.2, system-id "
HRN_PG_SYSTEMID_94_Z ") is not in the backup.info history, skipping");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("rerun test with db-system-id invalid and no main");
HRN_STORAGE_REMOVE(storageRepoWrite(), STORAGE_REPO_BACKUP "/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE);
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
TEST_MANIFEST_HEADER
"\n"
"[backup:db]\n"
"db-catalog-version=201409291\n"
"db-control-version=942\n"
"db-id=1\n"
"db-system-id=0\n"
"db-version=\"9.4\"\n"
TEST_MANIFEST_OPTION_ALL
TEST_MANIFEST_TARGET
TEST_MANIFEST_DB
TEST_MANIFEST_FILE
TEST_MANIFEST_FILE_DEFAULT
TEST_MANIFEST_LINK
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT,
.comment = "manifest copy - invalid system-id");
backupResult.status = backupValid;
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_PTR(manifest, NULL, "manifest not set - pg system-id mismatch");
TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid");
TEST_RESULT_LOG(
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/20181119-152138F/backup.manifest' for read\n"
"P00 WARN: 20181119-152138F/backup.manifest is missing or unusable, using copy\n"
"P00 ERROR: [028]: '20181119-152138F' may not be recoverable - PG data (id 1, version 9.4, system-id 0) is "
"not in the backup.info history, skipping");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("rerun copy test with db-id invalid");
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
TEST_MANIFEST_HEADER
"\n"
"[backup:db]\n"
"db-catalog-version=201409291\n"
"db-control-version=942\n"
"db-id=0\n"
"db-system-id=" HRN_PG_SYSTEMID_94_Z "\n"
"db-version=\"9.4\"\n"
TEST_MANIFEST_OPTION_ALL
TEST_MANIFEST_TARGET
TEST_MANIFEST_DB
TEST_MANIFEST_FILE
TEST_MANIFEST_FILE_DEFAULT
TEST_MANIFEST_LINK
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT,
.comment = "manifest copy - invalid db-id");
backupResult.status = backupValid;
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_PTR(manifest, NULL, "manifest not set - pg db-id mismatch");
TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid");
TEST_RESULT_LOG(
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/20181119-152138F/backup.manifest' for read\n"
"P00 WARN: 20181119-152138F/backup.manifest is missing or unusable, using copy\n"
"P00 ERROR: [028]: '20181119-152138F' may not be recoverable - PG data (id 0, version 9.4, system-id "
HRN_PG_SYSTEMID_94_Z ") is not in the backup.info history, skipping");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("missing main manifest, errored copy");
backupResult.status = backupValid;
HRN_STORAGE_PUT_Z(
storageRepoWrite(), TEST_PATH "/repo/" STORAGE_PATH_BACKUP "/db/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE
INFO_COPY_EXT, TEST_INVALID_BACKREST_INFO, .comment = "invalid manifest copy");
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, false, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid");
TEST_RESULT_LOG(
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/20181119-152138F/backup.manifest' for read\n"
"P00 WARN: invalid checksum, actual 'e056f784a995841fd4e2802b809299b8db6803a2' but expected 'BOGUS' "
"<REPO:BACKUP>/20181119-152138F/backup.manifest.copy");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("current backup true");
HRN_STORAGE_PUT_Z(
storageRepoWrite(), TEST_PATH "/repo/" STORAGE_PATH_BACKUP "/db/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE,
TEST_INVALID_BACKREST_INFO, .comment = "invalid manifest");
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, true, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_PTR(manifest, NULL, "manifest not set");
TEST_RESULT_UINT(backupResult.status, backupInvalid, "manifest unusable - backup invalid");
TEST_RESULT_LOG(
"P00 WARN: invalid checksum, actual 'e056f784a995841fd4e2802b809299b8db6803a2' but expected 'BOGUS' "
"<REPO:BACKUP>/20181119-152138F/backup.manifest\n"
"P00 WARN: invalid checksum, actual 'e056f784a995841fd4e2802b809299b8db6803a2' but expected 'BOGUS' "
"<REPO:BACKUP>/20181119-152138F/backup.manifest.copy");
// Write a valid manifest with a manifest copy that is invalid
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/" TEST_BACKUP_LABEL_FULL "/" BACKUP_MANIFEST_FILE,
TEST_MANIFEST_HEADER
TEST_MANIFEST_DB_94
TEST_MANIFEST_OPTION_ALL
TEST_MANIFEST_TARGET
TEST_MANIFEST_DB
TEST_MANIFEST_FILE
TEST_MANIFEST_FILE_DEFAULT
TEST_MANIFEST_LINK
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT,
.comment = "valid manifest");
backupResult.status = backupValid;
TEST_ASSIGN(manifest, verifyManifestFile(&backupResult, NULL, true, infoPg, &jobErrorTotal), "verify manifest");
TEST_RESULT_PTR_NE(manifest, NULL, "manifest set");
TEST_RESULT_UINT(backupResult.status, backupValid, "manifest usable");
TEST_RESULT_LOG("P00 WARN: backup '20181119-152138F' manifest.copy does not match manifest");
}
// *****************************************************************************************************************************
if (testBegin("verifyCreateArchiveIdRange()"))
{
VerifyWalRange *walRangeResult = NULL;
unsigned int errTotal = 0;
StringList *walFileList = strLstNew();
VerifyArchiveResult archiveResult =
{
.archiveId = strNewZ("9.4-1"),
.walRangeList = lstNewP(sizeof(VerifyWalRange), .comparator = lstComparatorStr),
};
List *archiveIdResultList = lstNewP(sizeof(VerifyArchiveResult), .comparator = archiveIdComparator);
lstAdd(archiveIdResultList, &archiveResult);
VerifyArchiveResult *archiveIdResult = lstGetLast(archiveIdResultList);
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("Single WAL");
archiveIdResult->pgWalInfo.size = PG_WAL_SEGMENT_SIZE_DEFAULT;
archiveIdResult->pgWalInfo.version = PG_VERSION_94;
strLstAddZ(walFileList, "000000020000000200000000-daa497dba64008db824607940609ba1cd7c6c501.gz");
TEST_RESULT_VOID(verifyCreateArchiveIdRange(archiveIdResult, walFileList, &errTotal), "create archiveId WAL range");
TEST_RESULT_UINT(errTotal, 0, "no errors");
TEST_RESULT_UINT(lstSize(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList), 1, "single range");
TEST_ASSIGN(
walRangeResult, (VerifyWalRange *)lstGet(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList, 0),
"get range");
TEST_RESULT_STR_Z(walRangeResult->start, "000000020000000200000000", "start range");
TEST_RESULT_STR_Z(walRangeResult->stop, "000000020000000200000000", "stop range");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("Duplicate WAL only - no range, all removed from list");
lstClear(archiveIdResult->walRangeList);
// Add a duplicate
strLstAddZ(walFileList, "000000020000000200000000");
TEST_RESULT_VOID(verifyCreateArchiveIdRange(archiveIdResult, walFileList, &errTotal), "create archiveId WAL range");
TEST_RESULT_UINT(errTotal, 1, "duplicate WAL error");
TEST_RESULT_UINT(strLstSize(walFileList), 0, "all WAL removed from WAL file list");
TEST_RESULT_UINT(lstSize(archiveIdResult->walRangeList), 0, "no range");
TEST_RESULT_LOG("P00 ERROR: [028]: duplicate WAL '000000020000000200000000' for '9.4-1' exists, skipping");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("FF Wal not skipped > 9.2, duplicates at beginning and end of list are removed");
errTotal = 0;
strLstAddZ(walFileList, "000000020000000100000000-daa497dba64008db824607940609ba1cd7c6c501.gz");
strLstAddZ(walFileList, "000000020000000100000000");
strLstAddZ(walFileList, "000000020000000100000000-aaaaaadba64008db824607940609ba1cd7c6c501");
strLstAddZ(walFileList, "0000000200000001000000FD-daa497dba64008db824607940609ba1cd7c6c501.gz");
strLstAddZ(walFileList, "0000000200000001000000FE-a6e1a64f0813352bc2e97f116a1800377e17d2e4.gz");
strLstAddZ(walFileList, "0000000200000001000000FF-daa497dba64008db824607940609ba1cd7c6c501");
strLstAddZ(walFileList, "000000020000000200000000");
strLstAddZ(walFileList, "000000020000000200000001");
strLstAddZ(walFileList, "000000020000000200000001");
TEST_RESULT_VOID(verifyCreateArchiveIdRange(archiveIdResult, walFileList, &errTotal), "create archiveId WAL range");
TEST_RESULT_UINT(errTotal, 2, "triplicate WAL error at beginning, duplicate WAL at end");
TEST_RESULT_UINT(strLstSize(walFileList), 4, "only duplicate WAL removed from WAL list");
TEST_RESULT_UINT(lstSize(archiveIdResultList), 1, "single archiveId result");
TEST_RESULT_UINT(lstSize(archiveIdResult->walRangeList), 1, "single range");
TEST_ASSIGN(
walRangeResult, (VerifyWalRange *)lstGet(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList, 0),
"get range");
TEST_RESULT_STR_Z(walRangeResult->start, "0000000200000001000000FD", "start range");
TEST_RESULT_STR_Z(walRangeResult->stop, "000000020000000200000000", "stop range");
TEST_RESULT_LOG(
"P00 ERROR: [028]: duplicate WAL '000000020000000100000000' for '9.4-1' exists, skipping\n"
"P00 ERROR: [028]: duplicate WAL '000000020000000200000001' for '9.4-1' exists, skipping");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("FF Wal skipped <= 9.2, duplicates in middle of list removed");
// Clear the range lists and rerun the test with PG_VERSION_92 to ensure FF is reported as an error
lstClear(archiveIdResult->walRangeList);
errTotal = 0;
archiveIdResult->archiveId = strNewZ("9.2-1");
archiveIdResult->pgWalInfo.version = PG_VERSION_92;
strLstAddZ(walFileList, "000000020000000200000001");
strLstAddZ(walFileList, "000000020000000200000001");
strLstAddZ(walFileList, "000000020000000200000002");
TEST_RESULT_VOID(verifyCreateArchiveIdRange(archiveIdResult, walFileList, &errTotal), "create archiveId WAL range");
TEST_RESULT_UINT(errTotal, 2, "error reported");
TEST_RESULT_UINT(lstSize(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList), 2, "multiple ranges");
TEST_ASSIGN(
walRangeResult, (VerifyWalRange *)lstGet(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList, 0),
"get range");
TEST_RESULT_STR_Z(walRangeResult->start, "0000000200000001000000FD", "start range");
TEST_RESULT_STR_Z(walRangeResult->stop, "000000020000000200000000", "stop range");
TEST_ASSIGN(
walRangeResult, (VerifyWalRange *)lstGet(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList, 1),
"get second range");
TEST_RESULT_STR_Z(walRangeResult->start, "000000020000000200000002", "start range");
TEST_RESULT_STR_Z(walRangeResult->stop, "000000020000000200000002", "stop range");
TEST_RESULT_LOG(
"P00 ERROR: [028]: invalid WAL '0000000200000001000000FF' for '9.2-1' exists, skipping\n"
"P00 ERROR: [028]: duplicate WAL '000000020000000200000001' for '9.2-1' exists, skipping");
TEST_RESULT_STRLST_Z(
walFileList,
"0000000200000001000000FD-daa497dba64008db824607940609ba1cd7c6c501.gz\n"
"0000000200000001000000FE-a6e1a64f0813352bc2e97f116a1800377e17d2e4.gz\n"
"000000020000000200000000\n000000020000000200000002\n",
"skipped files removed");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("Rerun <= 9.2, missing FF not a gap");
// Clear the range lists, rerun the PG_VERSION_92 test to ensure the missing FF is not considered a gap
lstClear(archiveIdResult->walRangeList);
errTotal = 0;
TEST_RESULT_VOID(verifyCreateArchiveIdRange(archiveIdResult, walFileList, &errTotal), "create archiveId WAL range");
TEST_RESULT_UINT(errTotal, 0, "error reported");
TEST_RESULT_UINT(lstSize(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList), 2, "multiple ranges");
TEST_ASSIGN(
walRangeResult, (VerifyWalRange *)lstGet(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList, 0),
"get range");
TEST_RESULT_STR_Z(walRangeResult->start, "0000000200000001000000FD", "start range");
TEST_RESULT_STR_Z(walRangeResult->stop, "000000020000000200000000", "stop range");
TEST_ASSIGN(
walRangeResult, (VerifyWalRange *)lstGet(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList, 1),
"get second range");
TEST_RESULT_STR_Z(walRangeResult->start, "000000020000000200000002", "start range");
TEST_RESULT_STR_Z(walRangeResult->stop, "000000020000000200000002", "stop range");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("version > 9.2, missing FF is a gap");
// Clear the range lists and update the version > 9.2 so missing FF is considered a gap in the WAL ranges
lstClear(archiveIdResult->walRangeList);
errTotal = 0;
archiveIdResult->archiveId = strNewZ("9.6-1");
archiveIdResult->pgWalInfo.version = PG_VERSION_96;
strLstAddZ(walFileList, "000000020000000200000003-123456");
strLstAddZ(walFileList, "000000020000000200000004-123456");
TEST_RESULT_VOID(verifyCreateArchiveIdRange(archiveIdResult, walFileList, &errTotal), "create archiveId WAL range");
TEST_RESULT_UINT(errTotal, 0, "no errors");
TEST_RESULT_UINT(lstSize(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList), 3, "multiple ranges");
TEST_ASSIGN(
walRangeResult, (VerifyWalRange *)lstGet(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList, 0),
"get first range");
TEST_RESULT_STR_Z(walRangeResult->start, "0000000200000001000000FD", "start range");
TEST_RESULT_STR_Z(walRangeResult->stop, "0000000200000001000000FE", "stop range");
TEST_ASSIGN(
walRangeResult, (VerifyWalRange *)lstGet(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList, 1),
"get second range");
TEST_RESULT_STR_Z(walRangeResult->start, "000000020000000200000000", "start range");
TEST_RESULT_STR_Z(walRangeResult->stop, "000000020000000200000000", "stop range");
TEST_ASSIGN(
walRangeResult, (VerifyWalRange *)lstGet(((VerifyArchiveResult *)lstGet(archiveIdResultList, 0))->walRangeList, 2),
"get third range");
TEST_RESULT_STR_Z(walRangeResult->start, "000000020000000200000002", "start range");
TEST_RESULT_STR_Z(walRangeResult->stop, "000000020000000200000004", "stop range");
}
// *****************************************************************************************************************************
if (testBegin("verifyPgHistory()"))
{
// Create backup.info
InfoBackup *backupInfo = NULL;
TEST_ASSIGN(
backupInfo, infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_BACKUP_INFO_MULTI_HISTORY_BASE))),
"backup.info multi-history");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("history mismatch - missing history");
// Create archive.info - history mismatch
InfoArchive *archiveInfo = NULL;
TEST_ASSIGN(
archiveInfo, infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(
"[db]\n"
"db-id=2\n"
"db-system-id=" HRN_PG_SYSTEMID_11_Z "\n"
"db-version=\"11\"\n"
"\n"
"[db:history]\n"
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))), "archive.info missing history");
TEST_ERROR(
verifyPgHistory(infoArchivePg(archiveInfo), infoBackupPg(backupInfo)), FormatError,
"archive and backup history lists do not match");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("history mismatch - system id");
TEST_ASSIGN(
archiveInfo, infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(
"[db]\n"
"db-id=2\n"
"db-system-id=" HRN_PG_SYSTEMID_11_Z "\n"
"db-version=\"11\"\n"
"\n"
"[db:history]\n"
"1={\"db-id\":6625592122879095777,\"db-version\":\"9.4\"}\n"
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))), "archive.info history system id mismatch");
TEST_ERROR(
verifyPgHistory(infoArchivePg(archiveInfo), infoBackupPg(backupInfo)), FormatError,
"archive and backup history lists do not match");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("history mismatch - version");
TEST_ASSIGN(
archiveInfo, infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(
"[db]\n"
"db-id=2\n"
"db-system-id=" HRN_PG_SYSTEMID_11_Z "\n"
"db-version=\"11\"\n"
"\n"
"[db:history]\n"
"1={\"db-id\":" HRN_PG_SYSTEMID_94_Z ",\"db-version\":\"9.5\"}\n"
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))), "archive.info history version mismatch");
TEST_ERROR(
verifyPgHistory(infoArchivePg(archiveInfo), infoBackupPg(backupInfo)), FormatError,
"archive and backup history lists do not match");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("history mismatch - id");
TEST_ASSIGN(
archiveInfo, infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(
"[db]\n"
"db-id=2\n"
"db-system-id=" HRN_PG_SYSTEMID_11_Z "\n"
"db-version=\"11\"\n"
"\n"
"[db:history]\n"
"3={\"db-id\":" HRN_PG_SYSTEMID_94_Z ",\"db-version\":\"9.4\"}\n"
"2={\"db-id\":" HRN_PG_SYSTEMID_11_Z ",\"db-version\":\"11\"}"))), "archive.info history id mismatch");
TEST_ERROR(
verifyPgHistory(infoArchivePg(archiveInfo), infoBackupPg(backupInfo)), FormatError,
"archive and backup history lists do not match");
}
// *****************************************************************************************************************************
if (testBegin("verifySetBackupCheckArchive(), verifyLogInvalidResult(), verifyRender()"))
{
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("verifySetBackupCheckArchive()");
InfoBackup *backupInfo = NULL;
InfoArchive *archiveInfo = NULL;
TEST_ASSIGN(
backupInfo, infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_BACKUP_INFO_MULTI_HISTORY_BASE))),
"backup.info multi-history");
TEST_ASSIGN(archiveInfo, infoArchiveNewLoad(ioBufferReadNew(harnessInfoChecksumZ(TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE))),
"archive.info multi-history");
InfoPg *pgHistory = infoArchivePg(archiveInfo);
StringList *backupList= strLstNew();
strLstAddZ(backupList, "20181119-152138F");
strLstAddZ(backupList, "20181119-152900F");
StringList *archiveIdList = strLstComparatorSet(strLstNew(), archiveIdComparator);
strLstAddZ(archiveIdList, "9.4-1");
strLstAddZ(archiveIdList, "11-2");
unsigned int errTotal = 0;
// Add backup to end of list
strLstAddZ(backupList, "20181119-153000F");
strLstAddZ(archiveIdList, "12-3");
TEST_RESULT_STR_Z(
verifySetBackupCheckArchive(backupList, backupInfo, archiveIdList, pgHistory, &errTotal),
"20181119-153000F", "current backup, missing archive");
TEST_RESULT_UINT(errTotal, 1, "error logged");
TEST_RESULT_LOG("P00 ERROR: [044]: archiveIds '12-3' are not in the archive.info history list");
errTotal = 0;
strLstAddZ(archiveIdList, "13-4");
TEST_RESULT_STR_Z(
verifySetBackupCheckArchive(backupList, backupInfo, archiveIdList, pgHistory, &errTotal),
"20181119-153000F", "test multiple archiveIds on disk not in archive.info");
TEST_RESULT_UINT(errTotal, 1, "error logged");
TEST_RESULT_LOG("P00 ERROR: [044]: archiveIds '12-3, 13-4' are not in the archive.info history list");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("verifyLogInvalidResult() - missing file");
TEST_RESULT_UINT(
verifyLogInvalidResult(STORAGE_REPO_ARCHIVE_STR, verifyFileMissing, 0, STRDEF("missingfilename")),
0, "file missing message");
TEST_RESULT_LOG("P00 WARN: file missing 'missingfilename'");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("verifyRender() - missing file, empty invalidList");
List *archiveIdResultList = lstNewP(sizeof(VerifyArchiveResult), .comparator = archiveIdComparator);
List *backupResultList = lstNewP(sizeof(VerifyBackupResult), .comparator = lstComparatorStr);
VerifyArchiveResult archiveIdResult =
{
.archiveId = strNewZ("9.6-1"),
.totalWalFile = 1,
.walRangeList = lstNewP(sizeof(VerifyWalRange), .comparator = lstComparatorStr),
};
VerifyWalRange walRange =
{
.start = strNewZ("0"),
.stop = strNewZ("2"),
.invalidFileList = lstNewP(sizeof(VerifyInvalidFile), .comparator = lstComparatorStr),
};
lstAdd(archiveIdResult.walRangeList, &walRange);
lstAdd(archiveIdResultList, &archiveIdResult);
TEST_RESULT_STR_Z(
verifyRender(archiveIdResultList, backupResultList),
"Results:\n"
" archiveId: 9.6-1, total WAL checked: 1, total valid WAL: 0\n"
" missing: 0, checksum invalid: 0, size invalid: 0, other: 0\n"
" backup: none found", "archive: no invalid file list");
VerifyInvalidFile invalidFile =
{
.fileName = strNewZ("file"),
.reason = verifyFileMissing,
};
lstAdd(walRange.invalidFileList, &invalidFile);
VerifyBackupResult backupResult =
{
.backupLabel = strNewZ("test-backup-label"),
.status = backupInvalid,
.totalFileVerify = 1,
.invalidFileList = lstNewP(sizeof(VerifyInvalidFile), .comparator = lstComparatorStr),
};
lstAdd(backupResult.invalidFileList, &invalidFile);
lstAdd(backupResultList, &backupResult);
TEST_RESULT_STR_Z(
verifyRender(archiveIdResultList, backupResultList),
"Results:\n"
" archiveId: 9.6-1, total WAL checked: 1, total valid WAL: 0\n"
" missing: 1, checksum invalid: 0, size invalid: 0, other: 0\n"
" backup: test-backup-label, status: invalid, total files checked: 1, total valid files: 0\n"
" missing: 1, checksum invalid: 0, size invalid: 0, other: 0", "archive file missing, backup file missing");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("verifyAddInvalidWalFile() - file missing (coverage test)");
TEST_RESULT_VOID(
verifyAddInvalidWalFile(archiveIdResult.walRangeList, verifyFileMissing, STRDEF("test"), STRDEF("3")), "coverage test");
}
// *****************************************************************************************************************************
if (testBegin("cmdVerify() - info files"))
{
// Load Parameters
StringList *argList = strLstDup(argListBase);
HRN_CFG_LOAD(cfgCmdVerify, argList);
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("backup.info invalid checksum, neither backup copy nor archive infos exist");
HRN_STORAGE_PUT_Z(storageRepoWrite(), INFO_BACKUP_PATH_FILE, TEST_INVALID_BACKREST_INFO, .comment = "invalid backup.info");
TEST_ERROR(cmdVerify(), RuntimeError, "2 fatal errors encountered, see log for details");
TEST_RESULT_LOG(
"P00 WARN: invalid checksum, actual 'e056f784a995841fd4e2802b809299b8db6803a2' but expected 'BOGUS' "
"<REPO:BACKUP>/backup.info\n"
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/backup.info.copy' for read\n"
"P00 ERROR: [029]: No usable backup.info file\n"
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/archive/db/archive.info' for read\n"
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/archive/db/archive.info.copy' for read\n"
"P00 ERROR: [029]: No usable archive.info file");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("backup.info invalid checksum, backup.info.copy valid, archive.info not exist, archive copy checksum invalid");
HRN_STORAGE_PUT_Z(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, TEST_INVALID_BACKREST_INFO,
.comment = "invalid archive.info.copy");
HRN_INFO_PUT(
storageRepoWrite(), INFO_BACKUP_PATH_FILE INFO_COPY_EXT,
"[backup:current]\n"
TEST_BACKUP_DB1_CURRENT_FULL1
"\n"
"[db]\n"
TEST_BACKUP_DB1_94
"\n"
"[db:history]\n"
TEST_BACKUP_DB1_HISTORY,
.comment = "valid backup.info.copy");
TEST_ERROR(cmdVerify(), RuntimeError, "1 fatal errors encountered, see log for details");
TEST_RESULT_LOG(
"P00 WARN: invalid checksum, actual 'e056f784a995841fd4e2802b809299b8db6803a2' but expected 'BOGUS'"
" <REPO:BACKUP>/backup.info\n"
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/archive/db/archive.info' for read\n"
"P00 WARN: invalid checksum, actual 'e056f784a995841fd4e2802b809299b8db6803a2' but expected 'BOGUS'"
" <REPO:ARCHIVE>/archive.info.copy\n"
"P00 ERROR: [029]: No usable archive.info file");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("backup.info and copy valid but checksum mismatch, archive.info checksum invalid, archive.info copy valid");
HRN_INFO_PUT(
storageRepoWrite(), INFO_BACKUP_PATH_FILE, TEST_BACKUP_INFO_MULTI_HISTORY_BASE, .comment = "valid backup.info");
HRN_STORAGE_PUT_Z(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE, TEST_INVALID_BACKREST_INFO, .comment = "invalid archive.info");
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, TEST_ARCHIVE_INFO_BASE, .comment = "valid archive.info.copy");
TEST_ERROR(cmdVerify(), RuntimeError, "1 fatal errors encountered, see log for details");
TEST_RESULT_LOG(
"P00 WARN: backup.info.copy does not match backup.info\n"
"P00 WARN: invalid checksum, actual 'e056f784a995841fd4e2802b809299b8db6803a2' but expected 'BOGUS'"
" <REPO:ARCHIVE>/archive.info\n"
"P00 ERROR: [029]: backup info file and archive info file do not match\n"
" archive: id = 1, version = 9.4, system-id = " HRN_PG_SYSTEMID_94_Z "\n"
" backup : id = 2, version = 11, system-id = " HRN_PG_SYSTEMID_11_Z "\n"
" HINT: this may be a symptom of repository corruption!");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("backup.info and copy valid and checksums match, archive.info and copy valid, but checksum mismatch");
HRN_INFO_PUT(
storageRepoWrite(), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, TEST_BACKUP_INFO_MULTI_HISTORY_BASE,
.comment = "valid backup.info.copy");
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE, TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE, .comment = "valid archive.info");
TEST_RESULT_VOID(cmdVerify(), "usable backup and archive info files");
TEST_RESULT_LOG(
"P00 WARN: archive.info.copy does not match archive.info\n"
"P00 WARN: no archives or backups exist in the repo");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("backup.info valid, copy invalid, archive.info valid, copy invalid");
HRN_STORAGE_REMOVE(storageRepoWrite(), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, .comment = "remove backup.info.copy");
HRN_STORAGE_REMOVE(storageRepoWrite(), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, .comment = "remove archive.info.copy");
TEST_RESULT_VOID(cmdVerify(), "usable backup and archive info files");
TEST_RESULT_LOG(
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/backup.info.copy' for read\n"
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/archive/db/archive.info.copy' for read\n"
"P00 WARN: no archives or backups exist in the repo");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("backup.info and copy missing, archive.info and copy valid");
HRN_STORAGE_REMOVE(storageRepoWrite(), INFO_BACKUP_PATH_FILE);
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE,
.comment = "valid and matching archive.info.copy");
TEST_ERROR(cmdVerify(), RuntimeError, "1 fatal errors encountered, see log for details");
TEST_RESULT_LOG(
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/backup.info' for read\n"
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/backup.info.copy' for read\n"
"P00 ERROR: [029]: No usable backup.info file");
}
// *****************************************************************************************************************************
if (testBegin("verifyFile()"))
{
// Load Parameters
StringList *argList = strLstDup(argListBase);
HRN_CFG_LOAD(cfgCmdVerify, argList);
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("zero-sized file in archive");
String *filePathName = strNewZ(STORAGE_REPO_ARCHIVE "/testfile");
HRN_STORAGE_PUT_EMPTY(storageRepoWrite(), strZ(filePathName));
TEST_RESULT_UINT(verifyFile(filePathName, STRDEF(HASH_TYPE_SHA1_ZERO), 0, NULL), verifyOk, "file ok");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("file size invalid in archive");
HRN_STORAGE_PUT_Z(storageRepoWrite(), strZ(filePathName), fileContents);
TEST_RESULT_UINT(verifyFile(filePathName, fileChecksum, 0, NULL), verifySizeInvalid, "file size invalid");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("file missing in archive");
TEST_RESULT_UINT(
verifyFile(
strNewFmt(STORAGE_REPO_ARCHIVE "/missingFile"), fileChecksum, 0, NULL), verifyFileMissing, "file missing");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("encrypted/compressed file in backup");
// Create a compressed encrypted repo file in backup
filePathName = strCatZ(strNew(), STORAGE_REPO_BACKUP "/testfile");
HRN_STORAGE_PUT_Z(
storageRepoWrite(), strZ(filePathName), fileContents, .compressType = compressTypeGz, .cipherType = cipherTypeAes256Cbc,
.cipherPass = "pass");
strCatZ(filePathName, ".gz");
TEST_RESULT_UINT(
verifyFile(filePathName, fileChecksum, fileSize, STRDEF("pass")), verifyOk, "file encrypted compressed ok");
TEST_RESULT_UINT(
verifyFile(
filePathName, STRDEF("badchecksum"), fileSize, STRDEF("pass")), verifyChecksumMismatch,
"file encrypted compressed checksum mismatch");
}
// *****************************************************************************************************************************
if (testBegin("cmdVerify(), verifyProcess() - errors"))
{
//--------------------------------------------------------------------------------------------------------------------------
// Load Parameters with multi-repo
StringList *argList = strLstDup(argListBase);
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 4, TEST_PATH "/repo4");
HRN_CFG_LOAD(cfgCmdVerify, argList);
// Store valid archive/backup info files
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE, TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE, .comment = "valid archive.info");
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE,
.comment = "valid archive.info.copy");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("valid info files, WAL files present, no backups");
#define TEST_NO_CURRENT_BACKUP \
"[db]\n" \
TEST_BACKUP_DB2_11 \
"\n" \
"[db:history]\n" \
TEST_BACKUP_DB1_HISTORY \
"\n" \
TEST_BACKUP_DB2_HISTORY
HRN_INFO_PUT(storageRepoWrite(), INFO_BACKUP_PATH_FILE, TEST_NO_CURRENT_BACKUP, .comment = "no current backups");
HRN_INFO_PUT(
storageRepoWrite(), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, TEST_NO_CURRENT_BACKUP, .comment = "no current backups copy");
// Create WAL file with just header info and small WAL size
Buffer *walBuffer = bufNew((size_t)(1024 * 1024));
bufUsedSet(walBuffer, bufSize(walBuffer));
memset(bufPtr(walBuffer), 0, bufSize(walBuffer));
hrnPgWalToBuffer((PgWal){.version = PG_VERSION_11, .size = 1024 * 1024}, walBuffer);
const char *walBufferSha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer)));
HRN_STORAGE_PUT(
storageRepoIdxWrite(0),
strZ(strNewFmt(STORAGE_REPO_ARCHIVE "/11-2/0000000200000007/000000020000000700000FFE-%s", walBufferSha1)), walBuffer,
.comment = "valid WAL");
HRN_STORAGE_PUT(
storageRepoIdxWrite(0),
STORAGE_REPO_ARCHIVE "/11-2/0000000200000007/000000020000000700000FFE-bad817043007aa2100c44c712bcb456db705dab9",
walBuffer, .comment = "duplicate WAL");
// Set log detail level to capture ranges (there should be none)
harnessLogLevelSet(logLevelDetail);
TEST_ERROR(cmdVerify(), RuntimeError, "1 fatal errors encountered, see log for details");
TEST_RESULT_LOG(
"P00 WARN: no backups exist in the repo\n"
"P00 ERROR: [028]: duplicate WAL '000000020000000700000FFE' for '11-2' exists, skipping\n"
"P00 WARN: path '11-2/0000000200000007' does not contain any valid WAL to be processed\n"
"P00 INFO: Results:\n"
" archiveId: 11-2, total WAL checked: 2, total valid WAL: 0\n"
" missing: 0, checksum invalid: 0, size invalid: 0, other: 0\n"
" backup: none found");
harnessLogLevelReset();
HRN_STORAGE_REMOVE(
storageRepoIdxWrite(0),
STORAGE_REPO_ARCHIVE "/11-2/0000000200000007/000000020000000700000FFE-bad817043007aa2100c44c712bcb456db705dab9",
.comment = "remove duplicate WAL");
HRN_STORAGE_PATH_CREATE(
storageRepoIdxWrite(0), STORAGE_REPO_ARCHIVE "/9.4-1", .comment = "empty path for old archiveId");
HRN_STORAGE_PATH_CREATE(
storageRepoIdxWrite(0), STORAGE_REPO_ARCHIVE "/11-2/0000000100000000", .comment = "empty timeline path");
HRN_STORAGE_PUT(
storageRepoIdxWrite(0),
STORAGE_REPO_ARCHIVE "/11-2/0000000200000007/000000020000000700000FFD-a6e1a64f0813352bc2e97f116a1800377e17d2e4",
walBuffer, .compressType = compressTypeGz, .comment = "first WAL compressed - but checksum failure");
HRN_STORAGE_PUT(
storageRepoIdxWrite(0),
strZ(
strNewFmt(
STORAGE_REPO_ARCHIVE "/11-2/0000000200000007/000000020000000700000FFF-%s",
strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, BUFSTRDEF("invalidsize")))))),
BUFSTRDEF("invalidsize"), .comment = "WAL - invalid size");
HRN_STORAGE_PUT(
storageRepoIdxWrite(0),
strZ(strNewFmt(STORAGE_REPO_ARCHIVE "/11-2/0000000200000008/000000020000000800000000-%s", walBufferSha1)),
walBuffer, .comment = "WAL - continue range");
// Set log detail level to capture ranges
harnessLogLevelSet(logLevelDetail);
// Test verifyProcess directly
unsigned int errorTotal = 0;
TEST_RESULT_STR_Z(
verifyProcess(&errorTotal),
"Results:\n"
" archiveId: 9.4-1, total WAL checked: 0, total valid WAL: 0\n"
" archiveId: 11-2, total WAL checked: 4, total valid WAL: 2\n"
" missing: 0, checksum invalid: 1, size invalid: 1, other: 0\n"
" backup: none found",
"verifyProcess() results");
TEST_RESULT_UINT(errorTotal, 2, "errors");
TEST_RESULT_LOG(
"P00 WARN: no backups exist in the repo\n"
"P00 WARN: archive path '9.4-1' is empty\n"
"P00 WARN: path '11-2/0000000100000000' does not contain any valid WAL to be processed\n"
"P01 ERROR: [028]: invalid checksum "
"'11-2/0000000200000007/000000020000000700000FFD-a6e1a64f0813352bc2e97f116a1800377e17d2e4.gz'\n"
"P01 ERROR: [028]: invalid size "
"'11-2/0000000200000007/000000020000000700000FFF-ee161f898c9012dd0c28b3fd1e7140b9cf411306'\n"
"P00 DETAIL: archiveId: 11-2, wal start: 000000020000000700000FFD, wal stop: 000000020000000800000000");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("valid info files, start next timeline");
// Load Parameters - single default repo
argList = strLstDup(argListBase);
HRN_CFG_LOAD(cfgCmdVerify, argList);
HRN_STORAGE_PUT(
storageRepoIdxWrite(0),
strZ(strNewFmt(STORAGE_REPO_ARCHIVE "/11-2/0000000200000008/000000020000000800000002-%s", walBufferSha1)),
walBuffer, .comment = "WAL - starts next range");
HRN_STORAGE_PUT(
storageRepoIdxWrite(0),
strZ(strNewFmt(STORAGE_REPO_ARCHIVE "/11-2/0000000300000000/000000030000000000000000-%s", walBufferSha1)),
walBuffer, .comment = "WAL - starts next timeline");
HRN_STORAGE_PUT(
storageRepoIdxWrite(0),
strZ(strNewFmt(STORAGE_REPO_ARCHIVE "/11-2/0000000300000000/000000030000000000000001-%s", walBufferSha1)),
walBuffer, .comment = "WAL - end next timeline");
// Set log level to errors only
harnessLogLevelSet(logLevelError);
TEST_ERROR(cmdVerify(), RuntimeError, "2 fatal errors encountered, see log for details");
TEST_RESULT_LOG(
"P01 ERROR: [028]: invalid checksum "
"'11-2/0000000200000007/000000020000000700000FFD-a6e1a64f0813352bc2e97f116a1800377e17d2e4.gz'\n"
"P01 ERROR: [028]: invalid size "
"'11-2/0000000200000007/000000020000000700000FFF-ee161f898c9012dd0c28b3fd1e7140b9cf411306'");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("valid info files - various archive/backup errors");
// Load Parameters - single non-default repo
argList = strLstNew();
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo");
hrnCfgArgRawZ(argList, cfgOptStanza, "db");
hrnCfgArgRawZ(argList, cfgOptRepo, "2");
HRN_CFG_LOAD(cfgCmdVerify, argList, .jobRetry = 1);
HRN_STORAGE_PUT(
storageRepoIdxWrite(0),
STORAGE_REPO_ARCHIVE "/11-2/0000000200000008/000000020000000800000003-656817043007aa2100c44c712bcb456db705dab9",
walBuffer, .modeFile = 0200, .comment = "WAL - file not readable");
HRN_STORAGE_PATH_CREATE(
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/20181119-152800F", .comment = "prior backup path missing manifests");
HRN_INFO_PUT(
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/20181119-152810F/" BACKUP_MANIFEST_FILE,
TEST_MANIFEST_HEADER
TEST_MANIFEST_DB_94
TEST_MANIFEST_OPTION_ALL
TEST_MANIFEST_TARGET
TEST_MANIFEST_DB,
.comment = "manifest without target files");
// Create full backup with files
HRN_STORAGE_PUT_Z(
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/20181119-152900F/pg_data/PG_VERSION", "BOGUS",
.comment = "put checksum-error backup file");
HRN_STORAGE_PUT_EMPTY(
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/20181119-152900F/pg_data/testzero",
.comment = "put zero-size backup file");
HRN_STORAGE_PUT_Z(
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/20181119-152900F/pg_data/testvalid", fileContents,
.comment = "put valid file");
// Write manifests for full backup
String *manifestContent = strNewFmt(
"[backup]\n"
"backup-label=\"20181119-152900F\"\n"
"backup-timestamp-copy-start=0\n"
"backup-timestamp-start=0\n"
"backup-timestamp-stop=0\n"
"backup-type=\"full\"\n"
"\n"
"[backup:db]\n"
TEST_BACKUP_DB2_11
TEST_MANIFEST_OPTION_ALL
TEST_MANIFEST_TARGET
TEST_MANIFEST_DB
TEST_MANIFEST_FILE
"pg_data/testvalid={\"checksum\":\"%s\",\"size\":7,\"timestamp\":1565282114}\n"
"pg_data/testzero={\"repo-size\":20,\"size\":0,\"timestamp\":1601405663}\n"
TEST_MANIFEST_FILE_DEFAULT
TEST_MANIFEST_LINK
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT,
strZ(fileChecksum));
HRN_INFO_PUT(
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/20181119-152900F/" BACKUP_MANIFEST_FILE, strZ(manifestContent),
.comment = "valid manifest");
HRN_INFO_PUT(
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/20181119-152900F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
strZ(manifestContent), .comment = "valid manifest copy");
// Create a manifest for the dependent that has references
manifestContent = strNewFmt(
"[backup]\n"
"backup-label=\"20181119-152900F_20181119-152909D\"\n"
"backup-timestamp-copy-start=0\n"
"backup-timestamp-start=0\n"
"backup-timestamp-stop=0\n"
"backup-type=\"diff\"\n"
"\n"
"[backup:db]\n"
TEST_BACKUP_DB2_11
TEST_MANIFEST_OPTION_ALL
TEST_MANIFEST_TARGET
TEST_MANIFEST_DB
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\","
"\"reference\":\"20181119-152900F\",\"size\":4,\"timestamp\":1565282114}\n"
"pg_data/testfile={\"checksum\":\"%s\",\"reference\":\"20181119-152900F\",\"size\":7,\"timestamp\":1565282114}\n"
"pg_data/testfile2={\"checksum\":\"%s\",\"size\":7,\"timestamp\":1565282114}\n"
"pg_data/testmissing="
"{\"checksum\":\"123473f470864e067ee3a22e64b47b0a1c356abc\",\"size\":7,\"timestamp\":1565282114}\n"
"pg_data/testother={\"checksum\":\"%s\",\"reference\":\"UNPROCESSEDBACKUP\",\"size\":7,\"timestamp\":1565282114}\n"
TEST_MANIFEST_FILE_DEFAULT
TEST_MANIFEST_LINK
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT,
strZ(fileChecksum), strZ(fileChecksum), strZ(fileChecksum));
// Write manifests for dependent backup
HRN_INFO_PUT(
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/20181119-152900F_20181119-152909D/" BACKUP_MANIFEST_FILE,
strZ(manifestContent), .comment = "manifest to dependent");
HRN_INFO_PUT(
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/20181119-152900F_20181119-152909D/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
strZ(manifestContent), .comment = "manifest copy to dependent");
HRN_STORAGE_PUT_Z(
storageRepoIdxWrite(0),
STORAGE_REPO_BACKUP "/20181119-152900F_20181119-152909D/pg_data/testfile2", fileContents,
.comment = "put valid file to dependent");
// Create an unprocessed backup label with a file that will be referenced in the dependent manifest
HRN_STORAGE_PUT_Z(
storageRepoIdxWrite(0),
STORAGE_REPO_BACKUP "/UNPROCESSEDBACKUP/pg_data/testother", fileContents, .modeFile = 0200,
.comment = "put unreadable file to unprocessed backup");
// Create in-progress backup
HRN_STORAGE_PATH_CREATE(
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/20181119-153000F",
.comment = "create empty backup path for newest backup so in-progress");
// Set log level to capture ranges
harnessLogLevelSet(logLevelDetail);
TEST_ERROR(cmdVerify(), RuntimeError, "7 fatal errors encountered, see log for details");
TEST_RESULT_LOG(
"P00 WARN: archive path '9.4-1' is empty\n"
"P00 WARN: path '11-2/0000000100000000' does not contain any valid WAL to be processed\n"
"P01 ERROR: [028]: invalid checksum "
"'11-2/0000000200000007/000000020000000700000FFD-a6e1a64f0813352bc2e97f116a1800377e17d2e4.gz'\n"
"P01 ERROR: [028]: invalid size "
"'11-2/0000000200000007/000000020000000700000FFF-ee161f898c9012dd0c28b3fd1e7140b9cf411306'\n"
"P01 ERROR: [039]: invalid result "
"11-2/0000000200000008/000000020000000800000003-656817043007aa2100c44c712bcb456db705dab9: [41] raised from "
"local-1 shim protocol: unable to open file '" TEST_PATH "/repo/archive/db/"
"11-2/0000000200000008/000000020000000800000003-656817043007aa2100c44c712bcb456db705dab9' for read:"
" [13] Permission denied\n"
" [FileOpenError] on retry after 0ms\n"
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/20181119-152800F/backup.manifest' for read\n"
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/20181119-152800F/backup.manifest.copy'"
" for read\n"
"P00 WARN: manifest missing for '20181119-152800F' - backup may have expired\n"
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/20181119-152810F/backup.manifest.copy'"
" for read\n"
"P00 ERROR: [028]: backup '20181119-152810F' manifest does not contain any target files to verify\n"
"P01 ERROR: [028]: invalid checksum '20181119-152900F/pg_data/PG_VERSION'\n"
"P01 ERROR: [028]: file missing '20181119-152900F_20181119-152909D/pg_data/testmissing'\n"
"P00 WARN: unable to open missing file '" TEST_PATH "/repo/backup/db/20181119-153000F/backup.manifest' for read\n"
"P00 INFO: backup '20181119-153000F' appears to be in progress, skipping\n"
"P01 ERROR: [039]: invalid result UNPROCESSEDBACKUP/pg_data/testother: [41] raised from local-1 shim protocol:"
" unable to open file '" TEST_PATH "/repo/backup/db/UNPROCESSEDBACKUP/pg_data/testother' for read: [13]"
" Permission denied\n"
" [FileOpenError] on retry after 0ms\n"
"P00 DETAIL: archiveId: 11-2, wal start: 000000020000000700000FFD, wal stop: 000000020000000800000000\n"
"P00 DETAIL: archiveId: 11-2, wal start: 000000020000000800000002, wal stop: 000000020000000800000003\n"
"P00 DETAIL: archiveId: 11-2, wal start: 000000030000000000000000, wal stop: 000000030000000000000001\n"
"P00 INFO: Results:\n"
" archiveId: 9.4-1, total WAL checked: 0, total valid WAL: 0\n"
" archiveId: 11-2, total WAL checked: 8, total valid WAL: 5\n"
" missing: 0, checksum invalid: 1, size invalid: 1, other: 1\n"
" backup: 20181119-152800F, status: manifest missing, total files checked: 0, total valid files: 0\n"
" backup: 20181119-152810F, status: invalid, total files checked: 0, total valid files: 0\n"
" backup: 20181119-152900F, status: invalid, total files checked: 3, total valid files: 2\n"
" missing: 0, checksum invalid: 1, size invalid: 0, other: 0\n"
" backup: 20181119-152900F_20181119-152909D, status: invalid, total files checked: 5, "
"total valid files: 2\n"
" missing: 1, checksum invalid: 1, size invalid: 0, other: 1\n"
" backup: 20181119-153000F, status: in-progress, total files checked: 0, total valid files: 0");
harnessLogLevelReset();
}
// *****************************************************************************************************************************
if (testBegin("cmdVerify()"))
{
// Load Parameters
StringList *argList = strLstDup(argListBase);
HRN_CFG_LOAD(cfgCmdVerify, argList);
#define TEST_BACKUP_DB1_CURRENT_FULL3_DIFF1 \
"20181119-152900F_20181119-152909D={" \
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\"," \
"\"backup-archive-start\":\"000000010000000000000006\",\"backup-archive-stop\":\"000000010000000000000007\"," \
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186," \
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900," \
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\"," \
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false," \
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
#define TEST_BACKUP_DB2_CURRENT_FULL1 \
"20201119-163000F={" \
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\"," \
"\"backup-archive-start\":\"000000020000000000000001\",\"backup-archive-stop\":\"000000020000000000000001\"," \
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186," \
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900," \
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\"," \
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false," \
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("prior backup verification incomplete - referenced file checked");
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE, TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE, .comment = "valid archive.info");
HRN_INFO_PUT(
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, TEST_ARCHIVE_INFO_MULTI_HISTORY_BASE,
.comment = "valid archive.info.copy");
#define TEST_BACKUP_INFO \
"[backup:current]\n" \
TEST_BACKUP_DB1_CURRENT_FULL3 \
TEST_BACKUP_DB1_CURRENT_FULL3_DIFF1 \
TEST_BACKUP_DB2_CURRENT_FULL1 \
"\n" \
"[db]\n" \
TEST_BACKUP_DB2_11 \
"\n" \
"[db:history]\n" \
TEST_BACKUP_DB1_HISTORY \
"\n" \
TEST_BACKUP_DB2_HISTORY
HRN_INFO_PUT(storageRepoWrite(), INFO_BACKUP_PATH_FILE, TEST_BACKUP_INFO);
HRN_INFO_PUT(storageRepoWrite(), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, TEST_BACKUP_INFO);
// Create valid full backup for DB1
#define TEST_MANIFEST_FULL_DB1 \
TEST_MANIFEST_HEADER \
TEST_MANIFEST_DB_94 \
TEST_MANIFEST_OPTION_ALL \
TEST_MANIFEST_TARGET \
TEST_MANIFEST_DB \
TEST_MANIFEST_FILE \
TEST_MANIFEST_FILE_DEFAULT \
TEST_MANIFEST_LINK \
TEST_MANIFEST_LINK_DEFAULT \
TEST_MANIFEST_PATH \
TEST_MANIFEST_PATH_DEFAULT
// Write manifests for full backup
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152900F/" BACKUP_MANIFEST_FILE, TEST_MANIFEST_FULL_DB1,
.comment = "valid manifest - full");
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152900F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT, TEST_MANIFEST_FULL_DB1,
.comment = "valid manifest copy - full");
// Create valid diff backup for DB1
#define TEST_MANIFEST_DIFF_DB1 \
TEST_MANIFEST_HEADER \
TEST_MANIFEST_DB_94 \
TEST_MANIFEST_OPTION_ALL \
TEST_MANIFEST_TARGET \
TEST_MANIFEST_DB \
"\n" \
"[target:file]\n" \
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"reference\":\"20181119-152900F\"" \
",\"size\":4,\"timestamp\":1565282114}\n" \
TEST_MANIFEST_FILE_DEFAULT \
TEST_MANIFEST_LINK \
TEST_MANIFEST_LINK_DEFAULT \
TEST_MANIFEST_PATH \
TEST_MANIFEST_PATH_DEFAULT
// Write manifests for diff backup
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152900F_20181119-152909D/" BACKUP_MANIFEST_FILE,
TEST_MANIFEST_DIFF_DB1, .comment = "valid manifest - diff");
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152900F_20181119-152909D/" BACKUP_MANIFEST_FILE INFO_COPY_EXT, TEST_MANIFEST_DIFF_DB1, .comment = "valid manifest copy - diff");
// Put the file referenced by both backups into the full backup
HRN_STORAGE_PUT_Z(storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152900F/pg_data/PG_VERSION", fileContents);
TEST_ERROR(cmdVerify(), RuntimeError, "2 fatal errors encountered, see log for details");
// The error for the referenced file is logged twice because it is checked again by the second backup since the first backup
// verification had not yet completed before the second backup verification began
TEST_RESULT_LOG(
"P00 WARN: no archives exist in the repo\n"
"P01 ERROR: [028]: invalid checksum '20181119-152900F/pg_data/PG_VERSION'\n"
"P01 ERROR: [028]: invalid checksum '20181119-152900F/pg_data/PG_VERSION'\n"
"P00 INFO: Results:\n"
" archiveId: none found\n"
" backup: 20181119-152900F, status: invalid, total files checked: 1, total valid files: 0\n"
" missing: 0, checksum invalid: 1, size invalid: 0, other: 0\n"
" backup: 20181119-152900F_20181119-152909D, status: invalid, total files checked: 1, total valid files: 0"
"\n"
" missing: 0, checksum invalid: 1, size invalid: 0, other: 0");
//--------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("valid backup, prior backup verification complete - referenced file not checked");
// Set process max to 1 and add more files to check so first backup completes before second is checked
hrnCfgArgRawZ(argList, cfgOptProcessMax, "1");
HRN_CFG_LOAD(cfgCmdVerify, argList);
String *manifestContent = strNewFmt(
TEST_MANIFEST_HEADER
TEST_MANIFEST_DB_94
TEST_MANIFEST_OPTION_ALL
TEST_MANIFEST_TARGET
TEST_MANIFEST_DB
TEST_MANIFEST_FILE
"pg_data/base/1/555_init={\"checksum\":\"%s\",\"size\":1,\"timestamp\":1565282114}\n"
"pg_data/base/1/555_init.1={\"size\":0,\"timestamp\":1565282114}\n"
TEST_MANIFEST_FILE_DEFAULT
TEST_MANIFEST_LINK
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT,
strZ(fileChecksum));
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152900F/" BACKUP_MANIFEST_FILE, strZ(manifestContent),
.comment = "valid manifest - full");
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152900F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT, strZ(manifestContent),
.comment = "valid manifest copy - full");
HRN_STORAGE_PUT_Z(
storageRepoWrite(),
STORAGE_REPO_BACKUP "/20181119-152900F/pg_data/base/1/555_init", fileContents, .comment = "invalid size");
// Diff manifest
manifestContent = strNewZ(
TEST_MANIFEST_HEADER
TEST_MANIFEST_DB_94
TEST_MANIFEST_OPTION_ALL
TEST_MANIFEST_TARGET
TEST_MANIFEST_DB
"\n"
"[target:file]\n"
"pg_data/PG_VERSION={\"checksum\":\"184473f470864e067ee3a22e64b47b0a1c356f29\",\"reference\":\"20181119-152900F\""
",\"size\":4,\"timestamp\":1565282114}\n"
TEST_MANIFEST_FILE_DEFAULT
TEST_MANIFEST_LINK
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT);
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152900F_20181119-152909D/" BACKUP_MANIFEST_FILE,
strZ(manifestContent), .comment = "valid manifest - diff");
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20181119-152900F_20181119-152909D/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
strZ(manifestContent), .comment = "valid manifest copy - diff");
// Create valid full backup and valid diff backup
manifestContent = strNewFmt(
TEST_MANIFEST_HEADER
"\n"
"[backup:db]\n"
TEST_BACKUP_DB2_11
TEST_MANIFEST_OPTION_ALL
TEST_MANIFEST_TARGET
TEST_MANIFEST_DB
"\n"
"[target:file]\n"
"pg_data/validfile={\"checksum\":\"%s\",\"size\":%u,\"timestamp\":1565282114}\n"
TEST_MANIFEST_FILE_DEFAULT
TEST_MANIFEST_LINK
TEST_MANIFEST_LINK_DEFAULT
TEST_MANIFEST_PATH
TEST_MANIFEST_PATH_DEFAULT,
strZ(fileChecksum), (unsigned int)fileSize);
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20201119-163000F/" BACKUP_MANIFEST_FILE, strZ(manifestContent),
.comment = "valid manifest - full");
HRN_INFO_PUT(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20201119-163000F/" BACKUP_MANIFEST_FILE INFO_COPY_EXT, strZ(manifestContent),
.comment = "valid manifest copy - full");
HRN_STORAGE_PUT_Z(
storageRepoWrite(), STORAGE_REPO_BACKUP "/20201119-163000F/pg_data/validfile", fileContents, .comment = "valid file");
// Create WAL file with just header info and small WAL size
Buffer *walBuffer = bufNew((size_t)(1024 * 1024));
bufUsedSet(walBuffer, bufSize(walBuffer));
memset(bufPtr(walBuffer), 0, bufSize(walBuffer));
hrnPgWalToBuffer((PgWal){.version = PG_VERSION_11, .size = 1024 * 1024}, walBuffer);
const char *walBufferSha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer)));
HRN_STORAGE_PUT(
storageRepoWrite(),
strZ(strNewFmt(STORAGE_REPO_ARCHIVE "/11-2/0000000200000000/000000020000000000000001-%s", walBufferSha1)), walBuffer,
.comment = "valid WAL");
TEST_ERROR(cmdVerify(), RuntimeError, "3 fatal errors encountered, see log for details");
TEST_RESULT_LOG(
"P01 ERROR: [028]: invalid checksum '20181119-152900F/pg_data/PG_VERSION'\n"
"P01 ERROR: [028]: invalid size '20181119-152900F/pg_data/base/1/555_init'\n"
"P01 ERROR: [028]: file missing '20181119-152900F/pg_data/base/1/555_init.1'\n"
"P00 INFO: Results:\n"
" archiveId: 11-2, total WAL checked: 1, total valid WAL: 1\n"
" missing: 0, checksum invalid: 0, size invalid: 0, other: 0\n"
" backup: 20181119-152900F, status: invalid, total files checked: 3, total valid files: 0\n"
" missing: 1, checksum invalid: 1, size invalid: 1, other: 0\n"
" backup: 20181119-152900F_20181119-152909D, status: invalid, total files checked: 1, total valid files: 0\n"
" missing: 0, checksum invalid: 1, size invalid: 0, other: 0\n"
" backup: 20201119-163000F, status: valid, total files checked: 1, total valid files: 1\n"
" missing: 0, checksum invalid: 0, size invalid: 0, other: 0");
}
FUNCTION_HARNESS_RETURN_VOID();
}