smalti / gmock-win32 Goto Github PK
View Code? Open in Web Editor NEWThe library implements gmock functionality for global win32 functions.
Home Page: https://smalti.github.io/gmock-win32/
License: MIT License
The library implements gmock functionality for global win32 functions.
Home Page: https://smalti.github.io/gmock-win32/
License: MIT License
I’m writing about two at once, because one follows from the other and it’s difficult to separate them.
Unexpected behavior after completing a single test..
Leads to: it is impossible to detect an error/failure after the completion of a particular test, there is no process termination error code to be processed, and there are also no error records in the xml/json output file.
Double "Reporting" on single API hook.
Leads to: additional reporting of false expectations.
After complete single test
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from verifyAndClear_unexpectedBehavior_reportAfterTests
[ RUN ] verifyAndClear_unexpectedBehavior_reportAfterTests.gmockWin32
C:\Prj\_PullRequest\gmock-win32\_changes\verifyAndClear\expectedButFail.cpp(13): error: Actual function call count doesn't match EXPECT_CALL(mock_module_GetActiveWindow::instance(), GetActiveWindow())...
Expected: to be called once
Actual: never called - unsatisfied and active
[ FAILED ] verifyAndClear_unexpectedBehavior_reportAfterTests.gmockWin32 (2 ms)
[----------] 1 test from verifyAndClear_unexpectedBehavior_reportAfterTests (5 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (11 ms total)
[ PASSED ] 0 tests.
[ FAILED ] 1 test, listed below:
[ FAILED ] verifyAndClear_unexpectedBehavior_reportAfterTests.gmockWin32
1 FAILED TEST
C:\Prj\_PullRequest\gmock-win32\_changes\verifyAndClear\bin\x64\Debug\expectedButFail.exe (process 5816) exited with code 1.
Press any key to close this window . . .
Note: (process Xxx) exited with code 1 !
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from verifyAndClear_unexpectedBehavior_reportAfterTests
[ RUN ] verifyAndClear_unexpectedBehavior_reportAfterTests.gmockWin32
[ OK ] verifyAndClear_unexpectedBehavior_reportAfterTests.gmockWin32 (0 ms)
[----------] 1 test from verifyAndClear_unexpectedBehavior_reportAfterTests (1 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (3 ms total)
[ PASSED ] 1 test.
C:\Prj\_PullRequest\gmock-win32\_changes\verifyAndClear\expectedButFail.cpp(13): error: Actual function call count doesn't match EXPECT_CALL(mock_module_GetActiveWindow::instance(), GetActiveWindow())...
Expected: to be called once
Actual: never called - unsatisfied and active
C:\Prj\_PullRequest\gmock-win32\_changes\verifyAndClear\bin\x64\Debug\expectedButFail.exe (process 7920) exited with code 0.
Press any key to close this window . . .
Note: (process Xxx) exited with code 0 !.
1.1. Source code
expectedButFail.cpp
#pragma comment( lib, "kernel32" )
#pragma comment( lib, "user32" )
#include "..\src\gtest\gtest-all.cc"
#include "..\src\gmock\gmock-all.cc"
#include "..\..\src\gmock-win32.cpp"
#include "..\include\gtest\gtest-spi.h"
int main(int argc, char **argv) {
const gmock_win32::init_scope gmockWin32{ };
return ::testing::InitGoogleTest( &argc, argv ), RUN_ALL_TESTS( );
}
MOCK_CDECL_FUNC( HWND, GetCapture );
TEST(verifyAndClear_unexpectedBehavior_reportAfterTests, gmockWin32) {
EXPECT_MODULE_FUNC_CALL( GetCapture );
// bool result = true;
// EXPECT_NONFATAL_FAILURE(
// VERIFY_AND_CLEAR_MODULE_FUNC( GetCapture )
// , "Actual function call count doesn't match EXPECT_CALL(mock_module_GetCapture::instance(), GetCapture())..."
// );
// ASSERT_TRUE( result );
}
2.1. Building in cmd line
Include path to googletest(NuGet) and current project
set googletest=googletest\gmock\include
set gmock-win32=gmock-win32\include
Building for cl from Msvc 2019
cl expectedButFail.cpp /EHsc /I"%googletest%" /I"%gmock-win32%"
3.1. Run expectedButFail.exe
Double report
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from verifyAndClear_unexpectedBehavior_doubleReport
[ RUN ] verifyAndClear_unexpectedBehavior_doubleReport.addingToInternals
C:\Prj\_PullRequest\gmock-win32\_changes\verifyAndClear\verifyAndClear.cpp(13): error: Actual function call count doesn't match EXPECT_CALL(mock_module_GetACP::instance(), GetACP())...
Expected: to be called once
Actual: never called - unsatisfied and active
[ FAILED ] verifyAndClear_unexpectedBehavior_doubleReport.addingToInternals (1 ms)
[ RUN ] verifyAndClear_unexpectedBehavior_doubleReport.forCurrentGetACP_and_previousGetACP
C:\Prj\_PullRequest\gmock-win32\_changes\verifyAndClear\verifyAndClear.cpp(17): error: Actual function call count doesn't match EXPECT_CALL(mock_module_GetACP::instance(), GetACP())...
Expected: to be called once
Actual: never called - unsatisfied and active
[ FAILED ] verifyAndClear_unexpectedBehavior_doubleReport.forCurrentGetACP_and_previousGetACP (0 ms)
[==========] Running 2 tests from 1 test suite.
[----------] Global test environment set-up.
[----------] 2 tests from verifyAndClear_unexpectedBehavior_doubleReport
[ RUN ] verifyAndClear_unexpectedBehavior_doubleReport.addingToInternals
[ OK ] verifyAndClear_unexpectedBehavior_doubleReport.addingToInternals (1 ms)
[ RUN ] verifyAndClear_unexpectedBehavior_doubleReport.forCurrentGetACP_and_previousGetACP
C:\Prj\_PullRequest\gmock-win32\_changes\verifyAndClear\doubleReport.cpp(13): error: Actual function call count doesn't match EXPECT_CALL(mock_module_GetACP::instance(), GetACP())...
Expected: to be called once
Actual: never called - unsatisfied and active
C:\Prj\_PullRequest\gmock-win32\_changes\verifyAndClear\doubleReport.cpp(17): error: Actual function call count doesn't match EXPECT_CALL(mock_module_GetACP::instance(), GetACP())...
Expected: to be called once
Actual: never called - unsatisfied and active
[ FAILED ] verifyAndClear_unexpectedBehavior_doubleReport.forCurrentGetACP_and_previousGetACP (1 ms)
2.1. Source code
doubleReport.cpp
#pragma comment( lib, "kernel32" )
#pragma comment( lib, "user32" )
#include "..\src\gtest\gtest-all.cc"
#include "..\src\gmock\gmock-all.cc"
#include "..\..\src\gmock-win32.cpp"
#include "..\include\gtest\gtest-spi.h"
int main(int argc, char **argv) {
const gmock_win32::init_scope gmockWin32{ };
return ::testing::InitGoogleTest( &argc, argv ), RUN_ALL_TESTS( );
}
MOCK_MODULE_FUNC( UINT, GetACP );
TEST(verifyAndClear_unexpectedBehavior_doubleReport, addingToInternals) {
EXPECT_MODULE_FUNC_CALL( GetACP );
//VERIFY_AND_CLEAR_MODULE_FUNC( GetACP );
}
TEST(verifyAndClear_unexpectedBehavior_doubleReport, forCurrentGetACP_and_previousGetACP) {
EXPECT_MODULE_FUNC_CALL( GetACP );
VERIFY_AND_CLEAR_MODULE_FUNC( GetACP );
}
2.2. Building in cmd line
Include path to googletest(NuGet) and current project
set googletest=googletest\gmock\include
set gmock-win32=gmock-win32\include
Building for cl from Msvc 2019
cl doubleReport.cpp /EHsc /I"%googletest%" /I"%gmock-win32%"
3.2. Run doubleReport.exe
Conversation from #23:
Can I do checks in CI from GitHubAction? I understand this a little.
Yes, it's a good idea, we require CI for writing and executing tests.
About writing tests, from the top of my head:
EXPECT_MODULE_FUNC_CALL
and ON_MODULE_FUNC_CALL
CreateWindowExA()
.RESTORE_MODULE_FUNC
and VERIFY_AND_CLEAR_MODULE_FUNC_EXPECTATIONS
It would be enough?
This issue occurred during the instantiation of a static NiceMock
object, which, in turn, invokes the GetCurrentThreadId
function (referenced in testing::internal::Mutex::Lock
). Environment: GoogleTest 1.14.0, Win10.
Minimal sample to reproduce:
#include <gmock/gmock.h>
#include <gmock-win32.h>
using namespace std;
using namespace testing;
MOCK_STDCALL_FUNC(DWORD, GetCurrentThreadId);
int main(int argc, char* argv[])
{
ON_MODULE_FUNC_CALL(GetCurrentThreadId).WillByDefault(Return(1));
return 0;
}
Hi,
I am a big fan of this library and it has saved me heaps of time. However, I am now trying other functions from the WIN32 which are not in the windows.h library. For example: physicalmonitorenumerationapi.h.
Is there already a process to support this type of library?
Thanks
Using GetWindowLongPtr
to get a stored pointer is quite common.
From <WinUser.h>
if !UNICODE
WINUSERAPI
LONG
WINAPI
GetWindowLongA(
_In_ HWND hWnd,
_In_ int nIndex);
#ifdef _WIN64
WINUSERAPI
LONG_PTR
WINAPI
GetWindowLongPtrA(
_In_ HWND hWnd,
_In_ int nIndex);
# define GetWindowLongPtr GetWindowLongPtrA
#else /* _WIN64 */
# define GetWindowLongPtrA GetWindowLongA
#endif /* _WIN64 */
Along with this: wrong to use GetWindowLongA()
on x64, pointer will be 32bit.
[==========] Running 1 test from 1 test suite.
[----------] Global test environment set-up.
[----------] 1 test from expander_x86_64_macro
[ RUN ] expander_x86_64_macro.test
[ OK ] expander_x86_64_macro.test (10 ms)
[----------] 1 test from expander_x86_64_macro (13 ms total)
[----------] Global test environment tear-down
[==========] 1 test from 1 test suite ran. (16 ms total)
[ PASSED ] 1 test.
Compile error issue
expander_x86_64_macro.cpp(12,2): error C3861: 'patchModuleFunc_GetWindowLongPtrA': identifier not found
expander_x86_64_macro.cpp(12,2): error C2653: 'mock_module_GetWindowLongPtrA': is not a class or namespace name
expander_x86_64_macro.cpp(12,2): error C3861: 'instance': identifier not found
expander_x86_64_macro.cpp(12,2): error C2672: 'gmock_win32::detail::make_proxy': no matching overloaded function found
expander_x86_64_macro.cpp
#include "gtest\gtest.h"
#include "gmock\gmock.h"
#include "gmock-win32.h"
#include <Windows.h>
// in x86 to `mock_module_GetWindowLongA`
// in x64 to `mock_module_GetWindowLongPtrA`
MOCK_STDCALL_FUNC( LONG_PTR, GetWindowLongPtrA, HWND hWnd, int nIndex );
TEST(expander_x86_64_macro, test) {
// in x86 to `patchModuleFunc_GetWindowLongPtrA`
// in x64 to `patchModuleFunc_GetWindowLongPtrA`
EXPECT_MODULE_FUNC_CALL( GetWindowLongPtrA, 0, 0 );
GetWindowLongPtrA( 0, 0 );
}
Include path to googletest and current project
set googletest=googletest\gmock\include
set gmock-win32=gmock-win32\include
Building launch for x86
cl expander_x86_64_macro.cpp /EHsc /I"%googletest%" /I"%gmock-win32%"
expander_x86_64_macro.exe
The current approach to IAT patching lacks support for certain system functions, such as the RoInitialize
function (see the Windows API set redirection mechanism). We need to fix our IAT patching approach to support functions that have been redirected to other DLLs.
Often tests are located in several *.cpp files, but are compiled into one *.exe.
[==========] Running 2 tests from 2 test suites.
[----------] Global test environment set-up.
[----------] 1 test from Bar
[ RUN ] Bar.test
[ OK ] Bar.test (2 ms)
[----------] 1 test from Bar (7 ms total)
[----------] 1 test from Foo
[ RUN ] Foo.test
[ OK ] Foo.test (1 ms)
[----------] 1 test from Foo (2 ms total)
[----------] Global test environment tear-down
[==========] 2 tests from 2 test suites ran. (25 ms total)
[ PASSED ] 2 tests.
Link error issue
Foo.obj : error LNK2005: "public: static void * mock_module_GetACP::oldFn_" (?oldFn_@mock_module_GetACP@@2PEAXEA) already defined in Bar.obj
multiply_defined.exe : fatal error LNK1169: one or more multiply defined symbols found
Foo.cpp
#include "gtest\gtest.h"
#include "gmock\gmock.h"
#include "gmock-win32.h"
#include <Windows.h>
MOCK_STDCALL_FUNC(UINT, GetACP);
TEST(Foo, test) {
EXPECT_MODULE_FUNC_CALL( GetACP );
GetACP( );
}
Bar.cpp
#include "gtest\gtest.h"
#include "gmock\gmock.h"
#include "gmock-win32.h"
#include <Windows.h>
MOCK_STDCALL_FUNC(UINT, GetACP);
TEST(Bar, test) {
EXPECT_MODULE_FUNC_CALL( GetACP );
GetACP( );
}
multiply_defined.cpp
#include "..\src\gtest\src\gtest_main.cc"
#include "..\src\gtest\gtest-all.cc"
#include "..\src\gmock\gmock-all.cc"
#include "..\..\src\gmock-win32.cpp"
Include path to googletest and current project
set googletest=googletest\gmock\include
set gmock-win32=gmock-win32\include
Building launch
cl /c Foo.cpp /EHsc /I"%googletest%" /I"%gmock-win32%"
cl /c Bar.cpp /EHsc /I"%googletest%" /I"%gmock-win32%"
cl /c multiply_defined.cpp /EHsc /I"%googletest%" /I"%gmock-win32%"
link multiply_defined Bar Foo
multiply_defined.exe
Need to add macro-expansion support for RESTORE_MODULE_FUNC
and VERIFY_AND_CLEAR_MODULE_FUNC_EXPECTATIONS
to fix errors:
error C2653: 'mock_module_GetWindowLongPtrA': is not a class or namespace name
error C3861: 'pp_old_fn': identifier not found
error C2065: 'stub': undeclared identifier
error C3861: 'instance': identifier not found
see related issue: #22
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.