1 | /**
|
---|
2 | UnitTestLib APIs to run unit tests
|
---|
3 |
|
---|
4 | Copyright (c) Microsoft Corporation.
|
---|
5 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
6 | **/
|
---|
7 |
|
---|
8 | #include <Uefi.h>
|
---|
9 | #include <Library/UnitTestLib.h>
|
---|
10 | #include <Library/BaseLib.h>
|
---|
11 | #include <Library/BaseMemoryLib.h>
|
---|
12 | #include <Library/DebugLib.h>
|
---|
13 | #include <Library/UnitTestResultReportLib.h>
|
---|
14 |
|
---|
15 | STATIC UNIT_TEST_FRAMEWORK_HANDLE mFrameworkHandle = NULL;
|
---|
16 |
|
---|
17 | BASE_LIBRARY_JUMP_BUFFER gUnitTestJumpBuffer;
|
---|
18 |
|
---|
19 | UNIT_TEST_FRAMEWORK_HANDLE
|
---|
20 | GetActiveFrameworkHandle (
|
---|
21 | VOID
|
---|
22 | )
|
---|
23 | {
|
---|
24 | return mFrameworkHandle;
|
---|
25 | }
|
---|
26 |
|
---|
27 | STATIC
|
---|
28 | EFI_STATUS
|
---|
29 | RunTestSuite (
|
---|
30 | IN UNIT_TEST_SUITE *Suite
|
---|
31 | )
|
---|
32 | {
|
---|
33 | UNIT_TEST_LIST_ENTRY *TestEntry;
|
---|
34 | UNIT_TEST *Test;
|
---|
35 | UNIT_TEST_FRAMEWORK *ParentFramework;
|
---|
36 |
|
---|
37 | if (Suite == NULL) {
|
---|
38 | return EFI_INVALID_PARAMETER;
|
---|
39 | }
|
---|
40 |
|
---|
41 | TestEntry = NULL;
|
---|
42 | ParentFramework = (UNIT_TEST_FRAMEWORK *)Suite->ParentFramework;
|
---|
43 |
|
---|
44 | DEBUG ((DEBUG_VERBOSE, "---------------------------------------------------------\n"));
|
---|
45 | DEBUG ((DEBUG_VERBOSE, "RUNNING TEST SUITE: %a\n", Suite->Title));
|
---|
46 | DEBUG ((DEBUG_VERBOSE, "---------------------------------------------------------\n"));
|
---|
47 |
|
---|
48 | if (Suite->Setup != NULL) {
|
---|
49 | Suite->Setup ();
|
---|
50 | }
|
---|
51 |
|
---|
52 | //
|
---|
53 | // Iterate all tests within the suite
|
---|
54 | //
|
---|
55 | for (TestEntry = (UNIT_TEST_LIST_ENTRY *)GetFirstNode (&(Suite->TestCaseList));
|
---|
56 | (LIST_ENTRY *)TestEntry != &(Suite->TestCaseList);
|
---|
57 | TestEntry = (UNIT_TEST_LIST_ENTRY *)GetNextNode (&(Suite->TestCaseList), (LIST_ENTRY *)TestEntry))
|
---|
58 | {
|
---|
59 | Test = &TestEntry->UT;
|
---|
60 | ParentFramework->CurrentTest = Test;
|
---|
61 |
|
---|
62 | DEBUG ((DEBUG_VERBOSE, "*********************************************************\n"));
|
---|
63 | DEBUG ((DEBUG_VERBOSE, " RUNNING TEST: %a:\n", Test->Description));
|
---|
64 | DEBUG ((DEBUG_VERBOSE, "**********************************************************\n"));
|
---|
65 |
|
---|
66 | //
|
---|
67 | // First, check to see whether the test has already been run.
|
---|
68 | // NOTE: This would generally only be the case if a saved state was detected and loaded.
|
---|
69 | //
|
---|
70 | if ((Test->Result != UNIT_TEST_PENDING) && (Test->Result != UNIT_TEST_RUNNING)) {
|
---|
71 | DEBUG ((DEBUG_VERBOSE, "Test was run on a previous pass. Skipping.\n"));
|
---|
72 | ParentFramework->CurrentTest = NULL;
|
---|
73 | continue;
|
---|
74 | }
|
---|
75 |
|
---|
76 | //
|
---|
77 | // Next, if we're still running, make sure that our test prerequisites are in place.
|
---|
78 | if ((Test->Result == UNIT_TEST_PENDING) && (Test->Prerequisite != NULL)) {
|
---|
79 | DEBUG ((DEBUG_VERBOSE, "PREREQ\n"));
|
---|
80 | if (SetJump (&gUnitTestJumpBuffer) == 0) {
|
---|
81 | if (Test->Prerequisite (Test->Context) != UNIT_TEST_PASSED) {
|
---|
82 | DEBUG ((DEBUG_ERROR, "Prerequisite Not Met\n"));
|
---|
83 | Test->Result = UNIT_TEST_ERROR_PREREQUISITE_NOT_MET;
|
---|
84 | ParentFramework->CurrentTest = NULL;
|
---|
85 | continue;
|
---|
86 | }
|
---|
87 | } else {
|
---|
88 | DEBUG ((DEBUG_ERROR, "Prerequisite Not Met\n"));
|
---|
89 | Test->Result = UNIT_TEST_ERROR_PREREQUISITE_NOT_MET;
|
---|
90 | ParentFramework->CurrentTest = NULL;
|
---|
91 | continue;
|
---|
92 | }
|
---|
93 | }
|
---|
94 |
|
---|
95 | //
|
---|
96 | // Now we should be ready to call the actual test.
|
---|
97 | // We set the status to UNIT_TEST_RUNNING in case the test needs to reboot
|
---|
98 | // or quit. The UNIT_TEST_RUNNING state will allow the test to resume
|
---|
99 | // but will prevent the Prerequisite from being dispatched a second time.
|
---|
100 | if (SetJump (&gUnitTestJumpBuffer) == 0) {
|
---|
101 | Test->Result = UNIT_TEST_RUNNING;
|
---|
102 | Test->Result = Test->RunTest (Test->Context);
|
---|
103 | } else {
|
---|
104 | Test->Result = UNIT_TEST_ERROR_TEST_FAILED;
|
---|
105 | }
|
---|
106 |
|
---|
107 | //
|
---|
108 | // Finally, clean everything up, if need be.
|
---|
109 | if (Test->CleanUp != NULL) {
|
---|
110 | DEBUG ((DEBUG_VERBOSE, "CLEANUP\n"));
|
---|
111 | if (SetJump (&gUnitTestJumpBuffer) == 0) {
|
---|
112 | Test->CleanUp (Test->Context);
|
---|
113 | }
|
---|
114 | }
|
---|
115 |
|
---|
116 | //
|
---|
117 | // End the test.
|
---|
118 | //
|
---|
119 | ParentFramework->CurrentTest = NULL;
|
---|
120 | }
|
---|
121 |
|
---|
122 | if (Suite->Teardown != NULL) {
|
---|
123 | Suite->Teardown ();
|
---|
124 | }
|
---|
125 |
|
---|
126 | return EFI_SUCCESS;
|
---|
127 | }
|
---|
128 |
|
---|
129 | /**
|
---|
130 | Execute all unit test cases in all unit test suites added to a Framework.
|
---|
131 |
|
---|
132 | Once a unit test framework is initialized and all unit test suites and unit
|
---|
133 | test cases are registered, this function will cause the unit test framework to
|
---|
134 | dispatch all unit test cases in sequence and record the results for reporting.
|
---|
135 |
|
---|
136 | @param[in] FrameworkHandle A handle to the current running framework that
|
---|
137 | dispatched the test. Necessary for recording
|
---|
138 | certain test events with the framework.
|
---|
139 |
|
---|
140 | @retval EFI_SUCCESS All test cases were dispatched.
|
---|
141 | @retval EFI_INVALID_PARAMETER FrameworkHandle is NULL.
|
---|
142 | **/
|
---|
143 | EFI_STATUS
|
---|
144 | EFIAPI
|
---|
145 | RunAllTestSuites (
|
---|
146 | IN UNIT_TEST_FRAMEWORK_HANDLE FrameworkHandle
|
---|
147 | )
|
---|
148 | {
|
---|
149 | UNIT_TEST_FRAMEWORK *Framework;
|
---|
150 | UNIT_TEST_SUITE_LIST_ENTRY *Suite;
|
---|
151 | EFI_STATUS Status;
|
---|
152 |
|
---|
153 | Framework = (UNIT_TEST_FRAMEWORK *)FrameworkHandle;
|
---|
154 | Suite = NULL;
|
---|
155 |
|
---|
156 | if (Framework == NULL) {
|
---|
157 | return EFI_INVALID_PARAMETER;
|
---|
158 | }
|
---|
159 |
|
---|
160 | DEBUG ((DEBUG_VERBOSE, "---------------------------------------------------------\n"));
|
---|
161 | DEBUG ((DEBUG_VERBOSE, "------------ RUNNING ALL TEST SUITES --------------\n"));
|
---|
162 | DEBUG ((DEBUG_VERBOSE, "---------------------------------------------------------\n"));
|
---|
163 | mFrameworkHandle = FrameworkHandle;
|
---|
164 |
|
---|
165 | //
|
---|
166 | // Iterate all suites
|
---|
167 | //
|
---|
168 | for (Suite = (UNIT_TEST_SUITE_LIST_ENTRY *)GetFirstNode (&Framework->TestSuiteList);
|
---|
169 | (LIST_ENTRY *)Suite != &Framework->TestSuiteList;
|
---|
170 | Suite = (UNIT_TEST_SUITE_LIST_ENTRY *)GetNextNode (&Framework->TestSuiteList, (LIST_ENTRY *)Suite))
|
---|
171 | {
|
---|
172 | Status = RunTestSuite (&(Suite->UTS));
|
---|
173 | if (EFI_ERROR (Status)) {
|
---|
174 | DEBUG ((DEBUG_ERROR, "Test Suite Failed with Error. %r\n", Status));
|
---|
175 | }
|
---|
176 | }
|
---|
177 |
|
---|
178 | //
|
---|
179 | // Save current state so if test is started again it doesn't have to run. It will just report
|
---|
180 | //
|
---|
181 | SaveFrameworkState (NULL, 0);
|
---|
182 | OutputUnitTestFrameworkReport (FrameworkHandle);
|
---|
183 |
|
---|
184 | mFrameworkHandle = NULL;
|
---|
185 |
|
---|
186 | return EFI_SUCCESS;
|
---|
187 | }
|
---|