Intro
I'm having a problem with implementing a pure virtual interface using Google Mock (v1.7.0).
In order to determine the root cause, I've put together pure virtual interface Simple and MockSimple as a test. I believe what I have done here is in line with this Google Mock example.
Yet, when I compile it, I get an error. Why is this? What am I doing wrong?
Simple Test Code
#include "gmock/gmock.h"
#include "gtest/gtest.h"
class Simple
{
public:
virtual ~Simple() {}
virtual int Initialize() = 0;
};
class MockSimple : public Simple
{
public:
MOCK_METHOD0(Initialize, int());
};
TEST(Hello, MockSimple)
{
MockSimple m;
EXPECT_CALL(m, Initialize);
m.Initialize();
}
Compilation Command
g++ -I../gmock/include/ -I../gmock/gtest/include -c test.cpp -o test.o
Error Output
test.cpp: In member function ‘virtual void Hello_MockSimple_Test::TestBody()’:
test.cpp:20:5: error: ‘m.MockSimple::gmock_Initialize’ does not have class type
Need argument list (an empty one, in this case) for the method called in the EXPECT_CALL :)
EXPECT_CALL(m, Initialize());
Related
I am using gtest/gmock framework to write unit tests. Following is my sample code.
In common.h,
void PreInit() {
cout<<"Doing Pre-initialization."<<endl;
}
In test.cpp,
#include <common.h>
class SampleComponent {
public:
void Init() {
PreInit();
// Do Initialization
}
}
So far, I have been mocking classes. Any idea how to mock independent functions called by member functions of class?
Thanks in advance.
So I am trying to write test cases for my production code but the coverage is drastically low due to the usage of some external C library which cannot be executed without target hardware, So I have no choice but to stub the same. Now the problem is how to stub a C function ?
My production code : prod_code.cpp
int TargetTestClass::targetFunc()
{
if(externalCFunc() == True)
{
statement1; statement2; statement3; /// and so on
}
}
My testcode.cpp generally contains tests like this
//Fixture for Target Test class
class TargetTestClassFixture : public testing::Test {
TargetTestClass* targetTestClassPtr;
void SetUp() {
targetTestClassPtr = new TargetTestClass();
}
void TearDown() {
delete targetTestClassPtr;
}
};
TEST_F (unitTest, test_001)
{
targetTestClassPtr->targetFunc(); //Need to do something here so that externalCFunc() returns true on call
}
What you can do is to create a source file like my_c_stubs.c where you rudimentary implement your C function. For example, the implementation can just return true. Then don't link original source file with the external C function but rather use your stub file. You should still use the original C header. In this way you won't be able to stub inline functions though. If it is required, some more sophisticated approach is needed.
I found 2 solutions to my problem so I am going to answer the same here.
Solution 1 : This involved changing the target source code. Basically you need to write a wrapper that calls the external C functions like below
Class TargetTestClass{
protected:
int targetFunc();
virtual int externalCFuncWrapper(); // Wrapper
};
//call the external C function from the wrapper
int TargetTestClass::externalCFunctionWrapper(){
return(externalCFunc());
}
//Definition of targetFuc in original question
//Now write a mock class for Target Test Class as usual and mock the wrapper function to return what you want to
class MockTargetTestClass : public TargetTestClass{
public: MOCK_METHOD0(externalCFunctionWrapper, int());
};
//Now use the Mock class as needed
TEST_F ( TargetUnitTest, TestingExternalCFuctionCall)
{
MockTargetTestClass mockTargetTestClassObj;
using ::testing::Return;
using ::testing::_;
Expect_Call(mockTargetTestClassObj, externalCFunctionWrapper())
.WillOnce(Return(1));
Assert_EQ(mockTargetTestClassObj.targetFunc(), 1);
}
Solution 2 : Thanks to #kreynolds, I have looked into Fake Function Framework and implemented as follows :
Class TargetTestClass{
protected:
int targetFunc();
//No Code change needed in target source code
};
//In testcode.cpp
#include <gmock-global/gmock-global.h>
MOCK_GLOBAL_FUNC0(externalCFunc, int());
TEST( Unittest, test002){
using ::testing::Return;
using ::testing::_;
EXPECT_GLOBAL_CALL(externalCFunc, externalCFunc()).WillOnce(Return(1));
TargetTestClass targetFunc; //This does not contain any wrapper
EXPECT_EQ(targetTestClassObj.targetFunc(), 1);
}
I am using the second solution as this does not require any change in my source code and easier to use.
Once again thank you everyone for giving your time.
I know questions about this error have been asked repeatedly, however none of the previous answers seem to solve my problem.
I have a pure abstract class ITile:
class ITile {
public:
virtual ~ITile() {}
virtual void display() = 0;
virtual bool isWalkable() = 0;
virtual bool isGoal() = 0;
};
And three subclasses that all implement these functions like so:
Floor.h
#include "ITile.h"
class Floor : public ITile {
public:
Floor();
virtual ~Floor();
virtual void display() override;
virtual bool isWalkable() override;
virtual bool isGoal() override;
};
Floor.cpp
#include "Floor.h"
#include <iostream>
using namespace std;
Floor::Floor() {}
Floor::~Floor() {}
void Floor::display() {
cout << " ";
}
bool Floor::isWalkable() {
return true;
}
bool Floor::isGoal() {
return false;
}
When trying to compile the whole project I get the following output:
g++ -std=c++0x -O0 -g3 -Wall -c -fmessage-length=0 -MMD -MP -MF"src/main.d" -MT"src/main.d" -o "src/main.o" "../src/main.cpp"
In file included from ../src/main.cpp:1:
In file included from ../src/board.h:1:
In file included from /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/vector:265:
In file included from /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/__bit_reference:15:
In file included from /Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/algorithm:627:
/Library/Developer/CommandLineTools/usr/bin/../include/c++/v1/memory:1641:31: error: allocating an object of abstract class type 'ITile'
::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);
[...]
...followed by a bunch of notes. But the problem is, I guess, the error in the last line above.
So, what exactly are these algorithm, memory files and so on? How can I get rid of this error?
I'm using Eclipse Luna with the C/C++ plugin on Mac OS X (Mavericks) with the Developer Command Line Tools. Any more info gladly given upon request.
Thanks in advance!
You can't declare a std::vector<ITile>, because ITiles cannot exist.
In order to make use of polymorphism in a container, you'll need to store pointers. Those pointers will point to dynamically-allocated objects of type Floor, Wall, Ceiling… whatever else you've got.
Consider a std::vector<std::unique_ptr<ITile>>.
ITile is an abstract class.
For pre C++11 compilers, you cannot create a std::vector<ITile>. std::vector can be used only with types that are CopyConstructible and CopyAssignable. An abstract class is neither CopyConstructible nor CopyAssignable.
If you are using a C++11, or later, compiler the type need not be CopyConstructible and CopyAssignable to construct a std::vector. Other member functions may impose those requirements. If your compiler is not strictly conformant, it will fail to construct a std::vector for such types.
More info:
http://en.cppreference.com/w/cpp/container/vector
http://en.cppreference.com/w/cpp/concept/CopyConstructible
http://en.cppreference.com/w/cpp/concept/CopyAssignable
I'm trying to become familiar with Google's mocking framework so I can more easily apply some TDD to my C++ development. I have the following interface:
#include <string>
class Symbol {
public:
Symbol (std::string name, unsigned long address) {}
virtual ~Symbol() {}
virtual std::string getName() const = 0;
virtual unsigned long getAddress() const = 0;
virtual void setAddress(unsigned long address) = 0;
};
I want to verify that the destructor is called when an instance is deleted. So I have the following MockSymbol class:
#include "gmock/gmock.h"
#include "symbol.h"
class MockSymbol : public Symbol {
public:
MockSymbol(std::string name, unsigned long address = 0) :
Symbol(name, address) {}
MOCK_CONST_METHOD0(getName, std::string());
MOCK_CONST_METHOD0(getAddress, unsigned long());
MOCK_METHOD1(setAddress, void(unsigned long address));
MOCK_METHOD0(Die, void());
virtual ~MockSymbol() { Die(); }
};
Note: I've omitted the include guards in the above but they are in my header files.
I haven't been able to get to a point where I'm actually testing anything yet. I have the following:
#include "gmock/gmock.h"
#include "MockSymbol.h"
TEST(SymbolTableTests, DestructorDeletesAllSymbols) {
::testing::FLAGS_gmock_verbose = "info";
MockSymbol *mockSymbol = new MockSymbol("mockSymbol");
EXPECT_CALL(*mockSymbol, Die());
}
When I execute my test runner, my other tests execute and pass as I expect them to. However, when the above test executes I get the following error:
SymbolTableTests.cpp:11: EXPECT_CALL(*mockSymbol, Die()) invoked
Segmentation fault (core dumped)
I've spent the last few hours searching Google and trying different things, but to know avail. Does anyone have any suggestions?
I found that setting gtest_disable_pthreads to ON in my build config solves the problem.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
GCC C++ Linker errors: Undefined reference to 'vtable for XXX', Undefined reference to 'ClassName::ClassName()'
I'm doing a little project in C++ and I've come into some problems regarding virtual functions.
I have a base class with some virtual functions:
#ifndef COLLISIONSHAPE_H_
#define COLLISIONSHAPE_H_
namespace domino
{
class CollisionShape : public DominoItem
{
public:
// CONSTRUCTOR
//-------------------------------------------------
// SETTERS
//-------------------------------------------------
// GETTERS
//-------------------------------------------------
virtual void GetRadius() = 0;
virtual void GetPosition() = 0;
virtual void GetGrowth(CollisionShape* other) = 0;
virtual void GetSceneNode();
// OTHER
//-------------------------------------------------
virtual bool overlaps(CollisionShape* shape) = 0;
};
}
#endif /* COLLISIONSHAPE_H_ */
and a SphereShape class which extends CollisionShape and implements the methods above
/* SphereShape.h */
#ifndef SPHERESHAPE_H_
#define SPHERESHAPE_H_
#include "CollisionShape.h"
namespace domino
{
class SphereShape : public CollisionShape
{
public:
// CONSTRUCTOR
//-------------------------------------------------
SphereShape();
SphereShape(CollisionShape* shape1, CollisionShape* shape2);
// DESTRUCTOR
//-------------------------------------------------
~SphereShape();
// SETTERS
//-------------------------------------------------
void SetPosition();
void SetRadius();
// GETTERS
//-------------------------------------------------
void GetRadius();
void GetPosition();
void GetSceneNode();
void GetGrowth(CollisionShape* other);
// OTHER
//-------------------------------------------------
bool overlaps(CollisionShape* shape);
};
}
#endif /* SPHERESHAPE_H_ */
and the .cpp file:
/*SphereShape.cpp*/
#include "SphereShape.h"
#define max(a,b) (a>b?a:b)
namespace domino
{
// CONSTRUCTOR
//-------------------------------------------------
SphereShape::SphereShape(CollisionShape* shape1, CollisionShape* shape2)
{
}
// DESTRUCTOR
//-------------------------------------------------
SphereShape::~SphereShape()
{
}
// SETTERS
//-------------------------------------------------
void SphereShape::SetPosition()
{
}
void SphereShape::SetRadius()
{
}
// GETTERS
//-------------------------------------------------
void SphereShape::GetRadius()
{
}
void SphereShape::GetPosition()
{
}
void SphereShape::GetSceneNode()
{
}
void SphereShape::GetGrowth(CollisionShape* other)
{
}
// OTHER
//-------------------------------------------------
bool SphereShape::overlaps(CollisionShape* shape)
{
return true;
}
}
These classes, along some other get compiled into a shared library.
Building libdomino.so
g++ -m32 -lpthread -ldl -L/usr/X11R6/lib -lglut -lGLU -lGL -shared -lSDKUtil -lglut -lGLEW -lOpenCL -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86 -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/TempSDKUtil/lib/x86 -L"/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86" -lSDKUtil -lglut -lGLEW -lOpenCL -o build/debug/x86/libdomino.so build/debug/x86//Material.o build/debug/x86//Body.o build/debug/x86//SphereShape.o build/debug/x86//World.o build/debug/x86//Engine.o build/debug/x86//BVHNode.o
When I compile the code that uses this library I get the following error:
../../../lib/x86//libdomino.so: undefined reference to `vtable for domino::CollisionShape'
../../../lib/x86//libdomino.so: undefined reference to `typeinfo for domino::CollisionShape'
Command used to compile the demo that uses the library:
g++ -o build/debug/x86/startdemo build/debug/x86//CMesh.o build/debug/x86//CSceneNode.o build/debug/x86//OFF.o build/debug/x86//Light.o build/debug/x86//main.o build/debug/x86//Camera.o -m32 -lpthread -ldl -L/usr/X11R6/lib -lglut -lGLU -lGL -lSDKUtil -lglut -lGLEW -ldomino -lSDKUtil -lOpenCL -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86 -L/home/adrian/AMD-APP-SDK-v2.4-lnx32/TempSDKUtil/lib/x86 -L../../../lib/x86/ -L"/home/adrian/AMD-APP-SDK-v2.4-lnx32/lib/x86"
(the -ldomino flag)
And when I run the demo, I manually tell it about the library:
LD_LIBRARY_PATH=../../lib/x86/:$AMDAPPSDKROOT/lib/x86:$LD_LIBRARY_PATH bin/x86/startdemo
After reading a bit about virtual functions and virtual tables I understood that virtual tables are handled by the compiler and I shouldn't worry about it, so I'm a little bit confused on how to handle this issue.
I'm using gcc version 4.6.0 20110530 (Red Hat 4.6.0-9) (GCC)
Later edit:
I'm really sorry, but I wrote the code by hand directly here.
I have defined the return types in the code.
I apologize to the 2 people that answered below.
I have to mention that I am a beginner at using more complex project layouts in C++.By this I mean more complex makefiles, shared libraries, stuff like that.
My problem was caused by the fact that I didn't define the body of virtual void CollisionShape::GetSceneNode().
The way to fix this is to either define the above function, or declare it as pure virtual as such:
virtual void CollisionShape::GetSceneNode() = 0;
Any non-pure virtual function must be defined, even if it's never used. A missing definition will often result in the 'vtable undefined' linker error, especially when the very first non-pure, non-inline virtual function of a class is left undefined. In your case, CollisionShape::GetSceneNode() is left undefined.
On an unrelated note, every class that has a virtual function needs a virtual destructor, every time, absolutely no exceptions whatsoever. The language unfortunately doesn't enforce this, so it's your responsibility. G++ has a flag, -Weffc++, which enables warnings for this and other common pitfalls, described in the Scott Meyers's book "Effective C++". I strongly recommend using this flag all the time. Using -Werror by default is also a good habit. Suppress individual warnings one by one, and only if there's no possibility to fix the code.
I can't say for certain whether this will fix your compilation error, but in any case you need to declare a virtual destructor (virtual ~CollisionShape()) in your CollisionShape class. Failure to do so will result in undefined runtime behavior when SphereShape is deleted through its base class pointer (a pointer to CollisionShape). Of course, since a virtual constructor is indeed added to a class's vtbl, I guess it's not beyond the realm of possibility that this is the culprit behind your error.
In Effective C++, Scott Meyers has the following to say.
The C++ language standard is unusually clear on this topic. When you try to delete a derived class object through a base class pointer and the base class has a nonvirtual destructor [...], the results are undefined. That means compilers may generate code to do whatever they like: reformat your disk, send suggestive mail to your boss, fax source code to your competitors, whatever. (What often happens at runtimme is that the derived class's destructor is never called. [...])
Due to the conflicting declarations of GetSceneNode, in your current code
virtual void GetSceneNode();
in the base class, and
SceneNode* GetSceneNode();
in the derived class, your code should not compile. You should not get to the linking stage. I'm pretty sure that the code that you're presenting is not your real code.
Hence, I downvoted the question.
But regarding the error that you evidently produced with some other code, it has been asked before on SO, and answered for example here.
Hence, I also voted to close the question.
Cheers & hth.,
This may not be the whole problem, but you are missing a return type on those functions. ie
virtual double GetPosition() = 0;