Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Infinite Loop when calling a mock function that takes boost::filesystem::path as parameter #521

Closed
BillyDonahue opened this issue Aug 25, 2015 · 13 comments

Comments

@BillyDonahue
Copy link
Contributor

From @GoogleCodeExporter on August 24, 2015 22:40

Minimal example:

---------------------
#include "gtest/gtest.h"
#include "gmock/gmock.h"
#include <boost/filesystem.hpp>

class MyMock {
public:
  MOCK_METHOD1(func, void(const boost::filesystem::path &path));
};

TEST(MyTest, mockTest) {
  MyMock mock;
  mock.func(boost::filesystem::path("/myfile"));
}
-------------------

When running this test (using gtest 1.7.0 and gmock 1.7.0 on linux 64bit with 
g++ (Ubuntu 4.9.1-16ubuntu6)), it aborts with a SIGSEV.
gdb shows that the SIGSEV is raised in malloc(), while the stack is very large 
and contains a short periodic set of functions calling each other in a circle. 
I assume there is an infinite loop.

The interesting part of the stacktrace is here:


#0  _int_malloc (av=0x7ffff703a760 <main_arena>, bytes=26) at malloc.c:3302
#1  0x00007ffff6cff1e0 in __GI___libc_malloc (bytes=26) at malloc.c:2891
#2  0x00007ffff72b7688 in operator new(unsigned long) () from 
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007ffff731b669 in std::string::_Rep::_S_create(unsigned long, unsigned 
long, std::allocator<char> const&) () from 
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007ffff731b6f4 in std::string::_M_mutate(unsigned long, unsigned long, 
unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007ffff731bd2e in std::string::_M_replace_safe(unsigned long, unsigned 
long, char const*, unsigned long) () from 
/usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007ffff731d1f9 in std::string::replace(unsigned long, unsigned long, 
char const*, unsigned long) () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#7  0x00007ffff7779821 in boost::filesystem::path::begin() const () from 
/usr/lib/x86_64-linux-gnu/libboost_filesystem.so.1.55.0
#8  0x00000000004c3cd4 in 
testing::internal::DefaultPrintTo<boost::filesystem::path> (container=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:275
#9  0x00000000004c3846 in testing::internal::PrintTo<boost::filesystem::path> 
(value=..., os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:376
#10 0x00000000004c2ea6 in 
testing::internal::UniversalPrinter<boost::filesystem::path>::Print (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:600
#11 0x00000000004c237d in 
testing::internal::UniversalPrint<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:756
#12 0x00000000004c3d37 in 
testing::internal::DefaultPrintTo<boost::filesystem::path> (container=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:287
#13 0x00000000004c3846 in testing::internal::PrintTo<boost::filesystem::path> 
(value=..., os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:376
#14 0x00000000004c2ea6 in 
testing::internal::UniversalPrinter<boost::filesystem::path>::Print (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:600
#15 0x00000000004c237d in 
testing::internal::UniversalPrint<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:756
#16 0x00000000004c3d37 in 
testing::internal::DefaultPrintTo<boost::filesystem::path> (container=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:287

[...many more repetitions of these lines..]

#116387 0x00000000004c237d in 
testing::internal::UniversalPrint<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:756
#116388 0x00000000004c3d37 in 
testing::internal::DefaultPrintTo<boost::filesystem::path> (container=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:287
#116389 0x00000000004c3846 in 
testing::internal::PrintTo<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:376
#116390 0x00000000004c2ea6 in 
testing::internal::UniversalPrinter<boost::filesystem::path>::Print (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:600
#116391 0x00000000004c237d in 
testing::internal::UniversalPrint<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:756
#116392 0x00000000004c3d37 in 
testing::internal::DefaultPrintTo<boost::filesystem::path> (container=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:287
#116393 0x00000000004c3846 in 
testing::internal::PrintTo<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:376
#116394 0x00000000004c2ea6 in 
testing::internal::UniversalPrinter<boost::filesystem::path>::Print (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:600
#116395 0x00000000004c237d in 
testing::internal::UniversalPrint<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:756
#116396 0x00000000004c3d37 in 
testing::internal::DefaultPrintTo<boost::filesystem::path> (container=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:287
#116397 0x00000000004c3846 in 
testing::internal::PrintTo<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:376
#116398 0x00000000004c2ea6 in 
testing::internal::UniversalPrinter<boost::filesystem::path>::Print (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:600
#116399 0x00000000004c237d in 
testing::internal::UniversalPrint<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:756
#116400 0x00000000004c3d37 in 
testing::internal::DefaultPrintTo<boost::filesystem::path> (container=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:287
#116401 0x00000000004c3846 in 
testing::internal::PrintTo<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:376
#116402 0x00000000004c2ea6 in 
testing::internal::UniversalPrinter<boost::filesystem::path>::Print (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:600
#116403 0x00000000004c237d in 
testing::internal::UniversalPrint<boost::filesystem::path> (value=..., 
os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:756
#116404 0x00000000004c22d0 in 
testing::internal::UniversalPrinter<boost::filesystem::path const&>::Print 
(value=..., os=0x7fffffffd720) at 
/home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/
gtest-printers.h:668
#116405 0x00000000004c0d81 in 
testing::internal::TuplePrefixPrinter<1ul>::PrintPrefixTo<std::tuple<boost::file
system::path const&> > (t=std::tuple containing = {...}, os=0x7fffffffd720)
    at /home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/gtest-printers.h:810
#116406 0x00000000004bfe71 in 
testing::internal::PrintTupleTo<std::tuple<boost::filesystem::path const&> > 
(t=std::tuple containing = {...}, os=0x7fffffffd720)
    at /home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/gtest-printers.h:827
#116407 0x00000000004bd1e5 in 
testing::internal::PrintTo<boost::filesystem::path const&> (t=std::tuple 
containing = {...}, os=0x7fffffffd720)
    at /home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/gtest-printers.h:503
#116408 0x00000000004b8eaa in 
testing::internal::UniversalPrinter<std::tuple<boost::filesystem::path const&> 
>::Print (value=std::tuple containing = {...}, os=0x7fffffffd720)
    at /home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/gtest-printers.h:600
#116409 0x00000000004b66a6 in 
testing::internal::UniversalPrint<std::tuple<boost::filesystem::path const&> > 
(value=std::tuple containing = {...}, os=0x7fffffffd720)
    at /home/heinzi/workspace_cpp/cryfs/build.debug/test/gtest/src/gtest/include/gtest/gtest-printers.h:756
#116410 0x00000000004b4e8b in testing::internal::FunctionMockerBase<void 
(boost::filesystem::path const&)>::UntypedDescribeUninterestingCall(void 
const*, std::ostream*) const (this=0x7fffffffd950, untyped_args=0x7fffffffd8f0, 
    os=0x7fffffffd720) at /home/heinzi/workspace_cpp/cryfs/build.debug/test/gmock/src/gmock/include/gmock/gmock-spec-builders.h:1604
#116411 0x000000000050204d in 
testing::internal::UntypedFunctionMockerBase::UntypedInvokeWith(void const*) ()
#116412 0x00000000004af8af in testing::internal::FunctionMockerBase<void 
(boost::filesystem::path 
const&)>::InvokeWith(std::tuple<boost::filesystem::path const&> const&) 
(this=0x7fffffffd950, args=std::tuple containing = {...})
    at /home/heinzi/workspace_cpp/cryfs/build.debug/test/gmock/src/gmock/include/gmock/gmock-spec-builders.h:1529
#116413 0x00000000004ad301 in testing::internal::FunctionMocker<void 
(boost::filesystem::path const&)>::Invoke(boost::filesystem::path const&) 
(this=0x7fffffffd950, a1=...)
    at /home/heinzi/workspace_cpp/cryfs/build.debug/test/gmock/src/gmock/include/gmock/gmock-generated-function-mockers.h:97
#116414 0x00000000004c8d7f in MyMock::func (this=0x7fffffffd950, gmock_a1=...) 
at /home/heinzi/workspace_cpp/cryfs/src/test/fspp/test.cpp:7
---Type <return> to continue, or q <return> to quit---
#116415 0x00000000004c8b84 in MyTest_mockTest_Test::TestBody (this=0x75bd10) at 
/home/heinzi/workspace_cpp/cryfs/src/test/fspp/test.cpp:12
#116416 0x00000000004f34a2 in void 
testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, 
void>(testing::Test*, void (testing::Test::*)(), char const*) ()
#116417 0x00000000004ee2b7 in void 
testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, 
void>(testing::Test*, void (testing::Test::*)(), char const*) ()
#116418 0x00000000004d429b in testing::Test::Run() ()
#116419 0x00000000004d4b1b in testing::TestInfo::Run() ()
#116420 0x00000000004d51f0 in testing::TestCase::Run() ()
#116421 0x00000000004dbe42 in testing::internal::UnitTestImpl::RunAllTests() ()
#116422 0x00000000004f4a65 in bool 
testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::Uni
tTestImpl, bool>(testing::internal::UnitTestImpl*, bool 
(testing::internal::UnitTestImpl::*)(), char const*) ()
#116423 0x00000000004ef14f in bool 
testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTe
stImpl, bool>(testing::internal::UnitTestImpl*, bool 
(testing::internal::UnitTestImpl::*)(), char const*) ()
#116424 0x00000000004da96e in testing::UnitTest::Run() ()
#116425 0x00000000004fe856 in RUN_ALL_TESTS() ()
#116426 0x00000000004fe7f1 in main ()

Original issue reported on code.google.com by heinzis...@gmail.com on 18 Nov 2014 at 6:27

Copied from original issue: google/googlemock#170

@BillyDonahue
Copy link
Contributor Author

From @GoogleCodeExporter on August 24, 2015 22:40

btw I'm using libboost-filesystem in version 1.55

Original comment by heinzis...@gmail.com on 18 Nov 2014 at 6:29

@BillyDonahue
Copy link
Contributor Author

From @GoogleCodeExporter on August 24, 2015 22:40

Can you make an even more minimal example that doesn't depend on Boost?
I'd like to know what it is about boost::filesystem::path that makes this 
happen.

Original comment by billydon...@google.com on 18 Nov 2014 at 6:33

@BillyDonahue
Copy link
Contributor Author

From @GoogleCodeExporter on August 24, 2015 22:40

I tried to, but gave up after some hours. It is quite complicated to resolve 
all the inner boost dependencies, boost::filesystem::path is having.

Original comment by heinzis...@gmail.com on 18 Nov 2014 at 8:12

@BillyDonahue
Copy link
Contributor Author

From @GoogleCodeExporter on August 24, 2015 22:40

I have this bug too.
The problem in function DefaultPrintTo(IsContainerTest<T>(0), is_pointer<T>(), 
value, os); [gmock-printers.h]. This function calls infinity times, because it 
desides that boost::filesystem::path is container (has cons_iterator), then 
takes first element: it = container.begin(), and then calls DefaultPrintTo(..., 
*it, ) again (subsequented call) - and we have infifnity calls loop, because 
the value_type of path iterator is - path !!!! (we have infinity nested 
containers)

Original comment by ibez...@gmail.com on 23 Apr 2015 at 3:29

@BillyDonahue
Copy link
Contributor Author

From @GoogleCodeExporter on August 24, 2015 22:40

This bug can also be triggered in Visual Studio 2012 with boost 1.51 gmock 
1.7.0.

You can work around this bug if you define a PrintTo function. Defining a 
PrintTo function is described in 
https://code.google.com/p/googletest/wiki/AdvancedGuide#Teaching_Google_Test_How
_to_Print_Your_Values

I use the following PrintTo function:

namespace boost {
    namespace filesystem {
        void PrintTo(const boost::filesystem::path& path, std::ostream* os) {
            *os << path;
        }
    }
}

Original comment by hb2...@googlemail.com on 20 May 2015 at 1:32

@Dani-Hub
Copy link
Contributor

It seems that the root of the problem is the incorrect assumption that IsContainerTest is only interested whether template parameter C is a "Container", but actually it should discriminate "RecursiveContainer" and "NonRecursiveContainer", where only the second one should be directed into DefaultPrintTo(IsContainer, ..). IMO the first category should simply defer to operator<<; this would solve the problem for any filesystem::path type or other recursive containers.

I once implemented a trait like this even with C++03 restrictions. Given the declarations within <gtest/gtest.h> I could imagine to create such a MP facility based on the existing Types tuple-like template plus the following additional n-ary MP constructs: contains, or_, and concat.

What do you think of such an approach?

@BillyDonahue
Copy link
Contributor Author

Sorry I don't get it.

On Sunday, December 20, 2015, Daniel Krügler notifications@github.com
wrote:

It seems that the root of the problem is the incorrect assumption that
IsContainerTest is only interested whether template parameter C is a
"Container", but actually it should discriminate "RecursiveContainer" and
"NonRecursiveContainer",

Meaning what?

where only the second one should be directed into DefaultPrintTo(IsContainer,
..). IMO the first category should simply defer to operator<<; this would
solve the problem for any filesystem::path type or other recursive
containers.

I once implemented a trait like this even with C++03 restrictions.

I'd have to see that.
I thought we need Decltype to detect operators.

Given the declarations within <gtest/gtest.h> I could imagine to create
such a MP facility based on the existing Types tuple-like template plus
the following additional n-ary MP constructs: contains, or_, and concat.

What do you think of such an approach?


Reply to this email directly or view it on GitHub
#521 (comment).

@Dani-Hub
Copy link
Contributor

In the context of this issue I would define a "RecursiveContainer" as a type that is a "Container" (as defined by the simple definition provided by the IsContainerTest function) that has the property that it has a value type (Defined by std::iterator_traits<typename C::iterator>::value_type, since as a "Container" it is guaranteed to have C::iterator [see IsContainerTest]), that is equal to one of it's "parent" container types. In other words: While searching through the chain of "value types" create a type list of these until you either reach an end (not recursive) or you find another value type that is already contained in the list of value types (recursive).

For example, both boost::filesystem::path as well as std::experimental::filesystem::path are recursive containers C, because std::iterator_traits<C::iterator>::value_type is equal to C. Same thing for std::vector<boost::filesystem::path> (Here at the second level, not at the first one) or for a possible user-defined type similar to the following one:

struct Funny
{
  struct Other
  {
    typedef std::list<Funny>::const_iterator iterator;
    typedef iterator const_iterator;
  };
  typedef std::vector<Other>::const_iterator iterator;
  typedef iterator const_iterator;
};

I don't understand your assertion regarding operators and decltype. First, there are non-SFINAE ways that work even with old compilers to deduce the existence of an available operator<< overload given the tested argument types. But in this case I would simply create a compile-error (instead of a runtime stack overflow), if no PrintTo function has been selected. Instead of deciding for "Container" and select (unconditionally) DefaultPrintTo(IsContainer, ..), just introduce a further splitting into DefaultPrintTo(IsNonRecursiveContainer, ..) and DefaultPrintTo(IsRecursiveContainer, ..), where the latter one doesn't go recursively through the chain of internal::UniversalPrint calls. I'm aware that this is just a sketch and possibly not easy to understand without looking at a concrete implementation, but I hope I have roughly clarified what kind of source changes would be necessary. If not, please try to ask more specific question (but be aware that I have not written the full solution yet).

The most critical decision would be (IMO) whether the increase of complexity to determine a "RecursiveContainerType", depending on something like the existing Types tuple-like type and the above mentioned MT helpers would seem acceptable to realize the goal. If so, I would try to make a more concrete suggestion (Presumably not before start of the next year, but the mentioned problem is an old and nasty one, so I hope the additional time needed to see something is worth waiting for it).

@BillyDonahue
Copy link
Contributor Author

On Sun, Dec 20, 2015 at 10:43 AM, Daniel Krügler notifications@github.com
wrote:

In the context of this issue I would define a "RecursiveContainer" as a
type that is a "Container" (as defined by the simple definition provided by
the IsContainerTest function) that has the property that it has a value
type (Defined by std::iterator_traits::value_type,
since as a "Container" it is guaranteed to have C::iterator [see
IsContainerTest]), that is equal to one of it's "parent" container types.
In other words: While searching through the chain of "value types" create a
type list of these until you either reach an end (not recursive) or you
find another value type that is already contained in the list of value
types (recursive).

OH! I didn't know we had such beasts.

One quick question: is it possible for such a detection to not terminate?
That is, are there containers for which the nested value types get more
complex the more you dig in a way that doesn't repeat? It seems like it
might be possible.

For example, both boost::filesystem::path as well as
std::experimental::filesystem::path are recursive containers C, because
std::iterator_traits<C::iterator>::value_type is equal to C. Same thing
for std::vectorboost::filesystem::path (Here at the second level, not
at the first one) or for a possible user-defined type similar to the
following one:

struct Funny
{
struct Other
{
typedef std::list::const_iterator iterator;
typedef iterator const_iterator;
};
typedef std::vector::const_iterator iterator;
typedef iterator const_iterator;
};

I don't understand your assertion regarding operators and decltype.

First, there are non-SFINAE ways that work even with old compilers to
deduce the existence of an available operator<< overload given the tested
argument types.

It sounds like you understand me and you think I'm wrong. That's a little
different. :)
I don't think I know how to do the kind of deduction you're suggesting, but
I'd like to see it.

But in this case I would simply create a compile-error (instead of a
runtime stack overflow), if no PrintTo function has been selected.
Instead of deciding for "Container" and select (unconditionally) DefaultPrintTo(IsContainer,
..), just introduce a further splitting into DefaultPrintTo(IsNonRecursiveContainer,
..) and DefaultPrintTo(IsRecursiveContainer, ..), where the latter one
doesn't go recursively through the chain of internal::UniversalPrint
calls. I'm aware that this is just a sketch and possibly not easy to
understand without looking at a concrete implementation, but I hope I have
roughly clarified what kind of source changes would be necessary. If not ,
please try to ask more specific question (but be aware that I have not
written the full solution yet).

The most critical decision would be (IMO) whether the increase of
complexity to determine a "RecursiveContainerType", depending on something
like the existing Types tuple-like type and the above mentioned MT
helpers would seem acceptable to realize the goal. If so, I would try to
make a more concrete suggestion (Presumably not before start of the next
year, but the mentioned problem is an old and nasty one, so I hope the
additional time needed to see something is worth waiting for it).

ok.

@Alexhuszagh
Copy link

Considering that most compilers have now implemented <experimental/filesytem>, signifying that containers with recursive versions of themselves as iterators are now a part of the standard library, it would be a good point to re-reference this issue.

Using gcc or clang, I can reproduce this with a simple file. Save the following code snippet to a.cpp:

#include <experimental/filesystem>
#include <gtest/gtest.h>

namespace fs = std::experimental::filesystem;


int main()
{
    fs::path p1("/lib/libc.so.6");
    fs::path p2("/lib/libnsl.so");
    EXPECT_TRUE(p1 == p2);      // fine
    EXPECT_EQ(p1, p2);          // infinite loop

    return 0;
}

Then, compile and run:

$ g++ a.cpp -lstdc++fs -gtest
$ ./a.out 
a.cpp:15: Failure
Value of: p1 == p2
  Actual: false
Expected: true
Segmentation fault (core dumped)

I'm not sure what the best solution would be (maybe SFINAE detection if the std::is_same<std::iterator_traits<T>::value_type, T>, with a specialized handler or throw a compile-time error), but I feel this issue should at least be considered...

@Dani-Hub
Copy link
Contributor

Yes, sorry, my intention was to work on that issue myself, but I lost the track of it. Thanks for the reminder!

Dani-Hub added a commit to Dani-Hub/googletest that referenced this issue Aug 9, 2017
Dani-Hub added a commit to Dani-Hub/googletest that referenced this issue Aug 9, 2017
…em::path as parameter google#521: Add is_same type trait and prevent infinite loops for recursive containers
@Dani-Hub
Copy link
Contributor

Dani-Hub commented Aug 9, 2017

I prepared a pull request (Prevent infinite loops for recursive containers like boost::filesystem::path #1186) which has passed all travis tests and I signed the CLA. The solution is simpler than I originally thought: The suggested fix simply prevents "recursive containers" entering the normal container output specialization. The effect is that boost::filesystem::path and similar containers use their own operator<< overload, if that exists, otherwise the "binary output fallback" will be used.

For example,

boost::filesystem::path p("k:\\some-thing\\weird");

would output (including quotation marks):

"k:\some-thing\weird"

Since I'm not aware of other know "recursively-defined" containers than boost::filesystem::path and std::filesystem::path (which both define their own operator<< overload), I see currently no reason for further fine-tuning the solution until another use-case occurs. Please let me know, if there are other types to consider as well, where the suggested approach would not work.

FrankieLi added a commit to lunasolutions/googletest that referenced this issue Dec 6, 2017
* Correct some typos in a comment

* fix small typo in comment

* add note about different definitions of Test Case

There are contradictory definitions of the term "test case", so prepare
new users in Primer.md to avoid confusion.

* Samples changes upstreaming

* Samples changes upstreaming

* WIP

* WIP, windows testing

* WIP, windows testing

* WIP, windows testing

* WIP, win testing

* WIP, win testing

* Punctuation

Missing periods

* be more specific on Test Case

* WIP

* Added googlemock tests

* Added googlemock tests

* Infinite Loop when calling a mock function that takes boost::filesystem::path as parameter google#521: Add is_same type trait

* Infinite Loop when calling a mock function that takes boost::filesystem::path as parameter google#521: Add is_same type trait and prevent infinite loops for recursive containers

* WIP

* Fix library install destinations

Modify library install destinations to install .dll's to the correct
location (`bin`, not `lib`), and to install other artifacts to the
correct platform-dependent location by using GNUInstallDirs. This is
required for some distributions (e.g. Fedora) and will fix an issue that
otherwise requires those distributions to patch the upstream sources.
Also, add options to suppress installation, which may be useful for
projects that embed Google Test.

Since Google Test is trying to support archaic versions of CMake, a
brain-dead fallback (which requires that the user set either LIB_SUFFIX
or CMAKE_INSTALL_LIBDIR themselves) is included for versions that
predate GNUInstallDirs.

Fixes google#1161.

Co-Authored-By: d3x0r <d3x0r@users.noreply.github.com>

* clarify distinction regarding Test Case

* Adding a flag option to change the default mock type

* Initial Revision, review 164634031

* Added Copyright

* Minor style fixes

Typos, punctuation & broken links

* say "former version" instead of "released version"

* Update WORKSPACE

Remove comments

* Addressing comments

* Addressing Comments

* Add support for pkgconfig

* Add documentation for pkg-config

* Use GTEST_LOG instead of printf

* Removed extra colon in error log

* Change AppVeyor Status Badge to point to new AppVeyor Project Location

* Change AppVeyor Status Badge to point to new AppVeyor Project Location

* Fix problem installing gtest when gmock enabled

Fix a bug deciding whether to enable the option to install Google Test
caused by one of the dependent option dependencies not being defined
yet.

Fixes google#1198; impossible to install Google Test if Google Mock is built.

* Add function name to exception if there's no default action

* Handling invalid flag values

* Update README.md

Another AppVeyor move

* adds test for NiceMock with unknown return value

* Fix test if exceptions are not supported

* Switch return type to class without default constructor

* Change tabs to spaces in test case

* Adding CMake visibility policy setting

This policy setting will silence a warning when using with a visibility settings on targets. Due to the forced `cmake_minimum_version`, policy settings in CMakeLists calling this one (including the main CMakeLists) are lost, forcing the change to be made here.

* Proposing these changes, please review

Slightly better names and cleaner tests.
Please review

* Added "explicit" as per compiler suggestion

* Remove unused variable

* Support ref-qualified member functions in Property().

* Support x64 configuration for old VS2010 projects

VS2010 solution only to simplify old users (who used these solutions) upgrading to new gtest/gmock, new users should use CMake generated solutions. VS2010 solution can be opened in any new VS.

* Remove gtest VS2005 projects

* Support x64 configuration for old VS2015 projects

* Applying lint checks from upstream google3

* fix typo in comment and string (SetUpTestCase)

* remove unused TestCase import

* fix typo: xUnit

* remove non-existing gmock_build_samples switch

* switch on verbose make

* run combined build only

There is no need for separate 'googlemock' and 'googletest' builds,
as the 'googlemock' build includes 'googletest' and it's unit tests.

* remove Yob's comma mentioned in issue google#1105

* use plural verb as mentioned in issue google#1105

* Detect Fuchsia, and set GTEST_HAS_PTHREAD on GTEST_OS_FUCHSIA

* use build type set in .travis.yml

The BUILD_TYPE variable of .travis.yml was ignored up to now.

* use upper-case build type

While cmake does not complain on build type 'debug', the cmake
documentation always spells it 'Debug', so take this.

* fix SetUp/TearDownTestCase() in AdvancedGuide

fixes issue google#1087

* remove obsolete comment regarding python tests on linux

* ask cmake for per-configuration output subdir

On single-configuration build systems as Makefile Generators, there is
no subdirectory for the configuration in the build tree - therefore ask
cmake for the subdir by using CMAKE_CFG_INTDIR, which is just '.' on
single-configuration build systems (Linux et al.).

* Revert "ask cmake for per-configuration output subdir"

This reverts commit 73d58dd.

Unfortunately, ${CMAKE_CFG_INTDIR} is set during build only and doesn't
help here.

* create different python based tests for single and multi configuration build generators

* Note that it is preferable for Googlers to create a CL internally first

* removed internal link ( not allowed in OSS)

* Removed "Trivial" 

Who knows? may not be very trivial given the code drift between internal and OSS

* AppVeyor MinGW-w64 test build

* fix example's comment

* change links from former code.google.com to current github repository

* CMake: use threads if allowed and found, not just if found.

If the user's cmakelists.txt first look for threads using
find_package(Threads), then set(gtest_disable_pthreads ON),
and then include googletest. GoogleTest will not look for
threads. But since they have already been found before in
user's cmakelists, it will use them regardless.

This helped me fix build issue in darktable-org/rawspeed
on windows/MSYS2, even though there are threads, and they
are usable, googletest build was failing with issues
about AutoHandle. I was first looking for threads, and only
then including googletest, so no matter the value of
gtest_disable_pthreads, it failed.

The other obvious solution is for user to first include
googletest, and only then look for threads by himself.

* switch one build to Release mode

This turns on optimization which allows the compiler to discover more
problems and omit some more warnings.

* treat all warnings as errors for GCC (-Werror)

* Allow macros inside of parametrized test names.

This allows doing things like TEST_P(TestFixture, MAYBE(TestName)) for nicer conditional test disabling.

* Add a non-parametrized test.

* avoid -Wshadow warning on GCC

When using INSTANTIATE_TEST_CASE_P with a lambda function which uses
'info' as parameter name, GCC complains that this would shadow
parameter 'info' used in the macro's VA_ARGS call.

* avoid warning about unused variable

* cache ccache

* set MAKEFLAGS to use multiple processors on Travis CI

* install ccache on travis osx build slave

* limit processors to use in Travis build to 4

* remove obsolete link_directories command

It's not necessary, as the target_link_libraries command contains an
absolute path already, and the path given doesn't exist anymore,
leading only to linker warnings like:
ld: warning: directory not found for option
'-L/Users/travis/build/google/googletest/build/googlemock/gtest/src'

* add a cast

* show ccache statistics in log

* call clang via ccache on Linux

* reset ccache statistics at install

* drop unused valgrind package from installation

... and remove explicit gcc installation (will be installed with g++
automatically)

* remove unused variables from travis environment

* Removed flush scopes around GTEST_LOG(FATAL) and exit call since FATAL is expected to abort()

* use GTEST_ATTRIBUTE_UNUSED_ instead of dummy function

* Fix ellipsis position in examples

* Make the failure messages from EXPECT_EQ and friends actually symmetric,

instead of reading more like reversing the former "expected" and "actual"
roles of the LHS and RHS arguments.

This patch is manually applied from internal version (125109873)

* Add explicit `CMAKE_DEBUG_POSTFIX` option

Enable generating different library name to be compatible with CMake's `FindGTest`.

* Remove redundant declaration

TempDir() function is declared twice, once in `internal/gtest-port.h`
and a second time in `gtest.h`.

Fixes a warning with GCC when -Wredundant-decls is given.

* Swap reinterpret_cast for static_cast

Swap reinterpret_cast for static_cast

* Revert "Allow macros inside of parametrized test names."

* Use gender-neutral pronouns in comments and docs

* Updated README with information about C runtime dynamic/static linking issues in Windows

* google#1282: Doc typo fix

* Workaround for Travis issue travis-ci/travis-ci#8552

* Revert "Workaround for Travis issue https://github.com/travis-ci/travis-ci/is…"

* Workaround for Travis issue https://goo.gl/d5eV8o

* googletest: Add GTEST_API_ attribute to ThreadLocal class.

ThreadLocal class needs to be have default visibility.
Root cause is gtest uses typeinfo for the ThreadLocal class.
The problem manifests When gtest/gmock are built as a shared library
with libc++. When a class is used in typeinfo, it must have default
visibility.

There is an explanation about typeinfo and visibility here:
https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/CppRuntimeEnv/Articles/SymbolVisibility.html

When libc++ is used with gtest in shared library mode, any tests
that are compiled with -fvisibility=hidden and exercise the
macro EXPECT_CALL, it results in an abort like:
[ FATAL ] /usr/include/gtest/internal/gtest-port.h:1394::
Condition typeid(*base) == typeid(Derived) failed.
This is because the typeinfo for ThreadLocal class is not visible.
Therefore, linker failed to match it to the shared library symbol, creating a
new symbol instead.

This fixes google#1207.

* Enable C++11 features for VS2015 and VS2017

* Fix tests with VS2015 and VS2017

* Fix gmock tests when std::unary_function unavailable

* Remove gcc 6 misleading indentations.

* Enable CI for VS2017

* remove markdown stars (bold) from code examples

* Fixes issue google#826 by treating MinGW as "non-Windows" when determining colored output
@gennadiycivil
Copy link
Contributor

#1186 should have addressed this

coryan added a commit to coryan/google-cloud-cpp that referenced this issue Aug 4, 2020
We needed this function to workaround a googletest bug
(google/googletest#521). This bug was fixed a couple of years ago, but
we neglected to remove the workaround until now.
coryan added a commit to googleapis/google-cloud-cpp that referenced this issue Aug 4, 2020
We needed this function to workaround a googletest bug
(google/googletest#521). This bug was fixed a couple of years ago, but
we neglected to remove the workaround until now.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants