public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [Patch V2 0/7] Add GoogleTest to UnitTestFrameworkPkg
@ 2022-11-04 20:25 Michael D Kinney
  2022-11-04 20:25 ` [Patch V2 1/7] MdePkg/Include: Update Base.h to improve C++ compatibility Michael D Kinney
                   ` (6 more replies)
  0 siblings, 7 replies; 13+ messages in thread
From: Michael D Kinney @ 2022-11-04 20:25 UTC (permalink / raw)
  To: devel
  Cc: Liming Gao, Zhiguang Liu, Bob Feng, Yuwei Chen, Sean Brogan,
	Michael Kubacki

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134

PR: https://github.com/tianocore/edk2/pull/3595
Branch: https://github.com/mdkinney/edk2/tree/Bug_4134_AddGoogleTest_V2

Add GoogleTest support to UnitTestFrameworkPkg to provide an
additional host-based unit test framework to developers.

Code: https://github.com/google/googletest
Docs: https://google.github.io/googletest

GoogleTest is implemented in C++, but does support implementing
unit tests for C code.  This patch series makes a few updates for C++
compatibility and build issues related to multiple definitions of _ASSERT().
The GoogleTest git submodule is added to the UnitTestFrameworkPkg
and .pytools/CISettings.py file along with an update to the host-based
test runner plugin to set the GTEST_OUTPUT environment variable to 
specify the XML output file format and location.

A port of the unit tests for the the MdePkg BaseSafeIntLib are included
to provide an example that is in both the current unit test style and the
GoogleTest style.

New in V2
---------
* Update maintainers/reviewers
* Add feature table to Readme.md and fix typos

Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Yuwei Chen <yuwei.chen@intel.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Michael Kubacki <mikuback@linux.microsoft.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>

Michael D Kinney (7):
  MdePkg/Include: Update Base.h to improve C++ compatibility
  MdePkg/Include/Library: Undefine _ASSERT() if already defined
  UnitTestFrameworkPkg: Add googletest submodule and GoogleTestLib
  UnitTestFrameworkPkg/Library/CmockaLib: Enable symbol files.
  .pytool: Add googletest submodule to CISettings.py
  BaseTools/Plugin/HostBaseUnitTestRunner: Enable gtest xml output
  MdePkg/Test: Add port of BaseSafeIntLib unit tests to GoogleTest

 .gitmodules                                   |    3 +
 .pytool/CISettings.py                         |    2 +
 .../HostBasedUnitTestRunner.py                |    7 +-
 MdePkg/Include/Base.h                         |   12 +-
 MdePkg/Include/Library/DebugLib.h             |    3 +
 .../GoogleTestBaseSafeIntLib.inf              |   37 +
 .../GoogleTestBaseSafeIntLib.uni              |   13 +
 .../SafeIntLibUintnIntnUnitTests32.cpp        |  425 +++
 .../SafeIntLibUintnIntnUnitTests64.cpp        |  429 ++++
 .../BaseSafeIntLib/TestBaseSafeIntLib.cpp     | 2274 +++++++++++++++++
 MdePkg/Test/MdePkgHostTest.dsc                |    1 +
 .../Include/Library/GoogleTestLib.h           |   14 +
 .../Library/CmockaLib/CmockaLib.inf           |    2 +-
 .../Library/GoogleTestLib/GoogleTestLib.inf   |   36 +
 .../Library/GoogleTestLib/GoogleTestLib.uni   |   14 +
 .../Library/GoogleTestLib/googletest          |    1 +
 UnitTestFrameworkPkg/ReadMe.md                |  255 +-
 .../SampleGoogleTest/SampleGoogleTest.cpp     |  263 ++
 .../SampleGoogleTest/SampleGoogleTestHost.inf |   35 +
 .../Test/UnitTestFrameworkPkgHostTest.dsc     |    4 +-
 .../UnitTestFrameworkPkg.ci.yaml              |    4 +-
 UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec |    8 +
 .../UnitTestFrameworkPkgHost.dsc.inc          |    4 +-
 23 files changed, 3810 insertions(+), 36 deletions(-)
 create mode 100644 MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.inf
 create mode 100644 MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.uni
 create mode 100644 MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTests32.cpp
 create mode 100644 MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTests64.cpp
 create mode 100644 MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.cpp
 create mode 100644 UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
 create mode 100644 UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
 create mode 100644 UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
 create mode 160000 UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
 create mode 100644 UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTest.cpp
 create mode 100644 UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTestHost.inf

-- 
2.37.1.windows.1


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [Patch V2 1/7] MdePkg/Include: Update Base.h to improve C++ compatibility
  2022-11-04 20:25 [Patch V2 0/7] Add GoogleTest to UnitTestFrameworkPkg Michael D Kinney
@ 2022-11-04 20:25 ` Michael D Kinney
  2022-11-08  6:59   ` 回复: " gaoliming
  2022-11-04 20:25 ` [Patch V2 2/7] MdePkg/Include/Library: Undefine _ASSERT() if already defined Michael D Kinney
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Michael D Kinney @ 2022-11-04 20:25 UTC (permalink / raw)
  To: devel; +Cc: Liming Gao, Zhiguang Liu

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134

* Map NULL to nullptr or __null when c++ compiler is used.
* Map STATIC_ASSERT to static_assert when a c++ compiler is used.
* Typecast RETURN_SUCCESS to type RETURN_STATUS to match type used
  by all return error/warning status codes.  C++ has stricter type
  checking and found this inconsistency.

Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
---
 MdePkg/Include/Base.h | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/MdePkg/Include/Base.h b/MdePkg/Include/Base.h
index d19ddfe4bba7..d209e6de280a 100644
--- a/MdePkg/Include/Base.h
+++ b/MdePkg/Include/Base.h
@@ -309,7 +309,15 @@ struct _LIST_ENTRY {
 ///
 /// NULL pointer (VOID *)
 ///
+#if defined (__cplusplus)
+  #if defined (_MSC_EXTENSIONS)
+#define NULL  nullptr
+  #else
+#define NULL  __null
+  #endif
+#else
 #define NULL  ((VOID *) 0)
+#endif
 
 //
 // Null character
@@ -760,7 +768,7 @@ typedef UINTN *BASE_LIST;
 **/
 #ifdef MDE_CPU_EBC
 #define STATIC_ASSERT(Expression, Message)
-#elif defined (_MSC_EXTENSIONS)
+#elif defined (_MSC_EXTENSIONS) || defined (__cplusplus)
 #define STATIC_ASSERT  static_assert
 #else
 #define STATIC_ASSERT  _Static_assert
@@ -959,7 +967,7 @@ typedef UINTN RETURN_STATUS;
 ///
 /// The operation completed successfully.
 ///
-#define RETURN_SUCCESS  0
+#define RETURN_SUCCESS  (RETURN_STATUS)(0)
 
 ///
 /// The image failed to load.
-- 
2.37.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Patch V2 2/7] MdePkg/Include/Library: Undefine _ASSERT() if already defined
  2022-11-04 20:25 [Patch V2 0/7] Add GoogleTest to UnitTestFrameworkPkg Michael D Kinney
  2022-11-04 20:25 ` [Patch V2 1/7] MdePkg/Include: Update Base.h to improve C++ compatibility Michael D Kinney
@ 2022-11-04 20:25 ` Michael D Kinney
  2022-11-08  6:59   ` 回复: " gaoliming
  2022-11-04 20:25 ` [Patch V2 3/7] UnitTestFrameworkPkg: Add googletest submodule and GoogleTestLib Michael D Kinney
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Michael D Kinney @ 2022-11-04 20:25 UTC (permalink / raw)
  To: devel; +Cc: Liming Gao, Zhiguang Liu

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134

When unit testing is enabled, make sure _ASSERT() is not already
defined by the host environment before defining _ASSERT().  This
avoids conflicts with VS20xx builds of GoogleTest based unit tests.

Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
---
 MdePkg/Include/Library/DebugLib.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/MdePkg/Include/Library/DebugLib.h b/MdePkg/Include/Library/DebugLib.h
index 8d3d08638d73..9110be2f41b3 100644
--- a/MdePkg/Include/Library/DebugLib.h
+++ b/MdePkg/Include/Library/DebugLib.h
@@ -337,6 +337,9 @@ UnitTestDebugAssert (
   IN CONST CHAR8  *Description
   );
 
+  #if defined (_ASSERT)
+    #undef _ASSERT
+  #endif
   #if defined (__clang__) && defined (__FILE_NAME__)
 #define _ASSERT(Expression)  UnitTestDebugAssert (__FILE_NAME__, DEBUG_LINE_NUMBER, DEBUG_EXPRESSION_STRING (Expression))
   #else
-- 
2.37.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Patch V2 3/7] UnitTestFrameworkPkg: Add googletest submodule and GoogleTestLib
  2022-11-04 20:25 [Patch V2 0/7] Add GoogleTest to UnitTestFrameworkPkg Michael D Kinney
  2022-11-04 20:25 ` [Patch V2 1/7] MdePkg/Include: Update Base.h to improve C++ compatibility Michael D Kinney
  2022-11-04 20:25 ` [Patch V2 2/7] MdePkg/Include/Library: Undefine _ASSERT() if already defined Michael D Kinney
@ 2022-11-04 20:25 ` Michael D Kinney
  2022-11-08  7:47   ` 回复: [edk2-devel] " gaoliming
  2022-11-04 20:25 ` [Patch V2 4/7] UnitTestFrameworkPkg/Library/CmockaLib: Enable symbol files Michael D Kinney
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 13+ messages in thread
From: Michael D Kinney @ 2022-11-04 20:25 UTC (permalink / raw)
  To: devel; +Cc: Michael Kubacki, Sean Brogan

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134

Add submodule for googletest and add GoogleTestLib that is
required for GoogleTest based unit tests. Add GoogleTest
documentation to Readme.md along with a port of the sample
unit test to the GoogleTest style.

Cc: Michael Kubacki <mikuback@linux.microsoft.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Michael Kubacki <mikuback@linux.microsoft.com>
---
 .gitmodules                                   |   3 +
 .../Include/Library/GoogleTestLib.h           |  14 +
 .../Library/GoogleTestLib/GoogleTestLib.inf   |  36 +++
 .../Library/GoogleTestLib/GoogleTestLib.uni   |  14 +
 .../Library/GoogleTestLib/googletest          |   1 +
 UnitTestFrameworkPkg/ReadMe.md                | 255 +++++++++++++++--
 .../SampleGoogleTest/SampleGoogleTest.cpp     | 263 ++++++++++++++++++
 .../SampleGoogleTest/SampleGoogleTestHost.inf |  35 +++
 .../Test/UnitTestFrameworkPkgHostTest.dsc     |   4 +-
 .../UnitTestFrameworkPkg.ci.yaml              |   4 +-
 UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec |   8 +
 .../UnitTestFrameworkPkgHost.dsc.inc          |   4 +-
 12 files changed, 610 insertions(+), 31 deletions(-)
 create mode 100644 UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
 create mode 100644 UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
 create mode 100644 UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
 create mode 160000 UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
 create mode 100644 UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTest.cpp
 create mode 100644 UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTestHost.inf

diff --git a/.gitmodules b/.gitmodules
index b845c9ee3ff0..8011a88d9d25 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -20,3 +20,6 @@
 [submodule "RedfishPkg/Library/JsonLib/jansson"]
 	path = RedfishPkg/Library/JsonLib/jansson
 	url = https://github.com/akheron/jansson
+[submodule "UnitTestFrameworkPkg/Library/GoogleTestLib/googletest"]
+	path = UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
+	url = https://github.com/google/googletest.git
diff --git a/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h b/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
new file mode 100644
index 000000000000..ebec766d4cf7
--- /dev/null
+++ b/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
@@ -0,0 +1,14 @@
+/** @file
+  GoogleTestLib class with APIs from the googletest project
+
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef GOOGLE_TEST_LIB_H_
+#define GOOGLE_TEST_LIB_H_
+
+#include <gtest/gtest.h>
+
+#endif
diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
new file mode 100644
index 000000000000..68db75d7023f
--- /dev/null
+++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
@@ -0,0 +1,36 @@
+## @file
+#  This module provides GoogleTest Library implementation.
+#
+#  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION     = 0x00010005
+  BASE_NAME       = GoogleTestLib
+  MODULE_UNI_FILE = GoogleTestLib.uni
+  FILE_GUID       = A90E4751-AD30-43CC-980B-01E356B49ADF
+  MODULE_TYPE     = BASE
+  VERSION_STRING  = 0.1
+  LIBRARY_CLASS   = GoogleTestLib|HOST_APPLICATION
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
+#
+
+[Sources]
+  googletest/googletest/src/gtest-all.cc
+
+[Packages]
+  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[BuildOptions]
+  MSFT:*_*_*_CC_FLAGS     == /c /EHsc /Zi
+  MSFT:NOOPT_*_*_CC_FLAGS =  /Od
+
+  GCC:*_*_*_CC_FLAGS     == -g -c
+
+  GCC:NOOPT_*_*_CC_FLAGS =  -O0
+  GCC:*_*_IA32_CC_FLAGS  =  -m32
+  GCC:*_*_X64_CC_FLAGS   =  -m64
diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
new file mode 100644
index 000000000000..14c862a23744
--- /dev/null
+++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
@@ -0,0 +1,14 @@
+// /** @file
+// This module provides GoogleTest Library implementation.
+//
+// This module provides GoogleTest Library implementation.
+//
+// Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "GoogleTest Library implementation"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This module provides GoogleTest Library implementation."
diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/googletest b/UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
new file mode 160000
index 000000000000..86add13493e5
--- /dev/null
+++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
@@ -0,0 +1 @@
+Subproject commit 86add13493e5c881d7e4ba77fb91c1f57752b3a4
diff --git a/UnitTestFrameworkPkg/ReadMe.md b/UnitTestFrameworkPkg/ReadMe.md
index e696412cb3cf..9ce04b7f3eb6 100644
--- a/UnitTestFrameworkPkg/ReadMe.md
+++ b/UnitTestFrameworkPkg/ReadMe.md
@@ -2,12 +2,67 @@
 
 ## About
 
-This package adds a unit test framework capable of building tests for multiple contexts including
+This package provides unit test frameworks capable of building tests for multiple contexts including
 the UEFI shell environment and host-based environments. It allows for unit test development to focus
-on the tests and leave error logging, result formatting, context persistance, and test running to the framework.
+on the tests and leave error logging, result formatting, context persistence, and test running to the framework.
 The unit test framework works well for low level unit tests as well as system level tests and
 fits easily in automation frameworks.
 
+### Framework
+
+The first unit test framework is called **Framework** and is implemented as a set of EDK II libraries.
+The Framework supports both host-based unit tests and target-based unit tests that share the same
+source style, macros, and APIs. In some scenarios, the same unit test case sources can be built
+for both host-based unit test execution and target-based unit test execution. Host-based unit tests
+that require mocked interfaces can use the mocking infrastructure provided by
+[cmocka](https://api.cmocka.org/) that is included in the UnitTestFrameworkPkg as a submodule.
+
+### GoogleTest
+
+The second unit test framework supported by the UnitTestFrameworkPkg is
+[GoogleTest](http://google.github.io/googletest/) that can be used to implement host-based unit tests.
+Use of GoogleTest for target-based unit tests of EDK II components is not supported. If a
+host-based unit test requires mocked interfaces, then the Framework with cmocka support should be
+used instead. Enabling support for mocked interfaces with GoogleTest is being actively investigated.
+[GoogleTest on GitHub](https://github.com/google/googletest) is included in the UnitTestFrameworkPkg
+as a submodule.
+
+GoogleTest requires less overhead to register test suites and test cases compared to the Framework.
+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.
+
+If a component can be tested with host-based unit tests without support for mocked interfaces,
+then GoogleTest is recommended. The MdePkg contains a port of the BaseSafeIntLib unit tests in
+the GoogleTest style so the differences between GoogleTest and Framework unit tests can be reviewed.
+The paths to the BaseSafeIntLib unit tests are:
+
+* MdePkg\Test\UnitTest\Library\BaseSafeIntLib
+* MdePkg\Test\GoogleTest\Library\BaseSafeIntLib
+
+## Framework and GoogleTest Feature Comparison
+
+| Feature                     | Framework | GoogleTest |
+|:----------------------------|:---------:|:----------:|
+| Host Based Unit Tests       |    YES    |    YES     |
+| Target Based Unit Tests     |    YES    |     NO     |
+| Unit Test Source Language   |     C     |    C++     |
+| Register Test Suite         |    YES    |    Auto    |
+| Register Test Case          |    YES    |    Auto    |
+| Death/Expected Assert Tests |    YES    |    YES     |
+| Setup/Teardown Hooks        |    YES    |    YES     |
+| Value-Parameterized Tests   |    NO     |    YES     |
+| Typed Tests                 |    NO     |    YES     |
+| Type-Parameterized Tests    |    NO     |    YES     |
+| Timeout Support             |    NO     |    YES     |
+| Mocking Support             |   Cmocka  |     NO     |
+| JUNIT XML Reports           |    YES    |    YES     |
+| Execute subset of tests     |    NO     |    YES     |
+| VS Code Extensions          |    NO     |    YES     |
+
+## Framework Libraries
+
 ### UnitTestLib
 
 The main "framework" library. The core of the framework is the Framework object, which can have any number
@@ -31,10 +86,10 @@ in supporting a system reboot in the middle of a test run.
 
 Library provides function to run at the end of a framework test run and handles formatting the report.
 This is a common customization point and allows the unit test framework to fit its output reports into
-other test infrastructure. In this package a simple library instances has been supplied to output test
+other test infrastructure. In this package simple library instances have been supplied to output test
 results to the console as plain text.
 
-## Samples
+## Framework Samples
 
 There is a sample unit test provided as both an example of how to write a unit test and leverage
 many of the features of the framework. This sample can be found in the `Test/UnitTest/Sample/SampleUnitTest`
@@ -43,7 +98,7 @@ directory.
 The sample is provided in PEI, SMM, DXE, and UEFI App flavors. It also has a flavor for the HOST_APPLICATION
 build type, which can be run on a host system without needing a target.
 
-## Usage
+## Framework Usage
 
 This section is built a lot like a "Getting Started". We'll go through some of the components that are needed
 when constructing a unit test and some of the decisions that are made by the test writer. We'll also describe
@@ -51,7 +106,7 @@ how to check for expected conditions in test cases and a bit of the logging char
 
 Most of these examples will refer to the SampleUnitTestUefiShell app found in this package.
 
-### Requirements - INF
+### Framework Requirements - INF
 
 In our INF file, we'll need to bring in the `UnitTestLib` library. Conveniently, the interface
 header for the `UnitTestLib` is located in `MdePkg`, so you shouldn't need to depend on any other
@@ -80,7 +135,7 @@ to make sure that the module `BASE_NAME` contains the word `Test`...
   BASE_NAME      = SampleUnitTestUefiShell
 ```
 
-### Requirements - Code
+### Framework Requirements - Code
 
 Not to state the obvious, but let's make sure we have the following include before getting too far along...
 
@@ -90,9 +145,9 @@ Not to state the obvious, but let's make sure we have the following include befo
 
 Now that we've got that squared away, let's look at our 'Main()'' routine (or DriverEntryPoint() or whatever).
 
-### Configuring the Framework
+### Framework Configuration
 
-Everything in the UnitTestPkg framework is built around an object called -- conveniently -- the Framework.
+Everything in the UnitTestFrameworkPkg framework is built around an object called -- conveniently -- the Framework.
 This Framework object will contain all the information about our test, the test suites and test cases associated
 with it, the current location within the test pass, and any results that have been recorded so far.
 
@@ -102,7 +157,7 @@ The long name and version strings are just for user presentation and relatively
 will be used to name any cache files and/or test results, so should be a name that makes sense in that context.
 These strings are copied internally to the Framework, so using stack-allocated or literal strings is fine.
 
-In the 'SampleUnitTestUefiShell' app, the module name is used as the short name, so the init looks like this.
+In the 'SampleUnitTestUefiShell' app, the module name is used as the short name, so the initialization looks like this.
 
 ```c
 DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME, UNIT_TEST_APP_VERSION ));
@@ -144,11 +199,11 @@ will be used when adding test cases.
 Great! Now we've finished some of the cruft, red tape, and busy work. We're ready to add some tests. Adding a test
 to a test suite is accomplished with the -- you guessed it -- `AddTestCase` function. It takes in the suite handle;
 a `CHAR8` string for the description and class name; a function pointer for the test case itself; additional, optional
-function pointers for prerequisite check and cleanup routines; and and optional pointer to a context structure.
+function pointers for prerequisite check and cleanup routines; and an optional pointer to a context structure.
 
 Okay, that's a lot. Let's take it one piece at a time. The description and class name strings are very similar in
 usage to the suite title and package name strings in the test suites. The former is for user presentation and the
-latter is for xUnit parsing. The test case function pointer is what is actually executed as the "test" and the
+latter is for xUnit parsing. The test case function pointer is what is executed as the "test" and the
 prototype should be `UNIT_TEST_FUNCTION`. The last three parameters require a little bit more explaining.
 
 The prerequisite check function has a prototype of `UNIT_TEST_PREREQUISITE` and -- if provided -- will be called
@@ -180,7 +235,7 @@ Once all the suites and cases are added, it's time to run the Framework.
 Status = RunAllTestSuites( Framework );
 ```
 
-### A Simple Test Case
+### Framework - A Simple Test Case
 
 We'll take a look at the below test case from 'SampleUnitTestApp'...
 
@@ -217,9 +272,9 @@ _Note_ that this early return can have implications for memory leakage.
 
 At the end, if all test criteria pass, you should return `UNIT_TEST_PASSED`.
 
-### More Complex Cases
+### Framework - More Complex Cases
 
-To write more advanced tests, first take a look at all the Assertion and Logging macros provided in the framework.
+To write more advanced tests, first look at all the Assertion and Logging macros provided in the framework.
 
 Beyond that, if you're writing host-based tests and want to take a dependency on the UnitTestFrameworkPkg, you can
 leverage the `cmocka.h` interface and write tests with all the features of the Cmocka framework.
@@ -227,6 +282,125 @@ leverage the `cmocka.h` interface and write tests with all the features of the C
 Documentation for Cmocka can be found here:
 https://api.cmocka.org/
 
+## GoogleTest Samples
+
+There is a sample unit test provided as both an example of how to write a unit test and leverage
+many of the GoogleTest features. This sample can be found in the `Test/GoogleTest/Sample/SampleGoogleTest`
+directory.
+
+The sample is provided for the HOST_APPLICATION build type, which can be run on a host system without
+needing a target.
+
+## GoogleTest Usage
+
+This section is built a lot like a "Getting Started". We'll go through some of the components that are needed
+when constructing a unit test and some of the decisions that are made by the test writer. We'll also describe
+how to check for expected conditions in test cases and a bit of the logging characteristics.
+
+Most of these examples will refer to the SampleGoogleTestHost app found in this package.
+
+### GoogleTest Requirements - INF
+
+In our INF file, we'll need to bring in the `GoogleTest` library. Conveniently, the interface
+header for the `GoogleTest` is in `UnitTestFrameworkPkg`, so you shouldn't need to depend on any other
+packages. As long as your DSC file knows where to find the lib implementation that you want to use,
+you should be good to go.
+
+See this example in 'SampleGoogleTestHost.inf'...
+
+```
+[Packages]
+  MdePkg/MdePkg.dec
+  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+  GoogleTestLib
+  BaseLib
+  DebugLib
+```
+
+Also, if you want you test to automatically be picked up by the Test Runner plugin, you will need
+to make sure that the module `BASE_NAME` contains the word `Test`...
+
+```
+[Defines]
+  BASE_NAME      = SampleGoogleTestHost
+```
+
+### GoogleTest Requirements - Code
+
+Not to state the obvious, but let's make sure we have the following include before getting too far along...
+
+```
+#include <gtest/gtest.h>
+extern "C" {
+  #include <Uefi.h>
+  #include <Library/BaseLib.h>
+  #include <Library/DebugLib.h>
+}
+```
+
+GoogleTest applications are implemented in C++. The first include brings in the
+GoogleTest definitions. Other EDK II related include files must be wrapped in
+`extern "C" {}` because they are C include files. Link failures will occur if
+this is not done.
+
+Now that we've got that squared away, let's look at our 'Main()'' routine (or DriverEntryPoint() or whatever).
+
+### GoogleTest Configuration
+
+Unlike the Framework, GoogleTest does not require test suites or test cases to
+be registered. Instead, the test cases declare the test suite name and test
+case name as part of their implementation. The only requirement for GoogleTest
+is to have a `main()` function that initialize the GoogleTest infrastructure and
+call the service `RUN_ALL_TESTS()` to run all the unit tests.
+
+```c
+int main(int argc, char* argv[]) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
+```
+
+### GoogleTest - A Simple Test Case
+
+We'll look at the below test case from 'SampleGoogleTestHost'...
+
+```c
+TEST(SimpleMathTests, OnePlusOneShouldEqualTwo) {
+  UINTN  A;
+  UINTN  B;
+  UINTN  C;
+
+  A = 1;
+  B = 1;
+  C = A + B;
+
+  ASSERT_EQ (C, 2);
+}
+```
+
+This uses the simplest form of a GoogleTest unit test using `TEST()` that
+declares the test suite name and the unit test name within that test suite.
+The unit test performs actions and typically makes calls to the code under test
+and contains test assertions to verify that the code under test behaves as
+expected for the given inputs.
+
+In this test case, the `ASSERT_EQ` assertion is being used to establish that the business logic has functioned
+correctly. There are several assertion macros, and you are encouraged to use one that matches as closely to your
+intended test criterium as possible, because the logging is specific to the macro and more specific macros have more
+detailed logs. When in doubt, there are always `ASSERT_TRUE` and `ASSERT_FALSE`. Assertion macros that fail their
+test criterium will immediately return from the test case with a failed status and log an error string.
+_Note_ that this early return can have implications for memory leakage.
+
+There is no return status from a GooglTest unit test. If no assertions are
+triggered then the unit test has a passing status.
+
+### GoogleTest - More Complex Cases
+
+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
@@ -243,11 +417,11 @@ stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=VS2017 -p MdePkg -t NOOP
 
 ### Hooking BaseLib
 
-Most unit test mocking can be performed by the functions provided in the UnitTestFramework libraries, but since
+Most unit test mocking can be performed by the functions provided in the UnitTestFrameworkPkg libraries, but since
 BaseLib is consumed by the Framework itself, it requires different techniques to substitute parts of the
 functionality.
 
-To solve some of this, the UnitTestFramework consumes a special implementation of BaseLib for host-based tests.
+To solve some of this, the UnitTestFrameworkPkg consumes a special implementation of BaseLib for host-based tests.
 This implementation contains a [hook table](https://github.com/tianocore/edk2/blob/e188ecc8b4aed8fdd26b731d43883861f5e5e7b4/MdePkg/Test/UnitTest/Include/Library/UnitTestHostBaseLib.h#L507)
 that can be used to substitute test functionality for any of the BaseLib functions. By default, this implementation
 will use the underlying BaseLib implementation, so the unit test writer only has to supply minimal code to test a
@@ -255,7 +429,7 @@ particular case.
 
 ### Debugging the Framework Itself
 
-While most of the tests that are produced by the UnitTestFramework are easy to step through in a debugger, the Framework
+While most of the tests that are produced by the UnitTestFrameworkPkg are easy to step through in a debugger, the Framework
 itself consumes code (mostly Cmocka) that sets its own build flags. These flags cause parts of the Framework to not
 export symbols and captures exceptions, and as such are harder to debug. We have provided a Stuart parameter to force
 symbolic debugging to be enabled.
@@ -269,15 +443,17 @@ stuart_ci_build -c .pytool/CISettings.py TOOL_CHAIN_TAG=VS2019 -p MdePkg -t NOOP
 ## Building and Running Host-Based Tests
 
 The EDK2 CI infrastructure provides a convenient way to run all host-based tests -- in the the entire tree or just
-selected packages -- and aggregate all the the reports, including highlighting any failures. This functionality is
-provided through the Stuart build system (published by EDK2-PyTools) and the `NOOPT` build target.
+selected packages -- and aggregate all the reports, including highlighting any failures. This functionality is
+provided through the Stuart build system (published by EDK2-PyTools) and the `NOOPT` build target. The sections that
+follow use Framework examples. Unit tests based on GoogleTest are built and run the same way. The text output and
+JUNIT XML output format have small differences.
 
 ### Building Locally
 
 First, to make sure you're working with the latest PyTools, run the following command:
 
 ```bash
-# Would recommend to run this in a Python venv, but that's out of scope for this doc.
+# Would recommend running this in a Python venv, but that's out of scope for this doc.
 python -m pip install --upgrade -r ./pip-requirements.txt
 ```
 
@@ -361,7 +537,7 @@ RUNNING TEST SUITE: Int Safe Conversions Test Suite
 ```
 
 You can also, if you are so inclined, read the output from the exact instance of the test that was run during
-`stuart_ci_build`. The ouput file can be found on a path that looks like:
+`stuart_ci_build`. The output file can be found on a path that looks like:
 
 `Build/<Package>/HostTest/<Arch>/<TestName>.<TestSuiteName>.<Arch>.result.xml`
 
@@ -389,22 +565,30 @@ c:\_uefi\MdePkg\Test\UnitTest\Library\BaseSafeIntLib\TestBaseSafeIntLib.c:35: er
 
 ### XML Reporting Mode
 
-Since these applications are built using the CMocka framework, they can also use the following env variables to output
-in a structured XML rather than text:
+Unit test applications using Framework are built using Cmocka that requires the
+following environment variables to be set to generate structured XML output
+rather than text:
 
-```text
+```
 CMOCKA_MESSAGE_OUTPUT=xml
 CMOCKA_XML_FILE=<absolute or relative path to output file>
 ```
 
+Unit test applications using GoogleTest require the following environment
+variable to be set to generate structured XML output rather than text:
+
+```
+GTEST_OUTPUT=xml:<absolute or relative path to output file>
+```
+
 This mode is used by the test running plugin to aggregate the results for CI test status reporting in the web view.
 
 ### Important Note
 
-This works on both Windows and Linux, but is currently limited to x64 architectures. Working on getting others, but we
+This works on both Windows and Linux but is currently limited to x64 architectures. Working on getting others, but we
 also welcome contributions.
 
-## Known Limitations
+## Framework Known Limitations
 
 ### PEI, DXE, SMM
 
@@ -418,7 +602,7 @@ PEI, DXE, and SMM is forthcoming, but should be considered beta/staging for now.
 The host-based test framework is powered internally by the Cmocka framework. As such, it has abilities
 that the target-based tests don't (yet). It would be awesome if this meant that it was a super set of
 the target-based tests, and it worked just like the target-based tests but with more features. Unfortunately,
-this is not the case. While care has been taken to keep them as close a possible, there are a few known
+this is not the case. While care has been taken to keep them as close as possible, there are a few known
 inconsistencies that we're still ironing out. For example, the logging messages in the target-based tests
 are cached internally and associated with the running test case. They can be saved later as part of the
 reporting lib. This isn't currently possible with host-based. Only the assertion failures are logged.
@@ -441,6 +625,9 @@ Non-Host-Based (PEI/DXE/SMM/Shell) Tests for a Functionality or Feature   | Simi
   ComponentY/
     ComponentY.inf
     ComponentY.c
+    GoogleTest/
+      ComponentYHostGoogleTest.inf    # Host-Based Test for Driver Module
+      ComponentYGoogleTest.cpp
     UnitTest/
       ComponentYHostUnitTest.inf      # Host-Based Test for Driver Module
       ComponentYUnitTest.c
@@ -455,11 +642,23 @@ Non-Host-Based (PEI/DXE/SMM/Shell) Tests for a Functionality or Feature   | Simi
     SpecificLibDxe/
       SpecificLibDxe.c
       SpecificLibDxe.inf
+      GoogleTest/                    # Host-Based Test for Specific Library Implementation
+        SpecificLibDxeHostGoogleTest.cpp
+        SpecificLibDxeHostGoogleTest.inf
       UnitTest/                      # Host-Based Test for Specific Library Implementation
         SpecificLibDxeHostUnitTest.c
         SpecificLibDxeHostUnitTest.inf
   Test/
     <Package>HostTest.dsc             # Host-Based Test Apps
+    GoogleTest/
+      InterfaceX
+        InterfaceXHostGoogleTest.inf  # Host-Based App (should be in Test/<Package>HostTest.dsc)
+        InterfaceXUnitTest.cpp        # Test Logic
+
+      GeneralPurposeLib/              # Host-Based Test for any implementation of GeneralPurposeLib
+        GeneralPurposeLibTest.cpp
+        GeneralPurposeLibHostUnitTest.inf
+
     UnitTest/
       InterfaceX
         InterfaceXHostUnitTest.inf    # Host-Based App (should be in Test/<Package>HostTest.dsc)
diff --git a/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTest.cpp b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTest.cpp
new file mode 100644
index 000000000000..c83e58596a82
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTest.cpp
@@ -0,0 +1,263 @@
+/** @file
+  This is a sample to demonstrates the use of GoogleTest that supports host
+  execution environments.
+
+  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <gtest/gtest.h>
+extern "C" {
+  #include <Uefi.h>
+  #include <Library/BaseLib.h>
+  #include <Library/DebugLib.h>
+}
+
+/**
+  Sample unit test that verifies the expected result of an unsigned integer
+  addition operation.
+**/
+TEST(SimpleMathTests, OnePlusOneShouldEqualTwo) {
+  UINTN  A;
+  UINTN  B;
+  UINTN  C;
+
+  A = 1;
+  B = 1;
+  C = A + B;
+
+  ASSERT_EQ (C, (UINTN)2);
+}
+
+/**
+  Sample unit test that verifies that a global BOOLEAN is updatable.
+**/
+class GlobalBooleanVarTests : public ::testing::Test {
+  public:
+    BOOLEAN  SampleGlobalTestBoolean  = FALSE;
+};
+
+TEST_F(GlobalBooleanVarTests, GlobalBooleanShouldBeChangeable) {
+  SampleGlobalTestBoolean = TRUE;
+  ASSERT_TRUE (SampleGlobalTestBoolean);
+
+  SampleGlobalTestBoolean = FALSE;
+  ASSERT_FALSE (SampleGlobalTestBoolean);
+}
+
+/**
+  Sample unit test that logs a warning message and verifies that a global
+  pointer is updatable.
+**/
+class GlobalVarTests : public ::testing::Test {
+  public:
+    VOID  *SampleGlobalTestPointer = NULL;
+
+  protected:
+  void SetUp() override {
+    ASSERT_EQ ((UINTN)SampleGlobalTestPointer, (UINTN)NULL);
+  }
+  void TearDown() {
+    SampleGlobalTestPointer = NULL;
+  }
+};
+
+TEST_F(GlobalVarTests, GlobalPointerShouldBeChangeable) {
+  SampleGlobalTestPointer = (VOID *)-1;
+  ASSERT_EQ ((UINTN)SampleGlobalTestPointer, (UINTN)((VOID *)-1));
+}
+
+
+/**
+  Set PcdDebugPropertyMask for each MacroTestsAssertsEnabledDisabled test
+**/
+class MacroTestsAssertsEnabledDisabled : public testing::TestWithParam<UINT8> {
+  void SetUp() {
+    PatchPcdSet8 (PcdDebugPropertyMask, GetParam());
+  }
+};
+
+/**
+  Sample unit test using the ASSERT_TRUE() macro.
+**/
+TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertTrue) {
+  UINT64  Result;
+
+  //
+  // This test passes because expression always evaluated to TRUE.
+  //
+  ASSERT_TRUE (TRUE);
+
+  //
+  // This test passes because expression always evaluates to TRUE.
+  //
+  Result = LShiftU64 (BIT0, 1);
+  ASSERT_TRUE (Result == BIT1);
+}
+
+/**
+  Sample unit test using the ASSERT_FALSE() macro.
+**/
+TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertFalse) {
+  UINT64  Result;
+
+  //
+  // This test passes because expression always evaluated to FALSE.
+  //
+  ASSERT_FALSE (FALSE);
+
+  //
+  // This test passes because expression always evaluates to FALSE.
+  //
+  Result = LShiftU64 (BIT0, 1);
+  ASSERT_FALSE (Result == BIT0);
+}
+
+/**
+  Sample unit test using the ASSERT_EQ() macro.
+**/
+TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertEqual) {
+  UINT64  Result;
+
+  //
+  // This test passes because both values are always equal.
+  //
+  ASSERT_EQ (1, 1);
+
+  //
+  // This test passes because both values are always equal.
+  //
+  Result = LShiftU64 (BIT0, 1);
+  ASSERT_EQ (Result, (UINT64)BIT1);
+}
+
+/**
+  Sample unit test using the ASSERT_STREQ() macro.
+**/
+TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertMemEqual) {
+  CHAR8  *String1;
+  CHAR8  *String2;
+
+  //
+  // This test passes because String1 and String2 are the same.
+  //
+  String1 = (CHAR8 *)"Hello";
+  String2 = (CHAR8 *)"Hello";
+  ASSERT_STREQ (String1, String2);
+}
+
+/**
+  Sample unit test using the ASSERT_NE() macro.
+**/
+TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertNotEqual) {
+  UINT64  Result;
+
+  //
+  // This test passes because both values are never equal.
+  //
+  ASSERT_NE (0, 1);
+
+  //
+  // This test passes because both values are never equal.
+  //
+  Result = LShiftU64 (BIT0, 1);
+  ASSERT_NE (Result, (UINT64)BIT0);
+}
+
+/**
+  Sample unit test using the ASSERT_TRUE() and ASSERT(FALSE)
+  and EFI_EFFOR() macros to check status
+**/
+TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertNotEfiError) {
+  //
+  // This test passes because the status is not an EFI error.
+  //
+  ASSERT_FALSE (EFI_ERROR (EFI_SUCCESS));
+
+  //
+  // This test passes because the status is not an EFI error.
+  //
+  ASSERT_FALSE (EFI_ERROR (EFI_WARN_BUFFER_TOO_SMALL));
+}
+
+/**
+  Sample unit test using the ASSERT_EQ() macro to compare EFI_STATUS values.
+**/
+TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertStatusEqual) {
+  //
+  // This test passes because the status value are always equal.
+  //
+  ASSERT_EQ (EFI_SUCCESS, EFI_SUCCESS);
+}
+
+/**
+  Sample unit test using ASSERT_NE() macro to make sure a pointer is not NULL.
+**/
+TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertNotNull) {
+  UINT64  Result;
+
+  //
+  // This test passes because the pointer is never NULL.
+  //
+  ASSERT_NE (&Result, (UINT64 *)NULL);
+}
+
+/**
+  Sample unit test using that should not generate any ASSERTs()
+**/
+TEST_P(MacroTestsAssertsEnabledDisabled, MacroExpectNoAssertFailure) {
+  //
+  // This test passes because it never triggers an ASSERT().
+  //
+  ASSERT (TRUE);
+
+  //
+  // This test passes because DecimalToBcd() does not ASSERT() if the
+  // value passed in is <= 99.
+  //
+  DecimalToBcd8 (99);
+}
+
+/**
+  Sample unit test using the ASSERT_DEATH() macro to test expected ASSERT()s.
+**/
+TEST_P(MacroTestsAssertsEnabledDisabled, MacroExpectAssertFailure) {
+  //
+  // Skip tests that verify an ASSERT() is triggered if ASSERT()s are disabled.
+  //
+  if ((PcdGet8 (PcdDebugPropertyMask) & BIT0) == 0x00) {
+    return;
+  }
+
+  //
+  // This test passes because it directly triggers an ASSERT().
+  //
+  ASSERT_DEATH (ASSERT (FALSE), "");
+
+  //
+  // This test passes because DecimalToBcd() generates an ASSERT() if the
+  // value passed in is >= 100.  The expected ASSERT() is caught by the unit
+  // test framework and ASSERT_DEATH() returns without an error.
+  //
+  ASSERT_DEATH (DecimalToBcd8 (101), "");
+}
+
+INSTANTIATE_TEST_SUITE_P(ValidInput,
+                         MacroTestsAssertsEnabledDisabled,
+                         ::testing::Values(PcdGet8 (PcdDebugPropertyMask) | BIT0, PcdGet8 (PcdDebugPropertyMask) & (~BIT0)));
+
+/**
+  Sample unit test using the SCOPED_TRACE() macro for trace messages.
+**/
+TEST(MacroTestsMessages, MacroTraceMessage) {
+  //
+  // Example of logging.
+  //
+  SCOPED_TRACE ("SCOPED_TRACE message\n");
+}
+
+int main(int argc, char* argv[]) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTestHost.inf b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTestHost.inf
new file mode 100644
index 000000000000..37e7c86910ed
--- /dev/null
+++ b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTestHost.inf
@@ -0,0 +1,35 @@
+## @file
+# This is a sample to demonstrates the use of GoogleTest that supports host
+# execution environments.
+#
+# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION    = 0x00010005
+  BASE_NAME      = SampleGoogleTestHost
+  FILE_GUID      = 7D8BBFBB-7977-4AEE-A59F-257BF5C2F87C
+  MODULE_TYPE    = HOST_APPLICATION
+  VERSION_STRING = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  SampleGoogleTest.cpp
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+  GoogleTestLib
+  BaseLib
+  DebugLib
+
+[Pcd]
+  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
diff --git a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
index 184fdec87acf..708ef7f9ab35 100644
--- a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
+++ b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
@@ -23,14 +23,16 @@ [PcdsPatchableInModule]
 
 [Components]
   #
-  # Build HOST_APPLICATION that tests the SampleUnitTest
+  # Build HOST_APPLICATIONs that test the SampleUnitTest
   #
   UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTestHost.inf
+  UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleGoogleTestHost.inf
 
   #
   # Build HOST_APPLICATION Libraries
   #
   UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
+  UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
   UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf
   UnitTestFrameworkPkg/Library/Posix/MemoryAllocationLibPosix/MemoryAllocationLibPosix.inf
   UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.inf
diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
index 77d51e13484c..072df6208c92 100644
--- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
+++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
@@ -78,7 +78,8 @@
     "SpellCheck": {
         "AuditOnly": False,           # Fails test but run in AuditOnly mode to collect log
         "IgnoreFiles": [             # use gitignore syntax to ignore errors in matching files
-            "Library/CmockaLib/cmocka/**/*.*"  # not going to spell check a submodule
+            "Library/CmockaLib/cmocka/**/*.*",  # not going to spell check a submodule
+            "Library/GoogleTestLib/googletest/**/*.*"  # not going to spell check a submodule
         ],
         "ExtendWords": [             # words to extend to the dictionary for this package
             "testcase",
@@ -91,6 +92,7 @@
             "NOFAILURE",
             "cmockery",
             "DHAVE", # build flag for cmocka in the INF
+            "gtest", # file name in GoogleTestLib.inf
             "corthon",      # Contact GitHub account in Readme
             "mdkinney",     # Contact GitHub account in Readme
             "spbrogan"      # Contact GitHub account in Readme
diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
index 069289f00969..ed12f32009d8 100644
--- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
@@ -16,11 +16,15 @@ [Defines]
   PACKAGE_VERSION   = 1.00
 
 [Includes]
+  Include
   Library/CmockaLib/cmocka/include
+  Library/GoogleTestLib/googletest/googletest/include
+  Library/GoogleTestLib/googletest/googlemock/include
 
 [Includes.Common.Private]
   PrivateInclude
   Library/CmockaLib/cmocka/include/cmockery
+  Library/GoogleTestLib/googletest/googletest
 
 [LibraryClasses.Common.Private]
   ## @libraryclass Allows save and restore unit test internal state
@@ -35,6 +39,10 @@ [LibraryClasses.Common.Private]
   #
   UnitTestBootLib|PrivateInclude/Library/UnitTestBootLib.h
 
+  ## @libraryclass GoogleTest infrastructure
+  #
+  GoogleTestLib|Include/Library/GoogleTestLib.h
+
 [Guids]
   gUnitTestFrameworkPkgTokenSpaceGuid = { 0x833d3aba, 0x39b4, 0x43a2, { 0xb9, 0x30, 0x7a, 0x34, 0x53, 0x39, 0x31, 0xb3 } }
 
diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
index f249813713a8..6d5f651f689f 100644
--- a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
@@ -14,6 +14,7 @@ [LibraryClasses.common.HOST_APPLICATION]
   CpuLib|MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf
   CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLibNull/BaseCacheMaintenanceLibNull.inf
   CmockaLib|UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
+  GoogleTestLib|UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
   UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.inf
   DebugLib|UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf
   MemoryAllocationLib|UnitTestFrameworkPkg/Library/Posix/MemoryAllocationLibPosix/MemoryAllocationLibPosix.inf
@@ -30,6 +31,7 @@ [BuildOptions.common.EDKII.HOST_APPLICATION]
   #
   # MSFT
   #
+  MSFT:*_*_*_CC_FLAGS               = /EHsc
   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 /NODEFAULTLIB:libcmt.lib libcmtd.lib
   MSFT:*_*_IA32_DLINK_FLAGS         = /MACHINE:I386
   MSFT:*_*_X64_DLINK_FLAGS          = /MACHINE:AMD64
@@ -49,7 +51,7 @@ [BuildOptions.common.EDKII.HOST_APPLICATION]
   #
   GCC:*_*_IA32_DLINK_FLAGS == -o $(BIN_DIR)/$(MODULE_NAME_GUID) -m32 -no-pie
   GCC:*_*_X64_DLINK_FLAGS  == -o $(BIN_DIR)/$(MODULE_NAME_GUID) -m64 -no-pie
-  GCC:*_*_*_DLINK2_FLAGS   == -lgcov
+  GCC:*_*_*_DLINK2_FLAGS   == -lgcov -lpthread -lstdc++ -lm
 
   #
   # Need to do this link via gcc and not ld as the pathing to libraries changes from OS version to OS version
-- 
2.37.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Patch V2 4/7] UnitTestFrameworkPkg/Library/CmockaLib: Enable symbol files.
  2022-11-04 20:25 [Patch V2 0/7] Add GoogleTest to UnitTestFrameworkPkg Michael D Kinney
                   ` (2 preceding siblings ...)
  2022-11-04 20:25 ` [Patch V2 3/7] UnitTestFrameworkPkg: Add googletest submodule and GoogleTestLib Michael D Kinney
@ 2022-11-04 20:25 ` Michael D Kinney
  2022-11-04 20:25 ` [Patch V2 5/7] .pytool: Add googletest submodule to CISettings.py Michael D Kinney
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 13+ messages in thread
From: Michael D Kinney @ 2022-11-04 20:25 UTC (permalink / raw)
  To: devel; +Cc: Michael Kubacki, Sean Brogan

Cc: Michael Kubacki <mikuback@linux.microsoft.com>
Cc: Sean Brogan <sean.brogan@microsoft.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Michael Kubacki <mikuback@linux.microsoft.com>
---
 UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf b/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
index 07da7a88e952..052c7f557210 100644
--- a/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
+++ b/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
@@ -26,7 +26,7 @@ [Packages]
   UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
 
 [BuildOptions]
-  MSFT:*_*_*_CC_FLAGS     == /c -DHAVE_VSNPRINTF -DHAVE_SNPRINTF
+  MSFT:*_*_*_CC_FLAGS     == /c -DHAVE_VSNPRINTF -DHAVE_SNPRINTF /Zi
   MSFT:NOOPT_*_*_CC_FLAGS =  /Od
 
   GCC:*_*_*_CC_FLAGS     == -g -DHAVE_SIGNAL_H
-- 
2.37.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Patch V2 5/7] .pytool: Add googletest submodule to CISettings.py
  2022-11-04 20:25 [Patch V2 0/7] Add GoogleTest to UnitTestFrameworkPkg Michael D Kinney
                   ` (3 preceding siblings ...)
  2022-11-04 20:25 ` [Patch V2 4/7] UnitTestFrameworkPkg/Library/CmockaLib: Enable symbol files Michael D Kinney
@ 2022-11-04 20:25 ` Michael D Kinney
  2022-11-04 20:25 ` [Patch V2 6/7] BaseTools/Plugin/HostBaseUnitTestRunner: Enable gtest xml output Michael D Kinney
  2022-11-04 20:25 ` [Patch V2 7/7] MdePkg/Test: Add port of BaseSafeIntLib unit tests to GoogleTest Michael D Kinney
  6 siblings, 0 replies; 13+ messages in thread
From: Michael D Kinney @ 2022-11-04 20:25 UTC (permalink / raw)
  To: devel; +Cc: Sean Brogan, Michael Kubacki, Liming Gao

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134

Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Michael Kubacki <mikuback@linux.microsoft.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Michael Kubacki <mikuback@linux.microsoft.com>
---
 .pytool/CISettings.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/.pytool/CISettings.py b/.pytool/CISettings.py
index cc2214071c96..76ac2b09dba6 100644
--- a/.pytool/CISettings.py
+++ b/.pytool/CISettings.py
@@ -192,6 +192,8 @@ class Settings(CiBuildSettingsManager, UpdateSettingsManager, SetupSettingsManag
             "CryptoPkg/Library/OpensslLib/openssl", False))
         rs.append(RequiredSubmodule(
             "UnitTestFrameworkPkg/Library/CmockaLib/cmocka", False))
+        rs.append(RequiredSubmodule(
+            "UnitTestFrameworkPkg/Library/GoogleTestLib/googletest", False))
         rs.append(RequiredSubmodule(
             "MdeModulePkg/Universal/RegularExpressionDxe/oniguruma", False))
         rs.append(RequiredSubmodule(
-- 
2.37.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Patch V2 6/7] BaseTools/Plugin/HostBaseUnitTestRunner: Enable gtest xml output
  2022-11-04 20:25 [Patch V2 0/7] Add GoogleTest to UnitTestFrameworkPkg Michael D Kinney
                   ` (4 preceding siblings ...)
  2022-11-04 20:25 ` [Patch V2 5/7] .pytool: Add googletest submodule to CISettings.py Michael D Kinney
@ 2022-11-04 20:25 ` Michael D Kinney
  2022-11-04 20:25 ` [Patch V2 7/7] MdePkg/Test: Add port of BaseSafeIntLib unit tests to GoogleTest Michael D Kinney
  6 siblings, 0 replies; 13+ messages in thread
From: Michael D Kinney @ 2022-11-04 20:25 UTC (permalink / raw)
  To: devel; +Cc: Bob Feng, Liming Gao, Yuwei Chen

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134

Set environment variable GTEST_OUTPUT to specify the output
format of XML and the output file name.  Both CMOCKA_XML_FILE
and GTEST_OUTPUT are set for each host based unit test to
support both cmocka unit tests and gtest unit tests.

Cc: Bob Feng <bob.c.feng@intel.com>
Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Yuwei Chen <yuwei.chen@intel.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
Reviewed-by: Bob Feng <bob.c.feng@intel.com>
---
 .../HostBasedUnitTestRunner/HostBasedUnitTestRunner.py     | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py b/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py
index c1eeaf26251e..a8220aacd396 100644
--- a/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py
+++ b/BaseTools/Plugin/HostBasedUnitTestRunner/HostBasedUnitTestRunner.py
@@ -85,9 +85,12 @@ class HostBasedUnitTestRunner(IUefiBuildPlugin):
                 raise NotImplementedError("Unsupported Operating System")
 
             for test in testList:
-                # Configure output name.
+                # Configure output name if test uses cmocka.
                 shell_env.set_shell_var(
-                    'CMOCKA_XML_FILE', test + ".%g." + arch + ".result.xml")
+                    'CMOCKA_XML_FILE', test + ".CMOCKA.%g." + arch + ".result.xml")
+                # Configure output name if test uses gtest.
+                shell_env.set_shell_var(
+                    'GTEST_OUTPUT', "xml:" + test + ".GTEST." + arch + ".result.xml")
 
                 # Run the test.
                 ret = RunCmd('"' + test + '"', "", workingdir=cp)
-- 
2.37.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [Patch V2 7/7] MdePkg/Test: Add port of BaseSafeIntLib unit tests to GoogleTest
  2022-11-04 20:25 [Patch V2 0/7] Add GoogleTest to UnitTestFrameworkPkg Michael D Kinney
                   ` (5 preceding siblings ...)
  2022-11-04 20:25 ` [Patch V2 6/7] BaseTools/Plugin/HostBaseUnitTestRunner: Enable gtest xml output Michael D Kinney
@ 2022-11-04 20:25 ` Michael D Kinney
  2022-11-08  6:59   ` 回复: [edk2-devel] " gaoliming
  6 siblings, 1 reply; 13+ messages in thread
From: Michael D Kinney @ 2022-11-04 20:25 UTC (permalink / raw)
  To: devel; +Cc: Liming Gao, Zhiguang Liu

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134

Cc: Liming Gao <gaoliming@byosoft.com.cn>
Cc: Zhiguang Liu <zhiguang.liu@intel.com>
Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
---
 .../GoogleTestBaseSafeIntLib.inf              |   37 +
 .../GoogleTestBaseSafeIntLib.uni              |   13 +
 .../SafeIntLibUintnIntnUnitTests32.cpp        |  425 +++
 .../SafeIntLibUintnIntnUnitTests64.cpp        |  429 ++++
 .../BaseSafeIntLib/TestBaseSafeIntLib.cpp     | 2274 +++++++++++++++++
 MdePkg/Test/MdePkgHostTest.dsc                |    1 +
 6 files changed, 3179 insertions(+)
 create mode 100644 MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.inf
 create mode 100644 MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.uni
 create mode 100644 MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTests32.cpp
 create mode 100644 MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTests64.cpp
 create mode 100644 MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.cpp

diff --git a/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.inf b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.inf
new file mode 100644
index 000000000000..f609bfa57f7b
--- /dev/null
+++ b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.inf
@@ -0,0 +1,37 @@
+## @file
+# Host OS based Application that Unit Tests the SafeIntLib using Google Test
+#
+# Copyright (c) 2022, Intel Corporation. All rights reserved.
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+##
+
+[Defines]
+  INF_VERSION     = 0x00010005
+  BASE_NAME       = GoogleTestBaseSafeIntLib
+  MODULE_UNI_FILE = GoogleTestBaseSafeIntLib.uni
+  FILE_GUID       = 2D9C1796-B0D2-4DA7-9529-1F8D9CCC11D3
+  MODULE_TYPE     = HOST_APPLICATION
+  VERSION_STRING  = 1.0
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  TestBaseSafeIntLib.cpp
+
+[Sources.IA32]
+  SafeIntLibUintnIntnUnitTests32.cpp
+
+[Sources.X64]
+  SafeIntLibUintnIntnUnitTests64.cpp
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+
+[LibraryClasses]
+  GoogleTestLib
+  SafeIntLib
diff --git a/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.uni b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.uni
new file mode 100644
index 000000000000..1c11b9e05205
--- /dev/null
+++ b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.uni
@@ -0,0 +1,13 @@
+// /** @file
+// Application that Unit Tests the SafeIntLib using Google Test
+//
+// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "Application that Unit Tests the SafeIntLib using Google Test"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "Application that Unit Tests the SafeIntLib using Google Test."
+
diff --git a/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTests32.cpp b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTests32.cpp
new file mode 100644
index 000000000000..6fbf302c1c5e
--- /dev/null
+++ b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTests32.cpp
@@ -0,0 +1,425 @@
+/** @file
+  IA32-specific functions for unit-testing INTN and UINTN functions in
+  SafeIntLib.
+
+  Copyright (c) Microsoft Corporation.<BR>
+  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <gtest/gtest.h>
+extern "C" {
+  #include <Base.h>
+  #include <Library/SafeIntLib.h>
+}
+
+TEST(ConversionTestSuite, TestSafeInt32ToUintn) {
+  RETURN_STATUS  Status;
+  INT32       Operand;
+  UINTN       Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeInt32ToUintn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-1537977259);
+  Status  = SafeInt32ToUintn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint32ToIntn) {
+  RETURN_STATUS  Status;
+  UINT32      Operand;
+  INTN        Result;
+
+  //
+  // If Operand is <= MAX_INTN, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeUint32ToIntn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabababab);
+  Status  = SafeUint32ToIntn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToInt32) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  INT32       Result;
+
+  //
+  // INTN is same as INT32 in IA32, so this is just a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeIntnToInt32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bababab, Result);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToUint32) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  UINT32      Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeIntnToUint32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT32)0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-1537977259);
+  Status  = SafeIntnToUint32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToUint32) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  UINT32      Result;
+
+  //
+  // UINTN is same as UINT32 in IA32, so this is just a cast
+  //
+  Operand = 0xabababab;
+  Result  = 0;
+  Status  = SafeUintnToUint32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabababab, Result);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToIntn) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  INTN        Result;
+
+  //
+  // If Operand is <= MAX_INTN, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeUintnToIntn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabababab);
+  Status  = SafeUintnToIntn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToInt64) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  INT64       Result;
+
+  //
+  // UINTN is same as UINT32 in IA32, and UINT32 is a subset of
+  // INT64, so this is just a cast
+  //
+  Operand = 0xabababab;
+  Result  = 0;
+  Status  = SafeUintnToInt64 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabababab, Result);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToIntn) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  INTN        Result;
+
+  //
+  // If Operand is between MIN_INTN and  MAX_INTN2 inclusive, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeInt64ToIntn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bababab, Result);
+
+  Operand = (-1537977259);
+  Status  = SafeInt64ToIntn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-1537977259), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5babababefefefef);
+  Status  = SafeInt64ToIntn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToIntn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToUintn) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  UINTN       Result;
+
+  //
+  // If Operand is between 0 and  MAX_UINTN inclusive, then it's a cast
+  //
+  Operand = 0xabababab;
+  Result  = 0;
+  Status  = SafeInt64ToUintn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5babababefefefef);
+  Status  = SafeInt64ToUintn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToUintn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToIntn) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  INTN        Result;
+
+  //
+  // If Operand is <= MAX_INTN, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeUint64ToIntn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToIntn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToUintn) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  UINTN       Result;
+
+  //
+  // If Operand is <= MAX_UINTN, then it's a cast
+  //
+  Operand = 0xabababab;
+  Result  = 0;
+  Status  = SafeUint64ToUintn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToUintn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeUintnAdd) {
+  RETURN_STATUS  Status;
+  UINTN       Augend;
+  UINTN       Addend;
+  UINTN       Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_UINTN, then it's addition
+  //
+  Augend = 0x3a3a3a3a;
+  Addend = 0x3a3a3a3a;
+  Result = 0;
+  Status = SafeUintnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x74747474, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0xabababab;
+  Addend = 0xbcbcbcbc;
+  Status = SafeUintnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeIntnAdd) {
+  RETURN_STATUS  Status;
+  INTN        Augend;
+  INTN        Addend;
+  INTN        Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_INTN
+  // and doesn't underflow MIN_INTN, then it's addition
+  //
+  Augend = 0x3a3a3a3a;
+  Addend = 0x3a3a3a3a;
+  Result = 0;
+  Status = SafeIntnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x74747474, Result);
+
+  Augend = (-976894522);
+  Addend = (-976894522);
+  Status = SafeIntnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-1953789044), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0x5a5a5a5a;
+  Addend = 0x5a5a5a5a;
+  Status = SafeIntnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Augend = (-1515870810);
+  Addend = (-1515870810);
+  Status = SafeIntnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeUintnSub) {
+  RETURN_STATUS  Status;
+  UINTN       Minuend;
+  UINTN       Subtrahend;
+  UINTN       Result;
+
+  //
+  // If Minuend >= Subtrahend, then it's subtraction
+  //
+  Minuend    = 0x5a5a5a5a;
+  Subtrahend = 0x3b3b3b3b;
+  Result     = 0;
+  Status     = SafeUintnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x1f1f1f1f, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = 0x5a5a5a5a;
+  Subtrahend = 0x6d6d6d6d;
+  Status     = SafeUintnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeIntnSub) {
+  RETURN_STATUS  Status;
+  INTN        Minuend;
+  INTN        Subtrahend;
+  INTN        Result;
+
+  //
+  // If the result of subtractions doesn't overflow MAX_INTN or
+  // underflow MIN_INTN, then it's subtraction
+  //
+  Minuend    = 0x5a5a5a5a;
+  Subtrahend = 0x3a3a3a3a;
+  Result     = 0;
+  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x20202020, Result);
+
+  Minuend    = 0x3a3a3a3a;
+  Subtrahend = 0x5a5a5a5a;
+  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-538976288), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = (-2054847098);
+  Subtrahend = 2054847098;
+  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Minuend    = (2054847098);
+  Subtrahend = (-2054847098);
+  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeUintnMult) {
+  RETURN_STATUS  Status;
+  UINTN       Multiplicand;
+  UINTN       Multiplier;
+  UINTN       Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_UINTN, it will succeed
+  //
+  Multiplicand = 0xa122a;
+  Multiplier   = 0xd23;
+  Result       = 0;
+  Status       = SafeUintnMult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x844c9dbe, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0xa122a;
+  Multiplier   = 0xed23;
+  Status       = SafeUintnMult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeIntnMult) {
+  RETURN_STATUS  Status;
+  INTN        Multiplicand;
+  INTN        Multiplier;
+  INTN        Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_INTN and doesn't
+  // underflow MIN_UINTN, it will succeed
+  //
+  Multiplicand = 0x123456;
+  Multiplier   = 0x678;
+  Result       = 0;
+  Status       = SafeIntnMult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x75c28c50, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0x123456;
+  Multiplier   = 0xabc;
+  Status       = SafeIntnMult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
diff --git a/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTests64.cpp b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTests64.cpp
new file mode 100644
index 000000000000..6fb0710cfed6
--- /dev/null
+++ b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTests64.cpp
@@ -0,0 +1,429 @@
+/** @file
+  x64-specific functions for unit-testing INTN and UINTN functions in
+  SafeIntLib.
+
+  Copyright (c) Microsoft Corporation.<BR>
+  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <gtest/gtest.h>
+extern "C" {
+  #include <Base.h>
+  #include <Library/SafeIntLib.h>
+}
+
+TEST(ConversionTestSuite, TestSafeInt32ToUintn) {
+  RETURN_STATUS  Status;
+  INT32       Operand;
+  UINTN       Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeInt32ToUintn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-1537977259);
+  Status  = SafeInt32ToUintn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint32ToIntn) {
+  RETURN_STATUS  Status;
+  UINT32      Operand;
+  INTN        Result;
+
+  //
+  // For x64, INTN is same as INT64 which is a superset of INT32
+  // This is just a cast then, and it'll never fail
+  //
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0xabababab;
+  Result  = 0;
+  Status  = SafeUint32ToIntn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabababab, Result);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToInt32) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  INT32       Result;
+
+  //
+  // If Operand is between MIN_INT32 and  MAX_INT32 inclusive, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeIntnToInt32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bababab, Result);
+
+  Operand = (-1537977259);
+  Status  = SafeIntnToInt32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-1537977259), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5babababefefefef);
+  Status  = SafeIntnToInt32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeIntnToInt32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToUint32) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  UINT32      Result;
+
+  //
+  // If Operand is between 0 and  MAX_UINT32 inclusive, then it's a cast
+  //
+  Operand = 0xabababab;
+  Result  = 0;
+  Status  = SafeIntnToUint32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5babababefefefef);
+  Status  = SafeIntnToUint32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeIntnToUint32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToUint32) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  UINT32      Result;
+
+  //
+  // If Operand is <= MAX_UINT32, then it's a cast
+  //
+  Operand = 0xabababab;
+  Result  = 0;
+  Status  = SafeUintnToUint32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUintnToUint32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToIntn) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  INTN        Result;
+
+  //
+  // If Operand is <= MAX_INTN (0x7fff_ffff_ffff_ffff), then it's a cast
+  //
+  Operand = 0x5babababefefefef;
+  Result  = 0;
+  Status  = SafeUintnToIntn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5babababefefefef, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUintnToIntn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToInt64) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  INT64       Result;
+
+  //
+  // If Operand is <= MAX_INT64, then it's a cast
+  //
+  Operand = 0x5babababefefefef;
+  Result  = 0;
+  Status  = SafeUintnToInt64 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5babababefefefef, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUintnToInt64 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToIntn) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  INTN        Result;
+
+  //
+  // INTN is same as INT64 in x64, so this is just a cast
+  //
+  Operand = 0x5babababefefefef;
+  Result  = 0;
+  Status  = SafeInt64ToIntn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5babababefefefef, Result);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToUintn) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  UINTN       Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5babababefefefef;
+  Result  = 0;
+  Status  = SafeInt64ToUintn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x5babababefefefef, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToUintn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToIntn) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  INTN        Result;
+
+  //
+  // If Operand is <= MAX_INTN (0x7fff_ffff_ffff_ffff), then it's a cast
+  //
+  Operand = 0x5babababefefefef;
+  Result  = 0;
+  Status  = SafeUint64ToIntn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5babababefefefef, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToIntn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToUintn) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  UINTN       Result;
+
+  //
+  // UINTN is same as UINT64 in x64, so this is just a cast
+  //
+  Operand = 0xababababefefefef;
+  Result  = 0;
+  Status  = SafeUint64ToUintn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xababababefefefef, Result);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeUintnAdd) {
+  RETURN_STATUS  Status;
+  UINTN       Augend;
+  UINTN       Addend;
+  UINTN       Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_UINTN, then it's addition
+  //
+  Augend = 0x3a3a3a3a12121212;
+  Addend = 0x3a3a3a3a12121212;
+  Result = 0;
+  Status = SafeUintnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x7474747424242424, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0xababababefefefef;
+  Addend = 0xbcbcbcbcdededede;
+  Status = SafeUintnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeIntnAdd) {
+  RETURN_STATUS  Status;
+  INTN        Augend;
+  INTN        Addend;
+  INTN        Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_INTN
+  // and doesn't underflow MIN_INTN, then it's addition
+  //
+  Augend = 0x3a3a3a3a3a3a3a3a;
+  Addend = 0x3a3a3a3a3a3a3a3a;
+  Result = 0;
+  Status = SafeIntnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x7474747474747474, Result);
+
+  Augend = (-4195730024608447034);
+  Addend = (-4195730024608447034);
+  Status = SafeIntnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-8391460049216894068), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0x5a5a5a5a5a5a5a5a;
+  Addend = 0x5a5a5a5a5a5a5a5a;
+  Status = SafeIntnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Augend = (-6510615555426900570);
+  Addend = (-6510615555426900570);
+  Status = SafeIntnAdd (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeUintnSub) {
+  RETURN_STATUS  Status;
+  UINTN       Minuend;
+  UINTN       Subtrahend;
+  UINTN       Result;
+
+  //
+  // If Minuend >= Subtrahend, then it's subtraction
+  //
+  Minuend    = 0x5a5a5a5a5a5a5a5a;
+  Subtrahend = 0x3b3b3b3b3b3b3b3b;
+  Result     = 0;
+  Status     = SafeUintnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x1f1f1f1f1f1f1f1f, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = 0x5a5a5a5a5a5a5a5a;
+  Subtrahend = 0x6d6d6d6d6d6d6d6d;
+  Status     = SafeUintnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeIntnSub) {
+  RETURN_STATUS  Status;
+  INTN        Minuend;
+  INTN        Subtrahend;
+  INTN        Result;
+
+  //
+  // If the result of subtractions doesn't overflow MAX_INTN or
+  // underflow MIN_INTN, then it's subtraction
+  //
+  Minuend    = 0x5a5a5a5a5a5a5a5a;
+  Subtrahend = 0x3a3a3a3a3a3a3a3a;
+  Result     = 0;
+  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x2020202020202020, Result);
+
+  Minuend    = 0x3a3a3a3a3a3a3a3a;
+  Subtrahend = 0x5a5a5a5a5a5a5a5a;
+  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-2314885530818453536), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = (-8825501086245354106);
+  Subtrahend = 8825501086245354106;
+  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Minuend    = (8825501086245354106);
+  Subtrahend = (-8825501086245354106);
+  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeUintnMult) {
+  RETURN_STATUS  Status;
+  UINTN       Multiplicand;
+  UINTN       Multiplier;
+  UINTN       Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_UINTN, it will succeed
+  //
+  Multiplicand = 0x123456789a;
+  Multiplier   = 0x1234567;
+  Result       = 0;
+  Status       = SafeUintnMult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x14b66db9745a07f6, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0x123456789a;
+  Multiplier   = 0x12345678;
+  Status       = SafeUintnMult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeIntnMult) {
+  RETURN_STATUS  Status;
+  INTN        Multiplicand;
+  INTN        Multiplier;
+  INTN        Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_INTN and doesn't
+  // underflow MIN_UINTN, it will succeed
+  //
+  Multiplicand = 0x123456789;
+  Multiplier   = 0x6789abcd;
+  Result       = 0;
+  Status       = SafeIntnMult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x75cd9045220d6bb5, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0x123456789;
+  Multiplier   = 0xa789abcd;
+  Status       = SafeIntnMult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
diff --git a/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.cpp b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.cpp
new file mode 100644
index 000000000000..1fd51067a1f3
--- /dev/null
+++ b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.cpp
@@ -0,0 +1,2274 @@
+/** @file
+  UEFI OS based application for unit testing the SafeIntLib.
+
+  Copyright (c) Microsoft Corporation.<BR>
+  Copyright (c) 2018 - 2022, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#include <gtest/gtest.h>
+extern "C" {
+  #include <Base.h>
+  #include <Library/SafeIntLib.h>
+}
+
+//
+// Conversion function tests:
+//
+TEST(ConversionTestSuite, TestSafeInt8ToUint8) {
+  RETURN_STATUS  Status;
+  INT8        Operand;
+  UINT8       Result;
+
+  //
+  // Positive UINT8 should result in just a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt8ToUint8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Negative number should result in an error status
+  //
+  Operand = (-56);
+  Status  = SafeInt8ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt8ToUint16) {
+  RETURN_STATUS  Status;
+  INT8        Operand;
+  UINT16      Result;
+
+  //
+  // Positive UINT8 should result in just a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt8ToUint16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Negative number should result in an error status
+  //
+  Operand = (-56);
+  Status  = SafeInt8ToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt8ToUint32) {
+  RETURN_STATUS  Status;
+  INT8        Operand;
+  UINT32      Result;
+
+  //
+  // Positive UINT8 should result in just a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt8ToUint32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT32)0x5b, Result);
+
+  //
+  // Negative number should result in an error status
+  //
+  Operand = (-56);
+  Status  = SafeInt8ToUint32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt8ToUintn) {
+  RETURN_STATUS  Status;
+  INT8        Operand;
+  UINTN       Result;
+
+  //
+  // Positive UINT8 should result in just a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt8ToUintn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x5b, Result);
+
+  //
+  // Negative number should result in an error status
+  //
+  Operand = (-56);
+  Status  = SafeInt8ToUintn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt8ToUint64) {
+  RETURN_STATUS  Status;
+  INT8        Operand;
+  UINT64      Result;
+
+  //
+  // Positive UINT8 should result in just a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt8ToUint64 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT64)0x5b, Result);
+
+  //
+  // Negative number should result in an error status
+  //
+  Operand = (-56);
+  Status  = SafeInt8ToUint64 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint8ToInt8) {
+  RETURN_STATUS  Status;
+  UINT8       Operand;
+  INT8        Result;
+
+  //
+  // Operand <= 0x7F (MAX_INT8) should result in a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeUint8ToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Operand larger than 0x7f should result in an error status
+  //
+  Operand = 0xaf;
+  Status  = SafeUint8ToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint8ToChar8) {
+  RETURN_STATUS  Status;
+  UINT8       Operand;
+  CHAR8       Result;
+
+  //
+  // CHAR8 is typedefed as char, which by default is signed, thus
+  // CHAR8 is same as INT8, so same tests as above:
+  //
+
+  //
+  // Operand <= 0x7F (MAX_INT8) should result in a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeUint8ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Operand larger than 0x7f should result in an error status
+  //
+  Operand = 0xaf;
+  Status  = SafeUint8ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt16ToInt8) {
+  RETURN_STATUS  Status;
+  INT16       Operand;
+  INT8        Result;
+
+  //
+  // If Operand is between MIN_INT8 and MAX_INT8 inclusive, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt16ToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  Operand = (-35);
+  Status  = SafeInt16ToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-35), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = 0x1234;
+  Status  = SafeInt16ToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-17835);
+  Status  = SafeInt16ToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt16ToChar8) {
+  RETURN_STATUS  Status;
+  INT16       Operand;
+  CHAR8       Result;
+
+  //
+  // CHAR8 is typedefed as char, which may be signed or unsigned based
+  // on the compiler. Thus, for compatibility CHAR8 should be between 0 and MAX_INT8.
+  //
+
+  //
+  // If Operand is between 0 and MAX_INT8 inclusive, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt16ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  Operand = 0;
+  Result  = 0;
+  Status  = SafeInt16ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0, Result);
+
+  Operand = MAX_INT8;
+  Result  = 0;
+  Status  = SafeInt16ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (MAX_INT8, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-35);
+  Status  = SafeInt16ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = 0x1234;
+  Status  = SafeInt16ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-17835);
+  Status  = SafeInt16ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt16ToUint8) {
+  RETURN_STATUS  Status;
+  INT16       Operand;
+  UINT8       Result;
+
+  //
+  // If Operand is between 0 and MAX_INT8 inclusive, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt16ToUint8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = 0x1234;
+  Status  = SafeInt16ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-17835);
+  Status  = SafeInt16ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt16ToUint16) {
+  RETURN_STATUS  Status;
+  INT16       Operand = 0x5b5b;
+  UINT16      Result  = 0;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Status = SafeInt16ToUint16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-17835);
+  Status  = SafeInt16ToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt16ToUint32) {
+  RETURN_STATUS  Status;
+  INT16       Operand;
+  UINT32      Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5b5b;
+  Result  = 0;
+  Status  = SafeInt16ToUint32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT32)0x5b5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-17835);
+  Status  = SafeInt16ToUint32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt16ToUintn) {
+  RETURN_STATUS  Status;
+  INT16       Operand;
+  UINTN       Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5b5b;
+  Result  = 0;
+  Status  = SafeInt16ToUintn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x5b5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-17835);
+  Status  = SafeInt16ToUintn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt16ToUint64) {
+  RETURN_STATUS  Status;
+  INT16       Operand;
+  UINT64      Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5b5b;
+  Result  = 0;
+  Status  = SafeInt16ToUint64 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT64)0x5b5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-17835);
+  Status  = SafeInt16ToUint64 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint16ToInt8) {
+  RETURN_STATUS  Status;
+  UINT16      Operand;
+  INT8        Result;
+
+  //
+  // If Operand is <= MAX_INT8, it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeUint16ToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5b5b);
+  Status  = SafeUint16ToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint16ToChar8) {
+  RETURN_STATUS  Status;
+  UINT16      Operand;
+  CHAR8       Result;
+
+  // CHAR8 is typedefed as char, which by default is signed, thus
+  // CHAR8 is same as INT8, so same tests as above:
+
+  //
+  // If Operand is <= MAX_INT8, it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeUint16ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5b5b);
+  Status  = SafeUint16ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint16ToUint8) {
+  RETURN_STATUS  Status;
+  UINT16      Operand;
+  UINT8       Result;
+
+  //
+  // If Operand is <= MAX_UINT8 (0xff), it's a cast
+  //
+  Operand = 0xab;
+  Result  = 0;
+  Status  = SafeUint16ToUint8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5b5b);
+  Status  = SafeUint16ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint16ToInt16) {
+  RETURN_STATUS  Status;
+  UINT16      Operand;
+  INT16       Result;
+
+  //
+  // If Operand is <= MAX_INT16 (0x7fff), it's a cast
+  //
+  Operand = 0x5b5b;
+  Result  = 0;
+  Status  = SafeUint16ToInt16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabab);
+  Status  = SafeUint16ToInt16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt32ToInt8) {
+  RETURN_STATUS  Status;
+  INT32       Operand;
+  INT8        Result;
+
+  //
+  // If Operand is between MIN_INT8 and MAX_INT8 inclusive, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt32ToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  Operand = (-57);
+  Status  = SafeInt32ToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-57), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5bababab);
+  Status  = SafeInt32ToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-1537977259);
+  Status  = SafeInt32ToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt32ToChar8) {
+  RETURN_STATUS  Status;
+  INT32       Operand;
+  CHAR8       Result;
+
+  //
+  // CHAR8 is typedefed as char, which may be signed or unsigned based
+  // on the compiler. Thus, for compatibility CHAR8 should be between 0 and MAX_INT8.
+  //
+
+  //
+  // If Operand is between 0 and MAX_INT8 inclusive, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt32ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  Operand = 0;
+  Result  = 0;
+  Status  = SafeInt32ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0, Result);
+
+  Operand = MAX_INT8;
+  Result  = 0;
+  Status  = SafeInt32ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (MAX_INT8, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-57);
+  Status  = SafeInt32ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (0x5bababab);
+  Status  = SafeInt32ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-1537977259);
+  Status  = SafeInt32ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt32ToUint8) {
+  RETURN_STATUS  Status;
+  INT32       Operand;
+  UINT8       Result;
+
+  //
+  // If Operand is between 0 and MAX_INT8 inclusive, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt32ToUint8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-57);
+  Status  = SafeInt32ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (0x5bababab);
+  Status  = SafeInt32ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-1537977259);
+  Status  = SafeInt32ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt32ToInt16) {
+  RETURN_STATUS  Status;
+  INT32       Operand;
+  INT16       Result;
+
+  //
+  // If Operand is between MIN_INT16 and MAX_INT16 inclusive, then it's a cast
+  //
+  Operand = 0x5b5b;
+  Result  = 0;
+  Status  = SafeInt32ToInt16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b5b, Result);
+
+  Operand = (-17857);
+  Status  = SafeInt32ToInt16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-17857), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5bababab);
+  Status  = SafeInt32ToInt16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-1537977259);
+  Status  = SafeInt32ToInt16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt32ToUint16) {
+  RETURN_STATUS  Status;
+  INT32       Operand;
+  UINT16      Result;
+
+  //
+  // If Operand is between 0 and MAX_UINT16 inclusive, then it's a cast
+  //
+  Operand = 0xabab;
+  Result  = 0;
+  Status  = SafeInt32ToUint16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-17857);
+  Status  = SafeInt32ToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (0x5bababab);
+  Status  = SafeInt32ToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-1537977259);
+  Status  = SafeInt32ToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt32ToUint32) {
+  RETURN_STATUS  Status;
+  INT32       Operand;
+  UINT32      Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeInt32ToUint32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT32)0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-1537977259);
+  Status  = SafeInt32ToUint32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt32ToUint64) {
+  RETURN_STATUS  Status;
+  INT32       Operand;
+  UINT64      Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeInt32ToUint64 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT64)0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-1537977259);
+  Status  = SafeInt32ToUint64 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint32ToInt8) {
+  RETURN_STATUS  Status;
+  UINT32      Operand;
+  INT8        Result;
+
+  //
+  // If Operand is <= MAX_INT8, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeUint32ToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5bababab);
+  Status  = SafeUint32ToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint32ToChar8) {
+  RETURN_STATUS  Status;
+  UINT32      Operand;
+  CHAR8       Result;
+
+  // CHAR8 is typedefed as char, which by default is signed, thus
+  // CHAR8 is same as INT8, so same tests as above:
+
+  //
+  // If Operand is <= MAX_INT8, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeUint32ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5bababab);
+  Status  = SafeUint32ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint32ToUint8) {
+  RETURN_STATUS  Status;
+  UINT32      Operand;
+  UINT8       Result;
+
+  //
+  // If Operand is <= MAX_UINT8, then it's a cast
+  //
+  Operand = 0xab;
+  Result  = 0;
+  Status  = SafeUint32ToUint8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabababab);
+  Status  = SafeUint32ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint32ToInt16) {
+  RETURN_STATUS  Status;
+  UINT32      Operand;
+  INT16       Result;
+
+  //
+  // If Operand is <= MAX_INT16, then it's a cast
+  //
+  Operand = 0x5bab;
+  Result  = 0;
+  Status  = SafeUint32ToInt16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabababab);
+  Status  = SafeUint32ToInt16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint32ToUint16) {
+  RETURN_STATUS  Status;
+  UINT32      Operand;
+  UINT16      Result;
+
+  //
+  // If Operand is <= MAX_UINT16, then it's a cast
+  //
+  Operand = 0xabab;
+  Result  = 0;
+  Status  = SafeUint32ToUint16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabababab);
+  Status  = SafeUint32ToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint32ToInt32) {
+  RETURN_STATUS  Status;
+  UINT32      Operand;
+  INT32       Result;
+
+  //
+  // If Operand is <= MAX_INT32, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeUint32ToInt32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabababab);
+  Status  = SafeUint32ToInt32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToInt8) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  INT8        Result;
+
+  //
+  // If Operand is between MIN_INT8 and MAX_INT8 inclusive, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeIntnToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  Operand = (-53);
+  Status  = SafeIntnToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-53), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5bababab);
+  Status  = SafeIntnToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-1537977259);
+  Status  = SafeIntnToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToChar8) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  CHAR8       Result;
+
+  //
+  // CHAR8 is typedefed as char, which may be signed or unsigned based
+  // on the compiler. Thus, for compatibility CHAR8 should be between 0 and MAX_INT8.
+  //
+
+  //
+  // If Operand is between MIN_INT8 and MAX_INT8 inclusive, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeIntnToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  Operand = 0;
+  Result  = 0;
+  Status  = SafeIntnToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0, Result);
+
+  Operand = MAX_INT8;
+  Result  = 0;
+  Status  = SafeIntnToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (MAX_INT8, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-53);
+  Status  = SafeIntnToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (0x5bababab);
+  Status  = SafeIntnToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-1537977259);
+  Status  = SafeIntnToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToUint8) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  UINT8       Result;
+
+  //
+  // If Operand is between 0 and MAX_UINT8 inclusive, then it's a cast
+  //
+  Operand = 0xab;
+  Result  = 0;
+  Status  = SafeIntnToUint8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5bababab);
+  Status  = SafeIntnToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-1537977259);
+  Status  = SafeIntnToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToInt16) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  INT16       Result;
+
+  //
+  // If Operand is between MIN_INT16 and MAX_INT16 inclusive, then it's a cast
+  //
+  Operand = 0x5bab;
+  Result  = 0;
+  Status  = SafeIntnToInt16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bab, Result);
+
+  Operand = (-23467);
+  Status  = SafeIntnToInt16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-23467), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5bababab);
+  Status  = SafeIntnToInt16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-1537977259);
+  Status  = SafeIntnToInt16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToUint16) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  UINT16      Result;
+
+  //
+  // If Operand is between 0 and MAX_UINT16 inclusive, then it's a cast
+  //
+  Operand = 0xabab;
+  Result  = 0;
+  Status  = SafeIntnToUint16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5bababab);
+  Status  = SafeIntnToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (-1537977259);
+  Status  = SafeIntnToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToUintn) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  UINTN       Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeIntnToUintn (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINTN)0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-1537977259);
+  Status  = SafeIntnToUintn (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeIntnToUint64) {
+  RETURN_STATUS  Status;
+  INTN        Operand;
+  UINT64      Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeIntnToUint64 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT64)0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-1537977259);
+  Status  = SafeIntnToUint64 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToInt8) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  INT8        Result;
+
+  //
+  // If Operand is <= MAX_INT8, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeUintnToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabab);
+  Status  = SafeUintnToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToChar8) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  CHAR8       Result;
+
+  // CHAR8 is typedefed as char, which by default is signed, thus
+  // CHAR8 is same as INT8, so same tests as above:
+
+  //
+  // If Operand is <= MAX_INT8, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeUintnToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabab);
+  Status  = SafeUintnToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToUint8) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  UINT8       Result;
+
+  //
+  // If Operand is <= MAX_UINT8, then it's a cast
+  //
+  Operand = 0xab;
+  Result  = 0;
+  Status  = SafeUintnToUint8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabab);
+  Status  = SafeUintnToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToInt16) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  INT16       Result;
+
+  //
+  // If Operand is <= MAX_INT16, then it's a cast
+  //
+  Operand = 0x5bab;
+  Result  = 0;
+  Status  = SafeUintnToInt16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabab);
+  Status  = SafeUintnToInt16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToUint16) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  UINT16      Result;
+
+  //
+  // If Operand is <= MAX_UINT16, then it's a cast
+  //
+  Operand = 0xabab;
+  Result  = 0;
+  Status  = SafeUintnToUint16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabababab);
+  Status  = SafeUintnToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUintnToInt32) {
+  RETURN_STATUS  Status;
+  UINTN       Operand;
+  INT32       Result;
+
+  //
+  // If Operand is <= MAX_INT32, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeUintnToInt32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xabababab);
+  Status  = SafeUintnToInt32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToInt8) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  INT8        Result;
+
+  //
+  // If Operand is between MIN_INT8 and  MAX_INT8 inclusive, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt64ToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  Operand = (-37);
+  Status  = SafeInt64ToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-37), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5babababefefefef);
+  Status  = SafeInt64ToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToChar8) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  CHAR8       Result;
+
+  //
+  // CHAR8 is typedefed as char, which may be signed or unsigned based
+  // on the compiler. Thus, for compatibility CHAR8 should be between 0 and MAX_INT8.
+  //
+
+  //
+  // If Operand is between MIN_INT8 and  MAX_INT8 inclusive, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeInt64ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  Operand = 0;
+  Result  = 0;
+  Status  = SafeInt64ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0, Result);
+
+  Operand = MAX_INT8;
+  Result  = 0;
+  Status  = SafeInt64ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (MAX_INT8, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (-37);
+  Status  = SafeInt64ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand = (0x5babababefefefef);
+  Status  = SafeInt64ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToUint8) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  UINT8       Result;
+
+  //
+  // If Operand is between 0 and  MAX_UINT8 inclusive, then it's a cast
+  //
+  Operand = 0xab;
+  Result  = 0;
+  Status  = SafeInt64ToUint8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5babababefefefef);
+  Status  = SafeInt64ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToInt16) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  INT16       Result;
+
+  //
+  // If Operand is between MIN_INT16 and  MAX_INT16 inclusive, then it's a cast
+  //
+  Operand = 0x5bab;
+  Result  = 0;
+  Status  = SafeInt64ToInt16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bab, Result);
+
+  Operand = (-23467);
+  Status  = SafeInt64ToInt16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-23467), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5babababefefefef);
+  Status  = SafeInt64ToInt16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToInt16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToUint16) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  UINT16      Result;
+
+  //
+  // If Operand is between 0 and  MAX_UINT16 inclusive, then it's a cast
+  //
+  Operand = 0xabab;
+  Result  = 0;
+  Status  = SafeInt64ToUint16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5babababefefefef);
+  Status  = SafeInt64ToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToInt32) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  INT32       Result;
+
+  //
+  // If Operand is between MIN_INT32 and  MAX_INT32 inclusive, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeInt64ToInt32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bababab, Result);
+
+  Operand = (-1537977259);
+  Status  = SafeInt64ToInt32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-1537977259), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5babababefefefef);
+  Status  = SafeInt64ToInt32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToInt32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToUint32) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  UINT32      Result;
+
+  //
+  // If Operand is between 0 and  MAX_UINT32 inclusive, then it's a cast
+  //
+  Operand = 0xabababab;
+  Result  = 0;
+  Status  = SafeInt64ToUint32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0x5babababefefefef);
+  Status  = SafeInt64ToUint32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToUint32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeInt64ToUint64) {
+  RETURN_STATUS  Status;
+  INT64       Operand;
+  UINT64      Result;
+
+  //
+  // If Operand is non-negative, then it's a cast
+  //
+  Operand = 0x5babababefefefef;
+  Result  = 0;
+  Status  = SafeInt64ToUint64 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT64)0x5babababefefefef, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand =  (-6605562033422200815);
+  Status  = SafeInt64ToUint64 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToInt8) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  INT8        Result;
+
+  //
+  // If Operand is <= MAX_INT8, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeUint64ToInt8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToInt8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToChar8) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  CHAR8       Result;
+
+  // CHAR8 is typedefed as char, which by default is signed, thus
+  // CHAR8 is same as INT8, so same tests as above:
+
+  //
+  // If Operand is <= MAX_INT8, then it's a cast
+  //
+  Operand = 0x5b;
+  Result  = 0;
+  Status  = SafeUint64ToChar8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5b, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToChar8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToUint8) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  UINT8       Result;
+
+  //
+  // If Operand is <= MAX_UINT8, then it's a cast
+  //
+  Operand = 0xab;
+  Result  = 0;
+  Status  = SafeUint64ToUint8 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToUint8 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToInt16) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  INT16       Result;
+
+  //
+  // If Operand is <= MAX_INT16, then it's a cast
+  //
+  Operand = 0x5bab;
+  Result  = 0;
+  Status  = SafeUint64ToInt16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToInt16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToUint16) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  UINT16      Result;
+
+  //
+  // If Operand is <= MAX_UINT16, then it's a cast
+  //
+  Operand = 0xabab;
+  Result  = 0;
+  Status  = SafeUint64ToUint16 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToUint16 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToInt32) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  INT32       Result;
+
+  //
+  // If Operand is <= MAX_INT32, then it's a cast
+  //
+  Operand = 0x5bababab;
+  Result  = 0;
+  Status  = SafeUint64ToInt32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5bababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToInt32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToUint32) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  UINT32      Result;
+
+  //
+  // If Operand is <= MAX_UINT32, then it's a cast
+  //
+  Operand = 0xabababab;
+  Result  = 0;
+  Status  = SafeUint64ToUint32 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xabababab, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToUint32 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(ConversionTestSuite, TestSafeUint64ToInt64) {
+  RETURN_STATUS  Status;
+  UINT64      Operand;
+  INT64       Result;
+
+  //
+  // If Operand is <= MAX_INT64, then it's a cast
+  //
+  Operand = 0x5babababefefefef;
+  Result  = 0;
+  Status  = SafeUint64ToInt64 (Operand, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x5babababefefefef, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Operand = (0xababababefefefef);
+  Status  = SafeUint64ToInt64 (Operand, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+//
+// Addition function tests:
+//
+TEST(AdditionSubtractionTestSuite, TestSafeUint8Add) {
+  RETURN_STATUS  Status;
+  UINT8       Augend;
+  UINT8       Addend;
+  UINT8       Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_UINT8, then it's addition
+  //
+  Augend = 0x3a;
+  Addend = 0x3a;
+  Result = 0;
+  Status = SafeUint8Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x74, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0xab;
+  Addend = 0xbc;
+  Status = SafeUint8Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeUint16Add) {
+  RETURN_STATUS  Status;
+  UINT16      Augend = 0x3a3a;
+  UINT16      Addend = 0x3a3a;
+  UINT16      Result = 0;
+
+  //
+  // If the result of addition doesn't overflow MAX_UINT16, then it's addition
+  //
+  Status = SafeUint16Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x7474, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0xabab;
+  Addend = 0xbcbc;
+  Status = SafeUint16Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeUint32Add) {
+  RETURN_STATUS  Status;
+  UINT32      Augend;
+  UINT32      Addend;
+  UINT32      Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_UINT32, then it's addition
+  //
+  Augend = 0x3a3a3a3a;
+  Addend = 0x3a3a3a3a;
+  Result = 0;
+  Status = SafeUint32Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT32)0x74747474, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0xabababab;
+  Addend = 0xbcbcbcbc;
+  Status = SafeUint32Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeUint64Add) {
+  RETURN_STATUS  Status;
+  UINT64      Augend;
+  UINT64      Addend;
+  UINT64      Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_UINT64, then it's addition
+  //
+  Augend = 0x3a3a3a3a12121212;
+  Addend = 0x3a3a3a3a12121212;
+  Result = 0;
+  Status = SafeUint64Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT64)0x7474747424242424, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0xababababefefefef;
+  Addend = 0xbcbcbcbcdededede;
+  Status = SafeUint64Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeInt8Add) {
+  RETURN_STATUS  Status;
+  INT8        Augend;
+  INT8        Addend;
+  INT8        Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_INT8
+  // and doesn't underflow MIN_INT8, then it's addition
+  //
+  Augend = 0x3a;
+  Addend = 0x3a;
+  Result = 0;
+  Status = SafeInt8Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x74, Result);
+
+  Augend = (-58);
+  Addend = (-58);
+  Status = SafeInt8Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-116), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0x5a;
+  Addend = 0x5a;
+  Status = SafeInt8Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Augend = (-90);
+  Addend = (-90);
+  Status = SafeInt8Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeInt16Add) {
+  RETURN_STATUS  Status;
+  INT16       Augend;
+  INT16       Addend;
+  INT16       Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_INT16
+  // and doesn't underflow MIN_INT16, then it's addition
+  //
+  Augend = 0x3a3a;
+  Addend = 0x3a3a;
+  Result = 0;
+  Status = SafeInt16Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x7474, Result);
+
+  Augend = (-14906);
+  Addend = (-14906);
+  Status = SafeInt16Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-29812), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0x5a5a;
+  Addend = 0x5a5a;
+  Status = SafeInt16Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Augend = (-23130);
+  Addend = (-23130);
+  Status = SafeInt16Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeInt32Add) {
+  RETURN_STATUS  Status;
+  INT32       Augend;
+  INT32       Addend;
+  INT32       Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_INT32
+  // and doesn't underflow MIN_INT32, then it's addition
+  //
+  Augend = 0x3a3a3a3a;
+  Addend = 0x3a3a3a3a;
+  Result = 0;
+  Status = SafeInt32Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x74747474, Result);
+
+  Augend = (-976894522);
+  Addend = (-976894522);
+  Status = SafeInt32Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-1953789044), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0x5a5a5a5a;
+  Addend = 0x5a5a5a5a;
+  Status = SafeInt32Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Augend = (-1515870810);
+  Addend = (-1515870810);
+  Status = SafeInt32Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeInt64Add) {
+  RETURN_STATUS  Status;
+  INT64       Augend;
+  INT64       Addend;
+  INT64       Result;
+
+  //
+  // If the result of addition doesn't overflow MAX_INT64
+  // and doesn't underflow MIN_INT64, then it's addition
+  //
+  Augend = 0x3a3a3a3a3a3a3a3a;
+  Addend = 0x3a3a3a3a3a3a3a3a;
+  Result = 0;
+  Status = SafeInt64Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x7474747474747474, Result);
+
+  Augend = (-4195730024608447034);
+  Addend = (-4195730024608447034);
+  Status = SafeInt64Add (Augend, Addend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-8391460049216894068), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Augend = 0x5a5a5a5a5a5a5a5a;
+  Addend = 0x5a5a5a5a5a5a5a5a;
+  Status = SafeInt64Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Augend = (-6510615555426900570);
+  Addend = (-6510615555426900570);
+  Status = SafeInt64Add (Augend, Addend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+//
+// Subtraction function tests:
+//
+TEST(AdditionSubtractionTestSuite, TestSafeUint8Sub) {
+  RETURN_STATUS  Status;
+  UINT8       Minuend;
+  UINT8       Subtrahend;
+  UINT8       Result;
+
+  //
+  // If Minuend >= Subtrahend, then it's subtraction
+  //
+  Minuend    = 0x5a;
+  Subtrahend = 0x3b;
+  Result     = 0;
+  Status     = SafeUint8Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x1f, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = 0x5a;
+  Subtrahend = 0x6d;
+  Status     = SafeUint8Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeUint16Sub) {
+  RETURN_STATUS  Status;
+  UINT16      Minuend;
+  UINT16      Subtrahend;
+  UINT16      Result;
+
+  //
+  // If Minuend >= Subtrahend, then it's subtraction
+  //
+  Minuend    = 0x5a5a;
+  Subtrahend = 0x3b3b;
+  Result     = 0;
+  Status     = SafeUint16Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x1f1f, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = 0x5a5a;
+  Subtrahend = 0x6d6d;
+  Status     = SafeUint16Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeUint32Sub) {
+  RETURN_STATUS  Status;
+  UINT32      Minuend;
+  UINT32      Subtrahend;
+  UINT32      Result;
+
+  //
+  // If Minuend >= Subtrahend, then it's subtraction
+  //
+  Minuend    = 0x5a5a5a5a;
+  Subtrahend = 0x3b3b3b3b;
+  Result     = 0;
+  Status     = SafeUint32Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT32)0x1f1f1f1f, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = 0x5a5a5a5a;
+  Subtrahend = 0x6d6d6d6d;
+  Status     = SafeUint32Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeUint64Sub) {
+  RETURN_STATUS  Status;
+  UINT64      Minuend;
+  UINT64      Subtrahend;
+  UINT64      Result;
+
+  //
+  // If Minuend >= Subtrahend, then it's subtraction
+  //
+  Minuend    = 0x5a5a5a5a5a5a5a5a;
+  Subtrahend = 0x3b3b3b3b3b3b3b3b;
+  Result     = 0;
+  Status     = SafeUint64Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT64)0x1f1f1f1f1f1f1f1f, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = 0x5a5a5a5a5a5a5a5a;
+  Subtrahend = 0x6d6d6d6d6d6d6d6d;
+  Status     = SafeUint64Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeInt8Sub) {
+  RETURN_STATUS  Status;
+  INT8        Minuend;
+  INT8        Subtrahend;
+  INT8        Result;
+
+  //
+  // If the result of subtractions doesn't overflow MAX_INT8 or
+  // underflow MIN_INT8, then it's subtraction
+  //
+  Minuend    = 0x5a;
+  Subtrahend = 0x3a;
+  Result     = 0;
+  Status     = SafeInt8Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x20, Result);
+
+  Minuend    = 58;
+  Subtrahend = 78;
+  Status     = SafeInt8Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-20), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = (-80);
+  Subtrahend = 80;
+  Status     = SafeInt8Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Minuend    = (80);
+  Subtrahend = (-80);
+  Status     = SafeInt8Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeInt16Sub) {
+  RETURN_STATUS  Status;
+  INT16       Minuend;
+  INT16       Subtrahend;
+  INT16       Result;
+
+  //
+  // If the result of subtractions doesn't overflow MAX_INT16 or
+  // underflow MIN_INT16, then it's subtraction
+  //
+  Minuend    = 0x5a5a;
+  Subtrahend = 0x3a3a;
+  Result     = 0;
+  Status     = SafeInt16Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x2020, Result);
+
+  Minuend    = 0x3a3a;
+  Subtrahend = 0x5a5a;
+  Status     = SafeInt16Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-8224), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = (-31354);
+  Subtrahend = 31354;
+  Status     = SafeInt16Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Minuend    = (31354);
+  Subtrahend = (-31354);
+  Status     = SafeInt16Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeInt32Sub) {
+  RETURN_STATUS  Status;
+  INT32       Minuend;
+  INT32       Subtrahend;
+  INT32       Result;
+
+  //
+  // If the result of subtractions doesn't overflow MAX_INT32 or
+  // underflow MIN_INT32, then it's subtraction
+  //
+  Minuend    = 0x5a5a5a5a;
+  Subtrahend = 0x3a3a3a3a;
+  Result     = 0;
+  Status     = SafeInt32Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x20202020, Result);
+
+  Minuend    = 0x3a3a3a3a;
+  Subtrahend = 0x5a5a5a5a;
+  Status     = SafeInt32Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-538976288), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = (-2054847098);
+  Subtrahend = 2054847098;
+  Status     = SafeInt32Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Minuend    = (2054847098);
+  Subtrahend = (-2054847098);
+  Status     = SafeInt32Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(AdditionSubtractionTestSuite, TestSafeInt64Sub) {
+  RETURN_STATUS  Status;
+  INT64       Minuend;
+  INT64       Subtrahend;
+  INT64       Result;
+
+  //
+  // If the result of subtractions doesn't overflow MAX_INT64 or
+  // underflow MIN_INT64, then it's subtraction
+  //
+  Minuend    = 0x5a5a5a5a5a5a5a5a;
+  Subtrahend = 0x3a3a3a3a3a3a3a3a;
+  Result     = 0;
+  Status     = SafeInt64Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x2020202020202020, Result);
+
+  Minuend    = 0x3a3a3a3a3a3a3a3a;
+  Subtrahend = 0x5a5a5a5a5a5a5a5a;
+  Status     = SafeInt64Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((-2314885530818453536), Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Minuend    = (-8825501086245354106);
+  Subtrahend = 8825501086245354106;
+  Status     = SafeInt64Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+
+  Minuend    = (8825501086245354106);
+  Subtrahend = (-8825501086245354106);
+  Status     = SafeInt64Sub (Minuend, Subtrahend, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+//
+// Multiplication function tests:
+//
+TEST(MultiplicationTestSuite, TestSafeUint8Mult) {
+  RETURN_STATUS  Status;
+  UINT8       Multiplicand;
+  UINT8       Multiplier;
+  UINT8       Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_UINT8, it will succeed
+  //
+  Multiplicand = 0x12;
+  Multiplier   = 0xa;
+  Result       = 0;
+  Status       = SafeUint8Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xb4, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0x12;
+  Multiplier   = 0x23;
+  Status       = SafeUint8Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeUint16Mult) {
+  RETURN_STATUS  Status;
+  UINT16      Multiplicand;
+  UINT16      Multiplier;
+  UINT16      Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_UINT16, it will succeed
+  //
+  Multiplicand = 0x212;
+  Multiplier   = 0x7a;
+  Result       = 0;
+  Status       = SafeUint16Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0xfc94, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0x1234;
+  Multiplier   = 0x213;
+  Status       = SafeUint16Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeUint32Mult) {
+  RETURN_STATUS  Status;
+  UINT32      Multiplicand;
+  UINT32      Multiplier;
+  UINT32      Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_UINT32, it will succeed
+  //
+  Multiplicand = 0xa122a;
+  Multiplier   = 0xd23;
+  Result       = 0;
+  Status       = SafeUint32Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x844c9dbe, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0xa122a;
+  Multiplier   = 0xed23;
+  Status       = SafeUint32Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeUint64Mult) {
+  RETURN_STATUS  Status;
+  UINT64      Multiplicand;
+  UINT64      Multiplier;
+  UINT64      Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_UINT64, it will succeed
+  //
+  Multiplicand = 0x123456789a;
+  Multiplier   = 0x1234567;
+  Result       = 0;
+  Status       = SafeUint64Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ ((UINT64)0x14b66db9745a07f6, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0x123456789a;
+  Multiplier   = 0x12345678;
+  Status       = SafeUint64Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeInt8Mult) {
+  RETURN_STATUS  Status;
+  INT8        Multiplicand;
+  INT8        Multiplier;
+  INT8        Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_INT8 and doesn't
+  // underflow MIN_UINT8, it will succeed
+  //
+  Multiplicand = 0x12;
+  Multiplier   = 0x7;
+  Result       = 0;
+  Status       = SafeInt8Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x7e, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0x12;
+  Multiplier   = 0xa;
+  Status       = SafeInt8Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeInt16Mult) {
+  RETURN_STATUS  Status;
+  INT16       Multiplicand;
+  INT16       Multiplier;
+  INT16       Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_INT16 and doesn't
+  // underflow MIN_UINT16, it will succeed
+  //
+  Multiplicand = 0x123;
+  Multiplier   = 0x67;
+  Result       = 0;
+  Status       = SafeInt16Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x7515, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0x123;
+  Multiplier   = 0xab;
+  Status       = SafeInt16Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeInt32Mult) {
+  RETURN_STATUS  Status;
+  INT32       Multiplicand;
+  INT32       Multiplier;
+  INT32       Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_INT32 and doesn't
+  // underflow MIN_UINT32, it will succeed
+  //
+  Multiplicand = 0x123456;
+  Multiplier   = 0x678;
+  Result       = 0;
+  Status       = SafeInt32Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x75c28c50, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0x123456;
+  Multiplier   = 0xabc;
+  Status       = SafeInt32Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+TEST(MultiplicationTestSuite, TestSafeInt64Mult) {
+  RETURN_STATUS  Status;
+  INT64       Multiplicand;
+  INT64       Multiplier;
+  INT64       Result;
+
+  //
+  // If the result of multiplication doesn't overflow MAX_INT64 and doesn't
+  // underflow MIN_UINT64, it will succeed
+  //
+  Multiplicand = 0x123456789;
+  Multiplier   = 0x6789abcd;
+  Result       = 0;
+  Status       = SafeInt64Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (Status, RETURN_SUCCESS);
+  ASSERT_EQ (0x75cd9045220d6bb5, Result);
+
+  //
+  // Otherwise should result in an error status
+  //
+  Multiplicand = 0x123456789;
+  Multiplier   = 0xa789abcd;
+  Status       = SafeInt64Mult (Multiplicand, Multiplier, &Result);
+  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
+}
+
+int main(int argc, char* argv[]) {
+  testing::InitGoogleTest(&argc, argv);
+  return RUN_ALL_TESTS();
+}
diff --git a/MdePkg/Test/MdePkgHostTest.dsc b/MdePkg/Test/MdePkgHostTest.dsc
index 0cac14f0e557..b8b186dd8b17 100644
--- a/MdePkg/Test/MdePkgHostTest.dsc
+++ b/MdePkg/Test/MdePkgHostTest.dsc
@@ -28,6 +28,7 @@ [Components]
   #
   MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibHost.inf
   MdePkg/Test/UnitTest/Library/BaseLib/BaseLibUnitTestsHost.inf
+  MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.inf
 
   #
   # Build HOST_APPLICATION Libraries
-- 
2.37.1.windows.1


^ permalink raw reply related	[flat|nested] 13+ messages in thread

* 回复: [Patch V2 1/7] MdePkg/Include: Update Base.h to improve C++ compatibility
  2022-11-04 20:25 ` [Patch V2 1/7] MdePkg/Include: Update Base.h to improve C++ compatibility Michael D Kinney
@ 2022-11-08  6:59   ` gaoliming
  0 siblings, 0 replies; 13+ messages in thread
From: gaoliming @ 2022-11-08  6:59 UTC (permalink / raw)
  To: 'Michael D Kinney', devel; +Cc: 'Zhiguang Liu'

Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>

> -----邮件原件-----
> 发件人: Michael D Kinney <michael.d.kinney@intel.com>
> 发送时间: 2022年11月5日 4:25
> 收件人: devel@edk2.groups.io
> 抄送: Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu
> <zhiguang.liu@intel.com>
> 主题: [Patch V2 1/7] MdePkg/Include: Update Base.h to improve C++
> compatibility
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134
> 
> * Map NULL to nullptr or __null when c++ compiler is used.
> * Map STATIC_ASSERT to static_assert when a c++ compiler is used.
> * Typecast RETURN_SUCCESS to type RETURN_STATUS to match type used
>   by all return error/warning status codes.  C++ has stricter type
>   checking and found this inconsistency.
> 
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Zhiguang Liu <zhiguang.liu@intel.com>
> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  MdePkg/Include/Base.h | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/MdePkg/Include/Base.h b/MdePkg/Include/Base.h
> index d19ddfe4bba7..d209e6de280a 100644
> --- a/MdePkg/Include/Base.h
> +++ b/MdePkg/Include/Base.h
> @@ -309,7 +309,15 @@ struct _LIST_ENTRY {
>  ///
>  /// NULL pointer (VOID *)
>  ///
> +#if defined (__cplusplus)
> +  #if defined (_MSC_EXTENSIONS)
> +#define NULL  nullptr
> +  #else
> +#define NULL  __null
> +  #endif
> +#else
>  #define NULL  ((VOID *) 0)
> +#endif
> 
>  //
>  // Null character
> @@ -760,7 +768,7 @@ typedef UINTN *BASE_LIST;
>  **/
>  #ifdef MDE_CPU_EBC
>  #define STATIC_ASSERT(Expression, Message)
> -#elif defined (_MSC_EXTENSIONS)
> +#elif defined (_MSC_EXTENSIONS) || defined (__cplusplus)
>  #define STATIC_ASSERT  static_assert
>  #else
>  #define STATIC_ASSERT  _Static_assert
> @@ -959,7 +967,7 @@ typedef UINTN RETURN_STATUS;
>  ///
>  /// The operation completed successfully.
>  ///
> -#define RETURN_SUCCESS  0
> +#define RETURN_SUCCESS  (RETURN_STATUS)(0)
> 
>  ///
>  /// The image failed to load.
> --
> 2.37.1.windows.1




^ permalink raw reply	[flat|nested] 13+ messages in thread

* 回复: [Patch V2 2/7] MdePkg/Include/Library: Undefine _ASSERT() if already defined
  2022-11-04 20:25 ` [Patch V2 2/7] MdePkg/Include/Library: Undefine _ASSERT() if already defined Michael D Kinney
@ 2022-11-08  6:59   ` gaoliming
  0 siblings, 0 replies; 13+ messages in thread
From: gaoliming @ 2022-11-08  6:59 UTC (permalink / raw)
  To: 'Michael D Kinney', devel; +Cc: 'Zhiguang Liu'

Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>

> -----邮件原件-----
> 发件人: Michael D Kinney <michael.d.kinney@intel.com>
> 发送时间: 2022年11月5日 4:25
> 收件人: devel@edk2.groups.io
> 抄送: Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu
> <zhiguang.liu@intel.com>
> 主题: [Patch V2 2/7] MdePkg/Include/Library: Undefine _ASSERT() if already
> defined
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134
> 
> When unit testing is enabled, make sure _ASSERT() is not already
> defined by the host environment before defining _ASSERT().  This
> avoids conflicts with VS20xx builds of GoogleTest based unit tests.
> 
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Zhiguang Liu <zhiguang.liu@intel.com>
> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  MdePkg/Include/Library/DebugLib.h | 3 +++
>  1 file changed, 3 insertions(+)
> 
> diff --git a/MdePkg/Include/Library/DebugLib.h
> b/MdePkg/Include/Library/DebugLib.h
> index 8d3d08638d73..9110be2f41b3 100644
> --- a/MdePkg/Include/Library/DebugLib.h
> +++ b/MdePkg/Include/Library/DebugLib.h
> @@ -337,6 +337,9 @@ UnitTestDebugAssert (
>    IN CONST CHAR8  *Description
>    );
> 
> +  #if defined (_ASSERT)
> +    #undef _ASSERT
> +  #endif
>    #if defined (__clang__) && defined (__FILE_NAME__)
>  #define _ASSERT(Expression)  UnitTestDebugAssert (__FILE_NAME__,
> DEBUG_LINE_NUMBER, DEBUG_EXPRESSION_STRING (Expression))
>    #else
> --
> 2.37.1.windows.1




^ permalink raw reply	[flat|nested] 13+ messages in thread

* 回复: [edk2-devel] [Patch V2 7/7] MdePkg/Test: Add port of BaseSafeIntLib unit tests to GoogleTest
  2022-11-04 20:25 ` [Patch V2 7/7] MdePkg/Test: Add port of BaseSafeIntLib unit tests to GoogleTest Michael D Kinney
@ 2022-11-08  6:59   ` gaoliming
  0 siblings, 0 replies; 13+ messages in thread
From: gaoliming @ 2022-11-08  6:59 UTC (permalink / raw)
  To: devel, michael.d.kinney; +Cc: 'Zhiguang Liu'

Reviewed-by: Liming Gao <gaoliming@byosoft.com.cn>

> -----邮件原件-----
> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Michael D
> Kinney
> 发送时间: 2022年11月5日 4:25
> 收件人: devel@edk2.groups.io
> 抄送: Liming Gao <gaoliming@byosoft.com.cn>; Zhiguang Liu
> <zhiguang.liu@intel.com>
> 主题: [edk2-devel] [Patch V2 7/7] MdePkg/Test: Add port of BaseSafeIntLib
> unit tests to GoogleTest
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134
> 
> Cc: Liming Gao <gaoliming@byosoft.com.cn>
> Cc: Zhiguang Liu <zhiguang.liu@intel.com>
> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
> ---
>  .../GoogleTestBaseSafeIntLib.inf              |   37 +
>  .../GoogleTestBaseSafeIntLib.uni              |   13 +
>  .../SafeIntLibUintnIntnUnitTests32.cpp        |  425 +++
>  .../SafeIntLibUintnIntnUnitTests64.cpp        |  429 ++++
>  .../BaseSafeIntLib/TestBaseSafeIntLib.cpp     | 2274
> +++++++++++++++++
>  MdePkg/Test/MdePkgHostTest.dsc                |    1 +
>  6 files changed, 3179 insertions(+)
>  create mode 100644
> MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.i
> nf
>  create mode 100644
> MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.u
> ni
>  create mode 100644
> MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTest
> s32.cpp
>  create mode 100644
> MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitTest
> s64.cpp
>  create mode 100644
> MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.cpp
> 
> diff --git
> a/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib
> .inf
> b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib
> .inf
> new file mode 100644
> index 000000000000..f609bfa57f7b
> --- /dev/null
> +++
> b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib
> .inf
> @@ -0,0 +1,37 @@
> +## @file
> +# Host OS based Application that Unit Tests the SafeIntLib using Google
Test
> +#
> +# Copyright (c) 2022, Intel Corporation. All rights reserved.
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +[Defines]
> +  INF_VERSION     = 0x00010005
> +  BASE_NAME       = GoogleTestBaseSafeIntLib
> +  MODULE_UNI_FILE = GoogleTestBaseSafeIntLib.uni
> +  FILE_GUID       = 2D9C1796-B0D2-4DA7-9529-1F8D9CCC11D3
> +  MODULE_TYPE     = HOST_APPLICATION
> +  VERSION_STRING  = 1.0
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  TestBaseSafeIntLib.cpp
> +
> +[Sources.IA32]
> +  SafeIntLibUintnIntnUnitTests32.cpp
> +
> +[Sources.X64]
> +  SafeIntLibUintnIntnUnitTests64.cpp
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> +
> +[LibraryClasses]
> +  GoogleTestLib
> +  SafeIntLib
> diff --git
> a/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib
> .uni
> b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib
> .uni
> new file mode 100644
> index 000000000000..1c11b9e05205
> --- /dev/null
> +++
> b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib
> .uni
> @@ -0,0 +1,13 @@
> +// /** @file
> +// Application that Unit Tests the SafeIntLib using Google Test
> +//
> +// Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_MODULE_ABSTRACT             #language en-US
> "Application that Unit Tests the SafeIntLib using Google Test"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US
> "Application that Unit Tests the SafeIntLib using Google Test."
> +
> diff --git
> a/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitT
> ests32.cpp
> b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitT
> ests32.cpp
> new file mode 100644
> index 000000000000..6fbf302c1c5e
> --- /dev/null
> +++
> b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitT
> ests32.cpp
> @@ -0,0 +1,425 @@
> +/** @file
> +  IA32-specific functions for unit-testing INTN and UINTN functions in
> +  SafeIntLib.
> +
> +  Copyright (c) Microsoft Corporation.<BR>
> +  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <gtest/gtest.h>
> +extern "C" {
> +  #include <Base.h>
> +  #include <Library/SafeIntLib.h>
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt32ToUintn) {
> +  RETURN_STATUS  Status;
> +  INT32       Operand;
> +  UINTN       Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeInt32ToUintn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-1537977259);
> +  Status  = SafeInt32ToUintn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint32ToIntn) {
> +  RETURN_STATUS  Status;
> +  UINT32      Operand;
> +  INTN        Result;
> +
> +  //
> +  // If Operand is <= MAX_INTN, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeUint32ToIntn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabababab);
> +  Status  = SafeUint32ToIntn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToInt32) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  INT32       Result;
> +
> +  //
> +  // INTN is same as INT32 in IA32, so this is just a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeIntnToInt32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bababab, Result);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToUint32) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  UINT32      Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeIntnToUint32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT32)0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-1537977259);
> +  Status  = SafeIntnToUint32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToUint32) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  UINT32      Result;
> +
> +  //
> +  // UINTN is same as UINT32 in IA32, so this is just a cast
> +  //
> +  Operand = 0xabababab;
> +  Result  = 0;
> +  Status  = SafeUintnToUint32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabababab, Result);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToIntn) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  INTN        Result;
> +
> +  //
> +  // If Operand is <= MAX_INTN, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeUintnToIntn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabababab);
> +  Status  = SafeUintnToIntn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToInt64) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  INT64       Result;
> +
> +  //
> +  // UINTN is same as UINT32 in IA32, and UINT32 is a subset of
> +  // INT64, so this is just a cast
> +  //
> +  Operand = 0xabababab;
> +  Result  = 0;
> +  Status  = SafeUintnToInt64 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabababab, Result);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToIntn) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  INTN        Result;
> +
> +  //
> +  // If Operand is between MIN_INTN and  MAX_INTN2 inclusive, then it's
> a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeInt64ToIntn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bababab, Result);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeInt64ToIntn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-1537977259), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeInt64ToIntn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToIntn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToUintn) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  UINTN       Result;
> +
> +  //
> +  // If Operand is between 0 and  MAX_UINTN inclusive, then it's a cast
> +  //
> +  Operand = 0xabababab;
> +  Result  = 0;
> +  Status  = SafeInt64ToUintn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeInt64ToUintn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToUintn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToIntn) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  INTN        Result;
> +
> +  //
> +  // If Operand is <= MAX_INTN, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeUint64ToIntn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToIntn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToUintn) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  UINTN       Result;
> +
> +  //
> +  // If Operand is <= MAX_UINTN, then it's a cast
> +  //
> +  Operand = 0xabababab;
> +  Result  = 0;
> +  Status  = SafeUint64ToUintn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToUintn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeUintnAdd) {
> +  RETURN_STATUS  Status;
> +  UINTN       Augend;
> +  UINTN       Addend;
> +  UINTN       Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_UINTN, then it's
addition
> +  //
> +  Augend = 0x3a3a3a3a;
> +  Addend = 0x3a3a3a3a;
> +  Result = 0;
> +  Status = SafeUintnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x74747474, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0xabababab;
> +  Addend = 0xbcbcbcbc;
> +  Status = SafeUintnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeIntnAdd) {
> +  RETURN_STATUS  Status;
> +  INTN        Augend;
> +  INTN        Addend;
> +  INTN        Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_INTN
> +  // and doesn't underflow MIN_INTN, then it's addition
> +  //
> +  Augend = 0x3a3a3a3a;
> +  Addend = 0x3a3a3a3a;
> +  Result = 0;
> +  Status = SafeIntnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x74747474, Result);
> +
> +  Augend = (-976894522);
> +  Addend = (-976894522);
> +  Status = SafeIntnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-1953789044), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0x5a5a5a5a;
> +  Addend = 0x5a5a5a5a;
> +  Status = SafeIntnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Augend = (-1515870810);
> +  Addend = (-1515870810);
> +  Status = SafeIntnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeUintnSub) {
> +  RETURN_STATUS  Status;
> +  UINTN       Minuend;
> +  UINTN       Subtrahend;
> +  UINTN       Result;
> +
> +  //
> +  // If Minuend >= Subtrahend, then it's subtraction
> +  //
> +  Minuend    = 0x5a5a5a5a;
> +  Subtrahend = 0x3b3b3b3b;
> +  Result     = 0;
> +  Status     = SafeUintnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x1f1f1f1f, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = 0x5a5a5a5a;
> +  Subtrahend = 0x6d6d6d6d;
> +  Status     = SafeUintnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeIntnSub) {
> +  RETURN_STATUS  Status;
> +  INTN        Minuend;
> +  INTN        Subtrahend;
> +  INTN        Result;
> +
> +  //
> +  // If the result of subtractions doesn't overflow MAX_INTN or
> +  // underflow MIN_INTN, then it's subtraction
> +  //
> +  Minuend    = 0x5a5a5a5a;
> +  Subtrahend = 0x3a3a3a3a;
> +  Result     = 0;
> +  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x20202020, Result);
> +
> +  Minuend    = 0x3a3a3a3a;
> +  Subtrahend = 0x5a5a5a5a;
> +  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-538976288), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = (-2054847098);
> +  Subtrahend = 2054847098;
> +  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Minuend    = (2054847098);
> +  Subtrahend = (-2054847098);
> +  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeUintnMult) {
> +  RETURN_STATUS  Status;
> +  UINTN       Multiplicand;
> +  UINTN       Multiplier;
> +  UINTN       Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_UINTN, it will
> succeed
> +  //
> +  Multiplicand = 0xa122a;
> +  Multiplier   = 0xd23;
> +  Result       = 0;
> +  Status       = SafeUintnMult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x844c9dbe, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0xa122a;
> +  Multiplier   = 0xed23;
> +  Status       = SafeUintnMult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeIntnMult) {
> +  RETURN_STATUS  Status;
> +  INTN        Multiplicand;
> +  INTN        Multiplier;
> +  INTN        Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_INTN and
doesn't
> +  // underflow MIN_UINTN, it will succeed
> +  //
> +  Multiplicand = 0x123456;
> +  Multiplier   = 0x678;
> +  Result       = 0;
> +  Status       = SafeIntnMult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x75c28c50, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0x123456;
> +  Multiplier   = 0xabc;
> +  Status       = SafeIntnMult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> diff --git
> a/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitT
> ests64.cpp
> b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitT
> ests64.cpp
> new file mode 100644
> index 000000000000..6fb0710cfed6
> --- /dev/null
> +++
> b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/SafeIntLibUintnIntnUnitT
> ests64.cpp
> @@ -0,0 +1,429 @@
> +/** @file
> +  x64-specific functions for unit-testing INTN and UINTN functions in
> +  SafeIntLib.
> +
> +  Copyright (c) Microsoft Corporation.<BR>
> +  Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <gtest/gtest.h>
> +extern "C" {
> +  #include <Base.h>
> +  #include <Library/SafeIntLib.h>
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt32ToUintn) {
> +  RETURN_STATUS  Status;
> +  INT32       Operand;
> +  UINTN       Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeInt32ToUintn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-1537977259);
> +  Status  = SafeInt32ToUintn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint32ToIntn) {
> +  RETURN_STATUS  Status;
> +  UINT32      Operand;
> +  INTN        Result;
> +
> +  //
> +  // For x64, INTN is same as INT64 which is a superset of INT32
> +  // This is just a cast then, and it'll never fail
> +  //
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0xabababab;
> +  Result  = 0;
> +  Status  = SafeUint32ToIntn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabababab, Result);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToInt32) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  INT32       Result;
> +
> +  //
> +  // If Operand is between MIN_INT32 and  MAX_INT32 inclusive, then
> it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeIntnToInt32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bababab, Result);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeIntnToInt32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-1537977259), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeIntnToInt32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeIntnToInt32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToUint32) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  UINT32      Result;
> +
> +  //
> +  // If Operand is between 0 and  MAX_UINT32 inclusive, then it's a cast
> +  //
> +  Operand = 0xabababab;
> +  Result  = 0;
> +  Status  = SafeIntnToUint32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeIntnToUint32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeIntnToUint32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToUint32) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  UINT32      Result;
> +
> +  //
> +  // If Operand is <= MAX_UINT32, then it's a cast
> +  //
> +  Operand = 0xabababab;
> +  Result  = 0;
> +  Status  = SafeUintnToUint32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUintnToUint32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToIntn) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  INTN        Result;
> +
> +  //
> +  // If Operand is <= MAX_INTN (0x7fff_ffff_ffff_ffff), then it's a cast
> +  //
> +  Operand = 0x5babababefefefef;
> +  Result  = 0;
> +  Status  = SafeUintnToIntn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5babababefefefef, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUintnToIntn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToInt64) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  INT64       Result;
> +
> +  //
> +  // If Operand is <= MAX_INT64, then it's a cast
> +  //
> +  Operand = 0x5babababefefefef;
> +  Result  = 0;
> +  Status  = SafeUintnToInt64 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5babababefefefef, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUintnToInt64 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToIntn) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  INTN        Result;
> +
> +  //
> +  // INTN is same as INT64 in x64, so this is just a cast
> +  //
> +  Operand = 0x5babababefefefef;
> +  Result  = 0;
> +  Status  = SafeInt64ToIntn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5babababefefefef, Result);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToUintn) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  UINTN       Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5babababefefefef;
> +  Result  = 0;
> +  Status  = SafeInt64ToUintn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x5babababefefefef, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToUintn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToIntn) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  INTN        Result;
> +
> +  //
> +  // If Operand is <= MAX_INTN (0x7fff_ffff_ffff_ffff), then it's a cast
> +  //
> +  Operand = 0x5babababefefefef;
> +  Result  = 0;
> +  Status  = SafeUint64ToIntn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5babababefefefef, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToIntn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToUintn) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  UINTN       Result;
> +
> +  //
> +  // UINTN is same as UINT64 in x64, so this is just a cast
> +  //
> +  Operand = 0xababababefefefef;
> +  Result  = 0;
> +  Status  = SafeUint64ToUintn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xababababefefefef, Result);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeUintnAdd) {
> +  RETURN_STATUS  Status;
> +  UINTN       Augend;
> +  UINTN       Addend;
> +  UINTN       Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_UINTN, then it's
addition
> +  //
> +  Augend = 0x3a3a3a3a12121212;
> +  Addend = 0x3a3a3a3a12121212;
> +  Result = 0;
> +  Status = SafeUintnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x7474747424242424, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0xababababefefefef;
> +  Addend = 0xbcbcbcbcdededede;
> +  Status = SafeUintnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeIntnAdd) {
> +  RETURN_STATUS  Status;
> +  INTN        Augend;
> +  INTN        Addend;
> +  INTN        Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_INTN
> +  // and doesn't underflow MIN_INTN, then it's addition
> +  //
> +  Augend = 0x3a3a3a3a3a3a3a3a;
> +  Addend = 0x3a3a3a3a3a3a3a3a;
> +  Result = 0;
> +  Status = SafeIntnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x7474747474747474, Result);
> +
> +  Augend = (-4195730024608447034);
> +  Addend = (-4195730024608447034);
> +  Status = SafeIntnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-8391460049216894068), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0x5a5a5a5a5a5a5a5a;
> +  Addend = 0x5a5a5a5a5a5a5a5a;
> +  Status = SafeIntnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Augend = (-6510615555426900570);
> +  Addend = (-6510615555426900570);
> +  Status = SafeIntnAdd (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeUintnSub) {
> +  RETURN_STATUS  Status;
> +  UINTN       Minuend;
> +  UINTN       Subtrahend;
> +  UINTN       Result;
> +
> +  //
> +  // If Minuend >= Subtrahend, then it's subtraction
> +  //
> +  Minuend    = 0x5a5a5a5a5a5a5a5a;
> +  Subtrahend = 0x3b3b3b3b3b3b3b3b;
> +  Result     = 0;
> +  Status     = SafeUintnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x1f1f1f1f1f1f1f1f, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = 0x5a5a5a5a5a5a5a5a;
> +  Subtrahend = 0x6d6d6d6d6d6d6d6d;
> +  Status     = SafeUintnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeIntnSub) {
> +  RETURN_STATUS  Status;
> +  INTN        Minuend;
> +  INTN        Subtrahend;
> +  INTN        Result;
> +
> +  //
> +  // If the result of subtractions doesn't overflow MAX_INTN or
> +  // underflow MIN_INTN, then it's subtraction
> +  //
> +  Minuend    = 0x5a5a5a5a5a5a5a5a;
> +  Subtrahend = 0x3a3a3a3a3a3a3a3a;
> +  Result     = 0;
> +  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x2020202020202020, Result);
> +
> +  Minuend    = 0x3a3a3a3a3a3a3a3a;
> +  Subtrahend = 0x5a5a5a5a5a5a5a5a;
> +  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-2314885530818453536), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = (-8825501086245354106);
> +  Subtrahend = 8825501086245354106;
> +  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Minuend    = (8825501086245354106);
> +  Subtrahend = (-8825501086245354106);
> +  Status     = SafeIntnSub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeUintnMult) {
> +  RETURN_STATUS  Status;
> +  UINTN       Multiplicand;
> +  UINTN       Multiplier;
> +  UINTN       Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_UINTN, it will
> succeed
> +  //
> +  Multiplicand = 0x123456789a;
> +  Multiplier   = 0x1234567;
> +  Result       = 0;
> +  Status       = SafeUintnMult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x14b66db9745a07f6, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0x123456789a;
> +  Multiplier   = 0x12345678;
> +  Status       = SafeUintnMult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeIntnMult) {
> +  RETURN_STATUS  Status;
> +  INTN        Multiplicand;
> +  INTN        Multiplier;
> +  INTN        Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_INTN and
doesn't
> +  // underflow MIN_UINTN, it will succeed
> +  //
> +  Multiplicand = 0x123456789;
> +  Multiplier   = 0x6789abcd;
> +  Result       = 0;
> +  Status       = SafeIntnMult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x75cd9045220d6bb5, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0x123456789;
> +  Multiplier   = 0xa789abcd;
> +  Status       = SafeIntnMult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> diff --git
> a/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.cpp
> b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.cpp
> new file mode 100644
> index 000000000000..1fd51067a1f3
> --- /dev/null
> +++
> b/MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/TestBaseSafeIntLib.cpp
> @@ -0,0 +1,2274 @@
> +/** @file
> +  UEFI OS based application for unit testing the SafeIntLib.
> +
> +  Copyright (c) Microsoft Corporation.<BR>
> +  Copyright (c) 2018 - 2022, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#include <gtest/gtest.h>
> +extern "C" {
> +  #include <Base.h>
> +  #include <Library/SafeIntLib.h>
> +}
> +
> +//
> +// Conversion function tests:
> +//
> +TEST(ConversionTestSuite, TestSafeInt8ToUint8) {
> +  RETURN_STATUS  Status;
> +  INT8        Operand;
> +  UINT8       Result;
> +
> +  //
> +  // Positive UINT8 should result in just a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt8ToUint8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Negative number should result in an error status
> +  //
> +  Operand = (-56);
> +  Status  = SafeInt8ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt8ToUint16) {
> +  RETURN_STATUS  Status;
> +  INT8        Operand;
> +  UINT16      Result;
> +
> +  //
> +  // Positive UINT8 should result in just a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt8ToUint16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Negative number should result in an error status
> +  //
> +  Operand = (-56);
> +  Status  = SafeInt8ToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt8ToUint32) {
> +  RETURN_STATUS  Status;
> +  INT8        Operand;
> +  UINT32      Result;
> +
> +  //
> +  // Positive UINT8 should result in just a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt8ToUint32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT32)0x5b, Result);
> +
> +  //
> +  // Negative number should result in an error status
> +  //
> +  Operand = (-56);
> +  Status  = SafeInt8ToUint32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt8ToUintn) {
> +  RETURN_STATUS  Status;
> +  INT8        Operand;
> +  UINTN       Result;
> +
> +  //
> +  // Positive UINT8 should result in just a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt8ToUintn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x5b, Result);
> +
> +  //
> +  // Negative number should result in an error status
> +  //
> +  Operand = (-56);
> +  Status  = SafeInt8ToUintn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt8ToUint64) {
> +  RETURN_STATUS  Status;
> +  INT8        Operand;
> +  UINT64      Result;
> +
> +  //
> +  // Positive UINT8 should result in just a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt8ToUint64 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT64)0x5b, Result);
> +
> +  //
> +  // Negative number should result in an error status
> +  //
> +  Operand = (-56);
> +  Status  = SafeInt8ToUint64 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint8ToInt8) {
> +  RETURN_STATUS  Status;
> +  UINT8       Operand;
> +  INT8        Result;
> +
> +  //
> +  // Operand <= 0x7F (MAX_INT8) should result in a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeUint8ToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Operand larger than 0x7f should result in an error status
> +  //
> +  Operand = 0xaf;
> +  Status  = SafeUint8ToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint8ToChar8) {
> +  RETURN_STATUS  Status;
> +  UINT8       Operand;
> +  CHAR8       Result;
> +
> +  //
> +  // CHAR8 is typedefed as char, which by default is signed, thus
> +  // CHAR8 is same as INT8, so same tests as above:
> +  //
> +
> +  //
> +  // Operand <= 0x7F (MAX_INT8) should result in a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeUint8ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Operand larger than 0x7f should result in an error status
> +  //
> +  Operand = 0xaf;
> +  Status  = SafeUint8ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt16ToInt8) {
> +  RETURN_STATUS  Status;
> +  INT16       Operand;
> +  INT8        Result;
> +
> +  //
> +  // If Operand is between MIN_INT8 and MAX_INT8 inclusive, then it's a
> cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt16ToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  Operand = (-35);
> +  Status  = SafeInt16ToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-35), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = 0x1234;
> +  Status  = SafeInt16ToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-17835);
> +  Status  = SafeInt16ToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt16ToChar8) {
> +  RETURN_STATUS  Status;
> +  INT16       Operand;
> +  CHAR8       Result;
> +
> +  //
> +  // CHAR8 is typedefed as char, which may be signed or unsigned based
> +  // on the compiler. Thus, for compatibility CHAR8 should be between 0
and
> MAX_INT8.
> +  //
> +
> +  //
> +  // If Operand is between 0 and MAX_INT8 inclusive, then it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt16ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  Operand = 0;
> +  Result  = 0;
> +  Status  = SafeInt16ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0, Result);
> +
> +  Operand = MAX_INT8;
> +  Result  = 0;
> +  Status  = SafeInt16ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (MAX_INT8, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-35);
> +  Status  = SafeInt16ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = 0x1234;
> +  Status  = SafeInt16ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-17835);
> +  Status  = SafeInt16ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt16ToUint8) {
> +  RETURN_STATUS  Status;
> +  INT16       Operand;
> +  UINT8       Result;
> +
> +  //
> +  // If Operand is between 0 and MAX_INT8 inclusive, then it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt16ToUint8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = 0x1234;
> +  Status  = SafeInt16ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-17835);
> +  Status  = SafeInt16ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt16ToUint16) {
> +  RETURN_STATUS  Status;
> +  INT16       Operand = 0x5b5b;
> +  UINT16      Result  = 0;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Status = SafeInt16ToUint16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-17835);
> +  Status  = SafeInt16ToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt16ToUint32) {
> +  RETURN_STATUS  Status;
> +  INT16       Operand;
> +  UINT32      Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5b5b;
> +  Result  = 0;
> +  Status  = SafeInt16ToUint32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT32)0x5b5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-17835);
> +  Status  = SafeInt16ToUint32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt16ToUintn) {
> +  RETURN_STATUS  Status;
> +  INT16       Operand;
> +  UINTN       Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5b5b;
> +  Result  = 0;
> +  Status  = SafeInt16ToUintn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x5b5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-17835);
> +  Status  = SafeInt16ToUintn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt16ToUint64) {
> +  RETURN_STATUS  Status;
> +  INT16       Operand;
> +  UINT64      Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5b5b;
> +  Result  = 0;
> +  Status  = SafeInt16ToUint64 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT64)0x5b5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-17835);
> +  Status  = SafeInt16ToUint64 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint16ToInt8) {
> +  RETURN_STATUS  Status;
> +  UINT16      Operand;
> +  INT8        Result;
> +
> +  //
> +  // If Operand is <= MAX_INT8, it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeUint16ToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5b5b);
> +  Status  = SafeUint16ToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint16ToChar8) {
> +  RETURN_STATUS  Status;
> +  UINT16      Operand;
> +  CHAR8       Result;
> +
> +  // CHAR8 is typedefed as char, which by default is signed, thus
> +  // CHAR8 is same as INT8, so same tests as above:
> +
> +  //
> +  // If Operand is <= MAX_INT8, it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeUint16ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5b5b);
> +  Status  = SafeUint16ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint16ToUint8) {
> +  RETURN_STATUS  Status;
> +  UINT16      Operand;
> +  UINT8       Result;
> +
> +  //
> +  // If Operand is <= MAX_UINT8 (0xff), it's a cast
> +  //
> +  Operand = 0xab;
> +  Result  = 0;
> +  Status  = SafeUint16ToUint8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5b5b);
> +  Status  = SafeUint16ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint16ToInt16) {
> +  RETURN_STATUS  Status;
> +  UINT16      Operand;
> +  INT16       Result;
> +
> +  //
> +  // If Operand is <= MAX_INT16 (0x7fff), it's a cast
> +  //
> +  Operand = 0x5b5b;
> +  Result  = 0;
> +  Status  = SafeUint16ToInt16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabab);
> +  Status  = SafeUint16ToInt16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt32ToInt8) {
> +  RETURN_STATUS  Status;
> +  INT32       Operand;
> +  INT8        Result;
> +
> +  //
> +  // If Operand is between MIN_INT8 and MAX_INT8 inclusive, then it's a
> cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt32ToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  Operand = (-57);
> +  Status  = SafeInt32ToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-57), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5bababab);
> +  Status  = SafeInt32ToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeInt32ToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt32ToChar8) {
> +  RETURN_STATUS  Status;
> +  INT32       Operand;
> +  CHAR8       Result;
> +
> +  //
> +  // CHAR8 is typedefed as char, which may be signed or unsigned based
> +  // on the compiler. Thus, for compatibility CHAR8 should be between 0
and
> MAX_INT8.
> +  //
> +
> +  //
> +  // If Operand is between 0 and MAX_INT8 inclusive, then it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt32ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  Operand = 0;
> +  Result  = 0;
> +  Status  = SafeInt32ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0, Result);
> +
> +  Operand = MAX_INT8;
> +  Result  = 0;
> +  Status  = SafeInt32ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (MAX_INT8, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-57);
> +  Status  = SafeInt32ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (0x5bababab);
> +  Status  = SafeInt32ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeInt32ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt32ToUint8) {
> +  RETURN_STATUS  Status;
> +  INT32       Operand;
> +  UINT8       Result;
> +
> +  //
> +  // If Operand is between 0 and MAX_INT8 inclusive, then it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt32ToUint8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-57);
> +  Status  = SafeInt32ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (0x5bababab);
> +  Status  = SafeInt32ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeInt32ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt32ToInt16) {
> +  RETURN_STATUS  Status;
> +  INT32       Operand;
> +  INT16       Result;
> +
> +  //
> +  // If Operand is between MIN_INT16 and MAX_INT16 inclusive, then it's a
> cast
> +  //
> +  Operand = 0x5b5b;
> +  Result  = 0;
> +  Status  = SafeInt32ToInt16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b5b, Result);
> +
> +  Operand = (-17857);
> +  Status  = SafeInt32ToInt16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-17857), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5bababab);
> +  Status  = SafeInt32ToInt16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeInt32ToInt16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt32ToUint16) {
> +  RETURN_STATUS  Status;
> +  INT32       Operand;
> +  UINT16      Result;
> +
> +  //
> +  // If Operand is between 0 and MAX_UINT16 inclusive, then it's a cast
> +  //
> +  Operand = 0xabab;
> +  Result  = 0;
> +  Status  = SafeInt32ToUint16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-17857);
> +  Status  = SafeInt32ToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (0x5bababab);
> +  Status  = SafeInt32ToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeInt32ToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt32ToUint32) {
> +  RETURN_STATUS  Status;
> +  INT32       Operand;
> +  UINT32      Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeInt32ToUint32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT32)0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-1537977259);
> +  Status  = SafeInt32ToUint32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt32ToUint64) {
> +  RETURN_STATUS  Status;
> +  INT32       Operand;
> +  UINT64      Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeInt32ToUint64 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT64)0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-1537977259);
> +  Status  = SafeInt32ToUint64 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint32ToInt8) {
> +  RETURN_STATUS  Status;
> +  UINT32      Operand;
> +  INT8        Result;
> +
> +  //
> +  // If Operand is <= MAX_INT8, then it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeUint32ToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5bababab);
> +  Status  = SafeUint32ToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint32ToChar8) {
> +  RETURN_STATUS  Status;
> +  UINT32      Operand;
> +  CHAR8       Result;
> +
> +  // CHAR8 is typedefed as char, which by default is signed, thus
> +  // CHAR8 is same as INT8, so same tests as above:
> +
> +  //
> +  // If Operand is <= MAX_INT8, then it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeUint32ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5bababab);
> +  Status  = SafeUint32ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint32ToUint8) {
> +  RETURN_STATUS  Status;
> +  UINT32      Operand;
> +  UINT8       Result;
> +
> +  //
> +  // If Operand is <= MAX_UINT8, then it's a cast
> +  //
> +  Operand = 0xab;
> +  Result  = 0;
> +  Status  = SafeUint32ToUint8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabababab);
> +  Status  = SafeUint32ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint32ToInt16) {
> +  RETURN_STATUS  Status;
> +  UINT32      Operand;
> +  INT16       Result;
> +
> +  //
> +  // If Operand is <= MAX_INT16, then it's a cast
> +  //
> +  Operand = 0x5bab;
> +  Result  = 0;
> +  Status  = SafeUint32ToInt16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabababab);
> +  Status  = SafeUint32ToInt16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint32ToUint16) {
> +  RETURN_STATUS  Status;
> +  UINT32      Operand;
> +  UINT16      Result;
> +
> +  //
> +  // If Operand is <= MAX_UINT16, then it's a cast
> +  //
> +  Operand = 0xabab;
> +  Result  = 0;
> +  Status  = SafeUint32ToUint16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabababab);
> +  Status  = SafeUint32ToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint32ToInt32) {
> +  RETURN_STATUS  Status;
> +  UINT32      Operand;
> +  INT32       Result;
> +
> +  //
> +  // If Operand is <= MAX_INT32, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeUint32ToInt32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabababab);
> +  Status  = SafeUint32ToInt32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToInt8) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  INT8        Result;
> +
> +  //
> +  // If Operand is between MIN_INT8 and MAX_INT8 inclusive, then it's a
> cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeIntnToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  Operand = (-53);
> +  Status  = SafeIntnToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-53), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5bababab);
> +  Status  = SafeIntnToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeIntnToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToChar8) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  CHAR8       Result;
> +
> +  //
> +  // CHAR8 is typedefed as char, which may be signed or unsigned based
> +  // on the compiler. Thus, for compatibility CHAR8 should be between 0
and
> MAX_INT8.
> +  //
> +
> +  //
> +  // If Operand is between MIN_INT8 and MAX_INT8 inclusive, then it's a
> cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeIntnToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  Operand = 0;
> +  Result  = 0;
> +  Status  = SafeIntnToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0, Result);
> +
> +  Operand = MAX_INT8;
> +  Result  = 0;
> +  Status  = SafeIntnToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (MAX_INT8, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-53);
> +  Status  = SafeIntnToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (0x5bababab);
> +  Status  = SafeIntnToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeIntnToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToUint8) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  UINT8       Result;
> +
> +  //
> +  // If Operand is between 0 and MAX_UINT8 inclusive, then it's a cast
> +  //
> +  Operand = 0xab;
> +  Result  = 0;
> +  Status  = SafeIntnToUint8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5bababab);
> +  Status  = SafeIntnToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeIntnToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToInt16) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  INT16       Result;
> +
> +  //
> +  // If Operand is between MIN_INT16 and MAX_INT16 inclusive, then it's a
> cast
> +  //
> +  Operand = 0x5bab;
> +  Result  = 0;
> +  Status  = SafeIntnToInt16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bab, Result);
> +
> +  Operand = (-23467);
> +  Status  = SafeIntnToInt16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-23467), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5bababab);
> +  Status  = SafeIntnToInt16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeIntnToInt16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToUint16) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  UINT16      Result;
> +
> +  //
> +  // If Operand is between 0 and MAX_UINT16 inclusive, then it's a cast
> +  //
> +  Operand = 0xabab;
> +  Result  = 0;
> +  Status  = SafeIntnToUint16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5bababab);
> +  Status  = SafeIntnToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeIntnToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToUintn) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  UINTN       Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeIntnToUintn (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINTN)0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-1537977259);
> +  Status  = SafeIntnToUintn (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeIntnToUint64) {
> +  RETURN_STATUS  Status;
> +  INTN        Operand;
> +  UINT64      Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeIntnToUint64 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT64)0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-1537977259);
> +  Status  = SafeIntnToUint64 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToInt8) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  INT8        Result;
> +
> +  //
> +  // If Operand is <= MAX_INT8, then it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeUintnToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabab);
> +  Status  = SafeUintnToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToChar8) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  CHAR8       Result;
> +
> +  // CHAR8 is typedefed as char, which by default is signed, thus
> +  // CHAR8 is same as INT8, so same tests as above:
> +
> +  //
> +  // If Operand is <= MAX_INT8, then it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeUintnToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabab);
> +  Status  = SafeUintnToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToUint8) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  UINT8       Result;
> +
> +  //
> +  // If Operand is <= MAX_UINT8, then it's a cast
> +  //
> +  Operand = 0xab;
> +  Result  = 0;
> +  Status  = SafeUintnToUint8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabab);
> +  Status  = SafeUintnToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToInt16) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  INT16       Result;
> +
> +  //
> +  // If Operand is <= MAX_INT16, then it's a cast
> +  //
> +  Operand = 0x5bab;
> +  Result  = 0;
> +  Status  = SafeUintnToInt16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabab);
> +  Status  = SafeUintnToInt16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToUint16) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  UINT16      Result;
> +
> +  //
> +  // If Operand is <= MAX_UINT16, then it's a cast
> +  //
> +  Operand = 0xabab;
> +  Result  = 0;
> +  Status  = SafeUintnToUint16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabababab);
> +  Status  = SafeUintnToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUintnToInt32) {
> +  RETURN_STATUS  Status;
> +  UINTN       Operand;
> +  INT32       Result;
> +
> +  //
> +  // If Operand is <= MAX_INT32, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeUintnToInt32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xabababab);
> +  Status  = SafeUintnToInt32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToInt8) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  INT8        Result;
> +
> +  //
> +  // If Operand is between MIN_INT8 and  MAX_INT8 inclusive, then it's a
> cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt64ToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  Operand = (-37);
> +  Status  = SafeInt64ToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-37), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeInt64ToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToChar8) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  CHAR8       Result;
> +
> +  //
> +  // CHAR8 is typedefed as char, which may be signed or unsigned based
> +  // on the compiler. Thus, for compatibility CHAR8 should be between 0
and
> MAX_INT8.
> +  //
> +
> +  //
> +  // If Operand is between MIN_INT8 and  MAX_INT8 inclusive, then it's a
> cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeInt64ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  Operand = 0;
> +  Result  = 0;
> +  Status  = SafeInt64ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0, Result);
> +
> +  Operand = MAX_INT8;
> +  Result  = 0;
> +  Status  = SafeInt64ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (MAX_INT8, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (-37);
> +  Status  = SafeInt64ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeInt64ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToUint8) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  UINT8       Result;
> +
> +  //
> +  // If Operand is between 0 and  MAX_UINT8 inclusive, then it's a cast
> +  //
> +  Operand = 0xab;
> +  Result  = 0;
> +  Status  = SafeInt64ToUint8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeInt64ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToInt16) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  INT16       Result;
> +
> +  //
> +  // If Operand is between MIN_INT16 and  MAX_INT16 inclusive, then
> it's a cast
> +  //
> +  Operand = 0x5bab;
> +  Result  = 0;
> +  Status  = SafeInt64ToInt16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bab, Result);
> +
> +  Operand = (-23467);
> +  Status  = SafeInt64ToInt16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-23467), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeInt64ToInt16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToInt16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToUint16) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  UINT16      Result;
> +
> +  //
> +  // If Operand is between 0 and  MAX_UINT16 inclusive, then it's a cast
> +  //
> +  Operand = 0xabab;
> +  Result  = 0;
> +  Status  = SafeInt64ToUint16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeInt64ToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToInt32) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  INT32       Result;
> +
> +  //
> +  // If Operand is between MIN_INT32 and  MAX_INT32 inclusive, then
> it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeInt64ToInt32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bababab, Result);
> +
> +  Operand = (-1537977259);
> +  Status  = SafeInt64ToInt32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-1537977259), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeInt64ToInt32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToInt32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToUint32) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  UINT32      Result;
> +
> +  //
> +  // If Operand is between 0 and  MAX_UINT32 inclusive, then it's a cast
> +  //
> +  Operand = 0xabababab;
> +  Result  = 0;
> +  Status  = SafeInt64ToUint32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0x5babababefefefef);
> +  Status  = SafeInt64ToUint32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToUint32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeInt64ToUint64) {
> +  RETURN_STATUS  Status;
> +  INT64       Operand;
> +  UINT64      Result;
> +
> +  //
> +  // If Operand is non-negative, then it's a cast
> +  //
> +  Operand = 0x5babababefefefef;
> +  Result  = 0;
> +  Status  = SafeInt64ToUint64 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT64)0x5babababefefefef, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand =  (-6605562033422200815);
> +  Status  = SafeInt64ToUint64 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToInt8) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  INT8        Result;
> +
> +  //
> +  // If Operand is <= MAX_INT8, then it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeUint64ToInt8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToInt8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToChar8) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  CHAR8       Result;
> +
> +  // CHAR8 is typedefed as char, which by default is signed, thus
> +  // CHAR8 is same as INT8, so same tests as above:
> +
> +  //
> +  // If Operand is <= MAX_INT8, then it's a cast
> +  //
> +  Operand = 0x5b;
> +  Result  = 0;
> +  Status  = SafeUint64ToChar8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5b, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToChar8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToUint8) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  UINT8       Result;
> +
> +  //
> +  // If Operand is <= MAX_UINT8, then it's a cast
> +  //
> +  Operand = 0xab;
> +  Result  = 0;
> +  Status  = SafeUint64ToUint8 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToUint8 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToInt16) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  INT16       Result;
> +
> +  //
> +  // If Operand is <= MAX_INT16, then it's a cast
> +  //
> +  Operand = 0x5bab;
> +  Result  = 0;
> +  Status  = SafeUint64ToInt16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToInt16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToUint16) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  UINT16      Result;
> +
> +  //
> +  // If Operand is <= MAX_UINT16, then it's a cast
> +  //
> +  Operand = 0xabab;
> +  Result  = 0;
> +  Status  = SafeUint64ToUint16 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToUint16 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToInt32) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  INT32       Result;
> +
> +  //
> +  // If Operand is <= MAX_INT32, then it's a cast
> +  //
> +  Operand = 0x5bababab;
> +  Result  = 0;
> +  Status  = SafeUint64ToInt32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5bababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToInt32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToUint32) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  UINT32      Result;
> +
> +  //
> +  // If Operand is <= MAX_UINT32, then it's a cast
> +  //
> +  Operand = 0xabababab;
> +  Result  = 0;
> +  Status  = SafeUint64ToUint32 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xabababab, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToUint32 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(ConversionTestSuite, TestSafeUint64ToInt64) {
> +  RETURN_STATUS  Status;
> +  UINT64      Operand;
> +  INT64       Result;
> +
> +  //
> +  // If Operand is <= MAX_INT64, then it's a cast
> +  //
> +  Operand = 0x5babababefefefef;
> +  Result  = 0;
> +  Status  = SafeUint64ToInt64 (Operand, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x5babababefefefef, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Operand = (0xababababefefefef);
> +  Status  = SafeUint64ToInt64 (Operand, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +//
> +// Addition function tests:
> +//
> +TEST(AdditionSubtractionTestSuite, TestSafeUint8Add) {
> +  RETURN_STATUS  Status;
> +  UINT8       Augend;
> +  UINT8       Addend;
> +  UINT8       Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_UINT8, then it's
addition
> +  //
> +  Augend = 0x3a;
> +  Addend = 0x3a;
> +  Result = 0;
> +  Status = SafeUint8Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x74, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0xab;
> +  Addend = 0xbc;
> +  Status = SafeUint8Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeUint16Add) {
> +  RETURN_STATUS  Status;
> +  UINT16      Augend = 0x3a3a;
> +  UINT16      Addend = 0x3a3a;
> +  UINT16      Result = 0;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_UINT16, then it's
> addition
> +  //
> +  Status = SafeUint16Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x7474, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0xabab;
> +  Addend = 0xbcbc;
> +  Status = SafeUint16Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeUint32Add) {
> +  RETURN_STATUS  Status;
> +  UINT32      Augend;
> +  UINT32      Addend;
> +  UINT32      Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_UINT32, then it's
> addition
> +  //
> +  Augend = 0x3a3a3a3a;
> +  Addend = 0x3a3a3a3a;
> +  Result = 0;
> +  Status = SafeUint32Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT32)0x74747474, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0xabababab;
> +  Addend = 0xbcbcbcbc;
> +  Status = SafeUint32Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeUint64Add) {
> +  RETURN_STATUS  Status;
> +  UINT64      Augend;
> +  UINT64      Addend;
> +  UINT64      Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_UINT64, then it's
> addition
> +  //
> +  Augend = 0x3a3a3a3a12121212;
> +  Addend = 0x3a3a3a3a12121212;
> +  Result = 0;
> +  Status = SafeUint64Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT64)0x7474747424242424, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0xababababefefefef;
> +  Addend = 0xbcbcbcbcdededede;
> +  Status = SafeUint64Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeInt8Add) {
> +  RETURN_STATUS  Status;
> +  INT8        Augend;
> +  INT8        Addend;
> +  INT8        Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_INT8
> +  // and doesn't underflow MIN_INT8, then it's addition
> +  //
> +  Augend = 0x3a;
> +  Addend = 0x3a;
> +  Result = 0;
> +  Status = SafeInt8Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x74, Result);
> +
> +  Augend = (-58);
> +  Addend = (-58);
> +  Status = SafeInt8Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-116), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0x5a;
> +  Addend = 0x5a;
> +  Status = SafeInt8Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Augend = (-90);
> +  Addend = (-90);
> +  Status = SafeInt8Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeInt16Add) {
> +  RETURN_STATUS  Status;
> +  INT16       Augend;
> +  INT16       Addend;
> +  INT16       Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_INT16
> +  // and doesn't underflow MIN_INT16, then it's addition
> +  //
> +  Augend = 0x3a3a;
> +  Addend = 0x3a3a;
> +  Result = 0;
> +  Status = SafeInt16Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x7474, Result);
> +
> +  Augend = (-14906);
> +  Addend = (-14906);
> +  Status = SafeInt16Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-29812), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0x5a5a;
> +  Addend = 0x5a5a;
> +  Status = SafeInt16Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Augend = (-23130);
> +  Addend = (-23130);
> +  Status = SafeInt16Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeInt32Add) {
> +  RETURN_STATUS  Status;
> +  INT32       Augend;
> +  INT32       Addend;
> +  INT32       Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_INT32
> +  // and doesn't underflow MIN_INT32, then it's addition
> +  //
> +  Augend = 0x3a3a3a3a;
> +  Addend = 0x3a3a3a3a;
> +  Result = 0;
> +  Status = SafeInt32Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x74747474, Result);
> +
> +  Augend = (-976894522);
> +  Addend = (-976894522);
> +  Status = SafeInt32Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-1953789044), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0x5a5a5a5a;
> +  Addend = 0x5a5a5a5a;
> +  Status = SafeInt32Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Augend = (-1515870810);
> +  Addend = (-1515870810);
> +  Status = SafeInt32Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeInt64Add) {
> +  RETURN_STATUS  Status;
> +  INT64       Augend;
> +  INT64       Addend;
> +  INT64       Result;
> +
> +  //
> +  // If the result of addition doesn't overflow MAX_INT64
> +  // and doesn't underflow MIN_INT64, then it's addition
> +  //
> +  Augend = 0x3a3a3a3a3a3a3a3a;
> +  Addend = 0x3a3a3a3a3a3a3a3a;
> +  Result = 0;
> +  Status = SafeInt64Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x7474747474747474, Result);
> +
> +  Augend = (-4195730024608447034);
> +  Addend = (-4195730024608447034);
> +  Status = SafeInt64Add (Augend, Addend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-8391460049216894068), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Augend = 0x5a5a5a5a5a5a5a5a;
> +  Addend = 0x5a5a5a5a5a5a5a5a;
> +  Status = SafeInt64Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Augend = (-6510615555426900570);
> +  Addend = (-6510615555426900570);
> +  Status = SafeInt64Add (Augend, Addend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +//
> +// Subtraction function tests:
> +//
> +TEST(AdditionSubtractionTestSuite, TestSafeUint8Sub) {
> +  RETURN_STATUS  Status;
> +  UINT8       Minuend;
> +  UINT8       Subtrahend;
> +  UINT8       Result;
> +
> +  //
> +  // If Minuend >= Subtrahend, then it's subtraction
> +  //
> +  Minuend    = 0x5a;
> +  Subtrahend = 0x3b;
> +  Result     = 0;
> +  Status     = SafeUint8Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x1f, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = 0x5a;
> +  Subtrahend = 0x6d;
> +  Status     = SafeUint8Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeUint16Sub) {
> +  RETURN_STATUS  Status;
> +  UINT16      Minuend;
> +  UINT16      Subtrahend;
> +  UINT16      Result;
> +
> +  //
> +  // If Minuend >= Subtrahend, then it's subtraction
> +  //
> +  Minuend    = 0x5a5a;
> +  Subtrahend = 0x3b3b;
> +  Result     = 0;
> +  Status     = SafeUint16Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x1f1f, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = 0x5a5a;
> +  Subtrahend = 0x6d6d;
> +  Status     = SafeUint16Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeUint32Sub) {
> +  RETURN_STATUS  Status;
> +  UINT32      Minuend;
> +  UINT32      Subtrahend;
> +  UINT32      Result;
> +
> +  //
> +  // If Minuend >= Subtrahend, then it's subtraction
> +  //
> +  Minuend    = 0x5a5a5a5a;
> +  Subtrahend = 0x3b3b3b3b;
> +  Result     = 0;
> +  Status     = SafeUint32Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT32)0x1f1f1f1f, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = 0x5a5a5a5a;
> +  Subtrahend = 0x6d6d6d6d;
> +  Status     = SafeUint32Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeUint64Sub) {
> +  RETURN_STATUS  Status;
> +  UINT64      Minuend;
> +  UINT64      Subtrahend;
> +  UINT64      Result;
> +
> +  //
> +  // If Minuend >= Subtrahend, then it's subtraction
> +  //
> +  Minuend    = 0x5a5a5a5a5a5a5a5a;
> +  Subtrahend = 0x3b3b3b3b3b3b3b3b;
> +  Result     = 0;
> +  Status     = SafeUint64Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT64)0x1f1f1f1f1f1f1f1f, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = 0x5a5a5a5a5a5a5a5a;
> +  Subtrahend = 0x6d6d6d6d6d6d6d6d;
> +  Status     = SafeUint64Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeInt8Sub) {
> +  RETURN_STATUS  Status;
> +  INT8        Minuend;
> +  INT8        Subtrahend;
> +  INT8        Result;
> +
> +  //
> +  // If the result of subtractions doesn't overflow MAX_INT8 or
> +  // underflow MIN_INT8, then it's subtraction
> +  //
> +  Minuend    = 0x5a;
> +  Subtrahend = 0x3a;
> +  Result     = 0;
> +  Status     = SafeInt8Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x20, Result);
> +
> +  Minuend    = 58;
> +  Subtrahend = 78;
> +  Status     = SafeInt8Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-20), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = (-80);
> +  Subtrahend = 80;
> +  Status     = SafeInt8Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Minuend    = (80);
> +  Subtrahend = (-80);
> +  Status     = SafeInt8Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeInt16Sub) {
> +  RETURN_STATUS  Status;
> +  INT16       Minuend;
> +  INT16       Subtrahend;
> +  INT16       Result;
> +
> +  //
> +  // If the result of subtractions doesn't overflow MAX_INT16 or
> +  // underflow MIN_INT16, then it's subtraction
> +  //
> +  Minuend    = 0x5a5a;
> +  Subtrahend = 0x3a3a;
> +  Result     = 0;
> +  Status     = SafeInt16Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x2020, Result);
> +
> +  Minuend    = 0x3a3a;
> +  Subtrahend = 0x5a5a;
> +  Status     = SafeInt16Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-8224), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = (-31354);
> +  Subtrahend = 31354;
> +  Status     = SafeInt16Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Minuend    = (31354);
> +  Subtrahend = (-31354);
> +  Status     = SafeInt16Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeInt32Sub) {
> +  RETURN_STATUS  Status;
> +  INT32       Minuend;
> +  INT32       Subtrahend;
> +  INT32       Result;
> +
> +  //
> +  // If the result of subtractions doesn't overflow MAX_INT32 or
> +  // underflow MIN_INT32, then it's subtraction
> +  //
> +  Minuend    = 0x5a5a5a5a;
> +  Subtrahend = 0x3a3a3a3a;
> +  Result     = 0;
> +  Status     = SafeInt32Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x20202020, Result);
> +
> +  Minuend    = 0x3a3a3a3a;
> +  Subtrahend = 0x5a5a5a5a;
> +  Status     = SafeInt32Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-538976288), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = (-2054847098);
> +  Subtrahend = 2054847098;
> +  Status     = SafeInt32Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Minuend    = (2054847098);
> +  Subtrahend = (-2054847098);
> +  Status     = SafeInt32Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(AdditionSubtractionTestSuite, TestSafeInt64Sub) {
> +  RETURN_STATUS  Status;
> +  INT64       Minuend;
> +  INT64       Subtrahend;
> +  INT64       Result;
> +
> +  //
> +  // If the result of subtractions doesn't overflow MAX_INT64 or
> +  // underflow MIN_INT64, then it's subtraction
> +  //
> +  Minuend    = 0x5a5a5a5a5a5a5a5a;
> +  Subtrahend = 0x3a3a3a3a3a3a3a3a;
> +  Result     = 0;
> +  Status     = SafeInt64Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x2020202020202020, Result);
> +
> +  Minuend    = 0x3a3a3a3a3a3a3a3a;
> +  Subtrahend = 0x5a5a5a5a5a5a5a5a;
> +  Status     = SafeInt64Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((-2314885530818453536), Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Minuend    = (-8825501086245354106);
> +  Subtrahend = 8825501086245354106;
> +  Status     = SafeInt64Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +
> +  Minuend    = (8825501086245354106);
> +  Subtrahend = (-8825501086245354106);
> +  Status     = SafeInt64Sub (Minuend, Subtrahend, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +//
> +// Multiplication function tests:
> +//
> +TEST(MultiplicationTestSuite, TestSafeUint8Mult) {
> +  RETURN_STATUS  Status;
> +  UINT8       Multiplicand;
> +  UINT8       Multiplier;
> +  UINT8       Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_UINT8, it will
> succeed
> +  //
> +  Multiplicand = 0x12;
> +  Multiplier   = 0xa;
> +  Result       = 0;
> +  Status       = SafeUint8Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xb4, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0x12;
> +  Multiplier   = 0x23;
> +  Status       = SafeUint8Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeUint16Mult) {
> +  RETURN_STATUS  Status;
> +  UINT16      Multiplicand;
> +  UINT16      Multiplier;
> +  UINT16      Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_UINT16, it will
> succeed
> +  //
> +  Multiplicand = 0x212;
> +  Multiplier   = 0x7a;
> +  Result       = 0;
> +  Status       = SafeUint16Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0xfc94, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0x1234;
> +  Multiplier   = 0x213;
> +  Status       = SafeUint16Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeUint32Mult) {
> +  RETURN_STATUS  Status;
> +  UINT32      Multiplicand;
> +  UINT32      Multiplier;
> +  UINT32      Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_UINT32, it will
> succeed
> +  //
> +  Multiplicand = 0xa122a;
> +  Multiplier   = 0xd23;
> +  Result       = 0;
> +  Status       = SafeUint32Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x844c9dbe, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0xa122a;
> +  Multiplier   = 0xed23;
> +  Status       = SafeUint32Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeUint64Mult) {
> +  RETURN_STATUS  Status;
> +  UINT64      Multiplicand;
> +  UINT64      Multiplier;
> +  UINT64      Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_UINT64, it will
> succeed
> +  //
> +  Multiplicand = 0x123456789a;
> +  Multiplier   = 0x1234567;
> +  Result       = 0;
> +  Status       = SafeUint64Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ ((UINT64)0x14b66db9745a07f6, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0x123456789a;
> +  Multiplier   = 0x12345678;
> +  Status       = SafeUint64Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeInt8Mult) {
> +  RETURN_STATUS  Status;
> +  INT8        Multiplicand;
> +  INT8        Multiplier;
> +  INT8        Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_INT8 and
doesn't
> +  // underflow MIN_UINT8, it will succeed
> +  //
> +  Multiplicand = 0x12;
> +  Multiplier   = 0x7;
> +  Result       = 0;
> +  Status       = SafeInt8Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x7e, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0x12;
> +  Multiplier   = 0xa;
> +  Status       = SafeInt8Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeInt16Mult) {
> +  RETURN_STATUS  Status;
> +  INT16       Multiplicand;
> +  INT16       Multiplier;
> +  INT16       Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_INT16 and
doesn't
> +  // underflow MIN_UINT16, it will succeed
> +  //
> +  Multiplicand = 0x123;
> +  Multiplier   = 0x67;
> +  Result       = 0;
> +  Status       = SafeInt16Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x7515, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0x123;
> +  Multiplier   = 0xab;
> +  Status       = SafeInt16Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeInt32Mult) {
> +  RETURN_STATUS  Status;
> +  INT32       Multiplicand;
> +  INT32       Multiplier;
> +  INT32       Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_INT32 and
doesn't
> +  // underflow MIN_UINT32, it will succeed
> +  //
> +  Multiplicand = 0x123456;
> +  Multiplier   = 0x678;
> +  Result       = 0;
> +  Status       = SafeInt32Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x75c28c50, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0x123456;
> +  Multiplier   = 0xabc;
> +  Status       = SafeInt32Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +TEST(MultiplicationTestSuite, TestSafeInt64Mult) {
> +  RETURN_STATUS  Status;
> +  INT64       Multiplicand;
> +  INT64       Multiplier;
> +  INT64       Result;
> +
> +  //
> +  // If the result of multiplication doesn't overflow MAX_INT64 and
doesn't
> +  // underflow MIN_UINT64, it will succeed
> +  //
> +  Multiplicand = 0x123456789;
> +  Multiplier   = 0x6789abcd;
> +  Result       = 0;
> +  Status       = SafeInt64Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (Status, RETURN_SUCCESS);
> +  ASSERT_EQ (0x75cd9045220d6bb5, Result);
> +
> +  //
> +  // Otherwise should result in an error status
> +  //
> +  Multiplicand = 0x123456789;
> +  Multiplier   = 0xa789abcd;
> +  Status       = SafeInt64Mult (Multiplicand, Multiplier, &Result);
> +  ASSERT_EQ (RETURN_BUFFER_TOO_SMALL, Status);
> +}
> +
> +int main(int argc, char* argv[]) {
> +  testing::InitGoogleTest(&argc, argv);
> +  return RUN_ALL_TESTS();
> +}
> diff --git a/MdePkg/Test/MdePkgHostTest.dsc
> b/MdePkg/Test/MdePkgHostTest.dsc
> index 0cac14f0e557..b8b186dd8b17 100644
> --- a/MdePkg/Test/MdePkgHostTest.dsc
> +++ b/MdePkg/Test/MdePkgHostTest.dsc
> @@ -28,6 +28,7 @@ [Components]
>    #
>    MdePkg/Test/UnitTest/Library/BaseSafeIntLib/TestBaseSafeIntLibHost.inf
>    MdePkg/Test/UnitTest/Library/BaseLib/BaseLibUnitTestsHost.inf
> +
> MdePkg/Test/GoogleTest/Library/BaseSafeIntLib/GoogleTestBaseSafeIntLib.i
> nf
> 
>    #
>    # Build HOST_APPLICATION Libraries
> --
> 2.37.1.windows.1
> 
> 
> 
> 
> 
> 
> 





^ permalink raw reply	[flat|nested] 13+ messages in thread

* 回复: [edk2-devel] [Patch V2 3/7] UnitTestFrameworkPkg: Add googletest submodule and GoogleTestLib
  2022-11-04 20:25 ` [Patch V2 3/7] UnitTestFrameworkPkg: Add googletest submodule and GoogleTestLib Michael D Kinney
@ 2022-11-08  7:47   ` gaoliming
  2022-11-08 23:03     ` Michael D Kinney
  0 siblings, 1 reply; 13+ messages in thread
From: gaoliming @ 2022-11-08  7:47 UTC (permalink / raw)
  To: devel, michael.d.kinney; +Cc: 'Michael Kubacki', 'Sean Brogan'

Mike:
  For new submodule, I think it is also required to be mentioned in License
Details section in Edk2\ReadMe.rst

Thanks
Liming
> -----邮件原件-----
> 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Michael D
> Kinney
> 发送时间: 2022年11月5日 4:25
> 收件人: devel@edk2.groups.io
> 抄送: Michael Kubacki <mikuback@linux.microsoft.com>; Sean Brogan
> <sean.brogan@microsoft.com>
> 主题: [edk2-devel] [Patch V2 3/7] UnitTestFrameworkPkg: Add googletest
> submodule and GoogleTestLib
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134
> 
> Add submodule for googletest and add GoogleTestLib that is
> required for GoogleTest based unit tests. Add GoogleTest
> documentation to Readme.md along with a port of the sample
> unit test to the GoogleTest style.
> 
> Cc: Michael Kubacki <mikuback@linux.microsoft.com>
> Cc: Sean Brogan <sean.brogan@microsoft.com>
> Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
> Reviewed-by: Michael Kubacki <mikuback@linux.microsoft.com>
> ---
>  .gitmodules                                   |   3 +
>  .../Include/Library/GoogleTestLib.h           |  14 +
>  .../Library/GoogleTestLib/GoogleTestLib.inf   |  36 +++
>  .../Library/GoogleTestLib/GoogleTestLib.uni   |  14 +
>  .../Library/GoogleTestLib/googletest          |   1 +
>  UnitTestFrameworkPkg/ReadMe.md                | 255
> +++++++++++++++--
>  .../SampleGoogleTest/SampleGoogleTest.cpp     | 263
> ++++++++++++++++++
>  .../SampleGoogleTest/SampleGoogleTestHost.inf |  35 +++
>  .../Test/UnitTestFrameworkPkgHostTest.dsc     |   4 +-
>  .../UnitTestFrameworkPkg.ci.yaml              |   4 +-
>  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec |   8 +
>  .../UnitTestFrameworkPkgHost.dsc.inc          |   4 +-
>  12 files changed, 610 insertions(+), 31 deletions(-)
>  create mode 100644
> UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
>  create mode 100644
> UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
>  create mode 100644
> UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
>  create mode 160000
> UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
>  create mode 100644
> UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleG
> oogleTest.cpp
>  create mode 100644
> UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleG
> oogleTestHost.inf
> 
> diff --git a/.gitmodules b/.gitmodules
> index b845c9ee3ff0..8011a88d9d25 100644
> --- a/.gitmodules
> +++ b/.gitmodules
> @@ -20,3 +20,6 @@
>  [submodule "RedfishPkg/Library/JsonLib/jansson"]
>  	path = RedfishPkg/Library/JsonLib/jansson
>  	url = https://github.com/akheron/jansson
> +[submodule "UnitTestFrameworkPkg/Library/GoogleTestLib/googletest"]
> +	path = UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
> +	url = https://github.com/google/googletest.git
> diff --git a/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
> b/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
> new file mode 100644
> index 000000000000..ebec766d4cf7
> --- /dev/null
> +++ b/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
> @@ -0,0 +1,14 @@
> +/** @file
> +  GoogleTestLib class with APIs from the googletest project
> +
> +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#ifndef GOOGLE_TEST_LIB_H_
> +#define GOOGLE_TEST_LIB_H_
> +
> +#include <gtest/gtest.h>
> +
> +#endif
> diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> new file mode 100644
> index 000000000000..68db75d7023f
> --- /dev/null
> +++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> @@ -0,0 +1,36 @@
> +## @file
> +#  This module provides GoogleTest Library implementation.
> +#
> +#  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION     = 0x00010005
> +  BASE_NAME       = GoogleTestLib
> +  MODULE_UNI_FILE = GoogleTestLib.uni
> +  FILE_GUID       = A90E4751-AD30-43CC-980B-01E356B49ADF
> +  MODULE_TYPE     = BASE
> +  VERSION_STRING  = 0.1
> +  LIBRARY_CLASS   = GoogleTestLib|HOST_APPLICATION
> +
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
> +#
> +
> +[Sources]
> +  googletest/googletest/src/gtest-all.cc
> +
> +[Packages]
> +  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> +
> +[BuildOptions]
> +  MSFT:*_*_*_CC_FLAGS     == /c /EHsc /Zi
> +  MSFT:NOOPT_*_*_CC_FLAGS =  /Od
> +
> +  GCC:*_*_*_CC_FLAGS     == -g -c
> +
> +  GCC:NOOPT_*_*_CC_FLAGS =  -O0
> +  GCC:*_*_IA32_CC_FLAGS  =  -m32
> +  GCC:*_*_X64_CC_FLAGS   =  -m64
> diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
> b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
> new file mode 100644
> index 000000000000..14c862a23744
> --- /dev/null
> +++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
> @@ -0,0 +1,14 @@
> +// /** @file
> +// This module provides GoogleTest Library implementation.
> +//
> +// This module provides GoogleTest Library implementation.
> +//
> +// Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> +//
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_MODULE_ABSTRACT             #language en-US
> "GoogleTest Library implementation"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This
> module provides GoogleTest Library implementation."
> diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
> b/UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
> new file mode 160000
> index 000000000000..86add13493e5
> --- /dev/null
> +++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
> @@ -0,0 +1 @@
> +Subproject commit 86add13493e5c881d7e4ba77fb91c1f57752b3a4
> diff --git a/UnitTestFrameworkPkg/ReadMe.md
> b/UnitTestFrameworkPkg/ReadMe.md
> index e696412cb3cf..9ce04b7f3eb6 100644
> --- a/UnitTestFrameworkPkg/ReadMe.md
> +++ b/UnitTestFrameworkPkg/ReadMe.md
> @@ -2,12 +2,67 @@
> 
>  ## About
> 
> -This package adds a unit test framework capable of building tests for
multiple
> contexts including
> +This package provides unit test frameworks capable of building tests for
> multiple contexts including
>  the UEFI shell environment and host-based environments. It allows for
unit
> test development to focus
> -on the tests and leave error logging, result formatting, context
persistance,
> and test running to the framework.
> +on the tests and leave error logging, result formatting, context
persistence,
> and test running to the framework.
>  The unit test framework works well for low level unit tests as well as
system
> level tests and
>  fits easily in automation frameworks.
> 
> +### Framework
> +
> +The first unit test framework is called **Framework** and is implemented
> as a set of EDK II libraries.
> +The Framework supports both host-based unit tests and target-based unit
> tests that share the same
> +source style, macros, and APIs. In some scenarios, the same unit test
case
> sources can be built
> +for both host-based unit test execution and target-based unit test
execution.
> Host-based unit tests
> +that require mocked interfaces can use the mocking infrastructure
provided
> by
> +[cmocka](https://api.cmocka.org/) that is included in the
> UnitTestFrameworkPkg as a submodule.
> +
> +### GoogleTest
> +
> +The second unit test framework supported by the UnitTestFrameworkPkg is
> +[GoogleTest](http://google.github.io/googletest/) that can be used to
> implement host-based unit tests.
> +Use of GoogleTest for target-based unit tests of EDK II components is not
> supported. If a
> +host-based unit test requires mocked interfaces, then the Framework with
> cmocka support should be
> +used instead. Enabling support for mocked interfaces with GoogleTest is
> being actively investigated.
> +[GoogleTest on GitHub](https://github.com/google/googletest) is included
in
> the UnitTestFrameworkPkg
> +as a submodule.
> +
> +GoogleTest requires less overhead to register test suites and test cases
> compared to the Framework.
> +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.
> +
> +If a component can be tested with host-based unit tests without support
for
> mocked interfaces,
> +then GoogleTest is recommended. The MdePkg contains a port of the
> BaseSafeIntLib unit tests in
> +the GoogleTest style so the differences between GoogleTest and Framework
> unit tests can be reviewed.
> +The paths to the BaseSafeIntLib unit tests are:
> +
> +* MdePkg\Test\UnitTest\Library\BaseSafeIntLib
> +* MdePkg\Test\GoogleTest\Library\BaseSafeIntLib
> +
> +## Framework and GoogleTest Feature Comparison
> +
> +| Feature                     | Framework | GoogleTest |
> +|:----------------------------|:---------:|:----------:|
> +| Host Based Unit Tests       |    YES    |    YES     |
> +| Target Based Unit Tests     |    YES    |     NO     |
> +| Unit Test Source Language   |     C     |    C++     |
> +| Register Test Suite         |    YES    |    Auto    |
> +| Register Test Case          |    YES    |    Auto    |
> +| Death/Expected Assert Tests |    YES    |    YES     |
> +| Setup/Teardown Hooks        |    YES    |    YES     |
> +| Value-Parameterized Tests   |    NO     |    YES     |
> +| Typed Tests                 |    NO     |    YES     |
> +| Type-Parameterized Tests    |    NO     |    YES     |
> +| Timeout Support             |    NO     |    YES     |
> +| Mocking Support             |   Cmocka  |     NO     |
> +| JUNIT XML Reports           |    YES    |    YES     |
> +| Execute subset of tests     |    NO     |    YES     |
> +| VS Code Extensions          |    NO     |    YES     |
> +
> +## Framework Libraries
> +
>  ### UnitTestLib
> 
>  The main "framework" library. The core of the framework is the Framework
> object, which can have any number
> @@ -31,10 +86,10 @@ in supporting a system reboot in the middle of a test
> run.
> 
>  Library provides function to run at the end of a framework test run and
> handles formatting the report.
>  This is a common customization point and allows the unit test framework
to
> fit its output reports into
> -other test infrastructure. In this package a simple library instances has
been
> supplied to output test
> +other test infrastructure. In this package simple library instances have
been
> supplied to output test
>  results to the console as plain text.
> 
> -## Samples
> +## Framework Samples
> 
>  There is a sample unit test provided as both an example of how to write a
> unit test and leverage
>  many of the features of the framework. This sample can be found in the
> `Test/UnitTest/Sample/SampleUnitTest`
> @@ -43,7 +98,7 @@ directory.
>  The sample is provided in PEI, SMM, DXE, and UEFI App flavors. It also
has a
> flavor for the HOST_APPLICATION
>  build type, which can be run on a host system without needing a target.
> 
> -## Usage
> +## Framework Usage
> 
>  This section is built a lot like a "Getting Started". We'll go through
some of
> the components that are needed
>  when constructing a unit test and some of the decisions that are made by
> the test writer. We'll also describe
> @@ -51,7 +106,7 @@ how to check for expected conditions in test cases and
> a bit of the logging char
> 
>  Most of these examples will refer to the SampleUnitTestUefiShell app
found
> in this package.
> 
> -### Requirements - INF
> +### Framework Requirements - INF
> 
>  In our INF file, we'll need to bring in the `UnitTestLib` library.
Conveniently,
> the interface
>  header for the `UnitTestLib` is located in `MdePkg`, so you shouldn't
need to
> depend on any other
> @@ -80,7 +135,7 @@ to make sure that the module `BASE_NAME` contains
> the word `Test`...
>    BASE_NAME      = SampleUnitTestUefiShell
>  ```
> 
> -### Requirements - Code
> +### Framework Requirements - Code
> 
>  Not to state the obvious, but let's make sure we have the following
include
> before getting too far along...
> 
> @@ -90,9 +145,9 @@ Not to state the obvious, but let's make sure we have
> the following include befo
> 
>  Now that we've got that squared away, let's look at our 'Main()'' routine
(or
> DriverEntryPoint() or whatever).
> 
> -### Configuring the Framework
> +### Framework Configuration
> 
> -Everything in the UnitTestPkg framework is built around an object called
--
> conveniently -- the Framework.
> +Everything in the UnitTestFrameworkPkg framework is built around an
object
> called -- conveniently -- the Framework.
>  This Framework object will contain all the information about our test,
the
> test suites and test cases associated
>  with it, the current location within the test pass, and any results that
have
> been recorded so far.
> 
> @@ -102,7 +157,7 @@ The long name and version strings are just for user
> presentation and relatively
>  will be used to name any cache files and/or test results, so should be a
name
> that makes sense in that context.
>  These strings are copied internally to the Framework, so using
> stack-allocated or literal strings is fine.
> 
> -In the 'SampleUnitTestUefiShell' app, the module name is used as the
short
> name, so the init looks like this.
> +In the 'SampleUnitTestUefiShell' app, the module name is used as the
short
> name, so the initialization looks like this.
> 
>  ```c
>  DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME,
> UNIT_TEST_APP_VERSION ));
> @@ -144,11 +199,11 @@ will be used when adding test cases.
>  Great! Now we've finished some of the cruft, red tape, and busy work.
We're
> ready to add some tests. Adding a test
>  to a test suite is accomplished with the -- you guessed it --
`AddTestCase`
> function. It takes in the suite handle;
>  a `CHAR8` string for the description and class name; a function pointer
for
> the test case itself; additional, optional
> -function pointers for prerequisite check and cleanup routines; and and
> optional pointer to a context structure.
> +function pointers for prerequisite check and cleanup routines; and an
> optional pointer to a context structure.
> 
>  Okay, that's a lot. Let's take it one piece at a time. The description
and class
> name strings are very similar in
>  usage to the suite title and package name strings in the test suites. The
> former is for user presentation and the
> -latter is for xUnit parsing. The test case function pointer is what is
actually
> executed as the "test" and the
> +latter is for xUnit parsing. The test case function pointer is what is
executed
> as the "test" and the
>  prototype should be `UNIT_TEST_FUNCTION`. The last three parameters
> require a little bit more explaining.
> 
>  The prerequisite check function has a prototype of
> `UNIT_TEST_PREREQUISITE` and -- if provided -- will be called
> @@ -180,7 +235,7 @@ Once all the suites and cases are added, it's time to
> run the Framework.
>  Status = RunAllTestSuites( Framework );
>  ```
> 
> -### A Simple Test Case
> +### Framework - A Simple Test Case
> 
>  We'll take a look at the below test case from 'SampleUnitTestApp'...
> 
> @@ -217,9 +272,9 @@ _Note_ that this early return can have implications
for
> memory leakage.
> 
>  At the end, if all test criteria pass, you should return
`UNIT_TEST_PASSED`.
> 
> -### More Complex Cases
> +### Framework - More Complex Cases
> 
> -To write more advanced tests, first take a look at all the Assertion and
> Logging macros provided in the framework.
> +To write more advanced tests, first look at all the Assertion and Logging
> macros provided in the framework.
> 
>  Beyond that, if you're writing host-based tests and want to take a
> dependency on the UnitTestFrameworkPkg, you can
>  leverage the `cmocka.h` interface and write tests with all the features
of the
> Cmocka framework.
> @@ -227,6 +282,125 @@ leverage the `cmocka.h` interface and write tests
> with all the features of the C
>  Documentation for Cmocka can be found here:
>  https://api.cmocka.org/
> 
> +## GoogleTest Samples
> +
> +There is a sample unit test provided as both an example of how to write a
> unit test and leverage
> +many of the GoogleTest features. This sample can be found in the
> `Test/GoogleTest/Sample/SampleGoogleTest`
> +directory.
> +
> +The sample is provided for the HOST_APPLICATION build type, which can be
> run on a host system without
> +needing a target.
> +
> +## GoogleTest Usage
> +
> +This section is built a lot like a "Getting Started". We'll go through
some of
> the components that are needed
> +when constructing a unit test and some of the decisions that are made by
> the test writer. We'll also describe
> +how to check for expected conditions in test cases and a bit of the
logging
> characteristics.
> +
> +Most of these examples will refer to the SampleGoogleTestHost app found
in
> this package.
> +
> +### GoogleTest Requirements - INF
> +
> +In our INF file, we'll need to bring in the `GoogleTest` library.
Conveniently,
> the interface
> +header for the `GoogleTest` is in `UnitTestFrameworkPkg`, so you
shouldn't
> need to depend on any other
> +packages. As long as your DSC file knows where to find the lib
> implementation that you want to use,
> +you should be good to go.
> +
> +See this example in 'SampleGoogleTestHost.inf'...
> +
> +```
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> +
> +[LibraryClasses]
> +  GoogleTestLib
> +  BaseLib
> +  DebugLib
> +```
> +
> +Also, if you want you test to automatically be picked up by the Test
Runner
> plugin, you will need
> +to make sure that the module `BASE_NAME` contains the word `Test`...
> +
> +```
> +[Defines]
> +  BASE_NAME      = SampleGoogleTestHost
> +```
> +
> +### GoogleTest Requirements - Code
> +
> +Not to state the obvious, but let's make sure we have the following
include
> before getting too far along...
> +
> +```
> +#include <gtest/gtest.h>
> +extern "C" {
> +  #include <Uefi.h>
> +  #include <Library/BaseLib.h>
> +  #include <Library/DebugLib.h>
> +}
> +```
> +
> +GoogleTest applications are implemented in C++. The first include brings
in
> the
> +GoogleTest definitions. Other EDK II related include files must be
wrapped in
> +`extern "C" {}` because they are C include files. Link failures will
occur if
> +this is not done.
> +
> +Now that we've got that squared away, let's look at our 'Main()'' routine
(or
> DriverEntryPoint() or whatever).
> +
> +### GoogleTest Configuration
> +
> +Unlike the Framework, GoogleTest does not require test suites or test
cases
> to
> +be registered. Instead, the test cases declare the test suite name and
test
> +case name as part of their implementation. The only requirement for
> GoogleTest
> +is to have a `main()` function that initialize the GoogleTest
infrastructure and
> +call the service `RUN_ALL_TESTS()` to run all the unit tests.
> +
> +```c
> +int main(int argc, char* argv[]) {
> +  testing::InitGoogleTest(&argc, argv);
> +  return RUN_ALL_TESTS();
> +}
> +```
> +
> +### GoogleTest - A Simple Test Case
> +
> +We'll look at the below test case from 'SampleGoogleTestHost'...
> +
> +```c
> +TEST(SimpleMathTests, OnePlusOneShouldEqualTwo) {
> +  UINTN  A;
> +  UINTN  B;
> +  UINTN  C;
> +
> +  A = 1;
> +  B = 1;
> +  C = A + B;
> +
> +  ASSERT_EQ (C, 2);
> +}
> +```
> +
> +This uses the simplest form of a GoogleTest unit test using `TEST()` that
> +declares the test suite name and the unit test name within that test
suite.
> +The unit test performs actions and typically makes calls to the code
under
> test
> +and contains test assertions to verify that the code under test behaves
as
> +expected for the given inputs.
> +
> +In this test case, the `ASSERT_EQ` assertion is being used to establish
that
> the business logic has functioned
> +correctly. There are several assertion macros, and you are encouraged to
> use one that matches as closely to your
> +intended test criterium as possible, because the logging is specific to
the
> macro and more specific macros have more
> +detailed logs. When in doubt, there are always `ASSERT_TRUE` and
> `ASSERT_FALSE`. Assertion macros that fail their
> +test criterium will immediately return from the test case with a failed
status
> and log an error string.
> +_Note_ that this early return can have implications for memory leakage.
> +
> +There is no return status from a GooglTest unit test. If no assertions
are
> +triggered then the unit test has a passing status.
> +
> +### GoogleTest - More Complex Cases
> +
> +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
> @@ -243,11 +417,11 @@ stuart_ci_build -c .pytool/CISettings.py
> TOOL_CHAIN_TAG=VS2017 -p MdePkg -t NOOP
> 
>  ### Hooking BaseLib
> 
> -Most unit test mocking can be performed by the functions provided in the
> UnitTestFramework libraries, but since
> +Most unit test mocking can be performed by the functions provided in the
> UnitTestFrameworkPkg libraries, but since
>  BaseLib is consumed by the Framework itself, it requires different
techniques
> to substitute parts of the
>  functionality.
> 
> -To solve some of this, the UnitTestFramework consumes a special
> implementation of BaseLib for host-based tests.
> +To solve some of this, the UnitTestFrameworkPkg consumes a special
> implementation of BaseLib for host-based tests.
>  This implementation contains a [hook
> table](https://github.com/tianocore/edk2/blob/e188ecc8b4aed8fdd26b731d
> 43883861f5e5e7b4/MdePkg/Test/UnitTest/Include/Library/UnitTestHostBase
> Lib.h#L507)
>  that can be used to substitute test functionality for any of the BaseLib
> functions. By default, this implementation
>  will use the underlying BaseLib implementation, so the unit test writer
only
> has to supply minimal code to test a
> @@ -255,7 +429,7 @@ particular case.
> 
>  ### Debugging the Framework Itself
> 
> -While most of the tests that are produced by the UnitTestFramework are
> easy to step through in a debugger, the Framework
> +While most of the tests that are produced by the UnitTestFrameworkPkg are
> easy to step through in a debugger, the Framework
>  itself consumes code (mostly Cmocka) that sets its own build flags. These
> flags cause parts of the Framework to not
>  export symbols and captures exceptions, and as such are harder to debug.
> We have provided a Stuart parameter to force
>  symbolic debugging to be enabled.
> @@ -269,15 +443,17 @@ stuart_ci_build -c .pytool/CISettings.py
> TOOL_CHAIN_TAG=VS2019 -p MdePkg -t NOOP
>  ## Building and Running Host-Based Tests
> 
>  The EDK2 CI infrastructure provides a convenient way to run all
host-based
> tests -- in the the entire tree or just
> -selected packages -- and aggregate all the the reports, including
highlighting
> any failures. This functionality is
> -provided through the Stuart build system (published by EDK2-PyTools) and
> the `NOOPT` build target.
> +selected packages -- and aggregate all the reports, including
highlighting any
> failures. This functionality is
> +provided through the Stuart build system (published by EDK2-PyTools) and
> the `NOOPT` build target. The sections that
> +follow use Framework examples. Unit tests based on GoogleTest are built
> and run the same way. The text output and
> +JUNIT XML output format have small differences.
> 
>  ### Building Locally
> 
>  First, to make sure you're working with the latest PyTools, run the
following
> command:
> 
>  ```bash
> -# Would recommend to run this in a Python venv, but that's out of scope
for
> this doc.
> +# Would recommend running this in a Python venv, but that's out of scope
for
> this doc.
>  python -m pip install --upgrade -r ./pip-requirements.txt
>  ```
> 
> @@ -361,7 +537,7 @@ RUNNING TEST SUITE: Int Safe Conversions Test
> Suite
>  ```
> 
>  You can also, if you are so inclined, read the output from the exact
instance
> of the test that was run during
> -`stuart_ci_build`. The ouput file can be found on a path that looks like:
> +`stuart_ci_build`. The output file can be found on a path that looks
like:
> 
> 
> `Build/<Package>/HostTest/<Arch>/<TestName>.<TestSuiteName>.<Arch>.re
> sult.xml`
> 
> @@ -389,22 +565,30 @@
> c:\_uefi\MdePkg\Test\UnitTest\Library\BaseSafeIntLib\TestBaseSafeIntLib.c:
> 35: er
> 
>  ### XML Reporting Mode
> 
> -Since these applications are built using the CMocka framework, they can
also
> use the following env variables to output
> -in a structured XML rather than text:
> +Unit test applications using Framework are built using Cmocka that
requires
> the
> +following environment variables to be set to generate structured XML
output
> +rather than text:
> 
> -```text
> +```
>  CMOCKA_MESSAGE_OUTPUT=xml
>  CMOCKA_XML_FILE=<absolute or relative path to output file>
>  ```
> 
> +Unit test applications using GoogleTest require the following environment
> +variable to be set to generate structured XML output rather than text:
> +
> +```
> +GTEST_OUTPUT=xml:<absolute or relative path to output file>
> +```
> +
>  This mode is used by the test running plugin to aggregate the results for
CI
> test status reporting in the web view.
> 
>  ### Important Note
> 
> -This works on both Windows and Linux, but is currently limited to x64
> architectures. Working on getting others, but we
> +This works on both Windows and Linux but is currently limited to x64
> architectures. Working on getting others, but we
>  also welcome contributions.
> 
> -## Known Limitations
> +## Framework Known Limitations
> 
>  ### PEI, DXE, SMM
> 
> @@ -418,7 +602,7 @@ PEI, DXE, and SMM is forthcoming, but should be
> considered beta/staging for now.
>  The host-based test framework is powered internally by the Cmocka
> framework. As such, it has abilities
>  that the target-based tests don't (yet). It would be awesome if this
meant
> that it was a super set of
>  the target-based tests, and it worked just like the target-based tests
but
> with more features. Unfortunately,
> -this is not the case. While care has been taken to keep them as close a
> possible, there are a few known
> +this is not the case. While care has been taken to keep them as close as
> possible, there are a few known
>  inconsistencies that we're still ironing out. For example, the logging
> messages in the target-based tests
>  are cached internally and associated with the running test case. They can
be
> saved later as part of the
>  reporting lib. This isn't currently possible with host-based. Only the
assertion
> failures are logged.
> @@ -441,6 +625,9 @@ Non-Host-Based (PEI/DXE/SMM/Shell) Tests for a
> Functionality or Feature   | Simi
>    ComponentY/
>      ComponentY.inf
>      ComponentY.c
> +    GoogleTest/
> +      ComponentYHostGoogleTest.inf    # Host-Based Test for Driver
> Module
> +      ComponentYGoogleTest.cpp
>      UnitTest/
>        ComponentYHostUnitTest.inf      # Host-Based Test for Driver
> Module
>        ComponentYUnitTest.c
> @@ -455,11 +642,23 @@ Non-Host-Based (PEI/DXE/SMM/Shell) Tests for a
> Functionality or Feature   | Simi
>      SpecificLibDxe/
>        SpecificLibDxe.c
>        SpecificLibDxe.inf
> +      GoogleTest/                    # Host-Based Test for Specific
> Library Implementation
> +        SpecificLibDxeHostGoogleTest.cpp
> +        SpecificLibDxeHostGoogleTest.inf
>        UnitTest/                      # Host-Based Test for Specific
> Library Implementation
>          SpecificLibDxeHostUnitTest.c
>          SpecificLibDxeHostUnitTest.inf
>    Test/
>      <Package>HostTest.dsc             # Host-Based Test Apps
> +    GoogleTest/
> +      InterfaceX
> +        InterfaceXHostGoogleTest.inf  # Host-Based App (should be in
> Test/<Package>HostTest.dsc)
> +        InterfaceXUnitTest.cpp        # Test Logic
> +
> +      GeneralPurposeLib/              # Host-Based Test for any
> implementation of GeneralPurposeLib
> +        GeneralPurposeLibTest.cpp
> +        GeneralPurposeLibHostUnitTest.inf
> +
>      UnitTest/
>        InterfaceX
>          InterfaceXHostUnitTest.inf    # Host-Based App (should be in
> Test/<Package>HostTest.dsc)
> diff --git
> a/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> eGoogleTest.cpp
> b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> eGoogleTest.cpp
> new file mode 100644
> index 000000000000..c83e58596a82
> --- /dev/null
> +++
> b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> eGoogleTest.cpp
> @@ -0,0 +1,263 @@
> +/** @file
> +  This is a sample to demonstrates the use of GoogleTest that supports
host
> +  execution environments.
> +
> +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> +
> +#include <gtest/gtest.h>
> +extern "C" {
> +  #include <Uefi.h>
> +  #include <Library/BaseLib.h>
> +  #include <Library/DebugLib.h>
> +}
> +
> +/**
> +  Sample unit test that verifies the expected result of an unsigned
integer
> +  addition operation.
> +**/
> +TEST(SimpleMathTests, OnePlusOneShouldEqualTwo) {
> +  UINTN  A;
> +  UINTN  B;
> +  UINTN  C;
> +
> +  A = 1;
> +  B = 1;
> +  C = A + B;
> +
> +  ASSERT_EQ (C, (UINTN)2);
> +}
> +
> +/**
> +  Sample unit test that verifies that a global BOOLEAN is updatable.
> +**/
> +class GlobalBooleanVarTests : public ::testing::Test {
> +  public:
> +    BOOLEAN  SampleGlobalTestBoolean  = FALSE;
> +};
> +
> +TEST_F(GlobalBooleanVarTests, GlobalBooleanShouldBeChangeable) {
> +  SampleGlobalTestBoolean = TRUE;
> +  ASSERT_TRUE (SampleGlobalTestBoolean);
> +
> +  SampleGlobalTestBoolean = FALSE;
> +  ASSERT_FALSE (SampleGlobalTestBoolean);
> +}
> +
> +/**
> +  Sample unit test that logs a warning message and verifies that a global
> +  pointer is updatable.
> +**/
> +class GlobalVarTests : public ::testing::Test {
> +  public:
> +    VOID  *SampleGlobalTestPointer = NULL;
> +
> +  protected:
> +  void SetUp() override {
> +    ASSERT_EQ ((UINTN)SampleGlobalTestPointer, (UINTN)NULL);
> +  }
> +  void TearDown() {
> +    SampleGlobalTestPointer = NULL;
> +  }
> +};
> +
> +TEST_F(GlobalVarTests, GlobalPointerShouldBeChangeable) {
> +  SampleGlobalTestPointer = (VOID *)-1;
> +  ASSERT_EQ ((UINTN)SampleGlobalTestPointer, (UINTN)((VOID *)-1));
> +}
> +
> +
> +/**
> +  Set PcdDebugPropertyMask for each MacroTestsAssertsEnabledDisabled
> test
> +**/
> +class MacroTestsAssertsEnabledDisabled : public
> testing::TestWithParam<UINT8> {
> +  void SetUp() {
> +    PatchPcdSet8 (PcdDebugPropertyMask, GetParam());
> +  }
> +};
> +
> +/**
> +  Sample unit test using the ASSERT_TRUE() macro.
> +**/
> +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertTrue) {
> +  UINT64  Result;
> +
> +  //
> +  // This test passes because expression always evaluated to TRUE.
> +  //
> +  ASSERT_TRUE (TRUE);
> +
> +  //
> +  // This test passes because expression always evaluates to TRUE.
> +  //
> +  Result = LShiftU64 (BIT0, 1);
> +  ASSERT_TRUE (Result == BIT1);
> +}
> +
> +/**
> +  Sample unit test using the ASSERT_FALSE() macro.
> +**/
> +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertFalse) {
> +  UINT64  Result;
> +
> +  //
> +  // This test passes because expression always evaluated to FALSE.
> +  //
> +  ASSERT_FALSE (FALSE);
> +
> +  //
> +  // This test passes because expression always evaluates to FALSE.
> +  //
> +  Result = LShiftU64 (BIT0, 1);
> +  ASSERT_FALSE (Result == BIT0);
> +}
> +
> +/**
> +  Sample unit test using the ASSERT_EQ() macro.
> +**/
> +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertEqual) {
> +  UINT64  Result;
> +
> +  //
> +  // This test passes because both values are always equal.
> +  //
> +  ASSERT_EQ (1, 1);
> +
> +  //
> +  // This test passes because both values are always equal.
> +  //
> +  Result = LShiftU64 (BIT0, 1);
> +  ASSERT_EQ (Result, (UINT64)BIT1);
> +}
> +
> +/**
> +  Sample unit test using the ASSERT_STREQ() macro.
> +**/
> +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertMemEqual) {
> +  CHAR8  *String1;
> +  CHAR8  *String2;
> +
> +  //
> +  // This test passes because String1 and String2 are the same.
> +  //
> +  String1 = (CHAR8 *)"Hello";
> +  String2 = (CHAR8 *)"Hello";
> +  ASSERT_STREQ (String1, String2);
> +}
> +
> +/**
> +  Sample unit test using the ASSERT_NE() macro.
> +**/
> +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertNotEqual) {
> +  UINT64  Result;
> +
> +  //
> +  // This test passes because both values are never equal.
> +  //
> +  ASSERT_NE (0, 1);
> +
> +  //
> +  // This test passes because both values are never equal.
> +  //
> +  Result = LShiftU64 (BIT0, 1);
> +  ASSERT_NE (Result, (UINT64)BIT0);
> +}
> +
> +/**
> +  Sample unit test using the ASSERT_TRUE() and ASSERT(FALSE)
> +  and EFI_EFFOR() macros to check status
> +**/
> +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertNotEfiError) {
> +  //
> +  // This test passes because the status is not an EFI error.
> +  //
> +  ASSERT_FALSE (EFI_ERROR (EFI_SUCCESS));
> +
> +  //
> +  // This test passes because the status is not an EFI error.
> +  //
> +  ASSERT_FALSE (EFI_ERROR (EFI_WARN_BUFFER_TOO_SMALL));
> +}
> +
> +/**
> +  Sample unit test using the ASSERT_EQ() macro to compare EFI_STATUS
> values.
> +**/
> +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertStatusEqual) {
> +  //
> +  // This test passes because the status value are always equal.
> +  //
> +  ASSERT_EQ (EFI_SUCCESS, EFI_SUCCESS);
> +}
> +
> +/**
> +  Sample unit test using ASSERT_NE() macro to make sure a pointer is not
> NULL.
> +**/
> +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertNotNull) {
> +  UINT64  Result;
> +
> +  //
> +  // This test passes because the pointer is never NULL.
> +  //
> +  ASSERT_NE (&Result, (UINT64 *)NULL);
> +}
> +
> +/**
> +  Sample unit test using that should not generate any ASSERTs()
> +**/
> +TEST_P(MacroTestsAssertsEnabledDisabled, MacroExpectNoAssertFailure) {
> +  //
> +  // This test passes because it never triggers an ASSERT().
> +  //
> +  ASSERT (TRUE);
> +
> +  //
> +  // This test passes because DecimalToBcd() does not ASSERT() if the
> +  // value passed in is <= 99.
> +  //
> +  DecimalToBcd8 (99);
> +}
> +
> +/**
> +  Sample unit test using the ASSERT_DEATH() macro to test expected
> ASSERT()s.
> +**/
> +TEST_P(MacroTestsAssertsEnabledDisabled, MacroExpectAssertFailure) {
> +  //
> +  // Skip tests that verify an ASSERT() is triggered if ASSERT()s are
disabled.
> +  //
> +  if ((PcdGet8 (PcdDebugPropertyMask) & BIT0) == 0x00) {
> +    return;
> +  }
> +
> +  //
> +  // This test passes because it directly triggers an ASSERT().
> +  //
> +  ASSERT_DEATH (ASSERT (FALSE), "");
> +
> +  //
> +  // This test passes because DecimalToBcd() generates an ASSERT() if the
> +  // value passed in is >= 100.  The expected ASSERT() is caught by the
unit
> +  // test framework and ASSERT_DEATH() returns without an error.
> +  //
> +  ASSERT_DEATH (DecimalToBcd8 (101), "");
> +}
> +
> +INSTANTIATE_TEST_SUITE_P(ValidInput,
> +                         MacroTestsAssertsEnabledDisabled,
> +                         ::testing::Values(PcdGet8
> (PcdDebugPropertyMask) | BIT0, PcdGet8 (PcdDebugPropertyMask) &
> (~BIT0)));
> +
> +/**
> +  Sample unit test using the SCOPED_TRACE() macro for trace messages.
> +**/
> +TEST(MacroTestsMessages, MacroTraceMessage) {
> +  //
> +  // Example of logging.
> +  //
> +  SCOPED_TRACE ("SCOPED_TRACE message\n");
> +}
> +
> +int main(int argc, char* argv[]) {
> +  testing::InitGoogleTest(&argc, argv);
> +  return RUN_ALL_TESTS();
> +}
> diff --git
> a/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> eGoogleTestHost.inf
> b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> eGoogleTestHost.inf
> new file mode 100644
> index 000000000000..37e7c86910ed
> --- /dev/null
> +++
> b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> eGoogleTestHost.inf
> @@ -0,0 +1,35 @@
> +## @file
> +# This is a sample to demonstrates the use of GoogleTest that supports
host
> +# execution environments.
> +#
> +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> +# SPDX-License-Identifier: BSD-2-Clause-Patent
> +##
> +
> +[Defines]
> +  INF_VERSION    = 0x00010005
> +  BASE_NAME      = SampleGoogleTestHost
> +  FILE_GUID      = 7D8BBFBB-7977-4AEE-A59F-257BF5C2F87C
> +  MODULE_TYPE    = HOST_APPLICATION
> +  VERSION_STRING = 1.0
> +
> +#
> +# The following information is for reference only and not required by the
> build tools.
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  SampleGoogleTest.cpp
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> +
> +[LibraryClasses]
> +  GoogleTestLib
> +  BaseLib
> +  DebugLib
> +
> +[Pcd]
> +  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
> diff --git a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> index 184fdec87acf..708ef7f9ab35 100644
> --- a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> +++ b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> @@ -23,14 +23,16 @@ [PcdsPatchableInModule]
> 
>  [Components]
>    #
> -  # Build HOST_APPLICATION that tests the SampleUnitTest
> +  # Build HOST_APPLICATIONs that test the SampleUnitTest
>    #
> 
> UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTe
> stHost.inf
> +
> UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleG
> oogleTestHost.inf
> 
>    #
>    # Build HOST_APPLICATION Libraries
>    #
>    UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
> +  UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
>    UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf
> 
> UnitTestFrameworkPkg/Library/Posix/MemoryAllocationLibPosix/MemoryAllo
> cationLibPosix.inf
>    UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.inf
> diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
> b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
> index 77d51e13484c..072df6208c92 100644
> --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
> +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
> @@ -78,7 +78,8 @@
>      "SpellCheck": {
>          "AuditOnly": False,           # Fails test but run in AuditOnly
> mode to collect log
>          "IgnoreFiles": [             # use gitignore syntax to ignore
> errors in matching files
> -            "Library/CmockaLib/cmocka/**/*.*"  # not going to spell
> check a submodule
> +            "Library/CmockaLib/cmocka/**/*.*",  # not going to spell
> check a submodule
> +            "Library/GoogleTestLib/googletest/**/*.*"  # not going to
> spell check a submodule
>          ],
>          "ExtendWords": [             # words to extend to the
> dictionary for this package
>              "testcase",
> @@ -91,6 +92,7 @@
>              "NOFAILURE",
>              "cmockery",
>              "DHAVE", # build flag for cmocka in the INF
> +            "gtest", # file name in GoogleTestLib.inf
>              "corthon",      # Contact GitHub account in Readme
>              "mdkinney",     # Contact GitHub account in Readme
>              "spbrogan"      # Contact GitHub account in Readme
> diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> index 069289f00969..ed12f32009d8 100644
> --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> @@ -16,11 +16,15 @@ [Defines]
>    PACKAGE_VERSION   = 1.00
> 
>  [Includes]
> +  Include
>    Library/CmockaLib/cmocka/include
> +  Library/GoogleTestLib/googletest/googletest/include
> +  Library/GoogleTestLib/googletest/googlemock/include
> 
>  [Includes.Common.Private]
>    PrivateInclude
>    Library/CmockaLib/cmocka/include/cmockery
> +  Library/GoogleTestLib/googletest/googletest
> 
>  [LibraryClasses.Common.Private]
>    ## @libraryclass Allows save and restore unit test internal state
> @@ -35,6 +39,10 @@ [LibraryClasses.Common.Private]
>    #
>    UnitTestBootLib|PrivateInclude/Library/UnitTestBootLib.h
> 
> +  ## @libraryclass GoogleTest infrastructure
> +  #
> +  GoogleTestLib|Include/Library/GoogleTestLib.h
> +
>  [Guids]
>    gUnitTestFrameworkPkgTokenSpaceGuid = { 0x833d3aba, 0x39b4, 0x43a2,
> { 0xb9, 0x30, 0x7a, 0x34, 0x53, 0x39, 0x31, 0xb3 } }
> 
> diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> index f249813713a8..6d5f651f689f 100644
> --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> @@ -14,6 +14,7 @@ [LibraryClasses.common.HOST_APPLICATION]
>    CpuLib|MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf
> 
> CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLibNull/Base
> CacheMaintenanceLibNull.inf
>    CmockaLib|UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
> +
> GoogleTestLib|UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.i
> nf
> 
> UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.i
> nf
> 
> DebugLib|UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosi
> x.inf
> 
> MemoryAllocationLib|UnitTestFrameworkPkg/Library/Posix/MemoryAllocatio
> nLibPosix/MemoryAllocationLibPosix.inf
> @@ -30,6 +31,7 @@ [BuildOptions.common.EDKII.HOST_APPLICATION]
>    #
>    # MSFT
>    #
> +  MSFT:*_*_*_CC_FLAGS               = /EHsc
>    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
> /NODEFAULTLIB:libcmt.lib libcmtd.lib
>    MSFT:*_*_IA32_DLINK_FLAGS         = /MACHINE:I386
>    MSFT:*_*_X64_DLINK_FLAGS          = /MACHINE:AMD64
> @@ -49,7 +51,7 @@ [BuildOptions.common.EDKII.HOST_APPLICATION]
>    #
>    GCC:*_*_IA32_DLINK_FLAGS == -o $(BIN_DIR)/$(MODULE_NAME_GUID)
> -m32 -no-pie
>    GCC:*_*_X64_DLINK_FLAGS  == -o
> $(BIN_DIR)/$(MODULE_NAME_GUID) -m64 -no-pie
> -  GCC:*_*_*_DLINK2_FLAGS   == -lgcov
> +  GCC:*_*_*_DLINK2_FLAGS   == -lgcov -lpthread -lstdc++ -lm
> 
>    #
>    # Need to do this link via gcc and not ld as the pathing to libraries
changes
> from OS version to OS version
> --
> 2.37.1.windows.1
> 
> 
> 
> 
> 
> 
> 





^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [edk2-devel] [Patch V2 3/7] UnitTestFrameworkPkg: Add googletest submodule and GoogleTestLib
  2022-11-08  7:47   ` 回复: [edk2-devel] " gaoliming
@ 2022-11-08 23:03     ` Michael D Kinney
  0 siblings, 0 replies; 13+ messages in thread
From: Michael D Kinney @ 2022-11-08 23:03 UTC (permalink / raw)
  To: Gao, Liming, devel@edk2.groups.io
  Cc: 'Michael Kubacki', 'Sean Brogan'

Hi Liming,

Thank you for the reminder.  I will update Readme.rst

Mike

> -----Original Message-----
> From: gaoliming <gaoliming@byosoft.com.cn>
> Sent: Monday, November 7, 2022 11:47 PM
> To: devel@edk2.groups.io; Kinney, Michael D <michael.d.kinney@intel.com>
> Cc: 'Michael Kubacki' <mikuback@linux.microsoft.com>; 'Sean Brogan' <sean.brogan@microsoft.com>
> Subject: 回复: [edk2-devel] [Patch V2 3/7] UnitTestFrameworkPkg: Add googletest submodule and GoogleTestLib
> 
> Mike:
>   For new submodule, I think it is also required to be mentioned in License
> Details section in Edk2\ReadMe.rst
> 
> Thanks
> Liming
> > -----邮件原件-----
> > 发件人: devel@edk2.groups.io <devel@edk2.groups.io> 代表 Michael D
> > Kinney
> > 发送时间: 2022年11月5日 4:25
> > 收件人: devel@edk2.groups.io
> > 抄送: Michael Kubacki <mikuback@linux.microsoft.com>; Sean Brogan
> > <sean.brogan@microsoft.com>
> > 主题: [edk2-devel] [Patch V2 3/7] UnitTestFrameworkPkg: Add googletest
> > submodule and GoogleTestLib
> >
> > REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4134
> >
> > Add submodule for googletest and add GoogleTestLib that is
> > required for GoogleTest based unit tests. Add GoogleTest
> > documentation to Readme.md along with a port of the sample
> > unit test to the GoogleTest style.
> >
> > Cc: Michael Kubacki <mikuback@linux.microsoft.com>
> > Cc: Sean Brogan <sean.brogan@microsoft.com>
> > Signed-off-by: Michael D Kinney <michael.d.kinney@intel.com>
> > Reviewed-by: Michael Kubacki <mikuback@linux.microsoft.com>
> > ---
> >  .gitmodules                                   |   3 +
> >  .../Include/Library/GoogleTestLib.h           |  14 +
> >  .../Library/GoogleTestLib/GoogleTestLib.inf   |  36 +++
> >  .../Library/GoogleTestLib/GoogleTestLib.uni   |  14 +
> >  .../Library/GoogleTestLib/googletest          |   1 +
> >  UnitTestFrameworkPkg/ReadMe.md                | 255
> > +++++++++++++++--
> >  .../SampleGoogleTest/SampleGoogleTest.cpp     | 263
> > ++++++++++++++++++
> >  .../SampleGoogleTest/SampleGoogleTestHost.inf |  35 +++
> >  .../Test/UnitTestFrameworkPkgHostTest.dsc     |   4 +-
> >  .../UnitTestFrameworkPkg.ci.yaml              |   4 +-
> >  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec |   8 +
> >  .../UnitTestFrameworkPkgHost.dsc.inc          |   4 +-
> >  12 files changed, 610 insertions(+), 31 deletions(-)
> >  create mode 100644
> > UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
> >  create mode 100644
> > UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> >  create mode 100644
> > UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
> >  create mode 160000
> > UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
> >  create mode 100644
> > UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleG
> > oogleTest.cpp
> >  create mode 100644
> > UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleG
> > oogleTestHost.inf
> >
> > diff --git a/.gitmodules b/.gitmodules
> > index b845c9ee3ff0..8011a88d9d25 100644
> > --- a/.gitmodules
> > +++ b/.gitmodules
> > @@ -20,3 +20,6 @@
> >  [submodule "RedfishPkg/Library/JsonLib/jansson"]
> >  	path = RedfishPkg/Library/JsonLib/jansson
> >  	url = https://github.com/akheron/jansson
> > +[submodule "UnitTestFrameworkPkg/Library/GoogleTestLib/googletest"]
> > +	path = UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
> > +	url = https://github.com/google/googletest.git
> > diff --git a/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
> > b/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
> > new file mode 100644
> > index 000000000000..ebec766d4cf7
> > --- /dev/null
> > +++ b/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
> > @@ -0,0 +1,14 @@
> > +/** @file
> > +  GoogleTestLib class with APIs from the googletest project
> > +
> > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#ifndef GOOGLE_TEST_LIB_H_
> > +#define GOOGLE_TEST_LIB_H_
> > +
> > +#include <gtest/gtest.h>
> > +
> > +#endif
> > diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> > b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> > new file mode 100644
> > index 000000000000..68db75d7023f
> > --- /dev/null
> > +++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> > @@ -0,0 +1,36 @@
> > +## @file
> > +#  This module provides GoogleTest Library implementation.
> > +#
> > +#  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +#
> > +##
> > +
> > +[Defines]
> > +  INF_VERSION     = 0x00010005
> > +  BASE_NAME       = GoogleTestLib
> > +  MODULE_UNI_FILE = GoogleTestLib.uni
> > +  FILE_GUID       = A90E4751-AD30-43CC-980B-01E356B49ADF
> > +  MODULE_TYPE     = BASE
> > +  VERSION_STRING  = 0.1
> > +  LIBRARY_CLASS   = GoogleTestLib|HOST_APPLICATION
> > +
> > +#
> > +#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
> > +#
> > +
> > +[Sources]
> > +  googletest/googletest/src/gtest-all.cc
> > +
> > +[Packages]
> > +  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> > +
> > +[BuildOptions]
> > +  MSFT:*_*_*_CC_FLAGS     == /c /EHsc /Zi
> > +  MSFT:NOOPT_*_*_CC_FLAGS =  /Od
> > +
> > +  GCC:*_*_*_CC_FLAGS     == -g -c
> > +
> > +  GCC:NOOPT_*_*_CC_FLAGS =  -O0
> > +  GCC:*_*_IA32_CC_FLAGS  =  -m32
> > +  GCC:*_*_X64_CC_FLAGS   =  -m64
> > diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
> > b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
> > new file mode 100644
> > index 000000000000..14c862a23744
> > --- /dev/null
> > +++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
> > @@ -0,0 +1,14 @@
> > +// /** @file
> > +// This module provides GoogleTest Library implementation.
> > +//
> > +// This module provides GoogleTest Library implementation.
> > +//
> > +// Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +//
> > +// SPDX-License-Identifier: BSD-2-Clause-Patent
> > +//
> > +// **/
> > +
> > +#string STR_MODULE_ABSTRACT             #language en-US
> > "GoogleTest Library implementation"
> > +
> > +#string STR_MODULE_DESCRIPTION          #language en-US "This
> > module provides GoogleTest Library implementation."
> > diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
> > b/UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
> > new file mode 160000
> > index 000000000000..86add13493e5
> > --- /dev/null
> > +++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/googletest
> > @@ -0,0 +1 @@
> > +Subproject commit 86add13493e5c881d7e4ba77fb91c1f57752b3a4
> > diff --git a/UnitTestFrameworkPkg/ReadMe.md
> > b/UnitTestFrameworkPkg/ReadMe.md
> > index e696412cb3cf..9ce04b7f3eb6 100644
> > --- a/UnitTestFrameworkPkg/ReadMe.md
> > +++ b/UnitTestFrameworkPkg/ReadMe.md
> > @@ -2,12 +2,67 @@
> >
> >  ## About
> >
> > -This package adds a unit test framework capable of building tests for
> multiple
> > contexts including
> > +This package provides unit test frameworks capable of building tests for
> > multiple contexts including
> >  the UEFI shell environment and host-based environments. It allows for
> unit
> > test development to focus
> > -on the tests and leave error logging, result formatting, context
> persistance,
> > and test running to the framework.
> > +on the tests and leave error logging, result formatting, context
> persistence,
> > and test running to the framework.
> >  The unit test framework works well for low level unit tests as well as
> system
> > level tests and
> >  fits easily in automation frameworks.
> >
> > +### Framework
> > +
> > +The first unit test framework is called **Framework** and is implemented
> > as a set of EDK II libraries.
> > +The Framework supports both host-based unit tests and target-based unit
> > tests that share the same
> > +source style, macros, and APIs. In some scenarios, the same unit test
> case
> > sources can be built
> > +for both host-based unit test execution and target-based unit test
> execution.
> > Host-based unit tests
> > +that require mocked interfaces can use the mocking infrastructure
> provided
> > by
> > +[cmocka](https://api.cmocka.org/) that is included in the
> > UnitTestFrameworkPkg as a submodule.
> > +
> > +### GoogleTest
> > +
> > +The second unit test framework supported by the UnitTestFrameworkPkg is
> > +[GoogleTest](http://google.github.io/googletest/) that can be used to
> > implement host-based unit tests.
> > +Use of GoogleTest for target-based unit tests of EDK II components is not
> > supported. If a
> > +host-based unit test requires mocked interfaces, then the Framework with
> > cmocka support should be
> > +used instead. Enabling support for mocked interfaces with GoogleTest is
> > being actively investigated.
> > +[GoogleTest on GitHub](https://github.com/google/googletest) is included
> in
> > the UnitTestFrameworkPkg
> > +as a submodule.
> > +
> > +GoogleTest requires less overhead to register test suites and test cases
> > compared to the Framework.
> > +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.
> > +
> > +If a component can be tested with host-based unit tests without support
> for
> > mocked interfaces,
> > +then GoogleTest is recommended. The MdePkg contains a port of the
> > BaseSafeIntLib unit tests in
> > +the GoogleTest style so the differences between GoogleTest and Framework
> > unit tests can be reviewed.
> > +The paths to the BaseSafeIntLib unit tests are:
> > +
> > +* MdePkg\Test\UnitTest\Library\BaseSafeIntLib
> > +* MdePkg\Test\GoogleTest\Library\BaseSafeIntLib
> > +
> > +## Framework and GoogleTest Feature Comparison
> > +
> > +| Feature                     | Framework | GoogleTest |
> > +|:----------------------------|:---------:|:----------:|
> > +| Host Based Unit Tests       |    YES    |    YES     |
> > +| Target Based Unit Tests     |    YES    |     NO     |
> > +| Unit Test Source Language   |     C     |    C++     |
> > +| Register Test Suite         |    YES    |    Auto    |
> > +| Register Test Case          |    YES    |    Auto    |
> > +| Death/Expected Assert Tests |    YES    |    YES     |
> > +| Setup/Teardown Hooks        |    YES    |    YES     |
> > +| Value-Parameterized Tests   |    NO     |    YES     |
> > +| Typed Tests                 |    NO     |    YES     |
> > +| Type-Parameterized Tests    |    NO     |    YES     |
> > +| Timeout Support             |    NO     |    YES     |
> > +| Mocking Support             |   Cmocka  |     NO     |
> > +| JUNIT XML Reports           |    YES    |    YES     |
> > +| Execute subset of tests     |    NO     |    YES     |
> > +| VS Code Extensions          |    NO     |    YES     |
> > +
> > +## Framework Libraries
> > +
> >  ### UnitTestLib
> >
> >  The main "framework" library. The core of the framework is the Framework
> > object, which can have any number
> > @@ -31,10 +86,10 @@ in supporting a system reboot in the middle of a test
> > run.
> >
> >  Library provides function to run at the end of a framework test run and
> > handles formatting the report.
> >  This is a common customization point and allows the unit test framework
> to
> > fit its output reports into
> > -other test infrastructure. In this package a simple library instances has
> been
> > supplied to output test
> > +other test infrastructure. In this package simple library instances have
> been
> > supplied to output test
> >  results to the console as plain text.
> >
> > -## Samples
> > +## Framework Samples
> >
> >  There is a sample unit test provided as both an example of how to write a
> > unit test and leverage
> >  many of the features of the framework. This sample can be found in the
> > `Test/UnitTest/Sample/SampleUnitTest`
> > @@ -43,7 +98,7 @@ directory.
> >  The sample is provided in PEI, SMM, DXE, and UEFI App flavors. It also
> has a
> > flavor for the HOST_APPLICATION
> >  build type, which can be run on a host system without needing a target.
> >
> > -## Usage
> > +## Framework Usage
> >
> >  This section is built a lot like a "Getting Started". We'll go through
> some of
> > the components that are needed
> >  when constructing a unit test and some of the decisions that are made by
> > the test writer. We'll also describe
> > @@ -51,7 +106,7 @@ how to check for expected conditions in test cases and
> > a bit of the logging char
> >
> >  Most of these examples will refer to the SampleUnitTestUefiShell app
> found
> > in this package.
> >
> > -### Requirements - INF
> > +### Framework Requirements - INF
> >
> >  In our INF file, we'll need to bring in the `UnitTestLib` library.
> Conveniently,
> > the interface
> >  header for the `UnitTestLib` is located in `MdePkg`, so you shouldn't
> need to
> > depend on any other
> > @@ -80,7 +135,7 @@ to make sure that the module `BASE_NAME` contains
> > the word `Test`...
> >    BASE_NAME      = SampleUnitTestUefiShell
> >  ```
> >
> > -### Requirements - Code
> > +### Framework Requirements - Code
> >
> >  Not to state the obvious, but let's make sure we have the following
> include
> > before getting too far along...
> >
> > @@ -90,9 +145,9 @@ Not to state the obvious, but let's make sure we have
> > the following include befo
> >
> >  Now that we've got that squared away, let's look at our 'Main()'' routine
> (or
> > DriverEntryPoint() or whatever).
> >
> > -### Configuring the Framework
> > +### Framework Configuration
> >
> > -Everything in the UnitTestPkg framework is built around an object called
> --
> > conveniently -- the Framework.
> > +Everything in the UnitTestFrameworkPkg framework is built around an
> object
> > called -- conveniently -- the Framework.
> >  This Framework object will contain all the information about our test,
> the
> > test suites and test cases associated
> >  with it, the current location within the test pass, and any results that
> have
> > been recorded so far.
> >
> > @@ -102,7 +157,7 @@ The long name and version strings are just for user
> > presentation and relatively
> >  will be used to name any cache files and/or test results, so should be a
> name
> > that makes sense in that context.
> >  These strings are copied internally to the Framework, so using
> > stack-allocated or literal strings is fine.
> >
> > -In the 'SampleUnitTestUefiShell' app, the module name is used as the
> short
> > name, so the init looks like this.
> > +In the 'SampleUnitTestUefiShell' app, the module name is used as the
> short
> > name, so the initialization looks like this.
> >
> >  ```c
> >  DEBUG(( DEBUG_INFO, "%a v%a\n", UNIT_TEST_APP_NAME,
> > UNIT_TEST_APP_VERSION ));
> > @@ -144,11 +199,11 @@ will be used when adding test cases.
> >  Great! Now we've finished some of the cruft, red tape, and busy work.
> We're
> > ready to add some tests. Adding a test
> >  to a test suite is accomplished with the -- you guessed it --
> `AddTestCase`
> > function. It takes in the suite handle;
> >  a `CHAR8` string for the description and class name; a function pointer
> for
> > the test case itself; additional, optional
> > -function pointers for prerequisite check and cleanup routines; and and
> > optional pointer to a context structure.
> > +function pointers for prerequisite check and cleanup routines; and an
> > optional pointer to a context structure.
> >
> >  Okay, that's a lot. Let's take it one piece at a time. The description
> and class
> > name strings are very similar in
> >  usage to the suite title and package name strings in the test suites. The
> > former is for user presentation and the
> > -latter is for xUnit parsing. The test case function pointer is what is
> actually
> > executed as the "test" and the
> > +latter is for xUnit parsing. The test case function pointer is what is
> executed
> > as the "test" and the
> >  prototype should be `UNIT_TEST_FUNCTION`. The last three parameters
> > require a little bit more explaining.
> >
> >  The prerequisite check function has a prototype of
> > `UNIT_TEST_PREREQUISITE` and -- if provided -- will be called
> > @@ -180,7 +235,7 @@ Once all the suites and cases are added, it's time to
> > run the Framework.
> >  Status = RunAllTestSuites( Framework );
> >  ```
> >
> > -### A Simple Test Case
> > +### Framework - A Simple Test Case
> >
> >  We'll take a look at the below test case from 'SampleUnitTestApp'...
> >
> > @@ -217,9 +272,9 @@ _Note_ that this early return can have implications
> for
> > memory leakage.
> >
> >  At the end, if all test criteria pass, you should return
> `UNIT_TEST_PASSED`.
> >
> > -### More Complex Cases
> > +### Framework - More Complex Cases
> >
> > -To write more advanced tests, first take a look at all the Assertion and
> > Logging macros provided in the framework.
> > +To write more advanced tests, first look at all the Assertion and Logging
> > macros provided in the framework.
> >
> >  Beyond that, if you're writing host-based tests and want to take a
> > dependency on the UnitTestFrameworkPkg, you can
> >  leverage the `cmocka.h` interface and write tests with all the features
> of the
> > Cmocka framework.
> > @@ -227,6 +282,125 @@ leverage the `cmocka.h` interface and write tests
> > with all the features of the C
> >  Documentation for Cmocka can be found here:
> >  https://api.cmocka.org/
> >
> > +## GoogleTest Samples
> > +
> > +There is a sample unit test provided as both an example of how to write a
> > unit test and leverage
> > +many of the GoogleTest features. This sample can be found in the
> > `Test/GoogleTest/Sample/SampleGoogleTest`
> > +directory.
> > +
> > +The sample is provided for the HOST_APPLICATION build type, which can be
> > run on a host system without
> > +needing a target.
> > +
> > +## GoogleTest Usage
> > +
> > +This section is built a lot like a "Getting Started". We'll go through
> some of
> > the components that are needed
> > +when constructing a unit test and some of the decisions that are made by
> > the test writer. We'll also describe
> > +how to check for expected conditions in test cases and a bit of the
> logging
> > characteristics.
> > +
> > +Most of these examples will refer to the SampleGoogleTestHost app found
> in
> > this package.
> > +
> > +### GoogleTest Requirements - INF
> > +
> > +In our INF file, we'll need to bring in the `GoogleTest` library.
> Conveniently,
> > the interface
> > +header for the `GoogleTest` is in `UnitTestFrameworkPkg`, so you
> shouldn't
> > need to depend on any other
> > +packages. As long as your DSC file knows where to find the lib
> > implementation that you want to use,
> > +you should be good to go.
> > +
> > +See this example in 'SampleGoogleTestHost.inf'...
> > +
> > +```
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> > +
> > +[LibraryClasses]
> > +  GoogleTestLib
> > +  BaseLib
> > +  DebugLib
> > +```
> > +
> > +Also, if you want you test to automatically be picked up by the Test
> Runner
> > plugin, you will need
> > +to make sure that the module `BASE_NAME` contains the word `Test`...
> > +
> > +```
> > +[Defines]
> > +  BASE_NAME      = SampleGoogleTestHost
> > +```
> > +
> > +### GoogleTest Requirements - Code
> > +
> > +Not to state the obvious, but let's make sure we have the following
> include
> > before getting too far along...
> > +
> > +```
> > +#include <gtest/gtest.h>
> > +extern "C" {
> > +  #include <Uefi.h>
> > +  #include <Library/BaseLib.h>
> > +  #include <Library/DebugLib.h>
> > +}
> > +```
> > +
> > +GoogleTest applications are implemented in C++. The first include brings
> in
> > the
> > +GoogleTest definitions. Other EDK II related include files must be
> wrapped in
> > +`extern "C" {}` because they are C include files. Link failures will
> occur if
> > +this is not done.
> > +
> > +Now that we've got that squared away, let's look at our 'Main()'' routine
> (or
> > DriverEntryPoint() or whatever).
> > +
> > +### GoogleTest Configuration
> > +
> > +Unlike the Framework, GoogleTest does not require test suites or test
> cases
> > to
> > +be registered. Instead, the test cases declare the test suite name and
> test
> > +case name as part of their implementation. The only requirement for
> > GoogleTest
> > +is to have a `main()` function that initialize the GoogleTest
> infrastructure and
> > +call the service `RUN_ALL_TESTS()` to run all the unit tests.
> > +
> > +```c
> > +int main(int argc, char* argv[]) {
> > +  testing::InitGoogleTest(&argc, argv);
> > +  return RUN_ALL_TESTS();
> > +}
> > +```
> > +
> > +### GoogleTest - A Simple Test Case
> > +
> > +We'll look at the below test case from 'SampleGoogleTestHost'...
> > +
> > +```c
> > +TEST(SimpleMathTests, OnePlusOneShouldEqualTwo) {
> > +  UINTN  A;
> > +  UINTN  B;
> > +  UINTN  C;
> > +
> > +  A = 1;
> > +  B = 1;
> > +  C = A + B;
> > +
> > +  ASSERT_EQ (C, 2);
> > +}
> > +```
> > +
> > +This uses the simplest form of a GoogleTest unit test using `TEST()` that
> > +declares the test suite name and the unit test name within that test
> suite.
> > +The unit test performs actions and typically makes calls to the code
> under
> > test
> > +and contains test assertions to verify that the code under test behaves
> as
> > +expected for the given inputs.
> > +
> > +In this test case, the `ASSERT_EQ` assertion is being used to establish
> that
> > the business logic has functioned
> > +correctly. There are several assertion macros, and you are encouraged to
> > use one that matches as closely to your
> > +intended test criterium as possible, because the logging is specific to
> the
> > macro and more specific macros have more
> > +detailed logs. When in doubt, there are always `ASSERT_TRUE` and
> > `ASSERT_FALSE`. Assertion macros that fail their
> > +test criterium will immediately return from the test case with a failed
> status
> > and log an error string.
> > +_Note_ that this early return can have implications for memory leakage.
> > +
> > +There is no return status from a GooglTest unit test. If no assertions
> are
> > +triggered then the unit test has a passing status.
> > +
> > +### GoogleTest - More Complex Cases
> > +
> > +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
> > @@ -243,11 +417,11 @@ stuart_ci_build -c .pytool/CISettings.py
> > TOOL_CHAIN_TAG=VS2017 -p MdePkg -t NOOP
> >
> >  ### Hooking BaseLib
> >
> > -Most unit test mocking can be performed by the functions provided in the
> > UnitTestFramework libraries, but since
> > +Most unit test mocking can be performed by the functions provided in the
> > UnitTestFrameworkPkg libraries, but since
> >  BaseLib is consumed by the Framework itself, it requires different
> techniques
> > to substitute parts of the
> >  functionality.
> >
> > -To solve some of this, the UnitTestFramework consumes a special
> > implementation of BaseLib for host-based tests.
> > +To solve some of this, the UnitTestFrameworkPkg consumes a special
> > implementation of BaseLib for host-based tests.
> >  This implementation contains a [hook
> > table](https://github.com/tianocore/edk2/blob/e188ecc8b4aed8fdd26b731d
> > 43883861f5e5e7b4/MdePkg/Test/UnitTest/Include/Library/UnitTestHostBase
> > Lib.h#L507)
> >  that can be used to substitute test functionality for any of the BaseLib
> > functions. By default, this implementation
> >  will use the underlying BaseLib implementation, so the unit test writer
> only
> > has to supply minimal code to test a
> > @@ -255,7 +429,7 @@ particular case.
> >
> >  ### Debugging the Framework Itself
> >
> > -While most of the tests that are produced by the UnitTestFramework are
> > easy to step through in a debugger, the Framework
> > +While most of the tests that are produced by the UnitTestFrameworkPkg are
> > easy to step through in a debugger, the Framework
> >  itself consumes code (mostly Cmocka) that sets its own build flags. These
> > flags cause parts of the Framework to not
> >  export symbols and captures exceptions, and as such are harder to debug.
> > We have provided a Stuart parameter to force
> >  symbolic debugging to be enabled.
> > @@ -269,15 +443,17 @@ stuart_ci_build -c .pytool/CISettings.py
> > TOOL_CHAIN_TAG=VS2019 -p MdePkg -t NOOP
> >  ## Building and Running Host-Based Tests
> >
> >  The EDK2 CI infrastructure provides a convenient way to run all
> host-based
> > tests -- in the the entire tree or just
> > -selected packages -- and aggregate all the the reports, including
> highlighting
> > any failures. This functionality is
> > -provided through the Stuart build system (published by EDK2-PyTools) and
> > the `NOOPT` build target.
> > +selected packages -- and aggregate all the reports, including
> highlighting any
> > failures. This functionality is
> > +provided through the Stuart build system (published by EDK2-PyTools) and
> > the `NOOPT` build target. The sections that
> > +follow use Framework examples. Unit tests based on GoogleTest are built
> > and run the same way. The text output and
> > +JUNIT XML output format have small differences.
> >
> >  ### Building Locally
> >
> >  First, to make sure you're working with the latest PyTools, run the
> following
> > command:
> >
> >  ```bash
> > -# Would recommend to run this in a Python venv, but that's out of scope
> for
> > this doc.
> > +# Would recommend running this in a Python venv, but that's out of scope
> for
> > this doc.
> >  python -m pip install --upgrade -r ./pip-requirements.txt
> >  ```
> >
> > @@ -361,7 +537,7 @@ RUNNING TEST SUITE: Int Safe Conversions Test
> > Suite
> >  ```
> >
> >  You can also, if you are so inclined, read the output from the exact
> instance
> > of the test that was run during
> > -`stuart_ci_build`. The ouput file can be found on a path that looks like:
> > +`stuart_ci_build`. The output file can be found on a path that looks
> like:
> >
> >
> > `Build/<Package>/HostTest/<Arch>/<TestName>.<TestSuiteName>.<Arch>.re
> > sult.xml`
> >
> > @@ -389,22 +565,30 @@
> > c:\_uefi\MdePkg\Test\UnitTest\Library\BaseSafeIntLib\TestBaseSafeIntLib.c:
> > 35: er
> >
> >  ### XML Reporting Mode
> >
> > -Since these applications are built using the CMocka framework, they can
> also
> > use the following env variables to output
> > -in a structured XML rather than text:
> > +Unit test applications using Framework are built using Cmocka that
> requires
> > the
> > +following environment variables to be set to generate structured XML
> output
> > +rather than text:
> >
> > -```text
> > +```
> >  CMOCKA_MESSAGE_OUTPUT=xml
> >  CMOCKA_XML_FILE=<absolute or relative path to output file>
> >  ```
> >
> > +Unit test applications using GoogleTest require the following environment
> > +variable to be set to generate structured XML output rather than text:
> > +
> > +```
> > +GTEST_OUTPUT=xml:<absolute or relative path to output file>
> > +```
> > +
> >  This mode is used by the test running plugin to aggregate the results for
> CI
> > test status reporting in the web view.
> >
> >  ### Important Note
> >
> > -This works on both Windows and Linux, but is currently limited to x64
> > architectures. Working on getting others, but we
> > +This works on both Windows and Linux but is currently limited to x64
> > architectures. Working on getting others, but we
> >  also welcome contributions.
> >
> > -## Known Limitations
> > +## Framework Known Limitations
> >
> >  ### PEI, DXE, SMM
> >
> > @@ -418,7 +602,7 @@ PEI, DXE, and SMM is forthcoming, but should be
> > considered beta/staging for now.
> >  The host-based test framework is powered internally by the Cmocka
> > framework. As such, it has abilities
> >  that the target-based tests don't (yet). It would be awesome if this
> meant
> > that it was a super set of
> >  the target-based tests, and it worked just like the target-based tests
> but
> > with more features. Unfortunately,
> > -this is not the case. While care has been taken to keep them as close a
> > possible, there are a few known
> > +this is not the case. While care has been taken to keep them as close as
> > possible, there are a few known
> >  inconsistencies that we're still ironing out. For example, the logging
> > messages in the target-based tests
> >  are cached internally and associated with the running test case. They can
> be
> > saved later as part of the
> >  reporting lib. This isn't currently possible with host-based. Only the
> assertion
> > failures are logged.
> > @@ -441,6 +625,9 @@ Non-Host-Based (PEI/DXE/SMM/Shell) Tests for a
> > Functionality or Feature   | Simi
> >    ComponentY/
> >      ComponentY.inf
> >      ComponentY.c
> > +    GoogleTest/
> > +      ComponentYHostGoogleTest.inf    # Host-Based Test for Driver
> > Module
> > +      ComponentYGoogleTest.cpp
> >      UnitTest/
> >        ComponentYHostUnitTest.inf      # Host-Based Test for Driver
> > Module
> >        ComponentYUnitTest.c
> > @@ -455,11 +642,23 @@ Non-Host-Based (PEI/DXE/SMM/Shell) Tests for a
> > Functionality or Feature   | Simi
> >      SpecificLibDxe/
> >        SpecificLibDxe.c
> >        SpecificLibDxe.inf
> > +      GoogleTest/                    # Host-Based Test for Specific
> > Library Implementation
> > +        SpecificLibDxeHostGoogleTest.cpp
> > +        SpecificLibDxeHostGoogleTest.inf
> >        UnitTest/                      # Host-Based Test for Specific
> > Library Implementation
> >          SpecificLibDxeHostUnitTest.c
> >          SpecificLibDxeHostUnitTest.inf
> >    Test/
> >      <Package>HostTest.dsc             # Host-Based Test Apps
> > +    GoogleTest/
> > +      InterfaceX
> > +        InterfaceXHostGoogleTest.inf  # Host-Based App (should be in
> > Test/<Package>HostTest.dsc)
> > +        InterfaceXUnitTest.cpp        # Test Logic
> > +
> > +      GeneralPurposeLib/              # Host-Based Test for any
> > implementation of GeneralPurposeLib
> > +        GeneralPurposeLibTest.cpp
> > +        GeneralPurposeLibHostUnitTest.inf
> > +
> >      UnitTest/
> >        InterfaceX
> >          InterfaceXHostUnitTest.inf    # Host-Based App (should be in
> > Test/<Package>HostTest.dsc)
> > diff --git
> > a/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> > eGoogleTest.cpp
> > b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> > eGoogleTest.cpp
> > new file mode 100644
> > index 000000000000..c83e58596a82
> > --- /dev/null
> > +++
> > b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> > eGoogleTest.cpp
> > @@ -0,0 +1,263 @@
> > +/** @file
> > +  This is a sample to demonstrates the use of GoogleTest that supports
> host
> > +  execution environments.
> > +
> > +  Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +  SPDX-License-Identifier: BSD-2-Clause-Patent
> > +
> > +**/
> > +
> > +#include <gtest/gtest.h>
> > +extern "C" {
> > +  #include <Uefi.h>
> > +  #include <Library/BaseLib.h>
> > +  #include <Library/DebugLib.h>
> > +}
> > +
> > +/**
> > +  Sample unit test that verifies the expected result of an unsigned
> integer
> > +  addition operation.
> > +**/
> > +TEST(SimpleMathTests, OnePlusOneShouldEqualTwo) {
> > +  UINTN  A;
> > +  UINTN  B;
> > +  UINTN  C;
> > +
> > +  A = 1;
> > +  B = 1;
> > +  C = A + B;
> > +
> > +  ASSERT_EQ (C, (UINTN)2);
> > +}
> > +
> > +/**
> > +  Sample unit test that verifies that a global BOOLEAN is updatable.
> > +**/
> > +class GlobalBooleanVarTests : public ::testing::Test {
> > +  public:
> > +    BOOLEAN  SampleGlobalTestBoolean  = FALSE;
> > +};
> > +
> > +TEST_F(GlobalBooleanVarTests, GlobalBooleanShouldBeChangeable) {
> > +  SampleGlobalTestBoolean = TRUE;
> > +  ASSERT_TRUE (SampleGlobalTestBoolean);
> > +
> > +  SampleGlobalTestBoolean = FALSE;
> > +  ASSERT_FALSE (SampleGlobalTestBoolean);
> > +}
> > +
> > +/**
> > +  Sample unit test that logs a warning message and verifies that a global
> > +  pointer is updatable.
> > +**/
> > +class GlobalVarTests : public ::testing::Test {
> > +  public:
> > +    VOID  *SampleGlobalTestPointer = NULL;
> > +
> > +  protected:
> > +  void SetUp() override {
> > +    ASSERT_EQ ((UINTN)SampleGlobalTestPointer, (UINTN)NULL);
> > +  }
> > +  void TearDown() {
> > +    SampleGlobalTestPointer = NULL;
> > +  }
> > +};
> > +
> > +TEST_F(GlobalVarTests, GlobalPointerShouldBeChangeable) {
> > +  SampleGlobalTestPointer = (VOID *)-1;
> > +  ASSERT_EQ ((UINTN)SampleGlobalTestPointer, (UINTN)((VOID *)-1));
> > +}
> > +
> > +
> > +/**
> > +  Set PcdDebugPropertyMask for each MacroTestsAssertsEnabledDisabled
> > test
> > +**/
> > +class MacroTestsAssertsEnabledDisabled : public
> > testing::TestWithParam<UINT8> {
> > +  void SetUp() {
> > +    PatchPcdSet8 (PcdDebugPropertyMask, GetParam());
> > +  }
> > +};
> > +
> > +/**
> > +  Sample unit test using the ASSERT_TRUE() macro.
> > +**/
> > +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertTrue) {
> > +  UINT64  Result;
> > +
> > +  //
> > +  // This test passes because expression always evaluated to TRUE.
> > +  //
> > +  ASSERT_TRUE (TRUE);
> > +
> > +  //
> > +  // This test passes because expression always evaluates to TRUE.
> > +  //
> > +  Result = LShiftU64 (BIT0, 1);
> > +  ASSERT_TRUE (Result == BIT1);
> > +}
> > +
> > +/**
> > +  Sample unit test using the ASSERT_FALSE() macro.
> > +**/
> > +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertFalse) {
> > +  UINT64  Result;
> > +
> > +  //
> > +  // This test passes because expression always evaluated to FALSE.
> > +  //
> > +  ASSERT_FALSE (FALSE);
> > +
> > +  //
> > +  // This test passes because expression always evaluates to FALSE.
> > +  //
> > +  Result = LShiftU64 (BIT0, 1);
> > +  ASSERT_FALSE (Result == BIT0);
> > +}
> > +
> > +/**
> > +  Sample unit test using the ASSERT_EQ() macro.
> > +**/
> > +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertEqual) {
> > +  UINT64  Result;
> > +
> > +  //
> > +  // This test passes because both values are always equal.
> > +  //
> > +  ASSERT_EQ (1, 1);
> > +
> > +  //
> > +  // This test passes because both values are always equal.
> > +  //
> > +  Result = LShiftU64 (BIT0, 1);
> > +  ASSERT_EQ (Result, (UINT64)BIT1);
> > +}
> > +
> > +/**
> > +  Sample unit test using the ASSERT_STREQ() macro.
> > +**/
> > +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertMemEqual) {
> > +  CHAR8  *String1;
> > +  CHAR8  *String2;
> > +
> > +  //
> > +  // This test passes because String1 and String2 are the same.
> > +  //
> > +  String1 = (CHAR8 *)"Hello";
> > +  String2 = (CHAR8 *)"Hello";
> > +  ASSERT_STREQ (String1, String2);
> > +}
> > +
> > +/**
> > +  Sample unit test using the ASSERT_NE() macro.
> > +**/
> > +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertNotEqual) {
> > +  UINT64  Result;
> > +
> > +  //
> > +  // This test passes because both values are never equal.
> > +  //
> > +  ASSERT_NE (0, 1);
> > +
> > +  //
> > +  // This test passes because both values are never equal.
> > +  //
> > +  Result = LShiftU64 (BIT0, 1);
> > +  ASSERT_NE (Result, (UINT64)BIT0);
> > +}
> > +
> > +/**
> > +  Sample unit test using the ASSERT_TRUE() and ASSERT(FALSE)
> > +  and EFI_EFFOR() macros to check status
> > +**/
> > +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertNotEfiError) {
> > +  //
> > +  // This test passes because the status is not an EFI error.
> > +  //
> > +  ASSERT_FALSE (EFI_ERROR (EFI_SUCCESS));
> > +
> > +  //
> > +  // This test passes because the status is not an EFI error.
> > +  //
> > +  ASSERT_FALSE (EFI_ERROR (EFI_WARN_BUFFER_TOO_SMALL));
> > +}
> > +
> > +/**
> > +  Sample unit test using the ASSERT_EQ() macro to compare EFI_STATUS
> > values.
> > +**/
> > +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertStatusEqual) {
> > +  //
> > +  // This test passes because the status value are always equal.
> > +  //
> > +  ASSERT_EQ (EFI_SUCCESS, EFI_SUCCESS);
> > +}
> > +
> > +/**
> > +  Sample unit test using ASSERT_NE() macro to make sure a pointer is not
> > NULL.
> > +**/
> > +TEST_P(MacroTestsAssertsEnabledDisabled, MacroAssertNotNull) {
> > +  UINT64  Result;
> > +
> > +  //
> > +  // This test passes because the pointer is never NULL.
> > +  //
> > +  ASSERT_NE (&Result, (UINT64 *)NULL);
> > +}
> > +
> > +/**
> > +  Sample unit test using that should not generate any ASSERTs()
> > +**/
> > +TEST_P(MacroTestsAssertsEnabledDisabled, MacroExpectNoAssertFailure) {
> > +  //
> > +  // This test passes because it never triggers an ASSERT().
> > +  //
> > +  ASSERT (TRUE);
> > +
> > +  //
> > +  // This test passes because DecimalToBcd() does not ASSERT() if the
> > +  // value passed in is <= 99.
> > +  //
> > +  DecimalToBcd8 (99);
> > +}
> > +
> > +/**
> > +  Sample unit test using the ASSERT_DEATH() macro to test expected
> > ASSERT()s.
> > +**/
> > +TEST_P(MacroTestsAssertsEnabledDisabled, MacroExpectAssertFailure) {
> > +  //
> > +  // Skip tests that verify an ASSERT() is triggered if ASSERT()s are
> disabled.
> > +  //
> > +  if ((PcdGet8 (PcdDebugPropertyMask) & BIT0) == 0x00) {
> > +    return;
> > +  }
> > +
> > +  //
> > +  // This test passes because it directly triggers an ASSERT().
> > +  //
> > +  ASSERT_DEATH (ASSERT (FALSE), "");
> > +
> > +  //
> > +  // This test passes because DecimalToBcd() generates an ASSERT() if the
> > +  // value passed in is >= 100.  The expected ASSERT() is caught by the
> unit
> > +  // test framework and ASSERT_DEATH() returns without an error.
> > +  //
> > +  ASSERT_DEATH (DecimalToBcd8 (101), "");
> > +}
> > +
> > +INSTANTIATE_TEST_SUITE_P(ValidInput,
> > +                         MacroTestsAssertsEnabledDisabled,
> > +                         ::testing::Values(PcdGet8
> > (PcdDebugPropertyMask) | BIT0, PcdGet8 (PcdDebugPropertyMask) &
> > (~BIT0)));
> > +
> > +/**
> > +  Sample unit test using the SCOPED_TRACE() macro for trace messages.
> > +**/
> > +TEST(MacroTestsMessages, MacroTraceMessage) {
> > +  //
> > +  // Example of logging.
> > +  //
> > +  SCOPED_TRACE ("SCOPED_TRACE message\n");
> > +}
> > +
> > +int main(int argc, char* argv[]) {
> > +  testing::InitGoogleTest(&argc, argv);
> > +  return RUN_ALL_TESTS();
> > +}
> > diff --git
> > a/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> > eGoogleTestHost.inf
> > b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> > eGoogleTestHost.inf
> > new file mode 100644
> > index 000000000000..37e7c86910ed
> > --- /dev/null
> > +++
> > b/UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/Sampl
> > eGoogleTestHost.inf
> > @@ -0,0 +1,35 @@
> > +## @file
> > +# This is a sample to demonstrates the use of GoogleTest that supports
> host
> > +# execution environments.
> > +#
> > +# Copyright (c) 2022, Intel Corporation. All rights reserved.<BR>
> > +# SPDX-License-Identifier: BSD-2-Clause-Patent
> > +##
> > +
> > +[Defines]
> > +  INF_VERSION    = 0x00010005
> > +  BASE_NAME      = SampleGoogleTestHost
> > +  FILE_GUID      = 7D8BBFBB-7977-4AEE-A59F-257BF5C2F87C
> > +  MODULE_TYPE    = HOST_APPLICATION
> > +  VERSION_STRING = 1.0
> > +
> > +#
> > +# The following information is for reference only and not required by the
> > build tools.
> > +#
> > +#  VALID_ARCHITECTURES           = IA32 X64
> > +#
> > +
> > +[Sources]
> > +  SampleGoogleTest.cpp
> > +
> > +[Packages]
> > +  MdePkg/MdePkg.dec
> > +  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> > +
> > +[LibraryClasses]
> > +  GoogleTestLib
> > +  BaseLib
> > +  DebugLib
> > +
> > +[Pcd]
> > +  gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask
> > diff --git a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> > b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> > index 184fdec87acf..708ef7f9ab35 100644
> > --- a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> > +++ b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> > @@ -23,14 +23,16 @@ [PcdsPatchableInModule]
> >
> >  [Components]
> >    #
> > -  # Build HOST_APPLICATION that tests the SampleUnitTest
> > +  # Build HOST_APPLICATIONs that test the SampleUnitTest
> >    #
> >
> > UnitTestFrameworkPkg/Test/UnitTest/Sample/SampleUnitTest/SampleUnitTe
> > stHost.inf
> > +
> > UnitTestFrameworkPkg/Test/GoogleTest/Sample/SampleGoogleTest/SampleG
> > oogleTestHost.inf
> >
> >    #
> >    # Build HOST_APPLICATION Libraries
> >    #
> >    UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
> > +  UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> >    UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf
> >
> > UnitTestFrameworkPkg/Library/Posix/MemoryAllocationLibPosix/MemoryAllo
> > cationLibPosix.inf
> >    UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.inf
> > diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
> > b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
> > index 77d51e13484c..072df6208c92 100644
> > --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
> > +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
> > @@ -78,7 +78,8 @@
> >      "SpellCheck": {
> >          "AuditOnly": False,           # Fails test but run in AuditOnly
> > mode to collect log
> >          "IgnoreFiles": [             # use gitignore syntax to ignore
> > errors in matching files
> > -            "Library/CmockaLib/cmocka/**/*.*"  # not going to spell
> > check a submodule
> > +            "Library/CmockaLib/cmocka/**/*.*",  # not going to spell
> > check a submodule
> > +            "Library/GoogleTestLib/googletest/**/*.*"  # not going to
> > spell check a submodule
> >          ],
> >          "ExtendWords": [             # words to extend to the
> > dictionary for this package
> >              "testcase",
> > @@ -91,6 +92,7 @@
> >              "NOFAILURE",
> >              "cmockery",
> >              "DHAVE", # build flag for cmocka in the INF
> > +            "gtest", # file name in GoogleTestLib.inf
> >              "corthon",      # Contact GitHub account in Readme
> >              "mdkinney",     # Contact GitHub account in Readme
> >              "spbrogan"      # Contact GitHub account in Readme
> > diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> > b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> > index 069289f00969..ed12f32009d8 100644
> > --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> > +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> > @@ -16,11 +16,15 @@ [Defines]
> >    PACKAGE_VERSION   = 1.00
> >
> >  [Includes]
> > +  Include
> >    Library/CmockaLib/cmocka/include
> > +  Library/GoogleTestLib/googletest/googletest/include
> > +  Library/GoogleTestLib/googletest/googlemock/include
> >
> >  [Includes.Common.Private]
> >    PrivateInclude
> >    Library/CmockaLib/cmocka/include/cmockery
> > +  Library/GoogleTestLib/googletest/googletest
> >
> >  [LibraryClasses.Common.Private]
> >    ## @libraryclass Allows save and restore unit test internal state
> > @@ -35,6 +39,10 @@ [LibraryClasses.Common.Private]
> >    #
> >    UnitTestBootLib|PrivateInclude/Library/UnitTestBootLib.h
> >
> > +  ## @libraryclass GoogleTest infrastructure
> > +  #
> > +  GoogleTestLib|Include/Library/GoogleTestLib.h
> > +
> >  [Guids]
> >    gUnitTestFrameworkPkgTokenSpaceGuid = { 0x833d3aba, 0x39b4, 0x43a2,
> > { 0xb9, 0x30, 0x7a, 0x34, 0x53, 0x39, 0x31, 0xb3 } }
> >
> > diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> > b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> > index f249813713a8..6d5f651f689f 100644
> > --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> > +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> > @@ -14,6 +14,7 @@ [LibraryClasses.common.HOST_APPLICATION]
> >    CpuLib|MdePkg/Library/BaseCpuLibNull/BaseCpuLibNull.inf
> >
> > CacheMaintenanceLib|MdePkg/Library/BaseCacheMaintenanceLibNull/Base
> > CacheMaintenanceLibNull.inf
> >    CmockaLib|UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
> > +
> > GoogleTestLib|UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.i
> > nf
> >
> > UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.i
> > nf
> >
> > DebugLib|UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosi
> > x.inf
> >
> > MemoryAllocationLib|UnitTestFrameworkPkg/Library/Posix/MemoryAllocatio
> > nLibPosix/MemoryAllocationLibPosix.inf
> > @@ -30,6 +31,7 @@ [BuildOptions.common.EDKII.HOST_APPLICATION]
> >    #
> >    # MSFT
> >    #
> > +  MSFT:*_*_*_CC_FLAGS               = /EHsc
> >    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
> > /NODEFAULTLIB:libcmt.lib libcmtd.lib
> >    MSFT:*_*_IA32_DLINK_FLAGS         = /MACHINE:I386
> >    MSFT:*_*_X64_DLINK_FLAGS          = /MACHINE:AMD64
> > @@ -49,7 +51,7 @@ [BuildOptions.common.EDKII.HOST_APPLICATION]
> >    #
> >    GCC:*_*_IA32_DLINK_FLAGS == -o $(BIN_DIR)/$(MODULE_NAME_GUID)
> > -m32 -no-pie
> >    GCC:*_*_X64_DLINK_FLAGS  == -o
> > $(BIN_DIR)/$(MODULE_NAME_GUID) -m64 -no-pie
> > -  GCC:*_*_*_DLINK2_FLAGS   == -lgcov
> > +  GCC:*_*_*_DLINK2_FLAGS   == -lgcov -lpthread -lstdc++ -lm
> >
> >    #
> >    # Need to do this link via gcc and not ld as the pathing to libraries
> changes
> > from OS version to OS version
> > --
> > 2.37.1.windows.1
> >
> >
> >
> > 
> >
> >
> >
> 
> 
> 


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2022-11-08 23:03 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-11-04 20:25 [Patch V2 0/7] Add GoogleTest to UnitTestFrameworkPkg Michael D Kinney
2022-11-04 20:25 ` [Patch V2 1/7] MdePkg/Include: Update Base.h to improve C++ compatibility Michael D Kinney
2022-11-08  6:59   ` 回复: " gaoliming
2022-11-04 20:25 ` [Patch V2 2/7] MdePkg/Include/Library: Undefine _ASSERT() if already defined Michael D Kinney
2022-11-08  6:59   ` 回复: " gaoliming
2022-11-04 20:25 ` [Patch V2 3/7] UnitTestFrameworkPkg: Add googletest submodule and GoogleTestLib Michael D Kinney
2022-11-08  7:47   ` 回复: [edk2-devel] " gaoliming
2022-11-08 23:03     ` Michael D Kinney
2022-11-04 20:25 ` [Patch V2 4/7] UnitTestFrameworkPkg/Library/CmockaLib: Enable symbol files Michael D Kinney
2022-11-04 20:25 ` [Patch V2 5/7] .pytool: Add googletest submodule to CISettings.py Michael D Kinney
2022-11-04 20:25 ` [Patch V2 6/7] BaseTools/Plugin/HostBaseUnitTestRunner: Enable gtest xml output Michael D Kinney
2022-11-04 20:25 ` [Patch V2 7/7] MdePkg/Test: Add port of BaseSafeIntLib unit tests to GoogleTest Michael D Kinney
2022-11-08  6:59   ` 回复: [edk2-devel] " gaoliming

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox