summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael D Kinney <michael.d.kinney@intel.com>2024-10-22 00:28:19 -0700
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>2025-01-21 05:02:38 +0000
commitde06288019e62ee563d6958fb0fb7d0ffb8a2e62 (patch)
tree75f586dc73aebf20ac17666f3e6fbb65380fc342
parent8d0e23d998e6181b3ba032bfc7e3217f8c396c69 (diff)
downloadedk2-de06288019e62ee563d6958fb0fb7d0ffb8a2e62.tar.gz
UnitTestFrameworkPkg: Use /MTd and enable Address Sanitizers
* Update host based unit test VS20xx builds to use /MTd instead of /MT to enable use of debug libraries for host based unit tests. * Enable /fsanitize=address for host based unit test VS2019 builds * Enable /fsanitize=address for host based unit test VS2022 builds * Enable -fsanitize=address for host based unit test GCC builds * Add UNIT_TESTING_ADDRESS_SANITIZER_ENABLE define that is set to TRUE by default so it is always enabled, but can be set to FALSE to temporarily disable during development/debug of unit tests. * Add address sanitizer information to ReadMe.md Enabling the Address Sanitizer can detect double frees, buffer overflow, buffer underflow, access to invalid addresses, and various exceptions. These can be detected in both the unit test case sources as well as the code under test. Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
-rw-r--r--UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf2
-rw-r--r--UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.inf2
-rw-r--r--UnitTestFrameworkPkg/ReadMe.md51
-rw-r--r--UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc25
4 files changed, 71 insertions, 9 deletions
diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
index 0c522832e9..7835a333ea 100644
--- a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
+++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
@@ -28,6 +28,6 @@
UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
[BuildOptions]
- MSFT:*_*_*_CC_FLAGS == /c /EHs /Zi /Od /MT
+ MSFT:*_*_*_CC_FLAGS == /c /EHs /Zi /Od /MTd
GCC:*_*_IA32_CC_FLAGS == -g -c -fshort-wchar -fexceptions -O0 -m32 -malign-double -fno-pie
GCC:*_*_X64_CC_FLAGS == -g -c -fshort-wchar -fexceptions -O0 -m64 -fno-pie "-DEFIAPI=__attribute__((ms_abi))"
diff --git a/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.inf b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.inf
index 9a7673f179..7458df7948 100644
--- a/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.inf
+++ b/UnitTestFrameworkPkg/Library/UnitTestDebugAssertLib/UnitTestDebugAssertLibHost.inf
@@ -31,6 +31,6 @@
UnitTestLib
[BuildOptions]
- MSFT:*_*_*_CC_FLAGS == /c /EHs /Zi /Od /MT
+ MSFT:*_*_*_CC_FLAGS == /c /EHs /Zi /Od /MTd
GCC:*_*_IA32_CC_FLAGS == -g -c -fshort-wchar -fexceptions -O0 -m32 -malign-double -fno-pie
GCC:*_*_X64_CC_FLAGS == -g -c -fshort-wchar -fexceptions -O0 -m64 -fno-pie "-DEFIAPI=__attribute__((ms_abi))"
diff --git a/UnitTestFrameworkPkg/ReadMe.md b/UnitTestFrameworkPkg/ReadMe.md
index 50d8e1b51d..9c069fb7a7 100644
--- a/UnitTestFrameworkPkg/ReadMe.md
+++ b/UnitTestFrameworkPkg/ReadMe.md
@@ -34,7 +34,22 @@ GoogleTest requires less overhead to register test suites and test cases compare
There are also a number of tools that layer on top of GoogleTest that improve developer productivity.
One example is the VS Code extension
[C++ TestMate](https://marketplace.visualstudio.com/items?itemName=matepek.vscode-catch2-test-adapter)
-that may be used to implement, run, and debug unit tests implemented using GoogleTest.
+that may be used to implement, run, and debug unit tests implemented using GoogleTest. The following
+is an example of the C++ TestMate JSON configuration to find unit tests and configure the environment
+for unit test execution.
+
+```
+"testMate.cpp.test.advancedExecutables": [
+ {
+ "pattern": "Build/**/*Test*",
+ "cwd": "${absDirpath}",
+ "env": {
+ "GTEST_CATCH_EXCEPTIONS": "0",
+ "ASAN_OPTIONS": "detect_leaks=0",
+ }
+ }
+],
+```
If a component can be tested with host-based unit tests, then GoogleTest is recommended. The MdePkg
contains a port of the BaseSafeIntLib unit tests in the GoogleTest style so the differences between
@@ -69,6 +84,7 @@ reviewed. The paths to the SecureBootVariableLib unit tests are:
| JUNIT XML Reports | YES | YES |
| Execute subset of tests | NO | YES |
| VS Code Extensions | NO | YES |
+| Address Sanitizer | Cmocka | YES |
## Framework Libraries
@@ -1007,12 +1023,14 @@ See this example in `UnitTestFrameworkPkgHostTest.dsc`...
Also, based on the type of tests that are being created, the associated DSC include file from the
UnitTestFrameworkPkg for Host or Target based tests should also be included at the top of the DSC
-file.
+file. This provides the default defines and library class mappings requires for unit testing.
```
!include UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
```
+ > **NOTE**: DSC files for host based unit tests must **not** include default mappings from packages such as `MdePkg/MdeLibs.dsc.inc`. This DSC files provides default defines and library mappings for firmware builds that may not be compatible with host based unit test builds. Instead, the DSC file for host based unit tests must provide all the settings required for host based unit tests.
+
Lastly, in the case that the test build has specific dependent libraries associated with it,
they should be added in the \<LibraryClasses\> sub-section for the INF file in the
`[Components]` section of the DSC file. Note that it is within this sub-section where you can
@@ -1373,6 +1391,15 @@ stuart_update -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2022
stuart_ci_build -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2022 -t NOOPT -p MdePkg
```
+#### Disabling Address Sanitizer
+
+By default, the address sanitizer feature is enabled for all host based unit test builds. It can be disabled for
+development/debug purposes by setting the DSC define `UNIT_TESTING_ADDRESS_SANITIZER_ENABLE` to `FALSE`.
+
+```
+stuart_ci_build -c ./.pytool/CISettings.py TOOL_CHAIN_TAG=VS2022 -t NOOPT -p MdePkg BLD_*_UNIT_TESTING_ADDRESS_SANITIZER_ENABLE=FALSE
+```
+
### Evaluating the Results
In your immediate output, any build failures will be highlighted. You can see these below as "WARNING" and "ERROR" messages.
@@ -1463,6 +1490,26 @@ c:\_uefi\MdePkg\Test\UnitTest\Library\BaseSafeIntLib\TestBaseSafeIntLib.c:35: er
</testcase>
```
+### Manually Running Unit Test Executables
+
+The host based unit test executed using `stuart_ci_build` sets up the environment to run host based unit tests
+including environment variable settings. If host based unit test executable are run manually either from a
+shell or using VS Code extensions such as `C++ TestMate`, then the environment must be setup correctly.
+
+#### Windows Environment Variable Settings
+
+```
+set GTEST_CATCH_EXCEPTIONS=0
+set ASAN_OPTIONS=detect_leaks=0
+```
+
+#### Linux Environment Variable Settings
+
+```
+export GTEST_CATCH_EXCEPTIONS=0
+export ASAN_OPTIONS=detect_leaks=0
+```
+
### XML Reporting Mode
Unit test applications using Framework are built using Cmocka that requires the
diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
index 2012c3ae9a..1c28855878 100644
--- a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
@@ -8,6 +8,9 @@
!include UnitTestFrameworkPkg/UnitTestFrameworkPkgCommon.dsc.inc
+[Defines]
+ UNIT_TESTING_ADDRESS_SANITIZER_ENABLE = TRUE
+
[LibraryClasses.common.HOST_APPLICATION]
BaseLib|MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf
UnitTestHostBaseLib|MdePkg/Library/BaseLib/UnitTestHostBaseLib.inf
@@ -26,10 +29,18 @@
NULL|MdePkg/Library/StackCheckLibNull/StackCheckLibNullHostApplication.inf
[BuildOptions]
- MSFT:*_*_*_CC_FLAGS = /MT
+ MSFT:*_*_*_CC_FLAGS = /MTd
GCC:*_*_*_CC_FLAGS = -fno-pie
+!if $(UNIT_TESTING_ADDRESS_SANITIZER_ENABLE)
+ #
+ # Enable Address Sanitizer for VS2019, VS2022, and GCC
+ #
+ MSFT:*_VS2019_*_CC_FLAGS = /fsanitize=address
+ MSFT:*_VS2022_*_CC_FLAGS = /fsanitize=address
+ GCC:*_*_*_CC_FLAGS = -fsanitize=address
+!endif
!ifdef $(UNIT_TESTING_DEBUG)
- MSFT:*_*_*_CC_FLAGS = /MTd -D UNIT_TESTING_DEBUG=1
+ MSFT:*_*_*_CC_FLAGS = -D UNIT_TESTING_DEBUG=1
GCC:*_*_*_CC_FLAGS = -D UNIT_TESTING_DEBUG=1
XCODE:*_*_*_CC_FLAGS = -D UNIT_TESTING_DEBUG=1
!endif
@@ -41,9 +52,7 @@
# MSFT
#
MSFT:*_*_*_CC_FLAGS = /EHs
- MSFT:*_*_*_DLINK_FLAGS == /out:"$(BIN_DIR)\$(MODULE_NAME_GUID).exe" /pdb:"$(BIN_DIR)\$(MODULE_NAME_GUID).pdb" /IGNORE:4001 /NOLOGO /SUBSYSTEM:CONSOLE /DEBUG /STACK:0x40000,0x40000 /WHOLEARCHIVE
- MSFT:*_*_IA32_DLINK_FLAGS = /MACHINE:I386
- MSFT:*_*_X64_DLINK_FLAGS = /MACHINE:AMD64
+ MSFT:*_*_*_DLINK_FLAGS == /nologo /SUBSYSTEM:CONSOLE /DEBUG /out:"$(BIN_DIR)\$(MODULE_NAME_GUID).exe" /pdb:"$(BIN_DIR)\$(MODULE_NAME_GUID).pdb"
MSFT:*_VS2015_IA32_DLINK_FLAGS = /LIBPATH:"%VS2015_PREFIX%Lib" /LIBPATH:"%VS2015_PREFIX%VC\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86"
MSFT:*_VS2015x86_IA32_DLINK_FLAGS = /LIBPATH:"%VS2015_PREFIX%Lib" /LIBPATH:"%VS2015_PREFIX%VC\Lib" /LIBPATH:"%UniversalCRTSdkDir%lib\%UCRTVersion%\ucrt\x86" /LIBPATH:"%WindowsSdkDir%lib\%WindowsSDKLibVersion%\um\x86"
@@ -68,6 +77,12 @@
#
GCC:*_*_*_DLINK_FLAGS = -Wl,--whole-archive
GCC:*_*_*_DLINK2_FLAGS == -Wl,--no-whole-archive -lgcov -lpthread -lstdc++ -lm
+!if $(UNIT_TESTING_ADDRESS_SANITIZER_ENABLE)
+ #
+ # Enable Address Sanitizer for GCC for HOST_APPLICATION
+ #
+ GCC:*_*_*_DLINK_FLAGS = -fsanitize=address
+!endif
#
# Need to do this link via gcc and not ld as the pathing to libraries changes from OS version to OS version