Michael D Kinney 26824851b0 UnitTestFrameworkPkg/UnitTestLib: Add checks for ASSERT()
REF: REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2801

Add UnitTestDebugAssertLib that provides the UnitTestDebugAssert()
service and the gUnitTestExpectAssertFailureJumpBuffer global
variable.  This NULL library is linked against all host and target
unit test builds.  This guarantees that the UnitTestDebugAssert()
service is available to link against all libraries and modules that
use the DebugLib class.

EDKII_UNIT_TEST_FRAMEWORK_ENABLED must always be defined when
building unit tests so the behavior of the DebugLib ASSERT()
macros can be adjusted to allow the unit test framework to
catch an ASSERT() if it is triggered by a function under test.

Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Bret Barkelew <Bret.Barkelew@microsoft.com>
Cc: Jiewen Yao <jiewen.yao@intel.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
Reviewed-by: Bret Barkelew <Bret.Barkelew@microsoft.com>
2020-07-15 05:25:21 +00:00

218 lines
6.9 KiB
C

/** @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;
}