VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/UnitTestFrameworkPkg/ReadMe.md@ 105598

最後變更 在這個檔案從105598是 101291,由 vboxsync 提交於 14 月 前

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 74.7 KB
 
1# Unit Test Framework Package
2
3## About
4
5This package provides unit test frameworks capable of building tests for multiple contexts including
6the UEFI shell environment and host-based environments. It allows for unit test development to focus
7on the tests and leave error logging, result formatting, context persistence, and test running to the framework.
8The unit test framework works well for low level unit tests as well as system level tests and
9fits easily in automation frameworks.
10
11### Framework
12
13The first unit test framework is called **Framework** and is implemented as a set of EDK II libraries.
14The Framework supports both host-based unit tests and target-based unit tests that share the same
15source style, macros, and APIs. In some scenarios, the same unit test case sources can be built
16for both host-based unit test execution and target-based unit test execution. Host-based unit tests
17that require mocked interfaces can use the mocking infrastructure provided by
18[cmocka](https://api.cmocka.org/) that is included in the UnitTestFrameworkPkg as a submodule.
19
20### GoogleTest
21
22The second unit test framework supported by the UnitTestFrameworkPkg is
23[GoogleTest](http://google.github.io/googletest/) and can be used to implement host-based unit tests.
24[GoogleTest on GitHub](https://github.com/google/googletest) is included in the UnitTestFrameworkPkg
25as a submodule. Use of GoogleTest for target-based unit tests of EDK II components is not supported.
26Host-based unit tests that require mocked interfaces can use the mocking infrastructure included with
27GoogleTest called [gMock](https://github.com/google/googletest/tree/main/googlemock). Note that the
28gMock framework does not directly support mocking of free (C style) functions, so the FunctionMockLib
29(containing a set of macros that wrap gMock's MOCK_METHOD macro) was created within the
30UnitTestFrameworkPkg to enable this support. The details and usage of these macros in the
31FunctionMockLib are described later.
32
33GoogleTest requires less overhead to register test suites and test cases compared to the Framework.
34There are also a number of tools that layer on top of GoogleTest that improve developer productivity.
35One example is the VS Code extension
36[C++ TestMate](https://marketplace.visualstudio.com/items?itemName=matepek.vscode-catch2-test-adapter)
37that may be used to implement, run, and debug unit tests implemented using GoogleTest.
38
39If a component can be tested with host-based unit tests, then GoogleTest is recommended. The MdePkg
40contains a port of the BaseSafeIntLib unit tests in the GoogleTest style so the differences between
41GoogleTest and Framework unit tests can be reviewed. The paths to the BaseSafeIntLib unit tests are:
42
43* `MdePkg/Test/UnitTest/Library/BaseSafeIntLib`
44* `MdePkg/Test/GoogleTest/Library/BaseSafeIntLib`
45
46Furthermore, the SecurityPkg contains unit tests for the SecureBootVariableLib using mocks in both
47the Framework/cmocka and GoogleTest/gMock style so the differences between cmocka and gMock can be
48reviewed. The paths to the SecureBootVariableLib unit tests are:
49
50* `SecurityPkg/Library/SecureBootVariableLib/UnitTest`
51* `SecurityPkg/Library/SecureBootVariableLib/GoogleTest`
52
53## Framework and GoogleTest Feature Comparison
54
55| Feature | Framework | GoogleTest |
56|:----------------------------|:---------:|:----------:|
57| Host Based Unit Tests | YES | YES |
58| Target Based Unit Tests | YES | NO |
59| Unit Test Source Language | C | C++ |
60| Register Test Suite | YES | Auto |
61| Register Test Case | YES | Auto |
62| Death/Expected Assert Tests | YES | YES |
63| Setup/Teardown Hooks | YES | YES |
64| Value-Parameterized Tests | NO | YES |
65| Typed Tests | NO | YES |
66| Type-Parameterized Tests | NO | YES |
67| Timeout Support | NO | YES |
68| Mocking Support | Cmocka | gMock |
69| JUNIT XML Reports | YES | YES |
70| Execute subset of tests | NO | YES |
71| VS Code Extensions | NO | YES |
72
73## Framework Libraries
74
75### UnitTestLib
76
77The main "framework" library. The core of the framework is the Framework object, which can have any number
78of test cases and test suites registered with it. The Framework object is also what drives test execution.
79
80The Framework also provides helper macros and functions for checking test conditions and
81reporting errors. Status and error info will be logged into the test context. There are a number
82of Assert macros that make the unit test code friendly to view and easy to understand.
83
84Finally, the Framework also supports logging strings during the test execution. This data is logged
85to the test context and will be available in the test reporting phase. This should be used for
86logging test details and helpful messages to resolve test failures.
87
88### UnitTestPersistenceLib
89
90Persistence lib has the main job of saving and restoring test context to a storage medium so that for tests
91that require exiting the active process and then resuming state can be maintained. This is critical
92in supporting a system reboot in the middle of a test run.
93
94### UnitTestResultReportLib
95
96Library provides function to run at the end of a framework test run and handles formatting the report.
97This is a common customization point and allows the unit test framework to fit its output reports into
98other test infrastructure. In this package simple library instances have been supplied to output test
99results to the console as plain text.
100
101## Framework Samples
102
103There is a sample unit test provided as both an example of how to write a unit test and leverage
104many of the features of the framework. This sample can be found in the `Test/UnitTest/Sample/SampleUnitTest`
105directory.
106
107The sample is provided in PEI, SMM, DXE, and UEFI App flavors. It also has a flavor for the HOST_APPLICATION
108build type, which can be run on a host system without needing a target.
109
110## Framework Usage
111
112This section is built a lot like a "Getting Started". We'll go through some of the components that are needed
113when constructing a unit test and some of the decisions that are made by the test writer. We'll also describe
114how to check for expected conditions in test cases and a bit of the logging characteristics.
115
116Most of these examples will refer to the `SampleUnitTestUefiShell` app found in this package.
117
118### Framework Requirements - INF
119
120In our INF file, we'll need to bring in the `UnitTestLib` library. Conveniently, the interface
121header for the `UnitTestLib` is located in `MdePkg`, so you shouldn't need to depend on any other
122packages. As long as your DSC file knows where to find the lib implementation that you want to use,
123you should be good to go.
124
125See this example in `SampleUnitTestUefiShell.inf`...
126
127```
128[Packages]
129 MdePkg/MdePkg.dec
130
131[LibraryClasses]
132 UefiApplicationEntryPoint
133 BaseLib
134 DebugLib
135 UnitTestLib
136 PrintLib
137```
138
139Also, if you want your test to automatically be picked up by the Test Runner plugin, you will need
140to make sure that the module `BASE_NAME` contains the word `Test`...
141
142```
143[Defines]
144 BASE_NAME = SampleUnitTestUefiShell
145```
146
147### Framework Requirements - DSC
148
149In our DSC file, we'll need to bring in the INF file that was just created into the `[Components]`
150section so that the unit tests will be built.
151
152See this example in `UnitTestFrameworkPkg.dsc`...
153
154```
155[Components]
156 UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestUefiShell.inf
157```
158
159Also, based on the type of tests that are being created, the associated DSC include file from the
160UnitTestFrameworkPkg for Host or Target based tests should also be included at the top of the DSC
161file.
162
163```
164!include UnitTestFrameworkPkg/UnitTestFrameworkPkgTarget.dsc.inc
165```
166
167Lastly, in the case that the test build has specific dependent libraries associated with it,
168they should be added in the \<LibraryClasses\> sub-section for the INF file in the
169`[Components]` section of the DSC file.
170
171See this example in `SecurityPkgHostTest.dsc`...
172
173```
174[Components]
175 SecurityPkg/Library/SecureBootVariableLib/UnitTest/SecureBootVariableLibUnitTest.inf {
176 <LibraryClasses>
177 SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
178 UefiRuntimeServicesTableLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiRuntimeServicesTableLib.inf
179 PlatformPKProtectionLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockPlatformPKProtectionLib.inf
180 UefiLib|SecurityPkg/Library/SecureBootVariableLib/UnitTest/MockUefiLib.inf
181 }
182```
183
184### Framework Requirements - Code
185
186Not to state the obvious, but let's make sure we have the following include before getting too far along...
187
188```c
189#include <Library/UnitTestLib.h>
190```
191
192Now that we've got that squared away, let's look at our 'Main()' routine (or DriverEntryPoint() or whatever).
193
194### Framework Configuration
195
196Everything in the UnitTestFrameworkPkg framework is built around an object called -- conveniently -- the Framework.
197This Framework object will contain all the information about our test, the test suites and test cases associated
198with it, the current location within the test pass, and any results that have been recorded so far.
199
200To get started with a test, we must first create a Framework instance. The function for this is
201`InitUnitTestFramework`. It takes in `CHAR8` strings for the long name, short name, and test version.
202The long name and version strings are just for user presentation and relatively flexible. The short name
203will be used to name any cache files and/or test results, so should be a name that makes sense in that context.
204These strings are copied internally to the Framework, so using stack-allocated or literal strings is fine.
205
206In the `SampleUnitTestUefiShell` app, the module name is used as the short name, so the initialization looks like this.
207
208```c
209DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION ));
210
211//
212// Start setting up the test framework for running the tests.
213//
214Status = InitUnitTestFramework( &Framework, UNIT_TEST_APP_NAME, gEfiCallerBaseName, UNIT_TEST_APP_VERSION );
215```
216
217The `&Framework` returned here is the handle to the Framework. If it's successfully returned, we can start adding
218test suites and test cases.
219
220Test suites exist purely to help organize test cases and to differentiate the results in reports. If you're writing
221a small unit test, you can conceivably put all test cases into a single suite. However, if you end up with 20+ test
222cases, it may be beneficial to organize them according to purpose. You _must_ have at least one test suite, even if
223it's just a catch-all. The function to create a test suite is `CreateUnitTestSuite`. It takes in a handle to
224the Framework object, a `CHAR8` string for the suite title and package name, and optional function pointers for
225a setup function and a teardown function.
226
227The suite title is for user presentation. The package name is for xUnit type reporting and uses a '.'-separated
228hierarchical format (see 'SampleUnitTestApp' for example). If provided, the setup and teardown functions will be
229called once at the start of the suite (before _any_ tests have run) and once at the end of the suite (after _all_
230tests have run), respectively. If either or both of these are unneeded, pass `NULL`. The function prototypes are
231`UNIT_TEST_SUITE_SETUP` and `UNIT_TEST_SUITE_TEARDOWN`.
232
233Looking at `SampleUnitTestUefiShell` app, you can see that the first test suite is created as below...
234
235```c
236//
237// Populate the SimpleMathTests Unit Test Suite.
238//
239Status = CreateUnitTestSuite( &SimpleMathTests, Fw, "Simple Math Tests", "Sample.Math", NULL, NULL );
240```
241
242This test suite has no setup or teardown functions. The `&SimpleMathTests` returned here is a handle to the suite and
243will be used when adding test cases.
244
245Great! Now we've finished some of the cruft, red tape, and busy work. We're ready to add some tests. Adding a test
246to a test suite is accomplished with the -- you guessed it -- `AddTestCase` function. It takes in the suite handle;
247a `CHAR8` string for the description and class name; a function pointer for the test case itself; additional, optional
248function pointers for prerequisite check and cleanup routines; and an optional pointer to a context structure.
249
250Okay, that's a lot. Let's take it one piece at a time. The description and class name strings are very similar in
251usage to the suite title and package name strings in the test suites. The former is for user presentation and the
252latter is for xUnit parsing. The test case function pointer is what is executed as the "test" and the
253prototype should be `UNIT_TEST_FUNCTION`. The last three parameters require a little bit more explaining.
254
255The prerequisite check function has a prototype of `UNIT_TEST_PREREQUISITE` and -- if provided -- will be called
256immediately before the test case. If this function returns any error, the test case will not be run and will be
257recorded as `UNIT_TEST_ERROR_PREREQUISITE_NOT_MET`. The cleanup function (prototype `UNIT_TEST_CLEANUP`) will be called
258immediately after the test case to provide an opportunity to reset any global state that may have been changed in the
259test case. In the event of a prerequisite failure, the cleanup function will also be skipped. If either of these
260functions is not needed, pass `NULL`.
261
262The context pointer is entirely case-specific. It will be passed to the test case upon execution. One of the purposes
263of the context pointer is to allow test case reuse with different input data. (Another use is for testing that wraps
264around a system reboot, but that's beyond the scope of this guide.) The test case must know how to interpret the context
265pointer, so it could be a simple value, or it could be a complex structure. If unneeded, pass `NULL`.
266
267In `SampleUnitTestUefiShell` app, the first test case is added using the code below...
268
269```c
270AddTestCase( SimpleMathTests, "Adding 1 to 1 should produce 2", "Addition", OnePlusOneShouldEqualTwo, NULL, NULL, NULL );
271```
272
273This test case calls the function `OnePlusOneShouldEqualTwo` and has no prerequisite, cleanup, or context.
274
275Once all the suites and cases are added, it's time to run the Framework.
276
277```c
278//
279// Execute the tests.
280//
281Status = RunAllTestSuites( Framework );
282```
283
284### Framework - A Simple Test Case
285
286We'll take a look at the below test case from 'SampleUnitTestApp'...
287
288```c
289UNIT_TEST_STATUS
290EFIAPI
291OnePlusOneShouldEqualTwo (
292 IN UNIT_TEST_FRAMEWORK_HANDLE Framework,
293 IN UNIT_TEST_CONTEXT Context
294 )
295{
296 UINTN A, B, C;
297
298 A = 1;
299 B = 1;
300 C = A + B;
301
302 UT_ASSERT_EQUAL(C, 2);
303 return UNIT_TEST_PASSED;
304} // OnePlusOneShouldEqualTwo()
305```
306
307The prototype for this function matches the `UNIT_TEST_FUNCTION` prototype. It takes in a handle to the Framework
308itself and the context pointer. The context pointer could be cast and interpreted as anything within this test case,
309which is why it's important to configure contexts carefully. The test case returns a value of `UNIT_TEST_STATUS`, which
310will be recorded in the Framework and reported at the end of all suites.
311
312In this test case, the `UT_ASSERT_EQUAL` assertion is being used to establish that the business logic has functioned
313correctly. There are several assertion macros, and you are encouraged to use one that matches as closely to your
314intended test criterium as possible, because the logging is specific to the macro and more specific macros have more
315detailed logs. When in doubt, there are always `UT_ASSERT_TRUE` and `UT_ASSERT_FALSE`. Assertion macros that fail their
316test criterium will immediately return from the test case with `UNIT_TEST_ERROR_TEST_FAILED` and log an error string.
317_Note_ that this early return can have implications for memory leakage.
318
319At the end, if all test criteria pass, you should return `UNIT_TEST_PASSED`.
320
321### Framework - More Complex Cases
322
323To write more advanced tests, first look at all the Assertion and Logging macros provided in the framework.
324
325Beyond that, if you're writing host-based tests and want to take a dependency on the UnitTestFrameworkPkg, you can
326leverage the `cmocka.h` interface and write tests with all the features of the Cmocka framework.
327
328Documentation for Cmocka can be found here:
329https://api.cmocka.org/
330
331## GoogleTest Libraries
332
333### GoogleTestLib
334
335GoogleTestLib is the core library used for GoogleTest in EDK II. This library is mainly a wrapper
336around the GoogleTest and gMock header and source files. So all the standard
337[GoogleTest](http://google.github.io/googletest/) and
338[gMock](https://github.com/google/googletest/tree/main/googlemock) documentation for writing tests
339and using mocks applies.
340
341Additionally, to support the use of some primitive types that are not directly supported by
342GoogleTest and gMock (but are needed to allow gMock to be used in EDK II), some custom gMock
343actions and matchers were added to GoogleTestLib. These customizations are briefly described in
344the following tables.
345
346#### Custom Actions
347
348| Action Name | Similar gMock Generic Action | Usage |
349|:--- |:--- |:--- |
350| `SetArgBuffer()` | `SetArgPointee()` | Used to set a buffer output argument (such as UINT8*, VOID*, a structure pointer, etc.) with data in an expect call. Can be used in an `EXPECT_CALL()` |
351
352#### Custom Matchers
353
354| Matcher Name | Similar gMock Generic Matcher | Usage |
355|:--- |:--- |:--- |
356| `BufferEq()` | `Pointee(Eq())` | Used to compare two buffer pointer types (such as UINT8*, VOID*, a structure pointer, etc.). Can be used in an `EXPECT_CALL()`, `EXPECT_THAT()`, or anywhere else a matcher to compare two buffers is needed. |
357| `Char16StrEq()` | `Pointee(Eq())` | Used to compare two CHAR16* strings. Can be used in an `EXPECT_CALL()`, `EXPECT_THAT()`, or anywhere else a matcher to compare two CHAR16* strings is needed. |
358
359### FunctionMockLib
360
361FunctionMockLib is the library that allows gMock to be used with free (C style) functions. This
362library contains a set of macros that wrap gMock's MOCK_METHOD macro to enable the standard gMock
363capabilities to be used with free functions. The details of how this is implemented is outside the
364scope of this document, but a brief description of each of the public macros in FunctionMockLib is
365described below. A full example of how to use these macros to create a mock is described in a
366later section.
367
368In total there are six public macros in FunctionMockLib. Four of the macros are related to creating
369the mock functions, and the other two macros are related to creating an interface that is necessary
370to contain the mock functions and connect them into the gMock framework.
371
372The macros used to create the interface are...
3731. `MOCK_INTERFACE_DECLARATION(MOCK)`
3742. `MOCK_INTERFACE_DEFINITION(MOCK)`
375
376These macros both take one argument which is the name of the interface for the mock. The
377`MOCK_INTERFACE_DECLARATION` macro is used to declare the interface in the `.h` file and the
378`MOCK_INTERFACE_DEFINITION` macro is used to define the interface in the `.cpp` file. For
379example, to create a mock for the `UefiLib`, a `MockUefiLib.h` file would be created and the
380below code would be added to it.
381
382```cpp
383struct MockUefiLib {
384 MOCK_INTERFACE_DECLARATION(MockUefiLib);
385};
386```
387
388Additionally, the below code would be written into a `MockUefiLib.cpp` file.
389
390```cpp
391MOCK_INTERFACE_DEFINITION(MockUefiLib);
392```
393
394The macros used to create the mock functions are...
3951. `MOCK_FUNCTION_DECLARATION(RET_TYPE, FUNC, ARGS)`
3962. `MOCK_FUNCTION_DEFINITION(MOCK, FUNC, NUM_ARGS, CALL_TYPE)`
3973. `MOCK_FUNCTION_INTERNAL_DECLARATION(RET_TYPE, FUNC, ARGS)`
3984. `MOCK_FUNCTION_INTERNAL_DEFINITION(MOCK, FUNC, NUM_ARGS, CALL_TYPE)`
399
400You will notice that there are two sets of macros: one to mock external functions and
401another to mock internal functions. Each set of macros has the exact same arguments, but
402they are used for slightly different use cases. The details of these different use cases
403is described in detail in a later section. For now, we will focus on the usage of the macro
404arguments since that is common between them.
405
406The `MOCK_FUNCTION_DECLARATION` macro is used to declare the mock function in the `.h` file,
407and it takes three arguments: return type, function name, and argument list. The
408`MOCK_FUNCTION_DEFINITION` macro is used to define the mock function in the `.cpp` file,
409and it takes four arguments: name of the interface for the mock, function name, number of
410arguments the function takes, and calling convention type of the function. For example, to
411continue with the `UefiLib` mock example above, the `GetVariable2` and `GetEfiGlobalVariable2`
412functions are declared in `UefiLib.h` as shown below.
413
414```cpp
415EFI_STATUS
416EFIAPI
417GetVariable2 (
418 IN CONST CHAR16 *Name,
419 IN CONST EFI_GUID *Guid,
420 OUT VOID **Value,
421 OUT UINTN *Size OPTIONAL
422 );
423
424EFI_STATUS
425EFIAPI
426GetEfiGlobalVariable2 (
427 IN CONST CHAR16 *Name,
428 OUT VOID **Value,
429 OUT UINTN *Size OPTIONAL
430 );
431```
432
433To declare mocks for these functions within the previously created `MockUefiLib` interface,
434the below code would be added to the `MockUefiLib.h` file. Note that the previously added
435interface declaration is also included in the code below for context.
436
437```cpp
438struct MockUefiLib {
439 MOCK_INTERFACE_DECLARATION (MockUefiLib);
440
441 MOCK_FUNCTION_DECLARATION (
442 EFI_STATUS,
443 GetVariable2,
444 (IN CONST CHAR16 *Name,
445 IN CONST EFI_GUID *Guid,
446 OUT VOID **Value,
447 OUT UINTN *Size OPTIONAL)
448 );
449
450 MOCK_FUNCTION_DECLARATION (
451 EFI_STATUS,
452 GetEfiGlobalVariable2,
453 (IN CONST CHAR16 *Name,
454 OUT VOID **Value,
455 OUT UINTN *Size OPTIONAL)
456 );
457};
458```
459
460Additionally, the below code would be added into the `MockUefiLib.cpp` file to provide
461the definitions for these mock functions. Again, the previously added interface
462definition is also included in the code below for context.
463
464```cpp
465MOCK_INTERFACE_DEFINITION(MockUefiLib);
466
467MOCK_FUNCTION_DEFINITION(MockUefiLib, GetVariable2, 4, EFIAPI);
468MOCK_FUNCTION_DEFINITION(MockUefiLib, GetEfiGlobalVariable2, 3, EFIAPI);
469```
470
471That concludes the basic overview on how to use the macros, but a more detailed
472description on how to name the mocks, where to put the files, how to build the
473mocks, and how to use the mocks is described in detail later.
474
475### SubhookLib
476
477SubhookLib is the library used by FunctionMockLib to implement the macros to
478mock internal functions: `MOCK_FUNCTION_INTERNAL_DECLARATION` and
479`MOCK_FUNCTION_INTERNAL_DEFINITION`. These macros require the additional
480functionality provided by SubhookLib because they create mock functions
481for functions that are already defined and compiled within the module being
482tested. More detail on this is provided in a later section, but for now it is
483sufficient to know that the SubhookLib allows a second definition of the
484function to be compiled into the test application and then hooked to during a
485test.
486
487This library is mainly a wrapper around the
488[subhook](https://github.com/Zeex/subhook) header and source files. It is
489important to note that the use of the mock function macros and the creation
490of mock functions requires no knowledge about the SubhookLib. The SubhookLib
491library is entirely hidden and encapsulated within FunctionMockLib, and it
492is only mentioned here to provide a complete explanation on all the libraries
493used in the implementation.
494
495## FunctionMockLib Mocks
496
497This section describes the details on how to use the mock function macros in
498FunctionMockLib to create mock functions, name them, organize their files,
499and build them so that they can be used within GoogleTest tests. The usage
500of the mock functions is detailed in a later section while this section
501simply details how to create them, build them, and where to put them.
502
503### FunctionMockLib Mocks - External vs. Internal
504
505The first question to ask when creating a mock function is if the function being
506mocked is external or internal to the module being tested. This is very important
507because the macros in FunctionMockLib used to create the mock function are named
508differently for these two use cases. Fortunately, the arguments to these macros
509and the usage of the mock functions within the tests are exactly the same.
510However, because of the different underlying implementations, two different sets
511of macros are used.
512
513A more detailed description of when to use the external vs. internal mock function
514macros is in the following sections, but the quick summary is as follows.
515
516* External mock function macros are used to mock functions that are outside the
517module being tested and use link-time replacement.
518* Internal mock function macros are used to mock functions that are inside the
519module being tested and use run-time replacement.
520
521The below table shows which macros to use in these two use cases. However, note that
522for the creation of the interface, the same macros are used in both cases.
523
524| Mock Function Use Case | Mock Interface Macros | Mock Function Macros |
525|:--- |:--- |:--- |
526| External mock functions | `MOCK_INTERFACE_DECLARATION`</br>`MOCK_INTERFACE_DEFINITION` | `MOCK_FUNCTION_DECLARATION`</br>`MOCK_FUNCTION_DEFINITION` |
527| Internal mock functions | `MOCK_INTERFACE_DECLARATION`</br>`MOCK_INTERFACE_DEFINITION` | `MOCK_FUNCTION_INTERNAL_DECLARATION`</br>`MOCK_FUNCTION_INTERNAL_DEFINITION` |
528
529#### FunctionMockLib Mocks - External mock function
530
531The external mock function macros are used to create mock function definitions
532for a library, global service, or protocol that is defined outside of the module
533being tested. These mock function definitions are linked into the test application
534instead of linking in the design function definitions. In other words, the
535external mock function macros use link-time replacement of the design functions.
536
537The `.h/.cpp` files for these mock functions are created within the package
538directory where the library, global table, or protocol that is being mocked is
539declared. These files are compiled into their own separate library (using
540an INF file) that can be shared and linked into many test applications, but more
541on that later.
542
543#### FunctionMockLib Mocks - Internal mock function
544
545The internal mock function macros are used to create mock function definitions
546for functions that are defined within the module being tested. These mock
547function definitions are compiled into the test application along with the design
548function definitions. This is possible because the mock functions are given a
549slightly different name during compilation. Then during test execution, the
550design function is hooked and replaced with the mock function. In other words,
551the internal mock function macros use run-time replacement of the design
552functions.
553
554The `.h/.cpp` files for these mock functions are created within the GoogleTest
555directory containing the specific tests that are using them. These files are
556compiled directly in the GoogleTest INF file that builds the test application,
557and they are not shared outside of that GoogleTest directory, but more on that
558later.
559
560### FunctionMockLib Mocks - Declaration
561
562The declaration of mock functions using the FunctionMockLib macros are done
563in header files. The name of the header file is determined by the interface
564(such as a library or a protocol) that is being created for the mock functions.
565The rules for naming the file are shown in the table below.
566
567| Interface Type | Header File Name |
568| :--- | :--- |
569| Library | Mock\<LibraryName\>Lib.h |
570| Global Table (e.g. gRT, gBS, etc.) | Mock\<GlobalTableLibraryName\>Lib.h |
571| Protocol | Mock\<ProtocolName\>Protocol.h |
572
573The below table shows examples for file names with each of the above cases.
574
575| Interface Type | Interface Name | Header File Name |
576| :--- | :--- | :--- |
577| Library | UefiLib | MockUefiLib.h |
578| Global Table (e.g. gRT, gBS, etc.) | UefiRuntimeServicesTableLib | MockUefiRuntimeServicesTableLib.h |
579| Protocol | EFI_USB_IO_PROTOCOL | MockEfiUsbIoProtocol.h |
580
581Once the header file name is known, the file needs to be created in the proper
582location. For internal mock functions, the location is simply the same
583GoogleTest directory that contains the INF file that builds the test application.
584For external mock functions, the location is within the `Test` directory under the
585package where the library, global table, or protocol that is being mocked is
586declared. The exact location depends on the interface type and is shown in the
587below table.
588
589| Interface Type | Header File Location |
590| :--- | :--- |
591| Library | \<PackageName\>/Test/Mock/Include/GoogleTest/Library |
592| Global Table (e.g. gRT, gBS, etc.) | \<PackageName\>/Test/Mock/Include/GoogleTest/Library |
593| Protocol | \<PackageName\>/Test/Mock/Include/GoogleTest/Protocol |
594
595The below table shows examples for file locations with each of the above cases.
596
597| Interface Type | Interface Name | Header File Location |
598| :--- | :--- | :--- |
599| Library | UefiLib | MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiLib.h |
600| Global Table (e.g. gRT, gBS, etc.) | UefiRuntimeServicesTableLib | MdePkg/Test/Mock/Include/GoogleTest/Library/MockUefiRuntimeServicesTableLib.h |
601| Protocol | EFI_USB_IO_PROTOCOL | MdePkg/Test/Mock/Include/GoogleTest/Protocol/MockEfiUsbIoProtocol.h |
602
603Now that the file location is known, the contents can be added to it. After the
604standard `#ifndef` for a header file is added at the top of the file, the
605`GoogleTestLib.h` and `FunctionMockLib.h` files are always added. Following these
606includes other EDK II related include files are added and must be wrapped in
607`extern "C" {}` because they are C include files. Failure to do this will cause
608link errors to occur. Note that a `#include` of the interface being mocked must
609also be added. This causes the declarations of the functions being mocked to be
610included in the compilation and allows the compilation to verify that the function
611signatures of the mock and design functions are identical.
612
613After all the needed includes have been added in the file , a `struct` is declared
614using the same name as the header file (which was determined using the rules
615above). Within this structure declaration a `MOCK_INTERFACE_DECLARATION` is
616added along with a `MOCK_FUNCTION_DECLARATION` (or a
617`MOCK_FUNCTION_INTERNAL_DECLARATION` if this interface is for internal mock
618functions) for each function in the interface. To build on the examples above,
619the complete `MockUefiLib.h` file would be as shown below. Note that for brevity
620only the `GetVariable2` and `GetEfiGlobalVariable2` declarations are included in
621the example.
622
623```cpp
624#ifndef MOCK_UEFI_LIB_H_
625#define MOCK_UEFI_LIB_H_
626
627#include <Library/GoogleTestLib.h>
628#include <Library/FunctionMockLib.h>
629extern "C" {
630 #include <Uefi.h>
631 #include <Library/UefiLib.h>
632}
633
634struct MockUefiLib {
635 MOCK_INTERFACE_DECLARATION (MockUefiLib);
636
637 MOCK_FUNCTION_DECLARATION (
638 EFI_STATUS,
639 GetVariable2,
640 (IN CONST CHAR16 *Name,
641 IN CONST EFI_GUID *Guid,
642 OUT VOID **Value,
643 OUT UINTN *Size OPTIONAL)
644 );
645
646 MOCK_FUNCTION_DECLARATION (
647 EFI_STATUS,
648 GetEfiGlobalVariable2,
649 (IN CONST CHAR16 *Name,
650 OUT VOID **Value,
651 OUT UINTN *Size OPTIONAL)
652 );
653};
654
655#endif
656```
657
658In the case of libraries, the function names in the mock declarations
659align exactly with the function names in the design. However, in the
660case of global tables and protocols, to eliminate possible function
661name collisions, the names are adjusted slightly in the mock
662declarations as shown in the below table.
663
664| Mock Function Use Case | Design Function Name | Mock Function Name |
665| :--- | :--- | :--- |
666| Library | GetVariable2 | GetVariable2 |
667| Global Table (e.g. gRT, gBS, etc.) | gRT->GetVariable | gRT_GetVariable |
668| Protocol | UsbIoProtocol->UsbPortReset | UsbIoProtocol_UsbPortReset |
669
670Lastly, when creating mock functions, there are two limitations to be
671aware of in gMock that extend into FunctionMockLib.
672
6731. gMock does not support mocking functions that have more than 15 arguments.
6742. gMock does not support mocking variadic functions.
675
676With those limitations in mind, that completes the mock function
677declarations, and now the mock function definitions for those declarations
678can be created.
679
680### FunctionMockLib Mocks - Definition
681
682The definition of mock functions using the FunctionMockLib macros are done
683in source files. The name of the source file is determined by the interface
684(such as a library or a protocol) that is being created for the mock functions.
685The rules for naming the file align with the naming of the file for declarations
686and are shown in the table below.
687
688| Interface Type | Source File Name |
689| :--- | :--- |
690| Library | Mock\<LibraryName\>Lib.cpp |
691| Global Table (e.g. gRT, gBS, etc.) | Mock\<GlobalTableLibraryName\>Lib.cpp |
692| Protocol | Mock\<ProtocolName\>Protocol.cpp |
693
694The below table shows examples for file names with each of the above cases.
695
696| Interface Type | Interface Name | Source File Name |
697| :--- | :--- | :--- |
698| Library | UefiLib | MockUefiLib.cpp |
699| Global Table (e.g. gRT, gBS, etc.) | UefiRuntimeServicesTableLib | MockUefiRuntimeServicesTableLib.cpp |
700| Protocol | EFI_USB_IO_PROTOCOL | MockEfiUsbIoProtocol.cpp |
701
702Once the source file name is known, the file needs to be created in the proper
703location. The location of the source file is aligned with the location for the
704header file. For internal mock functions, the location is simply the same
705GoogleTest directory that contains the INF file that builds the test application.
706For external mock functions, the location is within the `Test` directory under the
707package where the library, global table, or protocol that is being mocked is
708declared. The exact location depends on the interface type and is shown in the
709below table.
710
711| Interface Type | Source File Location |
712| :--- | :--- |
713| Library | \<PackageName\>/Test/Mock/Library/GoogleTest/Mock\<LibraryName\>Lib |
714| Global Table (e.g. gRT, gBS, etc.) | \<PackageName\>/Test/Mock/Library/GoogleTest/Mock\<GlobalTableLibraryName\>Lib |
715| Protocol | \<PackageName\>/Test/Mock/Library/GoogleTest/Mock\<ProtocolName\>Protocol |
716
717The below table shows examples for file locations with each of the above cases.
718
719| Interface Type | Interface Name | Source File Location |
720| :--- | :--- | :--- |
721| Library | UefiLib | MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.cpp |
722| Global Table (e.g. gRT, gBS, etc.) | UefiRuntimeServicesTableLib | MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.cpp |
723| Protocol | EFI_USB_IO_PROTOCOL | MdePkg/Test/Mock/Library/GoogleTest/MockEfiUsbIoProtocol/MockEfiUsbIoProtocol.cpp |
724
725Now that the file location is known, the contents can be added to it. At the top
726of the file, the header file containing the mock function declarations is always
727added. After this `#include`, the interface definition is created using
728`MOCK_INTERFACE_DEFINITION` with the interface name that was used in the mock
729function declaration header file. A `MOCK_FUNCTION_DEFINITION` is then added (or
730a `MOCK_FUNCTION_INTERNAL_DEFINITION` if this interface is for internal mock
731functions) for each function that was declared in the interface. To build on the
732prior declaration examples, the complete `MockUefiLib.cpp` file would be as shown
733below. Note that for brevity only the `GetVariable2` and `GetEfiGlobalVariable2`
734definitions are included in the example.
735
736```cpp
737#include <GoogleTest/Library/MockUefiLib.h>
738
739MOCK_INTERFACE_DEFINITION(MockUefiLib);
740
741MOCK_FUNCTION_DEFINITION(MockUefiLib, GetVariable2, 4, EFIAPI);
742MOCK_FUNCTION_DEFINITION(MockUefiLib, GetEfiGlobalVariable2, 3, EFIAPI);
743```
744
745When creating the defintions, there are a few things to keep in mind.
746
747First, when using `MOCK_FUNCTION_DEFINITION`, some functions being mocked do
748not specify a calling convention. In this case, it is fine to leave the last
749argument of `MOCK_FUNCTION_DEFINITION` empty. For example, if `GetVariable2`
750did not specify the `EFIAPI` calling convention in its declaration, then the
751below code would be used for the mock function definition.
752
753```cpp
754MOCK_FUNCTION_DEFINITION(MockUefiLib, GetVariable2, 4, );
755```
756
757Second, the function name used in `MOCK_FUNCTION_DEFINITION` must align with
758the function name used in the associated `MOCK_FUNCTION_DECLARATION` in the
759header file.
760
761Last, if the interface is mocking a global table or protocol, then the structure
762of function pointers for that interface must also be defined within the source
763file as a `static` structure with the mock function definitions being assigned
764to the associated entries in the structure. The address of this `static`
765structure is then assigned to the global table or protocol pointer. Note that
766this pointer must be wrapped in `extern "C" {}` because it needs C style
767linkage. Failure to do this will cause link errors to occur. For example, when
768creating the definition of the mock for the global runtime services table, the
769complete `MockUefiRuntimeServicesTableLib.cpp` file would be as shown below.
770Note that for brevity only the `GetVariable` and `SetVariable` definitions are
771included in the example.
772
773```cpp
774#include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h>
775
776MOCK_INTERFACE_DEFINITION(MockUefiRuntimeServicesTableLib);
777
778MOCK_FUNCTION_DEFINITION(MockUefiRuntimeServicesTableLib, gRT_GetVariable, 5, EFIAPI);
779MOCK_FUNCTION_DEFINITION(MockUefiRuntimeServicesTableLib, gRT_SetVariable, 5, EFIAPI);
780
781static EFI_RUNTIME_SERVICES localRt = {
782 {0}, // EFI_TABLE_HEADER
783
784 NULL, // EFI_GET_TIME
785 NULL, // EFI_SET_TIME
786 NULL, // EFI_GET_WAKEUP_TIME
787 NULL, // EFI_SET_WAKEUP_TIME
788
789 NULL, // EFI_SET_VIRTUAL_ADDRESS_MAP
790 NULL, // EFI_CONVERT_POINTER
791
792 gRT_GetVariable, // EFI_GET_VARIABLE
793 NULL, // EFI_GET_NEXT_VARIABLE_NAME
794 gRT_SetVariable, // EFI_SET_VARIABLE
795
796 NULL, // EFI_GET_NEXT_HIGH_MONO_COUNT
797 NULL, // EFI_RESET_SYSTEM
798
799 NULL, // EFI_UPDATE_CAPSULE
800 NULL, // EFI_QUERY_CAPSULE_CAPABILITIES
801
802 NULL, // EFI_QUERY_VARIABLE_INFO
803};
804
805extern "C" {
806 EFI_RUNTIME_SERVICES* gRT = &localRt;
807}
808```
809
810That completes the mock function definitions. So now these mock function
811definitions can be compiled.
812
813### FunctionMockLib Mocks - Build
814
815The building of mock functions using FunctionMockLib is done slightly
816differently for external and internal function mocks. External mock
817functions are built using their own separate INF file and internal mock
818functions are built as source files directly referenced in the GoogleTest
819INF file that builds the test application.
820
821#### FunctionMockLib Mocks - Build External Mock Functions
822
823The building of external mock functions is done using their own separate INF
824file which is placed in the same location as the associated source file
825containing the mock function definitions. The name of the INF file is exactly
826the same as the mock function definitions file, but uses the `.inf` extension
827rather than `.cpp`.
828
829Within the `.inf` file the `BASE_NAME` should be set to the same name as the
830file (minus the extension), the `MODULE_TYPE` should be set to
831`HOST_APPLICATION`, and the `LIBRARY_CLASS` should be the same as the
832`BASE_NAME` but without the `Mock` prefix.
833
834The `[Sources]` section will contain the single mock function definition
835source file, the `[Packages]` section will contain all the necessary DEC
836files to compile the mock functions (which at a minimum will include the
837`UnitTestFrameworkPkg.dec` file), the `[LibraryClasses]` section will contain
838the `GoogleTestLib`, and the `[BuildOptions]` will need to append the `/EHsc`
839compilation flag to all MSFT builds to enable proper use of the C++ exception
840handler. Below is the complete `MockUefiLib.inf` as an example.
841
842```
843[Defines]
844 INF_VERSION = 0x00010005
845 BASE_NAME = MockUefiLib
846 FILE_GUID = 47211F7A-6D90-4DFB-BDF9-610B69197C2E
847 MODULE_TYPE = HOST_APPLICATION
848 VERSION_STRING = 1.0
849 LIBRARY_CLASS = UefiLib
850
851#
852# The following information is for reference only and not required by the build tools.
853#
854# VALID_ARCHITECTURES = IA32 X64
855#
856
857[Sources]
858 MockUefiLib.cpp
859
860[Packages]
861 MdePkg/MdePkg.dec
862 UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
863
864[LibraryClasses]
865 GoogleTestLib
866
867[BuildOptions]
868 MSFT:*_*_*_CC_FLAGS = /EHsc
869```
870
871To ensure that this specific set of mock functions are always buildable even
872if no test uses it yet, this created INF file needs to be added into the
873`[Components]` section of the associated `Test` DSC file for the package in
874which this INF file resides. For example, the above `MockUefiLib.inf` would
875need to be added to the `MdePkg/Test/MdePkgHostTest.dsc` file as shown below.
876
877```
878[Components]
879 MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.inf
880```
881
882This created INF file will also be referenced within the necessary `Test` DSC
883files in order to include the mock function definitions in the test
884applications which use this set of mock functions, but more on that later.
885
886One small additional requirement is that if this INF file is added into a
887package that does not yet have any other external mock functions in it, then
888that package's DEC file will need to have the mock include directory (more
889specifically the `Test/Mock/Include` directory) added to its `[Includes]`
890section so that test files who want to use the mock functions will be able to
891locate the mock function header file. For example, if `MockUefiLib.inf` were
892the first mock added to the `MdePkg`, then the below snippet would need to be
893added to the `MdePkg.dec` file.
894
895```
896[Includes]
897 Test/Mock/Include
898```
899
900#### FunctionMockLib Mocks - Build Internal Mock Functions
901
902The building of internal mock functions is done using the GoogleTest INF file
903that already needs to exist to build the test application. This is easy to
904manage since the source and header files for the internal mock functions are
905also located in the same GoogleTest directory as the GoogleTest INF file that
906will reference them.
907
908The only additions that are required to the GoogleTest INF file are that the
909mock function definitions file be added to the `[Sources]` section, the
910`UnitTestFrameworkPkg.dec` file be added to the `[Packages]` section, and the
911`GoogleTestLib` and `SubhookLib` be added to the `[LibraryClasses]` section.
912Below is a minimal contrived example for a `MyModuleGoogleTest.inf` that uses a
913`MockMyModuleInternalFunctions.cpp` source file for its internal mock functions.
914
915```
916[Defines]
917 INF_VERSION = 0x00010017
918 BASE_NAME = MyModuleGoogleTest
919 FILE_GUID = 814B09B9-2D51-4786-8A77-2E10CD1C55F3
920 VERSION_STRING = 1.0
921 MODULE_TYPE = HOST_APPLICATION
922
923#
924# The following information is for reference only and not required by the build tools.
925#
926# VALID_ARCHITECTURES = IA32 X64
927#
928
929[Sources]
930 MyModuleGoogleTest.cpp
931 MockMyModuleInternalFunctions.cpp
932
933[Packages]
934 MdePkg/MdePkg.dec
935 UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
936
937[LibraryClasses]
938 GoogleTestLib
939 SubhookLib
940```
941
942## GoogleTest Samples
943
944There is a sample unit test provided as both an example of how to write a unit test and leverage
945many of the GoogleTest features. This sample can be found in the `Test/GoogleTest/Sample/SampleGoogleTest`
946directory.
947
948The sample is provided for the HOST_APPLICATION build type, which can be run on a host system without
949needing a target.
950
951There is also a sample unit test provided as both an example of how to write a unit test with
952mock functions and leverage some of the gMock features. This sample can be found in the
953`SecurityPkg/Library/SecureBootVariableLib/GoogleTest` directory.
954
955It too is provided for the HOST_APPLICATION build type, which can be run on a host system without
956needing a target.
957
958## GoogleTest Usage
959
960This section is built a lot like a "Getting Started". We'll go through some of the components that are needed
961when constructing a unit test and some of the decisions that are made by the test writer. We'll also describe
962how to check for expected conditions in test cases and a bit of the logging characteristics.
963
964Most of these examples will refer to the `SampleGoogleTestHost` app found in this package, but
965the examples related to mock functions will refer to the `SecureBootVariableLibGoogleTest` app
966found in the `SecurityPkg`.
967
968### GoogleTest Requirements - INF
969
970In our INF file, we'll need to bring in the `GoogleTestLib` library. Conveniently, the interface
971header for the `GoogleTestLib` is in `UnitTestFrameworkPkg`, so you shouldn't need to depend on any other
972packages. As long as your DSC file knows where to find the lib implementation that you want to use,
973you should be good to go.
974
975See this example in `SampleGoogleTestHost.inf`...
976
977```
978[Packages]
979 MdePkg/MdePkg.dec
980 UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
981
982[LibraryClasses]
983 GoogleTestLib
984 BaseLib
985 DebugLib
986```
987
988Also, if you want your test to automatically be picked up by the Test Runner plugin, you will need
989to make sure that the module `BASE_NAME` contains the word `Test`...
990
991```
992[Defines]
993 BASE_NAME = SampleGoogleTestHost
994```
995
996### GoogleTest Requirements - DSC
997
998In our DSC file, we'll need to bring in the INF file that was just created into the `[Components]`
999section so that the unit tests will be built.
1000
1001See this example in `UnitTestFrameworkPkgHostTest.dsc`...
1002
1003```
1004[Components]
1005 UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTestHost.inf
1006```
1007
1008Also, based on the type of tests that are being created, the associated DSC include file from the
1009UnitTestFrameworkPkg for Host or Target based tests should also be included at the top of the DSC
1010file.
1011
1012```
1013!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
1014```
1015
1016Lastly, in the case that the test build has specific dependent libraries associated with it,
1017they should be added in the \<LibraryClasses\> sub-section for the INF file in the
1018`[Components]` section of the DSC file. Note that it is within this sub-section where you can
1019control whether the design or mock version of a component is linked into the test exectuable.
1020
1021See this example in `SecurityPkgHostTest.dsc` where the `SecureBootVariableLib` design is
1022being tested using mock versions of `UefiRuntimeServicesTableLib`, `PlatformPKProtectionLib`,
1023and `UefiLib`...
1024
1025```
1026[Components]
1027 SecurityPkg/Library/SecureBootVariableLib/GoogleTest/SecureBootVariableLibGoogleTest.inf {
1028 <LibraryClasses>
1029 SecureBootVariableLib|SecurityPkg/Library/SecureBootVariableLib/SecureBootVariableLib.inf
1030 UefiRuntimeServicesTableLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiRuntimeServicesTableLib/MockUefiRuntimeServicesTableLib.inf
1031 PlatformPKProtectionLib|SecurityPkg/Test/Mock/Library/GoogleTest/MockPlatformPKProtectionLib/MockPlatformPKProtectionLib.inf
1032 UefiLib|MdePkg/Test/Mock/Library/GoogleTest/MockUefiLib/MockUefiLib.inf
1033 }
1034```
1035
1036### GoogleTest Requirements - Code
1037
1038GoogleTest applications are implemented in C++, so make sure that your test file has
1039a `.cpp` extension. With that behind us, not to state the obvious, but let's make sure
1040we have the following includes before getting too far along in the file...
1041
1042```cpp
1043#include <Library/GoogleTestLib.h>
1044extern "C" {
1045 #include <Uefi.h>
1046 #include <Library/BaseLib.h>
1047 #include <Library/DebugLib.h>
1048}
1049```
1050
1051The first include brings in the GoogleTest definitions. Other EDK II related include
1052files must be wrapped in `extern "C" {}` because they are C include files. Link
1053failures will occur if this is not done.
1054
1055Also, when using GoogleTest it is helpful to add a `using` declaration for its
1056`testing` namespace. This `using` statement greatly reduces the amount of code you
1057need to write in the tests when referencing the utilities within the `testing`
1058namespace. For example, instead of writing `::testing::Return` or `::testing::Test`,
1059you can just write `Return` or `Test` respectively, and these types of references
1060occur numerous times within the tests.
1061
1062Lastly, in the case that tests within a GoogleTest application require the usage of
1063mock functions, it is also necessary to include the header files for those interfaces
1064as well. As an example, the `SecureBootVariableLibGoogleTest` uses the mock versions
1065of `UefiLib` and `UefiRuntimeServicesTableLib`. So its test file contains the below
1066includes. Note that the `using` declaration mentioned above is also shown in the code
1067below for completeness of the example.
1068
1069```cpp
1070#include <Library/GoogleTestLib.h>
1071#include <GoogleTest/Library/MockUefiLib.h>
1072#include <GoogleTest/Library/MockUefiRuntimeServicesTableLib.h>
1073
1074extern "C" {
1075 #include <Uefi.h>
1076 ...
1077}
1078
1079using namespace testing;
1080```
1081
1082Now that we've got that squared away, let's look at our 'Main()' routine (or DriverEntryPoint() or whatever).
1083
1084### GoogleTest Configuration
1085
1086Unlike the Framework, GoogleTest does not require test suites or test cases to
1087be registered. Instead, the test cases declare the test suite name and test
1088case name as part of their implementation. The only requirement for GoogleTest
1089is to have a `main()` function that initializes the GoogleTest infrastructure
1090and calls the service `RUN_ALL_TESTS()` to run all the unit tests.
1091
1092```cpp
1093int main(int argc, char* argv[]) {
1094 testing::InitGoogleTest(&argc, argv);
1095 return RUN_ALL_TESTS();
1096}
1097```
1098
1099However, while GoogleTest does not require test suites or test cases to be
1100registered, there is still one rule within EDK II that currently needs to be
1101followed. This rule is that all tests for a given GoogleTest application must
1102be contained within the same source file that contains the `main()` function
1103shown above. These tests can be written directly in the file or a `#include`
1104can be used to add them into the file indirectly.
1105
1106The reason for this is due to EDK II taking the host application INF file and
1107first compiling all of its source files into a static library. This static
1108library is then linked into the final host application. The problem with this
1109method is that only the tests in the object file containing the `main()`
1110function are linked into the final host application. This is because the other
1111tests are contained in their own object files within the static library and
1112they have no symbols in them that the final host application depends on, so
1113those object files are not linked into the final host application.
1114
1115### GoogleTest - A Simple Test Case
1116
1117Below is a sample test case from `SampleGoogleTestHost`.
1118
1119```cpp
1120TEST(SimpleMathTests, OnePlusOneShouldEqualTwo) {
1121 UINTN A;
1122 UINTN B;
1123 UINTN C;
1124
1125 A = 1;
1126 B = 1;
1127 C = A + B;
1128
1129 ASSERT_EQ (C, 2);
1130}
1131```
1132
1133This uses the simplest form of a GoogleTest unit test using `TEST()` that
1134declares the test suite name and the unit test name within that test suite.
1135The unit test performs actions and typically makes calls to the code under test
1136and contains test assertions to verify that the code under test behaves as
1137expected for the given inputs.
1138
1139In this test case, the `ASSERT_EQ` assertion is being used to establish that the business logic has functioned
1140correctly. There are several assertion macros, and you are encouraged to use one that matches as closely to your
1141intended test criterium as possible, because the logging is specific to the macro and more specific macros have more
1142detailed logs. When in doubt, there are always `ASSERT_TRUE` and `ASSERT_FALSE`. Assertion macros that fail their
1143test criterium will immediately return from the test case with a failed status and log an error string.
1144_Note_ that this early return can have implications for memory leakage.
1145
1146For most `ASSERT` macros in GoogleTest there is also an equivalent `EXPECT` macro. Both macro versions
1147will ultimately cause the `TEST` to fail if the check fails. However, the difference between the two
1148macro versions is that when the check fails, the `ASSERT` version immediately returns from the `TEST`
1149while the `EXPECT` version continues running the `TEST`.
1150
1151There is no return status from a GooglTest unit test. If no assertions (or expectations) are
1152triggered then the unit test has a passing status.
1153
1154### GoogleTest - A gMock Test Case
1155
1156Below is a sample test case from `SecureBootVariableLibGoogleTest`. Although
1157actually, the test case is not written exactly like this in the test file, but
1158more on that in a bit.
1159
1160```cpp
1161TEST(SetSecureBootModeTest, SetVarError) {
1162 MockUefiRuntimeServicesTableLib RtServicesMock;
1163 UINT8 SecureBootMode;
1164 EFI_STATUS Status;
1165
1166 // Any random magic number can be used for these tests
1167 SecureBootMode = 0xAB;
1168
1169 EXPECT_CALL(RtServicesMock, gRT_SetVariable)
1170 .WillOnce(Return(EFI_INVALID_PARAMETER));
1171
1172 Status = SetSecureBootMode(SecureBootMode);
1173 EXPECT_EQ(Status, EFI_INVALID_PARAMETER);
1174}
1175```
1176
1177Keep in mind that this test is written to verify that `SetSecureBootMode()` will
1178return `EFI_INVALID_PARAMETER` when the call to `gRT->SetVariable()` within the
1179implementation of `SetSecureBootMode()` returns `EFI_INVALID_PARAMETER`. With that
1180in mind, let's discuss how a mock function is used to accomplish this in the test.
1181
1182In this test case, the `MockUefiRuntimeServicesTableLib` interface is instantiated as
1183`RtServicesMock` which enables its associated mock functions. These interface
1184instantiations that contain the mock functions are very important for mock function
1185based unit tests because without these instantiations, the mock functions within that
1186interface will not exist and can not be used.
1187
1188The next line of interest is the `EXPECT_CALL`, which is a standard part of the gMock
1189framework. This macro is telling the test that a call is expected to occur to a
1190specific function on a specific interface. The first argument is the name of the
1191interface object that was instantiated in this test, and the second argument is the
1192name of the mock function within that interface that is expected to be called. The
1193`WillOnce(Return(EFI_INVALID_PARAMETER))` associated with this `EXPECT_CALL` states
1194that the `gRT_SetVariable()` function (remember from earlier in this documentation
1195that this refers to the `gRT->SetVariable()` function) will be called once during
1196this test, and when it does get called, we want it to return `EFI_INVALID_PARAMETER`.
1197
1198Once this `EXPECT_CALL` has been setup, the call to `SetSecureBootMode()` occurs in
1199the test, and its return value is saved in `Status` so that it can be tested. Based
1200on the `EXPECT_CALL` that was setup earlier, when `SetSecureBootMode()` internally
1201calls `gRT->SetVariable()`, it returns `EFI_INVALID_PARAMETER`. This value should
1202then be returned by `SetSecureBootMode()`, and the
1203`EXPECT_EQ(Status, EFI_INVALID_PARAMETER)` verifies this is the case.
1204
1205There is much more that can be done with `EXPECT_CALL` and mock functions, but we
1206will leave those details to be explained in the gMock documentation.
1207
1208Now it was mentioned earlier that this test case is not written exactly like this
1209in the test file, and the next section describes how this test is slightly
1210refactored to reduce the total amount of code in the entire test suite.
1211
1212### GoogleTest - A gMock Test Case (refactored)
1213
1214The sample test case from `SecureBootVariableLibGoogleTest` in the prior section is
1215actually written as shown below.
1216
1217```cpp
1218class SetSecureBootModeTest : public Test {
1219 protected:
1220 MockUefiRuntimeServicesTableLib RtServicesMock;
1221 UINT8 SecureBootMode;
1222 EFI_STATUS Status;
1223
1224 void SetUp() override {
1225 // Any random magic number can be used for these tests
1226 SecureBootMode = 0xAB;
1227 }
1228};
1229
1230TEST_F(SetSecureBootModeTest, SetVarError) {
1231 EXPECT_CALL(RtServicesMock, gRT_SetVariable)
1232 .WillOnce(Return(EFI_INVALID_PARAMETER));
1233
1234 Status = SetSecureBootMode(SecureBootMode);
1235 EXPECT_EQ(Status, EFI_INVALID_PARAMETER);
1236}
1237```
1238
1239This code may at first seem more complicated, but you will notice that the code
1240with in it is still the same. There is still a `MockUefiRuntimeServicesTableLib`
1241instantiation, there is still a `SecureBootMode` and `Status` variable defined,
1242there is still an `EXPECT_CALL`, and etc. However, the benefit of constructing
1243the test this way is that the new `TEST_F()` requires less code than the prior
1244`TEST()`.
1245
1246This is made possible by the usage of what GoogleTest calls a _test fixture_.
1247This concept of a test fixture allows multiple tests to use (or more specifically
1248inherit from a base class) a common set of variables and initial conditions.
1249Notice that using `TEST_F()` requires the first argument to be a name that aligns
1250with a test fixture (in this case `SetSecureBootModeTest`), and the second
1251argument is the name of the test (just like in the `TEST()` macro).
1252
1253All `TEST_F()` tests that use a specific test fixture can be thought of as having
1254all of that test fixture's variables automatically defined in the test as well as
1255having that text fixture's `SetUp()` function called before entering the test.
1256
1257This means that another `TEST_F()` can be written without needing to worry about
1258defining a bunch of variables or instantiating a bunch of interfaces for mock
1259functions. For example, the below test (also in `SecureBootVariableLibGoogleTest`)
1260uses the same test fixture and makes use of its `RtServicesMock`, `Status`, and
1261`SecureBootMode` variables.
1262
1263```cpp
1264TEST_F(SetSecureBootModeTest, PropogateModeToSetVar) {
1265 EXPECT_CALL(RtServicesMock,
1266 gRT_SetVariable(
1267 Char16StrEq(EFI_CUSTOM_MODE_NAME),
1268 BufferEq(&gEfiCustomModeEnableGuid, sizeof(EFI_GUID)),
1269 EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS,
1270 sizeof(SecureBootMode),
1271 BufferEq(&SecureBootMode, sizeof(SecureBootMode))))
1272 .WillOnce(Return(EFI_SUCCESS));
1273
1274 Status = SetSecureBootMode(SecureBootMode);
1275 EXPECT_EQ(Status, EFI_SUCCESS);
1276}
1277```
1278
1279The biggest benefit is that the `TEST_F()` code can now focus on what is being
1280tested and not worry about any repetitive setup. There is more that can be done
1281with test fixtures, but we will leave those details to be explained in the
1282gMock documentation.
1283
1284Now, as for what is in the above test, it is slightly more complicated than the
1285first test. So let's explain this added complexity and what it is actually
1286testing. In this test, there is still an `EXPECT_CALL` for the
1287`gRT_SetVariable()` function. However, in this test we are stating that we
1288expect the input arguments passed to `gRT_SetVariable()` be specific values.
1289The order they are provided in the `EXPECT_CALL` align with the order of the
1290arguments in the `gRT_SetVariable()` function. In this case the order of the
1291`gRT_SetVariable()` arguments is as shown below.
1292
1293```cpp
1294IN CHAR16 *VariableName,
1295IN EFI_GUID *VendorGuid,
1296IN UINT32 Attributes,
1297IN UINTN DataSize,
1298IN VOID *Data
1299```
1300
1301So in the `EXPECT_CALL` we are stating that the call to `gRT_SetVariable()`
1302will be made with the below input argument values.
1303
13041. `VariableName` is equal to the `EFI_CUSTOM_MODE_NAME` string
13052. `VendorGuid` is equal to the `gEfiCustomModeEnableGuid` GUID (which has a byte length of `sizeof(EFI_GUID)`)
13063. `Attributes` is equal to `EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS`
13074. `DataSize` is equal to `sizeof(SecureBootMode)`
13085. `Data` is equal to `SecureBootMode` (which has a byte length of `sizeof(SecureBootMode)`)
1309
1310If any one of these input arguments does not match in the actual call to
1311`gRT_SetVariable()` in the design, then the test will fail. There is much more
1312that can be done with `EXPECT_CALL` and mock functions, but again we will
1313leave those details to be explained in the gMock documentation.
1314
1315### GoogleTest - More Complex Cases
1316
1317To write more advanced tests, take a look at the
1318[GoogleTest User's Guide](http://google.github.io/googletest/).
1319
1320## Development
1321
1322### Iterating on a Single Test
1323
1324When using the EDK2 Pytools for CI testing, the host-based unit tests will be built and run on any build that includes
1325the `NOOPT` build target.
1326
1327If you are trying to iterate on a single test, a convenient pattern is to build only that test module. For example,
1328the following command will build only the SafeIntLib host-based test from the MdePkg...
1329
1330```bash
1331stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=VS2017 -p MdePkg -t NOOPT BUILDMODULE=MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.inf
1332```
1333
1334### Hooking BaseLib
1335
1336Most unit test mocking can be performed by the functions provided in the UnitTestFrameworkPkg libraries, but since
1337BaseLib is consumed by the Framework itself, it requires different techniques to substitute parts of the
1338functionality.
1339
1340To solve some of this, the UnitTestFrameworkPkg consumes a special implementation of BaseLib for host-based tests.
1341This implementation contains a [hook table](https://github.com/tianocore/edk2/blob/e188ecc8b4aed8fdd26b731d43883861f5e5e7b4/MdePkg/Test/UnitTest/Include/Library/UnitTestHostBaseLib.h#L507)
1342that can be used to substitute test functionality for any of the BaseLib functions. By default, this implementation
1343will use the underlying BaseLib implementation, so the unit test writer only has to supply minimal code to test a
1344particular case.
1345
1346### Debugging the Framework Itself
1347
1348While most of the tests that are produced by the UnitTestFrameworkPkg are easy to step through in a debugger, the Framework
1349itself consumes code (mostly Cmocka) that sets its own build flags. These flags cause parts of the Framework to not
1350export symbols and captures exceptions, and as such are harder to debug. We have provided a Stuart parameter to force
1351symbolic debugging to be enabled.
1352
1353You can run a build by adding the `BLD_*_UNIT_TESTING_DEBUG=TRUE` parameter to enable this build option.
1354
1355```bash
1356stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=VS2019 -p MdePkg -t NOOPT BLD_*_UNIT_TESTING_DEBUG=TRUE
1357```
1358
1359## Building and Running Host-Based Tests
1360
1361The EDK2 CI infrastructure provides a convenient way to run all host-based tests -- in the the entire tree or just
1362selected packages -- and aggregate all the reports, including highlighting any failures. This functionality is
1363provided through the Stuart build system (published by EDK2-PyTools) and the `NOOPT` build target. The sections that
1364follow use Framework examples. Unit tests based on GoogleTest are built and run the same way. The text output and
1365JUNIT XML output format have small differences.
1366
1367### Building Locally
1368
1369First, to make sure you're working with the latest PyTools, run the following command:
1370
1371```bash
1372# Would recommend running this in a Python venv, but that's out of scope for this doc.
1373python -m pip install --upgrade -r ./pip-requirements.txt
1374```
1375
1376After that, the following commands will set up the build and run the host-based tests.
1377
1378```bash
1379# Setup repo for building
1380# stuart_setup -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=<GCC5, VS2019, etc.>
1381stuart_setup -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2019
1382
1383# Update all binary dependencies
1384# stuart_update -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=<GCC5, VS2019, etc.>
1385stuart_update -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2019
1386
1387# Build and run the tests
1388# stuart_ci_build -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=<GCC5, VS2019, etc.> -t NOOPT [-p <Package Name>]
1389stuart_ci_build -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2019 -t NOOPT -p MdePkg
1390```
1391
1392### Evaluating the Results
1393
1394In your immediate output, any build failures will be highlighted. You can see these below as "WARNING" and "ERROR" messages.
1395
1396```text
1397(edk_env) PS C:\_uefi\edk2> stuart_ci_build -c .\.pytool\CISettings.py TOOL_CHAIN_TAG=VS2019 -t NOOPT -p MdePkg
1398
1399SECTION - Init SDE
1400SECTION - Loading Plugins
1401SECTION - Start Invocable Tool
1402SECTION - Getting Environment
1403SECTION - Loading plugins
1404SECTION - Building MdePkg Package
1405PROGRESS - --Running MdePkg: Host Unit Test Compiler Plugin NOOPT --
1406WARNING - Allowing Override for key TARGET_ARCH
1407PROGRESS - Start time: 2020-07-27 17:18:08.521672
1408PROGRESS - Setting up the Environment
1409PROGRESS - Running Pre Build
1410PROGRESS - Running Build NOOPT
1411PROGRESS - Running Post Build
1412SECTION - Run Host based Unit Tests
1413SUBSECTION - Testing for architecture: X64
1414WARNING - TestBaseSafeIntLibHost.exe Test Failed
1415WARNING - Test SafeInt8ToUint8 - UT_ASSERT_EQUAL(0x5b:5b, Result:5c)
1416c:\_uefi\edk2\MdePkg\Test\UnitTest\Library\BaseSafeIntLib\TestBaseSafeIntLib.c:35: error: Failure!
1417ERROR - Plugin Failed: Host-Based Unit Test Runner returned 1
1418CRITICAL - Post Build failed
1419PROGRESS - End time: 2020-07-27 17:18:19.792313 Total time Elapsed: 0:00:11
1420ERROR - --->Test Failed: Host Unit Test Compiler Plugin NOOPT returned 1
1421ERROR - Overall Build Status: Error
1422PROGRESS - There were 1 failures out of 1 attempts
1423SECTION - Summary
1424ERROR - Error
1425
1426(edk_env) PS C:\_uefi\edk2>
1427```
1428
1429If a test fails, you can run it manually to get more details...
1430
1431```text
1432(edk_env) PS C:\_uefi\edk2> .\Build\MdePkg\HostTest\NOOPT_VS2019\X64\TestBaseSafeIntLibHost.exe
1433
1434Int Safe Lib Unit Test Application v0.1
1435---------------------------------------------------------
1436------------ RUNNING ALL TEST SUITES --------------
1437---------------------------------------------------------
1438---------------------------------------------------------
1439RUNNING TEST SUITE: Int Safe Conversions Test Suite
1440---------------------------------------------------------
1441[==========] Running 71 test(s).
1442[ RUN ] Test SafeInt8ToUint8
1443[ ERROR ] --- UT_ASSERT_EQUAL(0x5b:5b, Result:5c)
1444[ LINE ] --- c:\_uefi\edk2\MdePkg\Test\UnitTest\Library\BaseSafeIntLib\TestBaseSafeIntLib.c:35: error: Failure!
1445[ FAILED ] Test SafeInt8ToUint8
1446[ RUN ] Test SafeInt8ToUint16
1447[ OK ] Test SafeInt8ToUint16
1448[ RUN ] Test SafeInt8ToUint32
1449[ OK ] Test SafeInt8ToUint32
1450[ RUN ] Test SafeInt8ToUintn
1451[ OK ] Test SafeInt8ToUintn
1452...
1453```
1454
1455You can also, if you are so inclined, read the output from the exact instance of the test that was run during
1456`stuart_ci_build`. The output file can be found on a path that looks like:
1457
1458`Build/<Package>/HostTest/<Arch>/<TestName>.<TestSuiteName>.<Arch>.result.xml`
1459
1460A sample of this output looks like:
1461
1462```xml
1463<!--
1464 Excerpt taken from:
1465 Build\MdePkg\HostTest\NOOPT_VS2019\X64\TestBaseSafeIntLibHost.exe.Int Safe Conversions Test Suite.X64.result.xml
1466 -->
1467<?xml version="1.0" encoding="UTF-8" ?>
1468<testsuites>
1469 <testsuite name="Int Safe Conversions Test Suite" time="0.000" tests="71" failures="1" errors="0" skipped="0" >
1470 <testcase name="Test SafeInt8ToUint8" time="0.000" >
1471 <failure><![CDATA[UT_ASSERT_EQUAL(0x5c:5c, Result:5b)
1472c:\_uefi\MdePkg\Test\UnitTest\Library\BaseSafeIntLib\TestBaseSafeIntLib.c:35: error: Failure!]]></failure>
1473 </testcase>
1474 <testcase name="Test SafeInt8ToUint16" time="0.000" >
1475 </testcase>
1476 <testcase name="Test SafeInt8ToUint32" time="0.000" >
1477 </testcase>
1478 <testcase name="Test SafeInt8ToUintn" time="0.000" >
1479 </testcase>
1480```
1481
1482### XML Reporting Mode
1483
1484Unit test applications using Framework are built using Cmocka that requires the
1485following environment variables to be set to generate structured XML output
1486rather than text:
1487
1488```
1489CMOCKA_MESSAGE_OUTPUT=xml
1490CMOCKA_XML_FILE=<absolute or relative path to output file>
1491```
1492
1493Unit test applications using GoogleTest require the following environment
1494variable to be set to generate structured XML output rather than text:
1495
1496```
1497GTEST_OUTPUT=xml:<absolute or relative path to output file>
1498```
1499
1500This mode is used by the test running plugin to aggregate the results for CI test status reporting in the web view.
1501
1502### Code Coverage
1503
1504Host based Unit Tests will automatically enable coverage data.
1505
1506For Windows, this is primarily leveraged for pipeline builds, but this can be leveraged locally using the
1507OpenCppCoverage windows tool to parse coverage data to cobertura xml format.
1508
1509- Windows Prerequisite
1510 ```bash
1511 Download and install https://github.com/OpenCppCoverage/OpenCppCoverage/releases
1512 python -m pip install --upgrade -r ./pip-requirements.txt
1513 stuart_ci_build -c .pytool/CISettings.py -t NOOPT TOOL_CHAIN_TAG=VS2019 -p MdeModulePkg
1514 Open Build/coverage.xml
1515 ```
1516
1517 - How to see code coverage data on IDE Visual Studio
1518 ```
1519 Open Visual Studio VS2019 or above version
1520 Click "Tools" -> "OpenCppCoverage Settings"
1521 Fill your execute file into "Program to run:"
1522 Click "Tools" -> "Run OpenCppCoverage"
1523 ```
1524
1525
1526For Linux, this is primarily leveraged for pipeline builds, but this can be leveraged locally using the
1527lcov linux tool, and parsed using the lcov_cobertura python tool to parse it to cobertura xml format.
1528
1529- Linux Prerequisite
1530 ```bash
1531 sudo apt-get install -y lcov
1532 python -m pip install --upgrade -r ./pip-requirements.txt
1533 stuart_ci_build -c .pytool/CISettings.py -t NOOPT TOOL_CHAIN_TAG=GCC5 -p MdeModulePkg
1534 Open Build/coverage.xml
1535 ```
1536 - How to see code coverage data on IDE Visual Studio Code
1537 ```
1538 Download plugin "Coverage Gutters"
1539 Press Hot Key "Ctrl + Shift + P" and click option "Coverage Gutters: Display Coverage"
1540 ```
1541
1542
1543### Important Note
1544
1545This works on both Windows and Linux but is currently limited to x64 architectures. Working on getting others, but we
1546also welcome contributions.
1547
1548## Framework Known Limitations
1549
1550### PEI, DXE, SMM
1551
1552While sample tests have been provided for these execution environments, only cursory build validation
1553has been performed. Care has been taken while designing the frameworks to allow for execution during
1554boot phases, but only UEFI Shell and host-based tests have been thoroughly evaluated. Full support for
1555PEI, DXE, and SMM is forthcoming, but should be considered beta/staging for now.
1556
1557### Host-Based Support vs Other Tests
1558
1559The host-based test framework is powered internally by the Cmocka framework. As such, it has abilities
1560that the target-based tests don't (yet). It would be awesome if this meant that it was a super set of
1561the target-based tests, and it worked just like the target-based tests but with more features. Unfortunately,
1562this is not the case. While care has been taken to keep them as close as possible, there are a few known
1563inconsistencies that we're still ironing out. For example, the logging messages in the target-based tests
1564are cached internally and associated with the running test case. They can be saved later as part of the
1565reporting lib. This isn't currently possible with host-based. Only the assertion failures are logged.
1566
1567We will continue trying to make these as similar as possible.
1568
1569## Unit Test Location/Layout Rules
1570
1571Code/Test | Location
1572--------- | --------
1573Host-Based Unit Tests for a Library/Protocol/PPI/GUID Interface | If what's being tested is an interface (e.g. a library with a public header file, like DebugLib) and the test is agnostic to a specific implementation, then the test should be scoped to the parent package.<br/>Example: `MdePkg/Test/UnitTest/[Library/Protocol/Ppi/Guid]/`<br/><br/>A real-world example of this is the BaseSafeIntLib test in MdePkg.<br/>`MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibHost.inf`
1574Host-Based Unit Tests for a Library/Driver (PEI/DXE/SMM) implementation | If what's being tested is a specific implementation (e.g. BaseDebugLibSerialPort for DebugLib), then the test should be scoped to the implementation directory itself, in a UnitTest (or GoogleTest) subdirectory.<br/><br/>Module Example: `MdeModulePkg/Universal/EsrtFmpDxe/UnitTest/`<br/>Library Example: `MdePkg/Library/BaseMemoryLib/UnitTest/`<br/>Library Example (GoogleTest): `SecurityPkg/Library/SecureBootVariableLib/GoogleTest/`
1575Host-Based Tests for a Functionality or Feature | If you're writing a functional test that operates at the module level (i.e. if it's more than a single file or library), the test should be located in the package-level Tests directory under the HostFuncTest subdirectory.<br/>For example, if you were writing a test for the entire FMP Device Framework, you might put your test in:<br/>`FmpDevicePkg/Test/HostFuncTest/FmpDeviceFramework`<br/><br/>If the feature spans multiple packages, it's location should be determined by the package owners related to the feature.
1576Non-Host-Based (PEI/DXE/SMM/Shell) Tests for a Functionality or Feature | Similar to Host-Based, if the feature is in one package, should be located in the `*Pkg/Test/[Shell/Dxe/Smm/Pei]Test` directory.<br/><br/>If the feature spans multiple packages, it's location should be determined by the package owners related to the feature.<br/><br/>USAGE EXAMPLES<br/>PEI Example: MP_SERVICE_PPI. Or check MTRR configuration in a notification function.<br/> SMM Example: a test in a protocol callback function. (It is different with the solution that SmmAgent+ShellApp)<br/>DXE Example: a test in a UEFI event call back to check SPI/SMRAM status. <br/> Shell Example: the SMM handler audit test has a shell-based app that interacts with an SMM handler to get information. The SMM paging audit test gathers information about both DXE and SMM. And the SMM paging functional test actually forces errors into SMM via a DXE driver.
1577
1578### Example Directory Tree
1579
1580```text
1581<PackageName>Pkg/
1582 ComponentY/
1583 ComponentY.inf
1584 ComponentY.c
1585 GoogleTest/
1586 ComponentYHostGoogleTest.inf # Host-Based Test for Driver Module
1587 ComponentYGoogleTest.cpp
1588 UnitTest/
1589 ComponentYHostUnitTest.inf # Host-Based Test for Driver Module
1590 ComponentYUnitTest.c
1591
1592 Library/
1593 GeneralPurposeLibBase/
1594 ...
1595
1596 GeneralPurposeLibSerial/
1597 ...
1598
1599 SpecificLibDxe/
1600 SpecificLibDxe.c
1601 SpecificLibDxe.inf
1602 GoogleTest/ # Host-Based Test for Specific Library Implementation
1603 SpecificLibDxeHostGoogleTest.cpp
1604 SpecificLibDxeHostGoogleTest.inf
1605 UnitTest/ # Host-Based Test for Specific Library Implementation
1606 SpecificLibDxeHostUnitTest.c
1607 SpecificLibDxeHostUnitTest.inf
1608 Test/
1609 <Package>HostTest.dsc # Host-Based Test Apps
1610 GoogleTest/
1611 InterfaceX
1612 InterfaceXHostGoogleTest.inf # Host-Based App (should be in Test/<Package>HostTest.dsc)
1613 InterfaceXUnitTest.cpp # Test Logic
1614
1615 GeneralPurposeLib/ # Host-Based Test for any implementation of GeneralPurposeLib
1616 GeneralPurposeLibTest.cpp
1617 GeneralPurposeLibHostUnitTest.inf
1618
1619 UnitTest/
1620 InterfaceX
1621 InterfaceXHostUnitTest.inf # Host-Based App (should be in Test/<Package>HostTest.dsc)
1622 InterfaceXPeiUnitTest.inf # PEIM Target-Based Test (if applicable)
1623 InterfaceXDxeUnitTest.inf # DXE Target-Based Test (if applicable)
1624 InterfaceXSmmUnitTest.inf # SMM Target-Based Test (if applicable)
1625 InterfaceXShellUnitTest.inf # Shell App Target-Based Test (if applicable)
1626 InterfaceXUnitTest.c # Test Logic
1627
1628 GeneralPurposeLib/ # Host-Based Test for any implementation of GeneralPurposeLib
1629 GeneralPurposeLibTest.c
1630 GeneralPurposeLibHostUnitTest.inf
1631
1632 Mock/
1633 Include/
1634 GoogleTest/
1635 Library/
1636 MockGeneralPurposeLib.h
1637
1638 Library/
1639 GoogleTest/
1640 MockGeneralPurposeLib/
1641 MockGeneralPurposeLib.cpp
1642 MockGeneralPurposeLib.inf
1643
1644 <Package>Pkg.dsc # Standard Modules and any Target-Based Test Apps (including in Test/)
1645```
1646
1647### Future Locations in Consideration
1648
1649We don't know if these types will exist or be applicable yet, but if you write a support library or module that matches the following, please make sure they live in the correct place.
1650
1651Code/Test | Location
1652--------- | --------
1653Host-Based Library Implementations | Host-Based Implementations of common libraries (eg. MemoryAllocationLibHost) should live in the same package that declares the library interface in its .DEC file in the `*Pkg/HostLibrary` directory. Should have 'Host' in the name.
1654Host-Based Mocks and Stubs | Mock and Stub libraries should live in the `UefiTestFrameworkPkg/StubLibrary` with either 'Mock' or 'Stub' in the library name.
1655
1656### If still in doubt...
1657
1658Hop on GitHub and ask @corthon, @mdkinney, or @spbrogan. ;)
1659
1660## Copyright
1661
1662Copyright (c) Microsoft Corporation.
1663SPDX-License-Identifier: BSD-2-Clause-Patent
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette