Sample unit tests in UnitTestFrameworkPkg hangs when running in OVMF/QEMU environment. Build target is X64/GCC5. Fixing this issue by adding EFIAPI to ReportPrint() function that use VA_ARGS. Signed-off-by: Getnat Ejigu <getnatejigu@gmail.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Cc: Sean Brogan <sean.brogan@microsoft.com> Cc: Bret Barkelew <Bret.Barkelew@microsoft.com> Reviewed-by: Bret Barkelew <bret.barkelew@microsoft.com> Reviewed-by: Michael D Kinney <michael.d.kinney@intel.com>
		
			
				
	
	
		
			219 lines
		
	
	
		
			6.9 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			219 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
 | 
						|
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;
 | 
						|
}
 |