mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-01-30 05:39:12 +02:00
Improve storage harness/test macros.
Make the macros more consistent in format and make sure that each macro outputs a line number before doing any work so when errors happen it is clear where they happened. Add noRecurse option to TEST_STORAGE_LIST(). Add comment option to all storage macros.
This commit is contained in:
parent
0a43be0183
commit
c8427682ea
@ -10,9 +10,13 @@ Harness for Generating Test Info Files
|
||||
Write info to a file and add the checksum
|
||||
***********************************************************************************************************************************/
|
||||
#define HRN_INFO_PUT(storage, file, info, ...) \
|
||||
TEST_RESULT_VOID( \
|
||||
hrnStoragePut(storage, file, harnessInfoChecksumZ(info), (HrnStoragePutParam){VAR_PARAM_INIT, __VA_ARGS__}), \
|
||||
strZ(strNewFmt("put info %s", hrnStoragePutLog(storage, file, LF_BUF, (HrnStoragePutParam){VAR_PARAM_INIT, __VA_ARGS__}))))
|
||||
do \
|
||||
{ \
|
||||
hrnTestLogPrefix(__LINE__); \
|
||||
hrnStoragePut( \
|
||||
storage, file, harnessInfoChecksumZ(info), "put info", (HrnStoragePutParam){VAR_PARAM_INIT, __VA_ARGS__}); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Functions
|
||||
|
@ -175,15 +175,17 @@ hrnStorageInfoListCallback(void *callbackData, const StorageInfo *info)
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
testStorageGet(
|
||||
const int line, const Storage *const storage, const char *const file, const char *const expected, TestStorageGetParam param)
|
||||
testStorageGet(const Storage *const storage, const char *const file, const char *const expected, const TestStorageGetParam param)
|
||||
{
|
||||
hrnTestLogPrefix(line);
|
||||
hrnTestResultBegin(__func__, false);
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(file != NULL);
|
||||
|
||||
const String *const fileFull = storagePathP(storage, STR(file));
|
||||
printf("test content of '%s'\n", strZ(fileFull));
|
||||
fflush(stdout);
|
||||
|
||||
printf("test content of '%s'", strZ(fileFull));
|
||||
hrnTestResultComment(param.comment);
|
||||
|
||||
hrnTestResultZ(strZ(strNewBuf(storageGetP(storageNewReadP(storage, fileFull)))), expected, harnessTestResultOperationEq);
|
||||
|
||||
@ -191,6 +193,23 @@ testStorageGet(
|
||||
storageRemoveP(storage, fileFull, .errorOnMissing = true);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
testStorageExists(const Storage *const storage, const char *const file, const TestStorageExistsParam param)
|
||||
{
|
||||
hrnTestResultBegin(__func__, false);
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(file != NULL);
|
||||
|
||||
const String *const fileFull = storagePathP(storage, STR(file));
|
||||
|
||||
printf("file exists '%s'", strZ(fileFull));
|
||||
hrnTestResultComment(param.comment);
|
||||
|
||||
hrnTestResultBool(storageExistsP(storage, fileFull), true);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
static void
|
||||
hrnStorageListCallback(void *list, const StorageInfo *info)
|
||||
@ -213,21 +232,21 @@ hrnStorageListCallback(void *list, const StorageInfo *info)
|
||||
|
||||
void
|
||||
hrnStorageList(
|
||||
const int line, const Storage *const storage, const char *const path, const char *const expected,
|
||||
const HrnStorageListParam param)
|
||||
const Storage *const storage, const char *const path, const char *const expected, const HrnStorageListParam param)
|
||||
{
|
||||
// Log list test
|
||||
hrnTestLogPrefix(line);
|
||||
hrnTestResultBegin(__func__, false);
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
|
||||
const String *const pathFull = storagePathP(storage, STR(path));
|
||||
printf("list%s contents of '%s'\n", param.remove ? "/remove": "", strZ(pathFull));
|
||||
fflush(stdout);
|
||||
printf("list%s contents of '%s'", param.remove ? "/remove": "", strZ(pathFull));
|
||||
hrnTestResultComment(param.comment);
|
||||
|
||||
// Generate a list of files/paths/etc
|
||||
List *list = lstNewP(sizeof(StorageInfo));
|
||||
|
||||
storageInfoListP(storage, pathFull, hrnStorageListCallback, list, .sortOrder = sortOrderAsc, .recurse = true);
|
||||
storageInfoListP(storage, pathFull, hrnStorageListCallback, list, .sortOrder = sortOrderAsc, .recurse = !param.noRecurse);
|
||||
|
||||
// Remove files if requested
|
||||
if (param.remove)
|
||||
@ -284,11 +303,12 @@ hrnStorageList(
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
hrnStorageMode(const int line, const Storage *const storage, const char *const path, HrnStorageModeParam param)
|
||||
hrnStorageMode(const Storage *const storage, const char *const path, HrnStorageModeParam param)
|
||||
{
|
||||
hrnTestLogPrefix(line);
|
||||
hrnTestResultBegin(__func__, false);
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
|
||||
const char *const pathFull = strZ(storagePathP(storage, STR(path)));
|
||||
|
||||
// If no mode specified then default the mode based on the file type
|
||||
@ -304,8 +324,8 @@ hrnStorageMode(const int line, const Storage *const storage, const char *const p
|
||||
param.mode = STORAGE_MODE_FILE_DEFAULT;
|
||||
}
|
||||
|
||||
printf("chmod '%04o' on '%s'\n", param.mode, pathFull);
|
||||
fflush(stdout);
|
||||
printf("chmod '%04o' on '%s'", param.mode, pathFull);
|
||||
hrnTestResultComment(param.comment);
|
||||
|
||||
THROW_ON_SYS_ERROR_FMT(chmod(pathFull, param.mode) == -1, FileModeError, "unable to set mode on '%s'", pathFull);
|
||||
|
||||
@ -314,8 +334,15 @@ hrnStorageMode(const int line, const Storage *const storage, const char *const p
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
hrnStoragePut(const Storage *storage, const char *file, const Buffer *buffer, HrnStoragePutParam param)
|
||||
hrnStoragePut(
|
||||
const Storage *const storage, const char *const file, const Buffer *const buffer, const char *const logPrefix,
|
||||
HrnStoragePutParam param)
|
||||
{
|
||||
hrnTestResultBegin(__func__, false);
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(file != NULL);
|
||||
|
||||
// Add compression extension to file name
|
||||
String *fileStr = strNewZ(file);
|
||||
compressExtCat(fileStr, param.compressType);
|
||||
@ -325,10 +352,14 @@ hrnStoragePut(const Storage *storage, const char *file, const Buffer *buffer, Hr
|
||||
IoFilterGroup *filterGroup = ioWriteFilterGroup(storageWriteIo(destination));
|
||||
|
||||
// Add compression filter
|
||||
String *const filter = strNew();
|
||||
|
||||
if (param.compressType != compressTypeNone)
|
||||
{
|
||||
ASSERT(param.compressType == compressTypeGz || param.compressType == compressTypeBz2);
|
||||
ioFilterGroupAdd(filterGroup, compressFilter(param.compressType, 1));
|
||||
|
||||
strCatFmt(filter, "cmp[%s]", strZ(compressTypeStr(param.compressType)));
|
||||
}
|
||||
|
||||
// Add encrypted filter
|
||||
@ -339,55 +370,51 @@ hrnStoragePut(const Storage *storage, const char *file, const Buffer *buffer, Hr
|
||||
param.cipherPass = TEST_CIPHER_PASS;
|
||||
|
||||
ioFilterGroupAdd(filterGroup, cipherBlockNew(cipherModeEncrypt, param.cipherType, BUFSTRZ(param.cipherPass), NULL));
|
||||
|
||||
strCatFmt(filter, "%senc[%s,%s]", strEmpty(filter) ? "" : "/", strZ(strIdToStr(param.cipherType)), param.cipherPass);
|
||||
}
|
||||
|
||||
// Add file name
|
||||
printf(
|
||||
"%s %s%s%s'%s%s'", logPrefix != NULL ? logPrefix : "put file", buffer == NULL || bufEmpty(buffer) ? "(empty) " : "",
|
||||
strZ(filter), strEmpty(filter) ? "" : " ", strZ(storagePathP(storage, fileStr)), strZ(compressExtStr(param.compressType)));
|
||||
hrnTestResultComment(param.comment);
|
||||
|
||||
// Put file
|
||||
storagePutP(destination, buffer);
|
||||
}
|
||||
|
||||
const char *
|
||||
hrnStoragePutLog(const Storage *storage, const char *file, const Buffer *buffer, HrnStoragePutParam param)
|
||||
{
|
||||
// Empty if buffer is NULL
|
||||
String *log = strNewZ(buffer == NULL || bufEmpty(buffer) ? "(empty) " : "");
|
||||
|
||||
// Add compression detail
|
||||
if (param.compressType != compressTypeNone)
|
||||
strCatFmt(log, "cmp[%s]", strZ(compressTypeStr(param.compressType)));
|
||||
|
||||
// Add encryption detail
|
||||
if (param.cipherType != 0 && param.cipherType != cipherTypeNone)
|
||||
{
|
||||
if (param.cipherPass == NULL)
|
||||
param.cipherPass = TEST_CIPHER_PASS;
|
||||
|
||||
if (param.compressType != compressTypeNone)
|
||||
strCatZ(log, "/");
|
||||
|
||||
strCatFmt(log, "enc[%s,%s]", strZ(strIdToStr(param.cipherType)), param.cipherPass);
|
||||
}
|
||||
|
||||
// Add a space if compression/encryption defined
|
||||
if (param.compressType != compressTypeNone || (param.cipherType != 0 && param.cipherType != cipherTypeNone))
|
||||
strCatZ(log, " ");
|
||||
|
||||
// Add file name
|
||||
strCatFmt(log, "'%s%s'", strZ(storagePathP(storage, STR(file))), strZ(compressExtStr(param.compressType)));
|
||||
|
||||
return strZ(log);
|
||||
hrnTestResultEnd();
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
hrnStorageTime(const int line, const Storage *const storage, const char *const path, const time_t modified)
|
||||
hrnStorageRemove(const Storage *const storage, const char *const file, const TestStorageRemoveParam param)
|
||||
{
|
||||
hrnTestLogPrefix(line);
|
||||
hrnTestResultBegin(__func__, false);
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
ASSERT(file != NULL);
|
||||
|
||||
printf("remove file '%s'", strZ(storagePathP(storage, STR(file))));
|
||||
hrnTestResultComment(param.comment);
|
||||
|
||||
storageRemoveP(storage, STR(file), .errorOnMissing = true);
|
||||
|
||||
hrnTestResultEnd();
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
hrnStorageTime(const Storage *const storage, const char *const path, const time_t modified, const HrnStorageTimeParam param)
|
||||
{
|
||||
hrnTestResultBegin(__func__, false);
|
||||
|
||||
ASSERT(storage != NULL);
|
||||
|
||||
const char *const pathFull = strZ(storagePathP(storage, path == NULL ? NULL : STR(path)));
|
||||
|
||||
printf("time '%" PRId64 "' on '%s'\n", (int64_t)modified, pathFull);
|
||||
fflush(stdout);
|
||||
printf("time '%" PRId64 "' on '%s'", (int64_t)modified, pathFull);
|
||||
hrnTestResultComment(param.comment);
|
||||
|
||||
THROW_ON_SYS_ERROR_FMT(
|
||||
utime(pathFull, &((struct utimbuf){.actime = modified, .modtime = modified})) == -1, FileInfoError,
|
||||
|
@ -10,13 +10,6 @@ Helper functions for testing storage and related functions.
|
||||
#include "common/crypto/common.h"
|
||||
#include "storage/storage.intern.h"
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Check file exists
|
||||
***********************************************************************************************************************************/
|
||||
#define TEST_STORAGE_EXISTS(storage, file) \
|
||||
TEST_RESULT_BOOL( \
|
||||
storageExistsP(storage, STR(file)), true, strZ(strNewFmt("file exists '%s'", strZ(storagePathP(storage, STR(file))))))
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get a file and test it against the specified content
|
||||
***********************************************************************************************************************************/
|
||||
@ -24,15 +17,41 @@ typedef struct TestStorageGetParam
|
||||
{
|
||||
VAR_PARAM_HEADER;
|
||||
bool remove; // Remove file after testing?
|
||||
const char *comment; // Comment
|
||||
} TestStorageGetParam;
|
||||
|
||||
#define TEST_STORAGE_GET(storage, file, content, ...) \
|
||||
testStorageGet(__LINE__, storage, file, content, (TestStorageGetParam){VAR_PARAM_INIT, __VA_ARGS__})
|
||||
do \
|
||||
{ \
|
||||
hrnTestLogPrefix(__LINE__); \
|
||||
testStorageGet(storage, file, content, (TestStorageGetParam){VAR_PARAM_INIT, __VA_ARGS__}); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define TEST_STORAGE_GET_EMPTY(storage, file, ...) \
|
||||
TEST_STORAGE_GET(storage, file, "", __VA_ARGS__)
|
||||
|
||||
void testStorageGet(
|
||||
const int line, const Storage *const storage, const char *const file, const char *const expected, TestStorageGetParam param);
|
||||
const Storage *const storage, const char *const file, const char *const expected, const TestStorageGetParam param);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Check file exists
|
||||
***********************************************************************************************************************************/
|
||||
typedef struct TestStorageExistsParam
|
||||
{
|
||||
VAR_PARAM_HEADER;
|
||||
const char *comment; // Comment
|
||||
} TestStorageExistsParam;
|
||||
|
||||
#define TEST_STORAGE_EXISTS(storage, file, ...) \
|
||||
do \
|
||||
{ \
|
||||
hrnTestLogPrefix(__LINE__); \
|
||||
testStorageExists(storage, file, (TestStorageExistsParam){VAR_PARAM_INIT, __VA_ARGS__}); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
void testStorageExists(const Storage *const storage, const char *const file, const TestStorageExistsParam param);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
List files in a path and optionally remove them
|
||||
@ -40,18 +59,24 @@ List files in a path and optionally remove them
|
||||
typedef struct HrnStorageListParam
|
||||
{
|
||||
VAR_PARAM_HEADER;
|
||||
bool remove;
|
||||
bool remove; // Remove files after testing?
|
||||
bool noRecurse; // Do not recurse into subdirectories
|
||||
const char *comment; // Comment
|
||||
} HrnStorageListParam;
|
||||
|
||||
#define TEST_STORAGE_LIST(storage, path, expected, ...) \
|
||||
hrnStorageList(__LINE__, storage, path, expected, (HrnStorageListParam){VAR_PARAM_INIT, __VA_ARGS__})
|
||||
do \
|
||||
{ \
|
||||
hrnTestLogPrefix(__LINE__); \
|
||||
hrnStorageList(storage, path, expected, (HrnStorageListParam){VAR_PARAM_INIT, __VA_ARGS__}); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define TEST_STORAGE_LIST_EMPTY(storage, path, ...) \
|
||||
TEST_STORAGE_LIST(storage, path, NULL, __VA_ARGS__)
|
||||
|
||||
void hrnStorageList(
|
||||
const int line, const Storage *const storage, const char *const path, const char *const expected,
|
||||
const HrnStorageListParam param);
|
||||
const Storage *const storage, const char *const path, const char *const expected, const HrnStorageListParam param);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Change the mode of a path/file
|
||||
@ -60,12 +85,18 @@ typedef struct HrnStorageModeParam
|
||||
{
|
||||
VAR_PARAM_HEADER;
|
||||
mode_t mode; // Mode to set -- reset to default if not provided
|
||||
const char *comment; // Comment
|
||||
} HrnStorageModeParam;
|
||||
|
||||
#define HRN_STORAGE_MODE(storage, path, ...) \
|
||||
hrnStorageMode(__LINE__, storage, path, (HrnStorageModeParam){VAR_PARAM_INIT, __VA_ARGS__})
|
||||
do \
|
||||
{ \
|
||||
hrnTestLogPrefix(__LINE__); \
|
||||
hrnStorageMode(storage, path, (HrnStorageModeParam){VAR_PARAM_INIT, __VA_ARGS__}); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
void hrnStorageMode(const int line, const Storage *const storage, const char *const path, HrnStorageModeParam param);
|
||||
void hrnStorageMode(const Storage *const storage, const char *const path, HrnStorageModeParam param);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Put a file with optional compression and/or encryption
|
||||
@ -76,12 +107,16 @@ typedef struct HrnStoragePutParam
|
||||
CompressType compressType;
|
||||
CipherType cipherType;
|
||||
const char *cipherPass;
|
||||
const char *comment; // Comment
|
||||
} HrnStoragePutParam;
|
||||
|
||||
#define HRN_STORAGE_PUT(storage, file, buffer, ...) \
|
||||
TEST_RESULT_VOID( \
|
||||
hrnStoragePut(storage, file, buffer, (HrnStoragePutParam){VAR_PARAM_INIT, __VA_ARGS__}), \
|
||||
strZ(strNewFmt("put file %s", hrnStoragePutLog(storage, file, buffer, (HrnStoragePutParam){VAR_PARAM_INIT, __VA_ARGS__}))))
|
||||
do \
|
||||
{ \
|
||||
hrnTestLogPrefix(__LINE__); \
|
||||
hrnStoragePut(storage, file, buffer, NULL, (HrnStoragePutParam){VAR_PARAM_INIT, __VA_ARGS__}); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
#define HRN_STORAGE_PUT_EMPTY(storage, file, ...) \
|
||||
HRN_STORAGE_PUT(storage, file, NULL, __VA_ARGS__)
|
||||
@ -89,24 +124,47 @@ typedef struct HrnStoragePutParam
|
||||
#define HRN_STORAGE_PUT_Z(storage, file, stringz, ...) \
|
||||
HRN_STORAGE_PUT(storage, file, BUFSTRZ(stringz), __VA_ARGS__)
|
||||
|
||||
void hrnStoragePut(const Storage *storage, const char *file, const Buffer *buffer, HrnStoragePutParam param);
|
||||
const char *hrnStoragePutLog(const Storage *storage, const char *file, const Buffer *buffer, HrnStoragePutParam param);
|
||||
void hrnStoragePut(
|
||||
const Storage *const storage, const char *const file, const Buffer *const buffer, const char *const logPrefix,
|
||||
HrnStoragePutParam param);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Remove a file and error if it does not exist
|
||||
***********************************************************************************************************************************/
|
||||
#define TEST_STORAGE_REMOVE(storage, path) \
|
||||
TEST_RESULT_VOID( \
|
||||
storageRemoveP(storage, STR(path), .errorOnMissing = true), \
|
||||
strZ(strNewFmt("remove file '%s'", strZ(storagePathP(storage, STR(path))))))
|
||||
typedef struct TestStorageRemoveParam
|
||||
{
|
||||
VAR_PARAM_HEADER;
|
||||
const char *comment; // Comment
|
||||
} TestStorageRemoveParam;
|
||||
|
||||
#define TEST_STORAGE_REMOVE(storage, file, ...) \
|
||||
do \
|
||||
{ \
|
||||
hrnTestLogPrefix(__LINE__); \
|
||||
hrnStorageRemove(storage, file, (TestStorageRemoveParam){VAR_PARAM_INIT, __VA_ARGS__}); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
void hrnStorageRemove(const Storage *const storage, const char *const file, const TestStorageRemoveParam param);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Change the time of a path/file
|
||||
***********************************************************************************************************************************/
|
||||
#define HRN_STORAGE_TIME(storage, path, time) \
|
||||
hrnStorageTime(__LINE__, storage, path, time)
|
||||
typedef struct HrnStorageTimeParam
|
||||
{
|
||||
VAR_PARAM_HEADER;
|
||||
const char *comment; // Comment
|
||||
} HrnStorageTimeParam;
|
||||
|
||||
void hrnStorageTime(const int line, const Storage *const storage, const char *const path, const time_t modified);
|
||||
#define HRN_STORAGE_TIME(storage, path, time, ...) \
|
||||
do \
|
||||
{ \
|
||||
hrnTestLogPrefix(__LINE__); \
|
||||
hrnStorageTime(storage, path, time, (HrnStorageTimeParam){VAR_PARAM_INIT, __VA_ARGS__}); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
void hrnStorageTime(const Storage *const storage, const char *const path, const time_t modified, const HrnStorageTimeParam param);
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Dummy interface for constructing test storage drivers. All required functions are stubbed out so this interface can be copied and
|
||||
|
@ -388,6 +388,19 @@ hrnTestResultBegin(const char *const statement, const bool result)
|
||||
harnessTestLocal.logLastLineNo = 0;
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
void
|
||||
hrnTestResultComment(const char *const comment)
|
||||
{
|
||||
if (comment != NULL)
|
||||
printf(" (%s)\n", comment);
|
||||
else
|
||||
puts("");
|
||||
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
/**********************************************************************************************************************************/
|
||||
bool
|
||||
hrnTestResultException(void)
|
||||
{
|
||||
|
@ -53,6 +53,7 @@ void hrnTestLogPrefix(const int lineNo);
|
||||
|
||||
// Begin/end result test so an exception during the test will give a useful message about what happened and where
|
||||
void hrnTestResultBegin(const char *const statement, const bool result);
|
||||
void hrnTestResultComment(const char *const comment);
|
||||
bool hrnTestResultException(void);
|
||||
void hrnTestResultEnd(void);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user