From 3a70fc9fb4b4fba72eb32af4f7e78b4e58dee0fc Mon Sep 17 00:00:00 2001 From: Ken Lautner Date: Fri, 28 Jun 2024 20:07:25 -0700 Subject: [PATCH] Fix2 --- UnitTestFrameworkPkg/ReadMe.md | 58 +++++++++++++++------------------- 1 file changed, 26 insertions(+), 32 deletions(-) diff --git a/UnitTestFrameworkPkg/ReadMe.md b/UnitTestFrameworkPkg/ReadMe.md index 3a8ae40ac6..d8d5d45dc3 100644 --- a/UnitTestFrameworkPkg/ReadMe.md +++ b/UnitTestFrameworkPkg/ReadMe.md @@ -1093,22 +1093,6 @@ int main(int argc, char* argv[]) { } ``` -However, while GoogleTest does not require test suites or test cases to be -registered, there is still one rule within EDK II that currently needs to be -followed. This rule is that all tests for a given GoogleTest application must -be contained within the same source file that contains the `main()` function -shown above. These tests can be written directly in the file or a `#include` -can be used to add them into the file indirectly. - -The reason for this is due to EDK II taking the host application INF file and -first compiling all of its source files into a static library. This static -library is then linked into the final host application. The problem with this -method is that only the tests in the object file containing the `main()` -function are linked into the final host application. This is because the other -tests are contained in their own object files within the static library and -they have no symbols in them that the final host application depends on, so -those object files are not linked into the final host application. - ### GoogleTest - A Simple Test Case Below is a sample test case from `SampleGoogleTestHost`. @@ -1314,6 +1298,20 @@ leave those details to be explained in the gMock documentation. To write more advanced tests, take a look at the [GoogleTest User's Guide](http://google.github.io/googletest/). +## Development + +### Iterating on a Single Test + +When using the EDK2 Pytools for CI testing, the host-based unit tests will be built and run on any build that includes +the `NOOPT` build target. + +If you are trying to iterate on a single test, a convenient pattern is to build only that test module. For example, +the following command will build only the SafeIntLib host-based test from the MdePkg... + +```bash +stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=VS2017 -p MdePkg -t NOOPT BUILDMODULE=MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.inf +``` + ### Hooking BaseLib Most unit test mocking can be performed by the functions provided in the UnitTestFrameworkPkg libraries, but since @@ -1363,10 +1361,6 @@ After that, the following commands will set up the build and run the host-based # stuart_setup -c ./.pytool/CISettings.py TOOL_CHAIN_TAG= stuart_setup -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2019 -# Mu specific step to clone mu repos required for ci check -# stuart_ci_setup -c ./.pytool/CISettings.py TOOL_CHAIN_TAG= -stuart_ci_setup -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2019 - # Update all binary dependencies # stuart_update -c ./.pytool/CISettings.py TOOL_CHAIN_TAG= stuart_update -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2019 @@ -1563,7 +1557,7 @@ Code/Test | Location Host-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.
Example: `MdePkg/Test/UnitTest/[Library/Protocol/Ppi/Guid]/`

A real-world example of this is the BaseSafeIntLib test in MdePkg.
`MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibHost.inf` Host-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.

Module Example: `MdeModulePkg/Universal/EsrtFmpDxe/UnitTest/`
Library Example: `MdePkg/Library/BaseMemoryLib/UnitTest/`
Library Example (GoogleTest): `SecurityPkg/Library/SecureBootVariableLib/GoogleTest/` Host-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.
For example, if you were writing a test for the entire FMP Device Framework, you might put your test in:
`FmpDevicePkg/Test/HostFuncTest/FmpDeviceFramework`

If the feature spans multiple packages, it's location should be determined by the package owners related to the feature. -Non-Host-Based (PEI/DXE/SMM/UefiShell) Tests for a Functionality or Feature | Similar to Host-Based, if the feature is in one package, should be located in the `*Pkg/Test/[UefiShell/Dxe/Smm/Pei]Test` directory.

If the feature spans multiple packages, it's location should be determined by the package owners related to the feature.

USAGE EXAMPLES
PEI Example: MP_SERVICE_PPI. Or check MTRR configuration in a notification function.
SMM Example: a test in a protocol callback function. (It is different with the solution that SmmAgent+ShellApp)
DXE Example: a test in a UEFI event call back to check SPI/SMRAM status.
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. +Non-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.

If the feature spans multiple packages, it's location should be determined by the package owners related to the feature.

USAGE EXAMPLES
PEI Example: MP_SERVICE_PPI. Or check MTRR configuration in a notification function.
SMM Example: a test in a protocol callback function. (It is different with the solution that SmmAgent+ShellApp)
DXE Example: a test in a UEFI event call back to check SPI/SMRAM status.
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. ### Example Directory Tree @@ -1576,7 +1570,7 @@ Non-Host-Based (PEI/DXE/SMM/UefiShell) Tests for a Functionality or Feature | ComponentYHostGoogleTest.inf # Host-Based Test for Driver Module ComponentYGoogleTest.cpp UnitTest/ - ComponentYUnitTestHost.inf # Host-Based Test for Driver Module + ComponentYHostUnitTest.inf # Host-Based Test for Driver Module ComponentYUnitTest.c Library/ @@ -1593,8 +1587,8 @@ Non-Host-Based (PEI/DXE/SMM/UefiShell) Tests for a Functionality or Feature | SpecificLibDxeHostGoogleTest.cpp SpecificLibDxeHostGoogleTest.inf UnitTest/ # Host-Based Test for Specific Library Implementation - SpecificLibDxeUnitTest.c - SpecificLibDxeUnitTestHost.inf + SpecificLibDxeHostUnitTest.c + SpecificLibDxeHostUnitTest.inf Test/ HostTest.dsc # Host-Based Test Apps GoogleTest/ @@ -1608,16 +1602,16 @@ Non-Host-Based (PEI/DXE/SMM/UefiShell) Tests for a Functionality or Feature | UnitTest/ InterfaceX - InterfaceXUnitTestHost.inf # Host-Based App (should be in Test/HostTest.dsc) - InterfaceXUnitTestPei.inf # PEIM Target-Based Test (if applicable) - InterfaceXUnitTestDxe.inf # DXE Target-Based Test (if applicable) - InterfaceXUnitTestSmm.inf # SMM Target-Based Test (if applicable) - InterfaceXUnitTestUefiShell.inf # Shell App Target-Based Test (if applicable) + InterfaceXHostUnitTest.inf # Host-Based App (should be in Test/HostTest.dsc) + InterfaceXPeiUnitTest.inf # PEIM Target-Based Test (if applicable) + InterfaceXDxeUnitTest.inf # DXE Target-Based Test (if applicable) + InterfaceXSmmUnitTest.inf # SMM Target-Based Test (if applicable) + InterfaceXShellUnitTest.inf # Shell App Target-Based Test (if applicable) InterfaceXUnitTest.c # Test Logic GeneralPurposeLib/ # Host-Based Test for any implementation of GeneralPurposeLib GeneralPurposeLibTest.c - GeneralPurposeLibUnitTestHost.inf + GeneralPurposeLibHostUnitTest Mock/ Include/ @@ -1641,8 +1635,8 @@ the following, please make sure they live in the correct place. Code/Test | Location --------- | -------- -Host-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/Test/Library` directory. Should have 'Host' in the name. -Host-Based Mocks and Stubs | Mock and Stub libraries that require test infrastructure should live in the `UefiTestFrameworkPkg/Library` with either 'Mock' or 'Stub' in the library name. +Host-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. +Host-Based Mocks and Stubs | Mock and Stub libraries should live in the `UefiTestFrameworkPkg/StubLibrary` with either 'Mock' or 'Stub' in the library name. ### If still in doubt