blob: 5e2973beb3e1cbd9ad4b15ca283dbbc361504762 [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
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", __func__, (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;
}