blob: 66c9db457d80cd3380ee2dcd3c494c72752dad96 [file] [log] [blame]
/** @file
Implement UnitTestResultReportLib doing plain txt out to console
Copyright (c) Microsoft Corporation.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Uefi.h>
#include <Library/UnitTestResultReportLib.h>
#include <Library/BaseLib.h>
#include <Library/DebugLib.h>
VOID
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;
}