2017-10-16 10:09:56 -04:00
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Test Error Handling
|
|
|
|
***********************************************************************************************************************************/
|
2018-03-12 14:31:22 -04:00
|
|
|
#include <assert.h>
|
2018-05-06 08:56:42 -04:00
|
|
|
|
|
|
|
#include "common/harnessFork.h"
|
2018-05-05 09:38:09 -04:00
|
|
|
|
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Declare some error locally because real errors won't work for some tests -- they could also break as errors change
|
|
|
|
***********************************************************************************************************************************/
|
|
|
|
ERROR_DECLARE(TestParent1Error);
|
|
|
|
ERROR_DECLARE(TestParent2Error);
|
|
|
|
ERROR_DECLARE(TestChildError);
|
|
|
|
|
|
|
|
ERROR_DEFINE(101, TestParent1Error, TestParent1Error);
|
|
|
|
ERROR_DEFINE(102, TestParent2Error, TestParent1Error);
|
|
|
|
ERROR_DEFINE(200, TestChildError, TestParent2Error);
|
2017-10-16 10:09:56 -04:00
|
|
|
|
|
|
|
/***********************************************************************************************************************************
|
|
|
|
testTryRecurse - test to blow up try stack
|
|
|
|
***********************************************************************************************************************************/
|
2017-11-19 16:44:33 -05:00
|
|
|
volatile int testTryRecurseTotal = 0;
|
2017-10-16 10:09:56 -04:00
|
|
|
bool testTryRecurseCatch = false;
|
|
|
|
bool testTryRecurseFinally = false;
|
|
|
|
|
2018-01-31 18:22:25 -05:00
|
|
|
void
|
2018-08-03 19:19:14 -04:00
|
|
|
testTryRecurse(void)
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_BEGIN()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
testTryRecurseTotal++;
|
|
|
|
assert(errorContext.tryTotal == testTryRecurseTotal + 1);
|
|
|
|
|
|
|
|
testTryRecurse();
|
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
CATCH(MemoryError)
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
testTryRecurseCatch = true; // {uncoverable - catch should never be executed}
|
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
FINALLY()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
testTryRecurseFinally = true;
|
|
|
|
}
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_END();
|
2017-10-16 10:09:56 -04:00
|
|
|
} // {uncoverable - function throws error, never returns}
|
|
|
|
|
|
|
|
/***********************************************************************************************************************************
|
|
|
|
Test Run
|
|
|
|
***********************************************************************************************************************************/
|
2018-01-31 18:22:25 -05:00
|
|
|
void
|
2018-08-03 19:19:14 -04:00
|
|
|
testRun(void)
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
2018-05-18 11:57:32 -04:00
|
|
|
FUNCTION_HARNESS_VOID();
|
|
|
|
|
2018-05-05 09:38:09 -04:00
|
|
|
// *****************************************************************************************************************************
|
2017-10-16 10:09:56 -04:00
|
|
|
if (testBegin("check that try stack is initialized correctly"))
|
|
|
|
{
|
|
|
|
assert(errorContext.tryTotal == 0);
|
|
|
|
}
|
|
|
|
|
2018-05-05 09:38:09 -04:00
|
|
|
// *****************************************************************************************************************************
|
|
|
|
if (testBegin("errorTypeExtends"))
|
|
|
|
{
|
|
|
|
assert(errorTypeExtends(&TestParent1Error, &TestParent1Error));
|
|
|
|
assert(errorTypeExtends(&TestChildError, &TestParent1Error));
|
|
|
|
assert(errorTypeExtends(&TestChildError, &TestParent2Error));
|
|
|
|
assert(!errorTypeExtends(&TestChildError, &TestChildError));
|
|
|
|
}
|
|
|
|
|
|
|
|
// *****************************************************************************************************************************
|
2017-11-19 16:30:23 -05:00
|
|
|
if (testBegin("TRY with no errors"))
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
2017-11-19 16:44:33 -05:00
|
|
|
volatile bool tryDone = false;
|
2017-10-16 10:09:56 -04:00
|
|
|
bool catchDone = false;
|
|
|
|
bool finallyDone = false;
|
|
|
|
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_BEGIN()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
assert(errorContext.tryTotal == 1);
|
|
|
|
tryDone = true;
|
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
CATCH_ANY()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
catchDone = true; // {uncoverable - catch should never be executed}
|
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
FINALLY()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
assert(errorContext.tryList[1].state == errorStateFinal);
|
|
|
|
finallyDone = true;
|
|
|
|
}
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_END();
|
2017-10-16 10:09:56 -04:00
|
|
|
|
|
|
|
assert(tryDone);
|
|
|
|
assert(!catchDone);
|
|
|
|
assert(finallyDone);
|
|
|
|
assert(errorContext.tryTotal == 0);
|
|
|
|
}
|
|
|
|
|
2018-05-05 09:38:09 -04:00
|
|
|
// *****************************************************************************************************************************
|
2017-11-19 16:30:23 -05:00
|
|
|
if (testBegin("TRY with multiple catches"))
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
2017-11-19 16:44:33 -05:00
|
|
|
volatile bool tryDone = false;
|
|
|
|
volatile bool catchDone = false;
|
|
|
|
volatile bool finallyDone = false;
|
2017-10-16 10:09:56 -04:00
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
assert(errorTryDepth() == 0);
|
|
|
|
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_BEGIN()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
2018-05-18 11:57:32 -04:00
|
|
|
assert(errorTryDepth() == 1);
|
2017-10-16 10:09:56 -04:00
|
|
|
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_BEGIN()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
2018-05-18 11:57:32 -04:00
|
|
|
assert(errorTryDepth() == 2);
|
2017-10-16 10:09:56 -04:00
|
|
|
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_BEGIN()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
2018-05-18 11:57:32 -04:00
|
|
|
assert(errorTryDepth() == 3);
|
2017-10-16 10:09:56 -04:00
|
|
|
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_BEGIN()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
2018-05-18 11:57:32 -04:00
|
|
|
assert(errorTryDepth() == 4);
|
2017-10-16 10:09:56 -04:00
|
|
|
tryDone = true;
|
|
|
|
|
2018-05-21 08:06:31 -04:00
|
|
|
char bigMessage[sizeof(messageBuffer) * 32];
|
|
|
|
memset(bigMessage, 'A', sizeof(bigMessage));
|
|
|
|
|
|
|
|
THROW(AssertError, bigMessage);
|
2017-10-16 10:09:56 -04:00
|
|
|
}
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_END();
|
2017-10-16 10:09:56 -04:00
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
CATCH(AssertError)
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
// Finally below should run even though this error has been rethrown
|
2017-11-13 21:22:13 -05:00
|
|
|
RETHROW();
|
2017-10-16 10:09:56 -04:00
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
FINALLY()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
finallyDone = true;
|
|
|
|
}
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_END();
|
2017-10-16 10:09:56 -04:00
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
CATCH_ANY()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
2017-11-13 21:22:13 -05:00
|
|
|
RETHROW();
|
2017-10-16 10:09:56 -04:00
|
|
|
}
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_END();
|
2017-10-16 10:09:56 -04:00
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
CATCH(MemoryError)
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
assert(false); // {uncoverable - catch should never be executed}
|
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
CATCH(RuntimeError)
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
2018-05-18 11:57:32 -04:00
|
|
|
assert(errorTryDepth() == 1);
|
2017-10-16 10:09:56 -04:00
|
|
|
assert(errorContext.tryList[1].state == errorStateCatch);
|
2018-05-21 08:06:31 -04:00
|
|
|
assert(strlen(errorMessage()) == sizeof(messageBuffer) - 1);
|
2017-10-16 10:09:56 -04:00
|
|
|
|
|
|
|
catchDone = true;
|
|
|
|
}
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_END();
|
2017-10-16 10:09:56 -04:00
|
|
|
|
2018-05-18 11:57:32 -04:00
|
|
|
assert(errorTryDepth() == 0);
|
|
|
|
|
2017-10-16 10:09:56 -04:00
|
|
|
assert(tryDone);
|
|
|
|
assert(catchDone);
|
|
|
|
assert(finallyDone);
|
|
|
|
assert(errorContext.tryTotal == 0);
|
|
|
|
}
|
|
|
|
|
2018-05-05 09:38:09 -04:00
|
|
|
// *****************************************************************************************************************************
|
2017-10-16 10:09:56 -04:00
|
|
|
if (testBegin("too deep recursive TRY_ERROR()"))
|
|
|
|
{
|
2017-11-19 16:44:33 -05:00
|
|
|
volatile bool tryDone = false;
|
2017-10-16 10:09:56 -04:00
|
|
|
bool catchDone = false;
|
|
|
|
bool finallyDone = false;
|
|
|
|
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_BEGIN()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
tryDone = true;
|
|
|
|
testTryRecurse();
|
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
CATCH(AssertError)
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
assert(errorCode() == AssertError.code);
|
2018-05-18 11:57:32 -04:00
|
|
|
assert(strcmp(errorFileName(), "module/common/errorTest.c") == 0);
|
|
|
|
assert(strcmp(errorFunctionName(), "testTryRecurse") == 0);
|
|
|
|
assert(errorFileLine() == 29);
|
|
|
|
assert(
|
|
|
|
strcmp(errorStackTrace(), "module/common/errorTest:testTryRecurse:29:(test build required for parameters)") == 0);
|
2017-10-16 10:09:56 -04:00
|
|
|
assert(strcmp(errorMessage(), "too many nested try blocks") == 0);
|
|
|
|
assert(strcmp(errorName(), AssertError.name) == 0);
|
|
|
|
assert(errorType() == &AssertError);
|
|
|
|
assert(errorTypeCode(errorType()) == AssertError.code);
|
|
|
|
assert(strcmp(errorTypeName(errorType()), AssertError.name) == 0);
|
2018-05-18 11:57:32 -04:00
|
|
|
|
2017-10-16 10:09:56 -04:00
|
|
|
catchDone = true;
|
|
|
|
}
|
2017-11-13 21:22:13 -05:00
|
|
|
FINALLY()
|
2017-10-16 10:09:56 -04:00
|
|
|
{
|
|
|
|
finallyDone = true;
|
|
|
|
}
|
2017-11-19 16:30:23 -05:00
|
|
|
TRY_END();
|
2017-10-16 10:09:56 -04:00
|
|
|
|
|
|
|
assert(tryDone);
|
|
|
|
assert(catchDone);
|
|
|
|
assert(finallyDone);
|
|
|
|
assert(errorContext.tryTotal == 0);
|
|
|
|
|
|
|
|
// This is only ERROR_TRY_MAX - 1 because one try was used up by the wrapper above the recursive function
|
|
|
|
assert(testTryRecurseTotal == ERROR_TRY_MAX - 1);
|
|
|
|
assert(!testTryRecurseCatch);
|
|
|
|
assert(testTryRecurseFinally);
|
|
|
|
}
|
2018-01-16 13:29:27 -05:00
|
|
|
|
2018-05-05 09:38:09 -04:00
|
|
|
// *****************************************************************************************************************************
|
2018-05-03 11:24:29 -04:00
|
|
|
if (testBegin("THROW_CODE() and THROW_CODE_FMT()"))
|
2018-01-16 13:29:27 -05:00
|
|
|
{
|
|
|
|
TRY_BEGIN()
|
|
|
|
{
|
|
|
|
THROW_CODE(25, "message");
|
|
|
|
}
|
|
|
|
CATCH_ANY()
|
|
|
|
{
|
|
|
|
assert(errorCode() == 25);
|
|
|
|
assert(strcmp(errorMessage(), "message") == 0);
|
|
|
|
}
|
|
|
|
TRY_END();
|
|
|
|
|
2018-05-03 11:24:29 -04:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TRY_BEGIN()
|
|
|
|
{
|
|
|
|
THROW_CODE_FMT(122, "message %d", 1);
|
|
|
|
}
|
|
|
|
CATCH_ANY()
|
|
|
|
{
|
|
|
|
assert(errorCode() == 122);
|
|
|
|
assert(strcmp(errorMessage(), "message 1") == 0);
|
|
|
|
}
|
|
|
|
TRY_END();
|
|
|
|
|
2018-01-16 13:29:27 -05:00
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TRY_BEGIN()
|
|
|
|
{
|
|
|
|
THROW_CODE(777, "message");
|
|
|
|
}
|
|
|
|
CATCH_ANY()
|
|
|
|
{
|
|
|
|
assert(errorCode() == AssertError.code);
|
|
|
|
assert(strcmp(errorMessage(), "could not find error type for code '777'") == 0);
|
|
|
|
}
|
|
|
|
TRY_END();
|
|
|
|
}
|
|
|
|
|
2018-05-05 09:38:09 -04:00
|
|
|
// *****************************************************************************************************************************
|
2018-05-03 11:24:29 -04:00
|
|
|
if (testBegin("THROW_SYS_ERROR() and THROW_SYS_ERROR_FMT()"))
|
2018-01-16 13:29:27 -05:00
|
|
|
{
|
|
|
|
TRY_BEGIN()
|
|
|
|
{
|
|
|
|
errno = E2BIG;
|
2018-03-24 14:11:29 -04:00
|
|
|
THROW_SYS_ERROR(AssertError, "message");
|
2018-01-16 13:29:27 -05:00
|
|
|
}
|
|
|
|
CATCH_ANY()
|
|
|
|
{
|
|
|
|
printf("%s\n", errorMessage());
|
|
|
|
assert(errorCode() == AssertError.code);
|
|
|
|
assert(strcmp(errorMessage(), "message: [7] Argument list too long") == 0);
|
|
|
|
}
|
|
|
|
TRY_END();
|
2018-05-03 11:24:29 -04:00
|
|
|
|
|
|
|
// -------------------------------------------------------------------------------------------------------------------------
|
|
|
|
TRY_BEGIN()
|
|
|
|
{
|
|
|
|
errno = EIO;
|
|
|
|
THROW_SYS_ERROR_FMT(AssertError, "message %d", 1);
|
|
|
|
}
|
|
|
|
CATCH_ANY()
|
|
|
|
{
|
|
|
|
printf("%s\n", errorMessage());
|
|
|
|
assert(errorCode() == AssertError.code);
|
|
|
|
assert(strcmp(errorMessage(), "message 1: [5] Input/output error") == 0);
|
|
|
|
}
|
|
|
|
TRY_END();
|
2018-01-16 13:29:27 -05:00
|
|
|
}
|
2018-05-05 09:38:09 -04:00
|
|
|
|
|
|
|
// *****************************************************************************************************************************
|
|
|
|
if (testBegin("Uncaught error"))
|
|
|
|
{
|
|
|
|
// Test in a fork so the process does not actually exit
|
2018-05-06 08:56:42 -04:00
|
|
|
HARNESS_FORK_BEGIN()
|
2018-05-05 09:38:09 -04:00
|
|
|
{
|
2018-05-06 08:56:42 -04:00
|
|
|
HARNESS_FORK_CHILD()
|
|
|
|
{
|
|
|
|
THROW(TestChildError, "does not get caught!");
|
|
|
|
}
|
2018-05-05 09:38:09 -04:00
|
|
|
|
2018-05-06 08:56:42 -04:00
|
|
|
HARNESS_FORK_CHILD_EXPECTED_EXIT_STATUS_SET(UnhandledError.code);
|
2018-05-05 09:38:09 -04:00
|
|
|
}
|
2018-05-06 08:56:42 -04:00
|
|
|
HARNESS_FORK_END();
|
2018-05-05 09:38:09 -04:00
|
|
|
}
|
2018-05-18 11:57:32 -04:00
|
|
|
|
|
|
|
FUNCTION_HARNESS_RESULT_VOID();
|
2017-10-16 10:09:56 -04:00
|
|
|
}
|