diff options
Diffstat (limited to 'UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h')
| -rw-r--r-- | UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h | 262 |
1 files changed, 131 insertions, 131 deletions
diff --git a/UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h b/UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h index bf7a706656..0ed6e878a4 100644 --- a/UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h +++ b/UnitTestFrameworkPkg/Include/Library/FunctionMockLib.h @@ -1,131 +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_
+/** @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_ |
