mirror of
https://github.com/pgbackrest/pgbackrest.git
synced 2025-01-30 05:39:12 +02:00
Improve fork harness to allow multiple children and setup pipes automatically.
There was a lot of extra boilerplate involved in setting up pipes so that is now automated. In some cases testing with multiple children is useful so allow that as well.
This commit is contained in:
parent
18b62a4220
commit
4be271ea2a
@ -115,6 +115,10 @@
|
||||
<p>Create test matrix for <id>mock/archive</id> and <id>mock/stanza</id> to increase coverage and reduce tests.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Improve fork harness to allow multiple children and setup pipes automatically.</p>
|
||||
</release-item>
|
||||
|
||||
<release-item>
|
||||
<p>Reduce expect log level in <id>mock/archive</id> and <id>mock/stanza</id> tests.</p>
|
||||
</release-item>
|
||||
|
@ -8,96 +8,197 @@ The general form of the fork harness is:
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
// This block is required
|
||||
HARNESS_FORK_CHILD()
|
||||
// This block is required and can be repeated up to HARNESS_FORK_CHILD_MAX times.
|
||||
//
|
||||
// The first parameter is the expected exit code. If the child block does not have an explicit exit then it will automatically
|
||||
// exit on 0.
|
||||
//
|
||||
// The second paramater specifies whether pipes should be setup between the parent and child processes. These can be accessed
|
||||
// with the HARNESS_FORK_*() macros;
|
||||
HARNESS_FORK_CHILD_BEGIN(0, true)
|
||||
{
|
||||
// Child test code goes here
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
|
||||
// This block is optional
|
||||
HARNESS_FORK_PARENT()
|
||||
// This block is optional but generally useful
|
||||
HARNESS_FORK_PARENT_BEGIN()
|
||||
{
|
||||
// Parent test code goes here
|
||||
}
|
||||
|
||||
// If the exit result from the child process is expected to be non-zero then that must be set with this optional statement
|
||||
HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS_SET(<non-zero exit status>);
|
||||
HARNESS_FORK_PARENT_END();
|
||||
}
|
||||
HARNESS_FORK_END()
|
||||
|
||||
If the child process does not explicitly exit in HARNESS_FORK_CHILD() then it will exit with 0 at HARNESS_FORK_END(). This harness
|
||||
is not intended for long-lived child processes.
|
||||
If the child process does not explicitly exit in HARNESS_FORK_CHILD_BEGIN/END() then it will exit with 0 at HARNESS_FORK_END().
|
||||
This harness is not intended for long-lived child processes.
|
||||
|
||||
There should not be any code outside the HARNESS_FORK_CHILD() and HARNESS_FORK_PARENT() blocks except the
|
||||
HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS_SET() macro unless the code is intended to run in both the child and parent process which is
|
||||
rare.
|
||||
There should not be any code outside the HARNESS_FORK_CHILD_BEGIN/END() and HARNESS_FORK_PARENT_BEGIN/END() blocks.
|
||||
***********************************************************************************************************************************/
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
HARNESS_FORK_PROCESS_ID()
|
||||
|
||||
Return the id of the child process, 0 if in the child process.
|
||||
Define the max number of child processes allowed
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_PROCESS_ID() \
|
||||
HARNESS_FORK_processId
|
||||
#define HARNESS_FORK_CHILD_MAX 4
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS()
|
||||
Total number of child processes forked
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_PROCESS_TOTAL() \
|
||||
HARNESS_FORK_processTotal
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Return the process index of the child (i.e. the index in the total)
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_PROCESS_IDX() \
|
||||
HARNESS_FORK_processIdx
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Return the id of the child process, 0 if in the child process
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_PROCESS_ID(processId) \
|
||||
HARNESS_FORK_processIdList[processId]
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Return the pipe for the child process
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_PIPE(processId) \
|
||||
HARNESS_FORK_pipe[processId]
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Is the pipe required for this child process?
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_PIPE_REQUIRED(processId) \
|
||||
HARNESS_FORK_pipeRequired[processId]
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
Get read/write pipe handles
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_CHILD_READ_PROCESS(processId) \
|
||||
HARNESS_FORK_PIPE(processId)[1][0]
|
||||
|
||||
#define HARNESS_FORK_CHILD_READ() \
|
||||
HARNESS_FORK_CHILD_READ_PROCESS(HARNESS_FORK_PROCESS_IDX())
|
||||
|
||||
#define HARNESS_FORK_CHILD_WRITE_PROCESS(processId) \
|
||||
HARNESS_FORK_PIPE(processId)[0][1]
|
||||
|
||||
#define HARNESS_FORK_CHILD_WRITE() \
|
||||
HARNESS_FORK_CHILD_WRITE_PROCESS(HARNESS_FORK_PROCESS_IDX())
|
||||
|
||||
#define HARNESS_FORK_PARENT_READ_PROCESS(processId) \
|
||||
HARNESS_FORK_PIPE(processId)[0][0]
|
||||
|
||||
#define HARNESS_FORK_PARENT_WRITE_PROCESS(processId) \
|
||||
HARNESS_FORK_PIPE(processId)[1][1]
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
At the end of the HARNESS_FORK block the parent will wait for the child to exit. By default an exit code of 0 is expected but that
|
||||
can be modified with the _SET macro
|
||||
can be modified when the child begins.
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS() \
|
||||
HARNESS_FORK_expectedExitCode
|
||||
|
||||
#define HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS_SET(expectedExitStatus) \
|
||||
HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS() = expectedExitStatus;
|
||||
#define HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS(processId) \
|
||||
HARNESS_FORK_expectedExitStatus[processId]
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
HARNESS_FORK_BEGIN()
|
||||
|
||||
Performs the fork and stores the process id.
|
||||
Begin the fork block
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_BEGIN() \
|
||||
{ \
|
||||
pid_t HARNESS_FORK_PROCESS_ID() = fork(); \
|
||||
int HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS() = 0;
|
||||
do \
|
||||
{ \
|
||||
unsigned int HARNESS_FORK_PROCESS_TOTAL() = 0; \
|
||||
pid_t HARNESS_FORK_PROCESS_ID(HARNESS_FORK_CHILD_MAX) = {0}; \
|
||||
int HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS(HARNESS_FORK_CHILD_MAX) = {0}; \
|
||||
bool HARNESS_FORK_PIPE_REQUIRED(HARNESS_FORK_CHILD_MAX) = {0}; \
|
||||
int HARNESS_FORK_PIPE(HARNESS_FORK_CHILD_MAX)[2][2] = {{{0}}};
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
HARNESS_FORK_CHILD()
|
||||
|
||||
Is this the child process?
|
||||
Create a child process
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_CHILD() \
|
||||
if (HARNESS_FORK_PROCESS_ID() == 0)
|
||||
#define HARNESS_FORK_CHILD_BEGIN(expectedExitStatus, pipeRequired) \
|
||||
do \
|
||||
{ \
|
||||
HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS(HARNESS_FORK_PROCESS_TOTAL()) = expectedExitStatus; \
|
||||
\
|
||||
if (pipeRequired) \
|
||||
{ \
|
||||
HARNESS_FORK_PIPE_REQUIRED(HARNESS_FORK_PROCESS_TOTAL()) = true; \
|
||||
\
|
||||
THROW_ON_SYS_ERROR_FMT( \
|
||||
pipe(HARNESS_FORK_PIPE(HARNESS_FORK_PROCESS_TOTAL())[0]) == -1, KernelError, \
|
||||
"unable to create read pipe for child process %u", HARNESS_FORK_PROCESS_TOTAL()); \
|
||||
THROW_ON_SYS_ERROR_FMT( \
|
||||
pipe(HARNESS_FORK_PIPE(HARNESS_FORK_PROCESS_TOTAL())[1]) == -1, KernelError, \
|
||||
"unable to create write pipe for child process %u", HARNESS_FORK_PROCESS_TOTAL()); \
|
||||
} \
|
||||
\
|
||||
HARNESS_FORK_PROCESS_ID(HARNESS_FORK_PROCESS_TOTAL()) = fork(); \
|
||||
\
|
||||
if (HARNESS_FORK_PROCESS_ID(HARNESS_FORK_PROCESS_TOTAL()) == 0) \
|
||||
{ \
|
||||
unsigned int HARNESS_FORK_PROCESS_IDX() = HARNESS_FORK_PROCESS_TOTAL(); \
|
||||
\
|
||||
if (pipeRequired) \
|
||||
{ \
|
||||
close(HARNESS_FORK_PARENT_READ_PROCESS(HARNESS_FORK_PROCESS_IDX())); \
|
||||
close(HARNESS_FORK_PARENT_WRITE_PROCESS(HARNESS_FORK_PROCESS_IDX())); \
|
||||
}
|
||||
|
||||
#define HARNESS_FORK_CHILD_END() \
|
||||
if (HARNESS_FORK_PIPE_REQUIRED(HARNESS_FORK_PROCESS_IDX())) \
|
||||
{ \
|
||||
close(HARNESS_FORK_CHILD_READ()); \
|
||||
close(HARNESS_FORK_CHILD_WRITE()); \
|
||||
} \
|
||||
\
|
||||
exit(0); \
|
||||
} \
|
||||
\
|
||||
HARNESS_FORK_PROCESS_TOTAL()++; \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
HARNESS_FORK_PARENT()
|
||||
|
||||
Is this the parent process?
|
||||
Process in the parent
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_PARENT() \
|
||||
if (HARNESS_FORK_PROCESS_ID() != 0)
|
||||
#define HARNESS_FORK_PARENT_BEGIN() \
|
||||
do \
|
||||
{ \
|
||||
for (unsigned int processIdx = 0; processIdx < HARNESS_FORK_PROCESS_TOTAL(); processIdx++) \
|
||||
{ \
|
||||
if (HARNESS_FORK_PIPE_REQUIRED(processIdx)) \
|
||||
{ \
|
||||
close(HARNESS_FORK_CHILD_READ_PROCESS(processIdx)); \
|
||||
close(HARNESS_FORK_CHILD_WRITE_PROCESS(processIdx)); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define HARNESS_FORK_PARENT_END() \
|
||||
for (unsigned int processIdx = 0; processIdx < HARNESS_FORK_PROCESS_TOTAL(); processIdx++) \
|
||||
{ \
|
||||
if (HARNESS_FORK_PIPE_REQUIRED(processIdx)) \
|
||||
{ \
|
||||
close(HARNESS_FORK_PARENT_READ_PROCESS(processIdx)); \
|
||||
close(HARNESS_FORK_PARENT_WRITE_PROCESS(processIdx)); \
|
||||
} \
|
||||
} \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
/***********************************************************************************************************************************
|
||||
HARNESS_FORK_END()
|
||||
|
||||
Finish the fork block by waiting for the child to exit.
|
||||
End the fork block and check exit status for all child processes
|
||||
***********************************************************************************************************************************/
|
||||
#define HARNESS_FORK_END() \
|
||||
HARNESS_FORK_CHILD() \
|
||||
exit(0); \
|
||||
for (unsigned int processIdx = 0; processIdx < HARNESS_FORK_PROCESS_TOTAL(); processIdx++) \
|
||||
{ \
|
||||
int processStatus; \
|
||||
\
|
||||
HARNESS_FORK_PARENT() \
|
||||
{ \
|
||||
int processStatus; \
|
||||
if (waitpid(HARNESS_FORK_PROCESS_ID(processIdx), &processStatus, 0) != HARNESS_FORK_PROCESS_ID(processIdx)) \
|
||||
THROW_SYS_ERROR_FMT(AssertError, "unable to find child process %u", processIdx); \
|
||||
\
|
||||
if (waitpid(HARNESS_FORK_PROCESS_ID(), &processStatus, 0) != HARNESS_FORK_PROCESS_ID()) \
|
||||
THROW_SYS_ERROR(AssertError, "unable to find child process"); \
|
||||
\
|
||||
if (WEXITSTATUS(processStatus) != HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS()) \
|
||||
THROW_FMT(AssertError, "child exited with error %d", WEXITSTATUS(processStatus)); \
|
||||
if (WEXITSTATUS(processStatus) != HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS(processIdx)) \
|
||||
THROW_FMT(AssertError, "child %u exited with error %d", processIdx, WEXITSTATUS(processStatus)); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
while (0)
|
||||
|
@ -305,10 +305,11 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
TEST_ERROR(cmdArchiveGet(), ParamRequiredError, "WAL segment to get required");
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
@ -320,10 +321,11 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
TEST_ERROR(cmdArchiveGet(), ParamRequiredError, "path to copy WAL segment required");
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
@ -342,7 +344,7 @@ testRun(void)
|
||||
// Test this in a fork so we can use different Perl options in later tests
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
TEST_ERROR_FMT(
|
||||
cmdArchiveGet(), FileMissingError,
|
||||
@ -358,6 +360,7 @@ testRun(void)
|
||||
strPtr(cfgOptionStr(cfgOptRepoPath)), strPtr(cfgOptionStr(cfgOptRepoPath)),
|
||||
strPtr(cfgOptionStr(cfgOptRepoPath)), strPtr(cfgOptionStr(cfgOptRepoPath)));
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
@ -372,7 +375,7 @@ testRun(void)
|
||||
// Test this in a fork so we can use different Perl options in later tests
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
TEST_ERROR_FMT(
|
||||
cmdArchiveGet(), FileMissingError,
|
||||
@ -388,6 +391,7 @@ testRun(void)
|
||||
strPtr(cfgOptionStr(cfgOptRepoPath)), strPtr(cfgOptionStr(cfgOptRepoPath)),
|
||||
strPtr(cfgOptionStr(cfgOptRepoPath)), strPtr(cfgOptionStr(cfgOptRepoPath)));
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
@ -402,10 +406,11 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
TEST_RESULT_INT(cmdArchiveGet(), 1, "timeout getting WAL segment");
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
@ -418,10 +423,11 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
TEST_RESULT_INT(cmdArchiveGet(), 1, "successful get of missing WAL");
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
@ -439,10 +445,11 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
TEST_RESULT_INT(cmdArchiveGet(), 0, "successful get");
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
@ -470,10 +477,11 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
TEST_RESULT_INT(cmdArchiveGet(), 0, "successful get");
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
@ -489,10 +497,11 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
TEST_RESULT_INT(cmdArchiveGet(), 1, "timeout waiting for lock");
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
|
@ -28,11 +28,8 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, true)
|
||||
{
|
||||
close(pipeRead[0]);
|
||||
close(pipeWrite[1]);
|
||||
|
||||
StringList *argList = strLstNew();
|
||||
strLstAddZ(argList, "pgbackrest");
|
||||
strLstAddZ(argList, "--stanza=test1");
|
||||
@ -42,29 +39,22 @@ testRun(void)
|
||||
strLstAddZ(argList, "remote");
|
||||
harnessCfgLoad(strLstSize(argList), strLstPtr(argList));
|
||||
|
||||
cmdRemote(pipeWrite[0], pipeRead[1]);
|
||||
|
||||
close(pipeRead[1]);
|
||||
close(pipeWrite[0]);
|
||||
cmdRemote(HARNESS_FORK_CHILD_READ(), HARNESS_FORK_CHILD_WRITE());
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
|
||||
HARNESS_FORK_PARENT()
|
||||
HARNESS_FORK_PARENT_BEGIN()
|
||||
{
|
||||
close(pipeRead[1]);
|
||||
close(pipeWrite[0]);
|
||||
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("server read"), pipeRead[0], 2000));
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("server read"), HARNESS_FORK_PARENT_READ_PROCESS(0), 2000));
|
||||
ioReadOpen(read);
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("server write"), pipeWrite[1]));
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("server write"), HARNESS_FORK_PARENT_WRITE_PROCESS(0)));
|
||||
ioWriteOpen(write);
|
||||
|
||||
ProtocolClient *client = protocolClientNew(strNew("test"), PROTOCOL_SERVICE_REMOTE_STR, read, write);
|
||||
protocolClientNoOp(client);
|
||||
protocolClientFree(client);
|
||||
|
||||
close(pipeRead[0]);
|
||||
close(pipeWrite[1]);
|
||||
}
|
||||
HARNESS_FORK_PARENT_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
}
|
||||
|
@ -290,12 +290,11 @@ testRun(void)
|
||||
// Test in a fork so the process does not actually exit
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(UnhandledError.code, false)
|
||||
{
|
||||
THROW(TestChildError, "does not get caught!");
|
||||
}
|
||||
|
||||
HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS_SET(UnhandledError.code);
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
}
|
||||
|
@ -29,13 +29,12 @@ testRun(void)
|
||||
{
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(errorTypeCode(&TermError), false)
|
||||
{
|
||||
exitInit();
|
||||
raise(SIGTERM);
|
||||
}
|
||||
|
||||
HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS_SET(errorTypeCode(&TermError));
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
@ -30,6 +30,7 @@ testRun(void)
|
||||
TEST_RESULT_INT(write(STDOUT_FILENO, buffer, strlen(buffer)), -1, "write to stdout fails");
|
||||
TEST_RESULT_INT(write(STDERR_FILENO, buffer, strlen(buffer)), -1, "write to stderr fails");
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
}
|
||||
|
@ -464,22 +464,18 @@ testRun(void)
|
||||
{
|
||||
ioBufferSizeSet(16);
|
||||
|
||||
// Create pipe for testing
|
||||
int pipeTest[2];
|
||||
THROW_ON_SYS_ERROR(pipe(pipeTest) == -1, KernelError, "unable to create test pipe");
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, true)
|
||||
{
|
||||
close(pipeTest[0]);
|
||||
IoHandleWrite *write = NULL;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
TEST_RESULT_VOID(ioHandleWriteMove(NULL, MEM_CONTEXT_OLD()), "move null write");
|
||||
TEST_ASSIGN(
|
||||
write, ioHandleWriteMove(ioHandleWriteNew(strNew("write test"), pipeTest[1]), MEM_CONTEXT_OLD()),
|
||||
write,
|
||||
ioHandleWriteMove(ioHandleWriteNew(strNew("write test"), HARNESS_FORK_CHILD_WRITE()), MEM_CONTEXT_OLD()),
|
||||
"move write");
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
@ -504,20 +500,20 @@ testRun(void)
|
||||
// Free object
|
||||
TEST_RESULT_VOID(ioHandleWriteFree(NULL), "free null write");
|
||||
TEST_RESULT_VOID(ioHandleWriteFree(write), "free write");
|
||||
|
||||
close(pipeTest[1]);
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
|
||||
HARNESS_FORK_PARENT()
|
||||
HARNESS_FORK_PARENT_BEGIN()
|
||||
{
|
||||
close(pipeTest[1]);
|
||||
IoHandleRead *read = NULL;
|
||||
|
||||
MEM_CONTEXT_TEMP_BEGIN()
|
||||
{
|
||||
TEST_RESULT_VOID(ioHandleReadMove(NULL, MEM_CONTEXT_OLD()), "move null read");
|
||||
TEST_ASSIGN(
|
||||
read, ioHandleReadMove(ioHandleReadNew(strNew("read test"), pipeTest[0], 1000), MEM_CONTEXT_OLD()),
|
||||
read,
|
||||
ioHandleReadMove(
|
||||
ioHandleReadNew(strNew("read test"), HARNESS_FORK_PARENT_READ_PROCESS(0), 1000), MEM_CONTEXT_OLD()),
|
||||
"move read");
|
||||
}
|
||||
MEM_CONTEXT_TEMP_END();
|
||||
@ -548,9 +544,8 @@ testRun(void)
|
||||
// Free object
|
||||
TEST_RESULT_VOID(ioHandleReadFree(NULL), "free null read");
|
||||
TEST_RESULT_VOID(ioHandleReadFree(read), "free read");
|
||||
|
||||
close(pipeTest[0]);
|
||||
}
|
||||
HARNESS_FORK_PARENT_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
|
@ -82,13 +82,14 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
TEST_RESULT_BOOL(lockAcquireFile(backupLock, 0, true), true, "lock on fork");
|
||||
sleepMSec(500);
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
|
||||
HARNESS_FORK_PARENT()
|
||||
HARNESS_FORK_PARENT_BEGIN()
|
||||
{
|
||||
sleepMSec(250);
|
||||
TEST_ERROR(
|
||||
@ -99,6 +100,7 @@ testRun(void)
|
||||
"unable to acquire lock on file '%s': Resource temporarily unavailable\n"
|
||||
"HINT: is another pgBackRest process running?", strPtr(backupLock))));
|
||||
}
|
||||
HARNESS_FORK_PARENT_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
}
|
||||
|
@ -20,22 +20,13 @@ testRun(void)
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("configProtocol() and configProtocolOption()"))
|
||||
{
|
||||
// Create pipes for testing. Read/write is from the perspective of the client.
|
||||
int pipeRead[2];
|
||||
int pipeWrite[2];
|
||||
THROW_ON_SYS_ERROR(pipe(pipeRead) == -1, KernelError, "unable to read test pipe");
|
||||
THROW_ON_SYS_ERROR(pipe(pipeWrite) == -1, KernelError, "unable to write test pipe");
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, true)
|
||||
{
|
||||
close(pipeRead[0]);
|
||||
close(pipeWrite[1]);
|
||||
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("client read"), pipeWrite[0], 2000));
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("client read"), HARNESS_FORK_CHILD_READ(), 2000));
|
||||
ioReadOpen(read);
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("client write"), pipeRead[1]));
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("client write"), HARNESS_FORK_CHILD_WRITE()));
|
||||
ioWriteOpen(write);
|
||||
|
||||
StringList *argList = strLstNew();
|
||||
@ -49,19 +40,14 @@ testRun(void)
|
||||
ProtocolServer *server = protocolServerNew(strNew("test"), strNew("config"), read, write);
|
||||
protocolServerHandlerAdd(server, configProtocol);
|
||||
protocolServerProcess(server);
|
||||
|
||||
close(pipeRead[1]);
|
||||
close(pipeWrite[0]);
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
|
||||
HARNESS_FORK_PARENT()
|
||||
HARNESS_FORK_PARENT_BEGIN()
|
||||
{
|
||||
close(pipeRead[1]);
|
||||
close(pipeWrite[0]);
|
||||
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("server read"), pipeRead[0], 2000));
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("server read"), HARNESS_FORK_PARENT_READ_PROCESS(0), 2000));
|
||||
ioReadOpen(read);
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("server write"), pipeWrite[1]));
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("server write"), HARNESS_FORK_PARENT_WRITE_PROCESS(0)));
|
||||
ioWriteOpen(write);
|
||||
|
||||
ProtocolClient *client = protocolClientNew(strNew("test"), strNew("config"), read, write);
|
||||
@ -75,10 +61,8 @@ testRun(void)
|
||||
"get options");
|
||||
|
||||
protocolClientFree(client);
|
||||
|
||||
close(pipeRead[0]);
|
||||
close(pipeWrite[1]);
|
||||
}
|
||||
HARNESS_FORK_PARENT_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
}
|
||||
|
@ -137,14 +137,11 @@ testRun(void)
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, true)
|
||||
{
|
||||
close(pipeRead[0]);
|
||||
close(pipeWrite[1]);
|
||||
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("server read"), pipeWrite[0], 2000));
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("server read"), HARNESS_FORK_CHILD_READ(), 2000));
|
||||
ioReadOpen(read);
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("server write"), pipeRead[1]));
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("server write"), HARNESS_FORK_CHILD_WRITE()));
|
||||
ioWriteOpen(write);
|
||||
|
||||
// Various bogus greetings
|
||||
@ -190,19 +187,14 @@ testRun(void)
|
||||
|
||||
// Wait for exit
|
||||
TEST_RESULT_STR(strPtr(ioReadLine(read)), "{\"cmd\":\"exit\"}", "exit command");
|
||||
|
||||
close(pipeRead[1]);
|
||||
close(pipeWrite[0]);
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
|
||||
HARNESS_FORK_PARENT()
|
||||
HARNESS_FORK_PARENT_BEGIN()
|
||||
{
|
||||
close(pipeRead[1]);
|
||||
close(pipeWrite[0]);
|
||||
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("client read"), pipeRead[0], 2000));
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("client read"), HARNESS_FORK_PARENT_READ_PROCESS(0), 2000));
|
||||
ioReadOpen(read);
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("client write"), pipeWrite[1]));
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("client write"), HARNESS_FORK_PARENT_WRITE_PROCESS(0)));
|
||||
ioWriteOpen(write);
|
||||
|
||||
// Various bogus greetings
|
||||
@ -259,10 +251,8 @@ testRun(void)
|
||||
// Free client
|
||||
TEST_RESULT_VOID(protocolClientFree(client), "free client");
|
||||
TEST_RESULT_VOID(protocolClientFree(NULL), "free null client");
|
||||
|
||||
close(pipeRead[0]);
|
||||
close(pipeWrite[1]);
|
||||
}
|
||||
HARNESS_FORK_PARENT_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
}
|
||||
@ -270,22 +260,13 @@ testRun(void)
|
||||
// *****************************************************************************************************************************
|
||||
if (testBegin("ProtocolServer"))
|
||||
{
|
||||
// Create pipes for testing. Read/write is from the perspective of the client.
|
||||
int pipeRead[2];
|
||||
int pipeWrite[2];
|
||||
THROW_ON_SYS_ERROR(pipe(pipeRead) == -1, KernelError, "unable to read test pipe");
|
||||
THROW_ON_SYS_ERROR(pipe(pipeWrite) == -1, KernelError, "unable to write test pipe");
|
||||
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, true)
|
||||
{
|
||||
close(pipeRead[0]);
|
||||
close(pipeWrite[1]);
|
||||
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("client read"), pipeWrite[0], 2000));
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("client read"), HARNESS_FORK_CHILD_READ(), 2000));
|
||||
ioReadOpen(read);
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("client write"), pipeRead[1]));
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("client write"), HARNESS_FORK_CHILD_WRITE()));
|
||||
ioWriteOpen(write);
|
||||
|
||||
// Check greeting
|
||||
@ -321,19 +302,14 @@ testRun(void)
|
||||
// Exit
|
||||
TEST_RESULT_VOID(ioWriteLine(write, strNew("{\"cmd\":\"exit\"}")), "write exit");
|
||||
TEST_RESULT_VOID(ioWriteFlush(write), "flush exit");
|
||||
|
||||
close(pipeRead[1]);
|
||||
close(pipeWrite[0]);
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
|
||||
HARNESS_FORK_PARENT()
|
||||
HARNESS_FORK_PARENT_BEGIN()
|
||||
{
|
||||
close(pipeRead[1]);
|
||||
close(pipeWrite[0]);
|
||||
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("server read"), pipeRead[0], 2000));
|
||||
IoRead *read = ioHandleReadIo(ioHandleReadNew(strNew("server read"), HARNESS_FORK_PARENT_READ_PROCESS(0), 2000));
|
||||
ioReadOpen(read);
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("server write"), pipeWrite[1]));
|
||||
IoWrite *write = ioHandleWriteIo(ioHandleWriteNew(strNew("server write"), HARNESS_FORK_PARENT_WRITE_PROCESS(0)));
|
||||
ioWriteOpen(write);
|
||||
|
||||
// Send greeting
|
||||
@ -360,10 +336,8 @@ testRun(void)
|
||||
|
||||
TEST_RESULT_VOID(protocolServerFree(server), "free server");
|
||||
TEST_RESULT_VOID(protocolServerFree(NULL), "free null server");
|
||||
|
||||
close(pipeRead[0]);
|
||||
close(pipeWrite[1]);
|
||||
}
|
||||
HARNESS_FORK_PARENT_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
}
|
||||
|
@ -156,16 +156,18 @@ testRun(void)
|
||||
// -------------------------------------------------------------------------------------------------------------------------
|
||||
HARNESS_FORK_BEGIN()
|
||||
{
|
||||
HARNESS_FORK_CHILD()
|
||||
HARNESS_FORK_CHILD_BEGIN(0, false)
|
||||
{
|
||||
sleepMSec(250);
|
||||
TEST_RESULT_INT(system(strPtr(strNewFmt("touch %s", strPtr(fileExists)))), 0, "create exists file");
|
||||
}
|
||||
HARNESS_FORK_CHILD_END();
|
||||
|
||||
HARNESS_FORK_PARENT()
|
||||
HARNESS_FORK_PARENT_BEGIN()
|
||||
{
|
||||
TEST_RESULT_BOOL(storageExistsP(storageTest, fileExists, .timeout = 1000), true, "file exists after wait");
|
||||
}
|
||||
HARNESS_FORK_PARENT_END();
|
||||
}
|
||||
HARNESS_FORK_END();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user