You've already forked pgbackrest
mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-07-09 00:45:49 +02:00
It seems better to use TEST_PATH in combination with a constant string rather than have a number of different path constants. This improves readability and reduces confusion about which constant should be used.
1090 lines
54 KiB
C
1090 lines
54 KiB
C
/***********************************************************************************************************************************
|
|
Test Stanza Commands
|
|
***********************************************************************************************************************************/
|
|
#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"
|
|
|
|
/***********************************************************************************************************************************
|
|
Test Run
|
|
***********************************************************************************************************************************/
|
|
void
|
|
testRun(void)
|
|
{
|
|
FUNCTION_HARNESS_VOID();
|
|
|
|
// Create storage objects for the testing location and for the harness directory for items such as logs, stop files, etc
|
|
Storage *storageTest = storagePosixNewP(TEST_PATH_STR, .write = true);
|
|
Storage *storageHrn = storagePosixNewP(HRN_PATH_STR, .write = true);
|
|
|
|
#define TEST_STANZA "db"
|
|
#define TEST_STANZA_OTHER "otherstanza"
|
|
|
|
StringList *argListBase = strLstNew();
|
|
hrnCfgArgRawBool(argListBase, cfgOptOnline, false);
|
|
hrnCfgArgRawZ(argListBase, cfgOptStanza, TEST_STANZA);
|
|
hrnCfgArgRawZ(argListBase, cfgOptPgPath, TEST_PATH "/pg");
|
|
hrnCfgArgRawZ(argListBase, cfgOptRepoPath, TEST_PATH "/repo");
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("cmdStanzaCreate(), checkStanzaInfo(), cmdStanzaDelete()"))
|
|
{
|
|
TEST_TITLE("stanza-create: repo option not valid");
|
|
|
|
// Load Parameters
|
|
StringList *argList = strLstDup(argListBase);
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo2");
|
|
hrnCfgArgRawZ(argList, cfgOptRepo, "2");
|
|
|
|
TEST_ERROR(
|
|
hrnCfgLoadP(cfgCmdStanzaCreate, argList), OptionInvalidError, "option 'repo' not valid for command 'stanza-create'");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-create: stop file error");
|
|
|
|
HRN_CFG_LOAD(cfgCmdStanzaCreate, argListBase);
|
|
|
|
// Create the stop file, test, then remove the stop file
|
|
HRN_STORAGE_PUT_EMPTY(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))));
|
|
TEST_ERROR(cmdStanzaCreate(), StopError, "stop file exists for stanza db");
|
|
HRN_STORAGE_REMOVE(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))));
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-create: validate info files created");
|
|
|
|
argList = strLstDup(argListBase);
|
|
HRN_CFG_LOAD(cfgCmdStanzaCreate, argList);
|
|
|
|
// Create pg_control
|
|
HRN_STORAGE_PUT(
|
|
storagePgWrite(), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL,
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_96, .systemId = 6569239123849665679}));
|
|
|
|
TEST_RESULT_VOID(cmdStanzaCreate(), "stanza create - one repo, no files exist");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
HRN_INFO_PUT(
|
|
storageHrn, "test.info",
|
|
"[db]\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.6\"}\n",
|
|
.comment = "put archive info to test file");
|
|
|
|
TEST_RESULT_BOOL(
|
|
(bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_ARCHIVE_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), STRDEF(INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT)))) &&
|
|
bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_ARCHIVE_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageHrn, STRDEF("test.info"))))),
|
|
true, "test and stanza archive info files are equal");
|
|
|
|
HRN_INFO_PUT(
|
|
storageHrn, "test.info",
|
|
"[db]\n"
|
|
"db-catalog-version=201608131\n"
|
|
"db-control-version=960\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665679,"
|
|
"\"db-version\":\"9.6\"}\n",
|
|
.comment = "put backup info to test file");
|
|
|
|
TEST_RESULT_BOOL(
|
|
(bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), STRDEF(INFO_BACKUP_PATH_FILE INFO_COPY_EXT)))) &&
|
|
bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageHrn, STRDEF("test.info"))))),
|
|
true, "test and stanza backup info files are equal");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("cmdStanzaCreate success - multi-repo and encryption");
|
|
|
|
argList = strLstDup(argListBase);
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo2");
|
|
hrnCfgArgKeyRawStrId(argList, cfgOptRepoCipherType, 2, cipherTypeAes256Cbc);
|
|
hrnCfgEnvKeyRawZ(cfgOptRepoCipherPass, 2, "12345678");
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 3, TEST_PATH "/repo3");
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 4, TEST_PATH "/repo4");
|
|
hrnCfgArgKeyRawStrId(argList, cfgOptRepoCipherType, 4, cipherTypeAes256Cbc);
|
|
hrnCfgEnvKeyRawZ(cfgOptRepoCipherPass, 4, "87654321");
|
|
HRN_CFG_LOAD(cfgCmdStanzaCreate, argList);
|
|
|
|
TEST_RESULT_VOID(cmdStanzaCreate(), "stanza create - files already exist on repo1 and both are valid");
|
|
TEST_RESULT_LOG(
|
|
"P00 INFO: stanza-create for stanza 'db' on repo1\n"
|
|
"P00 INFO: stanza 'db' already exists on repo1 and is valid\n"
|
|
"P00 INFO: stanza-create for stanza 'db' on repo2\n"
|
|
"P00 INFO: stanza-create for stanza 'db' on repo3\n"
|
|
"P00 INFO: stanza-create for stanza 'db' on repo4");
|
|
|
|
InfoArchive *infoArchive = NULL;
|
|
TEST_ASSIGN(
|
|
infoArchive, infoArchiveLoadFile(storageRepoIdx(1), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeAes256Cbc,
|
|
STRDEF("12345678")), "load archive info from encrypted repo2");
|
|
TEST_RESULT_PTR_NE(infoArchiveCipherPass(infoArchive), NULL, "cipher sub set");
|
|
|
|
InfoBackup *infoBackup = NULL;
|
|
TEST_ASSIGN(
|
|
infoBackup, infoBackupLoadFile(storageRepoIdx(1), INFO_BACKUP_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF("12345678")),
|
|
"load backup info from encrypted repo2");
|
|
TEST_RESULT_PTR_NE(infoBackupCipherPass(infoBackup), NULL, "cipher sub set");
|
|
|
|
TEST_RESULT_BOOL(
|
|
strEq(infoArchiveCipherPass(infoArchive), infoBackupCipherPass(infoBackup)), false,
|
|
"cipher sub different for archive and backup");
|
|
|
|
// Confirm non-encrypted repo created successfully
|
|
TEST_ASSIGN(
|
|
infoArchive, infoArchiveLoadFile(storageRepoIdx(2), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeNone, NULL),
|
|
"load archive info from repo3");
|
|
TEST_RESULT_PTR(infoArchiveCipherPass(infoArchive), NULL, "archive cipher sub not set on non-encrypted repo");
|
|
|
|
TEST_ASSIGN(
|
|
infoBackup, infoBackupLoadFile(storageRepoIdx(2), INFO_BACKUP_PATH_FILE_STR, cipherTypeNone, NULL),
|
|
"load backup info from repo3");
|
|
TEST_RESULT_PTR(infoBackupCipherPass(infoBackup), NULL, "backup cipher sub not set on non-encrypted repo");
|
|
|
|
// Confirm other repo encrypted with different password
|
|
TEST_ASSIGN(
|
|
infoArchive, infoArchiveLoadFile(storageRepoIdx(3), INFO_ARCHIVE_PATH_FILE_STR, cipherTypeAes256Cbc,
|
|
STRDEF("87654321")), "load archive info from encrypted repo4");
|
|
TEST_RESULT_PTR_NE(infoArchiveCipherPass(infoArchive), NULL, "cipher sub set");
|
|
|
|
TEST_ASSIGN(
|
|
infoBackup, infoBackupLoadFile(storageRepoIdx(3), INFO_BACKUP_PATH_FILE_STR, cipherTypeAes256Cbc, STRDEF("87654321")),
|
|
"load backup info from encrypted repo4");
|
|
TEST_RESULT_PTR_NE(infoBackupCipherPass(infoBackup), NULL, "cipher sub set");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("cmdStanzaCreate missing files - multi-repo and encryption");
|
|
|
|
// Remove backup.info on repo1
|
|
TEST_STORAGE_EXISTS(storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE, .remove = true);
|
|
|
|
// Remove archive.info on repo2
|
|
TEST_STORAGE_EXISTS(storageRepoIdxWrite(1), INFO_ARCHIVE_PATH_FILE, .remove = true);
|
|
|
|
// Remove info files on repo3
|
|
TEST_STORAGE_EXISTS(storageRepoIdxWrite(2), INFO_ARCHIVE_PATH_FILE, .remove = true);
|
|
TEST_STORAGE_EXISTS(storageRepoIdxWrite(2), INFO_BACKUP_PATH_FILE, .remove = true);
|
|
|
|
// Remove copy files repo4
|
|
TEST_STORAGE_EXISTS(storageRepoIdxWrite(3), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, .remove = true);
|
|
TEST_STORAGE_EXISTS(storageRepoIdxWrite(3), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, .remove = true);
|
|
|
|
TEST_RESULT_VOID(cmdStanzaCreate(), "stanza create - success with missing files");
|
|
TEST_RESULT_LOG(
|
|
"P00 INFO: stanza-create for stanza 'db' on repo1\n"
|
|
"P00 INFO: stanza-create for stanza 'db' on repo2\n"
|
|
"P00 INFO: stanza-create for stanza 'db' on repo3\n"
|
|
"P00 INFO: stanza-create for stanza 'db' on repo4");
|
|
|
|
TEST_RESULT_BOOL(
|
|
bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), STRDEF(INFO_BACKUP_PATH_FILE INFO_COPY_EXT)))),
|
|
true, "backup.info recreated repo1 from backup.info.copy");
|
|
TEST_RESULT_BOOL(
|
|
bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(1), INFO_ARCHIVE_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(1), STRDEF(INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT)))),
|
|
true, "archive.info repo2 recreated from archive.info.copy");
|
|
TEST_RESULT_BOOL(
|
|
(bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(2), INFO_BACKUP_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(2), STRDEF(INFO_BACKUP_PATH_FILE INFO_COPY_EXT)))) &&
|
|
bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(2), INFO_ARCHIVE_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(2), STRDEF(INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT))))),
|
|
true, "info files recreated repo3 from copy files");
|
|
TEST_RESULT_BOOL(
|
|
(bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(3), INFO_BACKUP_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(3), STRDEF(INFO_BACKUP_PATH_FILE INFO_COPY_EXT)))) &&
|
|
bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(3), INFO_ARCHIVE_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(3), STRDEF(INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT))))),
|
|
true, "copy files recreated repo4 from info files");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("cmdStanzaDelete - multi-repo and encryption, delete");
|
|
|
|
StringList *argListCmd = strLstNew();
|
|
hrnCfgArgKeyRawZ(argListCmd, cfgOptRepoPath, 1, TEST_PATH "/repo");
|
|
hrnCfgArgKeyRawZ(argListCmd, cfgOptRepoPath, 2, TEST_PATH "/repo2");
|
|
hrnCfgArgKeyRawZ(argListCmd, cfgOptRepoPath, 3, TEST_PATH "/repo3");
|
|
hrnCfgArgKeyRawZ(argListCmd, cfgOptRepoPath, 4, TEST_PATH "/repo4");
|
|
hrnCfgArgRawZ(argListCmd, cfgOptStanza, TEST_STANZA);
|
|
hrnCfgArgRawZ(argListCmd, cfgOptPgPath, TEST_PATH "/pg");
|
|
|
|
TEST_ERROR(
|
|
hrnCfgLoadP(cfgCmdStanzaDelete, argListCmd), OptionRequiredError,
|
|
"stanza-delete command requires option: repo\n"
|
|
"HINT: this command requires a specific repository to operate on");
|
|
|
|
// Add the repo option
|
|
StringList *argListDelete = strLstDup(argListCmd);
|
|
hrnCfgArgRawZ(argListDelete, cfgOptRepo, "4");
|
|
HRN_CFG_LOAD(cfgCmdStanzaDelete, argListDelete);
|
|
|
|
TEST_ERROR(
|
|
cmdStanzaDelete(), FileMissingError,
|
|
"stop file does not exist for stanza 'db'\n"
|
|
"HINT: has the pgbackrest stop command been run on this server for this stanza?");
|
|
|
|
// Create the stop file
|
|
HRN_STORAGE_PUT_EMPTY(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))));
|
|
|
|
TEST_STORAGE_LIST(
|
|
storageTest, "repo4",
|
|
"archive/\n"
|
|
"archive/db/\n"
|
|
"archive/db/archive.info\n"
|
|
"archive/db/archive.info.copy\n"
|
|
"backup/\n"
|
|
"backup/db/\n"
|
|
"backup/db/backup.info\n"
|
|
"backup/db/backup.info.copy\n",
|
|
.comment = "stanza exists in repo4");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaDelete(), "stanza delete - repo4");
|
|
|
|
TEST_STORAGE_LIST(storageTest, "repo4", "archive/\nbackup/\n", .comment = "stanza deleted");
|
|
|
|
TEST_RESULT_BOOL(
|
|
storageExistsP(storageHrn, lockStopFileName(cfgOptionStr(cfgOptStanza))), false, "confirm stop file removed");
|
|
|
|
// Remove the cipher pass environment variable otherwise stanza-create will recreate the stanza
|
|
hrnCfgEnvKeyRemoveRaw(cfgOptRepoCipherPass, 4);
|
|
|
|
// Stanza with directories only
|
|
argListDelete = strLstDup(argListCmd);
|
|
hrnCfgArgRawZ(argListDelete, cfgOptRepo, "3");
|
|
HRN_CFG_LOAD(cfgCmdStanzaDelete, argListDelete);
|
|
|
|
HRN_STORAGE_PATH_CREATE(
|
|
storageRepoIdxWrite(2), STORAGE_REPO_ARCHIVE "/9.6-1/1234567812345678", .comment = "create archive sub directory");
|
|
HRN_STORAGE_PATH_CREATE(
|
|
storageRepoIdxWrite(2), STORAGE_REPO_BACKUP "/20190708-154306F", .comment = "create backup sub directory");
|
|
HRN_STORAGE_PUT_EMPTY(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))), .comment = "create stop file");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaDelete(), "stanza delete - repo3 - sub directories only");
|
|
|
|
TEST_STORAGE_LIST(storageTest, "repo3", "archive/\nbackup/\n", .comment = "stanza deleted");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("cmdStanzaCreate errors");
|
|
|
|
argList = strLstDup(argListBase);
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo2");
|
|
hrnCfgArgKeyRawStrId(argList, cfgOptRepoCipherType, 2, cipherTypeAes256Cbc);
|
|
hrnCfgEnvKeyRawZ(cfgOptRepoCipherPass, 2, "12345678");
|
|
HRN_CFG_LOAD(cfgCmdStanzaCreate, argList);
|
|
|
|
// Backup files removed - archive.info and archive.info.copy exist repo2
|
|
TEST_STORAGE_EXISTS(
|
|
storageRepoIdxWrite(1), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, .remove = true,
|
|
.comment = "repo2: remove backup.info.copy");
|
|
TEST_STORAGE_EXISTS(
|
|
storageRepoIdxWrite(1), INFO_BACKUP_PATH_FILE, .remove = true, .comment = "repo2: remove backup.info");
|
|
|
|
TEST_ERROR(
|
|
cmdStanzaCreate(), FileMissingError,
|
|
"archive.info exists but backup.info is missing on repo2\n"
|
|
"HINT: this may be a symptom of repository corruption!");
|
|
TEST_RESULT_LOG(
|
|
"P00 INFO: stanza-create for stanza 'db' on repo1\n"
|
|
"P00 INFO: stanza 'db' already exists on repo1 and is valid\n"
|
|
"P00 INFO: stanza-create for stanza 'db' on repo2");
|
|
|
|
// Archive files removed - backup.info and backup.info.copy exist repo1
|
|
TEST_STORAGE_EXISTS(
|
|
storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, .remove = true,
|
|
.comment = "repo1: remove archive.info.copy");
|
|
TEST_STORAGE_EXISTS(
|
|
storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE, .remove = true, .comment = "repo1: remove archive.info");
|
|
|
|
TEST_ERROR(
|
|
cmdStanzaCreate(), FileMissingError,
|
|
"backup.info exists but archive.info is missing on repo1\n"
|
|
"HINT: this may be a symptom of repository corruption!");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
// Delete the last repo so only 1 remains
|
|
argListDelete = strLstDup(argListCmd);
|
|
hrnCfgArgRawZ(argListDelete, cfgOptRepo, "2");
|
|
HRN_CFG_LOAD(cfgCmdStanzaDelete, argListDelete);
|
|
|
|
HRN_STORAGE_PUT_EMPTY(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))), .comment = "create stop file");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaDelete(), "stanza delete - only 1 remains");
|
|
|
|
// Remove the cipher pass environment variable otherwise stanza-create will recreate the stanza
|
|
hrnCfgEnvKeyRemoveRaw(cfgOptRepoCipherPass, 2);
|
|
|
|
argList = strLstDup(argListBase);
|
|
HRN_CFG_LOAD(cfgCmdStanzaCreate, argList);
|
|
|
|
// Archive files removed - backup.info exists
|
|
TEST_STORAGE_EXISTS(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, .remove = true,
|
|
.comment = "repo1: remove backup.info.copy");
|
|
TEST_ERROR(
|
|
cmdStanzaCreate(), FileMissingError,
|
|
"backup.info exists but archive.info is missing on repo1\n"
|
|
"HINT: this may be a symptom of repository corruption!");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
// Archive files removed - backup.info.copy exists, backup.info moved to backup.info.copy
|
|
HRN_STORAGE_MOVE(storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE, INFO_BACKUP_PATH_FILE INFO_COPY_EXT);
|
|
TEST_ERROR(
|
|
cmdStanzaCreate(), FileMissingError,
|
|
"backup.info exists but archive.info is missing on repo1\n"
|
|
"HINT: this may be a symptom of repository corruption!");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
// Backup files removed - archive.info file exists
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE,
|
|
"[db]\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.6\"}\n",
|
|
.comment = "put archive info to file repo1");
|
|
TEST_STORAGE_EXISTS(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, .remove = true,
|
|
.comment = "repo1: remove backup.info.copy");
|
|
TEST_ERROR(
|
|
cmdStanzaCreate(), FileMissingError,
|
|
"archive.info exists but backup.info is missing on repo1\n"
|
|
"HINT: this may be a symptom of repository corruption!");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
// Backup files removed - archive.info.copy file exists (renamed from archive.info)
|
|
HRN_STORAGE_MOVE(storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE, INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT);
|
|
TEST_ERROR(
|
|
cmdStanzaCreate(), FileMissingError,
|
|
"archive.info exists but backup.info is missing on repo1\n"
|
|
"HINT: this may be a symptom of repository corruption!");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("checkStanzaInfo() - already checked in checkTest so just a sanity check here");
|
|
|
|
// Create a corrupted backup file - db id
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE,
|
|
"[db]\n"
|
|
"db-catalog-version=201608131\n"
|
|
"db-control-version=960\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"2={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665679,"
|
|
"\"db-version\":\"9.6\"}\n",
|
|
.comment = "put backup info to file - bad db-id");
|
|
|
|
TEST_ERROR(
|
|
cmdStanzaCreate(), FileInvalidError,
|
|
"backup info file and archive info file do not match\n"
|
|
"archive: id = 1, version = 9.6, system-id = 6569239123849665679\n"
|
|
"backup : id = 2, version = 9.6, system-id = 6569239123849665679\n"
|
|
"HINT: this may be a symptom of repository corruption!");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("archive.info file and backup.info files that match but do not match the current database version");
|
|
|
|
// Copy files may or may not exist - remove
|
|
HRN_STORAGE_REMOVE(
|
|
storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT, .comment = "repo1: remove archive.info.copy");
|
|
HRN_STORAGE_REMOVE(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE INFO_COPY_EXT, .comment = "repo1: remove backup.info.copy");
|
|
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE,
|
|
"[db]\n"
|
|
"db-catalog-version=201510051\n"
|
|
"db-control-version=942\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.5\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6569239123849665679,"
|
|
"\"db-version\":\"9.5\"}\n");
|
|
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE,
|
|
"[db]\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.5\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.5\"}\n");
|
|
|
|
TEST_ERROR(
|
|
cmdStanzaCreate(), FileInvalidError,
|
|
"backup and archive info files exist but do not match the database\n"
|
|
"HINT: is this the correct stanza?\n"
|
|
"HINT: did an error occur during stanza-upgrade?");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("archive.info and backup.info files that match but do not match the current database system-id");
|
|
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE,
|
|
"[db]\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665999\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6569239123849665999,\"db-version\":\"9.6\"}\n");
|
|
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE,
|
|
"[db]\n"
|
|
"db-catalog-version=201608131\n"
|
|
"db-control-version=960\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665999\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665999,"
|
|
"\"db-version\":\"9.6\"}\n");
|
|
|
|
TEST_ERROR(
|
|
cmdStanzaCreate(), FileInvalidError,
|
|
"backup and archive info files exist but do not match the database\n"
|
|
"HINT: is this the correct stanza?\n"
|
|
"HINT: did an error occur during stanza-upgrade?");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
// Remove the info files and add sub directory to backup
|
|
TEST_STORAGE_EXISTS(storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE, .remove = true);
|
|
TEST_STORAGE_EXISTS(storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE, .remove = true);
|
|
HRN_STORAGE_PATH_CREATE(
|
|
storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/backup.history", .comment = "create directory in backup");
|
|
|
|
TEST_ERROR(cmdStanzaCreate(), PathNotEmptyError, "backup directory not empty");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
// File in archive, directory in backup
|
|
HRN_STORAGE_PUT_Z(storageRepoIdxWrite(0), STORAGE_REPO_ARCHIVE "/somefile", "some content");
|
|
TEST_ERROR(cmdStanzaCreate(), PathNotEmptyError, "backup directory and/or archive directory not empty");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
// File in archive, backup empty
|
|
HRN_STORAGE_PATH_REMOVE(storageRepoIdxWrite(0), STORAGE_REPO_BACKUP "/backup.history", .comment = "remove backup subdir");
|
|
TEST_ERROR(cmdStanzaCreate(), PathNotEmptyError, "archive directory not empty");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("repeat last test using --force (deprecated)");
|
|
|
|
hrnCfgArgRawBool(argList, cfgOptForce, true);
|
|
HRN_CFG_LOAD(cfgCmdStanzaCreate, argList);
|
|
TEST_ERROR(cmdStanzaCreate(), PathNotEmptyError, "archive directory not empty");
|
|
TEST_RESULT_LOG(
|
|
"P00 WARN: option --force is no longer supported\n"
|
|
"P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
}
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("pgValidate(), online=y"))
|
|
{
|
|
// Load Parameters
|
|
StringList *argList = strLstNew();
|
|
hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA);
|
|
hrnCfgArgRawZ(argList, cfgOptPgPath, TEST_PATH "/pg");
|
|
hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH "/repo");
|
|
HRN_CFG_LOAD(cfgCmdStanzaCreate, argList);
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("pgControl and database match");
|
|
|
|
// Create pg_control
|
|
HRN_STORAGE_PUT(
|
|
storagePgWrite(), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL,
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_92, .systemId = 6569239123849665699}));
|
|
|
|
harnessPqScriptSet((HarnessPq [])
|
|
{
|
|
HRNPQ_MACRO_OPEN_GE_92(1, "dbname='postgres' port=5432", PG_VERSION_92, TEST_PATH "/pg", false, NULL, NULL),
|
|
HRNPQ_MACRO_DONE()
|
|
});
|
|
|
|
TEST_RESULT_VOID(cmdStanzaCreate(), "stanza create - db online");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'db' on repo1");
|
|
TEST_STORAGE_LIST(
|
|
storageTest, TEST_PATH "/repo",
|
|
"archive/\n"
|
|
"archive/db/\n"
|
|
"archive/db/archive.info\n"
|
|
"archive/db/archive.info.copy\n"
|
|
"backup/\n"
|
|
"backup/db/\n"
|
|
"backup/db/backup.info\n"
|
|
"backup/db/backup.info.copy\n",
|
|
.comment = "stanza created");
|
|
|
|
HRN_CFG_LOAD(cfgCmdStanzaUpgrade, argList);
|
|
harnessPqScriptSet((HarnessPq [])
|
|
{
|
|
HRNPQ_MACRO_OPEN_GE_92(1, "dbname='postgres' port=5432", PG_VERSION_92, TEST_PATH "/pg", false, NULL, NULL),
|
|
HRNPQ_MACRO_DONE()
|
|
});
|
|
|
|
TEST_RESULT_VOID(cmdStanzaUpgrade(), "stanza upgrade - db online");
|
|
TEST_RESULT_LOG(
|
|
"P00 INFO: stanza-upgrade for stanza 'db' on repo1\n"
|
|
"P00 INFO: stanza 'db' on repo1 is already up to date");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("pg_control and version mismatch");
|
|
|
|
// Create pg_control with different version
|
|
HRN_STORAGE_PUT(
|
|
storagePgWrite(), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL,
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_91, .systemId = 6569239123849665699}));
|
|
|
|
harnessPqScriptSet((HarnessPq [])
|
|
{
|
|
HRNPQ_MACRO_OPEN_GE_92(1, "dbname='postgres' port=5432", PG_VERSION_92, TEST_PATH "/pg", false, NULL, NULL),
|
|
HRNPQ_MACRO_DONE()
|
|
});
|
|
|
|
TEST_ERROR(
|
|
pgValidate(), DbMismatchError,
|
|
"version '" PG_VERSION_92_STR "' and path '" TEST_PATH "/pg' queried from cluster do not match version '"
|
|
PG_VERSION_91_STR "' and '" TEST_PATH "/pg' read from '" TEST_PATH "/pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL "'\n"
|
|
"HINT: the pg1-path and pg1-port settings likely reference different clusters.");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("pg_control and path mismatch");
|
|
|
|
// Create pg_control
|
|
HRN_STORAGE_PUT(
|
|
storagePgWrite(), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL,
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_92, .systemId = 6569239123849665699}));
|
|
|
|
harnessPqScriptSet((HarnessPq [])
|
|
{
|
|
HRNPQ_MACRO_OPEN_GE_92(1, "dbname='postgres' port=5432", PG_VERSION_92, TEST_PATH "/pg2", false, NULL, NULL),
|
|
HRNPQ_MACRO_DONE()
|
|
});
|
|
|
|
TEST_ERROR(
|
|
pgValidate(), DbMismatchError,
|
|
"version '" PG_VERSION_92_STR "' and path '" TEST_PATH "/pg2' queried from cluster do not match version '"
|
|
PG_VERSION_92_STR "' and '" TEST_PATH "/pg' read from '" TEST_PATH "/pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL
|
|
"'\nHINT: the pg1-path and pg1-port settings likely reference different clusters.");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("primary at pg2");
|
|
|
|
argList = strLstNew();
|
|
hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA);
|
|
hrnCfgArgRawZ(argList, cfgOptPgPath, TEST_PATH "/pg");
|
|
hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH "/repo");
|
|
hrnCfgArgKeyRawZ(argList, cfgOptPgPath, 2, TEST_PATH "/pg1");
|
|
hrnCfgArgKeyRawZ(argList, cfgOptPgPort, 2, "5434");
|
|
|
|
HRN_CFG_LOAD(cfgCmdStanzaCreate, argList);
|
|
|
|
// Create pg_control for primary
|
|
HRN_STORAGE_PUT(
|
|
storagePgIdxWrite(1), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL,
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_92, .systemId = 6569239123849665699}));
|
|
|
|
// Create pg_control for standby
|
|
HRN_STORAGE_PUT(
|
|
storagePgIdxWrite(0), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL,
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_94, .systemId = 6569239123849665700}));
|
|
|
|
harnessPqScriptSet((HarnessPq [])
|
|
{
|
|
HRNPQ_MACRO_OPEN_GE_92(1, "dbname='postgres' port=5432", PG_VERSION_92, TEST_PATH "/pg", true, NULL, NULL),
|
|
HRNPQ_MACRO_OPEN_GE_92(2, "dbname='postgres' port=5434", PG_VERSION_92, TEST_PATH "/pg1", false, NULL, NULL),
|
|
HRNPQ_MACRO_DONE()
|
|
});
|
|
|
|
PgControl pgControl = {0};
|
|
TEST_ASSIGN(pgControl, pgValidate(), "validate primary on pg2");
|
|
TEST_RESULT_UINT(pgControl.version, PG_VERSION_92, "version set");
|
|
TEST_RESULT_UINT(pgControl.systemId, 6569239123849665699, "systemId set");
|
|
TEST_RESULT_UINT(pgControl.catalogVersion, 201204301, "catalogVersion set");
|
|
}
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("cmdStanzaUpgrade()"))
|
|
{
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-upgrade - config errors");
|
|
|
|
// Load Parameters
|
|
StringList *argList = strLstDup(argListBase);
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo2");
|
|
hrnCfgArgRawZ(argList, cfgOptRepo, "2");
|
|
|
|
TEST_ERROR(
|
|
hrnCfgLoadP(cfgCmdStanzaUpgrade, argList), OptionInvalidError,
|
|
"option 'repo' not valid for command 'stanza-upgrade'");
|
|
|
|
HRN_CFG_LOAD(cfgCmdStanzaUpgrade, argListBase);
|
|
|
|
// Create the stop file, test and remove
|
|
HRN_STORAGE_PUT_EMPTY(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))));
|
|
TEST_ERROR(cmdStanzaUpgrade(), StopError, "stop file exists for stanza db");
|
|
HRN_STORAGE_REMOVE(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))));
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
// Create pg_control for the rest of the tests
|
|
HRN_STORAGE_PUT(
|
|
storagePgWrite(), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL,
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_96, .systemId = 6569239123849665679}));
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-upgrade - info file mismatch: db-id");
|
|
|
|
// Stanza with only archive.info and backup.info but no .copy files
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE,
|
|
"[db]\n"
|
|
"db-catalog-version=201608131\n"
|
|
"db-control-version=960\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665679,"
|
|
"\"db-version\":\"9.6\"}\n");
|
|
|
|
// backup info up to date but archive info db-id mismatch
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE,
|
|
"[db]\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"2={\"db-id\":6569239123849665679,\"db-version\":\"9.6\"}\n");
|
|
|
|
TEST_ERROR(
|
|
cmdStanzaUpgrade(), FileInvalidError,
|
|
"backup info file and archive info file do not match\n"
|
|
"archive: id = 2, version = 9.6, system-id = 6569239123849665679\n"
|
|
"backup : id = 1, version = 9.6, system-id = 6569239123849665679\n"
|
|
"HINT: this may be a symptom of repository corruption!");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-upgrade for stanza 'db' on repo1");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-upgrade - info file mismatch: archive version");
|
|
|
|
// backup info up to date but archive info version is not
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE,
|
|
"[db]\n"
|
|
"db-catalog-version=201608131\n"
|
|
"db-control-version=960\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6569239123849665999,"
|
|
"\"db-version\":\"9.5\"}\n"
|
|
"2={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665679,"
|
|
"\"db-version\":\"9.6\"}\n");
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE,
|
|
"[db]\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.5\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.5\"}\n");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaUpgrade(), "stanza upgrade - archive.info file upgraded - version");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-upgrade for stanza 'db' on repo1");
|
|
|
|
HRN_INFO_PUT(
|
|
storageHrn, "test.info",
|
|
"[db]\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6569239123849665679,\"db-version\":\"9.5\"}\n"
|
|
"2={\"db-id\":6569239123849665679,\"db-version\":\"9.6\"}\n",
|
|
.comment = "put archive info to test file");
|
|
|
|
TEST_RESULT_BOOL(
|
|
(bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_ARCHIVE_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), STRDEF(INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT)))) &&
|
|
bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_ARCHIVE_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageHrn, STRDEF("test.info"))))),
|
|
true, "test and stanza archive info files are equal");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-upgrade - info file mismatch: backup version");
|
|
|
|
// archive info up to date but backup info version is not
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE,
|
|
"[db]\n"
|
|
"db-catalog-version=201608131\n"
|
|
"db-control-version=960\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.5\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6569239123849665679,"
|
|
"\"db-version\":\"9.5\"}\n");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaUpgrade(), "stanza upgrade - backup.info file upgraded - version");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-upgrade for stanza 'db' on repo1");
|
|
|
|
HRN_INFO_PUT(
|
|
storageHrn, "test.info",
|
|
"[db]\n"
|
|
"db-catalog-version=201608131\n"
|
|
"db-control-version=960\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6569239123849665679,"
|
|
"\"db-version\":\"9.5\"}\n"
|
|
"2={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665679,"
|
|
"\"db-version\":\"9.6\"}\n",
|
|
.comment = "put backup info to test file");
|
|
|
|
TEST_RESULT_BOOL(
|
|
(bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), STRDEF(INFO_BACKUP_PATH_FILE INFO_COPY_EXT)))) &&
|
|
bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageHrn, STRDEF("test.info"))))),
|
|
true, "test and stanza backup info files are equal");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-upgrade - info file mismatch: archive system-id");
|
|
|
|
// backup info up to date but archive info system-id is not
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE,
|
|
"[db]\n"
|
|
"db-catalog-version=201608131\n"
|
|
"db-control-version=960\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201510051,\"db-control-version\":942,\"db-system-id\":6569239123849665999,"
|
|
"\"db-version\":\"9.5\"}\n"
|
|
"2={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665679,"
|
|
"\"db-version\":\"9.6\"}\n");
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE,
|
|
"[db]\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665999\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6569239123849665999,\"db-version\":\"9.6\"}\n");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaUpgrade(), "stanza upgrade - archive.info file upgraded - system-id");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-upgrade for stanza 'db' on repo1");
|
|
|
|
HRN_INFO_PUT(
|
|
storageHrn, "test.info",
|
|
"[db]\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6569239123849665999,\"db-version\":\"9.6\"}\n"
|
|
"2={\"db-id\":6569239123849665679,\"db-version\":\"9.6\"}\n",
|
|
.comment = "put archive info to test file");
|
|
|
|
TEST_RESULT_BOOL(
|
|
(bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_ARCHIVE_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), STRDEF(INFO_ARCHIVE_PATH_FILE INFO_COPY_EXT)))) &&
|
|
bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_ARCHIVE_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageHrn, STRDEF("test.info"))))),
|
|
true, "test and stanza archive info files are equal");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-upgrade - info file mismatch: backup system-id");
|
|
|
|
// archive info up to date but backup info system-id is not
|
|
HRN_INFO_PUT(
|
|
storageRepoIdxWrite(0), INFO_BACKUP_PATH_FILE,
|
|
"[db]\n"
|
|
"db-catalog-version=201608131\n"
|
|
"db-control-version=960\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6569239123849665999\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665999,"
|
|
"\"db-version\":\"9.6\"}\n");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaUpgrade(), "stanza upgrade - backup.info file upgraded - system-id");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-upgrade for stanza 'db' on repo1");
|
|
|
|
HRN_INFO_PUT(
|
|
storageHrn, "test.info",
|
|
"[db]\n"
|
|
"db-catalog-version=201608131\n"
|
|
"db-control-version=960\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6569239123849665679\n"
|
|
"db-version=\"9.6\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665999,"
|
|
"\"db-version\":\"9.6\"}\n"
|
|
"2={\"db-catalog-version\":201608131,\"db-control-version\":960,\"db-system-id\":6569239123849665679,"
|
|
"\"db-version\":\"9.6\"}\n",
|
|
.comment = "put backup info to test file");
|
|
TEST_RESULT_BOOL(
|
|
(bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), STRDEF(INFO_BACKUP_PATH_FILE INFO_COPY_EXT)))) &&
|
|
bufEq(
|
|
storageGetP(storageNewReadP(storageRepoIdx(0), INFO_BACKUP_PATH_FILE_STR)),
|
|
storageGetP(storageNewReadP(storageHrn, STRDEF("test.info"))))),
|
|
true, "test and stanza backup info files are equal");
|
|
}
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("cmdStanzaDelete(), stanzaDelete(), manifestDelete()"))
|
|
{
|
|
// Load Parameters
|
|
StringList *argListCmd = strLstNew();
|
|
hrnCfgArgKeyRawZ(argListCmd, cfgOptRepoPath, 1, TEST_PATH "/repo");
|
|
|
|
// Load Parameters
|
|
StringList *argList = strLstDup(argListCmd);
|
|
hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA_OTHER);
|
|
hrnCfgArgKeyRawZ(argList, cfgOptPgPath, 1, TEST_PATH "/" TEST_STANZA_OTHER);
|
|
hrnCfgArgRawBool(argList, cfgOptOnline, false);
|
|
HRN_CFG_LOAD(cfgCmdStanzaCreate, argList);
|
|
|
|
// Create pg_control for stanza-create
|
|
HRN_STORAGE_PUT(
|
|
storagePgWrite(), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL,
|
|
hrnPgControlToBuffer((PgControl){.version = PG_VERSION_96, .systemId = 6569239123849665679}));
|
|
|
|
TEST_RESULT_VOID(cmdStanzaCreate(), "create a stanza that will not be deleted");
|
|
TEST_RESULT_LOG("P00 INFO: stanza-create for stanza 'otherstanza' on repo1");
|
|
|
|
argList = strLstDup(argListCmd);
|
|
hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA);
|
|
hrnCfgArgKeyRawZ(argList, cfgOptPgPath, 1, TEST_PATH "/pg");
|
|
HRN_CFG_LOAD(cfgCmdStanzaDelete, argList);
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-delete - stanza already deleted");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaDelete(), "stanza delete - success on stanza does not exist");
|
|
TEST_RESULT_BOOL(stanzaDelete(storageRepoWrite(), NULL, NULL), true, "archiveList=NULL, backupList=NULL");
|
|
TEST_RESULT_BOOL(stanzaDelete(storageRepoWrite(), strLstNew(), NULL), true, "archiveList=0, backupList=NULL");
|
|
TEST_RESULT_BOOL(stanzaDelete(storageRepoWrite(), NULL, strLstNew()), true, "archiveList=NULL, backupList=0");
|
|
TEST_RESULT_BOOL(stanzaDelete(storageRepoWrite(), strLstNew(), strLstNew()), true, "archiveList=0, backupList=0");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-delete - only archive exists");
|
|
|
|
// Confirm stanza does not exist
|
|
TEST_STORAGE_LIST(
|
|
storageTest, "repo/archive", "otherstanza/\n", .noRecurse=true,
|
|
.comment = "stanza '" TEST_STANZA "' archive does not exist");
|
|
TEST_STORAGE_LIST(
|
|
storageTest, "repo/backup", "otherstanza/\n", .noRecurse=true,
|
|
.comment = "stanza '" TEST_STANZA "' backup does not exist");
|
|
|
|
// Create stanza archive only
|
|
HRN_STORAGE_PUT_EMPTY(
|
|
storageRepoWrite(), INFO_ARCHIVE_PATH_FILE, .comment = "create empty archive info for stanza '" TEST_STANZA "'");
|
|
HRN_STORAGE_PUT_EMPTY(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))), .comment = "create stop file");
|
|
TEST_STORAGE_LIST(
|
|
storageTest, "repo/archive",
|
|
"db/\n"
|
|
"otherstanza/\n",
|
|
.noRecurse = true, .comment = "stanza archive exists");
|
|
TEST_RESULT_VOID(cmdStanzaDelete(), "stanza delete - archive only");
|
|
|
|
TEST_STORAGE_LIST(
|
|
storageTest, "repo/archive", "otherstanza/\n", .noRecurse=true, .comment = "stanza '" TEST_STANZA "' deleted");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-delete - only backup exists");
|
|
|
|
// Create stanza backup only
|
|
HRN_STORAGE_PUT_EMPTY(
|
|
storageRepoWrite(), INFO_BACKUP_PATH_FILE,
|
|
.comment = "create empty backup info for stanza '" TEST_STANZA "'");
|
|
HRN_STORAGE_PUT_EMPTY(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))), .comment = "create stop file");
|
|
TEST_STORAGE_LIST(
|
|
storageTest, "repo/backup",
|
|
"db/\n"
|
|
"otherstanza/\n",
|
|
.noRecurse = true, .comment = "stanza backup exists");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaDelete(), "stanza delete - backup only");
|
|
TEST_STORAGE_LIST(
|
|
storageTest, "repo/backup", "otherstanza/\n", .noRecurse=true, .comment = "stanza '" TEST_STANZA "' deleted");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-delete - error on file that looks like backup directory");
|
|
|
|
// Create a backup file that matches the regex for a backup directory
|
|
HRN_STORAGE_PUT_EMPTY(
|
|
storageRepoWrite(), STORAGE_REPO_BACKUP "/20190708-154306F", .comment = "backup file that looks like a directory");
|
|
HRN_STORAGE_PUT_EMPTY(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))), .comment = "create stop file");
|
|
TEST_ERROR(
|
|
cmdStanzaDelete(), FileRemoveError,
|
|
"unable to remove '" TEST_PATH "/repo/backup/db/20190708-154306F/backup.manifest': [20] Not a directory");
|
|
HRN_STORAGE_REMOVE(storageTest, "repo/backup/db/20190708-154306F", "cleanup - remove backup file");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("manifestDelete()");
|
|
|
|
// Create backup manifests
|
|
HRN_STORAGE_PUT_EMPTY(storageRepoWrite(), STORAGE_REPO_BACKUP "/20190708-154306F/" BACKUP_MANIFEST_FILE);
|
|
HRN_STORAGE_PUT_EMPTY(
|
|
storageRepoWrite(), STORAGE_REPO_BACKUP "/20190708-154306F_20190716-191726I/" BACKUP_MANIFEST_FILE INFO_COPY_EXT);
|
|
HRN_STORAGE_PUT_EMPTY(storageRepoWrite(), STORAGE_REPO_BACKUP "/20190708-154306F_20190716-191800D/" BACKUP_MANIFEST_FILE);
|
|
HRN_STORAGE_PUT_EMPTY(
|
|
storageRepoWrite(), STORAGE_REPO_BACKUP "/20190708-154306F_20190716-191800D/" BACKUP_MANIFEST_FILE INFO_COPY_EXT);
|
|
|
|
TEST_STORAGE_LIST(
|
|
storageRepoWrite(), STORAGE_REPO_BACKUP,
|
|
"20190708-154306F/\n"
|
|
"20190708-154306F/backup.manifest\n"
|
|
"20190708-154306F_20190716-191726I/\n"
|
|
"20190708-154306F_20190716-191726I/backup.manifest.copy\n"
|
|
"20190708-154306F_20190716-191800D/\n"
|
|
"20190708-154306F_20190716-191800D/backup.manifest\n"
|
|
"20190708-154306F_20190716-191800D/backup.manifest.copy\n");
|
|
|
|
TEST_RESULT_VOID(manifestDelete(storageRepoWrite()), "delete manifests");
|
|
TEST_STORAGE_LIST(
|
|
storageRepoWrite(), STORAGE_REPO_BACKUP,
|
|
"20190708-154306F/\n"
|
|
"20190708-154306F_20190716-191726I/\n"
|
|
"20190708-154306F_20190716-191800D/\n", .comment = "all manifest files deleted");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("stanza-delete - empty directories");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaDelete(), "remove stanza '" TEST_STANZA "'");
|
|
|
|
// Create only stanza paths
|
|
HRN_STORAGE_PATH_CREATE(storageTest, "repo/archive/" TEST_STANZA, .comment = "create empty stanza archive path");
|
|
HRN_STORAGE_PATH_CREATE(storageTest, "repo/backup/" TEST_STANZA, .comment = "create empty stanza backup path");
|
|
|
|
TEST_RESULT_VOID(cmdStanzaDelete(), "stanza delete - empty directories");
|
|
TEST_STORAGE_LIST(
|
|
storageTest, "repo/archive", "otherstanza/\n", .noRecurse=true, .comment = "stanza '" TEST_STANZA "' deleted");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("delete errors when pg appears to be running");
|
|
|
|
HRN_STORAGE_PUT_EMPTY(
|
|
storageRepoWrite(), INFO_BACKUP_PATH_FILE, .comment = "create empty backup info for stanza '" TEST_STANZA "'");
|
|
HRN_STORAGE_PUT_EMPTY(storageHrn, strZ(lockStopFileName(cfgOptionStr(cfgOptStanza))), .comment = "create stop file");
|
|
HRN_STORAGE_PUT_EMPTY(storagePgWrite(), PG_FILE_POSTMASTERPID, .comment = "create postmaster pid file");
|
|
|
|
TEST_ERROR(
|
|
cmdStanzaDelete(), PgRunningError, PG_FILE_POSTMASTERPID " exists - looks like " PG_NAME " is running. "
|
|
"To delete stanza 'db' on repo1, shut down " PG_NAME " for stanza 'db' and try again, or use --force.");
|
|
|
|
// Specify repo option
|
|
StringList *argListDel = strLstDup(argList);
|
|
hrnCfgArgKeyRawZ(argListDel, cfgOptRepoPath, 2, TEST_PATH "/repo2");
|
|
hrnCfgArgRawZ(argListDel, cfgOptRepo, "2");
|
|
HRN_CFG_LOAD(cfgCmdStanzaDelete, argListDel);
|
|
|
|
HRN_STORAGE_PUT_EMPTY(storageRepoIdxWrite(1), INFO_BACKUP_PATH_FILE, .comment = "create empty backup info repo2");
|
|
|
|
TEST_ERROR(
|
|
cmdStanzaDelete(), PgRunningError, PG_FILE_POSTMASTERPID " exists - looks like " PG_NAME " is running. "
|
|
"To delete stanza 'db' on repo2, shut down " PG_NAME " for stanza 'db' and try again, or use --force.");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("force delete when pg appears to be running, multi-repo");
|
|
|
|
argList = strLstDup(argListCmd);
|
|
hrnCfgArgRawZ(argList, cfgOptStanza, TEST_STANZA);
|
|
hrnCfgArgKeyRawFmt(argList, cfgOptPgPath, 1, TEST_PATH "/pg");
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo2");
|
|
hrnCfgArgRawZ(argList, cfgOptRepo, "1");
|
|
hrnCfgArgRawBool(argList, cfgOptForce, true);
|
|
HRN_CFG_LOAD(cfgCmdStanzaDelete, argList);
|
|
|
|
TEST_RESULT_VOID(cmdStanzaDelete(), "stanza '" TEST_STANZA "' delete --force");
|
|
TEST_RESULT_BOOL(storagePathExistsP(storageTest, strNewZ("repo/backup/" TEST_STANZA)), false, "repo1: stanza deleted");
|
|
TEST_RESULT_BOOL(storagePathExistsP(storageTest, strNewZ("repo2/backup/" TEST_STANZA)), true, "repo2: stanza not deleted");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("ensure other stanza never deleted from repo1");
|
|
|
|
TEST_STORAGE_LIST(
|
|
storageRepo(), "",
|
|
"archive/\n"
|
|
"archive/otherstanza/\n"
|
|
"archive/otherstanza/archive.info\n"
|
|
"archive/otherstanza/archive.info.copy\n"
|
|
"backup/\n"
|
|
"backup/otherstanza/\n"
|
|
"backup/otherstanza/backup.info\n"
|
|
"backup/otherstanza/backup.info.copy\n",
|
|
.comment = "otherstanza exists");
|
|
}
|
|
|
|
FUNCTION_HARNESS_RETURN_VOID();
|
|
}
|