Skip to content

Commit

Permalink
Fix #1625, add test log file
Browse files Browse the repository at this point in the history
Add cfe_assert capability to "tee" all test log output to a file
in addition to the regular output (console/event).

This aids in scripting and automation, by creating a file containing
only test results, not intermixed with other info, and not subject
to the length limitations of events.
  • Loading branch information
jphickey committed Jun 22, 2021
1 parent da76015 commit 0cd4cbe
Show file tree
Hide file tree
Showing 7 changed files with 150 additions and 0 deletions.
36 changes: 36 additions & 0 deletions modules/cfe_assert/inc/cfe_assert.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,40 @@ void CFE_Assert_ExecuteTest(void);
*/
void CFE_Assert_RegisterCallback(CFE_Assert_StatusCallback_t Callback);

/************************************************************************/
/** \brief Start a test log file
*
* \par Description
* Sets the name of a file which will store the results of all tests
* The output is saved to the log file in addition to the normal callback
* function provided in CFE_Assert_RegisterCallback().
*
* \par Assumptions, External Events, and Notes:
* Only the test outputs are saved to this log file, thereby providing
* a file that can be checked by a script. During test operation, the
* file is first created with a "tmp" extension, and then will be renamed
* to the name given here once the test is complete.
*
* \param[in] Filename Name of log file to write
*
* \return CFE Status code
* \retval #CFE_SUCCESS if file was opened successfully
*
*/
int32 CFE_Assert_OpenLogFile(const char *Filename);

/************************************************************************/
/** \brief Complete a test log file
*
* \par Description
* Closes the test log file that was previously opened via CFE_Assert_OpenLogFile
*
* \par Assumptions, External Events, and Notes:
* This should be called once test cases have completed
*
* \return None
*
*/
void CFE_Assert_CloseLogFile(void);

#endif /* CFE_ASSERT_H */
60 changes: 60 additions & 0 deletions modules/cfe_assert/src/cfe_assert_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,66 @@ void CFE_Assert_RegisterCallback(CFE_Assert_StatusCallback_t Callback)
CFE_Assert_Global.StatusCallback = Callback;
}

/*
* Opens a log file to "tee" the test output to
*/
int32 CFE_Assert_OpenLogFile(const char *Filename)
{
int32 Status;
char * Ext;
size_t NameLen;

strncpy(CFE_Assert_Global.LogFileFinal, Filename, sizeof(CFE_Assert_Global.LogFileFinal) - 1);
CFE_Assert_Global.LogFileFinal[sizeof(CFE_Assert_Global.LogFileFinal) - 1] = 0;

strncpy(CFE_Assert_Global.LogFileTemp, Filename, sizeof(CFE_Assert_Global.LogFileTemp) - 1);
CFE_Assert_Global.LogFileTemp[sizeof(CFE_Assert_Global.LogFileTemp) - 1] = 0;

Ext = strrchr(CFE_Assert_Global.LogFileTemp, '.');
if (Ext == NULL)
{
NameLen = strlen(CFE_Assert_Global.LogFileTemp);
}
else
{
NameLen = Ext - CFE_Assert_Global.LogFileTemp;
}

/* Use a ".tmp" file while actively writing, will rename at the end */
if (NameLen > (sizeof(CFE_Assert_Global.LogFileTemp) - 5))
{
NameLen = sizeof(CFE_Assert_Global.LogFileTemp) - 5;
}
strcpy(&CFE_Assert_Global.LogFileTemp[NameLen], ".tmp");

Status = OS_OpenCreate(&CFE_Assert_Global.LogFileDesc, CFE_Assert_Global.LogFileTemp,
OS_FILE_FLAG_CREATE | OS_FILE_FLAG_TRUNCATE, OS_WRITE_ONLY);
if (Status != OS_SUCCESS)
{
CFE_ES_WriteToSysLog("%s: Failed to open %s, rc=%d\n", __func__, CFE_Assert_Global.LogFileTemp, (int)Status);
return CFE_STATUS_EXTERNAL_RESOURCE_FAIL;
}

return CFE_SUCCESS;
}

/*
* Closes the log file
* This also renames the intermediate log file to its final name
*/
void CFE_Assert_CloseLogFile(void)
{
if (OS_ObjectIdDefined(CFE_Assert_Global.LogFileDesc))
{
OS_close(CFE_Assert_Global.LogFileDesc);
OS_rename(CFE_Assert_Global.LogFileTemp, CFE_Assert_Global.LogFileFinal);
}

CFE_Assert_Global.LogFileDesc = OS_OBJECT_ID_UNDEFINED;
CFE_Assert_Global.LogFileTemp[0] = 0;
CFE_Assert_Global.LogFileFinal[0] = 0;
}

/*
* Initialization Function for this library
*/
Expand Down
13 changes: 13 additions & 0 deletions modules/cfe_assert/src/cfe_assert_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ void UT_BSP_SysLogStatusReport(uint8 MessageType, const char *Prefix, const char
}
}

void UT_BSP_WriteLogFile(osal_id_t FileDesc, uint8 MessageType, const char *Prefix, const char *OutputMessage)
{
char LogFileBuffer[CFE_ASSERT_MAX_LOG_LINE_LENGTH];

snprintf(LogFileBuffer, sizeof(LogFileBuffer), "[%5s] %s\n", Prefix, OutputMessage);
OS_write(FileDesc, LogFileBuffer, strlen(LogFileBuffer));
}

void UT_BSP_DoText(uint8 MessageType, const char *OutputMessage)
{
const char * Prefix;
Expand Down Expand Up @@ -139,6 +147,11 @@ void UT_BSP_DoText(uint8 MessageType, const char *OutputMessage)

StatusCallback(MessageType, Prefix, OutputMessage);

if (OS_ObjectIdDefined(CFE_Assert_Global.LogFileDesc))
{
UT_BSP_WriteLogFile(CFE_Assert_Global.LogFileDesc, MessageType, Prefix, OutputMessage);
}

/*
* If any ABORT (major failure) message is thrown,
* then call a BSP-provided routine to stop the test and possibly dump a core
Expand Down
30 changes: 30 additions & 0 deletions modules/cfe_assert/src/cfe_assert_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,17 @@
*************************************************************************/
#include "common_types.h"
#include "cfe_assert.h"
#include "osconfig.h"
#include "cfe_mission_cfg.h"

/**
* Maximum length of a single line in the test log file
*
* Note this only applies to the log file. The user callback
* may have other limitations.
*/
#define CFE_ASSERT_MAX_LOG_LINE_LENGTH 512

/**
* State of the CFE assert library.
*
Expand Down Expand Up @@ -77,6 +86,27 @@ typedef struct
*/
CFE_Assert_StatusCallback_t StatusCallback;

/**
* Name of final log file for test results
*
* The temporary file will be renamed to this at the end of testing
*/
char LogFileFinal[OS_MAX_PATH_LEN];

/**
* Name of temporary log file for test results
*
* This is the file name that is actively written during the test
*/
char LogFileTemp[OS_MAX_PATH_LEN];

/**
* Log File descriptor
*
* Should be set to OS_OBJECT_ID_UNDEFINED if no log file is open
*/
osal_id_t LogFileDesc;

/**
* Mutex to control access to UtAssert structures.
*
Expand Down
1 change: 1 addition & 0 deletions modules/cfe_assert/src/cfe_assert_runner.c
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,7 @@ void CFE_Assert_ExecuteTest(void)
/* unregister the callback and unset the appid */
UT_BSP_Lock();
CFE_Assert_RegisterCallback(NULL);
CFE_Assert_CloseLogFile();
CFE_Assert_Global.OwnerAppId = CFE_ES_APPID_UNDEFINED;
UT_BSP_Unlock();
}
1 change: 1 addition & 0 deletions modules/cfe_testcase/src/cfe_test.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ void CFE_TestMain(void)
* state and gets ownership of the UtAssert subsystem
*/
CFE_Assert_RegisterTest("CFE API");
CFE_Assert_OpenLogFile(CFE_ASSERT_LOG_FILE_NAME);

/*
* Register test cases in UtAssert
Expand Down
9 changes: 9 additions & 0 deletions modules/cfe_testcase/src/cfe_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@
#include "uttest.h"
#include "utassert.h"

/**
* Name of log file to write
*
* This file captures all of the test results, independently of the
* events generated during the test run. The file can be used as part
* of scripted tests and/or capturing test artifacts.
*/
#define CFE_ASSERT_LOG_FILE_NAME "/cf/cfe_test.log"

/* Compare two Resource IDs */
#define UtAssert_ResourceID_EQ(actual, expect) \
UtAssert_True(CFE_RESOURCEID_TEST_EQUAL(actual, expect), "%s (%lu) == %s (%lu)", #actual, \
Expand Down

0 comments on commit 0cd4cbe

Please sign in to comment.