[edk2-devel] [Patch v2 03/12] UnitTestFrameworkPkg: Add gmock support to GoogleTestLib

Michael D Kinney posted 12 patches 2 years, 10 months ago
There is a newer version of this series
[edk2-devel] [Patch v2 03/12] UnitTestFrameworkPkg: Add gmock support to GoogleTestLib
Posted by Michael D Kinney 2 years, 10 months ago
From: Chris Johnson <chris.n.johnson@intel.com>

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

* Add gmock support to GoogleTestLib
* Add FunctionMockLib library class and library instance
* Add GoogleTest extension to GoogleTestLib.h for CHAR16 type
* Add GoogleTest extension to GoogleTestLib.h for buffer types
* HOST_APPLICATION only supports IA32/X64

Cc: Sean Brogan <sean.brogan@microsoft.com>
Cc: Michael Kubacki <mikuback@linux.microsoft.com>
Cc: Michael D Kinney <michael.d.kinney@intel.com>
Signed-off-by: Chris Johnson <chris.n.johnson@intel.com>
---
 .../Include/Library/FunctionMockLib.h         | 131 ++++++++++++++++++
 .../Include/Library/GoogleTestLib.h           |  96 +++++++++++++
 .../Library/CmockaLib/CmockaLib.inf           |   2 +-
 .../Library/FunctionMockLib/FunctionMockLib.c |   7 +
 .../FunctionMockLib/FunctionMockLib.inf       |  31 +++++
 .../FunctionMockLib/FunctionMockLib.uni       |  11 ++
 .../Library/GoogleTestLib/GoogleTestLib.inf   |   6 +-
 .../Library/GoogleTestLib/GoogleTestLib.uni   |   3 -
 .../Test/UnitTestFrameworkPkgHostTest.dsc     |   1 +
 .../UnitTestFrameworkPkg.ci.yaml              |   7 +-
 UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec |   2 +
 .../UnitTestFrameworkPkgHost.dsc.inc          |   1 +
 12 files changed, 291 insertions(+), 7 deletions(-)
 create mode 100644 UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h
 create mode 100644 UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.c
 create mode 100644 UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf
 create mode 100644 UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.uni

diff --git a/UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h b/UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h
new file mode 100644
index 000000000000..bf7a7066560a
--- /dev/null
+++ b/UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h
@@ -0,0 +1,131 @@
+/** @file
+  This header allows the mocking of free (C style) functions using gmock.
+
+  Copyright (c) 2023, Intel Corporation. All rights reserved.
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+**/
+
+#ifndef FUNCTION_MOCK_LIB_H_
+#define FUNCTION_MOCK_LIB_H_
+
+#include <Library/GoogleTestLib.h>
+#include <Library/SubhookLib.h>
+#include <type_traits>
+
+//////////////////////////////////////////////////////////////////////////////
+// The below macros are the public function mock interface that are intended
+// to be used outside this file.
+
+#define MOCK_INTERFACE_DECLARATION(MOCK) \
+  static MOCK * Instance;                \
+  MOCK ();                               \
+  ~MOCK ();
+
+#define MOCK_INTERFACE_DEFINITION(MOCK)   \
+  MOCK_STATIC_INSTANCE_DEFINITION (MOCK)  \
+  MOCK_INTERFACE_CONSTRUCTOR (MOCK)       \
+  MOCK_INTERFACE_DECONSTRUCTOR (MOCK)
+
+// Mock function declaration for external functions (i.e. functions to
+// mock that do not exist in the compilation unit).
+#define MOCK_FUNCTION_DECLARATION(RET_TYPE, FUNC, ARGS)  \
+  MOCK_FUNCTION_TYPE_DEFINITIONS(RET_TYPE, FUNC, ARGS)   \
+  MOCK_METHOD (RET_TYPE, FUNC, ARGS);
+
+// Mock function definition for external functions (i.e. functions to
+// mock that do not exist in the compilation unit).
+#define MOCK_FUNCTION_DEFINITION(MOCK, FUNC, NUM_ARGS, CALL_TYPE)         \
+  FUNCTION_DEFINITION_TO_CALL_MOCK(MOCK, FUNC, FUNC, NUM_ARGS, CALL_TYPE)
+
+// Mock function declaration for internal functions (i.e. functions to
+// mock that already exist in the compilation unit).
+#define MOCK_FUNCTION_INTERNAL_DECLARATION(RET_TYPE, FUNC, ARGS) \
+  MOCK_FUNCTION_DECLARATION(RET_TYPE, FUNC, ARGS)                \
+  MOCK_FUNCTION_HOOK_DECLARATIONS(FUNC)
+
+// Mock function definition for internal functions (i.e. functions to
+// mock that already exist in the compilation unit). This definition also
+// implements MOCK_FUNC() which is later hooked as FUNC().
+#define MOCK_FUNCTION_INTERNAL_DEFINITION(MOCK, FUNC, NUM_ARGS, CALL_TYPE)         \
+  FUNCTION_DEFINITION_TO_CALL_MOCK(MOCK, FUNC, MOCK##_##FUNC, NUM_ARGS, CALL_TYPE) \
+  MOCK_FUNCTION_HOOK_DEFINITIONS(MOCK, FUNC)
+
+//////////////////////////////////////////////////////////////////////////////
+// The below macros are private and should not be used outside this file.
+
+#define MOCK_FUNCTION_HOOK_DECLARATIONS(FUNC)     \
+  static subhook::Hook Hook##FUNC;                \
+  struct MockContainer_##FUNC {                   \
+    MockContainer_##FUNC ();                      \
+    ~MockContainer_##FUNC ();                     \
+  };                                              \
+  MockContainer_##FUNC MockContainerInst_##FUNC;
+
+// This definition implements a constructor and destructor inside a nested
+// class to enable automatic installation of the hooks to the associated
+// MOCK_FUNC() when the mock object is instantiated in scope and automatic
+// removal when the instantiated mock object goes out of scope.
+#define MOCK_FUNCTION_HOOK_DEFINITIONS(MOCK, FUNC)                        \
+  subhook :: Hook MOCK :: Hook##FUNC;                                     \
+  MOCK :: MockContainer_##FUNC :: MockContainer_##FUNC () {               \
+    if (MOCK :: Instance == NULL)                                         \
+      MOCK :: Hook##FUNC .Install(                                        \
+        (FUNC##_ret_type *) ::FUNC,                                       \
+        (FUNC##_ret_type *) MOCK##_##FUNC);                               \
+  }                                                                       \
+  MOCK :: MockContainer_##FUNC :: ~MockContainer_##FUNC () {              \
+      MOCK :: Hook##FUNC .Remove();                                       \
+  }                                                                       \
+  static_assert(                                                          \
+    std::is_same<decltype(&::FUNC), decltype(&MOCK##_##FUNC)>::value,     \
+    "Function signature from 'MOCK_FUNCTION_INTERNAL_DEFINITION' macro "  \
+    "invocation for '" #FUNC "' does not match the function signature "   \
+    "of '" #FUNC "' function it is mocking. Mismatch could be due to "    \
+    "different return type, arguments, or calling convention. See "       \
+    "associated 'MOCK_FUNCTION_INTERNAL_DECLARATION' macro invocation "   \
+    "for more details.");
+
+#define MOCK_FUNCTION_TYPE_DEFINITIONS(RET_TYPE, FUNC, ARGS)  \
+  using FUNC##_ret_type = RET_TYPE;                           \
+  using FUNC##_type = FUNC##_ret_type ARGS;
+
+// This function definition simply calls MOCK::Instance->FUNC() which is the
+// mocked counterpart of the original function. This allows using gmock with
+// C free functions (since by default gmock only works with object methods).
+#define FUNCTION_DEFINITION_TO_CALL_MOCK(MOCK, FUNC, FUNC_DEF_NAME, NUM_ARGS, CALL_TYPE) \
+  extern "C" {                                                                           \
+    typename MOCK :: FUNC##_ret_type CALL_TYPE FUNC_DEF_NAME(                            \
+      GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER,                                          \
+                      (MOCK :: FUNC##_type),                                             \
+                      NUM_ARGS))                                                         \
+    {                                                                                    \
+      EXPECT_TRUE(MOCK :: Instance != NULL)                                              \
+        << "Called '" #FUNC "' in '" #MOCK "' function mock object before "              \
+        << "an instance of '" #MOCK "' was created in test '"                            \
+        << ::testing::UnitTest::GetInstance()->current_test_info()->name()               \
+        << "'.";                                                                         \
+      return MOCK :: Instance->FUNC(                                                     \
+        GMOCK_PP_REPEAT(GMOCK_INTERNAL_FORWARD_ARG,                                      \
+                        (MOCK :: FUNC##_type),                                           \
+                        NUM_ARGS));                                                      \
+    }                                                                                    \
+  }
+
+#define MOCK_STATIC_INSTANCE_DEFINITION(MOCK)  MOCK * MOCK :: Instance = NULL;
+
+#define MOCK_INTERFACE_CONSTRUCTOR(MOCK)                                     \
+  MOCK :: MOCK () {                                                          \
+    EXPECT_TRUE(MOCK :: Instance == NULL)                                    \
+      << "Multiple instances of '" #MOCK "' function mock object were "      \
+      << "created and only one instance is allowed in test '"                \
+      << ::testing::UnitTest::GetInstance()->current_test_info()->name()     \
+      << "'.";                                                               \
+    MOCK :: Instance = this;                                                 \
+  }
+
+#define MOCK_INTERFACE_DECONSTRUCTOR(MOCK) \
+  MOCK :: ~ MOCK () {                      \
+    MOCK :: Instance = NULL;               \
+  }
+
+#endif // FUNCTION_MOCK_LIB_H_
diff --git a/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h b/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
index ebec766d4cf7..c0a3d8e66011 100644
--- a/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
+++ b/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
@@ -10,5 +10,101 @@
 #define GOOGLE_TEST_LIB_H_
 
 #include <gtest/gtest.h>
+#include <gmock/gmock.h>
+#include <cstring>
+
+extern "C" {
+#include <Uefi.h>
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Below are the action extensions to GoogleTest and gmock for EDK2 types.
+// These actions are intended to be used in EXPECT_CALL (and related gmock
+// macros) to support assignments to output arguments in the expected call.
+//
+
+// Action to support pointer types to a buffer (such as UINT8* or VOID*)
+ACTION_TEMPLATE (
+  SetArgBuffer,
+  HAS_1_TEMPLATE_PARAMS (size_t, ArgNum),
+  AND_2_VALUE_PARAMS (Buffer, ByteSize)
+  ) {
+  auto  ArgBuffer = std::get<ArgNum>(args);
+
+  std::memcpy (ArgBuffer, Buffer, ByteSize);
+}
+
+//////////////////////////////////////////////////////////////////////////////
+// Below are the matcher extensions to GoogleTest and gmock for EDK2 types.
+// These matchers are intended to be used in EXPECT_CALL (and related gmock
+// macros) to support comparisons to input arguments in the expected call.
+//
+// Note that these matchers can also be used in the EXPECT_THAT or ASSERT_THAT
+// macros to compare whether two values are equal.
+//
+
+// Matcher to support pointer types to a buffer (such as UINT8* or VOID* or
+// any structure pointer)
+MATCHER_P2 (
+  BufferEq,
+  Buffer,
+  ByteSize,
+  std::string ("buffer data to ") + (negation ? "not " : "") + "be the same"
+  ) {
+  UINT8  *Actual   = (UINT8 *)arg;
+  UINT8  *Expected = (UINT8 *)Buffer;
+
+  for (size_t i = 0; i < ByteSize; i++) {
+    if (Actual[i] != Expected[i]) {
+      *result_listener << "byte at offset " << i
+      << " does not match expected. [" << std::hex
+      << "Actual: 0x" << std::setw (2) << std::setfill ('0')
+      << (unsigned int)Actual[i] << ", "
+      << "Expected: 0x" << std::setw (2) << std::setfill ('0')
+      << (unsigned int)Expected[i] << "]";
+      return false;
+    }
+  }
+
+  *result_listener << "all bytes match";
+  return true;
+}
+
+// Matcher to support CHAR16* type
+MATCHER_P (
+  Char16StrEq,
+  String,
+  std::string ("strings to ") + (negation ? "not " : "") + "be the same"
+  ) {
+  CHAR16  *Actual   = (CHAR16 *)arg;
+  CHAR16  *Expected = (CHAR16 *)String;
+
+  for (size_t i = 0; Actual[i] != 0; i++) {
+    if (Actual[i] != Expected[i]) {
+      *result_listener << "character at offset " << i
+      << " does not match expected. [" << std::hex
+      << "Actual: 0x" << std::setw (4) << std::setfill ('0')
+      << Actual[i];
+
+      if (std::isprint (Actual[i])) {
+        *result_listener << " ('" << (char)Actual[i] << "')";
+      }
+
+      *result_listener << ", Expected: 0x" << std::setw (4) << std::setfill ('0')
+      << Expected[i];
+
+      if (std::isprint (Expected[i])) {
+        *result_listener << " ('" << (char)Expected[i] << "')";
+      }
+
+      *result_listener << "]";
+
+      return false;
+    }
+  }
+
+  *result_listener << "strings match";
+  return true;
+}
 
 #endif
diff --git a/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf b/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
index 052c7f557210..eeee6bc2b3f5 100644
--- a/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
+++ b/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
@@ -16,7 +16,7 @@ [Defines]
   LIBRARY_CLASS   = CmockaLib|HOST_APPLICATION
 
 #
-#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
+#  VALID_ARCHITECTURES           = IA32 X64
 #
 
 [Sources]
diff --git a/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.c b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.c
new file mode 100644
index 000000000000..b7bb23f1868b
--- /dev/null
+++ b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.c
@@ -0,0 +1,7 @@
+/** @file
+  Macro-only FunctionMockLib library instance with no services.
+
+  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+  SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
diff --git a/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf
new file mode 100644
index 000000000000..4b0662a8b96d
--- /dev/null
+++ b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf
@@ -0,0 +1,31 @@
+## @file
+#  This module provides FunctionMockLib Library implementation.
+#
+#  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+#  SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+##
+
+[Defines]
+  INF_VERSION     = 0x00010005
+  BASE_NAME       = FunctionMockLib
+  MODULE_UNI_FILE = FunctionMockLib.uni
+  FILE_GUID       = DF1CAF2F-D584-4EC1-9ABF-07E8B10AD560
+  MODULE_TYPE     = BASE
+  VERSION_STRING  = 0.1
+  LIBRARY_CLASS   = FunctionMockLib|HOST_APPLICATION
+
+#
+#  VALID_ARCHITECTURES           = IA32 X64
+#
+
+[Sources]
+  FunctionMockLib.c
+
+[LibraryClasses]
+  GoogleTestLib
+  SubhookLib
+
+[Packages]
+  MdePkg/MdePkg.dec
+  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
diff --git a/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.uni b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.uni
new file mode 100644
index 000000000000..13e5308ce0e7
--- /dev/null
+++ b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.uni
@@ -0,0 +1,11 @@
+// /** @file
+// This module provides FunctionMockLib Library implementation.
+//
+// Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+#string STR_MODULE_ABSTRACT             #language en-US "FunctionMockLib Library implementation"
+
+#string STR_MODULE_DESCRIPTION          #language en-US "This module provides FunctionMockLib Library implementation."
diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
index 68db75d7023f..1203a0e6eccd 100644
--- a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
+++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
@@ -16,20 +16,22 @@ [Defines]
   LIBRARY_CLASS   = GoogleTestLib|HOST_APPLICATION
 
 #
-#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
+#  VALID_ARCHITECTURES           = IA32 X64
 #
 
 [Sources]
   googletest/googletest/src/gtest-all.cc
+  googletest/googlemock/src/gmock-all.cc
 
 [Packages]
+  MdePkg/MdePkg.dec
   UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
 
 [BuildOptions]
   MSFT:*_*_*_CC_FLAGS     == /c /EHsc /Zi
   MSFT:NOOPT_*_*_CC_FLAGS =  /Od
 
-  GCC:*_*_*_CC_FLAGS     == -g -c
+  GCC:*_*_*_CC_FLAGS     == -g -c -fshort-wchar
 
   GCC:NOOPT_*_*_CC_FLAGS =  -O0
   GCC:*_*_IA32_CC_FLAGS  =  -m32
diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
index 14c862a23744..695588ce3f46 100644
--- a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
+++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
@@ -1,10 +1,7 @@
 // /** @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
 //
 // **/
diff --git a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
index 722509c8f26f..f14961ad86d0 100644
--- a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
+++ b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
@@ -34,6 +34,7 @@ [Components]
   UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
   UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
   UnitTestFrameworkPkg/Library/SubhookLib/SubhookLib.inf
+  UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.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 d8f8e024c476..be839d1af0a7 100644
--- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
+++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
@@ -79,9 +79,14 @@
         "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/GoogleTestLib/googletest/**/*.*"  # not going to spell check a submodule
+            "Library/GoogleTestLib/googletest/**/*.*",  # not going to spell check a submodule
+            "Library/SubhookLib/subhook/**/*.*"  # not going to spell check a submodule
         ],
         "ExtendWords": [             # words to extend to the dictionary for this package
+            "Pointee",
+            "gmock",
+            "GMOCK",
+            "DSUBHOOK",
             "testcase",
             "testsuites",
             "cmocka",
diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
index 30b489915d4a..ef0a148d4876 100644
--- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
+++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
@@ -26,6 +26,7 @@ [Includes.Common.Private]
   PrivateInclude
   Library/CmockaLib/cmocka/include/cmockery
   Library/GoogleTestLib/googletest/googletest
+  Library/GoogleTestLib/googletest/googlemock
 
 [LibraryClasses]
   ## @libraryclass Allows save and restore unit test internal state
@@ -36,6 +37,7 @@ [LibraryClasses]
   #
   GoogleTestLib|Include/Library/GoogleTestLib.h
   SubhookLib|Include/Library/SubhookLib.h
+  FunctionMockLib|Include/Library/FunctionMockLib.h
 
 [LibraryClasses.Common.Private]
   ## @libraryclass Provides a unit test result report
diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
index e77897bd326f..7866c36e6693 100644
--- a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
+++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
@@ -16,6 +16,7 @@ [LibraryClasses.common.HOST_APPLICATION]
   CmockaLib|UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
   GoogleTestLib|UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
   SubhookLib|UnitTestFrameworkPkg/Library/SubhookLib/SubhookLib.inf
+  FunctionMockLib|UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf
   UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.inf
   DebugLib|UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf
   MemoryAllocationLib|UnitTestFrameworkPkg/Library/Posix/MemoryAllocationLibPosix/MemoryAllocationLibPosix.inf
-- 
2.39.1.windows.1



-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#102521): https://edk2.groups.io/g/devel/message/102521
Mute This Topic: https://groups.io/mt/98066295/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/leave/3901457/1787277/102458076/xyzzy [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-
Re: [edk2-devel] [Patch v2 03/12] UnitTestFrameworkPkg: Add gmock support to GoogleTestLib
Posted by Michael Kubacki 2 years, 10 months ago
Reviewed-by: Michael Kubacki <michael.kubacki@microsoft.com>

On 4/4/2023 2:22 PM, Michael D Kinney wrote:
> From: Chris Johnson <chris.n.johnson@intel.com>
> 
> REF: https://bugzilla.tianocore.org/show_bug.cgi?id=4389
> 
> * Add gmock support to GoogleTestLib
> * Add FunctionMockLib library class and library instance
> * Add GoogleTest extension to GoogleTestLib.h for CHAR16 type
> * Add GoogleTest extension to GoogleTestLib.h for buffer types
> * HOST_APPLICATION only supports IA32/X64
> 
> Cc: Sean Brogan <sean.brogan@microsoft.com>
> Cc: Michael Kubacki <mikuback@linux.microsoft.com>
> Cc: Michael D Kinney <michael.d.kinney@intel.com>
> Signed-off-by: Chris Johnson <chris.n.johnson@intel.com>
> ---
>   .../Include/Library/FunctionMockLib.h         | 131 ++++++++++++++++++
>   .../Include/Library/GoogleTestLib.h           |  96 +++++++++++++
>   .../Library/CmockaLib/CmockaLib.inf           |   2 +-
>   .../Library/FunctionMockLib/FunctionMockLib.c |   7 +
>   .../FunctionMockLib/FunctionMockLib.inf       |  31 +++++
>   .../FunctionMockLib/FunctionMockLib.uni       |  11 ++
>   .../Library/GoogleTestLib/GoogleTestLib.inf   |   6 +-
>   .../Library/GoogleTestLib/GoogleTestLib.uni   |   3 -
>   .../Test/UnitTestFrameworkPkgHostTest.dsc     |   1 +
>   .../UnitTestFrameworkPkg.ci.yaml              |   7 +-
>   UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec |   2 +
>   .../UnitTestFrameworkPkgHost.dsc.inc          |   1 +
>   12 files changed, 291 insertions(+), 7 deletions(-)
>   create mode 100644 UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h
>   create mode 100644 UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.c
>   create mode 100644 UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf
>   create mode 100644 UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.uni
> 
> diff --git a/UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h b/UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h
> new file mode 100644
> index 000000000000..bf7a7066560a
> --- /dev/null
> +++ b/UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h
> @@ -0,0 +1,131 @@
> +/** @file
> +  This header allows the mocking of free (C style) functions using gmock.
> +
> +  Copyright (c) 2023, Intel Corporation. All rights reserved.
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +**/
> +
> +#ifndef FUNCTION_MOCK_LIB_H_
> +#define FUNCTION_MOCK_LIB_H_
> +
> +#include <Library/GoogleTestLib.h>
> +#include <Library/SubhookLib.h>
> +#include <type_traits>
> +
> +//////////////////////////////////////////////////////////////////////////////
> +// The below macros are the public function mock interface that are intended
> +// to be used outside this file.
> +
> +#define MOCK_INTERFACE_DECLARATION(MOCK) \
> +  static MOCK * Instance;                \
> +  MOCK ();                               \
> +  ~MOCK ();
> +
> +#define MOCK_INTERFACE_DEFINITION(MOCK)   \
> +  MOCK_STATIC_INSTANCE_DEFINITION (MOCK)  \
> +  MOCK_INTERFACE_CONSTRUCTOR (MOCK)       \
> +  MOCK_INTERFACE_DECONSTRUCTOR (MOCK)
> +
> +// Mock function declaration for external functions (i.e. functions to
> +// mock that do not exist in the compilation unit).
> +#define MOCK_FUNCTION_DECLARATION(RET_TYPE, FUNC, ARGS)  \
> +  MOCK_FUNCTION_TYPE_DEFINITIONS(RET_TYPE, FUNC, ARGS)   \
> +  MOCK_METHOD (RET_TYPE, FUNC, ARGS);
> +
> +// Mock function definition for external functions (i.e. functions to
> +// mock that do not exist in the compilation unit).
> +#define MOCK_FUNCTION_DEFINITION(MOCK, FUNC, NUM_ARGS, CALL_TYPE)         \
> +  FUNCTION_DEFINITION_TO_CALL_MOCK(MOCK, FUNC, FUNC, NUM_ARGS, CALL_TYPE)
> +
> +// Mock function declaration for internal functions (i.e. functions to
> +// mock that already exist in the compilation unit).
> +#define MOCK_FUNCTION_INTERNAL_DECLARATION(RET_TYPE, FUNC, ARGS) \
> +  MOCK_FUNCTION_DECLARATION(RET_TYPE, FUNC, ARGS)                \
> +  MOCK_FUNCTION_HOOK_DECLARATIONS(FUNC)
> +
> +// Mock function definition for internal functions (i.e. functions to
> +// mock that already exist in the compilation unit). This definition also
> +// implements MOCK_FUNC() which is later hooked as FUNC().
> +#define MOCK_FUNCTION_INTERNAL_DEFINITION(MOCK, FUNC, NUM_ARGS, CALL_TYPE)         \
> +  FUNCTION_DEFINITION_TO_CALL_MOCK(MOCK, FUNC, MOCK##_##FUNC, NUM_ARGS, CALL_TYPE) \
> +  MOCK_FUNCTION_HOOK_DEFINITIONS(MOCK, FUNC)
> +
> +//////////////////////////////////////////////////////////////////////////////
> +// The below macros are private and should not be used outside this file.
> +
> +#define MOCK_FUNCTION_HOOK_DECLARATIONS(FUNC)     \
> +  static subhook::Hook Hook##FUNC;                \
> +  struct MockContainer_##FUNC {                   \
> +    MockContainer_##FUNC ();                      \
> +    ~MockContainer_##FUNC ();                     \
> +  };                                              \
> +  MockContainer_##FUNC MockContainerInst_##FUNC;
> +
> +// This definition implements a constructor and destructor inside a nested
> +// class to enable automatic installation of the hooks to the associated
> +// MOCK_FUNC() when the mock object is instantiated in scope and automatic
> +// removal when the instantiated mock object goes out of scope.
> +#define MOCK_FUNCTION_HOOK_DEFINITIONS(MOCK, FUNC)                        \
> +  subhook :: Hook MOCK :: Hook##FUNC;                                     \
> +  MOCK :: MockContainer_##FUNC :: MockContainer_##FUNC () {               \
> +    if (MOCK :: Instance == NULL)                                         \
> +      MOCK :: Hook##FUNC .Install(                                        \
> +        (FUNC##_ret_type *) ::FUNC,                                       \
> +        (FUNC##_ret_type *) MOCK##_##FUNC);                               \
> +  }                                                                       \
> +  MOCK :: MockContainer_##FUNC :: ~MockContainer_##FUNC () {              \
> +      MOCK :: Hook##FUNC .Remove();                                       \
> +  }                                                                       \
> +  static_assert(                                                          \
> +    std::is_same<decltype(&::FUNC), decltype(&MOCK##_##FUNC)>::value,     \
> +    "Function signature from 'MOCK_FUNCTION_INTERNAL_DEFINITION' macro "  \
> +    "invocation for '" #FUNC "' does not match the function signature "   \
> +    "of '" #FUNC "' function it is mocking. Mismatch could be due to "    \
> +    "different return type, arguments, or calling convention. See "       \
> +    "associated 'MOCK_FUNCTION_INTERNAL_DECLARATION' macro invocation "   \
> +    "for more details.");
> +
> +#define MOCK_FUNCTION_TYPE_DEFINITIONS(RET_TYPE, FUNC, ARGS)  \
> +  using FUNC##_ret_type = RET_TYPE;                           \
> +  using FUNC##_type = FUNC##_ret_type ARGS;
> +
> +// This function definition simply calls MOCK::Instance->FUNC() which is the
> +// mocked counterpart of the original function. This allows using gmock with
> +// C free functions (since by default gmock only works with object methods).
> +#define FUNCTION_DEFINITION_TO_CALL_MOCK(MOCK, FUNC, FUNC_DEF_NAME, NUM_ARGS, CALL_TYPE) \
> +  extern "C" {                                                                           \
> +    typename MOCK :: FUNC##_ret_type CALL_TYPE FUNC_DEF_NAME(                            \
> +      GMOCK_PP_REPEAT(GMOCK_INTERNAL_PARAMETER,                                          \
> +                      (MOCK :: FUNC##_type),                                             \
> +                      NUM_ARGS))                                                         \
> +    {                                                                                    \
> +      EXPECT_TRUE(MOCK :: Instance != NULL)                                              \
> +        << "Called '" #FUNC "' in '" #MOCK "' function mock object before "              \
> +        << "an instance of '" #MOCK "' was created in test '"                            \
> +        << ::testing::UnitTest::GetInstance()->current_test_info()->name()               \
> +        << "'.";                                                                         \
> +      return MOCK :: Instance->FUNC(                                                     \
> +        GMOCK_PP_REPEAT(GMOCK_INTERNAL_FORWARD_ARG,                                      \
> +                        (MOCK :: FUNC##_type),                                           \
> +                        NUM_ARGS));                                                      \
> +    }                                                                                    \
> +  }
> +
> +#define MOCK_STATIC_INSTANCE_DEFINITION(MOCK)  MOCK * MOCK :: Instance = NULL;
> +
> +#define MOCK_INTERFACE_CONSTRUCTOR(MOCK)                                     \
> +  MOCK :: MOCK () {                                                          \
> +    EXPECT_TRUE(MOCK :: Instance == NULL)                                    \
> +      << "Multiple instances of '" #MOCK "' function mock object were "      \
> +      << "created and only one instance is allowed in test '"                \
> +      << ::testing::UnitTest::GetInstance()->current_test_info()->name()     \
> +      << "'.";                                                               \
> +    MOCK :: Instance = this;                                                 \
> +  }
> +
> +#define MOCK_INTERFACE_DECONSTRUCTOR(MOCK) \
> +  MOCK :: ~ MOCK () {                      \
> +    MOCK :: Instance = NULL;               \
> +  }
> +
> +#endif // FUNCTION_MOCK_LIB_H_
> diff --git a/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h b/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
> index ebec766d4cf7..c0a3d8e66011 100644
> --- a/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
> +++ b/UnitTestFrameworkPkg/Include/Library/GoogleTestLib.h
> @@ -10,5 +10,101 @@
>   #define GOOGLE_TEST_LIB_H_
>   
>   #include <gtest/gtest.h>
> +#include <gmock/gmock.h>
> +#include <cstring>
> +
> +extern "C" {
> +#include <Uefi.h>
> +}
> +
> +//////////////////////////////////////////////////////////////////////////////
> +// Below are the action extensions to GoogleTest and gmock for EDK2 types.
> +// These actions are intended to be used in EXPECT_CALL (and related gmock
> +// macros) to support assignments to output arguments in the expected call.
> +//
> +
> +// Action to support pointer types to a buffer (such as UINT8* or VOID*)
> +ACTION_TEMPLATE (
> +  SetArgBuffer,
> +  HAS_1_TEMPLATE_PARAMS (size_t, ArgNum),
> +  AND_2_VALUE_PARAMS (Buffer, ByteSize)
> +  ) {
> +  auto  ArgBuffer = std::get<ArgNum>(args);
> +
> +  std::memcpy (ArgBuffer, Buffer, ByteSize);
> +}
> +
> +//////////////////////////////////////////////////////////////////////////////
> +// Below are the matcher extensions to GoogleTest and gmock for EDK2 types.
> +// These matchers are intended to be used in EXPECT_CALL (and related gmock
> +// macros) to support comparisons to input arguments in the expected call.
> +//
> +// Note that these matchers can also be used in the EXPECT_THAT or ASSERT_THAT
> +// macros to compare whether two values are equal.
> +//
> +
> +// Matcher to support pointer types to a buffer (such as UINT8* or VOID* or
> +// any structure pointer)
> +MATCHER_P2 (
> +  BufferEq,
> +  Buffer,
> +  ByteSize,
> +  std::string ("buffer data to ") + (negation ? "not " : "") + "be the same"
> +  ) {
> +  UINT8  *Actual   = (UINT8 *)arg;
> +  UINT8  *Expected = (UINT8 *)Buffer;
> +
> +  for (size_t i = 0; i < ByteSize; i++) {
> +    if (Actual[i] != Expected[i]) {
> +      *result_listener << "byte at offset " << i
> +      << " does not match expected. [" << std::hex
> +      << "Actual: 0x" << std::setw (2) << std::setfill ('0')
> +      << (unsigned int)Actual[i] << ", "
> +      << "Expected: 0x" << std::setw (2) << std::setfill ('0')
> +      << (unsigned int)Expected[i] << "]";
> +      return false;
> +    }
> +  }
> +
> +  *result_listener << "all bytes match";
> +  return true;
> +}
> +
> +// Matcher to support CHAR16* type
> +MATCHER_P (
> +  Char16StrEq,
> +  String,
> +  std::string ("strings to ") + (negation ? "not " : "") + "be the same"
> +  ) {
> +  CHAR16  *Actual   = (CHAR16 *)arg;
> +  CHAR16  *Expected = (CHAR16 *)String;
> +
> +  for (size_t i = 0; Actual[i] != 0; i++) {
> +    if (Actual[i] != Expected[i]) {
> +      *result_listener << "character at offset " << i
> +      << " does not match expected. [" << std::hex
> +      << "Actual: 0x" << std::setw (4) << std::setfill ('0')
> +      << Actual[i];
> +
> +      if (std::isprint (Actual[i])) {
> +        *result_listener << " ('" << (char)Actual[i] << "')";
> +      }
> +
> +      *result_listener << ", Expected: 0x" << std::setw (4) << std::setfill ('0')
> +      << Expected[i];
> +
> +      if (std::isprint (Expected[i])) {
> +        *result_listener << " ('" << (char)Expected[i] << "')";
> +      }
> +
> +      *result_listener << "]";
> +
> +      return false;
> +    }
> +  }
> +
> +  *result_listener << "strings match";
> +  return true;
> +}
>   
>   #endif
> diff --git a/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf b/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
> index 052c7f557210..eeee6bc2b3f5 100644
> --- a/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
> +++ b/UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
> @@ -16,7 +16,7 @@ [Defines]
>     LIBRARY_CLASS   = CmockaLib|HOST_APPLICATION
>   
>   #
> -#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
> +#  VALID_ARCHITECTURES           = IA32 X64
>   #
>   
>   [Sources]
> diff --git a/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.c b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.c
> new file mode 100644
> index 000000000000..b7bb23f1868b
> --- /dev/null
> +++ b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.c
> @@ -0,0 +1,7 @@
> +/** @file
> +  Macro-only FunctionMockLib library instance with no services.
> +
> +  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
> +  SPDX-License-Identifier: BSD-2-Clause-Patent
> +
> +**/
> diff --git a/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf
> new file mode 100644
> index 000000000000..4b0662a8b96d
> --- /dev/null
> +++ b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf
> @@ -0,0 +1,31 @@
> +## @file
> +#  This module provides FunctionMockLib Library implementation.
> +#
> +#  Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
> +#  SPDX-License-Identifier: BSD-2-Clause-Patent
> +#
> +##
> +
> +[Defines]
> +  INF_VERSION     = 0x00010005
> +  BASE_NAME       = FunctionMockLib
> +  MODULE_UNI_FILE = FunctionMockLib.uni
> +  FILE_GUID       = DF1CAF2F-D584-4EC1-9ABF-07E8B10AD560
> +  MODULE_TYPE     = BASE
> +  VERSION_STRING  = 0.1
> +  LIBRARY_CLASS   = FunctionMockLib|HOST_APPLICATION
> +
> +#
> +#  VALID_ARCHITECTURES           = IA32 X64
> +#
> +
> +[Sources]
> +  FunctionMockLib.c
> +
> +[LibraryClasses]
> +  GoogleTestLib
> +  SubhookLib
> +
> +[Packages]
> +  MdePkg/MdePkg.dec
> +  UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> diff --git a/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.uni b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.uni
> new file mode 100644
> index 000000000000..13e5308ce0e7
> --- /dev/null
> +++ b/UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.uni
> @@ -0,0 +1,11 @@
> +// /** @file
> +// This module provides FunctionMockLib Library implementation.
> +//
> +// Copyright (c) 2023, Intel Corporation. All rights reserved.<BR>
> +// SPDX-License-Identifier: BSD-2-Clause-Patent
> +//
> +// **/
> +
> +#string STR_MODULE_ABSTRACT             #language en-US "FunctionMockLib Library implementation"
> +
> +#string STR_MODULE_DESCRIPTION          #language en-US "This module provides FunctionMockLib Library implementation."
> diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> index 68db75d7023f..1203a0e6eccd 100644
> --- a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> +++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
> @@ -16,20 +16,22 @@ [Defines]
>     LIBRARY_CLASS   = GoogleTestLib|HOST_APPLICATION
>   
>   #
> -#  VALID_ARCHITECTURES           = IA32 X64 ARM AARCH64
> +#  VALID_ARCHITECTURES           = IA32 X64
>   #
>   
>   [Sources]
>     googletest/googletest/src/gtest-all.cc
> +  googletest/googlemock/src/gmock-all.cc
>   
>   [Packages]
> +  MdePkg/MdePkg.dec
>     UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
>   
>   [BuildOptions]
>     MSFT:*_*_*_CC_FLAGS     == /c /EHsc /Zi
>     MSFT:NOOPT_*_*_CC_FLAGS =  /Od
>   
> -  GCC:*_*_*_CC_FLAGS     == -g -c
> +  GCC:*_*_*_CC_FLAGS     == -g -c -fshort-wchar
>   
>     GCC:NOOPT_*_*_CC_FLAGS =  -O0
>     GCC:*_*_IA32_CC_FLAGS  =  -m32
> diff --git a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
> index 14c862a23744..695588ce3f46 100644
> --- a/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
> +++ b/UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.uni
> @@ -1,10 +1,7 @@
>   // /** @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
>   //
>   // **/
> diff --git a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> index 722509c8f26f..f14961ad86d0 100644
> --- a/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> +++ b/UnitTestFrameworkPkg/Test/UnitTestFrameworkPkgHostTest.dsc
> @@ -34,6 +34,7 @@ [Components]
>     UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
>     UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
>     UnitTestFrameworkPkg/Library/SubhookLib/SubhookLib.inf
> +  UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.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 d8f8e024c476..be839d1af0a7 100644
> --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
> +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.ci.yaml
> @@ -79,9 +79,14 @@
>           "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/GoogleTestLib/googletest/**/*.*"  # not going to spell check a submodule
> +            "Library/GoogleTestLib/googletest/**/*.*",  # not going to spell check a submodule
> +            "Library/SubhookLib/subhook/**/*.*"  # not going to spell check a submodule
>           ],
>           "ExtendWords": [             # words to extend to the dictionary for this package
> +            "Pointee",
> +            "gmock",
> +            "GMOCK",
> +            "DSUBHOOK",
>               "testcase",
>               "testsuites",
>               "cmocka",
> diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> index 30b489915d4a..ef0a148d4876 100644
> --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkg.dec
> @@ -26,6 +26,7 @@ [Includes.Common.Private]
>     PrivateInclude
>     Library/CmockaLib/cmocka/include/cmockery
>     Library/GoogleTestLib/googletest/googletest
> +  Library/GoogleTestLib/googletest/googlemock
>   
>   [LibraryClasses]
>     ## @libraryclass Allows save and restore unit test internal state
> @@ -36,6 +37,7 @@ [LibraryClasses]
>     #
>     GoogleTestLib|Include/Library/GoogleTestLib.h
>     SubhookLib|Include/Library/SubhookLib.h
> +  FunctionMockLib|Include/Library/FunctionMockLib.h
>   
>   [LibraryClasses.Common.Private]
>     ## @libraryclass Provides a unit test result report
> diff --git a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> index e77897bd326f..7866c36e6693 100644
> --- a/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> +++ b/UnitTestFrameworkPkg/UnitTestFrameworkPkgHost.dsc.inc
> @@ -16,6 +16,7 @@ [LibraryClasses.common.HOST_APPLICATION]
>     CmockaLib|UnitTestFrameworkPkg/Library/CmockaLib/CmockaLib.inf
>     GoogleTestLib|UnitTestFrameworkPkg/Library/GoogleTestLib/GoogleTestLib.inf
>     SubhookLib|UnitTestFrameworkPkg/Library/SubhookLib/SubhookLib.inf
> +  FunctionMockLib|UnitTestFrameworkPkg/Library/FunctionMockLib/FunctionMockLib.inf
>     UnitTestLib|UnitTestFrameworkPkg/Library/UnitTestLib/UnitTestLibCmocka.inf
>     DebugLib|UnitTestFrameworkPkg/Library/Posix/DebugLibPosix/DebugLibPosix.inf
>     MemoryAllocationLib|UnitTestFrameworkPkg/Library/Posix/MemoryAllocationLibPosix/MemoryAllocationLibPosix.inf


-=-=-=-=-=-=-=-=-=-=-=-
Groups.io Links: You receive all messages sent to this group.
View/Reply Online (#102540): https://edk2.groups.io/g/devel/message/102540
Mute This Topic: https://groups.io/mt/98066295/1787277
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org]
-=-=-=-=-=-=-=-=-=-=-=-