aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGennadiy Civil <misterg@google.com>2018-03-15 14:31:37 -0400
committerGennadiy Civil <misterg@google.com>2018-03-15 14:31:37 -0400
commita178cc7ef73ce7e6e7e688d3d5cbccfc3c1d5d6b (patch)
treec0cdf002f62ce0af852a61777e009c9968ef806f
parenta325ad2db5deb623eab740527e559b81c0f39d65 (diff)
downloadgoogletest-a178cc7ef73ce7e6e7e688d3d5cbccfc3c1d5d6b.tar.gz
googletest-a178cc7ef73ce7e6e7e688d3d5cbccfc3c1d5d6b.tar.bz2
googletest-a178cc7ef73ce7e6e7e688d3d5cbccfc3c1d5d6b.zip
merge, again, IsRecursiveContainer
-rw-r--r--googlemock/include/gmock/gmock-spec-builders.h1
-rw-r--r--googlemock/test/gmock-matchers_test.cc1
-rw-r--r--googletest/include/gtest/gtest-printers.h12
-rw-r--r--googletest/include/gtest/internal/gtest-internal.h75
-rw-r--r--googletest/src/gtest.cc4
-rw-r--r--googletest/test/gtest_unittest.cc50
6 files changed, 123 insertions, 20 deletions
diff --git a/googlemock/include/gmock/gmock-spec-builders.h b/googlemock/include/gmock/gmock-spec-builders.h
index c1b63014..f8e1c6ab 100644
--- a/googlemock/include/gmock/gmock-spec-builders.h
+++ b/googlemock/include/gmock/gmock-spec-builders.h
@@ -563,6 +563,7 @@ class ExpectationSet {
public:
// A bidirectional iterator that can read a const element in the set.
typedef Expectation::Set::const_iterator const_iterator;
+ typedef Expectation::Set::iterator iterator;
// An object stored in the set. This is an alias of Expectation.
typedef Expectation::Set::value_type value_type;
diff --git a/googlemock/test/gmock-matchers_test.cc b/googlemock/test/gmock-matchers_test.cc
index 829935ef..f7bf2a82 100644
--- a/googlemock/test/gmock-matchers_test.cc
+++ b/googlemock/test/gmock-matchers_test.cc
@@ -4526,6 +4526,7 @@ class Streamlike {
class ConstIter;
public:
typedef ConstIter const_iterator;
+ typedef ConstIter iterator;
typedef T value_type;
template <typename InIter>
diff --git a/googletest/include/gtest/gtest-printers.h b/googletest/include/gtest/gtest-printers.h
index 2c83c3ff..36f4042a 100644
--- a/googletest/include/gtest/gtest-printers.h
+++ b/googletest/include/gtest/gtest-printers.h
@@ -509,17 +509,19 @@ void PrintTo(const T& value, ::std::ostream* os) {
// function pointers so that the `*os << p` in the object pointer overload
// doesn't cause that warning either.
DefaultPrintTo(
- WrapPrinterType<
- (sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) && !IsRecursiveContainer<T>::value
- ? kPrintContainer : !is_pointer<T>::value
- ? kPrintOther
+ WrapPrinterType <
+ (sizeof(IsContainerTest<T>(0)) == sizeof(IsContainer)) &&
+ !IsRecursiveContainer<T>::value
+ ? kPrintContainer
+ : !is_pointer<T>::value
+ ? kPrintOther
#if GTEST_LANG_CXX11
: std::is_function<typename std::remove_pointer<T>::type>::value
#else
: !internal::ImplicitlyConvertible<T, const void*>::value
#endif
? kPrintFunctionPointer
- : kPrintPointer>(),
+ : kPrintPointer > (),
value, os);
}
diff --git a/googletest/include/gtest/internal/gtest-internal.h b/googletest/include/gtest/internal/gtest-internal.h
index e87f85e6..612f8a4d 100644
--- a/googletest/include/gtest/internal/gtest-internal.h
+++ b/googletest/include/gtest/internal/gtest-internal.h
@@ -875,8 +875,11 @@ struct IsAProtocolMessage
// a container class by checking the type of IsContainerTest<C>(0).
// The value of the expression is insignificant.
//
-// Note that we look for both C::iterator and C::const_iterator. The
-// reason is that C++ injects the name of a class as a member of the
+// In C++11 mode we check the existence of a const_iterator and that an
+// iterator is properly implemented for the container.
+//
+// For pre-C++11 that we look for both C::iterator and C::const_iterator.
+// The reason is that C++ injects the name of a class as a member of the
// class itself (e.g. you can refer to class iterator as either
// 'iterator' or 'iterator::iterator'). If we look for C::iterator
// only, for example, we would mistakenly think that a class named
@@ -886,20 +889,52 @@ struct IsAProtocolMessage
// IsContainerTest(typename C::const_iterator*) and
// IsContainerTest(...) doesn't work with Visual Age C++ and Sun C++.
typedef int IsContainer;
+#if GTEST_LANG_CXX11
+template <class C,
+ class Iterator = decltype(::std::declval<const C&>().begin()),
+ class = decltype(::std::declval<const C&>().end()),
+ class = decltype(++::std::declval<Iterator&>()),
+ class = decltype(*::std::declval<Iterator>()),
+ class = typename C::const_iterator>
+IsContainer IsContainerTest(int /* dummy */) {
+ return 0;
+}
+#else
template <class C>
IsContainer IsContainerTest(int /* dummy */,
typename C::iterator* /* it */ = NULL,
typename C::const_iterator* /* const_it */ = NULL) {
return 0;
}
+#endif // GTEST_LANG_CXX11
typedef char IsNotContainer;
template <class C>
IsNotContainer IsContainerTest(long /* dummy */) { return '\0'; }
-template <typename C, bool =
- sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer)
->
+// Trait to detect whether a type T is a hash table.
+// The heuristic used is that the type contains an inner type `hasher` and does
+// not contain an inner type `reverse_iterator`.
+// If the container is iterable in reverse, then order might actually matter.
+template <typename T>
+struct IsHashTable {
+ private:
+ template <typename U>
+ static char test(typename U::hasher*, typename U::reverse_iterator*);
+ template <typename U>
+ static int test(typename U::hasher*, ...);
+ template <typename U>
+ static char test(...);
+
+ public:
+ static const bool value = sizeof(test<T>(0, 0)) == sizeof(int);
+};
+
+template <typename T>
+const bool IsHashTable<T>::value;
+
+template <typename C,
+ bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer)>
struct IsRecursiveContainerImpl;
template <typename C>
@@ -907,19 +942,34 @@ struct IsRecursiveContainerImpl<C, false> : public false_type {};
template <typename C>
struct IsRecursiveContainerImpl<C, true> {
- typedef
- typename IteratorTraits<typename C::iterator>::value_type
- value_type;
+ template <typename T>
+ struct VoidT {
+ typedef void value_type;
+ };
+ template <typename C1, typename VT = void>
+ struct PathTraits {
+ typedef typename C1::const_iterator::value_type value_type;
+ };
+ template <typename C2>
+ struct PathTraits<
+ C2, typename VoidT<typename C2::iterator::value_type>::value_type> {
+ typedef typename C2::iterator::value_type value_type;
+ };
+ typedef typename IteratorTraits<typename C::iterator>::value_type value_type;
+#if GTEST_LANG_CXX11
+ typedef std::is_same<value_type, C> type;
+#else
typedef is_same<value_type, C> type;
+#endif
};
// IsRecursiveContainer<Type> is a unary compile-time predicate that
-// evaluates whether C is a recursive container type. A recursive container
+// evaluates whether C is a recursive container type. A recursive container
// type is a container type whose value_type is equal to the container type
-// itself. An example for a recursive container type is
-// boost::filesystem::path, whose iterator has a value_type that is equal to
+// itself. An example for a recursive container type is
+// boost::filesystem::path, whose iterator has a value_type that is equal to
// boost::filesystem::path.
-template<typename C>
+template <typename C>
struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
// EnableIf<condition>::type is void when 'Cond' is true, and
@@ -1218,4 +1268,3 @@ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_
-
diff --git a/googletest/src/gtest.cc b/googletest/src/gtest.cc
index 74df5492..d22679f6 100644
--- a/googletest/src/gtest.cc
+++ b/googletest/src/gtest.cc
@@ -5185,8 +5185,8 @@ bool ShouldRunTestOnShard(int total_shards, int shard_index, int test_id) {
// each TestCase and TestInfo object.
// If shard_tests == true, further filters tests based on sharding
// variables in the environment - see
-// https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md .
-// Returns the number of tests that should run.
+// https://github.com/google/googletest/blob/master/googletest/docs/AdvancedGuide.md
+// . Returns the number of tests that should run.
int UnitTestImpl::FilterTests(ReactionToSharding shard_tests) {
const Int32 total_shards = shard_tests == HONOR_SHARDING_PROTOCOL ?
Int32FromEnvOrDie(kTestTotalShards, -1) : -1;
diff --git a/googletest/test/gtest_unittest.cc b/googletest/test/gtest_unittest.cc
index 11af9c9b..3791592b 100644
--- a/googletest/test/gtest_unittest.cc
+++ b/googletest/test/gtest_unittest.cc
@@ -64,6 +64,9 @@ TEST(CommandLineFlagsTest, CanBeAccessedInCodeOnceGTestHIsIncluded) {
#include <map>
#include <vector>
#include <ostream>
+#if GTEST_LANG_CXX11
+#include <unordered_set>
+#endif // GTEST_LANG_CXX11
#include "gtest/gtest-spi.h"
#include "src/gtest-internal-inl.h"
@@ -258,6 +261,8 @@ using testing::internal::IsContainer;
using testing::internal::IsContainerTest;
using testing::internal::IsNotContainer;
using testing::internal::NativeArray;
+using testing::internal::OsStackTraceGetter;
+using testing::internal::OsStackTraceGetterInterface;
using testing::internal::ParseInt32Flag;
using testing::internal::RelationToSourceCopy;
using testing::internal::RelationToSourceReference;
@@ -274,6 +279,7 @@ using testing::internal::String;
using testing::internal::TestEventListenersAccessor;
using testing::internal::TestResultAccessor;
using testing::internal::UInt32;
+using testing::internal::UnitTestImpl;
using testing::internal::WideStringToUtf8;
using testing::internal::edit_distance::CalculateOptimalEdits;
using testing::internal::edit_distance::CreateUnifiedDiff;
@@ -7526,6 +7532,50 @@ TEST(IsContainerTestTest, WorksForContainer) {
sizeof(IsContainerTest<std::map<int, double> >(0)));
}
+#if GTEST_LANG_CXX11
+struct ConstOnlyContainerWithPointerIterator {
+ using const_iterator = int*;
+ const_iterator begin() const;
+ const_iterator end() const;
+};
+
+struct ConstOnlyContainerWithClassIterator {
+ struct const_iterator {
+ const int& operator*() const;
+ const_iterator& operator++(/* pre-increment */);
+ };
+ const_iterator begin() const;
+ const_iterator end() const;
+};
+
+TEST(IsContainerTestTest, ConstOnlyContainer) {
+ EXPECT_EQ(sizeof(IsContainer),
+ sizeof(IsContainerTest<ConstOnlyContainerWithPointerIterator>(0)));
+ EXPECT_EQ(sizeof(IsContainer),
+ sizeof(IsContainerTest<ConstOnlyContainerWithClassIterator>(0)));
+}
+#endif // GTEST_LANG_CXX11
+
+// Tests IsHashTable.
+struct AHashTable {
+ typedef void hasher;
+};
+struct NotReallyAHashTable {
+ typedef void hasher;
+ typedef void reverse_iterator;
+};
+TEST(IsHashTable, Basic) {
+ EXPECT_TRUE(testing::internal::IsHashTable<AHashTable>::value);
+ EXPECT_FALSE(testing::internal::IsHashTable<NotReallyAHashTable>::value);
+#if GTEST_LANG_CXX11
+ EXPECT_FALSE(testing::internal::IsHashTable<std::vector<int>>::value);
+ EXPECT_TRUE(testing::internal::IsHashTable<std::unordered_set<int>>::value);
+#endif // GTEST_LANG_CXX11
+#if GTEST_HAS_HASH_SET_
+ EXPECT_TRUE(testing::internal::IsHashTable<hash_set<int>>::value);
+#endif // GTEST_HAS_HASH_SET_
+}
+
// Tests ArrayEq().
TEST(ArrayEqTest, WorksForDegeneratedArrays) {