I've just learned about value-parametrized unit tests in googletest and would like to use them in my project.
I wrote a simple parametrized test.
Header:
#include <gtest/gtest.h>
namespace EnsembleClustering {
class ParametrizedGTest: public testing::TestWithParam<int> {
public:
ParametrizedGTest();
virtual ~ParametrizedGTest();
};
} /* namespace EnsembleClustering */
Source:
#include "ParametrizedGTest.h"
namespace EnsembleClustering {
ParametrizedGTest::ParametrizedGTest() {
// TODO Auto-generated constructor stub
}
ParametrizedGTest::~ParametrizedGTest() {
// TODO Auto-generated destructor stub
}
TEST_P(ParametrizedGTest, testParameter) {
int n = GetParam();
EXPECT_EQ(n, GetParam());
}
INSTANTIATE_TEST_CASE_P(ParametrizedGTestInstance,
ParametrizedGTest,
::testing::Values(100));
} /* namespace EnsembleClustering */
Now, when I run googletest as usual, the program crashes without any output. The gdb stack trace is
EnsembleClustering-D [C/C++ Application]
EnsembleClustering
Thread [1] (Suspended : Signal : EXC_BAD_ACCESS:Could not access memory)
__gnu_debug::_Safe_sequence_base::_M_attach_single() at 0x100528add
__gnu_debug::_Safe_sequence_base::_M_attach() at 0x100528a74
__gnu_debug::_Safe_iterator_base::_M_attach() at 0x100528bfe
__gnu_debug::_Safe_iterator_base::_Safe_iterator_base() at safe_base.h:90 0x1000016e9
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<testing::internal::ParameterizedTestCaseInfoBase**, std::__cxx1998::vector<testing::internal::ParameterizedTestCaseInfoBase*, std::allocator<testing::internal::ParameterizedTestCaseInfoBase*> > >, std::__debug::vector<testing::internal::ParameterizedTestCaseInfoBase*, std::allocator<testing::internal::ParameterizedTestCaseInfoBase*> > >::_Safe_iterator() at safe_iterator.h:154 0x100002e9c
std::__debug::vector<testing::internal::ParameterizedTestCaseInfoBase*, std::allocator<testing::internal::ParameterizedTestCaseInfoBase*> >::begin() at vector:207 0x100001fbe
testing::internal::ParameterizedTestCaseRegistry::GetTestCasePatternHolder<EnsembleClustering::ParametrizedGTest>() at gtest-param-util.h:574 0x1000025b0
EnsembleClustering::ParametrizedGTest_testParameter_Test::AddToRegistry() at ParametrizedGTest.cpp:22 0x100001d3f
__static_initialization_and_destruction_0() at ParametrizedGTest.cpp:22 0x100001349
_GLOBAL__sub_I_ParametrizedGTest.cpp() at ParametrizedGTest.cpp:32 0x100001424
<...more frames...>
gdb
Am I doing something wrong or is this a bug in googletest? Can you reproduce this error?
EDIT: I am on Mac OS X 10.8.
From looking at the source code of gtest the only case if there are no parametrized tests available is on Windows using VC7.1 with disabled exceptions:
// We don't support MSVC 7.1 with exceptions disabled now. Therefore
// all the compilers we care about are adequate for supporting
// value-parameterized tests.
#define GTEST_HAS_PARAM_TEST 1
So, you'll need to check how your MinGW was built and probably update it? And can you run the gtest unit tests to see if they execute the typed parameters test?
More information on MinGW:
On their FAQ they report that when using MinGW the following compile option for building gtest is required: PATH/TO/configure CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin".
Complete Example:
#include <gtest/gtest.h>
namespace EnsembleClustering {
class ParametrizedGTest: public testing::TestWithParam<int> {
public:
ParametrizedGTest();
virtual ~ParametrizedGTest();
};
ParametrizedGTest::ParametrizedGTest() {
}
ParametrizedGTest::~ParametrizedGTest() {
}
TEST_P(ParametrizedGTest, testParameter) {
int n = GetParam();
EXPECT_EQ(n, GetParam());
}
INSTANTIATE_TEST_CASE_P(ParametrizedGTestInstance,
ParametrizedGTest,
::testing::Values(100));
} /* namespace EnsembleClustering */
int main(int argc, char* argv[]) {
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
I compiled this code using the following compiler call on Mac OS X 10.8:
g++ -IGTEST_INCLUDE_DIR -LGTEST_LIB_DIR -lgtest -o tt2 tt2.cpp
Where GTEST_INCLUDE_DIR and GTEST_LIB_DIR are the path where header and library files are stored. When you compile and execute, what happens?
Thanks #ChristianStaudt and #grundprinzip
I would like to point future readers to following link that explains this problem.
http://libcwd.sourceforge.net/reference-manual/group__enable__glibcxx__debug.html
This is a link to the documentation for GLIBCXX_DEBUG flag. It states the following important points.
"Note that this flag changes the sizes and behavior of standard class templates such as std::vector, and therefore you can only link code compiled with debug mode and code compiled without debug mode if no instantiation of a container is passed between the two translation units."
"When to use it
It is a good idea to use this if you suspect problems related to iterators."
Now, if you look at the stack trace posted originally, the crash happens due to vector<testing::internal::ParameterizedTestCaseInfoBase*> as gtest tries to get an iterator on this container, using begin() method.
In my case, gtest lib was compiled without GLICXX_DEBUG flag, but my test code was compiled with this flag. The test code worked like a charm when I compiled without this flag.
Related
I've wasted many hours to resolve this problem, but without success. At first, my configuration: Ubuntu 16.04.1, qmake 3.0, cmake 3.5.1, shared gtest and gmock libraries, version 1.8.0. I use Qt Creator, and this is a little example of minimal program that lead to the crush.
main.cpp:
#include <iostream>
#include <gtest/gtest.h>
#include <gmock/gmock.h>
using namespace std;
class A {
void print() {
std::cout << "PRINT" << std::endl;
}
};
class B: public A {
MOCK_METHOD0(print, void());
};
TEST(MOCK, TEST) {
B b;
}
int main(int argc, char *argv[])
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
google_test.pro:
TEMPLATE = app
CONFIG += console c++11
CONFIG -= app_bundle
CONFIG -= qt
SOURCES += main.cpp
LIBS += -lgtest -lgmock
Tests are OK, but at the end of program I get this error:
* Error in `/home/aminought/QtProjects/build-google_test-Desktop_Qt_5_7_0_GCC_64bit-Debug/google_test': double free or corruption (!prev): 0x0000000001a51270 *
How to fix this error? Very annoying.
This problem occurs only with google test compiled as shared libraries. I don't know why, but simple replacement of shared libraries to static solves the problem.
It's been a few years since this was posted.
I could not recreate the exact problem you are having,
but recently I have come across the same error message, in
a different scenario.
The problem was, that I purposely made an override to
TearDown(), freeing a protected member of a fixture class,
which resulted in double freeing pointers. It seems that
googletest is keeping track of allocated memory and tries
to free everything automatically, even though my TearDown()
override already did previously. Removing the override solved
the problem for me.
I hope it will be useful for someone sometime in the future.
In my case, dynamic linking did not have any effect.
I follow the instructions for build xerces in linux
./configure
make
make install
But I'm trying to run the first example from Programming Guide
#include <xercesc/util/PlatformUtils.hpp>
// Other include files, declarations, and non-Xerces-C++ initializations.
using namespace xercesc;
int main(int argc, char* argv[])
{
try {
XMLPlatformUtils::Initialize();
}
catch (const XMLException& toCatch) {
// Do your failure processing here
return 1;
}
// Do your actual work with Xerces-C++ here.
XMLPlatformUtils::Terminate();
// Other terminations and cleanup.
return 0;
}
But I'm getting a few errors:
=== Build: Debug in vasprun_xml (compiler: GNU GCC Compiler) ===
vasprun_xml/main.cpp|22|reference to `xercesc_3_1::XMLUni::fgXercescDefaultLocale' not define
vasprun_xml/main.cpp 22reference to `xercesc_3_1::XMLPlatformUtils::Initialize(char const*, char const*, xercesc_3_1::PanicHandler*, xercesc_3_1::MemoryManager*)' not define
How can I solve this issues?
Anon Mail has reason.
The problem is that Code::Blocks not auto detect system dynamic library.
We need go to
Project->Build Options->Linker Settings
and than add the the name of your library (in our case xerces-c-3.1) without lib prefix. Ok and than build and run without erros.
Is like do
g++ -o main main.cpp /path-to-your-lib/src/.libs/libxerces-c-3.1.so
I'm using Google Test and Google Mock to write code using Test Driven Development. I'm writing a small "plugin" for Google Test. To make sure the tests would fail when expected with the correct message, I created a simple FailureReporter class that I would sub-class and inject a mock version in the plugin to capture the results and compare with expected values.
In the spirit of TDD extremism, I also wrote a test to make sure the FailureReporter worked. To do this, I "replaced" the FAIL() macro in order to not cause a failure but to capture the resulting error message. However, this is where things became strange. It was working on one machine but not on another. While searching for the cause I discovered that it could be fixed by changing the link order. This seems strange, because the "fix" is done using macros, and I would assume that it would be hard coded at compile time, and linking it wouldn't make a difference.
What I found out was that: linking the test by itself causes no problems. Linking it with a test that uses the mock version of FailureReporter only works if the other test is linked after the FailureReporterTest. Why does this happen?
FailureReporter.hpp:
#ifndef FAILURE_REPORTER_H
#define FAILURE_REPORTER_H
#include "gtest/gtest.h"
class FailureReporter {
public:
virtual void fail(const char* errorMessage) {
FAIL() << errorMessage;
}
};
#endif
FailureReporterTest.cpp:
#include <sstream>
#include "gtest/gtest.h"
static std::stringstream* failStream;
#ifdef FAIL
#undef FAIL
#endif
#define FAIL() *failStream << ""
#include "FailureReporter.hpp"
TEST(FailureReporterTest, failMethod) {
const char* errorMessage = "Test error message";
FailureReporter *reporter;
std::stringstream stream;
failStream = &stream;
reporter = new FailureReporter();
reporter->fail(errorMessage);
EXPECT_STREQ(errorMessage, stream.str().c_str());
delete reporter;
}
MockFailureReporter.cpp
#ifndef MOCK_FAILURE_REPORTER_HPP
#define MOCK_FAILURE_REPORTER_HPP
#include "gmock/gmock.h"
#include "FailureReporter.hpp"
class MockFailureReporter : public FailureReporter {
public:
MOCK_METHOD1(fail, void(const char*));
};
#endif
DummyTest.cpp
#include "gtest/gtest.h"
#include "MockFailureReporter.hpp"
TEST(DummyTest, dummy) {
new MockFailureReporter();
SUCCEED();
}
Compiling the sources with
g++ -c DummyTest.cpp
g++ -c FailureReporterTest.cpp
and linking them with
g++ DummyTest.o FailureReporterTest.o -pthread -lgtest -lgmock -lgmock_main
generates an a.out executable that fails the failMethod test, while linking them with
g++ FailureReporterTest.o DummyTest.o -pthread -lgtest -lgmock -lgmock_main
generates an a.out executable that succeeds both tests. Why?
class FailureReporter {
public:
virtual void fail(const char* errorMessage) {
/* code */
creates an implicitly inline implementation of FailureReporter::fail.
inline functions are exported. If the linker sees two inline functions of the same name and type, it will silently discard one. If they are not actually identical, then your program is ill formed, and no diagnostic is required.
When you redefine FAIL() in only one compilation unit and link it with others, you end up with two definitions of FailureReporter::fail. They link, and undefined behaviour results. In your case, you get one of them running in both cases, determined bu whatever arbitrary rule the linker chose to discard inline collisions. Which looks like 'keep first one I see'.
I want to learn using google test framework with everyday projects, so I looked up a few tutorials, but I have no idea how to get started.
I'm using Qtcreator in Ubuntu 14.04, I downloaded gtest.zip from the google site and unzipped it, but here is where it all stoped.
This is the code i want to "gtest":
//main.cpp
#include <iostream>
#include <cstdlib>
#include "fib.h"
using namespace std;
int main(int argc, char *argv[])
{
int n = atof(argv[1]);
fib fibnumber;
cout << "\nDesired number is: " << fibnumber.fibRec(n) << endl;
}
//fib.h
#ifndef FIB_H
#define FIB_H
class fib
{
public:
int fibRec(int n);
};
#endif // FIB_H
//fib.cpp
#include "fib.h"
int fib::fibRec(int n)
{
if(n <= 0) return 0;
if(n == 1) return 1;
else return(fibRec(n-1)+fibRec(n-2));
}
So where do i even begin, I want to make unit test and compile it without any plugins, but i don't know how to make use of the file I unzipped and then use it to write a unit test.
The google Testing framework works by building it as part of your source code. That means there is no library that you have to link to, instead you build the library when you compile your code (there is a good reason for this).
Have a look at the official documentation:
https://github.com/google/googletest/blob/master/googletest/docs/primer.md
Steps
Try to build a test testcase for your program. I can't tell you how to do it with Qtcreator but that should be easy enough to find. Create a test that will definitely fail, like the one below.
TEST(MyFirstTest, ThisTestShallFail) {
EXPECT_EQ(1, 2);
}
Run this very simple test to check that it fails. If you want, change it to make it pass.
Start creating your unit tests. Check for a few easy number. Check boundary conditions etc.
In addition to #Unapiedra's suggestions, I would suggest to write a separate test file and a separate source/implementation file to test the code with google test framework and link the project using a build system or better a build generator system.
My example below demonstrates this using a cmake build generator. (My assumption here is that the user is familiar with cmake)
Note: although in practice it is recommended to write code incrementally using the Test Driven Development philosophy, I don't do it since the purpose here is to show how a simple unit test can be written and compiled using google test framework.
charOperations.hpp
#ifndef CHAR_OPERATIONS_H
#define CHAR_OPERATIONS_H
#incude <string>
class CharOperations{
private :
// ...
public:
//converts lower case characters to upper case
// and returns a std::string object from this
std::string convertToUpper(const char letter){
char upCase = std::toupper(static_cast<unsigned char>(letter));
return std::string(1, upCase);
}
//converts upper case characters to lower case
// and returns a std::string object from this
std::string convertToLower(const char letter){
char loCase = std::tolower(static_cast<unsigned char>(letter));
return std::string(1, loCase);
}
// more functions ...
};
#endif //class definition ends
test_example.cpp
#include <gtest/gtest.h>
#include <gmock/gmock.h>
#include "CharOperations.hpp"
//declare a test fixture so that the object
// CharOperation need not be declared in each test
//Each test fixture has to be publicly derived from
// testing::Test
class CharOperationsTest : public testing::Test{
//class object public so that it is accessible
//within the tests that are written
public:
CharOperations charOps;
};
// now write the tests using macro TEST_F
// which is used for testing with test fixtures
//1st parameter to TEST_F is the name of the fixture
//second parameter to TEST_F is the name of the test
//each test has to have a unique name.
//test #1
TEST_F(CharOperationsTest, ConvertsCharToUpperCaseString){
ASSERT_THAT(charOps.convertToUpper('a') testing::Eq("A");
}
//test #2
TEST_F(CharOperationsTest, ConvertsCharToLowerCaseString){
ASSERT_THAT(charOps.convertToLower('A') testing::Eq("a");
}
//more tests ...
//run all tests
int main(int argc, char **argv){
testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.2.3)
project(TDD CXX)
enable_testing()
set(CMAKE_CXX_STANDARD 11)
find_package(PkgConfig REQUIRED)
pkg_check_modules(gtest REQUIRED gtest>=1.8.1)
pkg_check_modules(gmock REQUIRED gmock>=1.8.1)
include_directories(${gtest_INCLUDE_DIRS})
include_directories(${gmock_INCLUDE_DIRS})
add_executable(test.out ##target executable name
test_example.cpp
)
target_link_libraries(test.out ${gtest_LIBRARIES})
A general suggestion for writing tests: It can be observed in the file test_example.cpp, the Macros/Functions Test. Eq and InitGoogleTests reside under the namespace testing. Hence it might be prudent to declare a using namespace testing declaration at the beginning of the file after all #includes. Lastly needles to say to compile in a separate build directory
I am now using Boost Unit Test to perform unit test for my project. Every time I run the unit test, I got a memory stack problem. I debug into the source code of BOOST library, and I find that the problem comes from invoking the following codes in unit_test_suite.hpp file:
void
traverse_test_tree( test_unit_id id, test_tree_visitor& V )
{
global_i = global_i + 1;
std::cout<<global_i<<std::endl;
if( ut_detail::test_id_2_unit_type( id ) == tut_case )
traverse_test_tree( framework::get<test_case>( id ), V );
else
traverse_test_tree( framework::get<test_suite>( id ), V );
}
The error information I have obtained from VC10 is:
Unhandled exception at 0x779815de in TestApplication.exe: 0xC00000FD: Stack overflow.
I was wondering what's wrong with the test program. Thanks!
EDIT Based on the suggestions I looked through my codes, and very strange things happen: if the test suite is defined in same program with main(), it works; however, if the test suite is from a .dll, the error will occur. I list the following codes to illustrate my problem:
boost::unit_test::test_suite* main_global_test_suite;
void Hellotestdll()
{
int i= 1;
int j= 2;
BOOST_CHECK(i == j);
}
boost::unit_test::test_suite* get_abc_test_suite()
{
test_suite* ts = BOOST_TEST_SUITE( "unit_geometric" );
ts->add( BOOST_TEST_CASE( &Hellotestdll ) );
return ts;
}
int main( int argc, char* argv[] )
{
try
{
/**
* Step 1. obtain options
*/
char* optionLine[1024];
int len;
len = obtain_options(optionLine, argc, argv);
/**
* Step 2. perform unit test based on user's options
*/
int test_status=0;
main_global_test_suite = get_abc_test_suite();
test_status = unit_test_main(run_global_test_suite, len, optionLine);
return test_status;
}
catch(std::exception& e)
{
std::cout << e.what() << std::endl;
return 1;
}
catch (const std::string& s)
{
std::cout << s << std::endl;
return 1;
}
catch (...)
{
return 1;
}
}
The above codes work very well. But if the test suite is from a .dll, for example:
// dll_header.h
namespace abc
{
ABC_EXPORT boost::unit_test::test_suite* get_geometric_test_suite();
}
// dll_header.cpp
namespace abc
{
using namespace boost;
using namespace boost::unit_test;
void Hellotestdllabc()
{
int i= 1;
int j= 2;
BOOST_CHECK(i == j);
}
boost::unit_test::test_suite* get_abc_test_suite()
{
test_suite* ts = BOOST_TEST_SUITE( "unit_abc" );
ts->add( BOOST_TEST_CASE( &Hellotestdllabc ) );
return ts;
}
}
Then if I invoke this test suite, with the following codes:
int main( int argc, char* argv[] )
{
............
/**
* Step 2. perform unit test based on user's options
*/
int test_status=0;
main_global_test_suite = abc::get_abc_test_suite();
test_status = unit_test_main(run_global_test_suite, len, optionLine);
return test_status;
}
The annoying stack overflow error will happen.
Summery of the Problems
(1) boost dll with MDd (Succeed)
If I link the boost unit test library (with the definition -DBOOST_ALL_DYN_LINK -DBOOST_TEST_NO_MAIN -DBOOST_TEST_DYN_LINK -DBOOST_ALL_NO_LIB)and the running executable program with the same dynamic run-time library (Multi-thread Debug Dll (MDd)), it will work.
(2) boost dll with MTd (Failed)
If the boost unit test library (with the definition -DBOOST_ALL_DYN_LINK -DBOOST_TEST_NO_MAIN -DBOOST_TEST_DYN_LINK -DBOOST_ALL_NO_LIB)and the running executable program are compiled and link with the same static run-time libray (Multi-thred Debu (MTd)), I will have a crash, but the crash is different from the one I reported above:
(3) boost static lib with MDd (Failed)
If the boost is built as a static library (with the definition of -DBOOST_TEST_NO_MAIN -DBOOST_ALL_NO_LIB), and both the boost library and the executable program are built with the same dynamic run-time library (MDd). The following crash will happen:
(4) boost static lib with MTd (Failed)
If the boost is built as a static library (with the definition of -DBOOST_TEST_NO_MAIN -DBOOST_ALL_NO_LIB), and both the boost library and the executable program are built with the same static run-time library (MTd). The following crash will happen:
ABC_EXPORT boost::unit_test::test_suite* get_geometric_test_suite();
The point of unit tests is to find problems in code early. That worked, it is just that you found the problem very early. Too early to even allow the unit test to run properly.
Functions in a DLL that returns pointers to C++ objects are a problem in general. It will only come to a good end when the layout of the C++ object exactly matches the assumptions made by the compiler when it compiled both your DLL and your EXE. And that the object lives on a heap that both modules have access to, required since the DLL creates the object and your EXE needs to delete it.
To allow the object to be properly deleted, both the DLL and the EXE must share the same CRT version. You will get into trouble when you build your program with /MT, asking for the static version of the CRT. The relevant compiler setting is C/C++, Code Generation, Runtime library setting. Your Debug configuration must use /MDd, your Release configuration must use /MD. For both the EXE and the DLL project, as well as the Boost library when it was compiled. If it is /MTd and /MT then the DLL will have its own copy of the CRT linked into it and will use its own heap to allocate from. The EXE cannot properly delete the object since it uses another heap. Doing so anyway will produce undefined behavior. Anything can happen, you tend to only get lucky when you run your program on a version of Windows that's newer than XP. Vista and up will use a debug heap when you run your unit test with a debugger attached, it invokes a breakpoint when it notices that the pointer passed to ::operator delete is invalid. Be sure to allow the linker to automatically find the correct Boost .lib to link to, don't force it yourself.
Object layout is more likely your problem, unfortunately much harder to diagnose. You stay out of trouble by building your EXE and DLL with the exact same compiler settings. With the additional requirement that they must match the settings that were used to build the Boost libraries. Which certainly is the difficult part, that requires a time machine. Particularly the _HAS_ITERATOR_DEBUGGING macro is a troublemaker, basic STL classes like std::vector will have a different layout that depends on the value of that macro.
I realize this is very vague, but there isn't enough info in the question to truly diagnose this issue. A very basic check you can do is putting the returned boost::unit_test::test_suite pointer in a watch expression. If you suddenly see the members of that object change when you step into Boost code then you know you have an object layout problem. What happens next is highly unpredictable, a stack overflow is certainly possible. Yet another diagnostic is to use the Debug + Windows + Registers window. Ensure that the ESP register value is stable when you step over functions.