mirror of
https://github.com/google/googletest.git
synced 2025-01-01 23:07:58 +08:00
Merge pull request #1508 from gennadiycivil/master
merge, again, IsRecursiveContainer
This commit is contained in:
commit
dccc2d6754
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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,40 +889,94 @@ 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 T>
|
||||
struct VoidT {
|
||||
typedef void value_type;
|
||||
};
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct HasValueType : false_type {};
|
||||
template <typename T>
|
||||
struct HasValueType<T, VoidT<typename T::value_type> > : true_type {
|
||||
};
|
||||
|
||||
template <typename C,
|
||||
bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer),
|
||||
bool = HasValueType<C>::value>
|
||||
struct IsRecursiveContainerImpl;
|
||||
|
||||
template <typename C, bool HV>
|
||||
struct IsRecursiveContainerImpl<C, false, HV> : public false_type {};
|
||||
|
||||
// Since the IsRecursiveContainerImpl depends on the IsContainerTest we need to
|
||||
// obey the same inconsistencies as the IsContainerTest, namely check if
|
||||
// something is a container is relying on only const_iterator in C++11 and
|
||||
// is relying on both const_iterator and iterator otherwise
|
||||
template <typename C>
|
||||
struct IsRecursiveContainerImpl<C, false> : public false_type {};
|
||||
struct IsRecursiveContainerImpl<C, true, false> : public false_type {};
|
||||
|
||||
template <typename C>
|
||||
struct IsRecursiveContainerImpl<C, true> {
|
||||
typedef
|
||||
typename IteratorTraits<typename C::iterator>::value_type
|
||||
value_type;
|
||||
struct IsRecursiveContainerImpl<C, true, true> {
|
||||
#if GTEST_LANG_CXX11
|
||||
typedef typename IteratorTraits<typename C::const_iterator>::value_type
|
||||
value_type;
|
||||
#else
|
||||
typedef typename IteratorTraits<typename C::iterator>::value_type value_type;
|
||||
#endif
|
||||
typedef is_same<value_type, C> type;
|
||||
};
|
||||
|
||||
// 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 +1275,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_
|
||||
|
||||
|
@ -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;
|
||||
|
@ -195,7 +195,6 @@ class PathLike {
|
||||
struct iterator {
|
||||
typedef PathLike value_type;
|
||||
};
|
||||
typedef iterator const_iterator;
|
||||
|
||||
PathLike() {}
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user