/** @file Implement UnitTestResultReportLib doing plain txt out to console Copyright (c) Microsoft Corporation.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include #include #include #include VOID EFIAPI ReportPrint ( IN CONST CHAR8 *Format, ... ); VOID ReportOutput ( IN CONST CHAR8 *Output ); struct _UNIT_TEST_STATUS_STRING { UNIT_TEST_STATUS Status; CHAR8 *String; }; struct _UNIT_TEST_FAILURE_TYPE_STRING { FAILURE_TYPE Type; CHAR8 *String; }; struct _UNIT_TEST_STATUS_STRING mStatusStrings[] = { { UNIT_TEST_PASSED, "PASSED"}, { UNIT_TEST_ERROR_PREREQUISITE_NOT_MET, "NOT RUN - PREREQUISITE FAILED"}, { UNIT_TEST_ERROR_TEST_FAILED, "FAILED"}, { UNIT_TEST_RUNNING, "RUNNING"}, { UNIT_TEST_PENDING, "PENDING"}, { 0, "**UNKNOWN**"} }; struct _UNIT_TEST_FAILURE_TYPE_STRING mFailureTypeStrings[] = { { FAILURETYPE_NOFAILURE, "NO FAILURE"}, { FAILURETYPE_OTHER, "OTHER FAILURE"}, { FAILURETYPE_ASSERTTRUE, "ASSERT_TRUE FAILURE"}, { FAILURETYPE_ASSERTFALSE, "ASSERT_FALSE FAILURE"}, { FAILURETYPE_ASSERTEQUAL, "ASSERT_EQUAL FAILURE"}, { FAILURETYPE_ASSERTNOTEQUAL, "ASSERT_NOTEQUAL FAILURE"}, { FAILURETYPE_ASSERTNOTEFIERROR, "ASSERT_NOTEFIERROR FAILURE"}, { FAILURETYPE_ASSERTSTATUSEQUAL, "ASSERT_STATUSEQUAL FAILURE"}, { FAILURETYPE_ASSERTNOTNULL, "ASSERT_NOTNULL FAILURE"}, { FAILURETYPE_EXPECTASSERT, "EXPECT_ASSERT FAILURE"}, { 0, "*UNKNOWN* Failure"} }; // // TEST REPORTING FUNCTIONS // STATIC CONST CHAR8* GetStringForUnitTestStatus ( IN UNIT_TEST_STATUS Status ) { UINTN Index; for (Index = 0; Index < ARRAY_SIZE (mStatusStrings) - 1; Index++) { if (mStatusStrings[Index].Status == Status) { // // Return string from matching entry // return mStatusStrings[Index].String; } } // // Return last entry if no match found. // return mStatusStrings[Index].String; } STATIC CONST CHAR8* GetStringForFailureType ( IN FAILURE_TYPE Failure ) { UINTN Index; for (Index = 0; Index < ARRAY_SIZE (mFailureTypeStrings) - 1; Index++) { if (mFailureTypeStrings[Index].Type == Failure) { // // Return string from matching entry // return mFailureTypeStrings[Index].String; } } // // Return last entry if no match found. // DEBUG((DEBUG_INFO, "%a Failure Type does not have string defined 0x%X\n", __FUNCTION__, (UINT32)Failure)); return mFailureTypeStrings[Index].String; } /* Method to print the Unit Test run results @retval Success */ EFI_STATUS EFIAPI OutputUnitTestFrameworkReport ( IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle ) { UNIT_TEST_FRAMEWORK *Framework; INTN Passed; INTN Failed; INTN NotRun; UNIT_TEST_SUITE_LIST_ENTRY *Suite; UNIT_TEST_LIST_ENTRY *Test; INTN SPassed; INTN SFailed; INTN SNotRun; Passed = 0; Failed = 0; NotRun = 0; Suite = NULL; Framework = (UNIT_TEST_FRAMEWORK *)FrameworkHandle; if (Framework == NULL) { return EFI_INVALID_PARAMETER; } ReportPrint ("---------------------------------------------------------\n"); ReportPrint ("------------- UNIT TEST FRAMEWORK RESULTS ---------------\n"); ReportPrint ("---------------------------------------------------------\n"); //print the version and time // // Iterate all suites // for (Suite = (UNIT_TEST_SUITE_LIST_ENTRY*)GetFirstNode(&Framework->TestSuiteList); (LIST_ENTRY*)Suite != &Framework->TestSuiteList; Suite = (UNIT_TEST_SUITE_LIST_ENTRY*)GetNextNode(&Framework->TestSuiteList, (LIST_ENTRY*)Suite)) { Test = NULL; SPassed = 0; SFailed = 0; SNotRun = 0; ReportPrint ("/////////////////////////////////////////////////////////\n"); ReportPrint (" SUITE: %a\n", Suite->UTS.Title); ReportPrint (" PACKAGE: %a\n", Suite->UTS.Name); ReportPrint ("/////////////////////////////////////////////////////////\n"); // // Iterate all tests within the suite // for (Test = (UNIT_TEST_LIST_ENTRY*)GetFirstNode(&(Suite->UTS.TestCaseList)); (LIST_ENTRY*)Test != &(Suite->UTS.TestCaseList); Test = (UNIT_TEST_LIST_ENTRY*)GetNextNode(&(Suite->UTS.TestCaseList), (LIST_ENTRY*)Test)) { ReportPrint ("*********************************************************\n"); ReportPrint (" CLASS NAME: %a\n", Test->UT.Name); ReportPrint (" TEST: %a\n", Test->UT.Description); ReportPrint (" STATUS: %a\n", GetStringForUnitTestStatus (Test->UT.Result)); ReportPrint (" FAILURE: %a\n", GetStringForFailureType (Test->UT.FailureType)); ReportPrint (" FAILURE MESSAGE:\n%a\n", Test->UT.FailureMessage); if (Test->UT.Log != NULL) { ReportPrint (" LOG:\n"); ReportOutput (Test->UT.Log); } switch (Test->UT.Result) { case UNIT_TEST_PASSED: SPassed++; break; case UNIT_TEST_ERROR_TEST_FAILED: SFailed++; break; case UNIT_TEST_PENDING: // Fall through... case UNIT_TEST_RUNNING: // Fall through... case UNIT_TEST_ERROR_PREREQUISITE_NOT_MET: SNotRun++; break; default: break; } ReportPrint ("**********************************************************\n"); } //End Test iteration ReportPrint ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n"); ReportPrint ("Suite Stats\n"); ReportPrint (" Passed: %d (%d%%)\n", SPassed, (SPassed * 100)/(SPassed+SFailed+SNotRun)); ReportPrint (" Failed: %d (%d%%)\n", SFailed, (SFailed * 100) / (SPassed + SFailed + SNotRun)); ReportPrint (" Not Run: %d (%d%%)\n", SNotRun, (SNotRun * 100) / (SPassed + SFailed + SNotRun)); ReportPrint ("+++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n" ); Passed += SPassed; //add to global counters Failed += SFailed; //add to global counters NotRun += SNotRun; //add to global counters }//End Suite iteration ReportPrint ("=========================================================\n"); ReportPrint ("Total Stats\n"); ReportPrint (" Passed: %d (%d%%)\n", Passed, (Passed * 100) / (Passed + Failed + NotRun)); ReportPrint (" Failed: %d (%d%%)\n", Failed, (Failed * 100) / (Passed + Failed + NotRun)); ReportPrint (" Not Run: %d (%d%%)\n", NotRun, (NotRun * 100) / (Passed + Failed + NotRun)); ReportPrint ("=========================================================\n" ); return EFI_SUCCESS; }