You've already forked pgbackrest
							
							
				mirror of
				https://github.com/pgbackrest/pgbackrest.git
				synced 2025-10-30 23:37:45 +02:00 
			
		
		
		
	Refactor storage/remote unit test using the protocol remote shim.
Using the local process shim improves coverage and simplifies the tests.
This commit is contained in:
		| @@ -213,6 +213,7 @@ | ||||
|                         <commit subject="Add local process shim to archive-get/archive-push unit tests."/> | ||||
|                         <commit subject="Set buffer-size in the configuration test harness."/> | ||||
|                         <commit subject="Factor remote process exec out of protocolRemoteGet()."/> | ||||
|                         <commit subject="Refactor storage/remote unit test using the protocol remote shim."/> | ||||
|  | ||||
|                         <p>Add local processs shim.</p> | ||||
|                     </release-item> | ||||
|   | ||||
| @@ -571,8 +571,6 @@ unit: | ||||
|       # ---------------------------------------------------------------------------------------------------------------------------- | ||||
|       - name: remote | ||||
|         total: 9 | ||||
|         containerReq: true | ||||
|         binReq: true | ||||
|  | ||||
|         coverage: | ||||
|           - storage/remote/read | ||||
|   | ||||
| @@ -5,11 +5,12 @@ Test Remote Storage | ||||
| #include "common/crypto/cipherBlock.h" | ||||
| #include "common/io/bufferRead.h" | ||||
| #include "common/io/bufferWrite.h" | ||||
| #include "config/protocol.h" | ||||
| #include "postgres/interface.h" | ||||
|  | ||||
| #include "common/harnessConfig.h" | ||||
| #include "common/harnessProtocol.h" | ||||
| #include "common/harnessStorage.h" | ||||
| #include "common/harnessTest.h" | ||||
|  | ||||
| /*********************************************************************************************************************************** | ||||
| Test Run | ||||
| @@ -19,10 +20,19 @@ testRun(void) | ||||
| { | ||||
|     FUNCTION_HARNESS_VOID(); | ||||
|  | ||||
|     // Install remote command handler shim | ||||
|     static const ProtocolServerHandler testRemoteHandlerList[] = | ||||
|     { | ||||
|         PROTOCOL_SERVER_HANDLER_OPTION_LIST | ||||
|         PROTOCOL_SERVER_HANDLER_STORAGE_REMOTE_LIST | ||||
|     }; | ||||
|  | ||||
|     hrnProtocolRemoteShimInstall(testRemoteHandlerList, PROTOCOL_SERVER_HANDLER_LIST_SIZE(testRemoteHandlerList)); | ||||
|  | ||||
|     // Test storage | ||||
|     Storage *storageTest = storagePosixNewP(TEST_PATH_STR, .write = true); | ||||
|  | ||||
|     // Load configuration to set repo-path and stanza | ||||
|     // Load configuration and get repo remote storage | ||||
|     StringList *argList = strLstNew(); | ||||
|     strLstAddZ(argList, "--stanza=db"); | ||||
|     strLstAddZ(argList, "--protocol-timeout=10"); | ||||
| @@ -34,77 +44,51 @@ testRun(void) | ||||
|     hrnCfgArgRawZ(argList, cfgOptRepo, "1"); | ||||
|     harnessCfgLoadRole(cfgCmdArchiveGet, cfgCmdRoleLocal, argList); | ||||
|  | ||||
|     // Set type since we'll be running local and remote tests here | ||||
|     cfgOptionSet(cfgOptRemoteType, cfgSourceParam, VARSTRDEF("repo")); | ||||
|     const Storage *const storageRepoWrite = storageRepoGet(0, true); | ||||
|     const Storage *const storageRepo = storageRepoGet(0, false); | ||||
|  | ||||
|     // Set pg host so we can run both pg and repo remotes | ||||
|     cfgOptionSet(cfgOptPgHost, cfgSourceParam, VARSTRDEF("localhost")); | ||||
|     // Load configuration and get pg remote storage | ||||
|     argList = strLstNew(); | ||||
|     hrnCfgArgRawZ(argList, cfgOptStanza, "db"); | ||||
|     hrnCfgArgRawFmt(argList, cfgOptBufferSize, "%zu", ioBufferSize()); | ||||
|     hrnCfgArgRawZ(argList, cfgOptProtocolTimeout, "10"); | ||||
|     hrnCfgArgKeyRawZ(argList, cfgOptPgPath, 1, TEST_PATH_PG "1"); | ||||
|     hrnCfgArgKeyRawZ(argList, cfgOptPgHost, 2, "localhost"); | ||||
|     hrnCfgArgKeyRawZ(argList, cfgOptPgHostUser, 2, TEST_USER); | ||||
|     hrnCfgArgKeyRawZ(argList, cfgOptPgPath, 2, TEST_PATH_PG "2"); | ||||
|     hrnCfgArgRawZ(argList, cfgOptRepoPath, TEST_PATH_REPO); | ||||
|     harnessCfgLoad(cfgCmdBackup, argList); | ||||
|  | ||||
|     // Start a protocol server to test the remote protocol | ||||
|     Buffer *serverRead = bufNew(8192); | ||||
|     Buffer *serverWrite = bufNew(8192); | ||||
|     IoRead *serverReadIo = ioBufferReadNew(serverRead); | ||||
|     IoWrite *serverWriteIo = ioBufferWriteNew(serverWrite); | ||||
|     ioReadOpen(serverReadIo); | ||||
|     ioWriteOpen(serverWriteIo); | ||||
|     const Storage *const storagePgWrite = storagePgGet(1, true); | ||||
|  | ||||
|     ProtocolServer *server = protocolServerNew(STRDEF("test"), STRDEF("test"), serverReadIo, serverWriteIo); | ||||
|     // Create a file larger than the remote buffer size | ||||
|     Buffer *contentBuf = bufNew(ioBufferSize() * 2); | ||||
|  | ||||
|     bufUsedSet(serverWrite, 0); | ||||
|     for (unsigned int contentIdx = 0; contentIdx < bufSize(contentBuf); contentIdx++) | ||||
|         bufPtr(contentBuf)[contentIdx] = contentIdx % 2 ? 'A' : 'B'; | ||||
|  | ||||
|     bufUsedSet(contentBuf, bufSize(contentBuf)); | ||||
|  | ||||
|     // ***************************************************************************************************************************** | ||||
|     if (testBegin("storageNew()")) | ||||
|     if (testBegin("storageInterface(), storageFeature, and storagePathP()")) | ||||
|     { | ||||
|         Storage *storageRemote = NULL; | ||||
|         TEST_ASSIGN(storageRemote, storageRepoGet(0, false), "get remote repo storage"); | ||||
|         TEST_RESULT_UINT(storageInterface(storageRemote).feature, storageInterface(storageTest).feature, "    check features"); | ||||
|         TEST_RESULT_BOOL(storageFeature(storageRemote, storageFeaturePath), true, "    check path feature"); | ||||
|         TEST_RESULT_BOOL(storageFeature(storageRemote, storageFeatureCompress), true, "    check compress feature"); | ||||
|         TEST_RESULT_STR_Z(storagePathP(storageRemote, NULL), TEST_PATH "/repo", "    check path"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("check protocol function directly (pg)"); | ||||
|  | ||||
|         cfgOptionSet(cfgOptRemoteType, cfgSourceParam, VARSTRDEF("pg")); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteFeatureProtocol(NULL, server), "protocol feature"); | ||||
|         TEST_RESULT_STR( | ||||
|             strNewBuf(serverWrite), strNewFmt(".\"" TEST_PATH "/repo\"\n.%" PRIu64 "\n{}\n", storageInterface(storageTest).feature), | ||||
|             "check result"); | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteFeatureProtocol(NULL, server), "protocol feature"); | ||||
|         TEST_RESULT_STR( | ||||
|             strNewBuf(serverWrite), strNewFmt(".\"" TEST_PATH "/repo\"\n.%" PRIu64 "\n{}\n", storageInterface(storageTest).feature), | ||||
|             "check result cache"); | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("check protocol function directly (repo)"); | ||||
|  | ||||
|         storageRemoteProtocolLocal.memContext = NULL; | ||||
|         cfgOptionSet(cfgOptRemoteType, cfgSourceParam, VARSTRDEF("repo")); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteFeatureProtocol(NULL, server), "protocol feature"); | ||||
|         TEST_RESULT_STR( | ||||
|             strNewBuf(serverWrite), strNewFmt(".\"" TEST_PATH "/repo\"\n.%" PRIu64 "\n{}\n", storageInterface(storageTest).feature), | ||||
|             "check result"); | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|         TEST_RESULT_UINT(storageInterface(storageRepoWrite).feature, storageInterface(storageTest).feature, "    check features"); | ||||
|         TEST_RESULT_BOOL(storageFeature(storageRepoWrite, storageFeaturePath), true, "    check path feature"); | ||||
|         TEST_RESULT_BOOL(storageFeature(storageRepoWrite, storageFeatureCompress), true, "    check compress feature"); | ||||
|         TEST_RESULT_STR_Z(storagePathP(storageRepo, NULL), TEST_PATH "/repo", "    check repo path"); | ||||
|         TEST_RESULT_STR_Z(storagePathP(storageRepoWrite, NULL), TEST_PATH "/repo", "    check repo write path"); | ||||
|         TEST_RESULT_STR_Z(storagePathP(storagePgWrite, NULL), TEST_PATH "/pg2", "    check pg write path"); | ||||
|     } | ||||
|  | ||||
|     // ***************************************************************************************************************************** | ||||
|     if (testBegin("storageInfo()")) | ||||
|     { | ||||
|         Storage *storageRemote = NULL; | ||||
|         TEST_ASSIGN(storageRemote, storageRepoGet(0, true), "get remote repo storage"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("missing file/path"); | ||||
|  | ||||
|         TEST_ERROR( | ||||
|             storageInfoP(storageRemote, STRDEF(BOGUS_STR)), FileOpenError, | ||||
|             storageInfoP(storageRepo, STRDEF(BOGUS_STR)), FileOpenError, | ||||
|             "unable to get info for missing path/file '" TEST_PATH "/repo/BOGUS'"); | ||||
|         TEST_RESULT_BOOL(storageInfoP(storageRemote, STRDEF(BOGUS_STR), .ignoreMissing = true).exists, false, "missing file/path"); | ||||
|         TEST_RESULT_BOOL(storageInfoP(storageRepo, STRDEF(BOGUS_STR), .ignoreMissing = true).exists, false, "missing file/path"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("path info"); | ||||
| @@ -113,7 +97,7 @@ testRun(void) | ||||
|         HRN_STORAGE_TIME(storageTest, "repo", 1555160000); | ||||
|  | ||||
|         StorageInfo info = {.exists = false}; | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRemote, NULL), "valid path"); | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRepo, NULL), "valid path"); | ||||
|         TEST_RESULT_STR(info.name, NULL, "    name is not set"); | ||||
|         TEST_RESULT_BOOL(info.exists, true, "    check exists"); | ||||
|         TEST_RESULT_INT(info.type, storageTypePath, "    check type"); | ||||
| @@ -129,9 +113,9 @@ testRun(void) | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("file info"); | ||||
|  | ||||
|         storagePutP(storageNewWriteP(storageRemote, STRDEF("test"), .timeModified = 1555160001), BUFSTRDEF("TESTME")); | ||||
|         storagePutP(storageNewWriteP(storageRepoWrite, STRDEF("test"), .timeModified = 1555160001), BUFSTRDEF("TESTME")); | ||||
|  | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRemote, STRDEF("test")), "valid file"); | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRepo, STRDEF("test")), "valid file"); | ||||
|         TEST_RESULT_STR(info.name, NULL, "    name is not set"); | ||||
|         TEST_RESULT_BOOL(info.exists, true, "    check exists"); | ||||
|         TEST_RESULT_INT(info.type, storageTypeFile, "    check type"); | ||||
| @@ -144,12 +128,23 @@ testRun(void) | ||||
|         TEST_RESULT_UINT(info.groupId, TEST_GROUP_ID, "    check group id"); | ||||
|         TEST_RESULT_STR(info.group, TEST_GROUP_STR, "    check group"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("file info (basic level)"); | ||||
|  | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRepo, STRDEF("test"), .level = storageInfoLevelBasic), "file basic info"); | ||||
|         TEST_RESULT_STR(info.name, NULL, "    name is not set"); | ||||
|         TEST_RESULT_BOOL(info.exists, true, "    exists"); | ||||
|         TEST_RESULT_INT(info.type, storageTypeFile, "    type"); | ||||
|         TEST_RESULT_UINT(info.size, 6, "    size"); | ||||
|         TEST_RESULT_INT(info.timeModified, 1555160001, "    mod time"); | ||||
|         TEST_RESULT_STR(info.user, NULL, "    user not set"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("special info"); | ||||
|  | ||||
|         HRN_SYSTEM("mkfifo -m 666 " TEST_PATH "/repo/fifo"); | ||||
|  | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRemote, STRDEF("fifo")), "valid fifo"); | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRepo, STRDEF("fifo")), "valid fifo"); | ||||
|         TEST_RESULT_STR(info.name, NULL, "    name is not set"); | ||||
|         TEST_RESULT_BOOL(info.exists, true, "    check exists"); | ||||
|         TEST_RESULT_INT(info.type, storageTypeSpecial, "    check type"); | ||||
| @@ -166,7 +161,7 @@ testRun(void) | ||||
|  | ||||
|         HRN_SYSTEM("ln -s ../repo/test " TEST_PATH "/repo/link"); | ||||
|  | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRemote, STRDEF("link")), "valid link"); | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRepo, STRDEF("link")), "valid link"); | ||||
|         TEST_RESULT_STR(info.name, NULL, "    name is not set"); | ||||
|         TEST_RESULT_BOOL(info.exists, true, "    check exists"); | ||||
|         TEST_RESULT_INT(info.type, storageTypeLink, "    check type"); | ||||
| @@ -181,7 +176,7 @@ testRun(void) | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("link info follow"); | ||||
|  | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRemote, STRDEF("link"), .followLink = true), "valid link follow"); | ||||
|         TEST_ASSIGN(info, storageInfoP(storageRepo, STRDEF("link"), .followLink = true), "valid link follow"); | ||||
|         TEST_RESULT_STR(info.name, NULL, "    name is not set"); | ||||
|         TEST_RESULT_BOOL(info.exists, true, "    check exists"); | ||||
|         TEST_RESULT_INT(info.type, storageTypeFile, "    check type"); | ||||
| @@ -192,79 +187,11 @@ testRun(void) | ||||
|         TEST_RESULT_STR(info.user, TEST_USER_STR, "    check user"); | ||||
|         TEST_RESULT_UINT(info.groupId, TEST_GROUP_ID, "    check group id"); | ||||
|         TEST_RESULT_STR(info.group, TEST_GROUP_STR, "    check group"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("protocol output that is not tested elsewhere (detail)"); | ||||
|  | ||||
|         info = (StorageInfo){.level = storageInfoLevelDetail, .type = storageTypeLink, .linkDestination = STRDEF("../")}; | ||||
|         TEST_RESULT_VOID(storageRemoteInfoWrite(server, &info), "write link info"); | ||||
|  | ||||
|         ioWriteFlush(serverWriteIo); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(serverWrite), ".2\n.0\n.0\n.null\n.0\n.null\n.0\n.\"../\"\n", "check result"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("check protocol function directly with missing path/file"); | ||||
|  | ||||
|         VariantList *paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStrZ(BOGUS_STR)); | ||||
|         varLstAdd(paramList, varNewUInt(storageInfoLevelBasic)); | ||||
|         varLstAdd(paramList, varNewBool(false)); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteInfoProtocol(paramList, server), "protocol list"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(serverWrite), "{\"out\":false}\n", "check result"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("check protocol function directly with a file (basic level)"); | ||||
|  | ||||
|         // Do these tests against pg for coverage.  We're not really going to get a pg remote here because the remote for this host | ||||
|         // id has already been created.  This will just test that the pg storage is selected to provide coverage. | ||||
|         cfgOptionSet(cfgOptRemoteType, cfgSourceParam, VARSTRDEF("pg")); | ||||
|  | ||||
|         paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStrZ(TEST_PATH "/repo/test")); | ||||
|         varLstAdd(paramList, varNewUInt(storageInfoLevelBasic)); | ||||
|         varLstAdd(paramList, varNewBool(false)); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteInfoProtocol(paramList, server), "protocol list"); | ||||
|         TEST_RESULT_STR_Z( | ||||
|             strNewBuf(serverWrite), | ||||
|             "{\"out\":true}\n" | ||||
|             ".0\n.1555160001\n.6\n" | ||||
|             "{}\n", | ||||
|             "check result"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("check protocol function directly with a file (detail level)"); | ||||
|  | ||||
|         paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStrZ(TEST_PATH "/repo/test")); | ||||
|         varLstAdd(paramList, varNewUInt(storageInfoLevelDetail)); | ||||
|         varLstAdd(paramList, varNewBool(false)); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteInfoProtocol(paramList, server), "protocol list"); | ||||
|         TEST_RESULT_STR_Z( | ||||
|             strNewBuf(serverWrite), | ||||
|             "{\"out\":true}\n" | ||||
|             ".0\n.1555160001\n.6\n." TEST_USER_ID_Z "\n.\"" TEST_USER "\"\n." TEST_GROUP_ID_Z "\n.\"" TEST_GROUP "\"\n.416\n" | ||||
|             "{}\n", | ||||
|             "check result"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|     } | ||||
|  | ||||
|     // ***************************************************************************************************************************** | ||||
|     if (testBegin("storageInfoList()")) | ||||
|     { | ||||
|         Storage *storageRemote = NULL; | ||||
|         TEST_ASSIGN(storageRemote, storageRepoGet(0, true), "get remote repo storage"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("path not found"); | ||||
|  | ||||
|         HarnessStorageInfoListCallbackData callbackData = | ||||
| @@ -273,8 +200,7 @@ testRun(void) | ||||
|         }; | ||||
|  | ||||
|         TEST_RESULT_BOOL( | ||||
|             storageInfoListP( | ||||
|                 storageRemote, STRDEF(BOGUS_STR), hrnStorageInfoListCallback, &callbackData, .sortOrder = sortOrderAsc), | ||||
|             storageInfoListP(storageRepo, STRDEF(BOGUS_STR), hrnStorageInfoListCallback, &callbackData, .sortOrder = sortOrderAsc), | ||||
|             false, "info list"); | ||||
|         TEST_RESULT_STR_Z( | ||||
|             callbackData.content, "", "check content"); | ||||
| @@ -282,90 +208,61 @@ testRun(void) | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("list path and file"); | ||||
|  | ||||
|         storagePathCreateP(storageRemote, NULL); | ||||
|         storagePutP(storageNewWriteP(storageRemote, STRDEF("test"), .timeModified = 1555160001), BUFSTRDEF("TESTME")); | ||||
|         storagePutP(storageNewWriteP(storagePgWrite, STRDEF("test"), .timeModified = 1555160001), BUFSTRDEF("TESTME")); | ||||
|  | ||||
|         // Path timestamp must be set after file is created since file creation updates it | ||||
|         HRN_STORAGE_TIME(storageRemote, NULL, 1555160000); | ||||
|         HRN_STORAGE_TIME(storagePgWrite, NULL, 1555160000); | ||||
|  | ||||
|         TEST_RESULT_BOOL( | ||||
|             storageInfoListP(storageRemote, NULL, hrnStorageInfoListCallback, &callbackData, .sortOrder = sortOrderAsc), | ||||
|             true, "info list"); | ||||
|             storageInfoListP(storagePgWrite, NULL, hrnStorageInfoListCallback, &callbackData, .sortOrder = sortOrderAsc), true, | ||||
|             "info list"); | ||||
|         TEST_RESULT_STR_Z( | ||||
|             callbackData.content, | ||||
|             ". {path, m=0750, u=" TEST_USER ", g=" TEST_GROUP "}\n" | ||||
|             "test {file, s=6, m=0640, t=1555160001, u=" TEST_USER ", g=" TEST_GROUP "}\n", | ||||
|             "check content"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("check protocol function directly with a path"); | ||||
|  | ||||
|         // Remove the file since ordering cannot be guaranteed in the protocol results | ||||
|         storageRemoveP(storageRemote, STRDEF("test"), .errorOnMissing = true); | ||||
|  | ||||
|         // Path timestamp must be set after file is removed since file removal updates it | ||||
|         HRN_STORAGE_TIME(storageRemote, NULL, 1555160000); | ||||
|  | ||||
|         VariantList *paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStrZ(TEST_PATH "/repo")); | ||||
|         varLstAdd(paramList, varNewUInt(storageInfoLevelDetail)); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteInfoListProtocol(paramList, server), "call protocol"); | ||||
|         TEST_RESULT_STR_Z( | ||||
|             strNewBuf(serverWrite), | ||||
|             ".\".\"\n.1\n.1555160000\n." TEST_USER_ID_Z "\n.\"" TEST_USER "\"\n." TEST_GROUP_ID_Z "\n.\"" TEST_GROUP "\"\n.488\n" | ||||
|             ".\n" | ||||
|             "{\"out\":true}\n", | ||||
|             "check result"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|     } | ||||
|  | ||||
|     // ***************************************************************************************************************************** | ||||
|     if (testBegin("storageNewRead()")) | ||||
|     { | ||||
|         Storage *storageRemote = NULL; | ||||
|         TEST_ASSIGN(storageRemote, storageRepoGet(0, false), "get remote repo storage"); | ||||
|         storagePathCreateP(storageTest, STRDEF("repo")); | ||||
|  | ||||
|         Buffer *contentBuf = bufNew(32768); | ||||
|  | ||||
|         for (unsigned int contentIdx = 0; contentIdx < bufSize(contentBuf); contentIdx++) | ||||
|             bufPtr(contentBuf)[contentIdx] = contentIdx % 2 ? 'A' : 'B'; | ||||
|  | ||||
|         bufUsedSet(contentBuf, bufSize(contentBuf)); | ||||
|         TEST_TITLE("file missing"); | ||||
|  | ||||
|         TEST_ERROR_FMT( | ||||
|             strZ(strNewBuf(storageGetP(storageNewReadP(storageRemote, STRDEF("test.txt"))))), FileMissingError, | ||||
|             "raised from remote-0 protocol on 'localhost': " STORAGE_ERROR_READ_MISSING, TEST_PATH "/repo/test.txt"); | ||||
|             strZ(strNewBuf(storageGetP(storageNewReadP(storagePgWrite, STRDEF("test.txt"))))), FileMissingError, | ||||
|             "raised from remote-0 shim protocol: " STORAGE_ERROR_READ_MISSING, TEST_PATH "/pg2/test.txt"); | ||||
|  | ||||
|         storagePutP(storageNewWriteP(storageTest, STRDEF("repo/test.txt")), contentBuf); | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("read file without compression"); | ||||
|  | ||||
|         // Disable protocol compression in the storage object to test no compression | ||||
|         ((StorageRemote *)storageDriver(storageRemote))->compressLevel = 0; | ||||
|         HRN_STORAGE_PUT(storageTest, TEST_PATH_REPO "/test.txt", contentBuf); | ||||
|  | ||||
|         // Disable protocol compression in the storage object | ||||
|         ((StorageRemote *)storageDriver(storageRepo))->compressLevel = 0; | ||||
|  | ||||
|         StorageRead *fileRead = NULL; | ||||
|  | ||||
|         ioBufferSizeSet(8193); | ||||
|         TEST_ASSIGN(fileRead, storageNewReadP(storageRemote, STRDEF("test.txt")), "new file"); | ||||
|         TEST_ASSIGN(fileRead, storageNewReadP(storageRepo, STRDEF("test.txt")), "new file"); | ||||
|         TEST_RESULT_BOOL(bufEq(storageGetP(fileRead), contentBuf), true, "get file"); | ||||
|         TEST_RESULT_BOOL(storageReadIgnoreMissing(fileRead), false, "check ignore missing"); | ||||
|         TEST_RESULT_STR_Z(storageReadName(fileRead), TEST_PATH "/repo/test.txt", "check name"); | ||||
|         TEST_RESULT_UINT(storageReadRemote(fileRead->driver, bufNew(32), false), 0, "nothing more to read"); | ||||
|  | ||||
|         TEST_ASSIGN(fileRead, storageNewReadP(storageRemote, STRDEF("test.txt")), "get file"); | ||||
|         TEST_RESULT_BOOL(bufEq(storageGetP(fileRead), contentBuf), true, "    check contents"); | ||||
|         TEST_RESULT_UINT(((StorageReadRemote *)fileRead->driver)->protocolReadBytes, bufSize(contentBuf), "    check read size"); | ||||
|  | ||||
|         TEST_ASSIGN(fileRead, storageNewReadP(storageRemote, STRDEF("test.txt"), .limit = VARUINT64(11)), "get file"); | ||||
|         // Enable protocol compression in the storage object | ||||
|         ((StorageRemote *)storageDriver(storageRepo))->compressLevel = 3; | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("read file with limit"); | ||||
|  | ||||
|         TEST_ASSIGN(fileRead, storageNewReadP(storageRepo, STRDEF("test.txt"), .limit = VARUINT64(11)), "get file"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(storageGetP(fileRead)), "BABABABABAB", "    check contents"); | ||||
|         TEST_RESULT_UINT(((StorageReadRemote *)fileRead->driver)->protocolReadBytes, 11, "    check read size"); | ||||
|  | ||||
|         // Enable protocol compression in the storage object | ||||
|         ((StorageRemote *)storageDriver(storageRemote))->compressLevel = 3; | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("read file with compression"); | ||||
|  | ||||
|         TEST_ASSIGN( | ||||
|             fileRead, storageNewReadP(storageRemote, STRDEF("test.txt"), .compressible = true), "get file (protocol compress)"); | ||||
|             fileRead, storageNewReadP(storageRepo, STRDEF("test.txt"), .compressible = true), "get file (protocol compress)"); | ||||
|         TEST_RESULT_BOOL(bufEq(storageGetP(fileRead), contentBuf), true, "    check contents"); | ||||
|         // We don't know how much protocol compression there will be exactly, but make sure this is some | ||||
|         TEST_RESULT_BOOL( | ||||
| @@ -375,31 +272,19 @@ testRun(void) | ||||
|         TEST_ERROR( | ||||
|             storageRemoteProtocolBlockSize(STRDEF("bogus")), ProtocolError, "'bogus' is not a valid block size message"); | ||||
|  | ||||
|         // Check protocol function directly (file missing) | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         VariantList *paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStr(STRDEF("missing.txt"))); | ||||
|         varLstAdd(paramList, varNewBool(true)); | ||||
|         varLstAdd(paramList, NULL); | ||||
|         varLstAdd(paramList, varNewVarLst(varLstNew())); | ||||
|         TEST_TITLE("file missing"); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteOpenReadProtocol(paramList, server), "protocol open read (missing)"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(serverWrite), "{\"out\":false}\n", "check result"); | ||||
|         TEST_RESULT_PTR(storageGetP(storageNewReadP(storageRepo, STRDEF("missing.txt"), .ignoreMissing = true)), NULL, "get"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         // Check protocol function directly (file exists) | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         storagePutP(storageNewWriteP(storageTest, STRDEF("repo/test.txt")), BUFSTRDEF("TESTDATA!")); | ||||
|         ioBufferSizeSet(4); | ||||
|         TEST_TITLE("read with filters"); | ||||
|  | ||||
|         paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStrZ(TEST_PATH "/repo/test.txt")); | ||||
|         varLstAdd(paramList, varNewBool(false)); | ||||
|         varLstAdd(paramList, varNewUInt64(8)); | ||||
|         HRN_STORAGE_PUT_Z(storageTest, TEST_PATH_REPO "/test.txt", "TESTDATA!"); | ||||
|  | ||||
|         // Create filters to test filter logic | ||||
|         IoFilterGroup *filterGroup = ioFilterGroupNew(); | ||||
|         TEST_ASSIGN(fileRead, storageNewReadP(storageRepo, STRDEF(TEST_PATH_REPO "/test.txt"), .limit = VARUINT64(8)), "new read"); | ||||
|  | ||||
|         IoFilterGroup *filterGroup = ioReadFilterGroup(storageReadIo(fileRead)); | ||||
|         ioFilterGroupAdd(filterGroup, ioSizeNew()); | ||||
|         ioFilterGroupAdd(filterGroup, cryptoHashNew(HASH_TYPE_SHA1_STR)); | ||||
|         ioFilterGroupAdd(filterGroup, pageChecksumNew(0, PG_SEGMENT_PAGE_DEFAULT, 0)); | ||||
| @@ -407,85 +292,57 @@ testRun(void) | ||||
|         ioFilterGroupAdd(filterGroup, cipherBlockNew(cipherModeDecrypt, cipherTypeAes256Cbc, BUFSTRZ("x"), NULL)); | ||||
|         ioFilterGroupAdd(filterGroup, compressFilter(compressTypeGz, 3)); | ||||
|         ioFilterGroupAdd(filterGroup, decompressFilter(compressTypeGz)); | ||||
|         varLstAdd(paramList, ioFilterGroupParamAll(filterGroup)); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteOpenReadProtocol(paramList, server), "protocol open read"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(storageGetP(fileRead)), "TESTDATA", "check contents"); | ||||
|  | ||||
|         TEST_RESULT_STR_Z( | ||||
|             strNewBuf(serverWrite), | ||||
|             "{\"out\":true}\n" | ||||
|                 "BRBLOCK4\n" | ||||
|                 "TESTBRBLOCK4\n" | ||||
|                 "DATABRBLOCK0\n" | ||||
|                 "{\"out\":{\"buffer\":null,\"cipherBlock\":null,\"gzCompress\":null,\"gzDecompress\":null" | ||||
|                     ",\"hash\":\"bbbcf2c59433f68f22376cd2439d6cd309378df6\",\"pageChecksum\":{\"align\":false,\"valid\":false}" | ||||
|                     ",\"size\":8}}\n", | ||||
|             "check result"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|         ioBufferSizeSet(8192); | ||||
|             jsonFromVar(ioFilterGroupResultAll(filterGroup)), | ||||
|             "{\"buffer\":null,\"cipherBlock\":null,\"gzCompress\":null,\"gzDecompress\":null" | ||||
|                 ",\"hash\":\"bbbcf2c59433f68f22376cd2439d6cd309378df6\",\"pageChecksum\":{\"align\":false,\"valid\":false}" | ||||
|                 ",\"size\":8}", | ||||
|             "filter results"); | ||||
|  | ||||
|         // Check protocol function directly (file exists but all data goes to sink) | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         storagePutP(storageNewWriteP(storageTest, STRDEF("repo/test.txt")), BUFSTRDEF("TESTDATA")); | ||||
|         TEST_TITLE("read into sink (no data returned)"); | ||||
|  | ||||
|         paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStrZ(TEST_PATH "/repo/test.txt")); | ||||
|         varLstAdd(paramList, varNewBool(false)); | ||||
|         varLstAdd(paramList, NULL); | ||||
|         HRN_STORAGE_PUT_Z(storageTest, TEST_PATH_REPO "/test.txt", "TESTDATA"); | ||||
|  | ||||
|         // Create filters to test filter logic | ||||
|         filterGroup = ioFilterGroupNew(); | ||||
|         TEST_ASSIGN(fileRead, storageNewReadP(storageRepo, STRDEF(TEST_PATH_REPO "/test.txt"), .limit = VARUINT64(8)), "new read"); | ||||
|  | ||||
|         filterGroup = ioReadFilterGroup(storageReadIo(fileRead)); | ||||
|         ioFilterGroupAdd(filterGroup, ioSizeNew()); | ||||
|         ioFilterGroupAdd(filterGroup, cryptoHashNew(HASH_TYPE_SHA1_STR)); | ||||
|         ioFilterGroupAdd(filterGroup, ioSinkNew()); | ||||
|         varLstAdd(paramList, ioFilterGroupParamAll(filterGroup)); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteOpenReadProtocol(paramList, server), "protocol open read (sink)"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(storageGetP(fileRead)), "", "no content"); | ||||
|  | ||||
|         TEST_RESULT_STR_Z( | ||||
|             strNewBuf(serverWrite), | ||||
|             "{\"out\":true}\n" | ||||
|                 "BRBLOCK0\n" | ||||
|                 "{\"out\":{\"buffer\":null,\"hash\":\"bbbcf2c59433f68f22376cd2439d6cd309378df6\",\"sink\":null,\"size\":8}}\n", | ||||
|             "check result"); | ||||
|             jsonFromVar(ioFilterGroupResultAll(filterGroup)), | ||||
|             "{\"buffer\":null,\"hash\":\"bbbcf2c59433f68f22376cd2439d6cd309378df6\",\"sink\":null,\"size\":8}", "filter results"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         // Check for error on a bogus filter | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStrZ(TEST_PATH "/repo/test.txt")); | ||||
|         varLstAdd(paramList, varNewBool(false)); | ||||
|         varLstAdd(paramList, NULL); | ||||
|         varLstAdd(paramList, varNewVarLst(varLstAdd(varLstNew(), varNewKv(kvPut(kvNew(), varNewStrZ("bogus"), NULL))))); | ||||
|         TEST_TITLE("error on invalid filter"); | ||||
|  | ||||
|         TEST_ERROR(storageRemoteOpenReadProtocol(paramList, server), AssertError, "unable to add filter 'bogus'"); | ||||
|         TEST_ERROR( | ||||
|             storageRemoteFilterGroup( | ||||
|                 ioFilterGroupNew(), varNewVarLst(varLstAdd(varLstNew(), varNewKv(kvPut(kvNew(), VARSTRDEF("bogus"), NULL))))), | ||||
|             AssertError, "unable to add filter 'bogus'"); | ||||
|     } | ||||
|  | ||||
|     // ***************************************************************************************************************************** | ||||
|     if (testBegin("storageNewWrite()")) | ||||
|     { | ||||
|         storagePathCreateP(storageTest, STRDEF("repo")); | ||||
|  | ||||
|         Storage *storageRemote = NULL; | ||||
|         TEST_ASSIGN(storageRemote, storageRepoGet(0, true), "get remote repo storage"); | ||||
|  | ||||
|         // Create buffer with plenty of data | ||||
|         Buffer *contentBuf = bufNew(32768); | ||||
|  | ||||
|         for (unsigned int contentIdx = 0; contentIdx < bufSize(contentBuf); contentIdx++) | ||||
|             bufPtr(contentBuf)[contentIdx] = contentIdx % 2 ? 'A' : 'B'; | ||||
|  | ||||
|         bufUsedSet(contentBuf, bufSize(contentBuf)); | ||||
|  | ||||
|         // Write the file | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("write with smaller buffer size than remote"); | ||||
|  | ||||
|         ioBufferSizeSet(9999); | ||||
|  | ||||
|         // Disable protocol compression in the storage object to test no compression | ||||
|         ((StorageRemote *)storageDriver(storageRemote))->compressLevel = 0; | ||||
|         ((StorageRemote *)storageDriver(storageRepoWrite))->compressLevel = 0; | ||||
|  | ||||
|         StorageWrite *write = NULL; | ||||
|         TEST_ASSIGN(write, storageNewWriteP(storageRemote, STRDEF("test.txt")), "new write file"); | ||||
|         TEST_ASSIGN(write, storageNewWriteP(storageRepoWrite, STRDEF("test.txt")), "new write file"); | ||||
|  | ||||
|         TEST_RESULT_BOOL(storageWriteAtomic(write), true, "write is atomic"); | ||||
|         TEST_RESULT_BOOL(storageWriteCreatePath(write), true, "path will be created"); | ||||
| @@ -501,15 +358,24 @@ testRun(void) | ||||
|         TEST_RESULT_VOID(storageWriteFree(write), "free file"); | ||||
|  | ||||
|         // Make sure the file was written correctly | ||||
|         TEST_RESULT_BOOL( | ||||
|             bufEq(storageGetP(storageNewReadP(storageRemote, STRDEF("test.txt"))), contentBuf), true, "check file"); | ||||
|         TEST_RESULT_BOOL(bufEq(storageGetP(storageNewReadP(storageRepo, STRDEF("test.txt"))), contentBuf), true, "check file"); | ||||
|  | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("write with larger buffer than remote"); | ||||
|  | ||||
|         ioBufferSizeSet(ioBufferSize() * 2); | ||||
|  | ||||
|         TEST_ASSIGN(write, storageNewWriteP(storageRepoWrite, STRDEF("test.txt")), "new write file"); | ||||
|         TEST_RESULT_VOID(storagePutP(write, contentBuf), "write file"); | ||||
|         TEST_RESULT_BOOL(bufEq(storageGetP(storageNewReadP(storageRepo, STRDEF("test.txt"))), contentBuf), true, "check file"); | ||||
|  | ||||
|         // Enable protocol compression in the storage object | ||||
|         ((StorageRemote *)storageDriver(storageRemote))->compressLevel = 3; | ||||
|         ((StorageRemote *)storageDriver(storageRepoWrite))->compressLevel = 3; | ||||
|  | ||||
|         // Write the file again, but this time free it before close and make sure the .tmp file is left | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_ASSIGN(write, storageNewWriteP(storageRemote, STRDEF("test2.txt")), "new write file"); | ||||
|         TEST_TITLE("write file, free before close, make sure the .tmp file remains"); | ||||
|  | ||||
|         TEST_ASSIGN(write, storageNewWriteP(storageRepoWrite, STRDEF("test2.txt")), "new write file"); | ||||
|  | ||||
|         TEST_RESULT_VOID(ioWriteOpen(storageWriteIo(write)), "open file"); | ||||
|         TEST_RESULT_VOID(ioWrite(storageWriteIo(write), contentBuf), "write bytes"); | ||||
| @@ -521,137 +387,58 @@ testRun(void) | ||||
|  | ||||
|         // Write the file again with protocol compression | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_ASSIGN(write, storageNewWriteP(storageRemote, STRDEF("test2.txt"), .compressible = true), "new write file (compress)"); | ||||
|         TEST_ASSIGN( | ||||
|             write, storageNewWriteP(storageRepoWrite, STRDEF("test2.txt"), .compressible = true), "new write file (compress)"); | ||||
|         TEST_RESULT_VOID(storagePutP(write, contentBuf), "write file"); | ||||
|         TEST_RESULT_BOOL( | ||||
|             ((StorageWriteRemote *)write->driver)->protocolWriteBytes < bufSize(contentBuf), true, | ||||
|             "    check compressed write size"); | ||||
|  | ||||
|         // Check protocol function directly (complete write) | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         ioBufferSizeSet(10); | ||||
|  | ||||
|         VariantList *paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStrZ(TEST_PATH "/repo/test3.txt")); | ||||
|         varLstAdd(paramList, varNewUInt64(0640)); | ||||
|         varLstAdd(paramList, varNewUInt64(0750)); | ||||
|         varLstAdd(paramList, NULL); | ||||
|         varLstAdd(paramList, NULL); | ||||
|         varLstAdd(paramList, varNewInt(0)); | ||||
|         varLstAdd(paramList, varNewBool(true)); | ||||
|         varLstAdd(paramList, varNewBool(true)); | ||||
|         varLstAdd(paramList, varNewBool(true)); | ||||
|         varLstAdd(paramList, varNewBool(true)); | ||||
|         varLstAdd(paramList, ioFilterGroupParamAll(ioFilterGroupAdd(ioFilterGroupNew(), ioSizeNew()))); | ||||
|  | ||||
|         // Generate input (includes the input for the test below -- need a way to reset this for better testing) | ||||
|         bufCat( | ||||
|             serverRead, | ||||
|             BUFSTRDEF( | ||||
|                 "BRBLOCK3\n" | ||||
|                 "ABCBRBLOCK15\n" | ||||
|                 "123456789012345BRBLOCK0\n" | ||||
|                 "BRBLOCK3\n" | ||||
|                 "ABCBRBLOCK-1\n")); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteOpenWriteProtocol(paramList, server), "protocol open write"); | ||||
|         TEST_RESULT_STR_Z( | ||||
|             strNewBuf(serverWrite), | ||||
|             "{}\n" | ||||
|             "{\"out\":{\"buffer\":null,\"size\":18}}\n", | ||||
|             "check result"); | ||||
|  | ||||
|         TEST_RESULT_STR_Z( | ||||
|             strNewBuf(storageGetP(storageNewReadP(storageTest, STRDEF("repo/test3.txt")))), "ABC123456789012345", | ||||
|             "check file"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         // Check protocol function directly (free before write is closed) | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         ioBufferSizeSet(10); | ||||
|  | ||||
|         paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStrZ(TEST_PATH "/repo/test4.txt")); | ||||
|         varLstAdd(paramList, varNewUInt64(0640)); | ||||
|         varLstAdd(paramList, varNewUInt64(0750)); | ||||
|         varLstAdd(paramList, NULL); | ||||
|         varLstAdd(paramList, NULL); | ||||
|         varLstAdd(paramList, varNewInt(0)); | ||||
|         varLstAdd(paramList, varNewBool(true)); | ||||
|         varLstAdd(paramList, varNewBool(true)); | ||||
|         varLstAdd(paramList, varNewBool(true)); | ||||
|         varLstAdd(paramList, varNewBool(true)); | ||||
|         varLstAdd(paramList, varNewVarLst(varLstNew())); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteOpenWriteProtocol(paramList, server), "protocol open write"); | ||||
|         TEST_RESULT_STR_Z( | ||||
|             strNewBuf(serverWrite), | ||||
|             "{}\n" | ||||
|             "{}\n", | ||||
|             "check result"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|         ioBufferSizeSet(8192); | ||||
|  | ||||
|         TEST_RESULT_STR_Z( | ||||
|             strNewBuf(storageGetP(storageNewReadP(storageTest, STRDEF("repo/test4.txt.pgbackrest.tmp")))), "", "check file"); | ||||
|     } | ||||
|  | ||||
|     // ***************************************************************************************************************************** | ||||
|     if (testBegin("storagePathCreate()")) | ||||
|     { | ||||
|         const String *path = STRDEF("testpath"); | ||||
|         storagePathCreateP(storageTest, STRDEF("repo")); | ||||
|  | ||||
|         Storage *storageRemote = NULL; | ||||
|         TEST_ASSIGN(storageRemote, storageRepoGet(0, true), "get remote repo storage"); | ||||
|  | ||||
|         // Create a path via the remote. Check the repo via the local test storage to ensure the remote created it. | ||||
|         TEST_RESULT_VOID(storagePathCreateP(storageRemote, path), "new path"); | ||||
|         TEST_RESULT_VOID(storagePathCreateP(storageRepoWrite, path), "new path"); | ||||
|         StorageInfo info = {0}; | ||||
|         TEST_ASSIGN(info, storageInfoP(storageTest, strNewFmt("repo/%s", strZ(path))), "  get path info"); | ||||
|         TEST_RESULT_BOOL(info.exists, true, "  path exists"); | ||||
|         TEST_RESULT_INT(info.mode, STORAGE_MODE_PATH_DEFAULT, "  mode is default"); | ||||
|  | ||||
|         // Check protocol function directly | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         VariantList *paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStr(strNewFmt(TEST_PATH "/repo/%s", strZ(path)))); | ||||
|         varLstAdd(paramList, varNewBool(true));     // errorOnExists | ||||
|         varLstAdd(paramList, varNewBool(true));     // noParentCreate (true=error if it does not have a parent, false=create parent) | ||||
|         varLstAdd(paramList, varNewUInt64(0));      // path mode | ||||
|         TEST_TITLE("error on existing path"); | ||||
|  | ||||
|         TEST_ERROR( | ||||
|             storageRemotePathCreateProtocol(paramList, server), PathCreateError, | ||||
|             "raised from remote-0 protocol on 'localhost': unable to create path '" TEST_PATH "/repo/testpath': [17] File exists"); | ||||
|             storagePathCreateP(storageRepoWrite, STRDEF("testpath"), .errorOnExists = true), PathCreateError, | ||||
|             "raised from remote-0 shim protocol: unable to create path '" TEST_PATH_REPO "/testpath': [17] File exists"); | ||||
|  | ||||
|         // Error if parent path not exist | ||||
|         path = STRDEF("parent/testpath"); | ||||
|         paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStr(strNewFmt(TEST_PATH "/repo/%s", strZ(path)))); | ||||
|         varLstAdd(paramList, varNewBool(false));    // errorOnExists | ||||
|         varLstAdd(paramList, varNewBool(true));     // noParentCreate (true=error if it does not have a parent, false=create parent) | ||||
|         varLstAdd(paramList, varNewUInt64(0));      // path mode | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("error on missing parent path"); | ||||
|  | ||||
|         TEST_ERROR( | ||||
|             storageRemotePathCreateProtocol(paramList, server), PathCreateError, | ||||
|             "raised from remote-0 protocol on 'localhost': unable to create path '" TEST_PATH "/repo/parent/testpath': [2] No such" | ||||
|             storagePathCreateP(storageRepoWrite, STRDEF("parent/testpath"), .noParentCreate = true), PathCreateError, | ||||
|             "raised from remote-0 shim protocol: unable to create path '" TEST_PATH_REPO "/parent/testpath': [2] No such" | ||||
|                 " file or directory"); | ||||
|  | ||||
|         // Create parent and path with default mode | ||||
|         paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStr(strNewFmt(TEST_PATH "/repo/%s", strZ(path)))); | ||||
|         varLstAdd(paramList, varNewBool(true));     // errorOnExists | ||||
|         varLstAdd(paramList, varNewBool(false));    // noParentCreate (true=error if it does not have a parent, false=create parent) | ||||
|         varLstAdd(paramList, varNewUInt64(0777));   // path mode | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("create parent/path with non-default mode"); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemotePathCreateProtocol(paramList, server), "create parent and path"); | ||||
|         TEST_ASSIGN(info, storageInfoP(storageTest, strNewFmt("repo/%s", strZ(path))), "  get path info"); | ||||
|         TEST_RESULT_BOOL(info.exists, true, "  path exists"); | ||||
|         TEST_RESULT_INT(info.mode, 0777, "  mode is set"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(serverWrite), "{}\n", "  check result"); | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|         TEST_RESULT_VOID(storagePathCreateP(storageRepoWrite, STRDEF("parent/testpath"), .mode = 0777), "path create"); | ||||
|  | ||||
|         HarnessStorageInfoListCallbackData callbackData = {.content = strNew(), .userOmit = true, .groupOmit = true}; | ||||
|  | ||||
|         TEST_RESULT_BOOL( | ||||
|             storageInfoListP( | ||||
|                 storageRepo, STRDEF(TEST_PATH_REPO "/parent"), hrnStorageInfoListCallback, &callbackData, | ||||
|                 .sortOrder = sortOrderAsc), | ||||
|             true, "info list"); | ||||
|         TEST_RESULT_STR_Z( | ||||
|             callbackData.content, | ||||
|             ". {path, m=0777}\n" | ||||
|             "testpath {path, m=0777}\n", | ||||
|             "check content"); | ||||
|     } | ||||
|  | ||||
|     // ***************************************************************************************************************************** | ||||
| @@ -659,36 +446,22 @@ testRun(void) | ||||
|     { | ||||
|         const String *path = STRDEF("testpath"); | ||||
|         storagePathCreateP(storageTest, STRDEF("repo")); | ||||
|  | ||||
|         Storage *storageRemote = NULL; | ||||
|         TEST_ASSIGN(storageRemote, storageRepoGet(0, true), "get remote repo storage"); | ||||
|         TEST_RESULT_VOID(storagePathCreateP(storageRemote, path), "new path"); | ||||
|         TEST_RESULT_VOID(storagePathCreateP(storageRepoWrite, path), "new path"); | ||||
|  | ||||
|         // Check the repo via the local test storage to ensure the remote wrote it, then remove via the remote and confirm removed | ||||
|         TEST_RESULT_BOOL(storagePathExistsP(storageTest, strNewFmt("repo/%s", strZ(path))), true, "path exists"); | ||||
|         TEST_RESULT_VOID(storagePathRemoveP(storageRemote, path), "remote remove path"); | ||||
|         TEST_RESULT_VOID(storagePathRemoveP(storageRepoWrite, path), "remote remove path"); | ||||
|         TEST_RESULT_BOOL(storagePathExistsP(storageTest, strNewFmt("repo/%s", strZ(path))), false, "path removed"); | ||||
|  | ||||
|         // Check protocol function directly | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         VariantList *paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStr(strNewFmt(TEST_PATH "/repo/%s", strZ(path)))); | ||||
|         varLstAdd(paramList, varNewBool(true));    // recurse | ||||
|         TEST_TITLE("remove recursive"); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemotePathRemoveProtocol(paramList, server), "  protocol path remove missing"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(serverWrite), "{\"out\":false}\n", "  check result"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         // Write the path and file to the repo and test the protocol | ||||
|         TEST_RESULT_VOID( | ||||
|             storagePutP(storageNewWriteP(storageRemote, strNewFmt("%s/file.txt", strZ(path))), BUFSTRDEF("TEST")), | ||||
|             storagePutP(storageNewWriteP(storageRepoWrite, strNewFmt("%s/file.txt", strZ(path))), BUFSTRDEF("TEST")), | ||||
|             "new path and file"); | ||||
|         TEST_RESULT_VOID(storageRemotePathRemoveProtocol(paramList, server), "  protocol path recurse remove"); | ||||
|         TEST_RESULT_BOOL(storagePathExistsP(storageTest, strNewFmt("repo/%s", strZ(path))), false, "  recurse path removed"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(serverWrite), "{\"out\":true}\n", "  check result"); | ||||
|  | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|         TEST_RESULT_VOID(storagePathRemoveP(storageRepoWrite, STRDEF("testpath"), .recurse = true), "remove missing path"); | ||||
|         TEST_RESULT_BOOL(storagePathExistsP(storageTest, strNewFmt("repo/%s", strZ(path))), false, "  recurse path removed"); | ||||
|     } | ||||
|  | ||||
|     // ***************************************************************************************************************************** | ||||
| @@ -696,43 +469,27 @@ testRun(void) | ||||
|     { | ||||
|         storagePathCreateP(storageTest, STRDEF("repo")); | ||||
|  | ||||
|         Storage *storageRemote = NULL; | ||||
|         TEST_ASSIGN(storageRemote, storageRepoGet(0, true), "get remote repo storage"); | ||||
|         const String *file = STRDEF("file.txt"); | ||||
|  | ||||
|         // Write the file to the repo via the remote so owner is pgbackrest | ||||
|         TEST_RESULT_VOID(storagePutP(storageNewWriteP(storageRemote, file), BUFSTRDEF("TEST")), "new file"); | ||||
|         TEST_RESULT_VOID(storagePutP(storageNewWriteP(storageRepoWrite, file), BUFSTRDEF("TEST")), "new file"); | ||||
|  | ||||
|         // Check the repo via the local test storage to ensure the remote wrote it, then remove via the remote and confirm removed | ||||
|         TEST_RESULT_BOOL(storageExistsP(storageTest, strNewFmt("repo/%s", strZ(file))), true, "file exists"); | ||||
|         TEST_RESULT_VOID(storageRemoveP(storageRemote, file), "remote remove file"); | ||||
|         TEST_RESULT_VOID(storageRemoveP(storageRepoWrite, file), "remote remove file"); | ||||
|         TEST_RESULT_BOOL(storageExistsP(storageTest, strNewFmt("repo/%s", strZ(file))), false, "file removed"); | ||||
|  | ||||
|         // Check protocol function directly | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         VariantList *paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStr(strNewFmt(TEST_PATH "/repo/%s", strZ(file)))); | ||||
|         varLstAdd(paramList, varNewBool(true)); | ||||
|         TEST_TITLE("error on missing file"); | ||||
|  | ||||
|         TEST_ERROR( | ||||
|             storageRemoteRemoveProtocol(paramList, server), FileRemoveError, | ||||
|             "raised from remote-0 protocol on 'localhost': unable to remove '" TEST_PATH "/repo/file.txt': [2] No such file or" | ||||
|                 " directory"); | ||||
|             storageRemoveP(storageRepoWrite, file, .errorOnMissing = true), FileRemoveError, | ||||
|             "raised from remote-0 shim protocol: unable to remove '" TEST_PATH "/repo/file.txt': [2] No such file or directory"); | ||||
|  | ||||
|         paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStr(strNewFmt(TEST_PATH "/repo/%s", strZ(file)))); | ||||
|         varLstAdd(paramList, varNewBool(false)); | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         TEST_TITLE("ignore missing file"); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemoteRemoveProtocol(paramList, server), "protocol file remove - no error on missing"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(serverWrite), "{}\n", "  check result"); | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         // Write the file to the repo via the remote and test the protocol | ||||
|         TEST_RESULT_VOID(storagePutP(storageNewWriteP(storageRemote, file), BUFSTRDEF("TEST")), "new file"); | ||||
|         TEST_RESULT_VOID(storageRemoteRemoveProtocol(paramList, server), "protocol file remove"); | ||||
|         TEST_RESULT_BOOL(storageExistsP(storageTest, strNewFmt("repo/%s", strZ(file))), false, "  confirm file removed"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(serverWrite), "{}\n", "  check result"); | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|         TEST_RESULT_VOID(storageRemoveP(storageRepoWrite, file), "remove missing"); | ||||
|     } | ||||
|  | ||||
|     // ***************************************************************************************************************************** | ||||
| @@ -740,27 +497,9 @@ testRun(void) | ||||
|     { | ||||
|         storagePathCreateP(storageTest, STRDEF("repo")); | ||||
|  | ||||
|         Storage *storageRemote = NULL; | ||||
|         TEST_ASSIGN(storageRemote, storageRepoGet(0, true), "get remote repo storage"); | ||||
|  | ||||
|         const String *path = STRDEF("testpath"); | ||||
|         TEST_RESULT_VOID(storagePathCreateP(storageRemote, path), "new path"); | ||||
|         TEST_RESULT_VOID(storagePathSyncP(storageRemote, path), "sync path"); | ||||
|  | ||||
|         // Check protocol function directly | ||||
|         // ------------------------------------------------------------------------------------------------------------------------- | ||||
|         VariantList *paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStr(strNewFmt(TEST_PATH "/repo/%s", strZ(path)))); | ||||
|  | ||||
|         TEST_RESULT_VOID(storageRemotePathSyncProtocol(paramList, server), "protocol path sync"); | ||||
|         TEST_RESULT_STR_Z(strNewBuf(serverWrite), "{}\n", "  check result"); | ||||
|         bufUsedSet(serverWrite, 0); | ||||
|  | ||||
|         paramList = varLstNew(); | ||||
|         varLstAdd(paramList, varNewStrZ(TEST_PATH "/repo/anewpath")); | ||||
|         TEST_ERROR_FMT( | ||||
|             storageRemotePathSyncProtocol(paramList, server), PathMissingError, | ||||
|             "raised from remote-0 protocol on 'localhost': " STORAGE_ERROR_PATH_SYNC_MISSING, TEST_PATH "/repo/anewpath"); | ||||
|         TEST_RESULT_VOID(storagePathCreateP(storageRepoWrite, path), "new path"); | ||||
|         TEST_RESULT_VOID(storagePathSyncP(storageRepoWrite, path), "sync path"); | ||||
|     } | ||||
|  | ||||
|     protocolFree(); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user