| /** | |
| UnitTestLib APIs to run unit tests | |
| Copyright (c) Microsoft Corporation. | |
| SPDX-License-Identifier: BSD-2-Clause-Patent | |
| **/ | |
| #include <Uefi.h> | |
| #include <Library/UnitTestLib.h> | |
| #include <Library/BaseLib.h> | |
| #include <Library/BaseMemoryLib.h> | |
| #include <Library/DebugLib.h> | |
| #include <Library/UnitTestResultReportLib.h> | |
| STATIC UNIT_TEST_FRAMEWORK_HANDLE mFrameworkHandle = NULL; | |
| BASE_LIBRARY_JUMP_BUFFER gUnitTestJumpBuffer; | |
| UNIT_TEST_FRAMEWORK_HANDLE | |
| GetActiveFrameworkHandle ( | |
| VOID | |
| ) | |
| { | |
| return mFrameworkHandle; | |
| } | |
| STATIC | |
| EFI_STATUS | |
| RunTestSuite ( | |
| IN UNIT_TEST_SUITE *Suite | |
| ) | |
| { | |
| UNIT_TEST_LIST_ENTRY *TestEntry; | |
| UNIT_TEST *Test; | |
| UNIT_TEST_FRAMEWORK *ParentFramework; | |
| if (Suite == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| TestEntry = NULL; | |
| ParentFramework = (UNIT_TEST_FRAMEWORK *)Suite->ParentFramework; | |
| DEBUG ((DEBUG_VERBOSE, "---------------------------------------------------------\n")); | |
| DEBUG ((DEBUG_VERBOSE, "RUNNING TEST SUITE: %a\n", Suite->Title)); | |
| DEBUG ((DEBUG_VERBOSE, "---------------------------------------------------------\n")); | |
| if (Suite->Setup != NULL) { | |
| Suite->Setup (); | |
| } | |
| // | |
| // Iterate all tests within the suite | |
| // | |
| for (TestEntry = (UNIT_TEST_LIST_ENTRY *)GetFirstNode (&(Suite->TestCaseList)); | |
| (LIST_ENTRY *)TestEntry != &(Suite->TestCaseList); | |
| TestEntry = (UNIT_TEST_LIST_ENTRY *)GetNextNode (&(Suite->TestCaseList), (LIST_ENTRY *)TestEntry)) | |
| { | |
| Test = &TestEntry->UT; | |
| ParentFramework->CurrentTest = Test; | |
| DEBUG ((DEBUG_VERBOSE, "*********************************************************\n")); | |
| DEBUG ((DEBUG_VERBOSE, " RUNNING TEST: %a:\n", Test->Description)); | |
| DEBUG ((DEBUG_VERBOSE, "**********************************************************\n")); | |
| // | |
| // First, check to see whether the test has already been run. | |
| // NOTE: This would generally only be the case if a saved state was detected and loaded. | |
| // | |
| if ((Test->Result != UNIT_TEST_PENDING) && (Test->Result != UNIT_TEST_RUNNING)) { | |
| DEBUG ((DEBUG_VERBOSE, "Test was run on a previous pass. Skipping.\n")); | |
| ParentFramework->CurrentTest = NULL; | |
| continue; | |
| } | |
| // | |
| // Next, if we're still running, make sure that our test prerequisites are in place. | |
| if ((Test->Result == UNIT_TEST_PENDING) && (Test->Prerequisite != NULL)) { | |
| DEBUG ((DEBUG_VERBOSE, "PREREQ\n")); | |
| if (SetJump (&gUnitTestJumpBuffer) == 0) { | |
| if (Test->Prerequisite (Test->Context) != UNIT_TEST_PASSED) { | |
| DEBUG ((DEBUG_ERROR, "Prerequisite Not Met\n")); | |
| Test->Result = UNIT_TEST_ERROR_PREREQUISITE_NOT_MET; | |
| ParentFramework->CurrentTest = NULL; | |
| continue; | |
| } | |
| } else { | |
| DEBUG ((DEBUG_ERROR, "Prerequisite Not Met\n")); | |
| Test->Result = UNIT_TEST_ERROR_PREREQUISITE_NOT_MET; | |
| ParentFramework->CurrentTest = NULL; | |
| continue; | |
| } | |
| } | |
| // | |
| // Now we should be ready to call the actual test. | |
| // We set the status to UNIT_TEST_RUNNING in case the test needs to reboot | |
| // or quit. The UNIT_TEST_RUNNING state will allow the test to resume | |
| // but will prevent the Prerequisite from being dispatched a second time. | |
| if (SetJump (&gUnitTestJumpBuffer) == 0) { | |
| Test->Result = UNIT_TEST_RUNNING; | |
| Test->Result = Test->RunTest (Test->Context); | |
| } else { | |
| Test->Result = UNIT_TEST_ERROR_TEST_FAILED; | |
| } | |
| // | |
| // Finally, clean everything up, if need be. | |
| if (Test->CleanUp != NULL) { | |
| DEBUG ((DEBUG_VERBOSE, "CLEANUP\n")); | |
| if (SetJump (&gUnitTestJumpBuffer) == 0) { | |
| Test->CleanUp (Test->Context); | |
| } | |
| } | |
| // | |
| // End the test. | |
| // | |
| ParentFramework->CurrentTest = NULL; | |
| } | |
| if (Suite->Teardown != NULL) { | |
| Suite->Teardown (); | |
| } | |
| return EFI_SUCCESS; | |
| } | |
| /** | |
| Execute all unit test cases in all unit test suites added to a Framework. | |
| Once a unit test framework is initialized and all unit test suites and unit | |
| test cases are registered, this function will cause the unit test framework to | |
| dispatch all unit test cases in sequence and record the results for reporting. | |
| @param[in] FrameworkHandle A handle to the current running framework that | |
| dispatched the test. Necessary for recording | |
| certain test events with the framework. | |
| @retval EFI_SUCCESS All test cases were dispatched. | |
| @retval EFI_INVALID_PARAMETER FrameworkHandle is NULL. | |
| **/ | |
| EFI_STATUS | |
| EFIAPI | |
| RunAllTestSuites ( | |
| IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle | |
| ) | |
| { | |
| UNIT_TEST_FRAMEWORK *Framework; | |
| UNIT_TEST_SUITE_LIST_ENTRY *Suite; | |
| EFI_STATUS Status; | |
| Framework = (UNIT_TEST_FRAMEWORK *)FrameworkHandle; | |
| Suite = NULL; | |
| if (Framework == NULL) { | |
| return EFI_INVALID_PARAMETER; | |
| } | |
| DEBUG ((DEBUG_VERBOSE, "---------------------------------------------------------\n")); | |
| DEBUG ((DEBUG_VERBOSE, "------------ RUNNING ALL TEST SUITES --------------\n")); | |
| DEBUG ((DEBUG_VERBOSE, "---------------------------------------------------------\n")); | |
| mFrameworkHandle = FrameworkHandle; | |
| // | |
| // 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)) | |
| { | |
| Status = RunTestSuite (&(Suite->UTS)); | |
| if (EFI_ERROR (Status)) { | |
| DEBUG ((DEBUG_ERROR, "Test Suite Failed with Error. %r\n", Status)); | |
| } | |
| } | |
| // | |
| // Save current state so if test is started again it doesn't have to run. It will just report | |
| // | |
| SaveFrameworkState (NULL, 0); | |
| OutputUnitTestFrameworkReport (FrameworkHandle); | |
| mFrameworkHandle = NULL; | |
| return EFI_SUCCESS; | |
| } |