gtest-internal.h (googletest-release-1.10.0) | : | gtest-internal.h (googletest-release-1.11.0) | ||
---|---|---|---|---|
skipping to change at line 37 | skipping to change at line 37 | |||
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |||
// | // | |||
// The Google C++ Testing and Mocking Framework (Google Test) | // The Google C++ Testing and Mocking Framework (Google Test) | |||
// | // | |||
// This header file declares functions and macros used internally by | // This header file declares functions and macros used internally by | |||
// Google Test. They are subject to change without notice. | // Google Test. They are subject to change without notice. | |||
// GOOGLETEST_CM0001 DO NOT DELETE | // GOOGLETEST_CM0001 DO NOT DELETE | |||
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ | #ifndef GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ | |||
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ | #define GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ | |||
#include "gtest/internal/gtest-port.h" | #include "gtest/internal/gtest-port.h" | |||
#if GTEST_OS_LINUX | #if GTEST_OS_LINUX | |||
# include <stdlib.h> | # include <stdlib.h> | |||
# include <sys/types.h> | # include <sys/types.h> | |||
# include <sys/wait.h> | # include <sys/wait.h> | |||
# include <unistd.h> | # include <unistd.h> | |||
#endif // GTEST_OS_LINUX | #endif // GTEST_OS_LINUX | |||
#if GTEST_HAS_EXCEPTIONS | #if GTEST_HAS_EXCEPTIONS | |||
# include <stdexcept> | # include <stdexcept> | |||
#endif | #endif | |||
#include <ctype.h> | #include <ctype.h> | |||
#include <float.h> | #include <float.h> | |||
#include <string.h> | #include <string.h> | |||
#include <cstdint> | ||||
#include <iomanip> | #include <iomanip> | |||
#include <limits> | #include <limits> | |||
#include <map> | #include <map> | |||
#include <set> | #include <set> | |||
#include <string> | #include <string> | |||
#include <type_traits> | #include <type_traits> | |||
#include <vector> | #include <vector> | |||
#include "gtest/gtest-message.h" | #include "gtest/gtest-message.h" | |||
#include "gtest/internal/gtest-filepath.h" | #include "gtest/internal/gtest-filepath.h" | |||
skipping to change at line 81 | skipping to change at line 82 | |||
// | // | |||
// foo ## __LINE__ | // foo ## __LINE__ | |||
// | // | |||
// will result in the token foo__LINE__, instead of foo followed by | // will result in the token foo__LINE__, instead of foo followed by | |||
// the current line number. For more details, see | // the current line number. For more details, see | |||
// http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 | // http://www.parashift.com/c++-faq-lite/misc-technical-issues.html#faq-39.6 | |||
#define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) | #define GTEST_CONCAT_TOKEN_(foo, bar) GTEST_CONCAT_TOKEN_IMPL_(foo, bar) | |||
#define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar | #define GTEST_CONCAT_TOKEN_IMPL_(foo, bar) foo ## bar | |||
// Stringifies its argument. | // Stringifies its argument. | |||
#define GTEST_STRINGIFY_(name) #name | // Work around a bug in visual studio which doesn't accept code like this: | |||
// | ||||
// #define GTEST_STRINGIFY_(name) #name | ||||
// #define MACRO(a, b, c) ... GTEST_STRINGIFY_(a) ... | ||||
// MACRO(, x, y) | ||||
// | ||||
// Complaining about the argument to GTEST_STRINGIFY_ being empty. | ||||
// This is allowed by the spec. | ||||
#define GTEST_STRINGIFY_HELPER_(name, ...) #name | ||||
#define GTEST_STRINGIFY_(...) GTEST_STRINGIFY_HELPER_(__VA_ARGS__, ) | ||||
namespace proto2 { class Message; } | namespace proto2 { | |||
class MessageLite; | ||||
} | ||||
namespace testing { | namespace testing { | |||
// Forward declarations. | // Forward declarations. | |||
class AssertionResult; // Result of an assertion. | class AssertionResult; // Result of an assertion. | |||
class Message; // Represents a failure message. | class Message; // Represents a failure message. | |||
class Test; // Represents a test. | class Test; // Represents a test. | |||
class TestInfo; // Information about a test. | class TestInfo; // Information about a test. | |||
class TestPartResult; // Result of a test part. | class TestPartResult; // Result of a test part. | |||
skipping to change at line 278 | skipping to change at line 290 | |||
// allow. A 0 value means that two numbers must be exactly the same | // allow. A 0 value means that two numbers must be exactly the same | |||
// to be considered equal. | // to be considered equal. | |||
// | // | |||
// The maximum error of a single floating-point operation is 0.5 | // The maximum error of a single floating-point operation is 0.5 | |||
// units in the last place. On Intel CPU's, all floating-point | // units in the last place. On Intel CPU's, all floating-point | |||
// calculations are done with 80-bit precision, while double has 64 | // calculations are done with 80-bit precision, while double has 64 | |||
// bits. Therefore, 4 should be enough for ordinary use. | // bits. Therefore, 4 should be enough for ordinary use. | |||
// | // | |||
// See the following article for more details on ULP: | // See the following article for more details on ULP: | |||
// http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-number s-2012-edition/ | // http://randomascii.wordpress.com/2012/02/25/comparing-floating-point-number s-2012-edition/ | |||
static const size_t kMaxUlps = 4; | static const uint32_t kMaxUlps = 4; | |||
// Constructs a FloatingPoint from a raw floating-point number. | // Constructs a FloatingPoint from a raw floating-point number. | |||
// | // | |||
// On an Intel CPU, passing a non-normalized NAN (Not a Number) | // On an Intel CPU, passing a non-normalized NAN (Not a Number) | |||
// around may change its bits, although the new value is guaranteed | // around may change its bits, although the new value is guaranteed | |||
// to be also a NAN. Therefore, don't expect this constructor to | // to be also a NAN. Therefore, don't expect this constructor to | |||
// preserve the bits in x when x is a NAN. | // preserve the bits in x when x is a NAN. | |||
explicit FloatingPoint(const RawType& x) { u_.value_ = x; } | explicit FloatingPoint(const RawType& x) { u_.value_ = x; } | |||
// Static methods | // Static methods | |||
skipping to change at line 511 | skipping to change at line 523 | |||
// SetUpTestSuite()/TearDownTestSuite() could be protected. Ths way | // SetUpTestSuite()/TearDownTestSuite() could be protected. Ths way | |||
// SuiteApiResolver can access them. | // SuiteApiResolver can access them. | |||
struct SuiteApiResolver : T { | struct SuiteApiResolver : T { | |||
// testing::Test is only forward declared at this point. So we make it a | // testing::Test is only forward declared at this point. So we make it a | |||
// dependend class for the compiler to be OK with it. | // dependend class for the compiler to be OK with it. | |||
using Test = | using Test = | |||
typename std::conditional<sizeof(T) != 0, ::testing::Test, void>::type; | typename std::conditional<sizeof(T) != 0, ::testing::Test, void>::type; | |||
static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename, | static SetUpTearDownSuiteFuncType GetSetUpCaseOrSuite(const char* filename, | |||
int line_num) { | int line_num) { | |||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ | ||||
SetUpTearDownSuiteFuncType test_case_fp = | SetUpTearDownSuiteFuncType test_case_fp = | |||
GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase); | GetNotDefaultOrNull(&T::SetUpTestCase, &Test::SetUpTestCase); | |||
SetUpTearDownSuiteFuncType test_suite_fp = | SetUpTearDownSuiteFuncType test_suite_fp = | |||
GetNotDefaultOrNull(&T::SetUpTestSuite, &Test::SetUpTestSuite); | GetNotDefaultOrNull(&T::SetUpTestSuite, &Test::SetUpTestSuite); | |||
GTEST_CHECK_(!test_case_fp || !test_suite_fp) | GTEST_CHECK_(!test_case_fp || !test_suite_fp) | |||
<< "Test can not provide both SetUpTestSuite and SetUpTestCase, please " | << "Test can not provide both SetUpTestSuite and SetUpTestCase, please " | |||
"make sure there is only one present at " | "make sure there is only one present at " | |||
<< filename << ":" << line_num; | << filename << ":" << line_num; | |||
return test_case_fp != nullptr ? test_case_fp : test_suite_fp; | return test_case_fp != nullptr ? test_case_fp : test_suite_fp; | |||
#else | ||||
(void)(filename); | ||||
(void)(line_num); | ||||
return &T::SetUpTestSuite; | ||||
#endif | ||||
} | } | |||
static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename, | static SetUpTearDownSuiteFuncType GetTearDownCaseOrSuite(const char* filename, | |||
int line_num) { | int line_num) { | |||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ | ||||
SetUpTearDownSuiteFuncType test_case_fp = | SetUpTearDownSuiteFuncType test_case_fp = | |||
GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase); | GetNotDefaultOrNull(&T::TearDownTestCase, &Test::TearDownTestCase); | |||
SetUpTearDownSuiteFuncType test_suite_fp = | SetUpTearDownSuiteFuncType test_suite_fp = | |||
GetNotDefaultOrNull(&T::TearDownTestSuite, &Test::TearDownTestSuite); | GetNotDefaultOrNull(&T::TearDownTestSuite, &Test::TearDownTestSuite); | |||
GTEST_CHECK_(!test_case_fp || !test_suite_fp) | GTEST_CHECK_(!test_case_fp || !test_suite_fp) | |||
<< "Test can not provide both TearDownTestSuite and TearDownTestCase," | << "Test can not provide both TearDownTestSuite and TearDownTestCase," | |||
" please make sure there is only one present at" | " please make sure there is only one present at" | |||
<< filename << ":" << line_num; | << filename << ":" << line_num; | |||
return test_case_fp != nullptr ? test_case_fp : test_suite_fp; | return test_case_fp != nullptr ? test_case_fp : test_suite_fp; | |||
#else | ||||
(void)(filename); | ||||
(void)(line_num); | ||||
return &T::TearDownTestSuite; | ||||
#endif | ||||
} | } | |||
}; | }; | |||
// Creates a new TestInfo object and registers it with Google Test; | // Creates a new TestInfo object and registers it with Google Test; | |||
// returns the created object. | // returns the created object. | |||
// | // | |||
// Arguments: | // Arguments: | |||
// | // | |||
// test_suite_name: name of the test suite | // test_suite_name: name of the test suite | |||
// name: name of the test | // name: name of the test | |||
// type_param the name of the test's type parameter, or NULL if | // type_param: the name of the test's type parameter, or NULL if | |||
// this is not a typed or a type-parameterized test. | // this is not a typed or a type-parameterized test. | |||
// value_param text representation of the test's value parameter, | // value_param: text representation of the test's value parameter, | |||
// or NULL if this is not a type-parameterized test. | // or NULL if this is not a type-parameterized test. | |||
// code_location: code location where the test is defined | // code_location: code location where the test is defined | |||
// fixture_class_id: ID of the test fixture class | // fixture_class_id: ID of the test fixture class | |||
// set_up_tc: pointer to the function that sets up the test suite | // 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 | // tear_down_tc: pointer to the function that tears down the test suite | |||
// factory: pointer to the factory that creates a test object. | // factory: pointer to the factory that creates a test object. | |||
// The newly created TestInfo instance will assume | // The newly created TestInfo instance will assume | |||
// ownership of the factory object. | // ownership of the factory object. | |||
GTEST_API_ TestInfo* MakeAndRegisterTestInfo( | GTEST_API_ TestInfo* MakeAndRegisterTestInfo( | |||
const char* test_suite_name, const char* name, const char* type_param, | const char* test_suite_name, const char* name, const char* type_param, | |||
const char* value_param, CodeLocation code_location, | const char* value_param, CodeLocation code_location, | |||
TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, | TypeId fixture_class_id, SetUpTestSuiteFunc set_up_tc, | |||
TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory); | TearDownTestSuiteFunc tear_down_tc, TestFactoryBase* factory); | |||
// If *pstr starts with the given prefix, modifies *pstr to be right | // If *pstr starts with the given prefix, modifies *pstr to be right | |||
// past the prefix and returns true; otherwise leaves *pstr unchanged | // past the prefix and returns true; otherwise leaves *pstr unchanged | |||
// and returns false. None of pstr, *pstr, and prefix can be NULL. | // and returns false. None of pstr, *pstr, and prefix can be NULL. | |||
GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); | GTEST_API_ bool SkipPrefix(const char* prefix, const char** pstr); | |||
#if GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P | ||||
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ | GTEST_DISABLE_MSC_WARNINGS_PUSH_(4251 \ | |||
/* class A needs to have dll-interface to be used by clients of class B */) | /* class A needs to have dll-interface to be used by clients of class B */) | |||
// State of the definition of a type-parameterized test suite. | // State of the definition of a type-parameterized test suite. | |||
class GTEST_API_ TypedTestSuitePState { | class GTEST_API_ TypedTestSuitePState { | |||
public: | public: | |||
TypedTestSuitePState() : registered_(false) {} | TypedTestSuitePState() : registered_(false) {} | |||
// Adds the given test name to defined_test_names_ and return true | // Adds the given test name to defined_test_names_ and return true | |||
// if the test suite hasn't been registered; otherwise aborts the | // if the test suite hasn't been registered; otherwise aborts the | |||
skipping to change at line 610 | skipping to change at line 632 | |||
const CodeLocation& GetCodeLocation(const std::string& test_name) const { | const CodeLocation& GetCodeLocation(const std::string& test_name) const { | |||
RegisteredTestsMap::const_iterator it = registered_tests_.find(test_name); | RegisteredTestsMap::const_iterator it = registered_tests_.find(test_name); | |||
GTEST_CHECK_(it != registered_tests_.end()); | GTEST_CHECK_(it != registered_tests_.end()); | |||
return it->second; | return it->second; | |||
} | } | |||
// Verifies that registered_tests match the test names in | // Verifies that registered_tests match the test names in | |||
// defined_test_names_; returns registered_tests if successful, or | // defined_test_names_; returns registered_tests if successful, or | |||
// aborts the program otherwise. | // aborts the program otherwise. | |||
const char* VerifyRegisteredTestNames( | const char* VerifyRegisteredTestNames(const char* test_suite_name, | |||
const char* file, int line, const char* registered_tests); | const char* file, int line, | |||
const char* registered_tests); | ||||
private: | private: | |||
typedef ::std::map<std::string, CodeLocation> RegisteredTestsMap; | typedef ::std::map<std::string, CodeLocation> RegisteredTestsMap; | |||
bool registered_; | bool registered_; | |||
RegisteredTestsMap registered_tests_; | RegisteredTestsMap registered_tests_; | |||
}; | }; | |||
// Legacy API is deprecated but still available | // Legacy API is deprecated but still available | |||
#ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ | #ifndef GTEST_REMOVE_LEGACY_TEST_CASEAPI_ | |||
skipping to change at line 665 | skipping to change at line 688 | |||
return StreamableToString(i); | return StreamableToString(i); | |||
} | } | |||
}; | }; | |||
template <typename Provided = DefaultNameGenerator> | template <typename Provided = DefaultNameGenerator> | |||
struct NameGeneratorSelector { | struct NameGeneratorSelector { | |||
typedef Provided type; | typedef Provided type; | |||
}; | }; | |||
template <typename NameGenerator> | template <typename NameGenerator> | |||
void GenerateNamesRecursively(Types0, std::vector<std::string>*, int) {} | void GenerateNamesRecursively(internal::None, std::vector<std::string>*, int) {} | |||
template <typename NameGenerator, typename Types> | template <typename NameGenerator, typename Types> | |||
void GenerateNamesRecursively(Types, std::vector<std::string>* result, int i) { | void GenerateNamesRecursively(Types, std::vector<std::string>* result, int i) { | |||
result->push_back(NameGenerator::template GetName<typename Types::Head>(i)); | result->push_back(NameGenerator::template GetName<typename Types::Head>(i)); | |||
GenerateNamesRecursively<NameGenerator>(typename Types::Tail(), result, | GenerateNamesRecursively<NameGenerator>(typename Types::Tail(), result, | |||
i + 1); | i + 1); | |||
} | } | |||
template <typename NameGenerator, typename Types> | template <typename NameGenerator, typename Types> | |||
std::vector<std::string> GenerateNames() { | std::vector<std::string> GenerateNames() { | |||
skipping to change at line 732 | skipping to change at line 755 | |||
code_location, | code_location, | |||
case_name, | case_name, | |||
test_names, | test_names, | |||
index + 1, | index + 1, | |||
type_names); | type_names); | |||
} | } | |||
}; | }; | |||
// The base case for the compile time recursion. | // The base case for the compile time recursion. | |||
template <GTEST_TEMPLATE_ Fixture, class TestSel> | template <GTEST_TEMPLATE_ Fixture, class TestSel> | |||
class TypeParameterizedTest<Fixture, TestSel, Types0> { | class TypeParameterizedTest<Fixture, TestSel, internal::None> { | |||
public: | public: | |||
static bool Register(const char* /*prefix*/, const CodeLocation&, | static bool Register(const char* /*prefix*/, const CodeLocation&, | |||
const char* /*case_name*/, const char* /*test_names*/, | const char* /*case_name*/, const char* /*test_names*/, | |||
int /*index*/, | int /*index*/, | |||
const std::vector<std::string>& = | const std::vector<std::string>& = | |||
std::vector<std::string>() /*type_names*/) { | std::vector<std::string>() /*type_names*/) { | |||
return true; | return true; | |||
} | } | |||
}; | }; | |||
GTEST_API_ void RegisterTypeParameterizedTestSuite(const char* test_suite_name, | ||||
CodeLocation code_location); | ||||
GTEST_API_ void RegisterTypeParameterizedTestSuiteInstantiation( | ||||
const char* case_name); | ||||
// TypeParameterizedTestSuite<Fixture, Tests, Types>::Register() | // TypeParameterizedTestSuite<Fixture, Tests, Types>::Register() | |||
// registers *all combinations* of 'Tests' and 'Types' with Google | // registers *all combinations* of 'Tests' and 'Types' with Google | |||
// Test. The return value is insignificant - we just need to return | // Test. The return value is insignificant - we just need to return | |||
// something such that we can call this function in a namespace scope. | // something such that we can call this function in a namespace scope. | |||
template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types> | template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types> | |||
class TypeParameterizedTestSuite { | class TypeParameterizedTestSuite { | |||
public: | public: | |||
static bool Register(const char* prefix, CodeLocation code_location, | static bool Register(const char* prefix, CodeLocation code_location, | |||
const TypedTestSuitePState* state, const char* case_name, | const TypedTestSuitePState* state, const char* case_name, | |||
const char* test_names, | const char* test_names, | |||
const std::vector<std::string>& type_names = | const std::vector<std::string>& type_names = | |||
GenerateNames<DefaultNameGenerator, Types>()) { | GenerateNames<DefaultNameGenerator, Types>()) { | |||
RegisterTypeParameterizedTestSuiteInstantiation(case_name); | ||||
std::string test_name = StripTrailingSpaces( | std::string test_name = StripTrailingSpaces( | |||
GetPrefixUntilComma(test_names)); | GetPrefixUntilComma(test_names)); | |||
if (!state->TestExists(test_name)) { | if (!state->TestExists(test_name)) { | |||
fprintf(stderr, "Failed to get code location for test %s.%s at %s.", | fprintf(stderr, "Failed to get code location for test %s.%s at %s.", | |||
case_name, test_name.c_str(), | case_name, test_name.c_str(), | |||
FormatFileLocation(code_location.file.c_str(), | FormatFileLocation(code_location.file.c_str(), | |||
code_location.line).c_str()); | code_location.line).c_str()); | |||
fflush(stderr); | fflush(stderr); | |||
posix::Abort(); | posix::Abort(); | |||
} | } | |||
skipping to change at line 784 | skipping to change at line 813 | |||
return TypeParameterizedTestSuite<Fixture, typename Tests::Tail, | return TypeParameterizedTestSuite<Fixture, typename Tests::Tail, | |||
Types>::Register(prefix, code_location, | Types>::Register(prefix, code_location, | |||
state, case_name, | state, case_name, | |||
SkipComma(test_names), | SkipComma(test_names), | |||
type_names); | type_names); | |||
} | } | |||
}; | }; | |||
// The base case for the compile time recursion. | // The base case for the compile time recursion. | |||
template <GTEST_TEMPLATE_ Fixture, typename Types> | template <GTEST_TEMPLATE_ Fixture, typename Types> | |||
class TypeParameterizedTestSuite<Fixture, Templates0, Types> { | class TypeParameterizedTestSuite<Fixture, internal::None, Types> { | |||
public: | public: | |||
static bool Register(const char* /*prefix*/, const CodeLocation&, | static bool Register(const char* /*prefix*/, const CodeLocation&, | |||
const TypedTestSuitePState* /*state*/, | const TypedTestSuitePState* /*state*/, | |||
const char* /*case_name*/, const char* /*test_names*/, | const char* /*case_name*/, const char* /*test_names*/, | |||
const std::vector<std::string>& = | const std::vector<std::string>& = | |||
std::vector<std::string>() /*type_names*/) { | std::vector<std::string>() /*type_names*/) { | |||
return true; | return true; | |||
} | } | |||
}; | }; | |||
#endif // GTEST_HAS_TYPED_TEST || GTEST_HAS_TYPED_TEST_P | ||||
// Returns the current OS stack trace as an std::string. | // Returns the current OS stack trace as an std::string. | |||
// | // | |||
// The maximum number of stack frames to be included is specified by | // The maximum number of stack frames to be included is specified by | |||
// the gtest_stack_trace_depth flag. The skip_count parameter | // the gtest_stack_trace_depth flag. The skip_count parameter | |||
// specifies the number of top frames to be skipped, which doesn't | // specifies the number of top frames to be skipped, which doesn't | |||
// count against the number of frames to be included. | // count against the number of frames to be included. | |||
// | // | |||
// For example, if Foo() calls Bar(), which in turn calls | // For example, if Foo() calls Bar(), which in turn calls | |||
// GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in | // GetCurrentOsStackTraceExceptTop(..., 1), Foo() will be included in | |||
// the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. | // the trace but Bar() and GetCurrentOsStackTraceExceptTop() won't. | |||
skipping to change at line 828 | skipping to change at line 855 | |||
// Helper for suppressing false warning from Clang on a const char* | // Helper for suppressing false warning from Clang on a const char* | |||
// variable declared in a conditional expression always being NULL in | // variable declared in a conditional expression always being NULL in | |||
// the else branch. | // the else branch. | |||
struct GTEST_API_ ConstCharPtr { | struct GTEST_API_ ConstCharPtr { | |||
ConstCharPtr(const char* str) : value(str) {} | ConstCharPtr(const char* str) : value(str) {} | |||
operator bool() const { return true; } | operator bool() const { return true; } | |||
const char* value; | const char* value; | |||
}; | }; | |||
// Helper for declaring std::string within 'if' statement | ||||
// in pre C++17 build environment. | ||||
struct TrueWithString { | ||||
TrueWithString() = default; | ||||
explicit TrueWithString(const char* str) : value(str) {} | ||||
explicit TrueWithString(const std::string& str) : value(str) {} | ||||
explicit operator bool() const { return true; } | ||||
std::string value; | ||||
}; | ||||
// A simple Linear Congruential Generator for generating random | // A simple Linear Congruential Generator for generating random | |||
// numbers with a uniform distribution. Unlike rand() and srand(), it | // numbers with a uniform distribution. Unlike rand() and srand(), it | |||
// doesn't use global state (and therefore can't interfere with user | // doesn't use global state (and therefore can't interfere with user | |||
// code). Unlike rand_r(), it's portable. An LCG isn't very random, | // code). Unlike rand_r(), it's portable. An LCG isn't very random, | |||
// but it's good enough for our purposes. | // but it's good enough for our purposes. | |||
class GTEST_API_ Random { | class GTEST_API_ Random { | |||
public: | public: | |||
static const UInt32 kMaxRange = 1u << 31; | static const uint32_t kMaxRange = 1u << 31; | |||
explicit Random(UInt32 seed) : state_(seed) {} | explicit Random(uint32_t seed) : state_(seed) {} | |||
void Reseed(UInt32 seed) { state_ = seed; } | void Reseed(uint32_t seed) { state_ = seed; } | |||
// Generates a random number from [0, range). Crashes if 'range' is | // Generates a random number from [0, range). Crashes if 'range' is | |||
// 0 or greater than kMaxRange. | // 0 or greater than kMaxRange. | |||
UInt32 Generate(UInt32 range); | uint32_t Generate(uint32_t range); | |||
private: | private: | |||
UInt32 state_; | uint32_t state_; | |||
GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); | GTEST_DISALLOW_COPY_AND_ASSIGN_(Random); | |||
}; | }; | |||
// Turns const U&, U&, const U, and U all into U. | // Turns const U&, U&, const U, and U all into U. | |||
#define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ | #define GTEST_REMOVE_REFERENCE_AND_CONST_(T) \ | |||
typename std::remove_const<typename std::remove_reference<T>::type>::type | typename std::remove_const<typename std::remove_reference<T>::type>::type | |||
// IsAProtocolMessage<T>::value is a compile-time bool constant that's | // HasDebugStringAndShortDebugString<T>::value is a compile-time bool constant | |||
// true if and only if T is type proto2::Message or a subclass of it. | // that's true if and only if T has methods DebugString() and ShortDebugString() | |||
// that return std::string. | ||||
template <typename T> | template <typename T> | |||
struct IsAProtocolMessage | class HasDebugStringAndShortDebugString { | |||
: public bool_constant< | private: | |||
std::is_convertible<const T*, const ::proto2::Message*>::value> {}; | template <typename C> | |||
static auto CheckDebugString(C*) -> typename std::is_same< | ||||
std::string, decltype(std::declval<const C>().DebugString())>::type; | ||||
template <typename> | ||||
static std::false_type CheckDebugString(...); | ||||
template <typename C> | ||||
static auto CheckShortDebugString(C*) -> typename std::is_same< | ||||
std::string, decltype(std::declval<const C>().ShortDebugString())>::type; | ||||
template <typename> | ||||
static std::false_type CheckShortDebugString(...); | ||||
using HasDebugStringType = decltype(CheckDebugString<T>(nullptr)); | ||||
using HasShortDebugStringType = decltype(CheckShortDebugString<T>(nullptr)); | ||||
public: | ||||
static constexpr bool value = | ||||
HasDebugStringType::value && HasShortDebugStringType::value; | ||||
}; | ||||
template <typename T> | ||||
constexpr bool HasDebugStringAndShortDebugString<T>::value; | ||||
// When the compiler sees expression IsContainerTest<C>(0), if C is an | // When the compiler sees expression IsContainerTest<C>(0), if C is an | |||
// STL-style container class, the first overload of IsContainerTest | // STL-style container class, the first overload of IsContainerTest | |||
// will be viable (since both C::iterator* and C::const_iterator* are | // will be viable (since both C::iterator* and C::const_iterator* are | |||
// valid types and NULL can be implicitly converted to them). It will | // valid types and NULL can be implicitly converted to them). It will | |||
// be picked over the second overload as 'int' is a perfect match for | // be picked over the second overload as 'int' is a perfect match for | |||
// the type of argument 0. If C::iterator or C::const_iterator is not | // the type of argument 0. If C::iterator or C::const_iterator is not | |||
// a valid type, the first overload is not viable, and the second | // a valid type, the first overload is not viable, and the second | |||
// overload will be picked. Therefore, we can determine whether C is | // overload will be picked. Therefore, we can determine whether C is | |||
// a container class by checking the type of IsContainerTest<C>(0). | // a container class by checking the type of IsContainerTest<C>(0). | |||
skipping to change at line 1095 | skipping to change at line 1154 | |||
// Initializes this object with a reference of the input. | // Initializes this object with a reference of the input. | |||
void InitRef(const Element* array, size_t a_size) { | void InitRef(const Element* array, size_t a_size) { | |||
array_ = array; | array_ = array; | |||
size_ = a_size; | size_ = a_size; | |||
clone_ = &NativeArray::InitRef; | clone_ = &NativeArray::InitRef; | |||
} | } | |||
const Element* array_; | const Element* array_; | |||
size_t size_; | size_t size_; | |||
void (NativeArray::*clone_)(const Element*, size_t); | void (NativeArray::*clone_)(const Element*, size_t); | |||
GTEST_DISALLOW_ASSIGN_(NativeArray); | ||||
}; | }; | |||
// Backport of std::index_sequence. | // Backport of std::index_sequence. | |||
template <size_t... Is> | template <size_t... Is> | |||
struct IndexSequence { | struct IndexSequence { | |||
using type = IndexSequence; | using type = IndexSequence; | |||
}; | }; | |||
// Double the IndexSequence, and one if plus_one is true. | // Double the IndexSequence, and one if plus_one is true. | |||
template <bool plus_one, typename T, size_t sizeofT> | template <bool plus_one, typename T, size_t sizeofT> | |||
skipping to change at line 1120 | skipping to change at line 1177 | |||
using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>; | using type = IndexSequence<I..., (sizeofT + I)..., 2 * sizeofT>; | |||
}; | }; | |||
template <size_t... I, size_t sizeofT> | template <size_t... I, size_t sizeofT> | |||
struct DoubleSequence<false, IndexSequence<I...>, sizeofT> { | struct DoubleSequence<false, IndexSequence<I...>, sizeofT> { | |||
using type = IndexSequence<I..., (sizeofT + I)...>; | using type = IndexSequence<I..., (sizeofT + I)...>; | |||
}; | }; | |||
// Backport of std::make_index_sequence. | // Backport of std::make_index_sequence. | |||
// It uses O(ln(N)) instantiation depth. | // It uses O(ln(N)) instantiation depth. | |||
template <size_t N> | template <size_t N> | |||
struct MakeIndexSequence | struct MakeIndexSequenceImpl | |||
: DoubleSequence<N % 2 == 1, typename MakeIndexSequence<N / 2>::type, | : DoubleSequence<N % 2 == 1, typename MakeIndexSequenceImpl<N / 2>::type, | |||
N / 2>::type {}; | N / 2>::type {}; | |||
template <> | template <> | |||
struct MakeIndexSequence<0> : IndexSequence<> {}; | struct MakeIndexSequenceImpl<0> : IndexSequence<> {}; | |||
template <size_t N> | ||||
using MakeIndexSequence = typename MakeIndexSequenceImpl<N>::type; | ||||
template <typename... T> | ||||
using IndexSequenceFor = typename MakeIndexSequence<sizeof...(T)>::type; | ||||
// FIXME: This implementation of ElemFromList is O(1) in instantiation depth, | template <size_t> | |||
// but it is O(N^2) in total instantiations. Not sure if this is the best | struct Ignore { | |||
// tradeoff, as it will make it somewhat slow to compile. | Ignore(...); // NOLINT | |||
template <typename T, size_t, size_t> | }; | |||
struct ElemFromListImpl {}; | ||||
template <typename> | ||||
template <typename T, size_t I> | struct ElemFromListImpl; | |||
struct ElemFromListImpl<T, I, I> { | template <size_t... I> | |||
using type = T; | struct ElemFromListImpl<IndexSequence<I...>> { | |||
}; | // We make Ignore a template to solve a problem with MSVC. | |||
// A non-template Ignore would work fine with `decltype(Ignore(I))...`, but | ||||
// Get the Nth element from T... | // MSVC doesn't understand how to deal with that pack expansion. | |||
// It uses O(1) instantiation depth. | // Use `0 * I` to have a single instantiation of Ignore. | |||
template <size_t N, typename I, typename... T> | template <typename R> | |||
struct ElemFromList; | static R Apply(Ignore<0 * I>..., R (*)(), ...); | |||
}; | ||||
template <size_t N, size_t... I, typename... T> | ||||
struct ElemFromList<N, IndexSequence<I...>, T...> | template <size_t N, typename... T> | |||
: ElemFromListImpl<T, N, I>... {}; | struct ElemFromList { | |||
using type = | ||||
decltype(ElemFromListImpl<typename MakeIndexSequence<N>::type>::Apply( | ||||
static_cast<T (*)()>(nullptr)...)); | ||||
}; | ||||
struct FlatTupleConstructTag {}; | ||||
template <typename... T> | template <typename... T> | |||
class FlatTuple; | class FlatTuple; | |||
template <typename Derived, size_t I> | template <typename Derived, size_t I> | |||
struct FlatTupleElemBase; | struct FlatTupleElemBase; | |||
template <typename... T, size_t I> | template <typename... T, size_t I> | |||
struct FlatTupleElemBase<FlatTuple<T...>, I> { | struct FlatTupleElemBase<FlatTuple<T...>, I> { | |||
using value_type = | using value_type = typename ElemFromList<I, T...>::type; | |||
typename ElemFromList<I, typename MakeIndexSequence<sizeof...(T)>::type, | ||||
T...>::type; | ||||
FlatTupleElemBase() = default; | FlatTupleElemBase() = default; | |||
explicit FlatTupleElemBase(value_type t) : value(std::move(t)) {} | template <typename Arg> | |||
explicit FlatTupleElemBase(FlatTupleConstructTag, Arg&& t) | ||||
: value(std::forward<Arg>(t)) {} | ||||
value_type value; | value_type value; | |||
}; | }; | |||
template <typename Derived, typename Idx> | template <typename Derived, typename Idx> | |||
struct FlatTupleBase; | struct FlatTupleBase; | |||
template <size_t... Idx, typename... T> | template <size_t... Idx, typename... T> | |||
struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>> | struct FlatTupleBase<FlatTuple<T...>, IndexSequence<Idx...>> | |||
: FlatTupleElemBase<FlatTuple<T...>, Idx>... { | : FlatTupleElemBase<FlatTuple<T...>, Idx>... { | |||
using Indices = IndexSequence<Idx...>; | using Indices = IndexSequence<Idx...>; | |||
FlatTupleBase() = default; | FlatTupleBase() = default; | |||
explicit FlatTupleBase(T... t) | template <typename... Args> | |||
: FlatTupleElemBase<FlatTuple<T...>, Idx>(std::move(t))... {} | explicit FlatTupleBase(FlatTupleConstructTag, Args&&... args) | |||
: FlatTupleElemBase<FlatTuple<T...>, Idx>(FlatTupleConstructTag{}, | ||||
std::forward<Args>(args))... {} | ||||
template <size_t I> | ||||
const typename ElemFromList<I, T...>::type& Get() const { | ||||
return FlatTupleElemBase<FlatTuple<T...>, I>::value; | ||||
} | ||||
template <size_t I> | ||||
typename ElemFromList<I, T...>::type& Get() { | ||||
return FlatTupleElemBase<FlatTuple<T...>, I>::value; | ||||
} | ||||
template <typename F> | ||||
auto Apply(F&& f) -> decltype(std::forward<F>(f)(this->Get<Idx>()...)) { | ||||
return std::forward<F>(f)(Get<Idx>()...); | ||||
} | ||||
template <typename F> | ||||
auto Apply(F&& f) const -> decltype(std::forward<F>(f)(this->Get<Idx>()...)) { | ||||
return std::forward<F>(f)(Get<Idx>()...); | ||||
} | ||||
}; | }; | |||
// Analog to std::tuple but with different tradeoffs. | // Analog to std::tuple but with different tradeoffs. | |||
// This class minimizes the template instantiation depth, thus allowing more | // This class minimizes the template instantiation depth, thus allowing more | |||
// elements that std::tuple would. std::tuple has been seen to require an | // elements than std::tuple would. std::tuple has been seen to require an | |||
// instantiation depth of more than 10x the number of elements in some | // instantiation depth of more than 10x the number of elements in some | |||
// implementations. | // implementations. | |||
// FlatTuple and ElemFromList are not recursive and have a fixed depth | // FlatTuple and ElemFromList are not recursive and have a fixed depth | |||
// regardless of T... | // regardless of T... | |||
// MakeIndexSequence, on the other hand, it is recursive but with an | // MakeIndexSequence, on the other hand, it is recursive but with an | |||
// instantiation depth of O(ln(N)). | // instantiation depth of O(ln(N)). | |||
template <typename... T> | template <typename... T> | |||
class FlatTuple | class FlatTuple | |||
: private FlatTupleBase<FlatTuple<T...>, | : private FlatTupleBase<FlatTuple<T...>, | |||
typename MakeIndexSequence<sizeof...(T)>::type> { | typename MakeIndexSequence<sizeof...(T)>::type> { | |||
using Indices = typename FlatTuple::FlatTupleBase::Indices; | using Indices = typename FlatTupleBase< | |||
FlatTuple<T...>, typename MakeIndexSequence<sizeof...(T)>::type>::Indices; | ||||
public: | public: | |||
FlatTuple() = default; | FlatTuple() = default; | |||
explicit FlatTuple(T... t) : FlatTuple::FlatTupleBase(std::move(t)...) {} | template <typename... Args> | |||
explicit FlatTuple(FlatTupleConstructTag tag, Args&&... args) | ||||
template <size_t I> | : FlatTuple::FlatTupleBase(tag, std::forward<Args>(args)...) {} | |||
const typename ElemFromList<I, Indices, T...>::type& Get() const { | ||||
return static_cast<const FlatTupleElemBase<FlatTuple, I>*>(this)->value; | ||||
} | ||||
template <size_t I> | using FlatTuple::FlatTupleBase::Apply; | |||
typename ElemFromList<I, Indices, T...>::type& Get() { | using FlatTuple::FlatTupleBase::Get; | |||
return static_cast<FlatTupleElemBase<FlatTuple, I>*>(this)->value; | ||||
} | ||||
}; | }; | |||
// Utility functions to be called with static_assert to induce deprecation | // Utility functions to be called with static_assert to induce deprecation | |||
// warnings. | // warnings. | |||
GTEST_INTERNAL_DEPRECATED( | GTEST_INTERNAL_DEPRECATED( | |||
"INSTANTIATE_TEST_CASE_P is deprecated, please use " | "INSTANTIATE_TEST_CASE_P is deprecated, please use " | |||
"INSTANTIATE_TEST_SUITE_P") | "INSTANTIATE_TEST_SUITE_P") | |||
constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; } | constexpr bool InstantiateTestCase_P_IsDeprecated() { return true; } | |||
GTEST_INTERNAL_DEPRECATED( | GTEST_INTERNAL_DEPRECATED( | |||
skipping to change at line 1235 | skipping to change at line 1322 | |||
constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; } | constexpr bool RegisterTypedTestCase_P_IsDeprecated() { return true; } | |||
GTEST_INTERNAL_DEPRECATED( | GTEST_INTERNAL_DEPRECATED( | |||
"INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use " | "INSTANTIATE_TYPED_TEST_CASE_P is deprecated, please use " | |||
"INSTANTIATE_TYPED_TEST_SUITE_P") | "INSTANTIATE_TYPED_TEST_SUITE_P") | |||
constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } | constexpr bool InstantiateTypedTestCase_P_IsDeprecated() { return true; } | |||
} // namespace internal | } // namespace internal | |||
} // namespace testing | } // namespace testing | |||
namespace std { | ||||
// Some standard library implementations use `struct tuple_size` and some use | ||||
// `class tuple_size`. Clang warns about the mismatch. | ||||
// https://reviews.llvm.org/D55466 | ||||
#ifdef __clang__ | ||||
#pragma clang diagnostic push | ||||
#pragma clang diagnostic ignored "-Wmismatched-tags" | ||||
#endif | ||||
template <typename... Ts> | ||||
struct tuple_size<testing::internal::FlatTuple<Ts...>> | ||||
: std::integral_constant<size_t, sizeof...(Ts)> {}; | ||||
#ifdef __clang__ | ||||
#pragma clang diagnostic pop | ||||
#endif | ||||
} // namespace std | ||||
#define GTEST_MESSAGE_AT_(file, line, message, result_type) \ | #define GTEST_MESSAGE_AT_(file, line, message, result_type) \ | |||
::testing::internal::AssertHelper(result_type, file, line, message) \ | ::testing::internal::AssertHelper(result_type, file, line, message) \ | |||
= ::testing::Message() | = ::testing::Message() | |||
#define GTEST_MESSAGE_(message, result_type) \ | #define GTEST_MESSAGE_(message, result_type) \ | |||
GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) | GTEST_MESSAGE_AT_(__FILE__, __LINE__, message, result_type) | |||
#define GTEST_FATAL_FAILURE_(message) \ | #define GTEST_FATAL_FAILURE_(message) \ | |||
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) | return GTEST_MESSAGE_(message, ::testing::TestPartResult::kFatalFailure) | |||
skipping to change at line 1257 | skipping to change at line 1360 | |||
#define GTEST_SUCCESS_(message) \ | #define GTEST_SUCCESS_(message) \ | |||
GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) | GTEST_MESSAGE_(message, ::testing::TestPartResult::kSuccess) | |||
#define GTEST_SKIP_(message) \ | #define GTEST_SKIP_(message) \ | |||
return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip) | return GTEST_MESSAGE_(message, ::testing::TestPartResult::kSkip) | |||
// Suppress MSVC warning 4072 (unreachable code) for the code following | // Suppress MSVC warning 4072 (unreachable code) for the code following | |||
// statement if it returns or throws (or doesn't return or throw in some | // statement if it returns or throws (or doesn't return or throw in some | |||
// situations). | // situations). | |||
// NOTE: The "else" is important to keep this expansion to prevent a top-level | ||||
// "else" from attaching to our "if". | ||||
#define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ | #define GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement) \ | |||
if (::testing::internal::AlwaysTrue()) { statement; } | if (::testing::internal::AlwaysTrue()) { \ | |||
statement; \ | ||||
} else /* NOLINT */ \ | ||||
static_assert(true, "") // User must have a semicolon after expansion. | ||||
#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ | #if GTEST_HAS_EXCEPTIONS | |||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | ||||
if (::testing::internal::ConstCharPtr gtest_msg = "") { \ | namespace testing { | |||
bool gtest_caught_expected = false; \ | namespace internal { | |||
try { \ | ||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ | class NeverThrown { | |||
} \ | public: | |||
catch (expected_exception const&) { \ | const char* what() const noexcept { | |||
gtest_caught_expected = true; \ | return "this exception should never be thrown"; | |||
} \ | } | |||
catch (...) { \ | }; | |||
gtest_msg.value = \ | ||||
"Expected: " #statement " throws an exception of type " \ | } // namespace internal | |||
#expected_exception ".\n Actual: it throws a different type."; \ | } // namespace testing | |||
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | ||||
} \ | #if GTEST_HAS_RTTI | |||
if (!gtest_caught_expected) { \ | ||||
gtest_msg.value = \ | #define GTEST_EXCEPTION_TYPE_(e) ::testing::internal::GetTypeName(typeid(e)) | |||
"Expected: " #statement " throws an exception of type " \ | ||||
#expected_exception ".\n Actual: it throws nothing."; \ | #else // GTEST_HAS_RTTI | |||
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | ||||
} \ | #define GTEST_EXCEPTION_TYPE_(e) \ | |||
} else \ | std::string { "an std::exception-derived error" } | |||
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__): \ | ||||
fail(gtest_msg.value) | #endif // GTEST_HAS_RTTI | |||
#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) \ | ||||
catch (typename std::conditional< \ | ||||
std::is_same<typename std::remove_cv<typename std::remove_reference< \ | ||||
expected_exception>::type>::type, \ | ||||
std::exception>::value, \ | ||||
const ::testing::internal::NeverThrown&, const std::exception&>::type \ | ||||
e) { \ | ||||
gtest_msg.value = "Expected: " #statement \ | ||||
" throws an exception of type " #expected_exception \ | ||||
".\n Actual: it throws "; \ | ||||
gtest_msg.value += GTEST_EXCEPTION_TYPE_(e); \ | ||||
gtest_msg.value += " with description \""; \ | ||||
gtest_msg.value += e.what(); \ | ||||
gtest_msg.value += "\"."; \ | ||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | ||||
} | ||||
#else // GTEST_HAS_EXCEPTIONS | ||||
#define GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) | ||||
#endif // GTEST_HAS_EXCEPTIONS | ||||
#define GTEST_TEST_THROW_(statement, expected_exception, fail) \ | ||||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | ||||
if (::testing::internal::TrueWithString gtest_msg{}) { \ | ||||
bool gtest_caught_expected = false; \ | ||||
try { \ | ||||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ | ||||
} catch (expected_exception const&) { \ | ||||
gtest_caught_expected = true; \ | ||||
} \ | ||||
GTEST_TEST_THROW_CATCH_STD_EXCEPTION_(statement, expected_exception) \ | ||||
catch (...) { \ | ||||
gtest_msg.value = "Expected: " #statement \ | ||||
" throws an exception of type " #expected_exception \ | ||||
".\n Actual: it throws a different type."; \ | ||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | ||||
} \ | ||||
if (!gtest_caught_expected) { \ | ||||
gtest_msg.value = "Expected: " #statement \ | ||||
" throws an exception of type " #expected_exception \ | ||||
".\n Actual: it throws nothing."; \ | ||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__); \ | ||||
} \ | ||||
} else /*NOLINT*/ \ | ||||
GTEST_CONCAT_TOKEN_(gtest_label_testthrow_, __LINE__) \ | ||||
: fail(gtest_msg.value.c_str()) | ||||
#if GTEST_HAS_EXCEPTIONS | ||||
#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ | ||||
catch (std::exception const& e) { \ | ||||
gtest_msg.value = "it throws "; \ | ||||
gtest_msg.value += GTEST_EXCEPTION_TYPE_(e); \ | ||||
gtest_msg.value += " with description \""; \ | ||||
gtest_msg.value += e.what(); \ | ||||
gtest_msg.value += "\"."; \ | ||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ | ||||
} | ||||
#else // GTEST_HAS_EXCEPTIONS | ||||
#define GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() | ||||
#endif // GTEST_HAS_EXCEPTIONS | ||||
#define GTEST_TEST_NO_THROW_(statement, fail) \ | #define GTEST_TEST_NO_THROW_(statement, fail) \ | |||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | |||
if (::testing::internal::AlwaysTrue()) { \ | if (::testing::internal::TrueWithString gtest_msg{}) { \ | |||
try { \ | try { \ | |||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ | GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ | |||
} \ | } \ | |||
GTEST_TEST_NO_THROW_CATCH_STD_EXCEPTION_() \ | ||||
catch (...) { \ | catch (...) { \ | |||
gtest_msg.value = "it throws."; \ | ||||
goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ | goto GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__); \ | |||
} \ | } \ | |||
} else \ | } else \ | |||
GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ | GTEST_CONCAT_TOKEN_(gtest_label_testnothrow_, __LINE__): \ | |||
fail("Expected: " #statement " doesn't throw an exception.\n" \ | fail(("Expected: " #statement " doesn't throw an exception.\n" \ | |||
" Actual: it throws.") | " Actual: " + gtest_msg.value).c_str()) | |||
#define GTEST_TEST_ANY_THROW_(statement, fail) \ | #define GTEST_TEST_ANY_THROW_(statement, fail) \ | |||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | |||
if (::testing::internal::AlwaysTrue()) { \ | if (::testing::internal::AlwaysTrue()) { \ | |||
bool gtest_caught_any = false; \ | bool gtest_caught_any = false; \ | |||
try { \ | try { \ | |||
GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ | GTEST_SUPPRESS_UNREACHABLE_CODE_WARNING_BELOW_(statement); \ | |||
} \ | } \ | |||
catch (...) { \ | catch (...) { \ | |||
gtest_caught_any = true; \ | gtest_caught_any = true; \ | |||
skipping to change at line 1320 | skipping to change at line 1497 | |||
if (!gtest_caught_any) { \ | if (!gtest_caught_any) { \ | |||
goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ | goto GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__); \ | |||
} \ | } \ | |||
} else \ | } else \ | |||
GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ | GTEST_CONCAT_TOKEN_(gtest_label_testanythrow_, __LINE__): \ | |||
fail("Expected: " #statement " throws an exception.\n" \ | fail("Expected: " #statement " throws an exception.\n" \ | |||
" Actual: it doesn't.") | " Actual: it doesn't.") | |||
// Implements Boolean test assertions such as EXPECT_TRUE. expression can be | // Implements Boolean test assertions such as EXPECT_TRUE. expression can be | |||
// either a boolean expression or an AssertionResult. text is a textual | // either a boolean expression or an AssertionResult. text is a textual | |||
// represenation of expression as it was passed into the EXPECT_TRUE. | // representation of expression as it was passed into the EXPECT_TRUE. | |||
#define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ | #define GTEST_TEST_BOOLEAN_(expression, text, actual, expected, fail) \ | |||
GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | GTEST_AMBIGUOUS_ELSE_BLOCKER_ \ | |||
if (const ::testing::AssertionResult gtest_ar_ = \ | if (const ::testing::AssertionResult gtest_ar_ = \ | |||
::testing::AssertionResult(expression)) \ | ::testing::AssertionResult(expression)) \ | |||
; \ | ; \ | |||
else \ | else \ | |||
fail(::testing::internal::GetBoolAssertionFailureMessage(\ | fail(::testing::internal::GetBoolAssertionFailureMessage(\ | |||
gtest_ar_, text, #actual, #expected).c_str()) | gtest_ar_, text, #actual, #expected).c_str()) | |||
#define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ | #define GTEST_TEST_NO_FATAL_FAILURE_(statement, fail) \ | |||
skipping to change at line 1357 | skipping to change at line 1534 | |||
// Helper macro for defining tests. | // Helper macro for defining tests. | |||
#define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \ | #define GTEST_TEST_(test_suite_name, test_name, parent_class, parent_id) \ | |||
static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \ | static_assert(sizeof(GTEST_STRINGIFY_(test_suite_name)) > 1, \ | |||
"test_suite_name must not be empty"); \ | "test_suite_name must not be empty"); \ | |||
static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \ | static_assert(sizeof(GTEST_STRINGIFY_(test_name)) > 1, \ | |||
"test_name must not be empty"); \ | "test_name must not be empty"); \ | |||
class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ | class GTEST_TEST_CLASS_NAME_(test_suite_name, test_name) \ | |||
: public parent_class { \ | : public parent_class { \ | |||
public: \ | public: \ | |||
GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() {} \ | GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() = default; \ | |||
~GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)() override = default; \ | ||||
GTEST_DISALLOW_COPY_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ | ||||
test_name)); \ | ||||
GTEST_DISALLOW_MOVE_AND_ASSIGN_(GTEST_TEST_CLASS_NAME_(test_suite_name, \ | ||||
test_name)); \ | ||||
\ | \ | |||
private: \ | private: \ | |||
virtual void TestBody(); \ | void TestBody() override; \ | |||
static ::testing::TestInfo* const test_info_ GTEST_ATTRIBUTE_UNUSED_; \ | 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, \ | ::testing::TestInfo* const GTEST_TEST_CLASS_NAME_(test_suite_name, \ | |||
test_name)::test_info_ = \ | test_name)::test_info_ = \ | |||
::testing::internal::MakeAndRegisterTestInfo( \ | ::testing::internal::MakeAndRegisterTestInfo( \ | |||
#test_suite_name, #test_name, nullptr, nullptr, \ | #test_suite_name, #test_name, nullptr, nullptr, \ | |||
::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \ | ::testing::internal::CodeLocation(__FILE__, __LINE__), (parent_id), \ | |||
::testing::internal::SuiteApiResolver< \ | ::testing::internal::SuiteApiResolver< \ | |||
parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \ | parent_class>::GetSetUpCaseOrSuite(__FILE__, __LINE__), \ | |||
::testing::internal::SuiteApiResolver< \ | ::testing::internal::SuiteApiResolver< \ | |||
parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \ | parent_class>::GetTearDownCaseOrSuite(__FILE__, __LINE__), \ | |||
new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \ | new ::testing::internal::TestFactoryImpl<GTEST_TEST_CLASS_NAME_( \ | |||
test_suite_name, test_name)>); \ | test_suite_name, test_name)>); \ | |||
void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() | void GTEST_TEST_CLASS_NAME_(test_suite_name, test_name)::TestBody() | |||
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ | #endif // GOOGLETEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ | |||
End of changes. 52 change blocks. | ||||
103 lines changed or deleted | 283 lines changed or added |