mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-04-15 11:36:40 +02:00
Multi-repository implementations for the archive-push, check, info, stanza-create, stanza-upgrade, and stanza-delete commands. Multi-repo configuration is disabled so there should be no behavioral changes between these commands and their current single-repo implementations. Multi-repo documentation and integration tests are still in the multi-repo development branch. All unit tests work as multi-repo since they are able to bypass the configuration restrictions.
2198 lines
132 KiB
C
2198 lines
132 KiB
C
/***********************************************************************************************************************************
|
|
Test Expire Command
|
|
***********************************************************************************************************************************/
|
|
#include <unistd.h>
|
|
|
|
#include "common/io/bufferRead.h"
|
|
#include "storage/posix/storage.h"
|
|
|
|
#include "common/harnessConfig.h"
|
|
#include "common/harnessInfo.h"
|
|
|
|
/***********************************************************************************************************************************
|
|
Helper functions
|
|
***********************************************************************************************************************************/
|
|
void
|
|
archiveGenerate(
|
|
Storage *storageTest, String *archiveStanzaPath, const unsigned int start, unsigned int end, const char *archiveId,
|
|
const char *majorWal)
|
|
{
|
|
// For simplicity, only allow 2 digits
|
|
if (end > 99)
|
|
end = 99;
|
|
|
|
String *wal = NULL;
|
|
|
|
for (unsigned int i = start; i <= end; i++)
|
|
{
|
|
if (i < 10)
|
|
wal = strNewFmt("%s0000000%u-9baedd24b61aa15305732ac678c4e2c102435a09", majorWal, i);
|
|
else
|
|
wal = strNewFmt("%s000000%u-9baedd24b61aa15305732ac678c4e2c102435a09", majorWal, i);
|
|
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/%s/%s/%s", strZ(archiveStanzaPath), archiveId, majorWal, strZ(wal))),
|
|
BUFSTRDEF(BOGUS_STR));
|
|
}
|
|
}
|
|
|
|
String *
|
|
archiveExpectList(const unsigned int start, unsigned int end, const char *majorWal)
|
|
{
|
|
String *result = strNew("");
|
|
|
|
// For simplicity, only allow 2 digits
|
|
if (end > 99)
|
|
end = 99;
|
|
|
|
String *wal = NULL;
|
|
|
|
for (unsigned int i = start; i <= end; i++)
|
|
{
|
|
if (i < 10)
|
|
wal = strNewFmt("%s0000000%u-9baedd24b61aa15305732ac678c4e2c102435a09", majorWal, i);
|
|
else
|
|
wal = strNewFmt("%s000000%u-9baedd24b61aa15305732ac678c4e2c102435a09", majorWal, i);
|
|
|
|
strCatFmt(result, "%s\n", strZ(wal));
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/***********************************************************************************************************************************
|
|
Test Run
|
|
***********************************************************************************************************************************/
|
|
void
|
|
testRun(void)
|
|
{
|
|
FUNCTION_HARNESS_VOID();
|
|
|
|
Storage *storageTest = storagePosixNewP(strNew(testPath()), .write = true);
|
|
|
|
String *backupStanzaPath = strNew("repo/backup/db");
|
|
String *backupInfoFileName = strNewFmt("%s/backup.info", strZ(backupStanzaPath));
|
|
String *archiveStanzaPath = strNew("repo/archive/db");
|
|
String *archiveInfoFileName = strNewFmt("%s/archive.info", strZ(archiveStanzaPath));
|
|
|
|
StringList *argListBase = strLstNew();
|
|
strLstAddZ(argListBase, "--stanza=db");
|
|
strLstAdd(argListBase, strNewFmt("--repo1-path=%s/repo", testPath()));
|
|
|
|
StringList *argListAvoidWarn = strLstDup(argListBase);
|
|
strLstAddZ(argListAvoidWarn, "--repo1-retention-full=1"); // avoid warning
|
|
|
|
uint64_t timeNow = (uint64_t)time(NULL); // time in seconds since Epoch
|
|
|
|
String *backupInfoContent = strNewFmt(
|
|
"[backup:current]\n"
|
|
"20181119-152138F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000002\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":%" PRIu64 ",\"backup-timestamp-stop\":%" PRIu64 ",\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000004\",\"backup-archive-stop\":\"000000010000000000000004\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":%" PRIu64 ",\"backup-timestamp-stop\":%" PRIu64 ",\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F_20181119-152152D={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000010000000000000006\","
|
|
"\"backup-archive-stop\":\"000000010000000000000006\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152800F\",\"backup-reference\":[\"20181119-152800F\"],"
|
|
"\"backup-timestamp-start\":%" PRIu64 ",\"backup-timestamp-stop\":%" PRIu64 ",\"backup-type\":\"diff\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F_20181119-152155I={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000010000000000000007\","
|
|
"\"backup-archive-stop\":\"000000010000000000000007\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152800F_20181119-152152D\","
|
|
"\"backup-reference\":[\"20181119-152800F\",\"20181119-152800F_20181119-152152D\"],"
|
|
"\"backup-timestamp-start\":%" PRIu64 ",\"backup-timestamp-stop\":%" PRIu64 ",\"backup-type\":\"incr\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152900F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000009\",\"backup-archive-stop\":\"000000010000000000000009\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":%" PRIu64 ",\"backup-timestamp-stop\":%" PRIu64 ",\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152900F_20181119-152600D={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000010000000000000011\","
|
|
"\"backup-archive-stop\":\"000000010000000000000011\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152900F\",\"backup-reference\":[\"20181119-152900F\"],"
|
|
"\"backup-timestamp-start\":%" PRIu64 ",\"backup-timestamp-stop\":%" PRIu64 ",\"backup-type\":\"diff\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201409291\n"
|
|
"db-control-version=942\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6625592122879095702\n"
|
|
"db-version=\"9.4\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}", timeNow - (41 * SEC_PER_DAY), timeNow - (40 * SEC_PER_DAY), timeNow - (30 * SEC_PER_DAY),
|
|
timeNow - (30 * SEC_PER_DAY), timeNow - (25 * SEC_PER_DAY), timeNow - (25 * SEC_PER_DAY), timeNow - (20 * SEC_PER_DAY),
|
|
timeNow - (20 * SEC_PER_DAY), timeNow - (10 * SEC_PER_DAY), timeNow - (10 * SEC_PER_DAY), timeNow - (5 * SEC_PER_DAY),
|
|
timeNow - (5 * SEC_PER_DAY));
|
|
|
|
const Buffer *backupInfoBase = harnessInfoChecksumZ(strZ(backupInfoContent));
|
|
|
|
// Sleep the remainder of the current second. If cmdExpire() gets the same time as timeNow then expiration won't work as
|
|
// expected in the tests.
|
|
sleepMSec(MSEC_PER_SEC - (timeMSec() % MSEC_PER_SEC));
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("expireBackup()"))
|
|
{
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("manifest file removal");
|
|
|
|
// Create backup.info
|
|
InfoBackup *infoBackup = NULL;
|
|
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info");
|
|
|
|
// Create backup directories and manifest files
|
|
String *full1 = strNew("20181119-152138F");
|
|
String *full2 = strNew("20181119-152800F");
|
|
String *full1Path = strNewFmt("%s/%s", strZ(backupStanzaPath), strZ(full1));
|
|
String *full2Path = strNewFmt("%s/%s", strZ(backupStanzaPath), strZ(full2));
|
|
|
|
// Load Parameters
|
|
StringList *argList = strLstDup(argListAvoidWarn);
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/%s", strZ(full1Path), BACKUP_MANIFEST_FILE)), BUFSTRDEF(BOGUS_STR)),
|
|
"full1 put manifest");
|
|
TEST_RESULT_VOID(
|
|
storagePutP(
|
|
storageNewWriteP(
|
|
storageTest, strNewFmt("%s/%s", strZ(full1Path), BACKUP_MANIFEST_FILE ".copy")), BUFSTRDEF(BOGUS_STR)),
|
|
"full1 put manifest copy");
|
|
TEST_RESULT_VOID(
|
|
storagePutP(storageNewWriteP(storageTest, strNewFmt("%s/%s", strZ(full1Path), "bogus")),
|
|
BUFSTRDEF(BOGUS_STR)), "full1 put extra file");
|
|
TEST_RESULT_VOID(storagePathCreateP(storageTest, full2Path), "full2 empty");
|
|
|
|
|
|
TEST_RESULT_VOID(expireBackup(infoBackup, full1), "expire backup with both manifest files");
|
|
TEST_RESULT_BOOL(
|
|
(strLstSize(storageListP(storageTest, full1Path)) && strLstExistsZ(storageListP(storageTest, full1Path), "bogus")),
|
|
true, "full1 - only manifest files removed");
|
|
|
|
TEST_RESULT_VOID(expireBackup(infoBackup, full2), "expire backup with no manifest - does not error");
|
|
|
|
TEST_RESULT_STRLST_Z(
|
|
infoBackupDataLabelList(infoBackup, NULL),
|
|
"20181119-152900F\n20181119-152900F_20181119-152600D\n",
|
|
"only backups in set passed to expireBackup are removed from backup:current (result is sorted)");
|
|
}
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("expireFullBackup()"))
|
|
{
|
|
// Create backup.info
|
|
InfoBackup *infoBackup = NULL;
|
|
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-full not set - nothing expired");
|
|
|
|
// Load Parameters
|
|
StringList *argList = strLstDup(argListBase);
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_UINT(expireFullBackup(infoBackup), 0, "retention-full not set");
|
|
harnessLogResult(
|
|
"P00 WARN: option 'repo1-retention-full' is not set for 'repo1-retention-full-type=count', the repository may run out"
|
|
" of space\n"
|
|
" HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the"
|
|
" maximum.");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-full set - full backup no dependencies expired");
|
|
|
|
strLstAddZ(argList, "--repo1-retention-full=2");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_UINT(expireFullBackup(infoBackup), 1, "retention-full=2 - one full backup expired");
|
|
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 5, "current backups reduced by 1 full - no dependencies");
|
|
TEST_RESULT_STRLST_Z(
|
|
infoBackupDataLabelList(infoBackup, NULL),
|
|
"20181119-152800F\n20181119-152800F_20181119-152152D\n20181119-152800F_20181119-152155I\n20181119-152900F\n"
|
|
"20181119-152900F_20181119-152600D\n",
|
|
"remaining backups correct");
|
|
harnessLogResult("P00 INFO: expire full backup 20181119-152138F");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-full set - full backup with dependencies expired");
|
|
|
|
argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=1");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_UINT(expireFullBackup(infoBackup), 3, "retention-full=1 - one full backup and dependencies expired");
|
|
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, "current backups reduced by 1 full and dependencies");
|
|
TEST_RESULT_STRLST_Z(
|
|
infoBackupDataLabelList(infoBackup, NULL), "20181119-152900F\n20181119-152900F_20181119-152600D\n",
|
|
"remaining backups correct");
|
|
harnessLogResult(
|
|
"P00 INFO: expire full backup set: 20181119-152800F, 20181119-152800F_20181119-152152D, "
|
|
"20181119-152800F_20181119-152155I");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-full set - no backups expired");
|
|
|
|
TEST_RESULT_UINT(expireFullBackup(infoBackup), 0, "retention-full=1 - not enough backups to expire any");
|
|
TEST_RESULT_STRLST_Z(
|
|
infoBackupDataLabelList(infoBackup, NULL), "20181119-152900F\n20181119-152900F_20181119-152600D\n",
|
|
" remaining backups correct");
|
|
}
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("expireDiffBackup()"))
|
|
{
|
|
// Create backup.info
|
|
InfoBackup *infoBackup = NULL;
|
|
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-diff not set");
|
|
|
|
// Load Parameters
|
|
StringList *argList = strLstDup(argListAvoidWarn);
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_UINT(expireDiffBackup(infoBackup), 0, "retention-diff not set - nothing expired");
|
|
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 6, "current backups not expired");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-diff set - nothing yet to expire");
|
|
|
|
// Add retention-diff
|
|
StringList *argListTemp = strLstDup(argList);
|
|
strLstAddZ(argListTemp, "--repo1-retention-diff=6");
|
|
harnessCfgLoad(cfgCmdExpire, argListTemp);
|
|
|
|
TEST_RESULT_UINT(expireDiffBackup(infoBackup), 0, "retention-diff set - too soon to expire");
|
|
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 6, "current backups not expired");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-diff set - diff and dependent incr expired");
|
|
|
|
strLstAddZ(argList, "--repo1-retention-diff=2");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_UINT(expireDiffBackup(infoBackup), 2, "retention-diff=2 - full considered in diff");
|
|
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 4, "current backups reduced by 1 diff and dependent increment");
|
|
TEST_RESULT_STRLST_Z(
|
|
infoBackupDataLabelList(infoBackup, NULL),
|
|
"20181119-152138F\n20181119-152800F\n20181119-152900F\n20181119-152900F_20181119-152600D\n",
|
|
"remaining backups correct");
|
|
harnessLogResult(
|
|
"P00 INFO: expire diff backup set: 20181119-152800F_20181119-152152D, 20181119-152800F_20181119-152155I");
|
|
|
|
TEST_RESULT_UINT(expireDiffBackup(infoBackup), 0, "retention-diff=2 but no more to expire");
|
|
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 4, "current backups not reduced");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-diff=1");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info");
|
|
TEST_RESULT_UINT(expireDiffBackup(infoBackup), 2, "retention-diff set to 1 - full considered in diff");
|
|
TEST_RESULT_STRLST_Z(
|
|
infoBackupDataLabelList(infoBackup, NULL),
|
|
"20181119-152138F\n20181119-152800F\n20181119-152900F\n20181119-152900F_20181119-152600D\n",
|
|
" remaining backups correct");
|
|
harnessLogResult(
|
|
"P00 INFO: expire diff backup set: 20181119-152800F_20181119-152152D, 20181119-152800F_20181119-152155I");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-diff set - diff with no dependents expired");
|
|
|
|
// Create backup.info with two diff - oldest to be expired - no "set:"
|
|
const Buffer *backupInfoContent = harnessInfoChecksumZ
|
|
(
|
|
"[backup:current]\n"
|
|
"20181119-152800F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000002\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F_20181119-152152D={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000010000000000000003\","
|
|
"\"backup-archive-stop\":\"000000010000000000000003\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152800F\",\"backup-reference\":[\"20181119-152800F\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"diff\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F_20181119-152155D={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000010000000000000004\","
|
|
"\"backup-archive-stop\":\"000000010000000000000004\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152800F\",\"backup-reference\":[\"20181119-152800F\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"diff\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201409291\n"
|
|
"db-control-version=942\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6625592122879095702\n"
|
|
"db-version=\"9.4\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}"
|
|
);
|
|
|
|
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent)), "get backup.info");
|
|
|
|
// Load parameters
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-diff=1");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_UINT(expireDiffBackup(infoBackup), 1, "retention-diff set - only oldest diff expired");
|
|
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, "current backups reduced by one");
|
|
TEST_RESULT_STRLST_Z(
|
|
infoBackupDataLabelList(infoBackup, NULL), "20181119-152800F\n20181119-152800F_20181119-152155D\n",
|
|
"remaining backups correct");
|
|
harnessLogResult(
|
|
"P00 INFO: expire diff backup 20181119-152800F_20181119-152152D");
|
|
}
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("removeExpiredBackup()"))
|
|
{
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("remove expired backup from disk - backup not in current backup");
|
|
|
|
// Create backup.info
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, backupInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[backup:current]\n"
|
|
"20181119-152138F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000002\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201409291\n"
|
|
"db-control-version=942\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6625592122879095702\n"
|
|
"db-version=\"9.4\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}"));
|
|
|
|
InfoBackup *infoBackup = NULL;
|
|
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
|
|
|
// Create backup directories, manifest files and other path/file
|
|
String *full = strNewFmt("%s/%s", strZ(backupStanzaPath), "20181119-152100F");
|
|
String *diff = strNewFmt("%s/%s", strZ(backupStanzaPath), "20181119-152100F_20181119-152152D");
|
|
String *otherPath = strNewFmt("%s/%s", strZ(backupStanzaPath), "bogus");
|
|
String *otherFile = strNewFmt("%s/%s", strZ(backupStanzaPath), "20181118-152100F_20181119-152152D.save");
|
|
String *full1 = strNewFmt("%s/%s", strZ(backupStanzaPath), "20181119-152138F");
|
|
|
|
TEST_RESULT_VOID(
|
|
storagePutP(storageNewWriteP(storageTest, strNewFmt("%s/%s", strZ(full), "bogus")),
|
|
BUFSTRDEF(BOGUS_STR)), "put file");
|
|
TEST_RESULT_VOID(
|
|
storagePutP(storageNewWriteP(storageTest, strNewFmt("%s/%s", strZ(full1), "somefile")),
|
|
BUFSTRDEF(BOGUS_STR)), "put file");
|
|
TEST_RESULT_VOID(storagePathCreateP(storageTest, diff), "empty backup directory must not error on delete");
|
|
TEST_RESULT_VOID(storagePathCreateP(storageTest, otherPath), "other path must not be removed");
|
|
TEST_RESULT_VOID(
|
|
storagePutP(storageNewWriteP(storageTest, otherFile),
|
|
BUFSTRDEF(BOGUS_STR)), "directory look-alike file must not be removed");
|
|
|
|
// Load Parameters
|
|
StringList *argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=1");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(removeExpiredBackup(infoBackup, NULL), "remove backups not in backup.info current");
|
|
|
|
harnessLogResult(
|
|
"P00 INFO: remove expired backup 20181119-152100F_20181119-152152D\n"
|
|
"P00 INFO: remove expired backup 20181119-152100F");
|
|
|
|
TEST_RESULT_STRLST_Z(
|
|
strLstSort(storageListP(storageTest, backupStanzaPath), sortOrderAsc),
|
|
"20181118-152100F_20181119-152152D.save\n20181119-152138F\nbackup.info\nbogus\n",
|
|
"remaining file/directories correct");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("remove expired backup from disk - no current backups");
|
|
|
|
// Create backup.info without current backups
|
|
const Buffer *backupInfoContent = harnessInfoChecksumZ
|
|
(
|
|
"[db]\n"
|
|
"db-catalog-version=201409291\n"
|
|
"db-control-version=942\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6625592122879095702\n"
|
|
"db-version=\"9.4\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}"
|
|
);
|
|
|
|
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent)), "get backup.info");
|
|
|
|
TEST_RESULT_VOID(removeExpiredBackup(infoBackup, NULL), "remove backups - backup.info current empty");
|
|
|
|
harnessLogResult("P00 INFO: remove expired backup 20181119-152138F");
|
|
TEST_RESULT_STRLST_Z(
|
|
strLstSort(storageListP(storageTest, backupStanzaPath), sortOrderAsc),
|
|
"20181118-152100F_20181119-152152D.save\nbackup.info\nbogus\n", "remaining file/directories correct");
|
|
}
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("removeExpiredArchive() & cmdExpire()"))
|
|
{
|
|
TEST_TITLE("check repo local");
|
|
|
|
// Load Parameters
|
|
StringList *argList = strLstNew();
|
|
strLstAddZ(argList, "--stanza=db");
|
|
strLstAddZ(argList, "--repo1-retention-full=1"); // avoid warning
|
|
strLstAddZ(argList, "--repo1-host=/repo/not/local");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_ERROR_FMT(
|
|
cmdExpire(), HostInvalidError, "expire command must be run on the repository host");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("check stop file");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
// Create the stop file
|
|
TEST_RESULT_VOID(
|
|
storagePutP(
|
|
storageNewWriteP(storageLocalWrite(), lockStopFileName(cfgOptionStr(cfgOptStanza))), BUFSTRDEF("")),
|
|
"create stop file");
|
|
TEST_ERROR_FMT(cmdExpire(), StopError, "stop file exists for stanza db");
|
|
TEST_RESULT_VOID(
|
|
storageRemoveP(storageLocalWrite(), lockStopFileName(cfgOptionStr(cfgOptStanza))), "remove the stop file");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-archive not set");
|
|
|
|
// Load Parameters
|
|
argList = strLstDup(argListBase);
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
// Create backup.info without current backups
|
|
const Buffer *backupInfoContent = harnessInfoChecksumZ
|
|
(
|
|
"[db]\n"
|
|
"db-catalog-version=201409291\n"
|
|
"db-control-version=942\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6625592122879095702\n"
|
|
"db-version=\"9.4\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}"
|
|
);
|
|
|
|
InfoBackup *infoBackup = NULL;
|
|
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoContent)), "get backup.info");
|
|
|
|
TEST_RESULT_VOID(removeExpiredArchive(infoBackup, false), "archive retention not set");
|
|
harnessLogResult(
|
|
"P00 WARN: option 'repo1-retention-full' is not set for 'repo1-retention-full-type=count', the repository may run out"
|
|
" of space\n"
|
|
" HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the"
|
|
" maximum.\n"
|
|
"P00 INFO: option 'repo1-retention-archive' is not set - archive logs will not be expired");
|
|
|
|
TEST_RESULT_VOID(removeExpiredArchive(infoBackup, true), "archive retention not set - retention-full-type=time");
|
|
harnessLogResult("P00 INFO: time-based archive retention not met - archive logs will not be expired");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-archive set - no current backups");
|
|
|
|
// Set archive retention, archive retention type default but no current backups - code path test
|
|
strLstAddZ(argList, "--repo1-retention-archive=4");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(removeExpiredArchive(infoBackup, false), "archive retention set, retention type default, no current backups");
|
|
harnessLogResult(
|
|
"P00 WARN: option 'repo1-retention-full' is not set for 'repo1-retention-full-type=count', the repository may run out"
|
|
" of space\n"
|
|
" HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the"
|
|
" maximum.");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-archive set - no archive on disk");
|
|
|
|
// Create backup.info with current backups spread over different timelines
|
|
storagePutP(storageNewWriteP(storageTest, backupInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[backup:current]\n"
|
|
"20181119-152138F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000002\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000020000000000000002\",\"backup-archive-stop\":\"000000020000000000000002\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F_20181119-152152D={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000020000000000000004\","
|
|
"\"backup-archive-stop\":\"000000020000000000000005\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152800F\",\"backup-reference\":[\"20181119-152800F\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"diff\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F_20181119-152155I={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000020000000000000007\","
|
|
"\"backup-archive-stop\":\"000000020000000000000007\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152800F_20181119-152152D\","
|
|
"\"backup-reference\":[\"20181119-152800F\",\"20181119-152800F_20181119-152152D\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"incr\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F_20181119-152252D={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000020000000000000009\","
|
|
"\"backup-archive-stop\":\"000000020000000000000009\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152800F\",\"backup-reference\":[\"20181119-152800F\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"diff\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152900F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000003\",\"backup-archive-stop\":\"000000010000000000000004\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152900F_20181119-152500I={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000010000000000000006\","
|
|
"\"backup-archive-stop\":\"000000010000000000000006\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152900F\",\"backup-reference\":[\"20181119-152900F\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"diff\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201707211\n"
|
|
"db-control-version=1002\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}\n"
|
|
"2={\"db-catalog-version\":201707211,\"db-control-version\":1002,\"db-system-id\":6626363367545678089,"
|
|
"\"db-version\":\"10\"}\n"));
|
|
|
|
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
|
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, archiveInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[db]\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6625592122879095702,\"db-version\":\"9.4\"}\n"
|
|
"2={\"db-id\":6626363367545678089,\"db-version\":\"10\"}"));
|
|
|
|
TEST_RESULT_VOID(removeExpiredArchive(infoBackup, true), "no archive on disk");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-archive set - remove archives across timelines");
|
|
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 10, "9.4-1", "0000000100000000");
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 10, "9.4-1", "0000000200000000");
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 10, "10-2", "0000000100000000");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-archive=3");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(removeExpiredArchive(infoBackup, false), "archive retention type = full (default), repo1-retention-archive=3");
|
|
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(2, 10, "0000000100000000"), "only 9.4-1/0000000100000000/000000010000000000000001 removed");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000200000000")), sortOrderAsc),
|
|
archiveExpectList(1, 10, "0000000200000000"),
|
|
"none removed from 9.4-1/0000000200000000 - crossing timelines to play through PITR");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "10-2", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(3, 10, "0000000100000000"),
|
|
"000000010000000000000001 and 000000010000000000000002 removed from 10-2/0000000100000000");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-archive set - latest archive not expired");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-archive=2");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(removeExpiredArchive(infoBackup, false), "archive retention type = full (default), repo1-retention-archive=2");
|
|
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(2, 2, "0000000100000000"),
|
|
"only 9.4-1/0000000100000000/000000010000000000000002 remains in major wal 1");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000200000000")), sortOrderAsc),
|
|
archiveExpectList(2, 10, "0000000200000000"),
|
|
"only 9.4-1/0000000200000000/000000010000000000000001 removed from major wal 2");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "10-2", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(3, 10, "0000000100000000"),
|
|
"none removed from 10-2/0000000100000000");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-archive set to lowest - keep PITR for each archiveId");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-archive=1");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(removeExpiredArchive(infoBackup, false), "archive retention type = full (default), repo1-retention-archive=1");
|
|
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(2, 2, "0000000100000000"),
|
|
"only 9.4-1/0000000100000000/000000010000000000000002 remains in major wal 1");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000200000000")), sortOrderAsc),
|
|
archiveExpectList(2, 10, "0000000200000000"),
|
|
"nothing removed from 9.4-1/0000000200000000 major wal 2 - each archiveId must have one backup to play through PITR");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "10-2", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(3, 10, "0000000100000000"), "none removed from 10-2/0000000100000000");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-archive, retention-archive-type=diff, retention-diff set");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-archive=2");
|
|
strLstAddZ(argList, "--repo1-retention-archive-type=diff");
|
|
strLstAddZ(argList, "--repo1-retention-diff=2");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(
|
|
removeExpiredArchive(infoBackup, false),
|
|
"full counts as differential and incremental associated with differential expires");
|
|
|
|
String *result = strNew("");
|
|
strCatFmt(
|
|
result,
|
|
"%s%s%s%s",
|
|
strZ(archiveExpectList(2, 2, "0000000200000000")), strZ(archiveExpectList(4, 5, "0000000200000000")),
|
|
strZ(archiveExpectList(7, 7, "0000000200000000")), strZ(archiveExpectList(9, 10, "0000000200000000")));
|
|
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(2, 2, "0000000100000000"),
|
|
"only 9.4-1/0000000100000000/000000010000000000000002 remains in major wal 1");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000200000000")), sortOrderAsc),
|
|
result, "all in-between removed from 9.4-1/0000000200000000 major wal 2 - last backup able to play through PITR");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "10-2", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(3, 10, "0000000100000000"), "none removed from 10-2/0000000100000000");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention-archive, retention-archive-type=incr");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-archive=4");
|
|
strLstAddZ(argList, "--repo1-retention-archive-type=incr");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
// Regenerate archive
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 10, "9.4-1", "0000000200000000");
|
|
|
|
TEST_RESULT_VOID(removeExpiredArchive(infoBackup, false), "differential and full count as an incremental");
|
|
|
|
result = strNew("");
|
|
strCatFmt(
|
|
result,
|
|
"%s%s%s",
|
|
strZ(archiveExpectList(2, 2, "0000000200000000")), strZ(archiveExpectList(4, 5, "0000000200000000")),
|
|
strZ(archiveExpectList(7, 10, "0000000200000000")));
|
|
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(2, 2, "0000000100000000"),
|
|
"only 9.4-1/0000000100000000/000000010000000000000002 remains in major wal 1");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000200000000")), sortOrderAsc),
|
|
result, "incremental and after remain in 9.4-1/0000000200000000 major wal 2");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "10-2", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(3, 10, "0000000100000000"), "none removed from 10-2/0000000100000000");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire command - dry run");
|
|
|
|
argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=2");
|
|
strLstAddZ(argList, "--repo1-retention-diff=3");
|
|
strLstAddZ(argList, "--repo1-retention-archive=2");
|
|
strLstAddZ(argList, "--repo1-retention-archive-type=diff");
|
|
strLstAddZ(argList, "--dry-run");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
// Write backup.manifest so infoBackup reconstruct produces same results as backup.info on disk
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152138F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F_20181119-152152D/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F_20181119-152155I/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F_20181119-152252D/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152900F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152900F_20181119-152500I/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "expire (dry-run) do not remove last backup in archive sub path or sub path");
|
|
TEST_RESULT_BOOL(
|
|
storagePathExistsP(storageTest, strNewFmt("%s/%s", strZ(archiveStanzaPath), "9.4-1/0000000100000000")), true,
|
|
"archive sub path not removed");
|
|
TEST_RESULT_BOOL(
|
|
storageExistsP(storageTest, strNewFmt("%s/20181119-152138F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))), true,
|
|
"backup not removed");
|
|
harnessLogResult(
|
|
"P00 INFO: [DRY-RUN] expire full backup 20181119-152138F\n"
|
|
"P00 INFO: [DRY-RUN] remove expired backup 20181119-152138F");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire via backup command");
|
|
|
|
// Copy the repo to another repo
|
|
TEST_SYSTEM_FMT("mkdir %s/repo2", testPath());
|
|
TEST_SYSTEM_FMT("cp -r %s/repo/* %s/repo2/", testPath(), testPath());
|
|
|
|
// Configure multi-repo and set the repo option to expire the second repo (non-default) files
|
|
argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=2");
|
|
strLstAddZ(argList, "--repo1-retention-diff=3");
|
|
strLstAddZ(argList, "--repo1-retention-archive=2");
|
|
strLstAddZ(argList, "--repo1-retention-archive-type=diff");
|
|
hrnCfgArgKeyRawFmt(argList, cfgOptRepoPath, 2, "%s/repo2", testPath());
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoRetentionFull, 2, "2");
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoRetentionDiff, 2, "3");
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoRetentionArchive, 2, "2");
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoRetentionArchiveType, 2, "diff");
|
|
hrnCfgArgRawZ(argList, cfgOptRepo, "2");
|
|
strLstAdd(argList, strNewFmt("--pg1-path=%s/pg", testPath()));
|
|
harnessCfgLoad(cfgCmdBackup, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "via backup command: expire last backup in archive sub path and remove sub path");
|
|
TEST_RESULT_BOOL(
|
|
storagePathExistsP(storageTest, STRDEF("repo2/archive/db/9.4-1/0000000100000000")), false,
|
|
"archive sub path removed repo2");
|
|
TEST_RESULT_BOOL(
|
|
storagePathExistsP(storageTest, strNewFmt("%s/9.4-1/0000000100000000", strZ(archiveStanzaPath))), true,
|
|
"archive sub path repo1 not removed");
|
|
|
|
String *backupLabel = strNew("20181119-152138F");
|
|
TEST_ASSIGN(
|
|
infoBackup, infoBackupLoadFile(storageTest, STRDEF("repo2/backup/db/backup.info"), cipherTypeNone, NULL),
|
|
"get backup.info repo2");
|
|
TEST_RESULT_BOOL(strLstExists(infoBackupDataLabelList(infoBackup, NULL), backupLabel), false, "backup removed from repo2");
|
|
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info repo1");
|
|
TEST_RESULT_BOOL(strLstExists(infoBackupDataLabelList(infoBackup, NULL), backupLabel), true, "backup exists repo1");
|
|
|
|
harnessLogResult(
|
|
"P00 INFO: expire full backup 20181119-152138F\n"
|
|
"P00 INFO: remove expired backup 20181119-152138F");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire command requires repo option");
|
|
|
|
argList = strLstDup(argListBase);
|
|
hrnCfgArgKeyRawFmt(argList, cfgOptRepoPath, 2, "%s/repo2", testPath());
|
|
hrnCfgArgKeyRawZ(argList, cfgOptRepoRetentionFull, 2, "3");
|
|
|
|
TEST_ERROR_FMT(
|
|
harnessCfgLoad(cfgCmdExpire, argList), OptionRequiredError, "expire command requires option: repo\n"
|
|
"HINT: this command requires a specific repository to operate on");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire command - no dry run");
|
|
|
|
// Add to previous list and specify repo
|
|
strLstAddZ(argList, "--repo1-retention-full=2");
|
|
strLstAddZ(argList, "--repo1-retention-diff=3");
|
|
strLstAddZ(argList, "--repo1-retention-archive=2");
|
|
strLstAddZ(argList, "--repo1-retention-archive-type=diff");
|
|
hrnCfgArgRawZ(argList, cfgOptRepo, "1");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "expire last backup in archive sub path and remove sub path");
|
|
TEST_RESULT_BOOL(
|
|
storagePathExistsP(storageTest, strNewFmt("%s/%s", strZ(archiveStanzaPath), "9.4-1/0000000100000000")), false,
|
|
"archive sub path removed");
|
|
harnessLogResult(
|
|
"P00 INFO: expire full backup 20181119-152138F\n"
|
|
"P00 INFO: remove expired backup 20181119-152138F");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire command - dry run: archive and backups not removed");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-archive=1");
|
|
strLstAddZ(argList, "--dry-run");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "expire (dry-run) - log expired backups and archive path to remove");
|
|
TEST_RESULT_BOOL(
|
|
storagePathExistsP(storageTest, strNewFmt("%s/%s", strZ(archiveStanzaPath), "9.4-1")), true,
|
|
"archive path not removed");
|
|
TEST_RESULT_BOOL(
|
|
(storageExistsP(storageTest, strNewFmt("%s/20181119-152800F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152800F_20181119-152152D/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152800F_20181119-152155I/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152800F_20181119-152252D/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath)))),
|
|
true, "backup not removed");
|
|
harnessLogResult(strZ(strNewFmt(
|
|
"P00 INFO: [DRY-RUN] expire full backup set: 20181119-152800F, 20181119-152800F_20181119-152152D, "
|
|
"20181119-152800F_20181119-152155I, 20181119-152800F_20181119-152252D\n"
|
|
"P00 INFO: [DRY-RUN] remove expired backup 20181119-152800F_20181119-152252D\n"
|
|
"P00 INFO: [DRY-RUN] remove expired backup 20181119-152800F_20181119-152155I\n"
|
|
"P00 INFO: [DRY-RUN] remove expired backup 20181119-152800F_20181119-152152D\n"
|
|
"P00 INFO: [DRY-RUN] remove expired backup 20181119-152800F\n"
|
|
"P00 INFO: [DRY-RUN] remove archive path: %s/%s/9.4-1", testPath(), strZ(archiveStanzaPath))));
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire via backup command - archive and backups removed");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-archive=1");
|
|
strLstAdd(argList, strNewFmt("--pg1-path=%s/pg", testPath()));
|
|
harnessCfgLoad(cfgCmdBackup, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "via backup command: expire backups and remove archive path");
|
|
TEST_RESULT_BOOL(
|
|
storagePathExistsP(storageTest, strNewFmt("%s/%s", strZ(archiveStanzaPath), "9.4-1")),
|
|
false, "archive path removed");
|
|
|
|
harnessLogResult(strZ(strNewFmt(
|
|
"P00 INFO: expire full backup set: 20181119-152800F, 20181119-152800F_20181119-152152D, "
|
|
"20181119-152800F_20181119-152155I, 20181119-152800F_20181119-152252D\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F_20181119-152252D\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F_20181119-152155I\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F_20181119-152152D\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F\n"
|
|
"P00 INFO: remove archive path: %s/%s/9.4-1", testPath(), strZ(archiveStanzaPath))));
|
|
|
|
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
|
TEST_RESULT_UINT(infoBackupDataTotal(infoBackup), 2, "backup.info updated on disk");
|
|
TEST_RESULT_STRLST_Z(
|
|
strLstSort(infoBackupDataLabelList(infoBackup, NULL), sortOrderAsc),
|
|
"20181119-152900F\n20181119-152900F_20181119-152500I\n", "remaining current backups correct");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire command - archive removed");
|
|
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 1, "9.4-1", "0000000100000000");
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-archive=1");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "expire remove archive path");
|
|
harnessLogResult(strZ(strNewFmt("P00 INFO: remove archive path: %s/%s/9.4-1", testPath(), strZ(archiveStanzaPath))));
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
storagePutP(storageNewWriteP(storageTest, backupInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[backup:current]\n"
|
|
"20181119-152138F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000002\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152900F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000004\",\"backup-archive-stop\":\"000000010000000000000004\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201707211\n"
|
|
"db-control-version=1002\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}\n"
|
|
"2={\"db-catalog-version\":201707211,\"db-control-version\":1002,\"db-system-id\":6626363367545678089,"
|
|
"\"db-version\":\"10\"}\n"));
|
|
|
|
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
|
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 5, "9.4-1", "0000000100000000");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("retention backup no archive-start");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-archive=2");
|
|
strLstAddZ(argList, "--repo1-retention-archive-type=full");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(
|
|
removeExpiredArchive(infoBackup, false), "backup selected for retention does not have archive-start so do nothing");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(1, 5, "0000000100000000"), "nothing removed from 9.4-1/0000000100000000");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("prior backup has no archive-start");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--repo1-retention-archive=1");
|
|
strLstAddZ(argList, "--repo1-retention-archive-type=full");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
harnessLogLevelSet(logLevelDetail);
|
|
|
|
TEST_RESULT_VOID(
|
|
removeExpiredArchive(infoBackup, false), "backup earlier than selected for retention does not have archive-start");
|
|
harnessLogResult(
|
|
"P00 DETAIL: archive retention on backup 20181119-152138F, archiveId = 9.4-1, start = 000000010000000000000002,"
|
|
" stop = 000000010000000000000002\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152900F, archiveId = 9.4-1, start = 000000010000000000000004\n"
|
|
"P00 DETAIL: remove archive: archiveId = 9.4-1, start = 000000010000000000000001, stop = 000000010000000000000001\n"
|
|
"P00 DETAIL: remove archive: archiveId = 9.4-1, start = 000000010000000000000003, stop = 000000010000000000000003");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire history files - dry run");
|
|
|
|
// Load Parameters
|
|
argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=2");
|
|
strLstAddZ(argList, "--dry-run");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
// Create backup.info and archives spread over different timelines
|
|
storagePutP(storageNewWriteP(storageTest, backupInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[backup:current]\n"
|
|
"20181119-152138F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000002\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152900F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000030000000000000006\",\"backup-archive-stop\":\"000000030000000000000006\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152900F_20181119-152500I={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000030000000000000008\","
|
|
"\"backup-archive-stop\":\"000000030000000000000008\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152900F\",\"backup-reference\":[\"20181119-152900F\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"diff\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201707211\n"
|
|
"db-control-version=1002\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}\n"
|
|
"2={\"db-catalog-version\":201707211,\"db-control-version\":1002,\"db-system-id\":6626363367545678089,"
|
|
"\"db-version\":\"10\"}\n"));
|
|
|
|
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
|
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152138F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, archiveInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[db]\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6625592122879095702,\"db-version\":\"9.4\"}\n"
|
|
"2={\"db-id\":6626363367545678089,\"db-version\":\"10\"}"));
|
|
|
|
storagePathRemoveP(storageTest, strNewFmt("%s/10-2/0000000100000000", strZ(archiveStanzaPath)), .recurse=true);
|
|
archiveGenerate(storageTest, archiveStanzaPath, 2, 2, "9.4-1", "0000000100000000");
|
|
archiveGenerate(storageTest, archiveStanzaPath, 6, 10, "10-2", "0000000300000000");
|
|
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/10-2/00000002.history", strZ(archiveStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/10-2/00000003.history", strZ(archiveStanzaPath))), BUFSTRDEF("tmp"));
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "expire (dry-run) do not remove 00000002.history file");
|
|
TEST_RESULT_BOOL(
|
|
storageExistsP(storageTest, strNewFmt("%s/10-2/00000002.history", strZ(archiveStanzaPath))), true,
|
|
"history file not removed");
|
|
|
|
harnessLogResult(
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152138F, archiveId = 9.4-1, "
|
|
"start = 000000010000000000000002\n"
|
|
"P00 DETAIL: [DRY-RUN] no archive to remove, archiveId = 9.4-1\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152900F, archiveId = 10-2, "
|
|
"start = 000000030000000000000006\n"
|
|
"P00 DETAIL: [DRY-RUN] no archive to remove, archiveId = 10-2\n"
|
|
"P00 DETAIL: [DRY-RUN] remove history file: archiveId = 10-2, file = 00000002.history");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire history files - no dry run");
|
|
|
|
// Load Parameters
|
|
argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=2");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "expire remove 00000002.history file");
|
|
TEST_RESULT_BOOL(
|
|
storageExistsP(storageTest, strNewFmt("%s/10-2/00000002.history", strZ(archiveStanzaPath))), false,
|
|
"00000002.history file removed");
|
|
TEST_RESULT_BOOL(
|
|
storageExistsP(storageTest, strNewFmt("%s/10-2/00000003.history", strZ(archiveStanzaPath))), true,
|
|
"00000003.history file not removed");
|
|
|
|
harnessLogResult(
|
|
"P00 DETAIL: archive retention on backup 20181119-152138F, archiveId = 9.4-1, start = 000000010000000000000002\n"
|
|
"P00 DETAIL: no archive to remove, archiveId = 9.4-1\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152900F, archiveId = 10-2, start = 000000030000000000000006\n"
|
|
"P00 DETAIL: no archive to remove, archiveId = 10-2\n"
|
|
"P00 DETAIL: remove history file: archiveId = 10-2, file = 00000002.history");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire history files via backup command");
|
|
|
|
// Load Parameters
|
|
argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=2");
|
|
strLstAdd(argList, strNewFmt("--pg1-path=%s/pg", testPath()));
|
|
harnessCfgLoad(cfgCmdBackup, argList);
|
|
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/10-2/00000002.history", strZ(archiveStanzaPath))), BUFSTRDEF("tmp"));
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "expire history files via backup command");
|
|
TEST_RESULT_BOOL(
|
|
storageExistsP(storageTest, strNewFmt("%s/10-2/00000002.history", strZ(archiveStanzaPath))), false,
|
|
"00000002.history file removed again");
|
|
TEST_RESULT_BOOL(
|
|
storageExistsP(storageTest, strNewFmt("%s/10-2/00000003.history", strZ(archiveStanzaPath))), true,
|
|
"00000003.history file not removed");
|
|
|
|
harnessLogResult(
|
|
"P00 DETAIL: archive retention on backup 20181119-152138F, archiveId = 9.4-1, start = 000000010000000000000002\n"
|
|
"P00 DETAIL: no archive to remove, archiveId = 9.4-1\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152900F, archiveId = 10-2, start = 000000030000000000000006\n"
|
|
"P00 DETAIL: no archive to remove, archiveId = 10-2\n"
|
|
"P00 DETAIL: remove history file: archiveId = 10-2, file = 00000002.history");
|
|
|
|
harnessLogLevelReset();
|
|
}
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("info files mismatch"))
|
|
{
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("archive.info has only current db with different db history id as backup.info");
|
|
|
|
// Load Parameters
|
|
StringList *argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=2");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
storagePutP(storageNewWriteP(storageTest, backupInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[backup:current]\n"
|
|
"20181119-152138F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000002\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000004\",\"backup-archive-stop\":\"000000010000000000000004\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152900F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000006\",\"backup-archive-stop\":\"000000010000000000000006\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201707211\n"
|
|
"db-control-version=1002\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":1002,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"10\"}\n"
|
|
"2={\"db-catalog-version\":201707211,\"db-control-version\":1002,\"db-system-id\":6626363367545678089,"
|
|
"\"db-version\":\"10\"}\n"));
|
|
|
|
// Write backup.manifest so infoBackup reconstruct produces same results as backup.info on disk and removeExpiredBackup
|
|
// will find backup directories to remove
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152138F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152900F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, archiveInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[db]\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6626363367545678089,\"db-version\":\"10\"}"));
|
|
|
|
// Create 10-1 and 10-2 although 10-2 is not realistic since the archive.info knows nothing about it - it is just to
|
|
// confirm that nothing from disk is removed and it will also be used for the next test.
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 7, "10-1", "0000000100000000");
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 7, "10-2", "0000000100000000");
|
|
|
|
TEST_ERROR(cmdExpire(), FormatError, "archive expiration cannot continue - archive and backup history lists do not match");
|
|
harnessLogResult(
|
|
"P00 INFO: expire full backup 20181119-152138F\n"
|
|
"P00 INFO: remove expired backup 20181119-152138F");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "10-1", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(1, 7, "0000000100000000"), "none removed from 10-1/0000000100000000");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "10-2", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(1, 7, "0000000100000000"), "none removed from 10-2/0000000100000000");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("archive.info old history db system id not the same as backup.info");
|
|
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, archiveInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[db]\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6626363367545671234,\"db-version\":\"10\"}\n"
|
|
"2={\"db-id\":6626363367545678089,\"db-version\":\"10\"}"));
|
|
|
|
TEST_ERROR(cmdExpire(), FormatError, "archive expiration cannot continue - archive and backup history lists do not match");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("archive.info old history db version not the same as backup.info");
|
|
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, archiveInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[db]\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6625592122879095702,\"db-version\":\"9.4\"}\n"
|
|
"2={\"db-id\":6626363367545678089,\"db-version\":\"10\"}"));
|
|
|
|
TEST_ERROR(cmdExpire(), FormatError, "archive expiration cannot continue - archive and backup history lists do not match");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("archive.info has only current db with same db history id as backup.info");
|
|
|
|
storagePutP(storageNewWriteP(storageTest, backupInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[backup:current]\n"
|
|
"20181119-152138F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000002\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000004\",\"backup-archive-stop\":\"000000010000000000000004\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152900F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000006\",\"backup-archive-stop\":\"000000010000000000000006\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201707211\n"
|
|
"db-control-version=1002\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":1002,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"10\"}\n"
|
|
"2={\"db-catalog-version\":201707211,\"db-control-version\":1002,\"db-system-id\":6626363367545678089,"
|
|
"\"db-version\":\"10\"}\n"));
|
|
|
|
// Write backup.manifest so infoBackup reconstruct produces same results as backup.info on disk and removeExpiredBackup
|
|
// will find backup directories to remove
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152138F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152900F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, archiveInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[db]\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"10\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"2={\"db-id\":6626363367545678089,\"db-version\":\"10\"}"));
|
|
|
|
argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=1");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
// Here, although backup 20181119-152138F of 10-1 will be expired, the WAL in 10-1 will not since the archive.info
|
|
// does not know about that dir. Again, not really realistic since if it is on disk and reconstructed it would have. So
|
|
// here we are testing that things on disk that we are not aware of are not touched.
|
|
TEST_RESULT_VOID(cmdExpire(), "Expire archive that archive.info is aware of");
|
|
|
|
harnessLogResult(
|
|
"P00 INFO: expire full backup 20181119-152138F\n"
|
|
"P00 INFO: expire full backup 20181119-152800F\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F\n"
|
|
"P00 INFO: remove expired backup 20181119-152138F");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "10-1", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(1, 7, "0000000100000000"), "none removed from 10-1/0000000100000000");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "10-2", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(6, 7, "0000000100000000"),
|
|
"all prior to 000000010000000000000006 removed from 10-2/0000000100000000");
|
|
}
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("expireAdhocBackup()"))
|
|
{
|
|
// Create backup.info
|
|
storagePutP(storageNewWriteP(storageTest, backupInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[backup:current]\n"
|
|
"20181119-152138F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000020000000000000001\",\"backup-archive-stop\":\"000000020000000000000001\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000020000000000000002\",\"backup-archive-stop\":\"000000020000000000000002\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F_20181119-152152D={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000020000000000000004\","
|
|
"\"backup-archive-stop\":\"000000020000000000000005\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152800F\",\"backup-reference\":[\"20181119-152800F\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"diff\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F_20181119-152155I={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000020000000000000007\","
|
|
"\"backup-archive-stop\":\"000000020000000000000007\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152800F_20181119-152152D\","
|
|
"\"backup-reference\":[\"20181119-152800F\",\"20181119-152800F_20181119-152152D\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"incr\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152800F_20181119-152252D={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000020000000000000009\","
|
|
"\"backup-archive-stop\":\"000000020000000000000009\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152800F\",\"backup-reference\":[\"20181119-152800F\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"diff\","
|
|
"\"db-id\":1,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152850F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000004\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152900F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000006\",\"backup-archive-stop\":\"000000010000000000000007\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201909212\n"
|
|
"db-control-version=1201\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"12\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}\n"
|
|
"2={\"db-catalog-version\":201909212,\"db-control-version\":1201,\"db-system-id\":6626363367545678089,"
|
|
"\"db-version\":\"12\"}\n"));
|
|
|
|
// Add backup directories with manifest file including a resumable backup dependent on last backup
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152138F/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F_20181119-152152D/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F_20181119-152155I/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F_20181119-152252D/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152850F/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152900F/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
// Resumable backup
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152900F_20181119-153000I/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
|
|
strZ(backupStanzaPath))),
|
|
harnessInfoChecksumZ(
|
|
"[backup]\n"
|
|
"backup-archive-start=\"000000010000000000000008\"\n"
|
|
"backup-label=null\n"
|
|
"backup-prior=\"20181119-152900F\"\n"
|
|
"backup-timestamp-copy-start=0\n"
|
|
"backup-timestamp-start=0\n"
|
|
"backup-timestamp-stop=0\n"
|
|
"backup-type=\"incr\"\n"
|
|
"\n"
|
|
"[backup:db]\n"
|
|
"db-catalog-version=201909212\n"
|
|
"db-control-version=1201\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"12\"\n"
|
|
"\n"
|
|
"[backup:option]\n"
|
|
"option-archive-check=false\n"
|
|
"option-archive-copy=false\n"
|
|
"option-checksum-page=false\n"
|
|
"option-compress=false\n"
|
|
"option-compress-type=\"none\"\n"
|
|
"option-hardlink=false\n"
|
|
"option-online=false\n"
|
|
"\n"
|
|
"[backup:target]\n"
|
|
"pg_data={\"path\":\"{[path]}/pg\",\"type\":\"path\"}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"postgres={\"db-id\":12980,\"db-last-system-id\":12979}\n"
|
|
"\n"
|
|
"[target:file]\n"
|
|
"pg_data/PG_VERSION={\"size\":3,\"timestamp\":1565282100}\n"
|
|
"\n"
|
|
"[target:file:default]\n"
|
|
"group=\"postgres\"\n"
|
|
"master=false\n"
|
|
"mode=\"0600\"\n"
|
|
"user=\"postgres\"\n"
|
|
"\n"
|
|
"[target:path]\n"
|
|
"pg_data={}\n"
|
|
"\n"
|
|
"[target:path:default]\n"
|
|
"group=\"postgres\"\n"
|
|
"mode=\"0700\"\n"
|
|
"user=\"postgres\"\n"));
|
|
|
|
InfoBackup *infoBackup = NULL;
|
|
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
|
|
|
// Create "latest" symlink
|
|
const String *latestLink = storagePathP(storageTest, strNewFmt("%s/latest", strZ(backupStanzaPath)));
|
|
THROW_ON_SYS_ERROR_FMT(
|
|
symlink(strZ(infoBackupData(infoBackup, infoBackupDataTotal(infoBackup) - 1).backupLabel), strZ(latestLink)) == -1,
|
|
FileOpenError, "unable to create symlink '%s' to '%s'", strZ(latestLink),
|
|
strZ(infoBackupData(infoBackup, infoBackupDataTotal(infoBackup) - 1).backupLabel));
|
|
|
|
// Create archive info
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, archiveInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[db]\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"12\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6625592122879095702,\"db-version\":\"9.4\"}\n"
|
|
"2={\"db-id\":6626363367545678089,\"db-version\":\"12\"}"));
|
|
|
|
// Create archive directories and generate archive
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 10, "9.4-1", "0000000200000000");
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 10, "12-2", "0000000100000000");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("invalid backup label");
|
|
|
|
TEST_RESULT_UINT(
|
|
expireAdhocBackup(infoBackup, STRDEF("20201119-123456F_20201119-234567I")), 0,
|
|
"label format OK but backup does not exist");
|
|
harnessLogResult(
|
|
"P00 WARN: backup 20201119-123456F_20201119-234567I does not exist\n"
|
|
" HINT: run the info command and confirm the backup is listed");
|
|
|
|
TEST_ERROR(
|
|
expireAdhocBackup(infoBackup, STRDEF(BOGUS_STR)), OptionInvalidValueError,
|
|
"'" BOGUS_STR "' is not a valid backup label format");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire backup and dependent");
|
|
|
|
StringList *argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=1");
|
|
strLstAddZ(argList, "--set=20181119-152800F_20181119-152152D");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
// Set the log level to detail so archive expiration messages are seen
|
|
harnessLogLevelSet(logLevelDetail);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "adhoc expire only backup and dependent");
|
|
TEST_RESULT_BOOL(
|
|
(storageExistsP(storageTest, strNewFmt("%s/20181119-152138F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(storageTest, strNewFmt("%s/20181119-152800F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152800F_20181119-152252D/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152850F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152900F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152900F_20181119-153000I/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
|
|
strZ(backupStanzaPath))) &&
|
|
!storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152800F_20181119-152152D/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
!storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152800F_20181119-152155I/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath)))),
|
|
true, "only adhoc and dependents removed - resumable and all other backups remain");
|
|
TEST_RESULT_STR(storageInfoP(storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest")).linkDestination,
|
|
STRDEF("20181119-152900F"), "latest link not updated");
|
|
harnessLogResult(
|
|
"P00 INFO: expire adhoc backup set: 20181119-152800F_20181119-152152D, 20181119-152800F_20181119-152155I\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F_20181119-152155I\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F_20181119-152152D\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152138F, archiveId = 9.4-1, start = 000000020000000000000001,"
|
|
" stop = 000000020000000000000001\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152800F, archiveId = 9.4-1, start = 000000020000000000000002\n"
|
|
"P00 DETAIL: no archive to remove, archiveId = 9.4-1\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152850F, archiveId = 12-2, start = 000000010000000000000002,"
|
|
" stop = 000000010000000000000004\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152900F, archiveId = 12-2, start = 000000010000000000000006\n"
|
|
"P00 DETAIL: remove archive: archiveId = 12-2, start = 000000010000000000000001, stop = 000000010000000000000001\n"
|
|
"P00 DETAIL: remove archive: archiveId = 12-2, start = 000000010000000000000005, stop = 000000010000000000000005");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire full and archive (no dependents)");
|
|
|
|
argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=1");
|
|
strLstAddZ(argList, "--set=20181119-152138F");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "adhoc expire full backup");
|
|
TEST_RESULT_BOOL(
|
|
(storageExistsP(storageTest, strNewFmt("%s/20181119-152800F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152800F_20181119-152252D/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152850F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152900F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152900F_20181119-153000I/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
|
|
strZ(backupStanzaPath))) &&
|
|
!storageExistsP(storageTest, strNewFmt("%s/20181119-152138F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath)))),
|
|
true, "only adhoc full removed");
|
|
harnessLogResult(
|
|
"P00 INFO: expire adhoc backup 20181119-152138F\n"
|
|
"P00 INFO: remove expired backup 20181119-152138F\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152800F, archiveId = 9.4-1, start = 000000020000000000000002\n"
|
|
"P00 DETAIL: remove archive: archiveId = 9.4-1, start = 000000020000000000000001, stop = 000000020000000000000001\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152850F, archiveId = 12-2, start = 000000010000000000000002,"
|
|
" stop = 000000010000000000000004\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152900F, archiveId = 12-2, start = 000000010000000000000006\n"
|
|
"P00 DETAIL: no archive to remove, archiveId = 12-2");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire latest and resumable");
|
|
|
|
argList = strLstDup(argListBase);
|
|
strLstAddZ(argList, "--repo1-retention-full=1");
|
|
strLstAddZ(argList, "--set=20181119-152900F");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
String *archiveRemaining = strNew("");
|
|
strCatFmt(
|
|
archiveRemaining, "%s%s", strZ(archiveExpectList(2, 4, "0000000100000000")),
|
|
strZ(archiveExpectList(6, 10, "0000000100000000")));
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "adhoc expire latest backup");
|
|
TEST_RESULT_BOOL(
|
|
(storageExistsP(storageTest, strNewFmt("%s/20181119-152800F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152800F_20181119-152252D/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
!storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152900F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
!storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152900F_20181119-153000I/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
|
|
strZ(backupStanzaPath)))),
|
|
true, "latest and resumable removed");
|
|
harnessLogResult(
|
|
"P00 WARN: expiring latest backup 20181119-152900F - the ability to perform point-in-time-recovery (PITR) may be"
|
|
" affected\n"
|
|
" HINT: non-default settings for 'repo1-retention-archive'/'repo1-retention-archive-type'"
|
|
" (even in prior expires) can cause gaps in the WAL.\n"
|
|
"P00 INFO: expire adhoc backup 20181119-152900F\n"
|
|
"P00 INFO: remove expired backup 20181119-152900F_20181119-153000I\n"
|
|
"P00 INFO: remove expired backup 20181119-152900F\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152800F, archiveId = 9.4-1, start = 000000020000000000000002\n"
|
|
"P00 DETAIL: no archive to remove, archiveId = 9.4-1\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152850F, archiveId = 12-2, start = 000000010000000000000002\n"
|
|
"P00 DETAIL: no archive to remove, archiveId = 12-2");
|
|
TEST_RESULT_STR(storageInfoP(storageRepo(), STRDEF(STORAGE_REPO_BACKUP "/latest")).linkDestination,
|
|
STRDEF("20181119-152850F"), "latest link updated");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "12-2", "0000000100000000")), sortOrderAsc),
|
|
archiveRemaining,
|
|
"no archives removed from latest except what was already removed");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("error on expire last full backup in current db-id");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--set=20181119-152850F");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_ERROR(
|
|
cmdExpire(), BackupSetInvalidError,
|
|
"full backup 20181119-152850F cannot be expired until another full backup has been created");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("allow adhoc expire on last full backup in prior db-id");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--set=20181119-152800F");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "adhoc expire last prior db-id backup");
|
|
TEST_RESULT_BOOL(
|
|
(storageExistsP(storageTest, strNewFmt("%s/20181119-152850F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
!storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152800F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))) &&
|
|
!storageExistsP(
|
|
storageTest, strNewFmt("%s/20181119-152800F_20181119-152252D/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath)))),
|
|
true, "only last prior backup removed");
|
|
harnessLogResult(
|
|
strZ(strNewFmt(
|
|
"P00 INFO: expire adhoc backup set: 20181119-152800F, 20181119-152800F_20181119-152252D\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F_20181119-152252D\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F\n"
|
|
"P00 INFO: remove archive path: %s/repo/archive/db/9.4-1\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152850F, archiveId = 12-2, start = 000000010000000000000002\n"
|
|
"P00 DETAIL: no archive to remove, archiveId = 12-2", testPath())));
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("error on expire last full backup on disk");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--set=20181119-152850F");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_ERROR(
|
|
cmdExpire(), BackupSetInvalidError,
|
|
"full backup 20181119-152850F cannot be expired until another full backup has been created");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("adhoc dry-run");
|
|
|
|
// Create backup.info
|
|
storagePutP(storageNewWriteP(storageTest, backupInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[backup:current]\n"
|
|
"20181119-152850F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000004\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152850F_20181119-152252D={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000010000000000000006\","
|
|
"\"backup-archive-stop\":\"000000010000000000000007\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152850F\",\"backup-reference\":[\"20181119-152850F\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"diff\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201909212\n"
|
|
"db-control-version=1201\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"12\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}\n"
|
|
"2={\"db-catalog-version\":201909212,\"db-control-version\":1201,\"db-system-id\":6626363367545678089,"
|
|
"\"db-version\":\"12\"}\n"));
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--set=20181119-152850F_20181119-152252D");
|
|
strLstAddZ(argList, "--dry-run");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
// Load the backup info. Do not store a manifest file for the adhoc backup for code coverage
|
|
TEST_ASSIGN(infoBackup, infoBackupLoadFile(storageTest, backupInfoFileName, cipherTypeNone, NULL), "get backup.info");
|
|
|
|
// Create the manifest file to create the directory then remove the file for code coverage
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152850F_20181119-152252D/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storageRemoveP(
|
|
storageTest, strNewFmt("%s/20181119-152850F_20181119-152252D/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath)));
|
|
|
|
String *adhocBackupLabel = strNew("20181119-152850F_20181119-152252D");
|
|
TEST_RESULT_UINT(expireAdhocBackup(infoBackup, adhocBackupLabel), 1, "adhoc expire last dependent backup");
|
|
TEST_RESULT_VOID(removeExpiredBackup(infoBackup, adhocBackupLabel), "code coverage: removeExpireBackup with no manifests");
|
|
harnessLogResult(
|
|
"P00 WARN: [DRY-RUN] expiring latest backup 20181119-152850F_20181119-152252D - the ability to perform"
|
|
" point-in-time-recovery (PITR) may be affected\n"
|
|
" HINT: non-default settings for 'repo1-retention-archive'/'repo1-retention-archive-type'"
|
|
" (even in prior expires) can cause gaps in the WAL.\n"
|
|
"P00 INFO: [DRY-RUN] expire adhoc backup 20181119-152850F_20181119-152252D\n"
|
|
"P00 INFO: [DRY-RUN] remove expired backup 20181119-152850F_20181119-152252D");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("resumable possibly based on adhoc expire backup");
|
|
|
|
argList = strLstDup(argListAvoidWarn);
|
|
strLstAddZ(argList, "--set=20181119-152850F_20181119-152252D");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
// Create backup.info
|
|
storagePutP(storageNewWriteP(storageTest, backupInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[backup:current]\n"
|
|
"20181119-152850F={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\","
|
|
"\"backup-archive-start\":\"000000010000000000000002\",\"backup-archive-stop\":\"000000010000000000000004\","
|
|
"\"backup-info-repo-size\":2369186,\"backup-info-repo-size-delta\":2369186,"
|
|
"\"backup-info-size\":20162900,\"backup-info-size-delta\":20162900,"
|
|
"\"backup-timestamp-start\":1542640898,\"backup-timestamp-stop\":1542640911,\"backup-type\":\"full\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"20181119-152850F_20181119-152252D={"
|
|
"\"backrest-format\":5,\"backrest-version\":\"2.08dev\",\"backup-archive-start\":\"000000010000000000000006\","
|
|
"\"backup-archive-stop\":\"000000010000000000000007\",\"backup-info-repo-size\":2369186,"
|
|
"\"backup-info-repo-size-delta\":346,\"backup-info-size\":20162900,\"backup-info-size-delta\":8428,"
|
|
"\"backup-prior\":\"20181119-152850F\",\"backup-reference\":[\"20181119-152850F\"],"
|
|
"\"backup-timestamp-start\":1542640912,\"backup-timestamp-stop\":1542640915,\"backup-type\":\"diff\","
|
|
"\"db-id\":2,\"option-archive-check\":true,\"option-archive-copy\":false,\"option-backup-standby\":false,"
|
|
"\"option-checksum-page\":true,\"option-compress\":true,\"option-hardlink\":false,\"option-online\":true}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"db-catalog-version=201909212\n"
|
|
"db-control-version=1201\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"12\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}\n"
|
|
"2={\"db-catalog-version\":201909212,\"db-control-version\":1201,\"db-system-id\":6626363367545678089,"
|
|
"\"db-version\":\"12\"}\n"));
|
|
|
|
// Adhoc backup and resumable backup manifests
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152850F_20181119-152252D/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152850F_20181200-152252D/" BACKUP_MANIFEST_FILE INFO_COPY_EXT,
|
|
strZ(backupStanzaPath))),
|
|
harnessInfoChecksumZ(
|
|
"[backup]\n"
|
|
"backup-archive-start=\"000000010000000000000009\"\n"
|
|
"backup-label=null\n"
|
|
"backup-prior=\"20181119-152850F\"\n"
|
|
"backup-timestamp-copy-start=0\n"
|
|
"backup-timestamp-start=0\n"
|
|
"backup-timestamp-stop=0\n"
|
|
"backup-type=\"incr\"\n"
|
|
"\n"
|
|
"[backup:db]\n"
|
|
"db-catalog-version=201909212\n"
|
|
"db-control-version=1201\n"
|
|
"db-id=2\n"
|
|
"db-system-id=6626363367545678089\n"
|
|
"db-version=\"12\"\n"
|
|
"\n"
|
|
"[backup:option]\n"
|
|
"option-archive-check=false\n"
|
|
"option-archive-copy=false\n"
|
|
"option-checksum-page=false\n"
|
|
"option-compress=false\n"
|
|
"option-compress-type=\"none\"\n"
|
|
"option-hardlink=false\n"
|
|
"option-online=false\n"
|
|
"\n"
|
|
"[backup:target]\n"
|
|
"pg_data={\"path\":\"{[path]}/pg\",\"type\":\"path\"}\n"
|
|
"\n"
|
|
"[db]\n"
|
|
"postgres={\"db-id\":12980,\"db-last-system-id\":12979}\n"
|
|
"\n"
|
|
"[target:file]\n"
|
|
"pg_data/PG_VERSION={\"size\":3,\"timestamp\":1565282100}\n"
|
|
"\n"
|
|
"[target:file:default]\n"
|
|
"group=\"postgres\"\n"
|
|
"master=false\n"
|
|
"mode=\"0600\"\n"
|
|
"user=\"postgres\"\n"
|
|
"\n"
|
|
"[target:path]\n"
|
|
"pg_data={}\n"
|
|
"\n"
|
|
"[target:path:default]\n"
|
|
"group=\"postgres\"\n"
|
|
"mode=\"0700\"\n"
|
|
"user=\"postgres\"\n"));
|
|
|
|
archiveGenerate(storageTest, archiveStanzaPath, 2, 10, "12-2", "0000000100000000");
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "adhoc expire latest with resumable possibly based on it");
|
|
harnessLogResult(
|
|
"P00 WARN: expiring latest backup 20181119-152850F_20181119-152252D - the ability to perform point-in-time-recovery"
|
|
" (PITR) may be affected\n"
|
|
" HINT: non-default settings for 'repo1-retention-archive'/'repo1-retention-archive-type'"
|
|
" (even in prior expires) can cause gaps in the WAL.\n"
|
|
"P00 INFO: expire adhoc backup 20181119-152850F_20181119-152252D\n"
|
|
"P00 INFO: remove expired backup 20181119-152850F_20181119-152252D\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152850F, archiveId = 12-2, start = 000000010000000000000002\n"
|
|
"P00 DETAIL: no archive to remove, archiveId = 12-2");
|
|
|
|
harnessLogLevelReset();
|
|
}
|
|
|
|
// *****************************************************************************************************************************
|
|
if (testBegin("expireTimeBasedBackup()"))
|
|
{
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("no current backups");
|
|
|
|
InfoBackup *infoBackup = NULL;
|
|
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(harnessInfoChecksumZ(
|
|
"[db]\n"
|
|
"db-catalog-version=201409291\n"
|
|
"db-control-version=942\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6625592122879095702\n"
|
|
"db-version=\"9.4\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-catalog-version\":201409291,\"db-control-version\":942,\"db-system-id\":6625592122879095702,"
|
|
"\"db-version\":\"9.4\"}"))), "empty backup.info");
|
|
|
|
TEST_RESULT_UINT(expireTimeBasedBackup(infoBackup, (time_t)(timeNow - (40 * SEC_PER_DAY))), 0, "no backups to expire");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
// Set up
|
|
StringList *argListTime = strLstDup(argListBase);
|
|
strLstAddZ(argListTime, "--repo1-retention-full-type=time");
|
|
|
|
// Create backup.info and archive.info
|
|
storagePutP(storageNewWriteP(storageTest, backupInfoFileName), backupInfoBase);
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, archiveInfoFileName),
|
|
harnessInfoChecksumZ(
|
|
"[db]\n"
|
|
"db-id=1\n"
|
|
"db-system-id=6625592122879095702\n"
|
|
"db-version=\"9.4\"\n"
|
|
"\n"
|
|
"[db:history]\n"
|
|
"1={\"db-id\":6625592122879095702,\"db-version\":\"9.4\"}"));
|
|
|
|
// Write backup.manifest so infoBackup reconstruct produces same results as backup.info on disk
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152138F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F_20181119-152152D/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152800F_20181119-152155I/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152900F/" BACKUP_MANIFEST_FILE, strZ(backupStanzaPath))),
|
|
BUFSTRDEF("tmp"));
|
|
storagePutP(
|
|
storageNewWriteP(storageTest, strNewFmt("%s/20181119-152900F_20181119-152600D/" BACKUP_MANIFEST_FILE,
|
|
strZ(backupStanzaPath))), BUFSTRDEF("tmp"));
|
|
|
|
// Genreate archive for backups in backup.info
|
|
archiveGenerate(storageTest, archiveStanzaPath, 1, 11, "9.4-1", "0000000100000000");
|
|
|
|
// Set the log level to detail so archive expiration messages are seen
|
|
harnessLogLevelSet(logLevelDetail);
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("oldest backup not expired");
|
|
|
|
StringList *argList = strLstDup(argListTime);
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_ASSIGN(infoBackup, infoBackupNewLoad(ioBufferReadNew(backupInfoBase)), "get backup.info");
|
|
TEST_RESULT_VOID(cmdExpire(), "repo-retention-full not set for time-based");
|
|
harnessLogResult(
|
|
"P00 WARN: option 'repo1-retention-full' is not set for 'repo1-retention-full-type=time', the repository may run out"
|
|
" of space\n"
|
|
" HINT: to retain full backups indefinitely (without warning), set option 'repo1-retention-full' to the"
|
|
" maximum.\n"
|
|
"P00 INFO: time-based archive retention not met - archive logs will not be expired");
|
|
|
|
// Stop time equals retention time
|
|
TEST_RESULT_UINT(
|
|
expireTimeBasedBackup(infoBackup, (time_t)(timeNow - (40 * SEC_PER_DAY))), 0,
|
|
"oldest backup stop time equals retention time");
|
|
TEST_RESULT_STRLST_Z(
|
|
infoBackupDataLabelList(infoBackup, NULL),
|
|
"20181119-152138F\n20181119-152800F\n20181119-152800F_20181119-152152D\n20181119-152800F_20181119-152155I\n"
|
|
"20181119-152900F\n20181119-152900F_20181119-152600D\n", "no backups expired");
|
|
|
|
// Add a time period
|
|
strLstAddZ(argList, "--repo1-retention-full=35");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "oldest backup older but other backups too young");
|
|
TEST_RESULT_STRLST_STR(
|
|
strLstSort(storageListP(
|
|
storageTest, strNewFmt("%s/%s/%s", strZ(archiveStanzaPath), "9.4-1", "0000000100000000")), sortOrderAsc),
|
|
archiveExpectList(1, 11, "0000000100000000"),
|
|
"no archives expired");
|
|
TEST_RESULT_STRLST_Z(
|
|
infoBackupDataLabelList(infoBackup, NULL),
|
|
"20181119-152138F\n20181119-152800F\n20181119-152800F_20181119-152152D\n20181119-152800F_20181119-152155I\n"
|
|
"20181119-152900F\n20181119-152900F_20181119-152600D\n", "no backups expired");
|
|
harnessLogResult("P00 INFO: time-based archive retention not met - archive logs will not be expired");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("oldest backup expired");
|
|
|
|
argList = strLstDup(argListTime);
|
|
strLstAddZ(argList, "--repo1-retention-full=30");
|
|
strLstAddZ(argList, "--dry-run");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
TEST_RESULT_VOID(cmdExpire(), "only oldest backup expired - dry-run");
|
|
harnessLogResult(
|
|
"P00 INFO: [DRY-RUN] expire time-based backup 20181119-152138F\n"
|
|
"P00 INFO: [DRY-RUN] remove expired backup 20181119-152138F\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152800F, archiveId = 9.4-1,"
|
|
" start = 000000010000000000000004\n"
|
|
"P00 DETAIL: [DRY-RUN] remove archive: archiveId = 9.4-1, start = 000000010000000000000001,"
|
|
" stop = 000000010000000000000003");
|
|
|
|
strLstAddZ(argList, "--repo1-retention-archive=9999999");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
TEST_RESULT_VOID(cmdExpire(), "only oldest backup expired - dry-run, retention-archive set to max, no archives expired");
|
|
harnessLogResult(
|
|
"P00 INFO: [DRY-RUN] expire time-based backup 20181119-152138F\n"
|
|
"P00 INFO: [DRY-RUN] remove expired backup 20181119-152138F");
|
|
|
|
argList = strLstDup(argListTime);
|
|
strLstAddZ(argList, "--repo1-retention-full=30");
|
|
strLstAddZ(argList, "--repo1-retention-archive=1"); // 1-day: expire all non-essential archive prior to newest full backup
|
|
strLstAddZ(argList, "--dry-run");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
TEST_RESULT_VOID(cmdExpire(), "only oldest backup expired but retention archive set lower - dry-run");
|
|
harnessLogResult(
|
|
"P00 INFO: [DRY-RUN] expire time-based backup 20181119-152138F\n"
|
|
"P00 INFO: [DRY-RUN] remove expired backup 20181119-152138F\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152800F, archiveId = 9.4-1,"
|
|
" start = 000000010000000000000004, stop = 000000010000000000000004\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152800F_20181119-152152D, archiveId = 9.4-1,"
|
|
" start = 000000010000000000000006, stop = 000000010000000000000006\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152800F_20181119-152155I, archiveId = 9.4-1,"
|
|
" start = 000000010000000000000007, stop = 000000010000000000000007\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152900F, archiveId = 9.4-1,"
|
|
" start = 000000010000000000000009\n"
|
|
"P00 DETAIL: [DRY-RUN] remove archive: archiveId = 9.4-1, start = 000000010000000000000001,"
|
|
" stop = 000000010000000000000003\n"
|
|
"P00 DETAIL: [DRY-RUN] remove archive: archiveId = 9.4-1, start = 000000010000000000000005,"
|
|
" stop = 000000010000000000000005\n"
|
|
"P00 DETAIL: [DRY-RUN] remove archive: archiveId = 9.4-1, start = 000000010000000000000008,"
|
|
" stop = 000000010000000000000008");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("repo1-retention-archive-type=diff");
|
|
|
|
argList = strLstDup(argListTime);
|
|
strLstAddZ(argList, "--repo1-retention-full=30");
|
|
strLstAddZ(argList, "--repo1-retention-archive-type=diff");
|
|
strLstAddZ(argList, "--repo1-retention-archive=1"); // 1-diff: expire all non-essential archive prior to newest diff backup
|
|
strLstAddZ(argList, "--dry-run");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "only oldest backup expired, retention archive is DIFF - dry-run");
|
|
harnessLogResult(
|
|
"P00 WARN: [DRY-RUN] option 'repo1-retention-diff' is not set for 'repo1-retention-archive-type=diff'\n"
|
|
" HINT: to retain differential backups indefinitely (without warning), set option 'repo1-retention-diff'"
|
|
" to the maximum.\n"
|
|
"P00 INFO: [DRY-RUN] expire time-based backup 20181119-152138F\n"
|
|
"P00 INFO: [DRY-RUN] remove expired backup 20181119-152138F\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152800F, archiveId = 9.4-1,"
|
|
" start = 000000010000000000000004, stop = 000000010000000000000004\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152800F_20181119-152152D, archiveId = 9.4-1,"
|
|
" start = 000000010000000000000006, stop = 000000010000000000000006\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152800F_20181119-152155I, archiveId = 9.4-1,"
|
|
" start = 000000010000000000000007, stop = 000000010000000000000007\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152900F, archiveId = 9.4-1,"
|
|
" start = 000000010000000000000009, stop = 000000010000000000000009\n"
|
|
"P00 DETAIL: [DRY-RUN] archive retention on backup 20181119-152900F_20181119-152600D, archiveId = 9.4-1,"
|
|
" start = 000000010000000000000011\n"
|
|
"P00 DETAIL: [DRY-RUN] remove archive: archiveId = 9.4-1, start = 000000010000000000000001,"
|
|
" stop = 000000010000000000000003\n"
|
|
"P00 DETAIL: [DRY-RUN] remove archive: archiveId = 9.4-1, start = 000000010000000000000005,"
|
|
" stop = 000000010000000000000005\n"
|
|
"P00 DETAIL: [DRY-RUN] remove archive: archiveId = 9.4-1, start = 000000010000000000000008,"
|
|
" stop = 000000010000000000000008\n"
|
|
"P00 DETAIL: [DRY-RUN] remove archive: archiveId = 9.4-1, start = 000000010000000000000010,"
|
|
" stop = 000000010000000000000010");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("expire oldest full");
|
|
|
|
argList = strLstDup(argListTime);
|
|
strLstAddZ(argList, "--repo1-retention-full=25");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
// Expire oldest from backup.info only, leaving the backup and archives on disk then save backup.info without oldest backup
|
|
TEST_RESULT_UINT(expireTimeBasedBackup(infoBackup, (time_t)(timeNow - (25 * SEC_PER_DAY))), 1, "expire oldest backup");
|
|
TEST_RESULT_VOID(
|
|
infoBackupSaveFile(infoBackup, storageTest, backupInfoFileName, cipherTypeNone, NULL),
|
|
"save backup.info without oldest");
|
|
harnessLogResult("P00 INFO: expire time-based backup 20181119-152138F");
|
|
TEST_RESULT_VOID(cmdExpire(), "only oldest backup expired");
|
|
harnessLogResult(
|
|
"P00 INFO: remove expired backup 20181119-152138F\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152800F, archiveId = 9.4-1, start = 000000010000000000000004\n"
|
|
"P00 DETAIL: remove archive: archiveId = 9.4-1, start = 000000010000000000000001, stop = 000000010000000000000003");
|
|
|
|
//--------------------------------------------------------------------------------------------------------------------------
|
|
TEST_TITLE("newest backup - retention met but must keep one");
|
|
|
|
argList = strLstDup(argListTime);
|
|
strLstAddZ(argList, "--repo1-retention-full=1");
|
|
harnessCfgLoad(cfgCmdExpire, argList);
|
|
|
|
TEST_RESULT_VOID(cmdExpire(), "expire all but newest");
|
|
harnessLogResult(
|
|
"P00 INFO: expire time-based backup set: 20181119-152800F, 20181119-152800F_20181119-152152D,"
|
|
" 20181119-152800F_20181119-152155I\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F_20181119-152155I\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F_20181119-152152D\n"
|
|
"P00 INFO: remove expired backup 20181119-152800F\n"
|
|
"P00 DETAIL: archive retention on backup 20181119-152900F, archiveId = 9.4-1, start = 000000010000000000000009\n"
|
|
"P00 DETAIL: remove archive: archiveId = 9.4-1, start = 000000010000000000000004, stop = 000000010000000000000008");
|
|
|
|
harnessLogLevelReset();
|
|
}
|
|
|
|
FUNCTION_HARNESS_RESULT_VOID();
|
|
}
|