Why is the MOCK_METHOD syntax not working in GMock? - c++

I have not even begun testing and I am encountering some syntax issues with GMock's MOCK_METHOD macro even though I am following GMock's documentation properly. Could it be a compiler issue? I have:
MingGW (GCC 4.9.2)
Googletest 1.10.x
class SimpleClass {
public:
virtual int simpleFirstFunction(int a, int b) { return (a + simpleSecondFunction(b)); }
virtual int simpleSecondFunction(int b) { return (2 * b); }
virtual ~SimpleClass();
};
class MockSimpleClass :public SimpleClass {
MOCK_METHOD(int, simpleSecondFunction, (int a, int b), (override));
};
I am seeing 3 compiler errors:
Error-1: about the function name
MockSimpleClass.cpp:18:24: error:
'simpleSecondFunction' is not a type
MOCK_METHOD(int, simpleSecondFunction(int a, int b), (override));
Error-2: about input parameters
MockSimpleClass.cpp:18:46: error:
expected identifier before '(' token
MOCK_METHOD(int, simpleSecondFunction, (int a, int b), (override));
Error-3: About parentheses around "override"
MockSimpleClass.cpp:18:60: error:
expected identifier before '(' token
MOCK_METHOD(int, simpleSecondFunction(int a, int b), (override));

MOCK_METHOD macro is not defined.
Here is how I troubleshooted the exact same issue:
Check preprocessor: gcc -E s1.cpp > s1.preproc.
First of all check the gmock.h included.
In my case it was:
72396 # 11 "s1.cpp" 2
72397 # 1 "/usr/include/gmock/gmock.h" 1 3 4
As you can see a system header is included.
I wen to check googletest version on system(Ubuntu 19.10):
doliaru#host:~/test/gtest/build$ dpkg -l google*
rc google-mock:amd64 1.8.1-3 aand using C++ mock classes
ii googletest:amd64 1.8.1-3 amd64 Google's C++ test frame
dpoliaru#host:~/test/gtest/build$
Apparently this feature was not implemented in 1.8.
I cloned the most recent version of googletest here.
Having checked the topmost CMakeLists.txt on master branch I see that
current gtest version on master is:
set(GOOGLETEST_VERSION 1.10.0)
And I built it with these cmake configs:
cmake .. -D CMAKE_INSTALL_PREFIX=/home/dpoliaru/.local/ -D gtest_build_samples=TRUE
After installation, gmock, that I needed for the project was here:
/home/dpoliaru/.local/include/gmock/gmock.h
Thus, I updated CMakeLists.txt file of the project with the proper include directory for given target:
...
target_include_directories(${PROJECT_NAME} PUBLIC ${GTEST_INCLUDE_DIRS} ${GMOCK_INCLUDE_DIRS})
...
If you are new to cmake, please check their webpage and find lots of great stuff in cmake-data debian package.
After cmake configure step I see this definition in flags.cmake file:
CXX_INCLUDES = -I/home/dpoliaru/.local/include
With proper include paths I managed to compile the project.
Hope that helps.

It sounds like the MOCK_METHOD macro is not defined. Have you set up your include path correctly and added the #include "gmock/gmock.h" directive at the top of your file? You are also missing a public access specifier and the number of arguments is wrong for the function.
This should work if you have the gmock headers on your include path:
#include "gmock/gmock.h"
class SimpleClass {
public:
virtual int simpleFirstFunction(int a, int b) { return (a + simpleSecondFunction(b)); }
virtual int simpleSecondFunction(int b) { return (2 * b); }
virtual ~SimpleClass();
};
class MockSimpleClass : public SimpleClass {
public:
MOCK_METHOD(int, simpleSecondFunction, (int b), (override));
};

Related

Can't link C++ methods in same source file using Gradle

I'm trying to use Gradle (5.6.2) to build a basic C++ library, and cannot figure out what is going wrong here. I started out using Gradle init to create the basic structure... here's my build.gradle:
plugins {
// Apply the cpp-library plugin to add support for building C++ libraries
id 'cpp-library'
// Apply the cpp-unit-test plugin to add support for building and running C++ test executables
id 'cpp-unit-test'
}
// Set the target operating system and architecture for this library
library {
targetMachines.add(machines.macOS.x86_64)
dependencies {
implementation files('/usr/local/lib/libjsoncpp.a') // used by classA
}
}
tasks.withType(CppCompile).configureEach {
compilerArgs.add "-std=c++11"
compilerArgs.add "-w"
}
The source tree looks like this:
src/main/cpp -> classA.cpp classB.cpp classB.hpp hello.cpp
src/main/public -> classA.hpp cppd.h cpplib.h
src/test/cpp -> classATest.cpp hello_test.cpp
hello.cpp, cppd.h, cpplib.h, and hello_test.cpp all came from the 'gradle init' and aren't actually used.
classA calls a few methods in classB. classB only depends on standard libraries.
classB has a public method classB::method1() that calls two private methods classB::method2() and classB::method3()
When I build, I get a linker error that it can't find classB::method2() or classB::method3(). I checked the method signatures and they all match up (same number and type of arguments in classB.hpp, classB.cpp, and in the linker error message).
I've scoured the Gradle documentation and Googled everything I can think of, tried several variations on the build.gradle file, and... I don't understand why the linker can't find methods in the same CPP file??
Building with Clang 11.0 on MacOS 10.14.6 in case it matters...
Also for reference, here's the relevant bits of the header file:
class classB {
public:
method1();
private:
string& method2(const string& s, bool b);
int method3(uint16_t* b, const string& s);
}
And the methods from the cpp file:
string& method2(const string& s, bool b) {
// blah
}
int method3(uint16_t* b, const string& s) {
// blah
}
OH MY GOODNESS! Just... Nevermind. You know how sometimes posting the question itself is enough to make the problem obvious?
For the record, of course what's missing is the class identifyer-thing (sorry, can't recall the term, I'm coming back from Java) on the front of the method names in the CPP file. They should be:
string& classB::method2(const string& s, bool b) {
// blah
}
int classB::method3(uint16_t* b, const string& s) {
// blah
}
Without the class identifyer-things, the linker doesn't realize they are member functions, and doesn't make the connection.

friend function in CUDA C++

I am working on a problem that class A and B are declared in namespace test0 and a friend function f of class A declared in namespace test1. Function f receives a reference of a class B object as the parameter. Here is an simplified example.
namespace test0 {
class B;
}
namespace test1 {
void f(test0::B& b);
}
namespace test0 {
class A {
friend void test1::f(test0::B& b);
};
}
The code works with g++. But nvcc gives the following compilation error.
a.cu:11:22: error: ‘B’ has not been declared
friend void test1::f(test0::B& b);
^
a.cu:11:27: error: ‘void test1::f(int&)’ should have been declared inside ‘test1’
friend void test1::f(test0::B& b);
^
Could you please help me figure out what the problem is? Thank you in advance.
It is important to understand that nvcc isn't a compiler, it is a compiler driver, and in both cases, the code is compiled with gcc and the error is a gcc generated error. If you put that code in a .cc extension file and compile it via nvcc, there will no be no error.
But when compiling CUDA code (in a .cu file in this case), there are some intermediate processing stages between your code and the final g++ pass which compiles it. Under the hood, what is happening is that your code is being transformed by the CUDA C++ front end parser to this:
# 1
# 2
namespace test0 {
# 3
class B;
# 4
}
# 6
namespace test1 {
# 7
void f(test0::B & b);
# 8
}
# 10
namespace test0 {
# 11
class A {
# 12
friend void test1::f(B & b);
# 13
};
# 14
}
compare that to the original friend void test1::f(test0::B& b); and you can see that the namespace has been stripped out by the cudafe++ pass. I don't know why it has been stripped out, but that is the source of the error.
I would recommend reporting this as a bug to NVIDIA if it is a real problem in your application.
After review by the NVIDIA development team, it appears that this may be exposing a bug in the gnu compiler. It is true that the front-end processing by the nvcc toolchain creates a host code (passed to the host compiler) that drops the namespace qualification for b's type, but this should be acceptable because B has already been declared in test0 namespace.
It appears that this has already been reported to the gnu community.
As a supporting data point, clang++ 3.9.1 on Fedora 25 compiles the code reported in the answer given by #talonmies with no errors and no warnings. On my testing up through gnu 6.4.1 on Fedora25, the gnu toolchain still throws an error. I'm not claiming this as a proof point, merely a suggestion that the claim of a bug in gnu might be possibly correct. I am not a language expert. Furthermore I don't wish to start an argument here about that; it's not the purpose of this question or answer.
The NVIDIA development team has taken the issue under review and hopes to have a fix or workaround in a future CUDA release.
In the meantime, the source-level workaround suggested is to use a dummy typedef for B in class A. i.e.:
class A {
typedef B dummy_t;
friend void test1::f(dummy_t & b);
};
UPDATE:
The issue should be resolved in CUDA 10.1.105 (CUDA 10.1)

gtest, undefined reference to 'testing::Test::~Test()', testing::Test::Test()

i installed the gtest using apt-get install libgtest-dev
and i am trying to check if that is working or not.
so i make simple code for testing in eclipse.
but there are error,
undefined reference to 'testing::Test::~Test()'
undefined reference
to 'testing::Test::Test()'
conversely if i change the inheritance at the ATest class as protected the error disappear but
the other error occur
testing::Test is inaccessible base of 'ATest_AAA_Test'
what is wrong ?
#include <iostream>
#include <gtest/gtest.h>
class A{
public:
int a;
A(int a){this->a = a;}
A(){}
~A(){}
int getA(){return a;}
void setA(int a){this->a = a;}
};
class ATest : public ::testing::Test{
public:
virtual void SetUp(){
a1 = A(1);
a2 = A(2);
a3 = A(3);
}
virtual void TearDwon(){}
A a1;
A a2;
A a3;
};
TEST_F(ATest, AAA){
EXPECT_EQ(1, a1.getA());
EXPECT_EQ(2, a2.getA());
EXPECT_EQ(3, a3.getA());
}
int main(int argc, char **argv){
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
I know this sounds obvious but my psychic debugging skills tell me you forgot to add -lgtest after your object file name when you linked your final binary.
Installing libgtest-dev does not install any of the gtest binaries.
It simply installs the googletest source package on your system - headers
under /usr/include/gtest and source files under /usr/src/gtest,
where you could proceed to build it with cmake or GNU autotools
if you want.
There is no binary package for googletest in ubuntu/debian software channels
(or elsewhere that I know of). The normal practice is to
download the source archive,
extract it and use binaries built by yourself. The README in the
source package gives guidance on building and using the library.
There is normally no purpose in performing a system install of
the source package, as you have done.
The linkage error you have encountered:
undefined reference to 'testing::Test::~Test()
has nothing to do with your code: it occurs because you are not
linking libgtest, and you cannot link it because it is not installed
by libgtest-dev and you have not built it yourself.
This linkage error disappears when you change the code in a way
that introduces a compilation error, because if compilation fails
then linkage does not happen.

Two or more data types in declaration of 'parameters' using mingw cross compiler under linux

I am trying to cross compile some code for windows using MinGw. The code is fairly simple:
Header:
class DragLabel : public QLabel
{
Q_OBJECT
public:
DragLabel();
void fn(QString path, int id, bool small);
};
cpp:
#include "draglabel.h"
DragLabel::DragLabel()
{
/* Snip ... */
};
void DragLabel::fn(QString path, int id, bool small)
{
(void)d;
};
The example function fails to compile givin me:
error: two or more data types in declaration of 'parameter'
for the declaration of fn(QString...).
[EDIT:] Sorry i forgot to mention that this error happens only if there is the bool variable declared, so the function without:
void fn(QString path, int id);
Workes just fine.
It compiles fine using qmake and make under debian linux.
Does anyone know what might happens here?
Thanks
It seems that small is some extension keyword of MinGW (I couldn't find it in standard). According to
When i change everything to int it works
small is some qualifier like long or signed, that extends int declaration.
Try to change variable name from small to anything else.

Calling method of object passed to qt plugin yields symbol lookup error

I have a problem with passing a object to Qt Plugin and when trying to get its member using const member function i get symbol lookup error. Example:
This is inside Qt application:
class A{
int a,b,c;
};
class B{
public:
const QList<A*>* a() const { return m_a; }
private:
QList<A*>* m_a;
};
class C{
public:
const B* b() const { return m_b; }
private:
B* m_b;
};
This is inside QtPlugin:
plugin.h
#include "a.h"
#include "b.h"
#include "c.h"
//....
plugin.cpp
void Plugin::somefunc(C* c)
{
qDebug() << c->b()->a()->count();
}
If I call from Qt application somefunc() of a plugin I get symbol lookup error:
symbol lookup error ... plugin.so undefined symbol _ZNK5b6a
but if I put B and C class members into public domain it works using:
qDebug() << c->m_b->m_a->count();
Did anyone have similar problem or knows how to solve this? Thanks.
Class members are private by default. B::a() and C::b() are private. To be able to call these member functions from Plugin::somefunc() you need to make them public explicitly.
There are two solutions to this "problem".
Make shared library - make shared library and move code that application and QtPlugin use into that library
Add .h and .cpp of files used to QMake file - header and source files of application used in QtPlugin add to HEADERS and SOURCES directive in .pro file - this is actually static linking
I haven't found similar question on web, and thus putting this answer. Maybe question was fuzzy, sorry about that. Thanks for answer. This answer is for any future reference.