1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2024-12-12 10:04:14 +02:00

Add unit tests for the unit test build code.

When this code was migrated to C the unit tests were not included because there were more important priorities at the time.

This also requires some adjustments to coverage because of the new code location.
This commit is contained in:
David Steele 2023-01-05 12:59:06 +07:00
parent a5499afabc
commit 4429bc82f5
9 changed files with 994 additions and 62 deletions

View File

@ -631,6 +631,19 @@ unit:
- build/postgres/parse
- build/postgres/render
# ********************************************************************************************************************************
- name: test
test:
# ----------------------------------------------------------------------------------------------------------------------------
- name: test
total: 3
coverage:
- test/command/test/build
- test/command/test/define
- test/command/test/test
# ********************************************************************************************************************************
- name: info

View File

@ -39,7 +39,7 @@ sub coverageLCovConfigGenerate
my $bCoverageSummary = shift;
my $strBranchFilter =
'OBJECT_DEFINE_[A-Z0-9_]+\(|\s{4}[A-Z][A-Z0-9_]+\([^\?]*\)|\s{4}(ASSERT|CHECK|assert|switch\s)\(|\{\+{0,1}' .
'OBJECT_DEFINE_[A-Z0-9_]+\(|\s{4}[A-Z][A-Z0-9_]+\([^\?]*\)|\s{4}(ASSERT|CHECK|CHECK_FMT|assert|switch\s)\(|\{\+{0,1}' .
($bCoverageSummary ? 'uncoverable_branch' : 'uncover(ed|able)_branch');
my $strLineFilter =
'\{\+{0,1}' . ($bCoverageSummary ? 'uncoverable' : '(uncover(ed|able)' . ($bContainer ? '' : '|vm_covered') . ')') . '[^_]';
@ -124,6 +124,12 @@ sub coverageExtract
foreach my $strCoveredModule (@stryCoveredModule)
{
my $strModuleName = testRunName($strCoveredModule, false);
if ($strModuleName =~ /^test/mg)
{
$strModuleName =~ s/^test/src/mg;
}
my $strModuleOutName = $strModuleName;
my $bTest = false;
@ -134,10 +140,21 @@ sub coverageExtract
}
# Generate lcov reports
my $strModulePath =
"${strWorkPath}/repo/" .
(${strModuleOutName} =~ /^test\// ?
'test/src/module/' . substr(${strModuleOutName}, 5) : "src/${strModuleOutName}");
my $strModulePath = "${strWorkPath}/repo/";
if (${strModuleOutName} =~ /^src\//)
{
$strModulePath .= 'test/src/' . substr(${strModuleOutName}, 4);
}
elsif (${strModuleOutName} =~ /^test\//)
{
$strModulePath .= 'test/src/module/' . substr(${strModuleOutName}, 5);
}
else
{
$strModulePath .= "src/${strModuleOutName}";
}
my $strLCovFile = "${strTestResultCoveragePath}/raw/${strModuleOutName}.lcov";
my $strLCovTotal = "${strWorkTmpPath}/all.lcov";
my $bInc = $strModuleName =~ '\.vendor$' || $strModuleName =~ '\.auto$';
@ -297,6 +314,7 @@ sub coverageValidateAndGenerate
foreach my $strCodeModule (sort(keys(%{$hCoverageActual})))
{
my $strCoverageFile = $strCodeModule;
$strCoverageFile =~ s/^test/src/mg;
$strCoverageFile =~ s/^module/test/mg;
$strCoverageFile = "${strTestResultCoveragePath}/raw/${strCoverageFile}.lcov";

View File

@ -129,9 +129,13 @@ testBldShim(const String *const shimC, const StringList *const functionList)
{
strCatChr(result, ' ');
strCat(result, in);
unsigned int scanIdx = inIdx + 1;
for (unsigned int scanIdx = inIdx + 1; scanIdx < strLstSize(inList); scanIdx++)
while (true)
{
// In a properly formatted C file the end of the list can never be reached
ASSERT(scanIdx < strLstSize(inList));
const String *const scan = strLstGet(inList, scanIdx);
if (strEqZ(scan, "{"))
@ -141,6 +145,7 @@ testBldShim(const String *const shimC, const StringList *const functionList)
strCatChr(result, ' ');
strCat(result, strTrim(strDup(scan)));
scanIdx++;
}
strCatZ(result, "; ");
@ -198,8 +203,30 @@ testBldWrite(const Storage *const storage, StringList *const fileList, const cha
/***********************************************************************************************************************************
Generate a relative path from the compare path to the base path
***********************************************************************************************************************************/
static String *
cmdBldPathModule(const String *const moduleName)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STRING, moduleName);
FUNCTION_LOG_END();
??? This function has not been hardened for edge cases, e.g. paths are equal. Probably this should he moved to the storage module.
String *const result = strNew();
MEM_CONTEXT_TEMP_BEGIN()
{
if (strBeginsWithZ(moduleName, "test/"))
strCatFmt(result, "test/src%s", strZ(strSub(moduleName, 4)));
else
strCatFmt(result, "src/%s", strZ(moduleName));
}
MEM_CONTEXT_TEMP_END();
FUNCTION_LOG_RETURN(STRING, result);
}
/***********************************************************************************************************************************
Generate a relative path from the compare path to the base path
***********************************************************************************************************************************/
static String *
cmdBldPathRelative(const String *const base, const String *const compare)
@ -211,6 +238,7 @@ cmdBldPathRelative(const String *const base, const String *const compare)
ASSERT(base != NULL);
ASSERT(compare != NULL);
ASSERT(!strEq(base, compare));
String *const result = strNew();
@ -243,7 +271,16 @@ cmdBldPathRelative(const String *const base, const String *const compare)
// Add remaining path
for (unsigned int pathIdx = compareIdx; pathIdx < strLstSize(compareList); pathIdx++)
strCatFmt(result, "/%s", strZ(strLstGet(compareList, pathIdx)));
{
// If first is still set then compare must be a subpath of base (i.e. there were no .. parts)
if (!first)
{
strCatChr(result, '/');
first = false;
}
strCat(result, strLstGet(compareList, pathIdx));
}
}
MEM_CONTEXT_TEMP_END();
@ -279,7 +316,7 @@ testBldUnit(TestBuild *const this)
for (unsigned int shimIdx = 0; shimIdx < lstSize(module->shimList); shimIdx++)
{
const TestDefShim *const shim = lstGet(module->shimList, shimIdx);
const String *const shimFile = strNewFmt("src/%s.c", strZ(shim->name));
const String *const shimFile = strNewFmt("%s.c", strZ(cmdBldPathModule(shim->name)));
String *const shimC = strCatBuf(
strNew(),
@ -309,8 +346,8 @@ testBldUnit(TestBuild *const this)
const String *const include = strLstGet(harness->includeList, includeIdx);
strCatFmt(
includeReplace, "%s#include \"%s/src/%s.c\"", includeIdx == 0 ? "" : "\n",
lstExists(module->shimList, &include) ? strZ(pathUnit) : strZ(pathRepo), strZ(include));
includeReplace, "%s#include \"%s/%s.c\"", includeIdx == 0 ? "" : "\n",
lstExists(module->shimList, &include) ? strZ(pathUnit) : strZ(pathRepo), strZ(cmdBldPathModule(include)));
strLstAdd(harnessIncludeList, include);
}
@ -396,7 +433,7 @@ testBldUnit(TestBuild *const this)
if (strLstExists(harnessIncludeList, depend))
continue;
strCatFmt(mesonBuild, " '%s/src/%s.c',\n", strZ(pathRepoRel), strZ(depend));
strCatFmt(mesonBuild, " '%s/%s.c',\n", strZ(pathRepoRel), strZ(cmdBldPathModule(depend)));
}
// Add harnesses
@ -524,24 +561,19 @@ testBldUnit(TestBuild *const this)
// Files to test/include
StringList *const testIncludeFileList = strLstNew();
if (module->coverageList != NULL)
for (unsigned int coverageIdx = 0; coverageIdx < lstSize(module->coverageList); coverageIdx++)
{
for (unsigned int coverageIdx = 0; coverageIdx < lstSize(module->coverageList); coverageIdx++)
{
const TestDefCoverage *const coverage = lstGet(module->coverageList, coverageIdx);
const TestDefCoverage *const coverage = lstGet(module->coverageList, coverageIdx);
if (coverage->coverable && !coverage->included)
strLstAdd(testIncludeFileList, coverage->name);
}
if (coverage->coverable && !coverage->included)
strLstAdd(testIncludeFileList, coverage->name);
}
if (module->includeList != NULL)
{
for (unsigned int includeIdx = 0; includeIdx < strLstSize(module->includeList); includeIdx++)
strLstAdd(testIncludeFileList, strLstGet(module->includeList, includeIdx));
}
for (unsigned int includeIdx = 0; includeIdx < strLstSize(module->includeList); includeIdx++)
strLstAdd(testIncludeFileList, strLstGet(module->includeList, includeIdx));
String *const testIncludeFile = strNew();
StringList *const testIncludeFile = strLstNew();
StringList *const harnessIncluded = strLstNew();
for (unsigned int testIncludeFileIdx = 0; testIncludeFileIdx < strLstSize(testIncludeFileList); testIncludeFileIdx++)
{
@ -556,16 +588,19 @@ testBldUnit(TestBuild *const this)
break;
}
if (testIncludeFileIdx != 0)
strCatChr(testIncludeFile, '\n');
if (harnessIdx != lstSize(module->harnessList))
strCatFmt(testIncludeFile, "#include \"%s\"", strZ(strLstGet(harnessList, harnessIdx)));
{
if (!strLstExists(harnessIncluded, strLstGet(harnessList, harnessIdx)))
{
strLstAddFmt(testIncludeFile, "#include \"%s\"", strZ(strLstGet(harnessList, harnessIdx)));
strLstAdd(harnessIncluded, strLstGet(harnessList, harnessIdx));
}
}
else
strCatFmt(testIncludeFile, "#include \"%s/src/%s.c\"", strZ(pathRepoRel), strZ(include));
strLstAddFmt(testIncludeFile, "#include \"%s/%s.c\"", strZ(pathRepoRel), strZ(cmdBldPathModule(include)));
}
strReplace(testC, STRDEF("{[C_INCLUDE]}"), testIncludeFile);
strReplace(testC, STRDEF("{[C_INCLUDE]}"), strLstJoin(testIncludeFile, "\n"));
// Test path
strReplace(testC, STRDEF("{[C_TEST_PATH]}"), storagePathP(storageTestId, NULL));

View File

@ -47,8 +47,7 @@ testDefParseModuleList(Yaml *const yaml, List *const moduleList)
// Check if next is db for integration tests
bool pgRequired = false;
if (type == testDefTypeIntegration && yamlEventPeek(yaml).type == yamlEventTypeScalar &&
strEqZ(yamlEventPeek(yaml).value, "db"))
if (type == testDefTypeIntegration && strEqZ(yamlEventPeek(yaml).value, "db"))
{
yamlScalarNextCheckZ(yaml, "db");
pgRequired = yamlBoolParse(yamlScalarNext(yaml));
@ -99,8 +98,8 @@ testDefParseModuleList(Yaml *const yaml, List *const moduleList)
{
testDefCoverage.coverable = true;
}
else if (!strEqZ(type, "noCode"))
THROW_FMT(FormatError, "invalid coverage type '%s'", strZ(type));
else
CHECK_FMT(AssertError, strEqZ(type, "noCode"), "invalid coverage type %s", strZ(type));
}
YAML_MAP_END();
}
@ -204,15 +203,14 @@ testDefParseModuleList(Yaml *const yaml, List *const moduleList)
{
testDefModule.name = strNewFmt("%s/%s", strZ(moduleName), strZ(yamlScalarNext(yaml).value));
}
else if (strEqZ(subModuleDef.value, "total"))
{
testDefModule.total = cvtZToUInt(strZ(yamlScalarNext(yaml).value));
}
else
{
THROW_FMT(
FormatError, "unexpected scalar '%s' at line %zu, column %zu", strZ(subModuleDef.value),
subModuleDef.line, subModuleDef.column);
CHECK_FMT(
FormatError, strEqZ(subModuleDef.value, "total"),
"unexpected keyword '%s' at line %zu, column %zu",
strZ(subModuleDef.value), subModuleDef.line, subModuleDef.column);
testDefModule.total = cvtZToUInt(strZ(yamlScalarNext(yaml).value));
}
}
YAML_MAP_END();
@ -224,11 +222,8 @@ testDefParseModuleList(Yaml *const yaml, List *const moduleList)
{
const String *const depend = strLstGet(globalDependList, dependIdx);
if ((coverageList == NULL || !lstExists(coverageList, &depend)) &&
(includeList == NULL || !strLstExists(includeList, depend)))
{
if (!lstExists(coverageList, &depend) && !strLstExists(includeList, depend))
strLstAdd(dependList, depend);
}
}
// Add test module

View File

@ -28,12 +28,11 @@ cmdTestExec(const String *const command)
if (system(zNewFmt("%s > %s 2>&1", strZ(command), strZ(cmdTestExecLog))) != 0)
{
const Buffer *const buffer = storageGetP(
storageNewReadP(storagePosixNewP(FSLASH_STR), cmdTestExecLog, .ignoreMissing = true));
const Buffer *const buffer = storageGetP(storageNewReadP(storagePosixNewP(FSLASH_STR), cmdTestExecLog));
THROW_FMT(
ExecuteError, "unable to execute: %s > %s 2>&1:%s", strZ(command), strZ(cmdTestExecLog),
buffer == NULL || bufEmpty(buffer) ? " no log output" : zNewFmt("\n%s", strZ(strNewBuf(buffer))));
ExecuteError, "unable to execute: %s > %s 2>&1:\n%s", strZ(command), strZ(cmdTestExecLog),
zNewFmt("\n%s", strZ(strTrim(strNewBuf(buffer)))));
}
FUNCTION_LOG_RETURN_VOID();
@ -73,15 +72,15 @@ cmdTestPathCreate(const Storage *const storage, const String *const path)
void
cmdTest(
const String *const pathRepo, const String *const pathTest, const String *const vm, const unsigned int vmId,
const StringList *moduleFilterList, const unsigned int test, const uint64_t scale, const LogLevel logLevel,
const bool logTime, const String *const timeZone, const bool coverage, const bool profile, const bool optimize)
const String *moduleName, const unsigned int test, const uint64_t scale, const LogLevel logLevel, const bool logTime,
const String *const timeZone, const bool coverage, const bool profile, const bool optimize)
{
FUNCTION_LOG_BEGIN(logLevelDebug);
FUNCTION_LOG_PARAM(STRING, pathRepo);
FUNCTION_LOG_PARAM(STRING, pathTest);
FUNCTION_LOG_PARAM(STRING, vm);
FUNCTION_LOG_PARAM(UINT, vmId);
FUNCTION_LOG_PARAM(STRING_LIST, moduleFilterList);
FUNCTION_LOG_PARAM(STRING, moduleName);
FUNCTION_LOG_PARAM(UINT, test);
FUNCTION_LOG_PARAM(UINT64, scale);
FUNCTION_LOG_PARAM(ENUM, logLevel);
@ -98,14 +97,12 @@ cmdTest(
cmdTestExecLog = strNewFmt("%s/exec-%u.log", strZ(pathTest), vmId);
// Find test
ASSERT(!strLstEmpty(moduleFilterList));
ASSERT(moduleName != NULL);
const TestDef testDef = testDefParse(storagePosixNewP(pathRepo));
const String *const moduleName = strLstGet(moduleFilterList, 0);
const TestDefModule *const module = lstFind(testDef.moduleList, &moduleName);
if (module == NULL)
THROW_FMT(ParamInvalidError, "'%s' is not a valid test", strZ(moduleName));
CHECK_FMT(ParamInvalidError, module != NULL, "'%s' is not a valid test", strZ(moduleName));
// Build test
bool buildRetry = false;

View File

@ -13,7 +13,7 @@ Perform a test.
Functions
***********************************************************************************************************************************/
void cmdTest(
const String *pathRepo, const String *pathTest, const String *const vm, unsigned int vmId, const StringList *moduleFilterList,
const String *pathRepo, const String *pathTest, const String *const vm, unsigned int vmId, const String *moduleName,
unsigned int test, uint64_t scale, LogLevel logLevel, bool logTime, const String *timeZone, bool coverage, bool profile,
bool optimize);

View File

@ -72,10 +72,11 @@ main(int argListSize, const char *argList[])
{
cmdTest(
cfgOptionStr(cfgOptRepoPath), cfgOptionStr(cfgOptTestPath), cfgOptionStr(cfgOptVm),
cfgOptionUInt(cfgOptVmId), cfgCommandParam(), cfgOptionTest(cfgOptTest) ? cfgOptionUInt(cfgOptTest) : 0,
cfgOptionUInt64(cfgOptScale), logLevelEnum(cfgOptionStrId(cfgOptLogLevelTest)),
cfgOptionBool(cfgOptLogTimestamp), cfgOptionStrNull(cfgOptTz), cfgOptionBool(cfgOptCoverage),
cfgOptionBool(cfgOptProfile), cfgOptionBool(cfgOptOptimize));
cfgOptionUInt(cfgOptVmId), strLstGet(cfgCommandParam(), 0),
cfgOptionTest(cfgOptTest) ? cfgOptionUInt(cfgOptTest) : 0, cfgOptionUInt64(cfgOptScale),
logLevelEnum(cfgOptionStrId(cfgOptLogLevelTest)), cfgOptionBool(cfgOptLogTimestamp),
cfgOptionStrNull(cfgOptTz), cfgOptionBool(cfgOptCoverage), cfgOptionBool(cfgOptProfile),
cfgOptionBool(cfgOptOptimize));
break;
}

View File

@ -0,0 +1,872 @@
/***********************************************************************************************************************************
Test Test Command
***********************************************************************************************************************************/
#include "storage/posix/storage.h"
#include "common/harnessStorage.h"
/***********************************************************************************************************************************
Build list of test files to compare
***********************************************************************************************************************************/
static StringList *
testStorageList(const Storage *const storage)
{
StringList *const result = strLstNew();
MEM_CONTEXT_TEMP_BEGIN()
{
StorageIterator *storageItr = storageNewItrP(storage, NULL, .sortOrder = sortOrderAsc, .recurse = true);
while (storageItrMore(storageItr))
{
const StorageInfo info = storageItrNext(storageItr);
if (info.type == storageTypeFile && !strBeginsWithZ(info.name, "build/"))
strLstAdd(result, info.name);
}
}
MEM_CONTEXT_TEMP_END();
return result;
}
/***********************************************************************************************************************************
Copy a list of files from the repo to the test repo
***********************************************************************************************************************************/
#define TEST_COPY(source, destination, ...) \
do \
{ \
const char *const copyList[] = {__VA_ARGS__}; \
\
for (unsigned int copyIdx = 0; copyIdx < LENGTH_OF(copyList); copyIdx++) \
{ \
HRN_STORAGE_PUT( \
destination, zNewFmt("repo/%s", copyList[copyIdx]), storageGetP(storageNewReadP(source, STR(copyList[copyIdx])))); \
} \
} \
while (0)
/***********************************************************************************************************************************
Test Run
***********************************************************************************************************************************/
static void
testRun(void)
{
FUNCTION_HARNESS_VOID();
const Storage *const storageRepo = storagePosixNewP(STRDEF(HRN_PATH_REPO));
const Storage *const storageTest = storagePosixNewP(STRDEF(TEST_PATH), .write = true);
// *****************************************************************************************************************************
if (testBegin("cmdBldPathRelative()"))
{
TEST_ERROR(cmdBldPathRelative(STRDEF("/tmp"), STRDEF("/tmp")), AssertError, "assertion '!strEq(base, compare)' failed");
TEST_RESULT_STR_Z(cmdBldPathRelative(STRDEF("/tmp/sub"), STRDEF("/tmp")), "..", "compare is sub of base");
TEST_RESULT_STR_Z(cmdBldPathRelative(STRDEF("/tmp"), STRDEF("/tmp/sub")), "sub", "base is sub of compare");
}
// *****************************************************************************************************************************
if (testBegin("cmdTestExec()"))
{
cmdTestExecLog = STRDEF(TEST_PATH "/error.log");
bool error = false;
// The error will vary by OS so just make sure an error was thrown
TRY_BEGIN()
{
cmdTestExec(STRDEF("/bogus/bogus"));
}
CATCH(ExecuteError)
{
error = true;
}
TRY_END();
TEST_RESULT_BOOL(error, true, "an error should be thrown");
cmdTestExecLog = NULL;
}
// *****************************************************************************************************************************
if (testBegin("TestDef and TestBuild"))
{
// meson_options.txt
// -------------------------------------------------------------------------------------------------------------------------
const char *const mesonOption = strZ(strNewBuf(storageGetP(storageNewReadP(storageRepo, STRDEF("meson_options.txt")))));
HRN_STORAGE_PUT_Z(storageTest, "repo/meson_options.txt", mesonOption);
// Root meson.build
// -------------------------------------------------------------------------------------------------------------------------
String *const mesonBuildRoot = strCat(
strNew(), strNewBuf(storageGetP(storageNewReadP(storageRepo, STRDEF("meson.build")))));
HRN_STORAGE_PUT_Z(storageTest, "repo/meson.build", strZ(mesonBuildRoot));
strReplace(mesonBuildRoot, STRDEF("subdir('"), STRDEF("# subdir('"));
strCatZ(
mesonBuildRoot,
"\n"
MESON_COMMENT_BLOCK "\n"
"# Write configuration\n"
MESON_COMMENT_BLOCK "\n"
"configure_file(output: 'build.auto.h', configuration: configuration)\n"
"\n"
"add_global_arguments('-DFN_EXTERN=extern', language : 'c')\n"
"add_global_arguments('-DVR_EXTERN_DECLARE=extern', language : 'c')\n"
"add_global_arguments('-DVR_EXTERN_DEFINE=', language : 'c')\n"
"add_global_arguments('-DERROR_MESSAGE_BUFFER_SIZE=131072', language : 'c')\n");
// harnessError.c
// -------------------------------------------------------------------------------------------------------------------------
String *const harnessErrorC = strCat(
strNew(), strNewBuf(storageGetP(storageNewReadP(storageRepo, STRDEF("test/src/common/harnessError.c")))));
strReplace(harnessErrorC, STRDEF("{[SHIM_MODULE]}"), STRDEF("#include \"" TEST_PATH "/repo/src/common/error.c\""));
// Unit test harness
// -------------------------------------------------------------------------------------------------------------------------
String *const testC = strCat(strNew(), strNewBuf(storageGetP(storageNewReadP(storageRepo, STRDEF("test/src/test.c")))));
strReplace(testC, STRDEF("{[C_HRN_PATH]}"), STRDEF(TEST_PATH "/test/data-3"));
strReplace(testC, STRDEF("{[C_HRN_PATH_REPO]}"), STRDEF(TEST_PATH "/repo"));
strReplace(testC, STRDEF("{[C_LOG_LEVEL_TEST]}"), STRDEF("logLevelDebug"));
strReplace(testC, STRDEF("{[C_TEST_GROUP]}"), STRDEF(TEST_GROUP));
strReplace(testC, STRDEF("{[C_TEST_GROUP_ID]}"), STRDEF(TEST_GROUP_ID_Z));
strReplace(testC, STRDEF("{[C_TEST_GROUP_ID_Z]}"), STRDEF("\"" TEST_GROUP_ID_Z "\""));
strReplace(testC, STRDEF("{[C_TEST_IDX]}"), STRDEF("3"));
strReplace(testC, STRDEF("{[C_TEST_PATH]}"), STRDEF(TEST_PATH "/test/test-3"));
strReplace(testC, STRDEF("{[C_TEST_PGB_PATH]}"), STRDEF("../../../../repo"));
strReplace(testC, STRDEF("{[C_TEST_SCALE]}"), STRDEF("1"));
strReplace(testC, STRDEF("{[C_TEST_TIMING]}"), STRDEF("true"));
strReplace(testC, STRDEF("{[C_TEST_USER]}"), STRDEF(TEST_USER));
strReplace(testC, STRDEF("{[C_TEST_USER_ID]}"), STRDEF(TEST_USER_ID_Z));
strReplace(testC, STRDEF("{[C_TEST_USER_ID_Z]}"), STRDEF("\"" TEST_USER_ID_Z "\""));
// Test definition
// -------------------------------------------------------------------------------------------------------------------------
HRN_STORAGE_PUT_Z(
storageTest, "repo/test/define.yaml",
"unit:\n"
" - name: common\n"
" test:\n"
" - name: pre\n"
" total: 1\n"
"\n"
" - name: error\n"
" total: 9\n"
" feature: error\n"
" harness:\n"
" name: error\n"
" shim:\n"
" common/error: ~\n"
" coverage:\n"
" - common/error\n"
" - common/error.auto: noCode\n"
" - common/error.inc: included\n"
" depend:\n"
" - common/stackTrace\n"
"\n"
" - name: stack-trace\n"
" total: 4\n"
" feature: stackTrace\n"
" coverage:\n"
" - common/stackTrace\n"
" depend:\n"
" - common/debug\n"
"\n"
" - name: test\n"
" test:\n"
" - name: shim\n"
" binReq: true\n"
" containerReq: true\n"
" total: 1\n"
" define: -DNDEBUG\n"
" harness: noShim\n"
" harness:\n"
" name: shim\n"
" shim:\n"
" test/common/shim:\n"
" function:\n"
" - shimFunc\n"
" - shimFunc2\n"
" test/common/shim2: ~\n"
" coverage:\n"
" - test/common/shim\n"
" - test/common/shim2\n"
" include:\n"
" - common/error\n"
" - test/common/include\n"
"\n"
"integration:\n"
" - name: mock\n"
" test:\n"
" - name: all\n"
" total: 2\n"
"\n"
" - name: real\n"
" db: true\n"
" test:\n"
" - name: all\n"
" total: 2\n"
"\n"
"performance:\n"
" - name: performance\n"
" test:\n"
" - name: type\n"
" total: 1\n");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("Test common/stack-trace");
TEST_COPY(
storageRepo, storageTest,
"src/common/assert.h",
"src/common/debug.c",
"src/common/debug.h",
"src/common/error.auto.c.inc",
"src/common/error.auto.h",
"src/common/error.c",
"src/common/error.h",
"src/common/logLevel.h",
"src/common/macro.h",
"src/common/stackTrace.c",
"src/common/stackTrace.h",
"src/common/type/convert.h",
"src/common/type/param.h",
"src/common/type/stringZ.h",
"test/src/common/harnessDebug.h",
"test/src/common/harnessLog.h",
"test/src/common/harnessError.c",
"test/src/common/harnessError.h",
"test/src/common/harnessTest.c",
"test/src/common/harnessTest.h",
"test/src/common/harnessTest.intern.h",
"test/src/module/common/stackTraceTest.c",
"test/src/test.c");
TEST_RESULT_VOID(
cmdTest(
STRDEF(TEST_PATH "/repo"), storagePathP(storageTest, STRDEF("test")), STRDEF("none"), 3,
STRDEF("common/stack-trace"), 0, 1, logLevelDebug, true, NULL, false, false, false),
"new build");
const Storage *storageUnit = storagePosixNewP(STRDEF(TEST_PATH "/test/unit-3/none"));
StringList *fileList = testStorageList(storageUnit);
TEST_RESULT_STRLST_Z(
fileList,
"meson.build\n"
"meson_options.txt\n"
"test/src/common/harnessError.c\n"
"test.c\n",
"check files");
for (unsigned int fileIdx = 0; fileIdx < strLstSize(fileList); fileIdx++)
{
const String *const file = strLstGet(fileList, fileIdx);
if (strEqZ(file, "meson.build"))
{
TEST_STORAGE_GET(
storageUnit, strZ(file),
zNewFmt(
"%s"
"add_global_arguments('-DHRN_INTEST_STACKTRACE', language : 'c')\n"
"add_global_arguments('-DHRN_FEATURE_ERROR', language : 'c')\n"
"\n"
MESON_COMMENT_BLOCK "\n"
"# Unit test\n"
MESON_COMMENT_BLOCK "\n"
"src_unit = files(\n"
" '../../../repo/src/common/debug.c',\n"
" 'test/src/common/harnessError.c',\n"
" '../../../repo/test/src/common/harnessTest.c',\n"
" 'test.c',\n"
")\n"
"\n"
"executable(\n"
" 'test-unit',\n"
" sources: src_unit,\n"
" include_directories:\n"
" include_directories(\n"
" '.',\n"
" '../../../repo/src',\n"
" '../../../repo/test/src',\n"
" ),\n"
" dependencies: [\n"
" lib_bz2,\n"
" lib_openssl,\n"
" lib_lz4,\n"
" lib_pq,\n"
" lib_xml,\n"
" lib_yaml,\n"
" lib_z,\n"
" lib_zstd,\n"
" ],\n"
")\n",
strZ(mesonBuildRoot)));
}
else if (strEqZ(file, "meson_options.txt"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), mesonOption);
}
else if (strEqZ(file, "test/src/common/harnessError.c"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(harnessErrorC));
}
else if (strEqZ(file, "test.c"))
{
String *const testCDup = strCat(strNew(), testC);
strReplace(testCDup, STRDEF("{[C_TEST_CONTAINER]}"), STRDEF("false"));
strReplace(testCDup, STRDEF("{[C_TEST_DEBUG_TEST_TRACE]}"), STRDEF("#define DEBUG_TEST_TRACE"));
strReplace(testCDup, STRDEF("{[C_TEST_PATH_BUILD]}"), STRDEF(TEST_PATH "/test/unit-3/none/build"));
strReplace(testCDup, STRDEF("{[C_TEST_PROFILE]}"), STRDEF("false"));
strReplace(testCDup, STRDEF("{[C_TEST_PROJECT_EXE]}"), STRDEF(TEST_PATH "/test/build/none/src/pgbackrest"));
strReplace(testCDup, STRDEF("{[C_TEST_TZ]}"), STRDEF("// No timezone specified"));
strReplace(testCDup, STRDEF("{[C_INCLUDE]}"), STRDEF("#include \"../../../repo/src/common/stackTrace.c\""));
strReplace(
testCDup, STRDEF("{[C_TEST_INCLUDE]}"),
STRDEF("#include \"../../../repo/test/src/module/common/stackTraceTest.c\""));
strReplace(
testCDup, STRDEF("{[C_TEST_LIST]}"),
STRDEF(
"hrnAdd( 1, true);\n"
" hrnAdd( 2, true);\n"
" hrnAdd( 3, true);\n"
" hrnAdd( 4, true);"));
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(testCDup));
}
else
THROW_FMT(TestError, "no test for '%s'", strZ(file));
}
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("Test common/error");
TEST_COPY(
storageRepo, storageTest,
"test/src/common/harnessFork.h",
"test/src/module/common/errorTest.c");
TEST_RESULT_VOID(
cmdTest(
STRDEF(TEST_PATH "/repo"), storagePathP(storageTest, STRDEF("test")), STRDEF("none"), 3,
STRDEF("common/error"), 5, 1, logLevelDebug, true, NULL, false, false, false),
"new build");
fileList = testStorageList(storageUnit);
TEST_RESULT_STRLST_Z(
fileList,
"meson.build\n"
"meson_options.txt\n"
"test/src/common/harnessError.c\n"
"test.c\n",
"check files");
for (unsigned int fileIdx = 0; fileIdx < strLstSize(fileList); fileIdx++)
{
const String *const file = strLstGet(fileList, fileIdx);
if (strEqZ(file, "meson.build"))
{
TEST_STORAGE_GET(
storageUnit, strZ(file),
zNewFmt(
"%s"
"add_global_arguments('-DHRN_INTEST_ERROR', language : 'c')\n"
"\n"
MESON_COMMENT_BLOCK "\n"
"# Unit test\n"
MESON_COMMENT_BLOCK "\n"
"src_unit = files(\n"
" '../../../repo/src/common/stackTrace.c',\n"
" '../../../repo/test/src/common/harnessTest.c',\n"
" 'test.c',\n"
")\n"
"\n"
"executable(\n"
" 'test-unit',\n"
" sources: src_unit,\n"
" include_directories:\n"
" include_directories(\n"
" '.',\n"
" '../../../repo/src',\n"
" '../../../repo/test/src',\n"
" ),\n"
" dependencies: [\n"
" lib_bz2,\n"
" lib_openssl,\n"
" lib_lz4,\n"
" lib_pq,\n"
" lib_xml,\n"
" lib_yaml,\n"
" lib_z,\n"
" lib_zstd,\n"
" ],\n"
")\n",
strZ(mesonBuildRoot)));
}
else if (strEqZ(file, "meson_options.txt"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), mesonOption);
}
else if (strEqZ(file, "test/src/common/harnessError.c"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(harnessErrorC));
}
else if (strEqZ(file, "test.c"))
{
String *const testCDup = strCat(strNew(), testC);
strReplace(testCDup, STRDEF("{[C_TEST_CONTAINER]}"), STRDEF("false"));
strReplace(testCDup, STRDEF("{[C_TEST_DEBUG_TEST_TRACE]}"), STRDEF("#define DEBUG_TEST_TRACE"));
strReplace(testCDup, STRDEF("{[C_TEST_PATH_BUILD]}"), STRDEF(TEST_PATH "/test/unit-3/none/build"));
strReplace(testCDup, STRDEF("{[C_TEST_PROFILE]}"), STRDEF("false"));
strReplace(testCDup, STRDEF("{[C_TEST_PROJECT_EXE]}"), STRDEF(TEST_PATH "/test/build/none/src/pgbackrest"));
strReplace(testCDup, STRDEF("{[C_TEST_TZ]}"), STRDEF("// No timezone specified"));
strReplace(
testCDup, STRDEF("{[C_INCLUDE]}"),
STRDEF("#include \"test/src/common/harnessError.c\""));
strReplace(
testCDup, STRDEF("{[C_TEST_INCLUDE]}"),
STRDEF("#include \"../../../repo/test/src/module/common/errorTest.c\""));
strReplace(
testCDup, STRDEF("{[C_TEST_LIST]}"),
STRDEF(
"hrnAdd( 1, false);\n"
" hrnAdd( 2, false);\n"
" hrnAdd( 3, false);\n"
" hrnAdd( 4, false);\n"
" hrnAdd( 5, true);\n"
" hrnAdd( 6, false);\n"
" hrnAdd( 7, false);\n"
" hrnAdd( 8, false);\n"
" hrnAdd( 9, false);"));
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(testCDup));
}
else
THROW_FMT(TestError, "no test for '%s'", strZ(file));
}
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("Test test/shim");
String *const shimC = strCatZ(
strNew(),
"int\n"
"shimFunc(void)\n"
"{\n"
" return 777;\n"
"}\n"
"\n"
"static int\n"
"shimFunc2(\n"
" int param1,\n"
" int param2)\n"
"{\n"
" return 777 + param1 + param2;\n"
"}\n");
HRN_STORAGE_PUT_Z(storageTest, "repo/test/src/common/shim.c", strZ(shimC));
HRN_STORAGE_PUT_Z(
storageTest, "repo/test/src/common/shim2.c",
"int noShimFunc3(void)\n"
"{\n"
" return 888;\n"
"}\n");
strReplace(shimC, STRDEF("int\nshimFunc(void)"), STRDEF("int\nshimFunc_SHIMMED(void)"));
strReplace(
shimC, STRDEF("static int\nshimFunc2("),
STRDEF("static int shimFunc2(int param1, int param2); static int\nshimFunc2_SHIMMED("));
String *const harnessShimC = strCatZ(
strNew(),
"{[SHIM_MODULE]}\n"
"\n"
"static int\n"
"shimFunc(void)\n"
"{\n"
" return shimFunc_SHIMMED() + 1;\n"
" (void)shimFunc2; // To suppress unused warnings\n"
"}\n"
"\n"
"static int\n"
"shimFunc2(int param1, int param2)\n"
"{\n"
" return shimFunc2_SHIMMED(param1, param2) + 2;\n"
" (void)shimFunc; // To suppress unused warnings\n"
"}\n");
HRN_STORAGE_PUT_Z(storageTest, "repo/test/src/common/harnessShim.c", strZ(harnessShimC));
HRN_STORAGE_PUT_EMPTY(storageTest, "repo/test/src/common/harnessShim/sub.c");
HRN_STORAGE_PUT_EMPTY(storageTest, "repo/test/src/common/harnessNoShim.c");
HRN_STORAGE_PUT_EMPTY(storageTest, "repo/test/src/common/include.c");
strReplace(
harnessShimC, STRDEF("{[SHIM_MODULE]}"),
STRDEF(
"#include \"" TEST_PATH "/test/unit-3/uXX/test/src/common/shim.c\"\n"
"#include \"" TEST_PATH "/repo/test/src/common/shim2.c\""));
HRN_STORAGE_PUT_Z(
storageTest, "repo/test/src/module/test/shimTest.c",
"static void\n"
"testRun(void)\n"
"{\n"
" FUNCTION_HARNESS_VOID();\n"
"\n"
" if (testBegin(\"shims\"))\n"
" {\n"
" TEST_RESULT_INT(shimFunc_SHIMMED(), 777, \"shimFunc()\");\n"
" TEST_RESULT_INT(shimFunc(), 778, \"shimFunc()\");\n"
"\n"
" TEST_RESULT_INT(shimFunc2_SHIMMED(111, 112), 1000, \"shimFunc2()\");\n"
" TEST_RESULT_INT(shimFunc2(111, 112), 1002, \"shimFunc2()\");\n"
"\n"
" TEST_RESULT_INT(noShimFunc3(), 888, \"noShimFunc3()\");\n"
" }\n"
"\n"
" FUNCTION_HARNESS_RETURN_VOID();\n"
"}\n");
HRN_STORAGE_PUT_EMPTY(storageTest, TEST_PATH "/test/unit-3/uXX/cleanme.txt");
TEST_RESULT_VOID(
cmdTest(
STRDEF(TEST_PATH "/repo"), storagePathP(storageTest, STRDEF("test")), STRDEF("uXX"), 3,
STRDEF("test/shim"), 0, 1, logLevelDebug, true, NULL, true, true, true),
"new build");
storageUnit = storagePosixNewP(STRDEF(TEST_PATH "/test/unit-3/uXX"));
fileList = testStorageList(storageUnit);
TEST_RESULT_STRLST_Z(
fileList,
"meson.build\n"
"meson_options.txt\n"
"test/src/common/harnessError.c\n"
"test/src/common/harnessShim.c\n"
"test/src/common/shim.c\n"
"test.c\n",
"check files");
for (unsigned int fileIdx = 0; fileIdx < strLstSize(fileList); fileIdx++)
{
const String *const file = strLstGet(fileList, fileIdx);
if (strEqZ(file, "meson.build"))
{
TEST_STORAGE_GET(
storageUnit, strZ(file),
zNewFmt(
"%s"
"add_global_arguments('-DHRN_FEATURE_ERROR', language : 'c')\n"
"add_global_arguments('-DHRN_FEATURE_STACKTRACE', language : 'c')\n"
"add_global_arguments('-DNDEBUG', language : 'c')\n"
"add_global_arguments('-DDEBUG_COVERAGE', language : 'c')\n"
"add_global_arguments('-DTEST_CONTAINER_REQUIRED', language : 'c')\n"
"\n"
MESON_COMMENT_BLOCK "\n"
"# Unit test\n"
MESON_COMMENT_BLOCK "\n"
"src_unit = files(\n"
" '../../../repo/src/common/stackTrace.c',\n"
" '../../../repo/src/common/debug.c',\n"
" '../../../repo/test/src/common/harnessNoShim.c',\n"
" '../../../repo/test/src/common/harnessShim/sub.c',\n"
" '../../../repo/test/src/common/harnessTest.c',\n"
" 'test.c',\n"
")\n"
"\n"
"executable(\n"
" 'test-unit',\n"
" sources: src_unit,\n"
" c_args: [\n"
" '-O2',\n"
" '-pg',\n"
" '-no-pie',\n"
" ],\n"
" link_args: [\n"
" '-pg',\n"
" '-no-pie',\n"
" ],\n"
" include_directories:\n"
" include_directories(\n"
" '.',\n"
" '../../../repo/src',\n"
" '../../../repo/test/src',\n"
" ),\n"
" dependencies: [\n"
" lib_bz2,\n"
" lib_openssl,\n"
" lib_lz4,\n"
" lib_pq,\n"
" lib_xml,\n"
" lib_yaml,\n"
" lib_z,\n"
" lib_zstd,\n"
" ],\n"
")\n",
strZ(mesonBuildRoot)));
}
else if (strEqZ(file, "meson_options.txt"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), mesonOption);
}
else if (strEqZ(file, "test/src/common/harnessError.c"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(harnessErrorC));
}
else if (strEqZ(file, "test/src/common/harnessShim.c"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(harnessShimC));
}
else if (strEqZ(file, "test/src/common/shim.c"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(shimC));
}
else if (strEqZ(file, "test.c"))
{
String *const testCDup = strCat(strNew(), testC);
strReplace(testCDup, STRDEF("{[C_TEST_CONTAINER]}"), STRDEF("true"));
strReplace(testCDup, STRDEF("{[C_TEST_DEBUG_TEST_TRACE]}"), STRDEF("// Debug test trace not enabled"));
strReplace(testCDup, STRDEF("{[C_TEST_PATH_BUILD]}"), STRDEF(TEST_PATH "/test/unit-3/uXX/build"));
strReplace(testCDup, STRDEF("{[C_TEST_PROFILE]}"), STRDEF("true"));
strReplace(testCDup, STRDEF("{[C_TEST_PROJECT_EXE]}"), STRDEF(TEST_PATH "/test/bin/uXX/pgbackrest"));
strReplace(testCDup, STRDEF("{[C_TEST_TZ]}"), STRDEF("// No timezone specified"));
strReplace(
testCDup,
STRDEF("{[C_INCLUDE]}"),
STRDEF(
"#include \"test/src/common/harnessShim.c\"\n"
"#include \"test/src/common/harnessError.c\"\n"
"#include \"../../../repo/test/src/common/include.c\""));
strReplace(
testCDup, STRDEF("{[C_TEST_INCLUDE]}"), STRDEF("#include \"../../../repo/test/src/module/test/shimTest.c\""));
strReplace(
testCDup, STRDEF("{[C_TEST_LIST]}"),
STRDEF(
"hrnAdd( 1, true);"));
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(testCDup));
}
else
THROW_FMT(TestError, "no test for '%s'", strZ(file));
}
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("Run test/shim and build again to cleanup coverage data");
HRN_SYSTEM(TEST_PATH "/test/unit-3/uXX/build/test-unit");
TEST_RESULT_VOID(
cmdTest(
STRDEF(TEST_PATH "/repo"), storagePathP(storageTest, STRDEF("test")), STRDEF("uXX"), 3,
STRDEF("test/shim"), 0, 1, logLevelDebug, true, NULL, true, true, true),
"new build");
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("Test performance/type");
HRN_STORAGE_PUT_Z(
storageTest, "repo/test/src/module/performance/typeTest.c",
"static void\n"
"testRun(void)\n"
"{\n"
" FUNCTION_HARNESS_VOID();\n"
"\n"
" if (testBegin(\"type\"))\n"
" {\n"
" }\n"
"\n"
" FUNCTION_HARNESS_RETURN_VOID();\n"
"}\n");
HRN_SYSTEM("chmod 000 " TEST_PATH "/test/unit-3/uXX/build");
TEST_RESULT_VOID(
cmdTest(
STRDEF(TEST_PATH "/repo"), storagePathP(storageTest, STRDEF("test")), STRDEF("uXX"), 3,
STRDEF("performance/type"), 0, 1, logLevelDebug, true, STRDEF("America/New_York"), false, true, false),
"new build");
TEST_RESULT_LOG(
"P00 WARN: build failed for unit performance/type -- will retry: unable to list file info for path '" TEST_PATH
"/test/unit-3/uXX/build': [13] Permission denied");
storageUnit = storagePosixNewP(STRDEF(TEST_PATH "/test/unit-3/uXX"));
fileList = testStorageList(storageUnit);
TEST_RESULT_STRLST_Z(
fileList,
"meson.build\n"
"meson_options.txt\n"
"test/src/common/harnessError.c\n"
"test/src/common/harnessShim.c\n"
"test/src/common/shim.c\n"
"test.c\n",
"check files");
for (unsigned int fileIdx = 0; fileIdx < strLstSize(fileList); fileIdx++)
{
const String *const file = strLstGet(fileList, fileIdx);
if (strEqZ(file, "meson.build"))
{
TEST_STORAGE_GET(
storageUnit, strZ(file),
zNewFmt(
"%s"
"add_global_arguments('-DHRN_FEATURE_ERROR', language : 'c')\n"
"add_global_arguments('-DHRN_FEATURE_STACKTRACE', language : 'c')\n"
"add_global_arguments('-DTEST_CONTAINER_REQUIRED', language : 'c')\n"
"\n"
MESON_COMMENT_BLOCK "\n"
"# Unit test\n"
MESON_COMMENT_BLOCK "\n"
"src_unit = files(\n"
" '../../../repo/src/common/stackTrace.c',\n"
" '../../../repo/src/common/debug.c',\n"
" 'test/src/common/harnessError.c',\n"
" '../../../repo/test/src/common/harnessNoShim.c',\n"
" '../../../repo/test/src/common/harnessShim/sub.c',\n"
" 'test/src/common/harnessShim.c',\n"
" '../../../repo/test/src/common/harnessTest.c',\n"
" 'test.c',\n"
")\n"
"\n"
"executable(\n"
" 'test-unit',\n"
" sources: src_unit,\n"
" c_args: [\n"
" '-O2',\n"
" '-pg',\n"
" '-no-pie',\n"
" ],\n"
" link_args: [\n"
" '-pg',\n"
" '-no-pie',\n"
" ],\n"
" include_directories:\n"
" include_directories(\n"
" '.',\n"
" '../../../repo/src',\n"
" '../../../repo/test/src',\n"
" ),\n"
" dependencies: [\n"
" lib_bz2,\n"
" lib_openssl,\n"
" lib_lz4,\n"
" lib_pq,\n"
" lib_xml,\n"
" lib_yaml,\n"
" lib_z,\n"
" lib_zstd,\n"
" ],\n"
")\n",
strZ(mesonBuildRoot)));
}
else if (strEqZ(file, "meson_options.txt"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), mesonOption);
}
else if (strEqZ(file, "test/src/common/harnessError.c"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(harnessErrorC));
}
else if (strEqZ(file, "test/src/common/harnessShim.c"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(harnessShimC));
}
else if (strEqZ(file, "test/src/common/shim.c"))
{
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(shimC));
}
else if (strEqZ(file, "test.c"))
{
String *const testCDup = strCat(strNew(), testC);
strReplace(testCDup, STRDEF("{[C_TEST_CONTAINER]}"), STRDEF("true"));
strReplace(testCDup, STRDEF("{[C_TEST_DEBUG_TEST_TRACE]}"), STRDEF("// Debug test trace not enabled"));
strReplace(testCDup, STRDEF("{[C_TEST_PATH_BUILD]}"), STRDEF(TEST_PATH "/test/unit-3/uXX/build"));
strReplace(testCDup, STRDEF("{[C_TEST_PROFILE]}"), STRDEF("true"));
strReplace(testCDup, STRDEF("{[C_TEST_PROJECT_EXE]}"), STRDEF(TEST_PATH "/test/bin/uXX/pgbackrest"));
strReplace(testCDup, STRDEF("{[C_TEST_TZ]}"), STRDEF("setenv(\"TZ\", \"America/New_York\", true);"));
strReplace(testCDup, STRDEF("{[C_INCLUDE]}"), STRDEF(""));
strReplace(
testCDup, STRDEF("{[C_TEST_INCLUDE]}"),
STRDEF("#include \"../../../repo/test/src/module/performance/typeTest.c\""));
strReplace(
testCDup, STRDEF("{[C_TEST_LIST]}"),
STRDEF(
"hrnAdd( 1, true);"));
TEST_STORAGE_GET(storageUnit, strZ(file), strZ(testCDup));
}
else
THROW_FMT(TestError, "no test for '%s'", strZ(file));
}
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("Test performance/type with profiling off for coverage");
TEST_RESULT_VOID(
cmdTest(
STRDEF(TEST_PATH "/repo"), storagePathP(storageTest, STRDEF("test")), STRDEF("uXX"), 3,
STRDEF("performance/type"), 0, 1, logLevelDebug, true, STRDEF("America/New_York"), false, false, false),
"new build");
storageUnit = storagePosixNewP(STRDEF(TEST_PATH "/test/unit-3/uXX"));
// Test one file to make sure profiling was not enabled
String *const testCDup = strCat(strNew(), testC);
strReplace(testCDup, STRDEF("{[C_TEST_CONTAINER]}"), STRDEF("true"));
strReplace(testCDup, STRDEF("{[C_TEST_DEBUG_TEST_TRACE]}"), STRDEF("// Debug test trace not enabled"));
strReplace(testCDup, STRDEF("{[C_TEST_PATH_BUILD]}"), STRDEF(TEST_PATH "/test/unit-3/uXX/build"));
strReplace(testCDup, STRDEF("{[C_TEST_PROFILE]}"), STRDEF("false"));
strReplace(testCDup, STRDEF("{[C_TEST_PROJECT_EXE]}"), STRDEF(TEST_PATH "/test/bin/uXX/pgbackrest"));
strReplace(testCDup, STRDEF("{[C_TEST_TZ]}"), STRDEF("setenv(\"TZ\", \"America/New_York\", true);"));
strReplace(testCDup, STRDEF("{[C_INCLUDE]}"), STRDEF(""));
strReplace(
testCDup, STRDEF("{[C_TEST_INCLUDE]}"),
STRDEF("#include \"../../../repo/test/src/module/performance/typeTest.c\""));
strReplace(
testCDup, STRDEF("{[C_TEST_LIST]}"),
STRDEF(
"hrnAdd( 1, true);"));
TEST_STORAGE_GET(storageUnit, "test.c", strZ(testCDup));
// -------------------------------------------------------------------------------------------------------------------------
TEST_TITLE("Fatal test error");
HRN_SYSTEM("chmod 000 " TEST_PATH "/repo/meson.build");
TEST_ERROR(
cmdTest(
STRDEF(TEST_PATH "/repo"), storagePathP(storageTest, STRDEF("test")), STRDEF("uXX"), 3,
STRDEF("performance/type"), 0, 1, logLevelDebug, true, STRDEF("America/New_York"), false, false, false),
FileOpenError,
"build failed for unit performance/type: unable to open file '" TEST_PATH "/repo/meson.build' for read: [13] Permission"
" denied");
TEST_RESULT_LOG(
"P00 WARN: build failed for unit performance/type -- will retry: unable to open file '" TEST_PATH "/repo/meson.build'"
" for read: [13] Permission denied");
}
FUNCTION_HARNESS_RETURN_VOID();
}

View File

@ -30,6 +30,7 @@ The test code is included directly so it can freely interact with the included C
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#ifdef HRN_FEATURE_ERROR
#include "common/error.h"