1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-07-09 00:45:49 +02:00
Files
pgbackrest/test/src/module/command/stanzaTest.c
David Steele 39c1c10120 Remove TEST_PATH_REPO, TEST_PATH_PG, and TEST_PATH_SPOOL constants.
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.
2021-06-28 13:28:28 -04:00

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();
}