update gtest on windx64

This commit is contained in:
Bassem Girgis
2020-01-19 14:18:22 -06:00
parent 320a1eeb10
commit bedc944f48
53 changed files with 4996 additions and 17751 deletions

View File

@@ -58,6 +58,7 @@
#include <map>
#include <set>
#include <string>
#include <type_traits>
#include <vector>
#include "gtest/gtest-message.h"
@@ -79,7 +80,6 @@
// Stringifies its argument.
#define GTEST_STRINGIFY_(name) #name
class ProtocolMessage;
namespace proto2 { class Message; }
namespace testing {
@@ -91,7 +91,7 @@ class Message; // Represents a failure message.
class Test; // Represents a test.
class TestInfo; // Information about a test.
class TestPartResult; // Result of a test part.
class UnitTest; // A collection of test cases.
class UnitTest; // A collection of test suites.
template <typename T>
::std::string PrintToString(const T& value);
@@ -106,34 +106,22 @@ class UnitTestImpl; // Opaque implementation of UnitTest
// stack trace.
GTEST_API_ extern const char kStackTraceMarker[];
// Two overloaded helpers for checking at compile time whether an
// expression is a null pointer literal (i.e. NULL or any 0-valued
// compile-time integral constant). Their return values have
// different sizes, so we can use sizeof() to test which version is
// picked by the compiler. These helpers have no implementations, as
// we only need their signatures.
//
// Given IsNullLiteralHelper(x), the compiler will pick the first
// version if x can be implicitly converted to Secret*, and pick the
// second version otherwise. Since Secret is a secret and incomplete
// type, the only expression a user can write that has type Secret* is
// a null pointer literal. Therefore, we know that x is a null
// pointer literal if and only if the first version is picked by the
// compiler.
char IsNullLiteralHelper(Secret* p);
char (&IsNullLiteralHelper(...))[2]; // NOLINT
// A compile-time bool constant that is true if and only if x is a
// null pointer literal (i.e. NULL or any 0-valued compile-time
// integral constant).
#ifdef GTEST_ELLIPSIS_NEEDS_POD_
// We lose support for NULL detection where the compiler doesn't like
// passing non-POD classes through ellipsis (...).
# define GTEST_IS_NULL_LITERAL_(x) false
#else
# define GTEST_IS_NULL_LITERAL_(x) \
(sizeof(::testing::internal::IsNullLiteralHelper(x)) == 1)
#endif // GTEST_ELLIPSIS_NEEDS_POD_
// An IgnoredValue object can be implicitly constructed from ANY value.
class IgnoredValue {
struct Sink {};
public:
// This constructor template allows any value to be implicitly
// converted to IgnoredValue. The object has no data member and
// doesn't try to remember anything about the argument. We
// deliberately omit the 'explicit' keyword in order to allow the
// conversion to be implicit.
// Disable the conversion if T already has a magical conversion operator.
// Otherwise we get ambiguity.
template <typename T,
typename std::enable_if<!std::is_convertible<T, Sink>::value,
int>::type = 0>
IgnoredValue(const T& /* ignored */) {} // NOLINT(runtime/explicit)
};
// Appends the user-supplied message to the Google-Test-generated message.
GTEST_API_ std::string AppendUserMessage(
@@ -201,7 +189,7 @@ GTEST_API_ std::string DiffStrings(const std::string& left,
// expected_value: "5"
// actual_value: "6"
//
// The ignoring_case parameter is true iff the assertion is a
// The ignoring_case parameter is true if and only if the assertion is a
// *_STRCASEEQ*. When it's true, the string " (ignoring case)" will
// be inserted into the message.
GTEST_API_ AssertionResult EqFailure(const char* expected_expression,
@@ -330,15 +318,15 @@ class FloatingPoint {
// Returns the sign bit of this number.
Bits sign_bit() const { return kSignBitMask & u_.bits_; }
// Returns true iff this is NAN (not a number).
// Returns true if and only if this is NAN (not a number).
bool is_nan() const {
// It's a NAN if the exponent bits are all ones and the fraction
// bits are not entirely zeros.
return (exponent_bits() == kExponentBitMask) && (fraction_bits() != 0);
}
// Returns true iff this number is at most kMaxUlps ULP's away from
// rhs. In particular, this function:
// Returns true if and only if this number is at most kMaxUlps ULP's away
// from rhs. In particular, this function:
//
// - returns false if either number is (or both are) NAN.
// - treats really large numbers as almost equal to infinity.
@@ -409,7 +397,7 @@ typedef FloatingPoint<float> Float;
typedef FloatingPoint<double> Double;
// In order to catch the mistake of putting tests that use different
// test fixture classes in the same test case, we need to assign
// test fixture classes in the same test suite, we need to assign
// unique IDs to fixture classes and compare them. The TypeId type is
// used to hold such IDs. The user should treat TypeId as an opaque
// type: the only operation allowed on TypeId values is to compare
@@ -469,7 +457,7 @@ class TestFactoryBase {
template <class TestClass>
class TestFactoryImpl : public TestFactoryBase {
public:
virtual Test* CreateTest() { return new TestClass; }
Test* CreateTest() override { return new TestClass; }
};
#if GTEST_OS_WINDOWS
@@ -485,9 +473,9 @@ GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
#endif // GTEST_OS_WINDOWS
// Types of SetUpTestCase() and TearDownTestCase() functions.
typedef void (*SetUpTestCaseFunc)();
typedef void (*TearDownTestCaseFunc)();
// Types of SetUpTestSuite() and TearDownTestSuite() functions.
using SetUpTestSuiteFunc = void (*)();
using TearDownTestSuiteFunc = void (*)();
struct CodeLocation {
CodeLocation(const std::string& a_file, int a_line)
@@ -497,12 +485,64 @@ struct CodeLocation {
int line;
};
// Helper to identify which setup function for TestCase / TestSuite to call.
// Only one function is allowed, either TestCase or TestSute but not both.
// Utility functions to help SuiteApiResolver
using SetUpTearDownSuiteFuncType = void (*)();
inline SetUpTearDownSuiteFuncType GetNotDefaultOrNull(
SetUpTearDownSuiteFuncType a, SetUpTearDownSuiteFuncType def) {
return a == def ? nullptr : a;
}
template <typename T>
// Note that SuiteApiResolver inherits from T because
// SetUpTestSuite()/TearDownTestSuite() could be protected. Ths way
// SuiteApiResolver can access them.
struct SuiteApiResolver : T {
// testing::Test is only forward declared at this point. So we make it a
// dependend class for the compiler to be OK with it.
using Test =
typename std::conditional<sizeof(T) != 0, ::testing::Test, void>::type;
static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename,
int line_num) {
SetUpTearDownSuiteFuncType test_case_fp =
GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase);
SetUpTearDownSuiteFuncType test_suite_fp =
GetNotDefaultOrNull(&T::SetUpTestSuite, &Test::SetUpTestSuite);
GTEST_CHECK_(!test_case_fp || !test_suite_fp)
<< "Test can not provide both SetUpTestSuite and SetUpTestCase, please "
"make sure there is only one present at "
<< filename << ":" << line_num;
return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
}
static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename,
int line_num) {
SetUpTearDownSuiteFuncType test_case_fp =
GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase);
SetUpTearDownSuiteFuncType test_suite_fp =
GetNotDefaultOrNull(&T::TearDownTestSuite, &Test::TearDownTestSuite);
GTEST_CHECK_(!test_case_fp || !test_suite_fp)
<< "Test can not provide both TearDownTestSuite and TearDownTestCase,"
" please make sure there is only one present at"
<< filename << ":" << line_num;
return test_case_fp != nullptr ? test_case_fp : test_suite_fp;
}
};
// Creates a new TestInfo object and registers it with Google Test;
// returns the created object.
//
// Arguments:
//
// test_case_name: name of the test case
// test_suite_name: name of the test suite
// name: name of the test
// type_param the name of the test's type parameter, or NULL if
// this is not a typed or a type-parameterized test.
@@ -510,21 +550,16 @@ struct CodeLocation {
// or NULL if this is not a type-parameterized test.
// code_location: code location where the test is defined
// fixture_class_id: ID of the test fixture class
// set_up_tc: pointer to the function that sets up the test case
// tear_down_tc: pointer to the function that tears down the test case
// set_up_tc: pointer to the function that sets up the test suite
// tear_down_tc: pointer to the function that tears down the test suite
// factory: pointer to the factory that creates a test object.
// The newly created TestInfo instance will assume
// ownership of the factory object.
GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
const char* test_case_name,
const char* name,
const char* type_param,
const char* value_param,
CodeLocation code_location,
TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc,
TestFactoryBase* factory);
const char* test_suite_name, const char* name, const char* type_param,
const char* value_param, CodeLocation code_location,
TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc,
TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory);
// If *pstr starts with the given prefix, modifies *pstr to be right
// past the prefix and returns true; otherwise leaves *pstr unchanged
@@ -536,19 +571,20 @@ GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr);
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \
/* class A needs to have dll-interface to be used by clients of class B */)
// State of the definition of a type-parameterized test case.
class GTEST_API_ TypedTestCasePState {
// State of the definition of a type-parameterized test suite.
class GTEST_API_ TypedTestSuitePState {
public:
TypedTestCasePState() : registered_(false) {}
TypedTestSuitePState() : registered_(false) {}
// Adds the given test name to defined_test_names_ and return true
// if the test case hasn't been registered; otherwise aborts the
// if the test suite hasn't been registered; otherwise aborts the
// program.
bool AddTestName(const char* file, int line, const char* case_name,
const char* test_name) {
if (registered_) {
fprintf(stderr, "%s Test %s must be defined before "
"REGISTER_TYPED_TEST_CASE_P(%s, ...).\n",
fprintf(stderr,
"%s Test %s must be defined before "
"REGISTER_TYPED_TEST_SUITE_P(%s, ...).\n",
FormatFileLocation(file, line).c_str(), test_name, case_name);
fflush(stderr);
posix::Abort();
@@ -581,14 +617,19 @@ class GTEST_API_ TypedTestCasePState {
RegisteredTestsMap registered_tests_;
};
// Legacy API is deprecated but still available
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_
using TypedTestCasePState = TypedTestSuitePState;
#endif // GTEST_REMOVE_LEGACY_TEST_CASEAPI_
GTEST_DISABLE_MSC_WARNINGS_POP_() // 4251
// Skips to the first non-space char after the first comma in 'str';
// returns NULL if no comma is found in 'str'.
inline const char* SkipComma(const char* str) {
const char* comma = strchr(str, ',');
if (comma == NULL) {
return NULL;
if (comma == nullptr) {
return nullptr;
}
while (IsSpace(*(++comma))) {}
return comma;
@@ -598,7 +639,7 @@ inline const char* SkipComma(const char* str) {
// the entire string if it contains no comma.
inline std::string GetPrefixUntilComma(const char* str) {
const char* comma = strchr(str, ',');
return comma == NULL ? str : std::string(str, comma);
return comma == nullptr ? str : std::string(str, comma);
}
// Splits a given string on a given delimiter, populating a given
@@ -648,7 +689,7 @@ template <GTEST_TEMPLATE_ Fixture, class TestSel, typename Types>
class TypeParameterizedTest {
public:
// 'index' is the index of the test in the type list 'Types'
// specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
// specified in INSTANTIATE_TYPED_TEST_SUITE_P(Prefix, TestSuite,
// Types). Valid values for 'index' are [0, N - 1] where N is the
// length of Types.
static bool Register(const char* prefix, const CodeLocation& code_location,
@@ -663,13 +704,17 @@ class TypeParameterizedTest {
// list.
MakeAndRegisterTestInfo(
(std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name +
"/" + type_names[index])
"/" + type_names[static_cast<size_t>(index)])
.c_str(),
StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
GetTypeName<Type>().c_str(),
NULL, // No value parameter.
code_location, GetTypeId<FixtureClass>(), TestClass::SetUpTestCase,
TestClass::TearDownTestCase, new TestFactoryImpl<TestClass>);
nullptr, // No value parameter.
code_location, GetTypeId<FixtureClass>(),
SuiteApiResolver<TestClass>::GetSetUpCaseOrSuite(
code_location.file.c_str(), code_location.line),
SuiteApiResolver<TestClass>::GetTearDownCaseOrSuite(
code_location.file.c_str(), code_location.line),
new TestFactoryImpl<TestClass>);
// Next, recurses (at compile time) with the tail of the type list.
return TypeParameterizedTest<Fixture, TestSel,
@@ -695,15 +740,15 @@ class TypeParameterizedTest<Fixture, TestSel, Types0> {
}
};
// TypeParameterizedTestCase<Fixture, Tests, Types>::Register()
// TypeParameterizedTestSuite<Fixture, Tests, Types>::Register()
// registers *all combinations* of 'Tests' and 'Types' with Google
// Test. The return value is insignificant - we just need to return
// something such that we can call this function in a namespace scope.
template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
class TypeParameterizedTestCase {
class TypeParameterizedTestSuite {
public:
static bool Register(const char* prefix, CodeLocation code_location,
const TypedTestCasePState* state, const char* case_name,
const TypedTestSuitePState* state, const char* case_name,
const char* test_names,
const std::vector<std::string>& type_names =
GenerateNames<DefaultNameGenerator, Types>()) {
@@ -726,20 +771,20 @@ class TypeParameterizedTestCase {
prefix, test_location, case_name, test_names, 0, type_names);
// Next, recurses (at compile time) with the tail of the test list.
return TypeParameterizedTestCase<Fixture, typename Tests::Tail,
Types>::Register(prefix, code_location,
state, case_name,
SkipComma(test_names),
type_names);
return TypeParameterizedTestSuite<Fixture, typename Tests::Tail,
Types>::Register(prefix, code_location,
state, case_name,
SkipComma(test_names),
type_names);
}
};
// The base case for the compile time recursion.
template <GTEST_TEMPLATE_ Fixture, typename Types>
class TypeParameterizedTestCase<Fixture, Templates0, Types> {
class TypeParameterizedTestSuite<Fixture, Templates0, Types> {
public:
static bool Register(const char* /*prefix*/, const CodeLocation&,
const TypedTestCasePState* /*state*/,
const TypedTestSuitePState* /*state*/,
const char* /*case_name*/, const char* /*test_names*/,
const std::vector<std::string>& =
std::vector<std::string>() /*type_names*/) {
@@ -802,120 +847,16 @@ class GTEST_API_ Random {
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random);
};
// Defining a variable of type CompileAssertTypesEqual<T1, T2> will cause a
// compiler error iff T1 and T2 are different types.
template <typename T1, typename T2>
struct CompileAssertTypesEqual;
template <typename T>
struct CompileAssertTypesEqual<T, T> {
};
// Removes the reference from a type if it is a reference type,
// otherwise leaves it unchanged. This is the same as
// tr1::remove_reference, which is not widely available yet.
template <typename T>
struct RemoveReference { typedef T type; }; // NOLINT
template <typename T>
struct RemoveReference<T&> { typedef T type; }; // NOLINT
// A handy wrapper around RemoveReference that works when the argument
// T depends on template parameters.
#define GTEST_REMOVE_REFERENCE_(T) \
typename ::testing::internal::RemoveReference<T>::type
// Removes const from a type if it is a const type, otherwise leaves
// it unchanged. This is the same as tr1::remove_const, which is not
// widely available yet.
template <typename T>
struct RemoveConst { typedef T type; }; // NOLINT
template <typename T>
struct RemoveConst<const T> { typedef T type; }; // NOLINT
// MSVC 8.0, Sun C++, and IBM XL C++ have a bug which causes the above
// definition to fail to remove the const in 'const int[3]' and 'const
// char[3][4]'. The following specialization works around the bug.
template <typename T, size_t N>
struct RemoveConst<const T[N]> {
typedef typename RemoveConst<T>::type type[N];
};
#if defined(_MSC_VER) && _MSC_VER < 1400
// This is the only specialization that allows VC++ 7.1 to remove const in
// 'const int[3] and 'const int[3][4]'. However, it causes trouble with GCC
// and thus needs to be conditionally compiled.
template <typename T, size_t N>
struct RemoveConst<T[N]> {
typedef typename RemoveConst<T>::type type[N];
};
#endif
// A handy wrapper around RemoveConst that works when the argument
// T depends on template parameters.
#define GTEST_REMOVE_CONST_(T) \
typename ::testing::internal::RemoveConst<T>::type
// Turns const U&, U&, const U, and U all into U.
#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \
GTEST_REMOVE_CONST_(GTEST_REMOVE_REFERENCE_(T))
// ImplicitlyConvertible<From, To>::value is a compile-time bool
// constant that's true iff type From can be implicitly converted to
// type To.
template <typename From, typename To>
class ImplicitlyConvertible {
private:
// We need the following helper functions only for their types.
// They have no implementations.
// MakeFrom() is an expression whose type is From. We cannot simply
// use From(), as the type From may not have a public default
// constructor.
static typename AddReference<From>::type MakeFrom();
// These two functions are overloaded. Given an expression
// Helper(x), the compiler will pick the first version if x can be
// implicitly converted to type To; otherwise it will pick the
// second version.
//
// The first version returns a value of size 1, and the second
// version returns a value of size 2. Therefore, by checking the
// size of Helper(x), which can be done at compile time, we can tell
// which version of Helper() is used, and hence whether x can be
// implicitly converted to type To.
static char Helper(To);
static char (&Helper(...))[2]; // NOLINT
// We have to put the 'public' section after the 'private' section,
// or MSVC refuses to compile the code.
public:
#if defined(__BORLANDC__)
// C++Builder cannot use member overload resolution during template
// instantiation. The simplest workaround is to use its C++0x type traits
// functions (C++Builder 2009 and above only).
static const bool value = __is_convertible(From, To);
#else
// MSVC warns about implicitly converting from double to int for
// possible loss of data, so we need to temporarily disable the
// warning.
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4244)
static const bool value =
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
GTEST_DISABLE_MSC_WARNINGS_POP_()
#endif // __BORLANDC__
};
template <typename From, typename To>
const bool ImplicitlyConvertible<From, To>::value;
typename std::remove_const<typename std::remove_reference<T>::type>::type
// IsAProtocolMessage<T>::value is a compile-time bool constant that's
// true iff T is type ProtocolMessage, proto2::Message, or a subclass
// of those.
// true if and only if T is type proto2::Message or a subclass of it.
template <typename T>
struct IsAProtocolMessage
: public bool_constant<
ImplicitlyConvertible<const T*, const ::ProtocolMessage*>::value ||
ImplicitlyConvertible<const T*, const ::proto2::Message*>::value> {
};
std::is_convertible<const T*, const ::proto2::Message*>::value> {};
// When the compiler sees expression IsContainerTest<C>(0), if C is an
// STL-style container class, the first overload of IsContainerTest
@@ -942,7 +883,6 @@ 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()),
@@ -952,14 +892,6 @@ template <class C,
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>
@@ -980,47 +912,30 @@ struct IsHashTable {
static char test(...);
public:
static const bool value = sizeof(test<T>(0, 0)) == sizeof(int);
static const bool value = sizeof(test<T>(nullptr, nullptr)) == 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>
bool = sizeof(IsContainerTest<C>(0)) == sizeof(IsContainer)>
struct IsRecursiveContainerImpl;
template <typename C, bool HV>
struct IsRecursiveContainerImpl<C, false, HV> : public false_type {};
template <typename C>
struct IsRecursiveContainerImpl<C, false> : public std::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, true, false> : public false_type {};
template <typename C>
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;
struct IsRecursiveContainerImpl<C, true> {
using value_type = decltype(*std::declval<typename C::const_iterator>());
using type =
std::is_same<typename std::remove_const<
typename std::remove_reference<value_type>::type>::type,
C>;
};
// IsRecursiveContainer<Type> is a unary compile-time predicate that
@@ -1032,13 +947,6 @@ struct IsRecursiveContainerImpl<C, true, true> {
template <typename C>
struct IsRecursiveContainer : public IsRecursiveContainerImpl<C>::type {};
// EnableIf<condition>::type is void when 'Cond' is true, and
// undefined when 'Cond' is false. To use SFINAE to make a function
// overload only apply when a particular expression is true, add
// "typename EnableIf<expression>::type* = 0" as the last parameter.
template<bool> struct EnableIf;
template<> struct EnableIf<true> { typedef void type; }; // NOLINT
// Utilities for native arrays.
// ArrayEq() compares two k-dimensional native arrays using the
@@ -1161,10 +1069,9 @@ class NativeArray {
}
private:
enum {
kCheckTypeIsNotConstOrAReference = StaticAssertTypeEqHelper<
Element, GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>::value
};
static_assert(!std::is_const<Element>::value, "Type must not be const");
static_assert(!std::is_reference<Element>::value,
"Type must not be a reference");
// Initializes this object with a copy of the input.
void InitCopy(const Element* array, size_t a_size) {
@@ -1189,6 +1096,139 @@ class NativeArray {
GTEST_DISALLOW_ASSIGN_(NativeArray);
};
// Backport of std::index_sequence.
template <size_t... Is>
struct IndexSequence {
using type = IndexSequence;
};
// Double the IndexSequence, and one if plus_one is true.
template <bool plus_one, typename T, size_t sizeofT>
struct DoubleSequence;
template <size_t... I, size_t sizeofT>
struct DoubleSequence<true, IndexSequence<I...>, sizeofT> {
using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>;
};
template <size_t... I, size_t sizeofT>
struct DoubleSequence<false, IndexSequence<I...>, sizeofT> {
using type = IndexSequence<I..., (sizeofT + I)...>;
};
// Backport of std::make_index_sequence.
// It uses O(ln(N)) instantiation depth.
template <size_t N>
struct MakeIndexSequence
: DoubleSequence<N % 2 == 1, typename MakeIndexSequence<N / 2>::type,
N / 2>::type {};
template <>
struct MakeIndexSequence<0> : IndexSequence<> {};
// FIXME: This implementation of ElemFromList is O(1) in instantiation depth,
// but it is O(N^2) in total instantiations. Not sure if this is the best
// tradeoff, as it will make it somewhat slow to compile.
template <typename T, size_t, size_t>
struct ElemFromListImpl {};
template <typename T, size_t I>
struct ElemFromListImpl<T, I, I> {
using type = T;
};
// Get the Nth element from T...
// It uses O(1) instantiation depth.
template <size_t N, typename I, typename... T>
struct ElemFromList;
template <size_t N, size_t... I, typename... T>
struct ElemFromList<N, IndexSequence<I...>, T...>
: ElemFromListImpl<T, N, I>... {};
template <typename... T>
class FlatTuple;
template <typename Derived, size_t I>
struct FlatTupleElemBase;
template <typename... T, size_t I>
struct FlatTupleElemBase<FlatTuple<T...>, I> {
using value_type =
typename ElemFromList<I, typename MakeIndexSequence<sizeof...(T)>::type,
T...>::type;
FlatTupleElemBase() = default;
explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {}
value_type value;
};
template <typename Derived, typename Idx>
struct FlatTupleBase;
template <size_t... Idx, typename... T>
struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>>
: FlatTupleElemBase<FlatTuple<T...>, Idx>... {
using Indices = IndexSequence<Idx...>;
FlatTupleBase() = default;
explicit FlatTupleBase(T... t)
: FlatTupleElemBase<FlatTuple<T...>, Idx>(std::move(t))... {}
};
// Analog to std::tuple but with different tradeoffs.
// This class minimizes the template instantiation depth, thus allowing more
// elements that std::tuple would. std::tuple has been seen to require an
// instantiation depth of more than 10x the number of elements in some
// implementations.
// FlatTuple and ElemFromList are not recursive and have a fixed depth
// regardless of T...
// MakeIndexSequence, on the other hand, it is recursive but with an
// instantiation depth of O(ln(N)).
template <typename... T>
class FlatTuple
: private FlatTupleBase<FlatTuple<T...>,
typename MakeIndexSequence<sizeof...(T)>::type> {
using Indices = typename FlatTuple::FlatTupleBase::Indices;
public:
FlatTuple() = default;
explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {}
template <size_t I>
const typename ElemFromList<I, Indices, T...>::type& Get() const {
return static_cast<const FlatTupleElemBase<FlatTuple, I>*>(this)->value;
}
template <size_t I>
typename ElemFromList<I, Indices, T...>::type& Get() {
return static_cast<FlatTupleElemBase<FlatTuple, I>*>(this)->value;
}
};
// Utility functions to be called with static_assert to induce deprecation
// warnings.
GTEST_INTERNAL_DEPRECATED(
"INSTANTIATE_TEST_CASE_P is deprecated, please use "
"INSTANTIATE_TEST_SUITE_P")
constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; }
GTEST_INTERNAL_DEPRECATED(
"TYPED_TEST_CASE_P is deprecated, please use "
"TYPED_TEST_SUITE_P")
constexpr bool TypedTestCase_P_IsDeprecated() { return true; }
GTEST_INTERNAL_DEPRECATED(
"TYPED_TEST_CASE is deprecated, please use "
"TYPED_TEST_SUITE")
constexpr bool TypedTestCaseIsDeprecated() { return true; }
GTEST_INTERNAL_DEPRECATED(
"REGISTER_TYPED_TEST_CASE_P is deprecated, please use "
"REGISTER_TYPED_TEST_SUITE_P")
constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; }
GTEST_INTERNAL_DEPRECATED(
"INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use "
"INSTANTIATE_TYPED_TEST_SUITE_P")
constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; }
} // namespace internal
} // namespace testing
@@ -1208,7 +1248,10 @@ class NativeArray {
#define GTEST_SUCCESS_(message) \
GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess)
// Suppress MSVC warning 4702 (unreachable code) for the code following
#define GTEST_SKIP_(message) \
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip)
// Suppress MSVC warning 4072 (unreachable code) for the code following
// statement if it returns or throws (or doesn't return or throw in some
// situations).
#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \
@@ -1300,31 +1343,38 @@ class NativeArray {
" Actual: it does.")
// Expands to the name of the class that implements the given test.
#define GTEST_TEST_CLASS_NAME_(test_case_name, test_name) \
test_case_name##_##test_name##_Test
#define GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
test_suite_name##_##test_name##_Test
// Helper macro for defining tests.
#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\
class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
public:\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\
private:\
virtual void TestBody();\
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_;\
GTEST_DISALLOW_COPY_AND_ASSIGN_(\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name));\
};\
\
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_case_name, test_name)\
::test_info_ =\
::testing::internal::MakeAndRegisterTestInfo(\
#test_case_name, #test_name, NULL, NULL, \
::testing::internal::CodeLocation(__FILE__, __LINE__), \
(parent_id), \
parent_class::SetUpTestCase, \
parent_class::TearDownTestCase, \
new ::testing::internal::TestFactoryImpl<\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>);\
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \
static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \
"test_suite_name must not be empty"); \
static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \
"test_name must not be empty"); \
class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \
: public parent_class { \
public: \
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \
\
private: \
virtual void TestBody(); \
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)); \
}; \
\
::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \
test_name)::test_info_ = \
::testing::internal::MakeAndRegisterTestInfo( \
#test_suite_name, #test_name, nullptr, nullptr, \
::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \
::testing::internal::SuiteApiResolver< \
parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \
::testing::internal::SuiteApiResolver< \
parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \
new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \
test_suite_name, test_name)>); \
void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody()
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_