diff --git a/doc/xml/release.xml b/doc/xml/release.xml index 13149ad88..6d877fd52 100644 --- a/doc/xml/release.xml +++ b/doc/xml/release.xml @@ -96,6 +96,9 @@ + + + diff --git a/test/src/module/command/archiveCommonTest.c b/test/src/module/command/archiveCommonTest.c index 535f1d88c..b306e772b 100644 --- a/test/src/module/command/archiveCommonTest.c +++ b/test/src/module/command/archiveCommonTest.c @@ -25,67 +25,61 @@ testRun(void) if (testBegin("archiveAsyncErrorClear() and archiveAsyncStatus()")) { StringList *argList = strLstNew(); - strLstAddZ(argList, "--spool-path=" TEST_PATH); - strLstAddZ(argList, "--archive-async"); - strLstAddZ(argList, "--archive-timeout=1"); - strLstAddZ(argList, "--stanza=db"); + hrnCfgArgRawZ(argList, cfgOptStanza, "db"); + hrnCfgArgRawZ(argList, cfgOptSpoolPath, TEST_PATH); + hrnCfgArgRawBool(argList, cfgOptArchiveAsync, true); + hrnCfgArgRawZ(argList, cfgOptArchiveTimeout, "1"); HRN_CFG_LOAD(cfgCmdArchivePush, argList); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("archiveAsyncStatus() - directory and status file not present"); + const String *segment = STRDEF("000000010000000100000001"); TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false, true), false, "directory and status file not present"); TEST_RESULT_BOOL(archiveAsyncStatus(archiveModeGet, segment, false, true), false, "directory and status file not present"); // ------------------------------------------------------------------------------------------------------------------------- - mkdir(TEST_PATH "/archive", 0750); - mkdir(TEST_PATH "/archive/db", 0750); - mkdir(TEST_PATH "/archive/db/out", 0750); + TEST_TITLE("archiveAsyncStatus() - directories present and status file not present"); + + HRN_STORAGE_PATH_CREATE(storageTest, "archive/db/out", .mode = 0750); TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false, true), false, "status file not present"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("clear archive file errors"); - const String *errorSegment = strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.error", strZ(segment)); - const String *errorGlobal = STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/global.error"); + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.error"); + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/global.error"); - storagePutP(storageNewWriteP(storageSpoolWrite(), errorSegment), NULL); - storagePutP(storageNewWriteP(storageSpoolWrite(), errorGlobal), NULL); + TEST_STORAGE_LIST(storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT, "000000010000000100000001.error\nglobal.error\n"); TEST_RESULT_VOID(archiveAsyncErrorClear(archiveModePush, segment), "clear error"); - TEST_RESULT_BOOL(storageExistsP(storageSpool(), errorSegment), false, " check segment error"); - TEST_RESULT_BOOL(storageExistsP(storageSpool(), errorGlobal), false, " check global error"); + TEST_STORAGE_LIST_EMPTY(storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT, .comment = "segment and global error cleared"); // ------------------------------------------------------------------------------------------------------------------------- - storagePutP( - storageNewWriteP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strZ(segment))), - BUFSTRDEF(BOGUS_STR)); + TEST_TITLE("check ok file"); + + HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok", BOGUS_STR); TEST_ERROR( archiveAsyncStatus(archiveModePush, segment, false, true), FormatError, "000000010000000100000001.ok content must have at least two lines"); - storagePutP( - storageNewWriteP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strZ(segment))), - BUFSTRDEF(BOGUS_STR "\n")); + HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok", BOGUS_STR "\n"); TEST_ERROR( archiveAsyncStatus(archiveModePush, segment, false, true), FormatError, "000000010000000100000001.ok message must be > 0"); - storagePutP( - storageNewWriteP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strZ(segment))), - BUFSTRDEF(BOGUS_STR "\nmessage")); + HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok", BOGUS_STR "\nmessage"); TEST_ERROR( archiveAsyncStatus(archiveModePush, segment, false, true), FormatError, "unable to convert base 10 string 'BOGUS' to int"); - storagePutP(storageNewWriteP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strZ(segment))), NULL); + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok"); TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false, true), true, "ok file"); - storagePutP( - storageNewWriteP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strZ(segment))), - BUFSTRDEF("0\nwarning")); + HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok", "0\nwarning"); TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false, true), true, "ok file with warning"); TEST_RESULT_LOG("P00 WARN: warning"); @@ -97,36 +91,31 @@ testRun(void) TEST_RESULT_LOG(""); // ------------------------------------------------------------------------------------------------------------------------- - storagePutP( - storageNewWriteP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strZ(segment))), - BUFSTRDEF("25\nerror")); + TEST_TITLE("error status renamed to ok"); + + HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok", "25\nerror"); TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false, true), true, "error status renamed to ok"); TEST_RESULT_LOG( "P00 WARN: WAL segment '000000010000000100000001' was not pushed due to error [25] and was manually skipped: error"); - TEST_RESULT_VOID( - storageRemoveP( - storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.ok", strZ(segment)), .errorOnMissing = true), - "remove ok"); + HRN_STORAGE_REMOVE(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok", .errorOnMissing = true); // ------------------------------------------------------------------------------------------------------------------------- - storagePutP( - storageNewWriteP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.error", strZ(segment))), bufNew(0)); + TEST_TITLE("segment error file - AssertError"); + + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.error"); TEST_ERROR( archiveAsyncStatus(archiveModePush, segment, true, true), AssertError, "status file '000000010000000100000001.error' has no content"); - storagePutP( - storageNewWriteP(storageSpoolWrite(), strNewFmt(STORAGE_SPOOL_ARCHIVE_OUT "/%s.error", strZ(segment))), - BUFSTRDEF("25\nmessage")); + HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.error", "25\nmessage"); TEST_ERROR(archiveAsyncStatus(archiveModePush, segment, true, true), AssertError, "message"); TEST_RESULT_BOOL(archiveAsyncStatus(archiveModePush, segment, false, true), false, "suppress error"); // ------------------------------------------------------------------------------------------------------------------------- - storagePutP( - storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/global.error")), - BUFSTRDEF("102\nexecute error")); + TEST_TITLE("global error file - ExecuteError"); + HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/global.error", "102\nexecute error"); TEST_ERROR(archiveAsyncStatus(archiveModePush, STRDEF("anyfile"), true, true), ExecuteError, "execute error"); } @@ -134,49 +123,40 @@ testRun(void) if (testBegin("archiveAsyncStatusErrorWrite() and archiveAsyncStatusOkWrite()")) { StringList *argList = strLstNew(); - strLstAddZ(argList, "--spool-path=" TEST_PATH); - strLstAddZ(argList, "--stanza=db"); + hrnCfgArgRawZ(argList, cfgOptStanza, "db"); + hrnCfgArgRawZ(argList, cfgOptSpoolPath, TEST_PATH); hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); - strLstAddZ(argList, "--" CFGOPT_ARCHIVE_ASYNC); + hrnCfgArgRawBool(argList, cfgOptArchiveAsync, true); HRN_CFG_LOAD(cfgCmdArchiveGet, argList, .role = cfgCmdRoleAsync); const String *walSegment = STRDEF("000000010000000100000001"); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("archiveAsyncStatusErrorWrite()"); + TEST_RESULT_VOID( - archiveAsyncStatusErrorWrite(archiveModeGet, walSegment, 25, STRDEF("error message")), "write error"); - TEST_RESULT_STR_Z( - strNewBuf(storageGetP(storageNewReadP(storageTest, STRDEF("archive/db/in/000000010000000100000001.error")))), - "25\nerror message", "check error"); - TEST_RESULT_VOID( - storageRemoveP(storageTest, STRDEF("archive/db/in/000000010000000100000001.error"), .errorOnMissing = true), - "remove error"); + archiveAsyncStatusErrorWrite(archiveModeGet, walSegment, 25, STRDEF("error message")), "write segment error"); + TEST_STORAGE_GET( + storageTest, "archive/db/in/000000010000000100000001.error", "25\nerror message", .remove = true, + .comment = "check segment error and remove"); TEST_RESULT_VOID( archiveAsyncStatusErrorWrite(archiveModeGet, NULL, 25, STRDEF("global error message")), "write global error"); - TEST_RESULT_STR_Z( - strNewBuf(storageGetP(storageNewReadP(storageTest, STRDEF("archive/db/in/global.error")))), - "25\nglobal error message", "check global error"); - TEST_RESULT_VOID( - storageRemoveP(storageTest, STRDEF("archive/db/in/global.error"), .errorOnMissing = true), - "remove global error"); + TEST_STORAGE_GET( + storageTest, "archive/db/in/global.error", "25\nglobal error message", .remove = true, + .comment = "check global error and remove"); - TEST_RESULT_VOID( - archiveAsyncStatusOkWrite(archiveModeGet, walSegment, NULL), "write ok file"); - TEST_RESULT_STR_Z( - strNewBuf(storageGetP(storageNewReadP(storageTest, STRDEF("archive/db/in/000000010000000100000001.ok")))), - "", "check ok"); - TEST_RESULT_VOID( - storageRemoveP(storageTest, STRDEF("archive/db/in/000000010000000100000001.ok"), .errorOnMissing = true), - "remove ok"); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("archiveAsyncStatusOkWrite()"); - TEST_RESULT_VOID( - archiveAsyncStatusOkWrite(archiveModeGet, walSegment, STRDEF("WARNING")), "write ok file with warning"); - TEST_RESULT_STR_Z( - strNewBuf(storageGetP(storageNewReadP(storageTest, STRDEF("archive/db/in/000000010000000100000001.ok")))), - "0\nWARNING", "check ok warning"); - TEST_RESULT_VOID( - storageRemoveP(storageTest, STRDEF("archive/db/in/000000010000000100000001.ok"), .errorOnMissing = true), - "remove ok"); + TEST_RESULT_VOID(archiveAsyncStatusOkWrite(archiveModeGet, walSegment, NULL), "write ok file"); + TEST_STORAGE_GET( + storageTest, "archive/db/in/000000010000000100000001.ok", "", .remove = true, .comment = "check ok and remove"); + + TEST_RESULT_VOID(archiveAsyncStatusOkWrite(archiveModeGet, walSegment, STRDEF("WARNING")), "write ok file with warning"); + TEST_STORAGE_GET( + storageTest, "archive/db/in/000000010000000100000001.ok", "0\nWARNING", .remove = true, + .comment = "check ok warning and remove"); } // ***************************************************************************************************************************** @@ -197,8 +177,16 @@ testRun(void) // ***************************************************************************************************************************** if (testBegin("walPath()")) { + StringList *argList = strLstNew(); + hrnCfgArgRawZ(argList, cfgOptStanza, "db"); + hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); + HRN_CFG_LOAD(cfgCmdArchiveGet, argList); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("absolute and relative paths"); + const String *pgPath = storagePathP(storageTest, STRDEF("pg")); - storagePathCreateP(storageTest, pgPath); + HRN_STORAGE_PATH_CREATE(storageTest, strZ(pgPath)); TEST_RESULT_STR_Z(walPath(STRDEF("/absolute/path"), pgPath, STRDEF("test")), "/absolute/path", "absolute path"); @@ -206,6 +194,9 @@ testRun(void) TEST_RESULT_STR( walPath(STRDEF("relative/path"), pgPath, STRDEF("test")), strNewFmt("%s/relative/path", strZ(pgPath)), "relative path"); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("symlink path"); + const String *pgPathLink = storagePathP(storageTest, STRDEF("pg-link")); THROW_ON_SYS_ERROR_FMT( symlink(strZ(pgPath), strZ(pgPathLink)) == -1, FileOpenError, "unable to create symlink '%s' to '%s'", strZ(pgPath), @@ -216,6 +207,9 @@ testRun(void) walPath(STRDEF("relative/path"), pgPathLink, STRDEF("test")), strNewFmt("%s/relative/path", strZ(pgPathLink)), "relative path"); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("path errors"); + THROW_ON_SYS_ERROR(chdir("/") != 0, PathMissingError, "unable to chdir()"); TEST_ERROR( walPath(STRDEF("relative/path"), pgPathLink, STRDEF("test")), OptionInvalidValueError, @@ -234,15 +228,17 @@ testRun(void) { // Load configuration to set repo-path and stanza StringList *argList = strLstNew(); - strLstAddZ(argList, "--stanza=db"); + hrnCfgArgRawZ(argList, cfgOptStanza, "db"); hrnCfgArgRawZ(argList, cfgOptPgPath, "/path/to/pg"); - strLstAddZ(argList, "--repo-path=" TEST_PATH); - strLstAddZ(argList, "archive-get"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH); HRN_CFG_LOAD(cfgCmdArchiveGet, argList); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("no path or segment"); + TEST_RESULT_STR(walSegmentFind(storageRepo(), STRDEF("9.6-2"), STRDEF("123456781234567812345678"), 0), NULL, "no path"); - storagePathCreateP(storageTest, STRDEF("archive/db/9.6-2/1234567812345678")); + HRN_STORAGE_PATH_CREATE(storageTest, "archive/db/9.6-2/1234567812345678"); TEST_RESULT_STR( walSegmentFind(storageRepo(), STRDEF("9.6-2"), STRDEF("123456781234567812345678"), 0), NULL, "no segment"); TEST_ERROR( @@ -252,6 +248,9 @@ testRun(void) "HINT: check the PostgreSQL server log for errors.\n" "HINT: run the 'start' command if the stanza was previously stopped."); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("timeout"); + // Check timeout by making the wal segment appear after 250ms HARNESS_FORK_BEGIN() { @@ -259,12 +258,9 @@ testRun(void) { sleepMSec(250); - storagePutP( - storageNewWriteP( - storageTest, - STRDEF( - "archive/db/9.6-2/1234567812345678/123456781234567812345678-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa")), - NULL); + HRN_STORAGE_PUT_EMPTY( + storageTest, + "archive/db/9.6-2/1234567812345678/123456781234567812345678-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); } HARNESS_FORK_CHILD_END(); @@ -278,11 +274,11 @@ testRun(void) } HARNESS_FORK_END(); - storagePutP( - storageNewWriteP( - storageTest, - STRDEF("archive/db/9.6-2/1234567812345678/123456781234567812345678-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.gz")), - NULL); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("duplicate"); + + HRN_STORAGE_PUT_EMPTY( + storageTest, "archive/db/9.6-2/1234567812345678/123456781234567812345678-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.gz"); TEST_ERROR( walSegmentFind(storageRepo(), STRDEF("9.6-2"), STRDEF("123456781234567812345678"), 0), @@ -292,6 +288,9 @@ testRun(void) ", 123456781234567812345678-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb.gz" "\nHINT: are multiple primaries archiving to this stanza?"); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("partial not found"); + TEST_RESULT_STR( walSegmentFind(storageRepo(), STRDEF("9.6-2"), STRDEF("123456781234567812345678.partial"), 0), NULL, "did not find partial segment"); @@ -300,12 +299,19 @@ testRun(void) // ***************************************************************************************************************************** if (testBegin("walSegmentNext()")) { + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("beginning and end range"); + TEST_RESULT_STR_Z( walSegmentNext(STRDEF("000000010000000100000001"), 16 * 1024 * 1024, PG_VERSION_10), "000000010000000100000002", "get next"); TEST_RESULT_STR_Z( walSegmentNext(STRDEF("0000000100000001000000FE"), 16 * 1024 * 1024, PG_VERSION_93), "0000000100000001000000FF", "get next"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("check overflow by version"); + TEST_RESULT_STR_Z( walSegmentNext(STRDEF("0000009900000001000000FF"), 16 * 1024 * 1024, PG_VERSION_93), "000000990000000200000000", "get next overflow >= 9.3"); @@ -323,9 +329,16 @@ testRun(void) // ***************************************************************************************************************************** if (testBegin("walSegmentRange()")) { + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("single segment"); + TEST_RESULT_STRLST_Z( walSegmentRange(STRDEF("000000010000000100000000"), 16 * 1024 * 1024, PG_VERSION_92, 1), "000000010000000100000000\n", "get single"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("check range by version"); + TEST_RESULT_STRLST_Z( walSegmentRange(STRDEF("0000000100000001000000FD"), 16 * 1024 * 1024, PG_VERSION_92, 4), "0000000100000001000000FD\n0000000100000001000000FE\n000000010000000200000000\n000000010000000200000001\n", diff --git a/test/src/module/command/archiveGetTest.c b/test/src/module/command/archiveGetTest.c index 85db670d5..d7ea72d91 100644 --- a/test/src/module/command/archiveGetTest.c +++ b/test/src/module/command/archiveGetTest.c @@ -23,20 +23,25 @@ testRun(void) if (testBegin("queueNeed()")) { StringList *argList = strLstNew(); - strLstAddZ(argList, "--stanza=test1"); - strLstAddZ(argList, "--archive-async"); + hrnCfgArgRawZ(argList, cfgOptStanza, "test1"); + hrnCfgArgRawBool(argList, cfgOptArchiveAsync, true); hrnCfgArgRawZ(argList, cfgOptPgPath, "/unused"); - strLstAddZ(argList, "--spool-path=" TEST_PATH "/spool"); + hrnCfgArgRawZ(argList, cfgOptSpoolPath, TEST_PATH "/spool"); HRN_CFG_LOAD(cfgCmdArchiveGet, argList); size_t queueSize = 16 * 1024 * 1024; size_t walSegmentSize = 16 * 1024 * 1024; + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("path missing"); + TEST_ERROR( queueNeed(STRDEF("000000010000000100000001"), false, queueSize, walSegmentSize, PG_VERSION_92), PathMissingError, "unable to list file info for missing path '" TEST_PATH "/spool/archive/test1/in'"); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("queue size too small"); + HRN_STORAGE_PATH_CREATE(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN); TEST_RESULT_STRLST_Z( @@ -44,6 +49,8 @@ testRun(void) "000000010000000100000001\n000000010000000100000002\n", "queue size smaller than min"); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("queue empty"); + queueSize = (16 * 1024 * 1024) * 3; TEST_RESULT_STRLST_Z( @@ -51,6 +58,8 @@ testRun(void) "000000010000000100000001\n000000010000000100000002\n000000010000000100000003\n", "empty queue"); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("pg version earlier than 9.3"); + Buffer *walSegmentBuffer = bufNew(walSegmentSize); memset(bufPtr(walSegmentBuffer), 0, walSegmentSize); @@ -61,8 +70,7 @@ testRun(void) queueNeed(STRDEF("0000000100000001000000FE"), false, queueSize, walSegmentSize, PG_VERSION_92), "000000010000000200000000\n000000010000000200000001\n", "queue has wal < 9.3"); - TEST_RESULT_STRLST_Z( - storageListP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_IN)), "0000000100000001000000FE\n", "check queue"); + TEST_STORAGE_LIST(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN, "0000000100000001000000FE\n", .comment = "check queue"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("pg >= 9.3 and ok/junk status files"); @@ -341,25 +349,28 @@ testRun(void) TEST_RESULT_VOID(cmdArchiveGetAsync(), "archive async"); - #define TEST_WARN \ - "repo2: [ArchiveMismatchError] unable to retrieve the archive id for database version '10' and system-id" \ - " '18072658121562454734'" - TEST_RESULT_LOG( "P00 INFO: get 3 WAL file(s) from archive: 0000000100000001000000FE...000000010000000200000000\n" - "P00 WARN: " TEST_WARN "\n" + "P00 WARN: repo2: [ArchiveMismatchError] unable to retrieve the archive id for database version '10' and system-id" + " '18072658121562454734'\n" "P01 DETAIL: found 0000000100000001000000FE in the repo1: 10-1 archive\n" "P00 DETAIL: unable to find 0000000100000001000000FF in the archive"); TEST_STORAGE_GET( - storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FE.ok", "0\n" TEST_WARN, .remove = true); + storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FE.ok", + "0\n" + "repo2: [ArchiveMismatchError] unable to retrieve the archive id for database version '10' and system-id" + " '18072658121562454734'", + .remove = true); TEST_STORAGE_GET( - storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FF.ok", "0\n" TEST_WARN, .remove = true); + storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FF.ok", + "0\n" + "repo2: [ArchiveMismatchError] unable to retrieve the archive id for database version '10' and system-id" + " '18072658121562454734'", + .remove = true); TEST_STORAGE_GET_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FE", .remove = true); TEST_STORAGE_LIST_EMPTY(storageSpool(), STORAGE_SPOOL_ARCHIVE_IN); - #undef TEST_WARN - // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("error on duplicates now that no segments are missing, repo with bad perms"); @@ -379,17 +390,12 @@ testRun(void) TEST_RESULT_VOID(cmdArchiveGetAsync(), "archive async"); - #define TEST_WARN1 \ - "repo2: [PathOpenError] unable to list file info for path '" TEST_PATH "/repo2/archive/test2/10-1" \ - "/0000000100000001': [13] Permission denied" - #define TEST_WARN2 \ - "repo2: [PathOpenError] unable to list file info for path '" TEST_PATH "/repo2/archive/test2/10-1" \ - "/0000000100000002': [13] Permission denied" - TEST_RESULT_LOG( "P00 INFO: get 3 WAL file(s) from archive: 0000000100000001000000FE...000000010000000200000000\n" - "P00 WARN: " TEST_WARN1 "\n" - "P00 WARN: " TEST_WARN2 "\n" + "P00 WARN: repo2: [PathOpenError] unable to list file info for path '" TEST_PATH "/repo2/archive/test2/10-1" + "/0000000100000001': [13] Permission denied\n" + "P00 WARN: repo2: [PathOpenError] unable to list file info for path '" TEST_PATH "/repo2/archive/test2/10-1" + "/0000000100000002': [13] Permission denied\n" "P01 DETAIL: found 0000000100000001000000FE in the repo1: 10-1 archive\n" "P01 DETAIL: found 0000000100000001000000FF in the repo1: 10-1 archive\n" "P00 WARN: [ArchiveDuplicateError] duplicates found for WAL segment 000000010000000200000000:\n" @@ -399,10 +405,18 @@ testRun(void) TEST_STORAGE_GET_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FE", .remove = true); TEST_STORAGE_GET( - storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FE.ok", "0\n" TEST_WARN1, .remove = true); + storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FE.ok", + "0\n" + "repo2: [PathOpenError] unable to list file info for path '" TEST_PATH "/repo2/archive/test2/10-1/0000000100000001':" + " [13] Permission denied", + .remove = true); TEST_STORAGE_GET_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FF", .remove = true); TEST_STORAGE_GET( - storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FF.ok", "0\n" TEST_WARN1, .remove = true); + storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/0000000100000001000000FF.ok", + "0\n" + "repo2: [PathOpenError] unable to list file info for path '" TEST_PATH "/repo2/archive/test2/10-1/0000000100000001':" + " [13] Permission denied", + .remove = true); TEST_STORAGE_GET( storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/000000010000000200000000.error", "45\n" @@ -410,15 +424,13 @@ testRun(void) "repo1: 10-1/0000000100000002/000000010000000200000000-bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, 10-1/0000000100000002" "/000000010000000200000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\n" "HINT: are multiple primaries archiving to this stanza?\n" - TEST_WARN2, + "repo2: [PathOpenError] unable to list file info for path '" TEST_PATH "/repo2/archive/test2/10-1" \ + "/0000000100000002': [13] Permission denied", .remove = true); TEST_STORAGE_LIST_EMPTY(storageSpool(), STORAGE_SPOOL_ARCHIVE_IN); HRN_STORAGE_MODE(storageRepoIdxWrite(1), STORAGE_REPO_ARCHIVE "/10-1"); - #undef TEST_WARN1 - #undef TEST_WARN2 - // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("error on duplicates"); @@ -479,21 +491,21 @@ testRun(void) TEST_RESULT_VOID(cmdArchiveGetAsync(), "archive async"); - #define TEST_WARN1 \ - "repo3: [ArchiveMismatchError] unable to retrieve the archive id for database version '10' and system-id" \ - " '18072658121562454734'" - #define TEST_WARN2 \ - "repo1: 10-1/0000000100000002/000000010000000200000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.gz" \ - " [FormatError] unexpected eof in compressed data" - TEST_RESULT_LOG( "P00 INFO: get 1 WAL file(s) from archive: 000000010000000200000000\n" - "P00 WARN: " TEST_WARN1 "\n" - "P01 WARN: " TEST_WARN2 "\n" + "P00 WARN: repo3: [ArchiveMismatchError] unable to retrieve the archive id for database version '10' and system-id" + " '18072658121562454734'\n" + "P01 WARN: repo1: 10-1/0000000100000002/000000010000000200000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.gz" + " [FormatError] unexpected eof in compressed data\n" "P01 DETAIL: found 000000010000000200000000 in the repo2: 10-1 archive"); TEST_STORAGE_GET( - storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/000000010000000200000000.ok", "0\n" TEST_WARN1 "\n" TEST_WARN2, + storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/000000010000000200000000.ok", + "0\n" + "repo3: [ArchiveMismatchError] unable to retrieve the archive id for database version '10' and system-id" + " '18072658121562454734'\n" + "repo1: 10-1/0000000100000002/000000010000000200000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.gz" + " [FormatError] unexpected eof in compressed data", .remove = true); TEST_STORAGE_GET_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/000000010000000200000000", .remove = true); TEST_STORAGE_LIST_EMPTY(storageSpool(), STORAGE_SPOOL_ARCHIVE_IN); @@ -511,24 +523,26 @@ testRun(void) TEST_RESULT_VOID(cmdArchiveGetAsync(), "archive async"); - #define TEST_WARN3 \ - "repo2: 10-1/0000000100000002/000000010000000200000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.gz" \ - " [FormatError] unexpected eof in compressed data" - TEST_RESULT_LOG( "P00 INFO: get 1 WAL file(s) from archive: 000000010000000200000000\n" - "P00 WARN: " TEST_WARN1 "\n" + "P00 WARN: repo3: [ArchiveMismatchError] unable to retrieve the archive id for database version '10' and system-id" + " '18072658121562454734'\n" "P01 WARN: [FileReadError] raised from local-1 shim protocol: unable to get 000000010000000200000000:\n" - " " TEST_WARN2 "\n" - " " TEST_WARN3); + " repo1: 10-1/0000000100000002/000000010000000200000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.gz" + " [FormatError] unexpected eof in compressed data\n" + " repo2: 10-1/0000000100000002/000000010000000200000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.gz" + " [FormatError] unexpected eof in compressed data"); TEST_STORAGE_GET( storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/000000010000000200000000.error", "42\n" "raised from local-1 shim protocol: unable to get 000000010000000200000000:\n" - TEST_WARN2 "\n" - TEST_WARN3 "\n" - TEST_WARN1, + "repo1: 10-1/0000000100000002/000000010000000200000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.gz" + " [FormatError] unexpected eof in compressed data\n" + "repo2: 10-1/0000000100000002/000000010000000200000000-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.gz" + " [FormatError] unexpected eof in compressed data\n" + "repo3: [ArchiveMismatchError] unable to retrieve the archive id for database version '10' and system-id" + " '18072658121562454734'", .remove = true); TEST_STORAGE_LIST( storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN, "000000010000000200000000.pgbackrest.tmp\n", .remove = true); @@ -571,7 +585,6 @@ testRun(void) { harnessLogLevelSet(logLevelDetail); - // Arguments that must be included. Use raw config here because we need to keep the StringList *argBaseList = strLstNew(); hrnCfgArgRawZ(argBaseList, cfgOptPgPath, TEST_PATH "/pg"); hrnCfgArgRawZ(argBaseList, cfgOptRepoPath, TEST_PATH "/repo"); @@ -588,12 +601,16 @@ testRun(void) TEST_ERROR(cmdArchiveGet(), HostInvalidError, "archive-get command must be run on the PostgreSQL host"); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("segment parameter not specified"); + argList = strLstDup(argBaseList); HRN_CFG_LOAD(cfgCmdArchiveGet, argList, .exeBogus = true); TEST_ERROR(cmdArchiveGet(), ParamRequiredError, "WAL segment to get required"); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("path parameter not specified"); + argList = strLstDup(argBaseList); strLstAddZ(argList, "000000010000000100000001"); HRN_CFG_LOAD(cfgCmdArchiveGet, argList, .exeBogus = true); @@ -601,6 +618,8 @@ testRun(void) TEST_ERROR(cmdArchiveGet(), ParamRequiredError, "path to copy WAL segment required"); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("no valid repo"); + HRN_STORAGE_PUT( storagePgWrite(), PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, hrnPgControlToBuffer((PgControl){.version = PG_VERSION_10, .systemId = 0xFACEFACEFACEFACE})); @@ -623,10 +642,12 @@ testRun(void) " scheme."); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("no valid repo - async"); + argList = strLstDup(argBaseList); + hrnCfgArgRawBool(argList, cfgOptArchiveAsync, true); strLstAddZ(argList, "00000001.history"); strLstAddZ(argList, TEST_PATH "/pg/pg_wal/RECOVERYHISTORY"); - strLstAddZ(argList, "--archive-async"); HRN_CFG_LOAD(cfgCmdArchiveGet, argList, .exeBogus = true); TEST_ERROR(cmdArchiveGet(), RepoInvalidError, "unable to find a valid repository"); @@ -643,8 +664,10 @@ testRun(void) " HINT: use --no-archive-check to disable archive checks during backup if you have an alternate archiving" " scheme."); - // Make sure the process times out when there is nothing to get // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("WAL not found - timeout"); + + // Make sure the process times out when there is nothing to get argList = strLstDup(argBaseList); hrnCfgArgRawZ(argList, cfgOptSpoolPath, TEST_PATH "/spool"); hrnCfgArgRawBool(argList, cfgOptArchiveAsync, true); @@ -658,8 +681,9 @@ testRun(void) cmdArchiveGet(), ArchiveTimeoutError, "unable to get WAL file '000000010000000100000001' from the archive asynchronously after 1 second(s)"); - // Check for missing WAL // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("check for missing WAL"); + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/000000010000000100000001.ok"); TEST_ERROR( @@ -670,8 +694,9 @@ testRun(void) storageExistsP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_IN "/000000010000000100000001.ok")), false, "check OK file was removed"); - // Write out a WAL segment for success // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("write WAL segment for success"); + HRN_STORAGE_PATH_CREATE(storagePgWrite(), "pg_wal"); HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/000000010000000100000001", "SHOULD-BE-A-REAL-WAL-FILE"); @@ -682,11 +707,13 @@ testRun(void) TEST_STORAGE_LIST_EMPTY(storageSpool(), STORAGE_SPOOL_ARCHIVE_IN); TEST_STORAGE_LIST(storagePgWrite(), "pg_wal", "RECOVERYXLOG\n", .remove = true); - // Write more WAL segments (in this case queue should be full) // ------------------------------------------------------------------------------------------------------------------------- - strLstAddZ(argList, "--archive-get-queue-max=48"); + TEST_TITLE("write WAL segments for success - queue full"); + + hrnCfgArgRawZ(argList, cfgOptArchiveGetQueueMax, "48"); HRN_CFG_LOAD(cfgCmdArchiveGet, argList, .exeBogus = true); + // Write more WAL segments (in this case queue should be full) HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/000000010000000100000001", "SHOULD-BE-A-REAL-WAL-FILE"); HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/000000010000000100000001.ok", "0\nwarning about x"); HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN "/000000010000000100000002", "SHOULD-BE-A-REAL-WAL-FILE"); @@ -700,8 +727,10 @@ testRun(void) TEST_STORAGE_LIST(storagePgWrite(), "pg_wal", "RECOVERYXLOG\n", .remove = true); TEST_STORAGE_LIST(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_IN, "000000010000000100000002\n", .remove = true); - // Make sure the process times out when it can't get a lock // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("unable to get lock"); + + // Make sure the process times out when it can't get a lock HARNESS_FORK_BEGIN() { HARNESS_FORK_CHILD_BEGIN(0, true) @@ -749,6 +778,8 @@ testRun(void) HARNESS_FORK_END(); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("too many parameters specified"); + strLstAddZ(argList, BOGUS_STR); HRN_CFG_LOAD(cfgCmdArchiveGet, argList, .exeBogus = true); @@ -1029,9 +1060,9 @@ testRun(void) // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("unable to get from one repo"); - HRN_STORAGE_PUT( + HRN_STORAGE_PUT_EMPTY( storageRepoIdxWrite(0), - STORAGE_REPO_ARCHIVE "/10-2/01ABCDEF01ABCDEF01ABCDEF-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.gz", NULL); + STORAGE_REPO_ARCHIVE "/10-2/01ABCDEF01ABCDEF01ABCDEF-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.gz"); TEST_RESULT_INT(cmdArchiveGet(), 0, "get"); @@ -1070,8 +1101,7 @@ testRun(void) TEST_RESULT_INT(cmdArchiveGet(), 0, "get"); - TEST_RESULT_LOG( - "P00 INFO: found 01ABCDEF01ABCDEF01ABCDEF in the repo2: 10-1 archive"); + TEST_RESULT_LOG("P00 INFO: found 01ABCDEF01ABCDEF01ABCDEF in the repo2: 10-1 archive"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("no segments to find with existing ok file"); diff --git a/test/src/module/command/archivePushTest.c b/test/src/module/command/archivePushTest.c index 4feab2291..eeaeaa242 100644 --- a/test/src/module/command/archivePushTest.c +++ b/test/src/module/command/archivePushTest.c @@ -28,47 +28,44 @@ testRun(void) if (testBegin("archivePushReadyList(), archivePushProcessList(), and archivePushDrop()")) { StringList *argList = strLstNew(); - strLstAddZ(argList, "--stanza=db"); - strLstAddZ(argList, "--pg1-path=" TEST_PATH "/db"); - strLstAddZ(argList, "--spool-path=" TEST_PATH "/spool"); - strLstAddZ(argList, "--" CFGOPT_ARCHIVE_ASYNC); + hrnCfgArgRawZ(argList, cfgOptStanza, "db"); + hrnCfgArgRawZ(argList, cfgOptPgPath, TEST_PATH "/db"); + hrnCfgArgRawZ(argList, cfgOptSpoolPath, TEST_PATH "/spool"); + hrnCfgArgRawBool(argList, cfgOptArchiveAsync, true); HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync); - storagePathCreateP(storagePgWrite(), STRDEF("pg_wal/archive_status")); - storagePathCreateP(storageTest, STRDEF("spool/archive/db/out")); + HRN_STORAGE_PATH_CREATE(storagePgWrite(), "pg_wal/archive_status"); + HRN_STORAGE_PATH_CREATE(storageTest, "spool/archive/db/out"); // Create ok files to indicate WAL that has already been archived - storagePutP( - storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok")), NULL); - storagePutP( - storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000003.ok")), NULL); - storagePutP( - storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000004.ok")), NULL); - storagePutP( - storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000005.error")), NULL); - storagePutP( - storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000006.error")), NULL); - storagePutP( - storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/global.error")), NULL); + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok"); + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000003.ok"); + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000004.ok"); + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000005.error"); + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000006.error"); + HRN_STORAGE_PUT_EMPTY(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/global.error"); // Create ready files for wal that still needs to be archived - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000002.ready")), NULL); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000003.ready")), NULL); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000005.ready")), NULL); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000006.ready")), NULL); + HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "pg_wal/archive_status/000000010000000100000002.ready"); + HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "pg_wal/archive_status/000000010000000100000003.ready"); + HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "pg_wal/archive_status/000000010000000100000005.ready"); + HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "pg_wal/archive_status/000000010000000100000006.ready"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("ready list"); TEST_RESULT_STRLST_Z( archivePushProcessList(STRDEF(TEST_PATH "/db/pg_wal")), "000000010000000100000002\n000000010000000100000005\n000000010000000100000006\n", "ready list"); - TEST_RESULT_STRLST_Z( - strLstSort(storageListP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT)), sortOrderAsc), - "000000010000000100000003.ok\n", "remaining status list"); + TEST_STORAGE_LIST( + storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT, "000000010000000100000003.ok\n", .comment = "remaining status list"); - // Test drop // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("WAL drop"); + StringList *argListDrop = strLstDup(argList); - strLstAdd(argListDrop, strNewFmt("--archive-push-queue-max=%zu", (size_t)1024 * 1024 * 1024)); + hrnCfgArgRawFmt(argListDrop, cfgOptArchivePushQueueMax, "%zu", (size_t)1024 * 1024 * 1024); HRN_CFG_LOAD(cfgCmdArchivePush, argListDrop, .role = cfgCmdRoleAsync); // Write the files that we claim are in pg_wal @@ -77,50 +74,48 @@ testRun(void) memset(bufPtr(walBuffer), 0, bufSize(walBuffer)); hrnPgWalToBuffer((PgWal){.version = PG_VERSION_10, .systemId = 0xFACEFACEFACEFACE}, walBuffer); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000002")), walBuffer); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000003")), walBuffer); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000005")), walBuffer); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000006")), walBuffer); + HRN_STORAGE_PUT(storagePgWrite(), "pg_wal/000000010000000100000002", walBuffer); + HRN_STORAGE_PUT(storagePgWrite(), "pg_wal/000000010000000100000003", walBuffer); + HRN_STORAGE_PUT(storagePgWrite(), "pg_wal/000000010000000100000005", walBuffer); + HRN_STORAGE_PUT(storagePgWrite(), "pg_wal/000000010000000100000006", walBuffer); // Queue max is high enough that no WAL will be dropped TEST_RESULT_BOOL( - archivePushDrop(STRDEF("pg_wal"), archivePushProcessList(STRDEF(TEST_PATH "/db/pg_wal"))), false, - "wal is not dropped"); + archivePushDrop(STRDEF("pg_wal"), archivePushProcessList(STRDEF(TEST_PATH "/db/pg_wal"))), false, "wal is not dropped"); // Now set queue max low enough that WAL will be dropped argListDrop = strLstDup(argList); - strLstAdd(argListDrop, strNewFmt("--archive-push-queue-max=%zu", (size_t)16 * 1024 * 1024 * 2)); + hrnCfgArgRawFmt(argListDrop, cfgOptArchivePushQueueMax, "%zu", (size_t)16 * 1024 * 1024 * 2); HRN_CFG_LOAD(cfgCmdArchivePush, argListDrop, .role = cfgCmdRoleAsync); TEST_RESULT_BOOL( - archivePushDrop(STRDEF("pg_wal"), archivePushProcessList(STRDEF(TEST_PATH "/db/pg_wal"))), true, - "wal is dropped"); + archivePushDrop(STRDEF("pg_wal"), archivePushProcessList(STRDEF(TEST_PATH "/db/pg_wal"))), true, "wal is dropped"); } // ***************************************************************************************************************************** if (testBegin("archivePushCheck()")) { StringList *argList = strLstNew(); - strLstAddZ(argList, "--stanza=test"); - strLstAddZ(argList, "--pg1-path=" TEST_PATH "/pg"); - strLstAddZ(argList, "--repo1-path=" TEST_PATH "/repo"); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawZ(argList, cfgOptPgPath, TEST_PATH "/pg"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH "/repo"); HRN_CFG_LOAD(cfgCmdArchivePush, argList); - // Check mismatched pg_control and archive.info // ------------------------------------------------------------------------------------------------------------------------- - storagePutP( - storageNewWriteP(storageTest, STRDEF("pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL)), + TEST_TITLE("mismatched pg_control and archive.info - pg version"); + + HRN_STORAGE_PUT( + storageTest, "pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, hrnPgControlToBuffer((PgControl){.version = PG_VERSION_96, .systemId = 0xFACEFACEFACEFACE})); // Create incorrect archive info - storagePutP( - storageNewWriteP(storageTest, STRDEF("repo/archive/test/archive.info")), - harnessInfoChecksumZ( - "[db]\n" - "db-id=1\n" - "\n" - "[db:history]\n" - "1={\"db-id\":5555555555555555555,\"db-version\":\"9.4\"}\n")); + HRN_INFO_PUT( + storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE, + "[db]\n" + "db-id=1\n" + "\n" + "[db:history]\n" + "1={\"db-id\":5555555555555555555,\"db-version\":\"9.4\"}\n"); TEST_ERROR( archivePushCheck(true), RepoInvalidError, @@ -129,15 +124,17 @@ testRun(void) " 9.4, system-id 5555555555555555555" "\nHINT: are you archiving to the correct stanza?"); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("mismatched pg_control and archive.info - system-id"); + // Fix the version - storagePutP( - storageNewWriteP(storageTest, STRDEF("repo/archive/test/archive.info")), - harnessInfoChecksumZ( - "[db]\n" - "db-id=1\n" - "\n" - "[db:history]\n" - "1={\"db-id\":5555555555555555555,\"db-version\":\"9.6\"}\n")); + HRN_INFO_PUT( + storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE, + "[db]\n" + "db-id=1\n" + "\n" + "[db:history]\n" + "1={\"db-id\":5555555555555555555,\"db-version\":\"9.6\"}\n"); TEST_ERROR( archivePushCheck(true), RepoInvalidError, @@ -146,15 +143,17 @@ testRun(void) " 9.6, system-id 5555555555555555555" "\nHINT: are you archiving to the correct stanza?"); + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("pg_control and archive.info match"); + // Fix archive info - storagePutP( - storageNewWriteP(storageTest, STRDEF("repo/archive/test/archive.info")), - harnessInfoChecksumZ( - "[db]\n" - "db-id=1\n" - "\n" - "[db:history]\n" - "1={\"db-id\":18072658121562454734,\"db-version\":\"9.6\"}\n")); + HRN_INFO_PUT( + storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE, + "[db]\n" + "db-id=1\n" + "\n" + "[db:history]\n" + "1={\"db-id\":18072658121562454734,\"db-version\":\"9.6\"}\n"); ArchivePushCheckResult result = {0}; TEST_ASSIGN(result, archivePushCheck(true), "get archive check result"); @@ -172,30 +171,28 @@ testRun(void) TEST_TITLE("mismatched repos when pg-path not present"); argList = strLstNew(); - strLstAddZ(argList, "--stanza=test"); - strLstAddZ(argList, "--repo2-path=" TEST_PATH "/repo2"); - strLstAddZ(argList, "--repo4-path=" TEST_PATH "/repo4"); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 2, TEST_PATH "/repo2"); + hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 4, TEST_PATH "/repo4"); HRN_CFG_LOAD(cfgCmdArchivePush, argList); // repo2 has correct info - storagePutP( - storageNewWriteP(storageTest, STRDEF("repo2/archive/test/archive.info")), - harnessInfoChecksumZ( - "[db]\n" - "db-id=1\n" - "\n" - "[db:history]\n" - "1={\"db-id\":18072658121562454734,\"db-version\":\"9.6\"}\n")); + HRN_INFO_PUT( + storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE, + "[db]\n" + "db-id=1\n" + "\n" + "[db:history]\n" + "1={\"db-id\":18072658121562454734,\"db-version\":\"9.6\"}\n"); // repo4 has incorrect info - storagePutP( - storageNewWriteP(storageTest, STRDEF("repo4/archive/test/archive.info")), - harnessInfoChecksumZ( - "[db]\n" - "db-id=1\n" - "\n" - "[db:history]\n" - "1={\"db-id\":5555555555555555555,\"db-version\":\"9.4\"}\n")); + HRN_INFO_PUT( + storageRepoIdxWrite(1), INFO_ARCHIVE_PATH_FILE, + "[db]\n" + "db-id=1\n" + "\n" + "[db:history]\n" + "1={\"db-id\":5555555555555555555,\"db-version\":\"9.4\"}\n"); TEST_ASSIGN(result, archivePushCheck(false), "get archive check result"); @@ -218,15 +215,14 @@ testRun(void) TEST_TITLE("matched repos when pg-path not present"); // repo4 has correct info - storagePutP( - storageNewWriteP(storageTest, STRDEF("repo4/archive/test/archive.info")), - harnessInfoChecksumZ( - "[db]\n" - "db-id=2\n" - "\n" - "[db:history]\n" - "1={\"db-id\":5555555555555555555,\"db-version\":\"9.4\"}\n" - "2={\"db-id\":18072658121562454734,\"db-version\":\"9.6\"}\n")); + HRN_INFO_PUT( + storageRepoIdxWrite(1), INFO_ARCHIVE_PATH_FILE, + "[db]\n" + "db-id=2\n" + "\n" + "[db:history]\n" + "1={\"db-id\":5555555555555555555,\"db-version\":\"9.4\"}\n" + "2={\"db-id\":18072658121562454734,\"db-version\":\"9.6\"}\n"); TEST_ASSIGN(result, archivePushCheck(false), "get archive check result"); @@ -249,24 +245,29 @@ testRun(void) // ***************************************************************************************************************************** if (testBegin("Synchronous cmdArchivePush() and archivePushFile()")) { + // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("command must be run on the pg host"); StringList *argList = strLstNew(); hrnCfgArgRawZ(argList, cfgOptPgHost, "host"); hrnCfgArgRawZ(argList, cfgOptPgPath, "/pg"); - strLstAddZ(argList, "--" CFGOPT_STANZA "=test2"); + hrnCfgArgRawZ(argList, cfgOptStanza, "test2"); HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleMain); TEST_ERROR(cmdArchivePush(), HostInvalidError, "archive-push command must be run on the PostgreSQL host"); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("WAL segment not specified"); + argList = strLstNew(); - strLstAddZ(argList, "--stanza=test"); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); HRN_CFG_LOAD(cfgCmdArchivePush, argList); TEST_ERROR(cmdArchivePush(), ParamRequiredError, "WAL segment to push required"); // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("pg-path not specified"); + StringList *argListTemp = strLstDup(argList); strLstAddZ(argListTemp, "pg_wal/000000010000000100000001"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); @@ -277,36 +278,36 @@ testRun(void) "\nHINT: is %f passed to archive-push instead of %p?" "\nHINT: PostgreSQL may pass relative paths even with %p depending on the environment."); - // Create pg_control and archive.info // ------------------------------------------------------------------------------------------------------------------------- - strLstAddZ(argList, "--pg1-path=" TEST_PATH "/pg"); - strLstAddZ(argList, "--repo1-path=" TEST_PATH "/repo"); + TEST_TITLE("attempt to push WAL with incorrect headers"); + + // Create pg_control and archive.info + hrnCfgArgRawZ(argList, cfgOptPgPath, TEST_PATH "/pg"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH "/repo"); argListTemp = strLstDup(argList); strLstAddZ(argListTemp, "pg_wal/000000010000000100000001"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); - storagePutP( - storageNewWriteP(storageTest, STRDEF("pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL)), + HRN_STORAGE_PUT( + storageTest, "pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, hrnPgControlToBuffer((PgControl){.version = PG_VERSION_11, .systemId = 0xFACEFACEFACEFACE})); - storagePutP( - storageNewWriteP(storageTest, STRDEF("repo/archive/test/archive.info")), - harnessInfoChecksumZ( - "[db]\n" - "db-id=1\n" - "\n" - "[db:history]\n" - "1={\"db-id\":18072658121562454734,\"db-version\":\"11\"}\n")); + HRN_INFO_PUT( + storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE, + "[db]\n" + "db-id=1\n" + "\n" + "[db:history]\n" + "1={\"db-id\":18072658121562454734,\"db-version\":\"11\"}\n"); // Generate WAL with incorrect headers and try to push them - // ------------------------------------------------------------------------------------------------------------------------- Buffer *walBuffer1 = bufNew((size_t)16 * 1024 * 1024); bufUsedSet(walBuffer1, bufSize(walBuffer1)); memset(bufPtr(walBuffer1), 0, bufSize(walBuffer1)); hrnPgWalToBuffer((PgWal){.version = PG_VERSION_10, .systemId = 0xFACEFACEFACEFACE}, walBuffer1); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000001")), walBuffer1); + HRN_STORAGE_PUT(storagePgWrite(), "pg_wal/000000010000000100000001", walBuffer1); THROW_ON_SYS_ERROR(chdir(strZ(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()"); @@ -319,7 +320,7 @@ testRun(void) hrnPgWalToBuffer((PgWal){.version = PG_VERSION_11, .systemId = 0xECAFECAFECAFECAF}, walBuffer1); const char *walBuffer1Sha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer1))); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000001")), walBuffer1); + HRN_STORAGE_PUT(storagePgWrite(), "pg_wal/000000010000000100000001", walBuffer1); TEST_ERROR( cmdArchivePush(), ArchiveMismatchError, @@ -330,24 +331,20 @@ testRun(void) TEST_TITLE("push by ignoring the invalid header"); argListTemp = strLstDup(argList); - hrnCfgArgRawNegate(argListTemp, cfgOptArchiveHeaderCheck); + hrnCfgArgRawBool(argListTemp, cfgOptArchiveHeaderCheck, false); strLstAddZ(argListTemp, "pg_wal/000000010000000100000001"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment"); TEST_RESULT_LOG("P00 INFO: pushed WAL file '000000010000000100000001' to the archive"); - TEST_RESULT_BOOL( - storageExistsP( - storageRepoIdx(0), - strNewFmt(STORAGE_REPO_ARCHIVE "/11-1/000000010000000100000001-%s.gz", walBuffer1Sha1)), - true, "check repo for WAL file"); TEST_STORAGE_EXISTS( storageRepoIdxWrite(0), strZ(strNewFmt(STORAGE_REPO_ARCHIVE "/11-1/000000010000000100000001-%s.gz", walBuffer1Sha1)), - .remove = true); + .remove = true, .comment = "check repo for WAL file, then remove"); - // Generate valid WAL and push them // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("generate valid WAL and push them"); + argListTemp = strLstDup(argList); strLstAddZ(argListTemp, "pg_wal/000000010000000100000001"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); @@ -361,15 +358,14 @@ testRun(void) (TEST_BIG_ENDIAN() ? "1c5f963d720bb199d7935dbd315447ea2ec3feb2" : "aae7591a1dbc58f21d0d004886075094f622e6dd") : "28a13fd8cf6fcd9f9a8108aed4c8bcc58040863a"; - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000001")), walBuffer1); + HRN_STORAGE_PUT(storagePgWrite(), "pg_wal/000000010000000100000001", walBuffer1); TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment"); TEST_RESULT_LOG("P00 INFO: pushed WAL file '000000010000000100000001' to the archive"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo/archive/test/11-1/0000000100000001/000000010000000100000001-%s.gz", walBuffer1Sha1)), - true, "check repo for WAL file"); + TEST_STORAGE_EXISTS( + storageRepoIdxWrite(0), strZ(strNewFmt(STORAGE_REPO_ARCHIVE "/11-1/000000010000000100000001-%s.gz", walBuffer1Sha1)), + .comment = "check repo for WAL file"); TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment again"); TEST_RESULT_LOG( @@ -384,7 +380,7 @@ testRun(void) hrnPgWalToBuffer((PgWal){.version = PG_VERSION_11, .systemId = 0xFACEFACEFACEFACE}, walBuffer2); const char *walBuffer2Sha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer2))); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/000000010000000100000001")), walBuffer2); + HRN_STORAGE_PUT(storagePgWrite(), "pg_wal/000000010000000100000001", walBuffer2); TEST_ERROR( cmdArchivePush(), ArchiveDuplicateError, @@ -394,58 +390,58 @@ testRun(void) TEST_TITLE("WAL with absolute path and no pg1-path"); argListTemp = strLstNew(); - strLstAddZ(argListTemp, "--" CFGOPT_STANZA "=test"); + hrnCfgArgRawZ(argListTemp, cfgOptStanza, "test"); hrnCfgArgRawZ(argListTemp, cfgOptRepoPath, TEST_PATH "/repo"); strLstAddZ(argListTemp, TEST_PATH "/pg/pg_wal/000000010000000100000002"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); - TEST_RESULT_VOID( - storagePutP(storageNewWriteP(storageTest, STRDEF("pg/pg_wal/000000010000000100000002")), walBuffer2), "write WAL"); + HRN_STORAGE_PUT(storageTest, "pg/pg_wal/000000010000000100000002", walBuffer2, .comment = "write WAL"); // Create tmp file to make it look like a prior push failed partway through to ensure that retries work - TEST_RESULT_VOID( - storagePutP( - storageNewWriteP( - storageTest, - strNewFmt("repo/archive/test/11-1/0000000100000001/000000010000000100000002-%s.gz.pgbackrest.tmp", - walBuffer2Sha1)), - BUFSTRDEF("PARTIAL")), - "write WAL tmp file"); + HRN_STORAGE_PUT_Z( + storageTest, + strZ( + strNewFmt("repo/archive/test/11-1/0000000100000001/000000010000000100000002-%s.gz.pgbackrest.tmp", walBuffer2Sha1)), + "PARTIAL", .comment = "write WAL tmp file"); TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment"); TEST_RESULT_LOG("P00 INFO: pushed WAL file '000000010000000100000002' to the archive"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo/archive/test/11-1/0000000100000001/000000010000000100000002-%s.gz", walBuffer2Sha1)), - true, "check repo for WAL file"); + TEST_STORAGE_EXISTS( + storageRepoIdxWrite(0), + strZ( + strNewFmt( + STORAGE_REPO_ARCHIVE "/11-1/0000000100000001/000000010000000100000002-%s.gz", walBuffer2Sha1)), + .comment = "check repo for WAL file"); TEST_RESULT_BOOL( storageExistsP( storageTest, strNewFmt("repo/archive/test/11-1/0000000100000001/000000010000000100000002-%s.gz.pgbackrest.tmp", walBuffer2Sha1)), false, "check WAL tmp file is gone"); - // Push a history file // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("push a history file"); + argListTemp = strLstDup(argList); strLstAddZ(argListTemp, "pg_wal/00000001.history"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/00000001.history")), BUFSTRDEF("FAKEHISTORY")); + HRN_STORAGE_PUT_Z(storagePgWrite(), "pg_wal/00000001.history", "FAKEHISTORY"); TEST_RESULT_VOID(cmdArchivePush(), "push a history file"); TEST_RESULT_LOG("P00 INFO: pushed WAL file '00000001.history' to the archive"); - TEST_RESULT_BOOL( - storageExistsP(storageTest, STRDEF("repo/archive/test/11-1/00000001.history")), true, "check repo for history file"); + TEST_STORAGE_EXISTS( + storageRepoIdx(0), STORAGE_REPO_ARCHIVE "/11-1/00000001.history", .comment = "check repo for history file"); - // Check drop functionality // ------------------------------------------------------------------------------------------------------------------------- - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000001.ready")), NULL); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_wal/archive_status/000000010000000100000002.ready")), NULL); + TEST_TITLE("check drop functionality"); + + HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "pg_wal/archive_status/000000010000000100000001.ready"); + HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "pg_wal/archive_status/000000010000000100000002.ready"); argListTemp = strLstDup(argList); - strLstAddZ(argListTemp, "--archive-push-queue-max=16m"); + hrnCfgArgRawZ(argListTemp, cfgOptArchivePushQueueMax, "16m"); strLstAddZ(argListTemp, "pg_wal/000000010000000100000002"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); @@ -453,7 +449,7 @@ testRun(void) TEST_RESULT_LOG("P00 WARN: dropped WAL file '000000010000000100000002' because archive queue exceeded 16MB"); argListTemp = strLstDup(argList); - strLstAddZ(argListTemp, "--archive-push-queue-max=1GB"); + hrnCfgArgRawZ(argListTemp, cfgOptArchivePushQueueMax, "1GB"); strLstAddZ(argListTemp, "pg_wal/000000010000000100000002"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); @@ -469,36 +465,6 @@ testRun(void) // Remove old repo HRN_STORAGE_PATH_REMOVE(storageTest, "repo", .errorOnMissing = true, .recurse = true); - // repo2 is encrypted - StorageWrite *infoWrite = storageNewWriteP(storageTest, STRDEF("repo2/archive/test/archive.info")); - - ioFilterGroupAdd( - ioWriteFilterGroup(storageWriteIo(infoWrite)), cipherBlockNew(cipherModeEncrypt, cipherTypeAes256Cbc, - BUFSTRDEF("badpassphrase"), NULL)); - - storagePutP( - infoWrite, - harnessInfoChecksumZ( - "[cipher]\n" - "cipher-pass=\"badsubpassphrase\"\n" - "\n" - "[db]\n" - "db-id=1\n" - "\n" - "[db:history]\n" - "1={\"db-id\":18072658121562454734,\"db-version\":\"11\"}")); - - // repo3 is not encrypted - storagePutP( - storageNewWriteP(storageTest, STRDEF("repo3/archive/test/archive.info")), - harnessInfoChecksumZ( - "[db]\n" - "db-id=1\n" - "\n" - "[db:history]\n" - "1={\"db-id\":18072658121562454734,\"db-version\":\"11\"}")); - - // Push encrypted WAL segment argListTemp = strLstNew(); hrnCfgArgRawZ(argListTemp, cfgOptStanza, "test"); hrnCfgArgKeyRawZ(argListTemp, cfgOptPgPath, 1, TEST_PATH "/pg"); @@ -511,29 +477,43 @@ testRun(void) HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); hrnCfgEnvKeyRemoveRaw(cfgOptRepoCipherPass, 2); + // repo2 is encrypted + HRN_INFO_PUT( + storageRepoIdxWrite(0), INFO_ARCHIVE_PATH_FILE, + "[cipher]\n" + "cipher-pass=\"badsubpassphrase\"\n" + "\n" + "[db]\n" + "db-id=1\n" + "\n" + "[db:history]\n" + "1={\"db-id\":18072658121562454734,\"db-version\":\"11\"}", + .cipherType = cipherTypeAes256Cbc, .cipherPass = "badpassphrase"); + + // repo3 is not encrypted + HRN_INFO_PUT( + storageRepoIdxWrite(1), INFO_ARCHIVE_PATH_FILE, + "[db]\n" + "db-id=1\n" + "\n" + "[db:history]\n" + "1={\"db-id\":18072658121562454734,\"db-version\":\"11\"}"); + + // Push encrypted WAL segment TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment"); TEST_RESULT_LOG("P00 INFO: pushed WAL file '000000010000000100000002' to the archive"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo2/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), - true, "check repo2 for WAL file"); + TEST_STORAGE_EXISTS( + storageTest, strZ(strNewFmt("repo2/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), + .remove = true, .comment = "check repo2 for WAL file then remove"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo3/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), - true, "check repo3 for WAL file"); + TEST_STORAGE_EXISTS( + storageTest, strZ(strNewFmt("repo3/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), + .remove = true, .comment = "check repo3 for WAL file then remove"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("write error on one repo but other repo succeeds"); - storageRemoveP( - storageTest, strNewFmt("repo2/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1), - .errorOnMissing = true); - storageRemoveP( - storageTest, strNewFmt("repo3/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1), - .errorOnMissing = true); - HRN_STORAGE_MODE(storageTest, "repo2/archive/test/11-1/0000000100000001", .mode = 0500); TEST_ERROR( @@ -544,14 +524,10 @@ testRun(void) "repo2: [FileOpenError] unable to open file '" TEST_PATH "/repo2/archive/test/11-1/0000000100000001" "/000000010000000100000002-%s' for write: [13] Permission denied", walBuffer2Sha1))); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo2/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), - false, "check repo2 for no WAL file"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo3/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), - true, "check repo3 for WAL file"); + TEST_STORAGE_LIST_EMPTY(storageTest, "repo2/archive/test/11-1/0000000100000001", .comment = "check repo2 for no WAL file"); + TEST_STORAGE_LIST( + storageTest, "repo3/archive/test/11-1/0000000100000001", + strZ(strNewFmt("000000010000000100000002-%s\n", walBuffer2Sha1)), .comment = "check repo3 for WAL file"); HRN_STORAGE_MODE(storageTest, "repo2/archive/test/11-1/0000000100000001"); @@ -564,10 +540,9 @@ testRun(void) " HINT: this is valid in some recovery scenarios but may also indicate a problem.\n" "P00 INFO: pushed WAL file '000000010000000100000002' to the archive"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo2/archive/test/11-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), - true, "check repo2 for WAL file"); + TEST_STORAGE_LIST( + storageTest, "repo2/archive/test/11-1/0000000100000001", + strZ(strNewFmt("000000010000000100000002-%s\n", walBuffer2Sha1)), .comment = "check repo2 for WAL file"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("WAL already exists in both repos"); @@ -639,6 +614,7 @@ testRun(void) static const ProtocolServerHandler testLocalHandlerList[] = {PROTOCOL_SERVER_HANDLER_ARCHIVE_PUSH_LIST}; hrnProtocolLocalShimInstall(testLocalHandlerList, PROTOCOL_SERVER_HANDLER_LIST_SIZE(testLocalHandlerList)); + // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("command must be run on the pg host"); StringList *argList = strLstNew(); @@ -655,78 +631,80 @@ testRun(void) TEST_TITLE("pg1-path must be set when async"); argList = strLstNew(); - strLstAddZ(argList, "--" CFGOPT_SPOOL_PATH "=/spool"); - strLstAddZ(argList, "--" CFGOPT_STANZA "=test2"); - strLstAddZ(argList, "--" CFGOPT_ARCHIVE_ASYNC); + hrnCfgArgRawZ(argList, cfgOptSpoolPath, "/spool"); + hrnCfgArgRawZ(argList, cfgOptStanza, "test2"); + hrnCfgArgRawBool(argList, cfgOptArchiveAsync, true); strLstAddZ(argList, "/000000010000000100000001"); HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync); TEST_ERROR(cmdArchivePush(), OptionRequiredError, "'archive-push' command in async mode requires option 'pg1-path'"); - // Call with a bogus exe name so the async process will error out and we can make sure timeouts work // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("check timeout on async error"); + + // Call with a bogus exe name so the async process will error out and we can make sure timeouts work argList = strLstNew(); - strLstAddZ(argList, "--stanza=test"); - strLstAddZ(argList, "--archive-async"); - strLstAddZ(argList, "--archive-timeout=1"); - strLstAddZ(argList, "--spool-path=" TEST_PATH " /spool"); - strLstAddZ(argList, "--pg1-path=" TEST_PATH "/pg"); - strLstAddZ(argList, "--repo1-path=" TEST_PATH "/repo"); + hrnCfgArgRawZ(argList, cfgOptSpoolPath, TEST_PATH "/spool"); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawBool(argList, cfgOptArchiveAsync, true); + hrnCfgArgRawZ(argList, cfgOptPgPath, TEST_PATH "/pg"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH "/repo"); + hrnCfgArgRawZ(argList, cfgOptArchiveTimeout, "1"); strLstAddZ(argList, "pg_wal/bogus"); HRN_CFG_LOAD(cfgCmdArchivePush, argList, .exeBogus = true); - storagePathCreateP(storageTest, cfgOptionStr(cfgOptPgPath)); + HRN_STORAGE_PATH_CREATE(storageTest, strZ(cfgOptionStr(cfgOptPgPath))); THROW_ON_SYS_ERROR(chdir(strZ(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()"); TEST_ERROR( cmdArchivePush(), ArchiveTimeoutError, "unable to push WAL file 'bogus' to the archive asynchronously after 1 second(s)"); - // Create pg_control and archive.info + // Create pg_control and archive.info for next set of tests // ------------------------------------------------------------------------------------------------------------------------- argList = strLstNew(); - strLstAddZ(argList, "--stanza=test"); - strLstAddZ(argList, "--archive-async"); - strLstAddZ(argList, "--no-compress"); - strLstAddZ(argList, "--spool-path=" TEST_PATH "/spool"); - strLstAddZ(argList, "--pg1-path=" TEST_PATH "/pg"); - strLstAddZ(argList, "--repo1-path=" TEST_PATH "/repo"); - strLstAddZ(argList, "--log-subprocess"); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawBool(argList, cfgOptArchiveAsync, true); + hrnCfgArgRawBool(argList, cfgOptCompress, false); + hrnCfgArgRawZ(argList, cfgOptSpoolPath, TEST_PATH "/spool"); + hrnCfgArgRawZ(argList, cfgOptPgPath, TEST_PATH "/pg"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH "/repo"); + hrnCfgArgRawBool(argList, cfgOptLogSubprocess, true); - storagePutP( - storageNewWriteP(storageTest, STRDEF("pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL)), + HRN_STORAGE_PUT(storageTest, "pg/" PG_PATH_GLOBAL "/" PG_FILE_PGCONTROL, hrnPgControlToBuffer((PgControl){.version = PG_VERSION_94, .systemId = 0xAAAABBBBCCCCDDDD})); - storagePutP( - storageNewWriteP(storageTest, STRDEF("repo/archive/test/archive.info")), - harnessInfoChecksumZ( - "[db]\n" - "db-id=1\n" - "\n" - "[db:history]\n" - "1={\"db-id\":12297848147757817309,\"db-version\":\"9.4\"}\n")); + HRN_INFO_PUT( + storageTest, "repo/archive/test/archive.info", + "[db]\n" + "db-id=1\n" + "\n" + "[db:history]\n" + "1={\"db-id\":12297848147757817309,\"db-version\":\"9.4\"}\n"); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("async, ignore error file on first pass"); // Write out an error file that will be ignored on the first pass, then the async process will write a new one - // ------------------------------------------------------------------------------------------------------------------------- StringList *argListTemp = strLstDup(argList); strLstAddZ(argListTemp, TEST_PATH "/pg/pg_xlog/000000010000000100000001"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); - storagePathCreateP(storagePgWrite(), STRDEF("pg_xlog/archive_status")); + HRN_STORAGE_PATH_CREATE(storagePgWrite(), "pg_xlog/archive_status"); - storagePutP( - storageNewWriteP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.error")), - BUFSTRDEF("25\nbogus error")); + HRN_STORAGE_PUT_Z(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.error", "25\nbogus error"); TEST_ERROR(cmdArchivePush(), AssertError, "no WAL files to process"); - storageRemoveP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/global.error"), .errorOnMissing = true); + TEST_STORAGE_EXISTS(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/global.error", .remove = true); + + // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("with lock, prevent async from running"); // Acquire a lock so the async process will not be able to run -- this will result in a timeout - // ------------------------------------------------------------------------------------------------------------------------- argListTemp = strLstDup(argList); strLstAddZ(argListTemp, TEST_PATH "/pg/pg_xlog/000000010000000100000001"); - strLstAddZ(argListTemp, "--archive-timeout=1"); + hrnCfgArgRawZ(argListTemp, cfgOptArchiveTimeout, "1"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); THROW_ON_SYS_ERROR(chdir(strZ(cfgOptionStr(cfgOptPgPath))) != 0, PathMissingError, "unable to chdir()"); @@ -774,13 +752,15 @@ testRun(void) } HARNESS_FORK_END(); - // Actually push a WAL file // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("async WAL push"); + + // Actually push a WAL file argListTemp = strLstDup(argList); strLstAddZ(argListTemp, TEST_PATH "/pg/pg_xlog/000000010000000100000001"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/archive_status/000000010000000100000001.ready")), NULL); + HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "pg_xlog/archive_status/000000010000000100000001.ready"); Buffer *walBuffer1 = bufNew((size_t)16 * 1024 * 1024); bufUsedSet(walBuffer1, bufSize(walBuffer1)); @@ -788,51 +768,50 @@ testRun(void) hrnPgWalToBuffer((PgWal){.version = PG_VERSION_94, .systemId = 0xAAAABBBBCCCCDDDD}, walBuffer1); const char *walBuffer1Sha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer1))); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/000000010000000100000001")), walBuffer1); + HRN_STORAGE_PUT(storagePgWrite(),"pg_xlog/000000010000000100000001", walBuffer1); TEST_RESULT_VOID(cmdArchivePush(), "push the WAL segment"); TEST_RESULT_LOG("P00 INFO: pushed WAL file '000000010000000100000001' to the archive asynchronously"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)), - true, "check repo for WAL file"); + TEST_STORAGE_EXISTS( + storageTest, strZ(strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)), + .comment = "check repo for WAL file"); - // Direct tests of the async function // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("direct tests of the async function"); + argList = strLstNew(); - strLstAddZ(argList, "--stanza=test"); + hrnCfgArgRawZ(argList, cfgOptSpoolPath, TEST_PATH "/spool"); + hrnCfgArgRawZ(argList, cfgOptStanza, "test"); + hrnCfgArgRawBool(argList, cfgOptArchiveAsync, true); + hrnCfgArgRawZ(argList, cfgOptPgPath, TEST_PATH "/pg"); + hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH "/repo"); + hrnCfgArgRawBool(argList, cfgOptLogSubprocess, true); hrnCfgArgRawZ(argList, cfgOptCompressType, "none"); - strLstAddZ(argList, "--spool-path=" TEST_PATH "/spool"); - strLstAddZ(argList, "--" CFGOPT_ARCHIVE_ASYNC); - strLstAddZ(argList, "--pg1-path=" TEST_PATH "/pg"); - strLstAddZ(argList, "--repo1-path=" TEST_PATH "/repo"); - strLstAddZ(argList, "--log-subprocess"); HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync); TEST_ERROR(cmdArchivePushAsync(), ParamRequiredError, "WAL path to push required"); - // Check that global.error is created // ------------------------------------------------------------------------------------------------------------------------- + TEST_TITLE("async, check that global.error is created"); + // Remove data from prior tests HRN_STORAGE_PATH_REMOVE(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT, .recurse = true); - storagePathCreateP(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT_STR); + HRN_STORAGE_PATH_CREATE(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT); HRN_STORAGE_PATH_REMOVE(storagePgWrite(), "pg_xlog/archive_status", .recurse = true); - storagePathCreateP(storagePgWrite(), STRDEF("pg_xlog/archive_status")); + HRN_STORAGE_PATH_CREATE(storagePgWrite(), "pg_xlog/archive_status"); strLstAddZ(argList, TEST_PATH "/pg/pg_xlog"); HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync); TEST_ERROR(cmdArchivePushAsync(), AssertError, "no WAL files to process"); - TEST_RESULT_STR_Z( - strNewBuf(storageGetP(storageNewReadP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/global.error")))), - "25\nno WAL files to process", "check global.error"); + TEST_STORAGE_GET( + storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT "/global.error", "25\nno WAL files to process", + .comment = "check global.error"); - TEST_RESULT_STRLST_Z( - strLstSort(storageListP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT)), sortOrderAsc), - "global.error\n", "check status files"); + TEST_STORAGE_LIST(storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT, "global.error\n", .comment = "check status files"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("add repo, push already pushed WAL and new WAL"); @@ -841,25 +820,23 @@ testRun(void) hrnCfgArgKeyRawZ(argList, cfgOptRepoPath, 3, TEST_PATH "/repo3"); HRN_CFG_LOAD(cfgCmdArchivePush, argList, .role = cfgCmdRoleAsync); - storagePutP( - storageNewWriteP(storageTest, STRDEF("repo3/archive/test/archive.info")), - harnessInfoChecksumZ( - "[db]\n" - "db-id=1\n" - "\n" - "[db:history]\n" - "1={\"db-id\":12297848147757817309,\"db-version\":\"9.4\"}\n")); + HRN_INFO_PUT( + storageTest, "repo3/archive/test/archive.info", + "[db]\n" + "db-id=1\n" + "\n" + "[db:history]\n" + "1={\"db-id\":12297848147757817309,\"db-version\":\"9.4\"}\n"); // Recreate ready file for WAL 1 - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/archive_status/000000010000000100000001.ready")), NULL); + HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "pg_xlog/archive_status/000000010000000100000001.ready"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)), - true, "check repo1 for WAL 1 file"); + TEST_STORAGE_EXISTS( + storageTest, strZ(strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)), + .comment = "check repo1 for WAL 1 file"); // Create a ready file for WAL 2 but don't create the segment yet -- this will test the file error - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/archive_status/000000010000000100000002.ready")), NULL); + HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "pg_xlog/archive_status/000000010000000100000002.ready"); TEST_RESULT_VOID(cmdArchivePushAsync(), "push WAL segments"); TEST_RESULT_LOG_FMT( @@ -871,19 +848,19 @@ testRun(void) "[55] raised from local-1 shim protocol: " STORAGE_ERROR_READ_MISSING, TEST_PATH "/pg/pg_xlog/000000010000000100000002"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)), - true, "check repo1 for WAL 1 file"); + TEST_STORAGE_EXISTS( + storageTest, strZ(strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)), + .comment = "check repo1 for WAL 1 file"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)), - true, "check repo3 for WAL 1 file"); + TEST_STORAGE_EXISTS( + storageTest, strZ(strNewFmt("repo3/archive/test/9.4-1/0000000100000001/000000010000000100000001-%s", walBuffer1Sha1)), + .comment = "check repo3 for WAL 1 file"); - TEST_RESULT_STRLST_Z( - strLstSort(storageListP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT)), sortOrderAsc), - "000000010000000100000001.ok\n000000010000000100000002.error\n", "check status files"); + TEST_STORAGE_LIST( + storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT, + "000000010000000100000001.ok\n" + "000000010000000100000002.error\n", + .comment = "check status files"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("create and push previously missing WAL"); @@ -895,10 +872,10 @@ testRun(void) hrnPgWalToBuffer((PgWal){.version = PG_VERSION_94, .systemId = 0xAAAABBBBCCCCDDDD}, walBuffer2); const char *walBuffer2Sha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer2))); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/000000010000000100000002")), walBuffer2); + HRN_STORAGE_PUT(storagePgWrite(), "pg_xlog/000000010000000100000002", walBuffer2); argListTemp = strLstDup(argList); - strLstAddZ(argListTemp, "--archive-push-queue-max=1gb"); + hrnCfgArgRawZ(argListTemp, cfgOptArchivePushQueueMax, "1gb"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp, .role = cfgCmdRoleAsync); TEST_RESULT_VOID(cmdArchivePushAsync(), "push WAL segments"); @@ -906,24 +883,24 @@ testRun(void) "P00 INFO: push 1 WAL file(s) to archive: 000000010000000100000002\n" "P01 DETAIL: pushed WAL file '000000010000000100000002' to the archive"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), - true, "check repo1 for WAL 2 file"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo3/archive/test/9.4-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), - true, "check repo3 for WAL 2 file"); + TEST_STORAGE_EXISTS( + storageTest, strZ(strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), + .comment = "check repo1 for WAL 2 file"); + TEST_STORAGE_EXISTS( + storageTest, strZ(strNewFmt("repo3/archive/test/9.4-1/0000000100000001/000000010000000100000002-%s", walBuffer2Sha1)), + .comment = "check repo3 for WAL 2 file"); - TEST_RESULT_STRLST_Z( - strLstSort(storageListP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT)), sortOrderAsc), - "000000010000000100000001.ok\n000000010000000100000002.ok\n", "check status files"); + TEST_STORAGE_LIST( + storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT, + "000000010000000100000001.ok\n" + "000000010000000100000002.ok\n", + .comment = "check status files"); // ------------------------------------------------------------------------------------------------------------------------- TEST_TITLE("push wal 2 again to get warnings from both repos"); // Remove the OK file so the WAL gets pushed again - storageRemoveP(storageSpoolWrite(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000002.ok")); + HRN_STORAGE_REMOVE(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000002.ok"); TEST_RESULT_VOID(cmdArchivePushAsync(), "push WAL segments"); TEST_RESULT_LOG( @@ -944,36 +921,34 @@ testRun(void) hrnPgWalToBuffer((PgWal){.version = PG_VERSION_94, .systemId = 0xAAAABBBBCCCCDDDD}, walBuffer3); const char *walBuffer3Sha1 = strZ(bufHex(cryptoHashOne(HASH_TYPE_SHA1_STR, walBuffer3))); - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/000000010000000100000003")), walBuffer3); + HRN_STORAGE_PUT(storagePgWrite(), "pg_xlog/000000010000000100000003", walBuffer3); // Create ready file - storagePutP(storageNewWriteP(storagePgWrite(), STRDEF("pg_xlog/archive_status/000000010000000100000003.ready")), NULL); + HRN_STORAGE_PUT_EMPTY(storagePgWrite(), "pg_xlog/archive_status/000000010000000100000003.ready"); TEST_RESULT_VOID(cmdArchivePushAsync(), "push WAL segment"); TEST_RESULT_LOG( "P00 INFO: push 1 WAL file(s) to archive: 000000010000000100000003\n" "P01 DETAIL: pushed WAL file '000000010000000100000003' to the archive"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000003-%s", walBuffer3Sha1)), - true, "check repo1 for WAL 3 file"); - TEST_RESULT_BOOL( - storageExistsP( - storageTest, strNewFmt("repo3/archive/test/9.4-1/0000000100000001/000000010000000100000003-%s", walBuffer3Sha1)), - true, "check repo3 for WAL 3 file"); + TEST_STORAGE_EXISTS( + storageTest, strZ(strNewFmt("repo/archive/test/9.4-1/0000000100000001/000000010000000100000003-%s", walBuffer3Sha1)), + .comment = "check repo1 for WAL 3 file"); + TEST_STORAGE_EXISTS( + storageTest, strZ(strNewFmt("repo3/archive/test/9.4-1/0000000100000001/000000010000000100000003-%s", walBuffer3Sha1)), + .comment = "check repo3 for WAL 3 file"); // Remove the ready file to prevent WAL 3 from being considered for the next test - storageRemoveP(storagePgWrite(), STRDEF("pg_xlog/archive_status/000000010000000100000003.ready"), .errorOnMissing = true); + HRN_STORAGE_REMOVE(storagePgWrite(), "pg_xlog/archive_status/000000010000000100000003.ready", .errorOnMissing = true); // Check that drop functionality works // ------------------------------------------------------------------------------------------------------------------------- // Remove status files HRN_STORAGE_PATH_REMOVE(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT, .recurse = true); - storagePathCreateP(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT_STR); + HRN_STORAGE_PATH_CREATE(storageSpoolWrite(), STORAGE_SPOOL_ARCHIVE_OUT); argListTemp = strLstDup(argList); - strLstAddZ(argListTemp, "--archive-push-queue-max=16m"); + hrnCfgArgRawZ(argListTemp, cfgOptArchivePushQueueMax, "16m"); HRN_CFG_LOAD(cfgCmdArchivePush, argListTemp, .role = cfgCmdRoleAsync); TEST_RESULT_VOID(cmdArchivePushAsync(), "push WAL segments"); @@ -982,19 +957,19 @@ testRun(void) "P00 WARN: dropped WAL file '000000010000000100000001' because archive queue exceeded 16MB\n" "P00 WARN: dropped WAL file '000000010000000100000002' because archive queue exceeded 16MB"); - TEST_RESULT_STR_Z( - strNewBuf( - storageGetP(storageNewReadP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok")))), - "0\ndropped WAL file '000000010000000100000001' because archive queue exceeded 16MB", "check WAL 1 warning"); + TEST_STORAGE_GET( + storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000001.ok", + "0\ndropped WAL file '000000010000000100000001' because archive queue exceeded 16MB", .comment = "check WAL 1 warning"); - TEST_RESULT_STR_Z( - strNewBuf( - storageGetP(storageNewReadP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000002.ok")))), - "0\ndropped WAL file '000000010000000100000002' because archive queue exceeded 16MB", "check WAL 2 warning"); + TEST_STORAGE_GET( + storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT "/000000010000000100000002.ok", + "0\ndropped WAL file '000000010000000100000002' because archive queue exceeded 16MB", .comment = "check WAL 2 warning"); - TEST_RESULT_STRLST_Z( - strLstSort(storageListP(storageSpool(), STRDEF(STORAGE_SPOOL_ARCHIVE_OUT)), sortOrderAsc), - "000000010000000100000001.ok\n000000010000000100000002.ok\n", "check status files"); + TEST_STORAGE_LIST( + storageSpool(), STORAGE_SPOOL_ARCHIVE_OUT, + "000000010000000100000001.ok\n" + "000000010000000100000002.ok\n", + .comment = "check status files"); // Uninstall local command handler shim hrnProtocolLocalShimUninstall();