Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #596, scrub all UT_Report calls #1624

Merged
merged 10 commits into from
Jun 23, 2021
153 changes: 94 additions & 59 deletions modules/core_private/ut-stubs/inc/ut_support.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,43 +235,6 @@ void UT_ResetCDS(void);
/* Reset pool buffer array index */
void UT_ResetPoolBufferIndex(void);

/*****************************************************************************/
/**
** \brief Output single test's pass/fail status
**
** \par Description
** Out the results and description for a single test, and update the
** pass/fail counters.
**
** \par Assumptions, External Events, and Notes:
**
** \param[in] test Equals 0 if the test failed; non-zero if the
** test passed
**
** \param[in] fun_name Character string pointer to the name of the function
** being tested
**
** \param[in] info Character string pointer to the description of the test
**
** \returns
** This function does not return a value.
**
******************************************************************************/
void UT_Report(const char *file, uint32 line, bool test, const char *fun_name, const char *info);

/*****************************************************************************/
/**
** \brief Test pass/fail summary
**
** \par Description
** Output total number of tests passed and failed.
**
** \returns
** This function does not return a value.
**
******************************************************************************/
void UT_ReportFailures(void);

/*****************************************************************************/
/**
** \brief Send a message via the software bus
Expand Down Expand Up @@ -648,6 +611,44 @@ void UT_AddSubTest(void (*Test)(void), void (*Setup)(void), void (*Teardown)(voi
bool CFE_UtAssert_SuccessCheck_Impl(CFE_Status_t Status, UtAssert_CaseType_t CaseType, const char *File, uint32 Line,
const char *Text);

/*****************************************************************************/
/**
** \brief Helper function for message check (printf/syslog) verifications
**
** \par Description
** This helper function wraps the normal UtAssert function, intended for verifying
** CFE API calls that are expected to generate printf or syslog messages. This
** includes the actual message in the log, but scrubs it for newlines and other
** items that may affect the ability to parse the log file via a script.
**
** \par Assumptions, External Events, and Notes:
** None
**
** \returns Test pass status, returns true if status was successful, false if it failed.
**
******************************************************************************/
bool CFE_UtAssert_MessageCheck_Impl(bool Status, const char *File, uint32 Line, const char *Desc,
const char *FormatString);

/*****************************************************************************/
/**
** \brief Helper function for string buffer check verifications
**
** \par Description
** This helper function wraps the normal UtAssert function, intended for verifying
** the contents of string buffer(s). This also includes the actual message in the log,
** but scrubs it for newlines and other items that may affect the ability to parse
** the log file via a script.
**
** \par Assumptions, External Events, and Notes:
** None
**
** \returns Test pass status, returns true if status was successful, false if it failed.
**
******************************************************************************/
bool CFE_UtAssert_StringBufCheck_Impl(const char *String1, size_t String1Max, const char *String2, size_t String2Max,
const char *File, uint32 Line);

/*****************************************************************************/
/**
** \brief Helper function for generic unsigned integer value checks
Expand Down Expand Up @@ -718,22 +719,6 @@ bool CFE_UtAssert_GenericSignedCompare_Impl(int32 ActualValue, CFE_UtAssert_Comp
******************************************************************************/
#define CFE_UtAssert_SUCCESS(FN) CFE_UtAssert_SuccessCheck_Impl(FN, UTASSERT_CASETYPE_FAILURE, __FILE__, __LINE__, #FN)

/*****************************************************************************/
/**
** \brief Asserts the specific status code from the function being tested.
**
** \par Description
** The core of each unit test is the execution of the function being tested.
** This function and macro should be used to test for a specific status code
** from a function (typically an error case).
**
** \par Assumptions, External Events, and Notes:
** None
**
******************************************************************************/
#define CFE_UtAssert_EQUAL(FN, EXP) \
CFE_UtAssert_GenericSignedCompare_Impl(FN, CFE_UtAssert_Compare_EQ, EXP, __FILE__, __LINE__, "", #FN, #EXP)

/*****************************************************************************/
/**
** \brief Asserts the expression/function evaluates as logically true
Expand Down Expand Up @@ -860,9 +845,8 @@ bool CFE_UtAssert_GenericSignedCompare_Impl(int32 ActualValue, CFE_UtAssert_Comp
** is potentially useful to confirm a specific code path was followed.
**
******************************************************************************/
#define CFE_UtAssert_SYSLOG(str) \
CFE_UtAssert_GenericSignedCompare_Impl(UT_SyslogIsInHistory(str), CFE_UtAssert_Compare_GT, 0, __FILE__, __LINE__, \
"Syslog generated: ", #str, "")
#define CFE_UtAssert_SYSLOG(str) \
CFE_UtAssert_MessageCheck_Impl(UT_SyslogIsInHistory(str), __FILE__, __LINE__, "Syslog generated: ", str)

/*****************************************************************************/
/**
Expand All @@ -876,9 +860,8 @@ bool CFE_UtAssert_GenericSignedCompare_Impl(int32 ActualValue, CFE_UtAssert_Comp
** is potentially useful to confirm a specific code path was followed.
**
******************************************************************************/
#define CFE_UtAssert_PRINTF(str) \
CFE_UtAssert_GenericSignedCompare_Impl(UT_PrintfIsInHistory(str), CFE_UtAssert_Compare_GT, 0, __FILE__, __LINE__, \
"Printf generated: ", #str, "")
#define CFE_UtAssert_PRINTF(str) \
CFE_UtAssert_MessageCheck_Impl(UT_PrintfIsInHistory(str), __FILE__, __LINE__, "Printf generated: ", str)

/*****************************************************************************/
/**
Expand Down Expand Up @@ -927,4 +910,56 @@ bool CFE_UtAssert_GenericSignedCompare_Impl(int32 ActualValue, CFE_UtAssert_Comp
CFE_RESOURCEID_TO_ULONG(id2), __FILE__, __LINE__, \
"Resource ID Check: ", #id1, #id2)

/*****************************************************************************/
/**
** \brief Macro to check CFE memory size/offset for equality
**
** \par Description
** A macro that checks two memory offset/size values for equality.
**
** \par Assumptions, External Events, and Notes:
** This is a simple unsigned comparison which logs the values as hexadecimal
**
******************************************************************************/
#define CFE_UtAssert_MEMOFFSET_EQ(off1, off2) \
CFE_UtAssert_GenericUnsignedCompare_Impl(off1, CFE_UtAssert_Compare_EQ, off2, __FILE__, __LINE__, \
"Offset Check: ", #off1, #off2)

/*****************************************************************************/
/**
** \brief Macro to check CFE message ID for equality
**
** \par Description
** A macro that checks two message ID values for equality.
**
** \par Assumptions, External Events, and Notes:
** The generic #UtAssert_UINT32_EQ check should not be used, as CFE_SB_MsgId_t values
** and integers may not be interchangable with strict type checking.
**
******************************************************************************/
#define CFE_UtAssert_MSGID_EQ(mid1, mid2) \
CFE_UtAssert_GenericUnsignedCompare_Impl(CFE_SB_MsgIdToValue(mid1), CFE_UtAssert_Compare_EQ, \
CFE_SB_MsgIdToValue(mid2), __FILE__, __LINE__, "MsgId Check: ", #mid1, \
#mid2)

/*****************************************************************************/
/**
** \brief Macro to check string buffers for equality
**
** \par Description
** A macro that checks two string buffers for equality. Both buffer maximum sizes are explicitly
** specified, so that strings may reside in a fixed length buffer. The function will never
** check beyond the specified length, regardless of termination.
**
** \par Assumptions, External Events, and Notes:
** The generic #UtAssert_StrCmp macro requires both arguments to be NULL terminated. This also
** includes the actual string in the log, but filters embedded newlines to keep the log clean.
**
** If the string arguments are guaranteed to be NULL terminated and/or the max size is
** not known, then the SIZE_MAX constant may be passed for the respective string.
**
******************************************************************************/
#define CFE_UtAssert_STRINGBUF_EQ(str1, size1, str2, size2) \
CFE_UtAssert_StringBufCheck_Impl(str1, size1, str2, size2, __FILE__, __LINE__)

#endif /* UT_SUPPORT_H */
137 changes: 129 additions & 8 deletions modules/core_private/ut-stubs/src/ut_support.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,6 @@ void UT_ResetPoolBufferIndex(void)
UT_SetDataBuffer(UT_KEY(CFE_ES_GetPoolBuf), &UT_CFE_ES_MemoryPool, sizeof(UT_CFE_ES_MemoryPool), false);
}

/*
** Output single test's pass/fail status
*/
void UT_Report(const char *file, uint32 line, bool test, const char *fun_name, const char *info)
{
UtAssertEx(test, UtAssert_GetContext(), file, line, "%s - %s", fun_name, info);
}

/*
** Calls the specified "task pipe" function
**
Expand Down Expand Up @@ -826,3 +818,132 @@ bool CFE_UtAssert_GenericSignedCompare_Impl(int32 ActualValue, CFE_UtAssert_Comp
return UtAssertEx(Result, UTASSERT_CASETYPE_FAILURE, File, Line, "%s%s (%ld) %s %s (%ld)", Desc, ActualText,
(long)ActualValue, CFE_UtAssert_GetOpText(CompareType), ReferenceText, (long)ReferenceValue);
}

bool CFE_UtAssert_MessageCheck_Impl(bool Status, const char *File, uint32 Line, const char *Desc,
const char *FormatString)
{
char ScrubbedFormat[256];
const char *EndPtr;
size_t FormatLen;

/* Locate the actual end of the string, but limited to length of local buffer */
/* Reserve two extra chars for quotes */
EndPtr = memchr(FormatString, 0, sizeof(ScrubbedFormat) - 2);
if (EndPtr != NULL)
{
FormatLen = EndPtr - FormatString;
}
else
{
FormatLen = sizeof(ScrubbedFormat) - 3;
}

/* Check for a newline within that range, and if present, end the string there instead */
EndPtr = memchr(FormatString, '\n', FormatLen);
if (EndPtr != NULL)
{
FormatLen = EndPtr - FormatString;
}

/* Need to make a copy, as the input string is "const" */
ScrubbedFormat[0] = '\'';
memcpy(&ScrubbedFormat[1], FormatString, FormatLen);
ScrubbedFormat[FormatLen] = '\'';
ScrubbedFormat[FormatLen + 1] = 0;

return CFE_UtAssert_GenericSignedCompare_Impl(Status, CFE_UtAssert_Compare_GT, 0, File, Line, Desc, ScrubbedFormat,
"");
}

bool CFE_UtAssert_StringBufCheck_Impl(const char *String1, size_t String1Max, const char *String2, size_t String2Max,
const char *File, uint32 Line)
{
char ScrubbedString1[256];
char ScrubbedString2[256];
const char *EndPtr1;
const char *EndPtr2;
size_t FormatLen1;
size_t FormatLen2;
bool Result;

/* Locate the actual end of both strings */
if (String1 == NULL)
{
EndPtr1 = NULL;
}
else
{
EndPtr1 = memchr(String1, 0, String1Max);
}

if (EndPtr1 != NULL)
{
FormatLen1 = EndPtr1 - String1;
}
else
{
FormatLen1 = String1Max;
}

if (String2 == NULL)
{
EndPtr2 = NULL;
}
else
{
EndPtr2 = memchr(String2, 0, String2Max);
}

if (EndPtr2 != NULL)
{
FormatLen2 = EndPtr2 - String2;
}
else
{
FormatLen2 = String2Max;
}

if (FormatLen1 != FormatLen2)
{
/* This means the strings have different termination/length, and therefore must not be equal (content doesn't
* matter) */
Result = false;
}
else if (FormatLen1 == 0)
{
/* Two empty strings are considered equal */
Result = true;
}
else
{
/* If the effective lengths are the same, use memcmp to check content */
Result = (memcmp(String1, String2, FormatLen1) == 0);
}

/* Now make "safe" copies of the strings */
/* Check for a newline within the string, and if present, end the string there instead */
if (FormatLen1 > 0)
{
EndPtr1 = memchr(String1, '\n', FormatLen1);
if (EndPtr1 != NULL)
{
FormatLen1 = EndPtr1 - String1;
}
memcpy(ScrubbedString1, String1, FormatLen1);
}
ScrubbedString1[FormatLen1] = 0;

if (FormatLen2 > 0)
{
EndPtr2 = memchr(String2, '\n', FormatLen2);
if (EndPtr2 != NULL)
{
FormatLen2 = EndPtr2 - String2;
}
memcpy(ScrubbedString2, String2, FormatLen2);
}
ScrubbedString2[FormatLen2] = 0;

return UtAssertEx(Result, UTASSERT_CASETYPE_FAILURE, File, Line, "String: \'%s\' == \'%s\'", ScrubbedString1,
ScrubbedString2);
}
Loading