/*----------------------------------------------------------------------------- * Name: report.c * Purpose: Report statistics and layout implementation *----------------------------------------------------------------------------- * Copyright(c) KEIL - An ARM Company *----------------------------------------------------------------------------*/ #include "DV_Report.h" TEST_REPORT test_report; static AS_STAT current_assertions; /* Current test case statistics */ #define TAS (&test_report.assertions) /* Total assertions */ #define CAS (¤t_assertions) /* Current assertions */ #define PRINT(x) MsgPrint x #define FLUSH() MsgFlush() static uint8_t Passed[] = "PASSED"; static uint8_t Warning[] = "WARNING"; static uint8_t Failed[] = "FAILED"; static uint8_t NotExe[] = "NOT EXECUTED"; /*----------------------------------------------------------------------------- * Test report function prototypes *----------------------------------------------------------------------------*/ static BOOL tr_Init (void); static BOOL tc_Init (void); static uint8_t *tr_Eval (void); static uint8_t *tc_Eval (void); static BOOL StatCount (TC_RES res); /*----------------------------------------------------------------------------- * Printer function prototypes *----------------------------------------------------------------------------*/ static void MsgPrint (const char *msg, ...); static void MsgFlush (void); /*----------------------------------------------------------------------------- * Assert interface function prototypes *----------------------------------------------------------------------------*/ static BOOL As_File_Result (TC_RES res); static BOOL As_File_Dbgi (TC_RES res, const char *fn, uint32_t ln, char *desc); TC_ITF tcitf = { As_File_Result, As_File_Dbgi, }; /*----------------------------------------------------------------------------- * Test report interface function prototypes *----------------------------------------------------------------------------*/ BOOL tr_File_Init (void); BOOL tr_File_Open (const char *title, const char *date, const char *time, const char *fn); BOOL tr_File_Close (void); BOOL tc_File_Open (uint32_t num, const char *fn); BOOL tc_File_Close (void); REPORT_ITF ritf = { tr_File_Init, tr_File_Open, tr_File_Close, tc_File_Open, tc_File_Close }; /*----------------------------------------------------------------------------- * Init test report *----------------------------------------------------------------------------*/ BOOL tr_File_Init (void) { return (tr_Init()); } /*----------------------------------------------------------------------------- * Open test report *----------------------------------------------------------------------------*/ BOOL tr_File_Open (const char *title, const char *date, const char *time, const char *fn) { #if (PRINT_XML_REPORT==1) PRINT(("\n")); PRINT(("\n")); PRINT(("\n")); PRINT(("\n")); PRINT(("%s\n", title)); PRINT(("%s\n", date)); PRINT(("\n", time)); PRINT(("%s\n", fn)); PRINT(("\n")); #else (void) fn; PRINT(("%s %s %s \n\n", title, date, time)); #endif return (__TRUE); } /*----------------------------------------------------------------------------- * Open test case *----------------------------------------------------------------------------*/ BOOL tc_File_Open (uint32_t num, const char *fn) { tc_Init (); #if (PRINT_XML_REPORT==1) PRINT(("\n")); PRINT(("%d\n", num)); PRINT(("%s\n", fn)); PRINT(("")); PRINT(("")); PRINT(("\n")); #else PRINT(("TEST %02d: %-32s ", num, fn)); #endif return (__TRUE); } /*----------------------------------------------------------------------------- * Close test case *----------------------------------------------------------------------------*/ BOOL tc_File_Close (void) { uint8_t *res = tc_Eval(); #if (PRINT_XML_REPORT==1) PRINT(("\n")); PRINT(("%s\n", res)); PRINT(("\n")); #else if ((res==Passed)||(res==NotExe)) PRINT(("%s\n", res)); else PRINT(("\n")); #endif FLUSH(); return (__TRUE); } /*----------------------------------------------------------------------------- * Close test report *----------------------------------------------------------------------------*/ BOOL tr_File_Close (void) { #if (PRINT_XML_REPORT==1) PRINT(("\n")); PRINT(("\n")); PRINT(("%d\n", test_report.tests)); PRINT(("%d\n", test_report.executed)); PRINT(("%d\n", test_report.passed)); PRINT(("%d\n", test_report.failed)); PRINT(("%d\n", test_report.warnings)); PRINT(("%s\n", tr_Eval())); PRINT(("\n")); PRINT(("\n")); PRINT(("\n")); #else PRINT(("\nTest Summary: %d Tests, %d Executed, %d Passed, %d Failed, %d Warnings.\n", test_report.tests, test_report.executed, test_report.passed, test_report.failed, test_report.warnings)); PRINT(("Test Result: %s\n", tr_Eval())); #endif FLUSH(); return (__TRUE); } /*----------------------------------------------------------------------------- * Assertion result counter *----------------------------------------------------------------------------*/ BOOL As_File_Result (TC_RES res) { return (StatCount (res)); } /*----------------------------------------------------------------------------- * Set debug information state *----------------------------------------------------------------------------*/ BOOL As_File_Dbgi (TC_RES res, const char *fn, uint32_t ln, char *desc) { /* Write debug information block */ #if (PRINT_XML_REPORT==1) PRINT(("\n")); if (desc!=NULL) PRINT(("%s\n", desc)); PRINT(("%s\n", fn)); PRINT(("%d\n", ln)); PRINT(("\n")); #else PRINT(("\n %s (%d)", fn, ln)); if (res==WARNING) PRINT((" [WARNING]")); if (res==FAILED) PRINT((" [FAILED]")); if (desc!=NULL) PRINT((" %s", desc)); #endif return (__TRUE); } /*----------------------------------------------------------------------------- * Init test report *----------------------------------------------------------------------------*/ BOOL tr_Init (void) { TAS->passed = 0; TAS->failed = 0; TAS->warnings = 0; return (__TRUE); } /*----------------------------------------------------------------------------- * Init test case *----------------------------------------------------------------------------*/ BOOL tc_Init (void) { CAS->passed = 0; CAS->failed = 0; CAS->warnings = 0; return (__TRUE); } /*----------------------------------------------------------------------------- * Evaluate test report results *----------------------------------------------------------------------------*/ uint8_t *tr_Eval (void) { if (test_report.failed > 0) { /* Test fails if any test case failed */ return (Failed); } else if (test_report.warnings > 0) { /* Test warns if any test case warnings */ return (Warning); } else if (test_report.passed > 0) { /* Test passes if at least one test case passed */ return (Passed); } else { /* No test cases were executed */ return (NotExe); } } /*----------------------------------------------------------------------------- * Evaluate test case results *----------------------------------------------------------------------------*/ uint8_t *tc_Eval (void) { test_report.tests++; test_report.executed++; if (CAS->failed > 0) { /* Test case fails if any failed assertion recorded */ test_report.failed++; return Failed; } else if (CAS->warnings > 0) { /* Test case warns if any warnings assertion recorded */ test_report.warnings++; return Warning; } else if (CAS->passed > 0) { /* Test case passes if at least one assertion passed */ test_report.passed++; return Passed; } else { /* Assert was not invoked - nothing to evaluate */ test_report.executed--; return NotExe; } } /*----------------------------------------------------------------------------- * Statistics result counter *----------------------------------------------------------------------------*/ BOOL StatCount (TC_RES res) { switch (res) { case PASSED: CAS->passed++; TAS->passed++; break; case WARNING: CAS->warnings++; TAS->warnings++; break; case FAILED: CAS->failed++; TAS->failed++; break; case NOT_EXECUTED: return (__FALSE); } return (__TRUE); } /*----------------------------------------------------------------------------- * No path *----------------------------------------------------------------------------*/ static const char *no_path (const char *fn) { const char *cp; #if defined(__CC_ARM) cp = strrchr(fn, '\\'); #else cp = strrchr(fn, '/'); #endif if (cp) return (cp + 1); return (fn); } /*----------------------------------------------------------------------------- * Set result *----------------------------------------------------------------------------*/ uint32_t __set_result (const char *fn, uint32_t ln, TC_RES res, char* desc) { fn = no_path (fn); // save assertion result switch (res) { case PASSED: if (TAS->passed < BUFFER_ASSERTIONS) { test_report.assertions.info.passed[TAS->passed].module = fn; test_report.assertions.info.passed[TAS->passed].line = ln; } break; case FAILED: if (TAS->failed < BUFFER_ASSERTIONS) { test_report.assertions.info.failed[TAS->failed].module = fn; test_report.assertions.info.failed[TAS->failed].line = ln; } break; case WARNING: if (TAS->warnings < BUFFER_ASSERTIONS) { test_report.assertions.info.warnings[TAS->warnings].module = fn; test_report.assertions.info.warnings[TAS->warnings].line = ln; } break; case NOT_EXECUTED: break; } // set debug info (if the test case didn't pass) if (res != PASSED) tcitf.Dbgi (res, fn, ln, desc); // set result tcitf.Result (res); return (res); } /*----------------------------------------------------------------------------- * Assert true *----------------------------------------------------------------------------*/ uint32_t __assert_true (const char *fn, uint32_t ln, uint32_t cond) { TC_RES res = FAILED; if (cond!=0) res = PASSED; __set_result(fn, ln, res, NULL); return (res); } #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wformat-nonliteral" #endif /*----------------------------------------------------------------------------- * MsgPrint: Print a message to the standard output *----------------------------------------------------------------------------*/ void MsgPrint (const char *msg, ...) { va_list args; va_start(args, msg); vprintf(msg, args); va_end(args); } #if defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) #pragma clang diagnostic pop #endif /*----------------------------------------------------------------------------- * SER_MsgFlush: Flush the standard output *----------------------------------------------------------------------------*/ void MsgFlush(void) { fflush(stdout); } /*----------------------------------------------------------------------------- * End of file *----------------------------------------------------------------------------*/