First, thanks for the awesome mocking library, I'm new to it, but I'm a big fan. I'm constantly impressed by how well it works despite the challenging limitations of the language.
I am unit testing a plugin loader. The plugin loader uses the classic pattern of exporting a create function and a destroy function. In testing, I mock both of these functions, and it works great using hippomocks' ExpectCallFunc feature to mock the function getting called. The test uses dlopen( nullptr, RTLD_LAZY ); to load the target functions out of the running unit test executable.
All tests pass, and the mocked functions are successfully called using the function pointer returned from dlsym.
However, when running tests with valgrind, via ctest -T memcheck, the mocked functions are not called. Instead the non-mocked functions are called and the test fails.
The link at the top goes directly to the test that fails when run with valgrind and passes when run without valgrind. Note that valgrind does not detect memory leaks, the unit test just fails, because the REQUIRE expects the result of the mocked function, but instead gets the result of the original function.
I haven't tested this with any compilers other than gcc-7 yet. Instructions:
git clone https://github.com/Marcus10110/ci_helloworld.git
cd ci_helloworld
git checkout hippomocks-valgrind-repro
mkdir build
cd build
cmake ..
make
ctest
ctest -T memcheck
ctest should pass and ctest -T memcheck should fail.
Below is an excerpt of the code for easy reading:
#include <hippomocks.h>
#include <catch/catch.hpp>
#include <dlfcn.h>
extern "C" __attribute__((visibility("default"))) int* CreatePlugin();
using create_t = int * ( * )();
TEST_CASE("c func plugin mocked")
{
MockRepository mocks;
int i = 5;
mocks.ExpectCallFunc( CreatePlugin ).Return( &i );
void* handle = dlopen( nullptr, RTLD_LAZY );
create_t create_func = reinterpret_cast<create_t>(dlsym( handle, "CreatePlugin" ));
REQUIRE(create_func() == &i); //create_func() should return the address if i when mocked, and nullptr when not mocked.
}
int* CreatePlugin()
{
return nullptr;
}
I'm also having this problem with hippmocks 5.0 and valgrind 3.18 on Ubuntu 22.04. Same general issue, but showing up when mocking libsodium functions and running with valgrind - non-valgrind usage works fine.
First, thanks for the awesome mocking library, I'm new to it, but I'm a big fan. I'm constantly impressed by how well it works despite the challenging limitations of the language.
Environment & Libraries:
Ubuntu 16.04, gcc 7, catch, latest hippomocks master, valgrind 3.11.0 (stock valgrind from package manager)
basic repro case:
https://github.com/Marcus10110/ci_helloworld/blob/hippomocks-valgrind-repro/test/test_consumer.cpp#L87
Problem description:
I am unit testing a plugin loader. The plugin loader uses the classic pattern of exporting a create function and a destroy function. In testing, I mock both of these functions, and it works great using hippomocks'
ExpectCallFunc
feature to mock the function getting called. The test usesdlopen( nullptr, RTLD_LAZY );
to load the target functions out of the running unit test executable.All tests pass, and the mocked functions are successfully called using the function pointer returned from
dlsym
.However, when running tests with valgrind, via
ctest -T memcheck
, the mocked functions are not called. Instead the non-mocked functions are called and the test fails.I created a repro case with a few minor edits to a C++ hello world application that's already setup with valgrind and hippomocks. My fork is here: https://github.com/Marcus10110/ci_helloworld/tree/hippomocks-valgrind-repro
The link at the top goes directly to the test that fails when run with valgrind and passes when run without valgrind. Note that valgrind does not detect memory leaks, the unit test just fails, because the REQUIRE expects the result of the mocked function, but instead gets the result of the original function.
I haven't tested this with any compilers other than gcc-7 yet. Instructions:
ctest
should pass andctest -T memcheck
should fail.Below is an excerpt of the code for easy reading: