Externals: Update gtest to r733

This commit is contained in:
Jeffrey Pfau 2015-07-20 22:53:28 -07:00
parent 3d6ee7313d
commit 67d0e81cf3
24 changed files with 2250 additions and 638 deletions

28
Externals/gtest/LICENSE vendored Normal file
View File

@ -0,0 +1,28 @@
Copyright 2008, Google Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
* Neither the name of Google Inc. nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -1387,14 +1387,17 @@ internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
static int AddToRegistry() { \ static int AddToRegistry() { \
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
GetTestCasePatternHolder<test_case_name>(\ GetTestCasePatternHolder<test_case_name>(\
#test_case_name, __FILE__, __LINE__)->AddTestPattern(\ #test_case_name, \
::testing::internal::CodeLocation(\
__FILE__, __LINE__))->AddTestPattern(\
#test_case_name, \ #test_case_name, \
#test_name, \ #test_name, \
new ::testing::internal::TestMetaFactory< \ new ::testing::internal::TestMetaFactory< \
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ GTEST_TEST_CLASS_NAME_(\
test_case_name, test_name)>()); \
return 0; \ return 0; \
} \ } \
static int gtest_registering_dummy_; \ static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \
GTEST_DISALLOW_COPY_AND_ASSIGN_(\ GTEST_DISALLOW_COPY_AND_ASSIGN_(\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
}; \ }; \
@ -1406,10 +1409,12 @@ internal::CartesianProductHolder10<Generator1, Generator2, Generator3,
# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ # define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
::testing::internal::ParamGenerator<test_case_name::ParamType> \ ::testing::internal::ParamGenerator<test_case_name::ParamType> \
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
int gtest_##prefix##test_case_name##_dummy_ = \ int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
GetTestCasePatternHolder<test_case_name>(\ GetTestCasePatternHolder<test_case_name>(\
#test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\ #test_case_name, \
::testing::internal::CodeLocation(\
__FILE__, __LINE__))->AddTestCaseInstantiation(\
#prefix, \ #prefix, \
&gtest_##prefix##test_case_name##_EvalGenerator_, \ &gtest_##prefix##test_case_name##_EvalGenerator_, \
__FILE__, __LINE__) __FILE__, __LINE__)

View File

@ -453,14 +453,17 @@ internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
static int AddToRegistry() { \ static int AddToRegistry() { \
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
GetTestCasePatternHolder<test_case_name>(\ GetTestCasePatternHolder<test_case_name>(\
#test_case_name, __FILE__, __LINE__)->AddTestPattern(\ #test_case_name, \
::testing::internal::CodeLocation(\
__FILE__, __LINE__))->AddTestPattern(\
#test_case_name, \ #test_case_name, \
#test_name, \ #test_name, \
new ::testing::internal::TestMetaFactory< \ new ::testing::internal::TestMetaFactory< \
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)>()); \ GTEST_TEST_CLASS_NAME_(\
test_case_name, test_name)>()); \
return 0; \ return 0; \
} \ } \
static int gtest_registering_dummy_; \ static int gtest_registering_dummy_ GTEST_ATTRIBUTE_UNUSED_; \
GTEST_DISALLOW_COPY_AND_ASSIGN_(\ GTEST_DISALLOW_COPY_AND_ASSIGN_(\
GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)); \
}; \ }; \
@ -472,10 +475,12 @@ internal::CartesianProductHolder$i<$for j, [[Generator$j]]> Combine(
# define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \ # define INSTANTIATE_TEST_CASE_P(prefix, test_case_name, generator) \
::testing::internal::ParamGenerator<test_case_name::ParamType> \ ::testing::internal::ParamGenerator<test_case_name::ParamType> \
gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \ gtest_##prefix##test_case_name##_EvalGenerator_() { return generator; } \
int gtest_##prefix##test_case_name##_dummy_ = \ int gtest_##prefix##test_case_name##_dummy_ GTEST_ATTRIBUTE_UNUSED_ = \
::testing::UnitTest::GetInstance()->parameterized_test_registry(). \ ::testing::UnitTest::GetInstance()->parameterized_test_registry(). \
GetTestCasePatternHolder<test_case_name>(\ GetTestCasePatternHolder<test_case_name>(\
#test_case_name, __FILE__, __LINE__)->AddTestCaseInstantiation(\ #test_case_name, \
::testing::internal::CodeLocation(\
__FILE__, __LINE__))->AddTestCaseInstantiation(\
#prefix, \ #prefix, \
&gtest_##prefix##test_case_name##_EvalGenerator_, \ &gtest_##prefix##test_case_name##_EvalGenerator_, \
__FILE__, __LINE__) __FILE__, __LINE__)

View File

@ -593,10 +593,7 @@ class UniversalPrinter {
public: public:
// MSVC warns about adding const to a function type, so we want to // MSVC warns about adding const to a function type, so we want to
// disable the warning. // disable the warning.
#ifdef _MSC_VER GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4180) // Temporarily disables warning 4180.
#endif // _MSC_VER
// Note: we deliberately don't call this PrintTo(), as that name // Note: we deliberately don't call this PrintTo(), as that name
// conflicts with ::testing::internal::PrintTo in the body of the // conflicts with ::testing::internal::PrintTo in the body of the
@ -613,9 +610,7 @@ class UniversalPrinter {
PrintTo(value, os); PrintTo(value, os);
} }
#ifdef _MSC_VER GTEST_DISABLE_MSC_WARNINGS_POP_()
# pragma warning(pop) // Restores the warning state.
#endif // _MSC_VER
}; };
// UniversalPrintArray(begin, len, os) prints an array of 'len' // UniversalPrintArray(begin, len, os) prints an array of 'len'
@ -667,10 +662,7 @@ class UniversalPrinter<T&> {
public: public:
// MSVC warns about adding const to a function type, so we want to // MSVC warns about adding const to a function type, so we want to
// disable the warning. // disable the warning.
#ifdef _MSC_VER GTEST_DISABLE_MSC_WARNINGS_PUSH_(4180)
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4180) // Temporarily disables warning 4180.
#endif // _MSC_VER
static void Print(const T& value, ::std::ostream* os) { static void Print(const T& value, ::std::ostream* os) {
// Prints the address of the value. We use reinterpret_cast here // Prints the address of the value. We use reinterpret_cast here
@ -681,9 +673,7 @@ class UniversalPrinter<T&> {
UniversalPrint(value, os); UniversalPrint(value, os);
} }
#ifdef _MSC_VER GTEST_DISABLE_MSC_WARNINGS_POP_()
# pragma warning(pop) // Restores the warning state.
#endif // _MSC_VER
}; };
// Prints a value tersely: for a reference type, the referenced value // Prints a value tersely: for a reference type, the referenced value
@ -835,9 +825,9 @@ struct TuplePrefixPrinter {
template <typename Tuple> template <typename Tuple>
static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) { static void PrintPrefixTo(const Tuple& t, ::std::ostream* os) {
TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os); TuplePrefixPrinter<N - 1>::PrintPrefixTo(t, os);
GTEST_INTENTIONAL_CONST_COND_PUSH_ GTEST_INTENTIONAL_CONST_COND_PUSH_()
if (N > 1) { if (N > 1) {
GTEST_INTENTIONAL_CONST_COND_POP_ GTEST_INTENTIONAL_CONST_COND_POP_()
*os << ", "; *os << ", ";
} }
UniversalPrinter< UniversalPrinter<
@ -898,4 +888,9 @@ template <typename T>
} // namespace testing } // namespace testing
// Include any custom printer added by the local installation.
// We must include this header at the end to make sure it can use the
// declarations from this file.
#include "gtest/internal/custom/gtest-printers.h"
#endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_ #endif // GTEST_INCLUDE_GTEST_GTEST_PRINTERS_H_

View File

@ -181,7 +181,8 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
::testing::internal::TemplateSel< \ ::testing::internal::TemplateSel< \
GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \ GTEST_TEST_CLASS_NAME_(CaseName, TestName)>, \
GTEST_TYPE_PARAMS_(CaseName)>::Register(\ GTEST_TYPE_PARAMS_(CaseName)>::Register(\
"", #CaseName, #TestName, 0); \ "", ::testing::internal::CodeLocation(__FILE__, __LINE__), \
#CaseName, #TestName, 0); \
template <typename gtest_TypeParam_> \ template <typename gtest_TypeParam_> \
void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody() void GTEST_TEST_CLASS_NAME_(CaseName, TestName)<gtest_TypeParam_>::TestBody()
@ -252,7 +253,10 @@ INSTANTIATE_TYPED_TEST_CASE_P(My, FooTest, MyTypes);
::testing::internal::TypeParameterizedTestCase<CaseName, \ ::testing::internal::TypeParameterizedTestCase<CaseName, \
GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \ GTEST_CASE_NAMESPACE_(CaseName)::gtest_AllTests_, \
::testing::internal::TypeList< Types >::type>::Register(\ ::testing::internal::TypeList< Types >::type>::Register(\
#Prefix, #CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName)) #Prefix, \
::testing::internal::CodeLocation(__FILE__, __LINE__), \
&GTEST_TYPED_TEST_CASE_P_STATE_(CaseName), \
#CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
#endif // GTEST_HAS_TYPED_TEST_P #endif // GTEST_HAS_TYPED_TEST_P

View File

@ -70,14 +70,14 @@
// class ::string, which has the same interface as ::std::string, but // class ::string, which has the same interface as ::std::string, but
// has a different implementation. // has a different implementation.
// //
// The user can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that // You can define GTEST_HAS_GLOBAL_STRING to 1 to indicate that
// ::string is available AND is a distinct type to ::std::string, or // ::string is available AND is a distinct type to ::std::string, or
// define it to 0 to indicate otherwise. // define it to 0 to indicate otherwise.
// //
// If the user's ::std::string and ::string are the same class due to // If ::std::string and ::string are the same class on your platform
// aliasing, he should define GTEST_HAS_GLOBAL_STRING to 0. // due to aliasing, you should define GTEST_HAS_GLOBAL_STRING to 0.
// //
// If the user doesn't define GTEST_HAS_GLOBAL_STRING, it is defined // If you do not define GTEST_HAS_GLOBAL_STRING, it is defined
// heuristically. // heuristically.
namespace testing { namespace testing {
@ -258,8 +258,31 @@ class GTEST_API_ AssertionResult {
// Copy constructor. // Copy constructor.
// Used in EXPECT_TRUE/FALSE(assertion_result). // Used in EXPECT_TRUE/FALSE(assertion_result).
AssertionResult(const AssertionResult& other); AssertionResult(const AssertionResult& other);
GTEST_DISABLE_MSC_WARNINGS_PUSH_(4800 /* forcing value to bool */)
// Used in the EXPECT_TRUE/FALSE(bool_expression). // Used in the EXPECT_TRUE/FALSE(bool_expression).
explicit AssertionResult(bool success) : success_(success) {} //
// T must be contextually convertible to bool.
//
// The second parameter prevents this overload from being considered if
// the argument is implicitly convertible to AssertionResult. In that case
// we want AssertionResult's copy constructor to be used.
template <typename T>
explicit AssertionResult(
const T& success,
typename internal::EnableIf<
!internal::ImplicitlyConvertible<T, AssertionResult>::value>::type*
/*enabler*/ = NULL)
: success_(success) {}
GTEST_DISABLE_MSC_WARNINGS_POP_()
// Assignment operator.
AssertionResult& operator=(AssertionResult other) {
swap(other);
return *this;
}
// Returns true iff the assertion succeeded. // Returns true iff the assertion succeeded.
operator bool() const { return success_; } // NOLINT operator bool() const { return success_; } // NOLINT
@ -300,6 +323,9 @@ class GTEST_API_ AssertionResult {
message_->append(a_message.GetString().c_str()); message_->append(a_message.GetString().c_str());
} }
// Swap the contents of this AssertionResult with other.
void swap(AssertionResult& other);
// Stores result of the assertion predicate. // Stores result of the assertion predicate.
bool success_; bool success_;
// Stores the message describing the condition in case the expectation // Stores the message describing the condition in case the expectation
@ -307,8 +333,6 @@ class GTEST_API_ AssertionResult {
// Referenced via a pointer to avoid taking too much stack frame space // Referenced via a pointer to avoid taking too much stack frame space
// with test assertions. // with test assertions.
internal::scoped_ptr< ::std::string> message_; internal::scoped_ptr< ::std::string> message_;
GTEST_DISALLOW_ASSIGN_(AssertionResult);
}; };
// Makes a successful assertion result. // Makes a successful assertion result.
@ -335,8 +359,8 @@ GTEST_API_ AssertionResult AssertionFailure(const Message& msg);
// //
// class FooTest : public testing::Test { // class FooTest : public testing::Test {
// protected: // protected:
// virtual void SetUp() { ... } // void SetUp() override { ... }
// virtual void TearDown() { ... } // void TearDown() override { ... }
// ... // ...
// }; // };
// //
@ -428,20 +452,19 @@ class GTEST_API_ Test {
// internal method to avoid clashing with names used in user TESTs. // internal method to avoid clashing with names used in user TESTs.
void DeleteSelf_() { delete this; } void DeleteSelf_() { delete this; }
// Uses a GTestFlagSaver to save and restore all Google Test flags. const internal::scoped_ptr< GTEST_FLAG_SAVER_ > gtest_flag_saver_;
const internal::GTestFlagSaver* const gtest_flag_saver_;
// Often a user mis-spells SetUp() as Setup() and spends a long time // Often a user misspells SetUp() as Setup() and spends a long time
// wondering why it is never called by Google Test. The declaration of // wondering why it is never called by Google Test. The declaration of
// the following method is solely for catching such an error at // the following method is solely for catching such an error at
// compile time: // compile time:
// //
// - The return type is deliberately chosen to be not void, so it // - The return type is deliberately chosen to be not void, so it
// will be a conflict if a user declares void Setup() in his test // will be a conflict if void Setup() is declared in the user's
// fixture. // test fixture.
// //
// - This method is private, so it will be another compiler error // - This method is private, so it will be another compiler error
// if a user calls it from his test fixture. // if the method is called from the user's test fixture.
// //
// DO NOT OVERRIDE THIS FUNCTION. // DO NOT OVERRIDE THIS FUNCTION.
// //
@ -646,6 +669,12 @@ class GTEST_API_ TestInfo {
return NULL; return NULL;
} }
// Returns the file name where this test is defined.
const char* file() const { return location_.file.c_str(); }
// Returns the line where this test is defined.
int line() const { return location_.line; }
// Returns true if this test should run, that is if the test is not // Returns true if this test should run, that is if the test is not
// disabled (or it is disabled but the also_run_disabled_tests flag has // disabled (or it is disabled but the also_run_disabled_tests flag has
// been specified) and its full name matches the user-specified filter. // been specified) and its full name matches the user-specified filter.
@ -688,6 +717,7 @@ class GTEST_API_ TestInfo {
const char* name, const char* name,
const char* type_param, const char* type_param,
const char* value_param, const char* value_param,
internal::CodeLocation code_location,
internal::TypeId fixture_class_id, internal::TypeId fixture_class_id,
Test::SetUpTestCaseFunc set_up_tc, Test::SetUpTestCaseFunc set_up_tc,
Test::TearDownTestCaseFunc tear_down_tc, Test::TearDownTestCaseFunc tear_down_tc,
@ -699,6 +729,7 @@ class GTEST_API_ TestInfo {
const std::string& name, const std::string& name,
const char* a_type_param, // NULL if not a type-parameterized test const char* a_type_param, // NULL if not a type-parameterized test
const char* a_value_param, // NULL if not a value-parameterized test const char* a_value_param, // NULL if not a value-parameterized test
internal::CodeLocation a_code_location,
internal::TypeId fixture_class_id, internal::TypeId fixture_class_id,
internal::TestFactoryBase* factory); internal::TestFactoryBase* factory);
@ -725,6 +756,7 @@ class GTEST_API_ TestInfo {
// Text representation of the value parameter, or NULL if this is not a // Text representation of the value parameter, or NULL if this is not a
// value-parameterized test. // value-parameterized test.
const internal::scoped_ptr<const ::std::string> value_param_; const internal::scoped_ptr<const ::std::string> value_param_;
internal::CodeLocation location_;
const internal::TypeId fixture_class_id_; // ID of the test fixture class const internal::TypeId fixture_class_id_; // ID of the test fixture class
bool should_run_; // True iff this test should run bool should_run_; // True iff this test should run
bool is_disabled_; // True iff this test is disabled bool is_disabled_; // True iff this test is disabled
@ -924,7 +956,7 @@ class GTEST_API_ TestCase {
}; };
// An Environment object is capable of setting up and tearing down an // An Environment object is capable of setting up and tearing down an
// environment. The user should subclass this to define his own // environment. You should subclass this to define your own
// environment(s). // environment(s).
// //
// An Environment object does the set-up and tear-down in virtual // An Environment object does the set-up and tear-down in virtual
@ -1433,31 +1465,34 @@ std::string FormatForComparisonFailureMessage(
return FormatForComparison<T1, T2>::Format(value); return FormatForComparison<T1, T2>::Format(value);
} }
// Separate the error generating code from the code path to reduce the stack
// frame size of CmpHelperEQ. This helps reduce the overhead of some sanitizers
// when calling EXPECT_* in a tight loop.
template <typename T1, typename T2>
AssertionResult CmpHelperEQFailure(const char* expected_expression,
const char* actual_expression,
const T1& expected, const T2& actual) {
return EqFailure(expected_expression,
actual_expression,
FormatForComparisonFailureMessage(expected, actual),
FormatForComparisonFailureMessage(actual, expected),
false);
}
// The helper function for {ASSERT|EXPECT}_EQ. // The helper function for {ASSERT|EXPECT}_EQ.
template <typename T1, typename T2> template <typename T1, typename T2>
AssertionResult CmpHelperEQ(const char* expected_expression, AssertionResult CmpHelperEQ(const char* expected_expression,
const char* actual_expression, const char* actual_expression,
const T1& expected, const T1& expected,
const T2& actual) { const T2& actual) {
#ifdef _MSC_VER GTEST_DISABLE_MSC_WARNINGS_PUSH_(4389 /* signed/unsigned mismatch */)
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4389) // Temporarily disables warning on
// signed/unsigned mismatch.
#endif
if (expected == actual) { if (expected == actual) {
return AssertionSuccess(); return AssertionSuccess();
} }
GTEST_DISABLE_MSC_WARNINGS_POP_()
#ifdef _MSC_VER return CmpHelperEQFailure(expected_expression, actual_expression, expected,
# pragma warning(pop) // Restores the warning state. actual);
#endif
return EqFailure(expected_expression,
actual_expression,
FormatForComparisonFailureMessage(expected, actual),
FormatForComparisonFailureMessage(actual, expected),
false);
} }
// With this overloaded version, we allow anonymous enums to be used // With this overloaded version, we allow anonymous enums to be used
@ -1545,6 +1580,19 @@ class EqHelper<true> {
} }
}; };
// Separate the error generating code from the code path to reduce the stack
// frame size of CmpHelperOP. This helps reduce the overhead of some sanitizers
// when calling EXPECT_OP in a tight loop.
template <typename T1, typename T2>
AssertionResult CmpHelperOpFailure(const char* expr1, const char* expr2,
const T1& val1, const T2& val2,
const char* op) {
return AssertionFailure()
<< "Expected: (" << expr1 << ") " << op << " (" << expr2
<< "), actual: " << FormatForComparisonFailureMessage(val1, val2)
<< " vs " << FormatForComparisonFailureMessage(val2, val1);
}
// A macro for implementing the helper functions needed to implement // A macro for implementing the helper functions needed to implement
// ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste // ASSERT_?? and EXPECT_??. It is here just to avoid copy-and-paste
// of similar code. // of similar code.
@ -1555,6 +1603,7 @@ class EqHelper<true> {
// with gcc 4. // with gcc 4.
// //
// INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM. // INTERNAL IMPLEMENTATION - DO NOT USE IN A USER PROGRAM.
#define GTEST_IMPL_CMP_HELPER_(op_name, op)\ #define GTEST_IMPL_CMP_HELPER_(op_name, op)\
template <typename T1, typename T2>\ template <typename T1, typename T2>\
AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
@ -1562,10 +1611,7 @@ AssertionResult CmpHelper##op_name(const char* expr1, const char* expr2, \
if (val1 op val2) {\ if (val1 op val2) {\
return AssertionSuccess();\ return AssertionSuccess();\
} else {\ } else {\
return AssertionFailure() \ return CmpHelperOpFailure(expr1, expr2, val1, val2, #op);\
<< "Expected: (" << expr1 << ") " #op " (" << expr2\
<< "), actual: " << FormatForComparisonFailureMessage(val1, val2)\
<< " vs " << FormatForComparisonFailureMessage(val2, val1);\
}\ }\
}\ }\
GTEST_API_ AssertionResult CmpHelper##op_name(\ GTEST_API_ AssertionResult CmpHelper##op_name(\
@ -2215,8 +2261,8 @@ bool StaticAssertTypeEq() {
// The convention is to end the test case name with "Test". For // The convention is to end the test case name with "Test". For
// example, a test case for the Foo class can be named FooTest. // example, a test case for the Foo class can be named FooTest.
// //
// The user should put his test code between braces after using this // Test code should appear between braces after an invocation of
// macro. Example: // this macro. Example:
// //
// TEST(FooTest, InitializesCorrectly) { // TEST(FooTest, InitializesCorrectly) {
// Foo foo; // Foo foo;

View File

@ -0,0 +1,69 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Injection point for custom user configurations.
// The following macros can be defined:
//
// Flag related macros:
// GTEST_FLAG(flag_name)
// GTEST_USE_OWN_FLAGFILE_FLAG_ - Define to 0 when the system provides its
// own flagfile flag parsing.
// GTEST_DECLARE_bool_(name)
// GTEST_DECLARE_int32_(name)
// GTEST_DECLARE_string_(name)
// GTEST_DEFINE_bool_(name, default_val, doc)
// GTEST_DEFINE_int32_(name, default_val, doc)
// GTEST_DEFINE_string_(name, default_val, doc)
//
// Test filtering:
// GTEST_TEST_FILTER_ENV_VAR_ - The name of an environment variable that
// will be used if --GTEST_FLAG(test_filter)
// is not provided.
//
// Logging:
// GTEST_LOG_(severity)
// GTEST_CHECK_(condition)
// Functions LogToStderr() and FlushInfoLog() have to be provided too.
//
// Threading:
// GTEST_HAS_NOTIFICATION_ - Enabled if Notification is already provided.
// GTEST_HAS_MUTEX_AND_THREAD_LOCAL_ - Enabled if Mutex and ThreadLocal are
// already provided.
// Must also provide GTEST_DECLARE_STATIC_MUTEX_(mutex) and
// GTEST_DEFINE_STATIC_MUTEX_(mutex)
//
// GTEST_EXCLUSIVE_LOCK_REQUIRED_(locks)
// GTEST_LOCK_EXCLUDED_(locks)
//
// ** Custom implementation starts here **
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PORT_H_

View File

@ -0,0 +1,42 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// This file provides an injection point for custom printers in a local
// installation of gTest.
// It will be included from gtest-printers.h and the overrides in this file
// will be visible to everyone.
// See documentation at gtest/gtest-printers.h for details on how to define a
// custom printer.
//
// ** Custom implementation starts here **
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_PRINTERS_H_

View File

@ -0,0 +1,41 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Injection point for custom user configurations.
// The following macros can be defined:
//
// GTEST_OS_STACK_TRACE_GETTER_ - The name of an implementation of
// OsStackTraceGetterInterface.
//
// ** Custom implementation starts here **
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_
#endif // GTEST_INCLUDE_GTEST_INTERNAL_CUSTOM_GTEST_H_

View File

@ -55,7 +55,10 @@
#include <string.h> #include <string.h>
#include <iomanip> #include <iomanip>
#include <limits> #include <limits>
#include <map>
#include <set> #include <set>
#include <string>
#include <vector>
#include "gtest/gtest-message.h" #include "gtest/gtest-message.h"
#include "gtest/internal/gtest-string.h" #include "gtest/internal/gtest-string.h"
@ -171,6 +174,36 @@ class GTEST_API_ ScopedTrace {
// c'tor and d'tor. Therefore it doesn't // c'tor and d'tor. Therefore it doesn't
// need to be used otherwise. // need to be used otherwise.
namespace edit_distance {
// Returns the optimal edits to go from 'left' to 'right'.
// All edits cost the same, with replace having lower priority than
// add/remove.
// Simple implementation of the WagnerFischer algorithm.
// See http://en.wikipedia.org/wiki/Wagner-Fischer_algorithm
enum EditType { kMatch, kAdd, kRemove, kReplace };
GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
const std::vector<size_t>& left, const std::vector<size_t>& right);
// Same as above, but the input is represented as strings.
GTEST_API_ std::vector<EditType> CalculateOptimalEdits(
const std::vector<std::string>& left,
const std::vector<std::string>& right);
// Create a diff of the input strings in Unified diff format.
GTEST_API_ std::string CreateUnifiedDiff(const std::vector<std::string>& left,
const std::vector<std::string>& right,
size_t context = 2);
} // namespace edit_distance
// Calculate the diff between 'left' and 'right' and return it in unified diff
// format.
// If not null, stores in 'total_line_count' the total number of lines found
// in left + right.
GTEST_API_ std::string DiffStrings(const std::string& left,
const std::string& right,
size_t* total_line_count);
// Constructs and returns the message for an equality assertion // Constructs and returns the message for an equality assertion
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. // (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
// //
@ -471,6 +504,13 @@ GTEST_API_ AssertionResult IsHRESULTFailure(const char* expr,
typedef void (*SetUpTestCaseFunc)(); typedef void (*SetUpTestCaseFunc)();
typedef void (*TearDownTestCaseFunc)(); typedef void (*TearDownTestCaseFunc)();
struct CodeLocation {
CodeLocation(const string& a_file, int a_line) : file(a_file), line(a_line) {}
string file;
int line;
};
// 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.
// //
@ -482,6 +522,7 @@ typedef void (*TearDownTestCaseFunc)();
// 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
// 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 case // 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 // tear_down_tc: pointer to the function that tears down the test case
@ -493,6 +534,7 @@ GTEST_API_ TestInfo* MakeAndRegisterTestInfo(
const char* name, const char* name,
const char* type_param, const char* type_param,
const char* value_param, const char* value_param,
CodeLocation code_location,
TypeId fixture_class_id, TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc, SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc, TearDownTestCaseFunc tear_down_tc,
@ -522,10 +564,21 @@ class GTEST_API_ TypedTestCasePState {
fflush(stderr); fflush(stderr);
posix::Abort(); posix::Abort();
} }
defined_test_names_.insert(test_name); registered_tests_.insert(
::std::make_pair(test_name, CodeLocation(file, line)));
return true; return true;
} }
bool TestExists(const std::string& test_name) const {
return registered_tests_.count(test_name) > 0;
}
const CodeLocation& GetCodeLocation(const std::string& test_name) const {
RegisteredTestsMap::const_iterator it = registered_tests_.find(test_name);
GTEST_CHECK_(it != registered_tests_.end());
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.
@ -533,8 +586,10 @@ class GTEST_API_ TypedTestCasePState {
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;
bool registered_; bool registered_;
::std::set<const char*> defined_test_names_; RegisteredTestsMap registered_tests_;
}; };
// Skips to the first non-space char after the first comma in 'str'; // Skips to the first non-space char after the first comma in 'str';
@ -555,6 +610,11 @@ inline std::string GetPrefixUntilComma(const char* str) {
return comma == NULL ? str : std::string(str, comma); return comma == NULL ? str : std::string(str, comma);
} }
// Splits a given string on a given delimiter, populating a given
// vector with the fields.
void SplitString(const ::std::string& str, char delimiter,
::std::vector< ::std::string>* dest);
// TypeParameterizedTest<Fixture, TestSel, Types>::Register() // TypeParameterizedTest<Fixture, TestSel, Types>::Register()
// registers a list of type-parameterized tests with Google Test. The // registers a list of type-parameterized tests with Google Test. The
// return value is insignificant - we just need to return something // return value is insignificant - we just need to return something
@ -569,8 +629,10 @@ class TypeParameterizedTest {
// specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase, // specified in INSTANTIATE_TYPED_TEST_CASE_P(Prefix, TestCase,
// Types). Valid values for 'index' are [0, N - 1] where N is the // Types). Valid values for 'index' are [0, N - 1] where N is the
// length of Types. // length of Types.
static bool Register(const char* prefix, const char* case_name, static bool Register(const char* prefix,
const char* test_names, int index) { CodeLocation code_location,
const char* case_name, const char* test_names,
int index) {
typedef typename Types::Head Type; typedef typename Types::Head Type;
typedef Fixture<Type> FixtureClass; typedef Fixture<Type> FixtureClass;
typedef typename GTEST_BIND_(TestSel, Type) TestClass; typedef typename GTEST_BIND_(TestSel, Type) TestClass;
@ -580,9 +642,10 @@ class TypeParameterizedTest {
MakeAndRegisterTestInfo( MakeAndRegisterTestInfo(
(std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/" (std::string(prefix) + (prefix[0] == '\0' ? "" : "/") + case_name + "/"
+ StreamableToString(index)).c_str(), + StreamableToString(index)).c_str(),
GetPrefixUntilComma(test_names).c_str(), StripTrailingSpaces(GetPrefixUntilComma(test_names)).c_str(),
GetTypeName<Type>().c_str(), GetTypeName<Type>().c_str(),
NULL, // No value parameter. NULL, // No value parameter.
code_location,
GetTypeId<FixtureClass>(), GetTypeId<FixtureClass>(),
TestClass::SetUpTestCase, TestClass::SetUpTestCase,
TestClass::TearDownTestCase, TestClass::TearDownTestCase,
@ -590,7 +653,7 @@ class TypeParameterizedTest {
// Next, recurses (at compile time) with the tail of the type list. // Next, recurses (at compile time) with the tail of the type list.
return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail> return TypeParameterizedTest<Fixture, TestSel, typename Types::Tail>
::Register(prefix, case_name, test_names, index + 1); ::Register(prefix, code_location, case_name, test_names, index + 1);
} }
}; };
@ -598,8 +661,9 @@ class TypeParameterizedTest {
template <GTEST_TEMPLATE_ Fixture, class TestSel> template <GTEST_TEMPLATE_ Fixture, class TestSel>
class TypeParameterizedTest<Fixture, TestSel, Types0> { class TypeParameterizedTest<Fixture, TestSel, Types0> {
public: public:
static bool Register(const char* /*prefix*/, const char* /*case_name*/, static bool Register(const char* /*prefix*/, CodeLocation,
const char* /*test_names*/, int /*index*/) { const char* /*case_name*/, const char* /*test_names*/,
int /*index*/) {
return true; return true;
} }
}; };
@ -611,17 +675,31 @@ class TypeParameterizedTest<Fixture, TestSel, Types0> {
template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types> template <GTEST_TEMPLATE_ Fixture, typename Tests, typename Types>
class TypeParameterizedTestCase { class TypeParameterizedTestCase {
public: public:
static bool Register(const char* prefix, const char* case_name, static bool Register(const char* prefix, CodeLocation code_location,
const char* test_names) { const TypedTestCasePState* state,
const char* case_name, const char* test_names) {
std::string test_name = StripTrailingSpaces(
GetPrefixUntilComma(test_names));
if (!state->TestExists(test_name)) {
fprintf(stderr, "Failed to get code location for test %s.%s at %s.",
case_name, test_name.c_str(),
FormatFileLocation(code_location.file.c_str(),
code_location.line).c_str());
fflush(stderr);
posix::Abort();
}
const CodeLocation& test_location = state->GetCodeLocation(test_name);
typedef typename Tests::Head Head; typedef typename Tests::Head Head;
// First, register the first test in 'Test' for each type in 'Types'. // First, register the first test in 'Test' for each type in 'Types'.
TypeParameterizedTest<Fixture, Head, Types>::Register( TypeParameterizedTest<Fixture, Head, Types>::Register(
prefix, case_name, test_names, 0); prefix, test_location, case_name, test_names, 0);
// Next, recurses (at compile time) with the tail of the test list. // Next, recurses (at compile time) with the tail of the test list.
return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types> return TypeParameterizedTestCase<Fixture, typename Tests::Tail, Types>
::Register(prefix, case_name, SkipComma(test_names)); ::Register(prefix, code_location, state,
case_name, SkipComma(test_names));
} }
}; };
@ -629,8 +707,9 @@ class TypeParameterizedTestCase {
template <GTEST_TEMPLATE_ Fixture, typename Types> template <GTEST_TEMPLATE_ Fixture, typename Types>
class TypeParameterizedTestCase<Fixture, Templates0, Types> { class TypeParameterizedTestCase<Fixture, Templates0, Types> {
public: public:
static bool Register(const char* /*prefix*/, const char* /*case_name*/, static bool Register(const char* /*prefix*/, CodeLocation,
const char* /*test_names*/) { const TypedTestCasePState* /*state*/,
const char* /*case_name*/, const char* /*test_names*/) {
return true; return true;
} }
}; };
@ -802,25 +881,20 @@ class ImplicitlyConvertible {
// We have to put the 'public' section after the 'private' section, // We have to put the 'public' section after the 'private' section,
// or MSVC refuses to compile the code. // or MSVC refuses to compile the code.
public: public:
// MSVC warns about implicitly converting from double to int for #if defined(__BORLANDC__)
// possible loss of data, so we need to temporarily disable the
// warning.
#ifdef _MSC_VER
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4244) // Temporarily disables warning 4244.
static const bool value =
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
# pragma warning(pop) // Restores the warning state.
#elif defined(__BORLANDC__)
// C++Builder cannot use member overload resolution during template // C++Builder cannot use member overload resolution during template
// instantiation. The simplest workaround is to use its C++0x type traits // instantiation. The simplest workaround is to use its C++0x type traits
// functions (C++Builder 2009 and above only). // functions (C++Builder 2009 and above only).
static const bool value = __is_convertible(From, To); static const bool value = __is_convertible(From, To);
#else #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 = static const bool value =
sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1; sizeof(Helper(ImplicitlyConvertible::MakeFrom())) == 1;
#endif // _MSV_VER GTEST_DISABLE_MSC_WARNINGS_POP_()
#endif // __BORLANDC__
}; };
template <typename From, typename To> template <typename From, typename To>
const bool ImplicitlyConvertible<From, To>::value; const bool ImplicitlyConvertible<From, To>::value;
@ -946,11 +1020,10 @@ void CopyArray(const T* from, size_t size, U* to) {
// The relation between an NativeArray object (see below) and the // The relation between an NativeArray object (see below) and the
// native array it represents. // native array it represents.
enum RelationToSource { // We use 2 different structs to allow non-copyable types to be used, as long
kReference, // The NativeArray references the native array. // as RelationToSourceReference() is passed.
kCopy // The NativeArray makes a copy of the native array and struct RelationToSourceReference {};
// owns the copy. struct RelationToSourceCopy {};
};
// Adapts a native array to a read-only STL-style container. Instead // Adapts a native array to a read-only STL-style container. Instead
// of the complete STL container concept, this adaptor only implements // of the complete STL container concept, this adaptor only implements
@ -968,22 +1041,23 @@ class NativeArray {
typedef Element* iterator; typedef Element* iterator;
typedef const Element* const_iterator; typedef const Element* const_iterator;
// Constructs from a native array. // Constructs from a native array. References the source.
NativeArray(const Element* array, size_t count, RelationToSource relation) { NativeArray(const Element* array, size_t count, RelationToSourceReference) {
Init(array, count, relation); InitRef(array, count);
}
// Constructs from a native array. Copies the source.
NativeArray(const Element* array, size_t count, RelationToSourceCopy) {
InitCopy(array, count);
} }
// Copy constructor. // Copy constructor.
NativeArray(const NativeArray& rhs) { NativeArray(const NativeArray& rhs) {
Init(rhs.array_, rhs.size_, rhs.relation_to_source_); (this->*rhs.clone_)(rhs.array_, rhs.size_);
} }
~NativeArray() { ~NativeArray() {
// Ensures that the user doesn't instantiate NativeArray with a if (clone_ != &NativeArray::InitRef)
// const or reference type.
static_cast<void>(StaticAssertTypeEqHelper<Element,
GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>());
if (relation_to_source_ == kCopy)
delete[] array_; delete[] array_;
} }
@ -997,23 +1071,30 @@ class NativeArray {
} }
private: private:
// Initializes this object; makes a copy of the input array if enum {
// 'relation' is kCopy. kCheckTypeIsNotConstOrAReference = StaticAssertTypeEqHelper<
void Init(const Element* array, size_t a_size, RelationToSource relation) { Element, GTEST_REMOVE_REFERENCE_AND_CONST_(Element)>::value,
if (relation == kReference) { };
array_ = array;
} else { // Initializes this object with a copy of the input.
void InitCopy(const Element* array, size_t a_size) {
Element* const copy = new Element[a_size]; Element* const copy = new Element[a_size];
CopyArray(array, a_size, copy); CopyArray(array, a_size, copy);
array_ = copy; array_ = copy;
}
size_ = a_size; size_ = a_size;
relation_to_source_ = relation; clone_ = &NativeArray::InitCopy;
}
// Initializes this object with a reference of the input.
void InitRef(const Element* array, size_t a_size) {
array_ = array;
size_ = a_size;
clone_ = &NativeArray::InitRef;
} }
const Element* array_; const Element* array_;
size_t size_; size_t size_;
RelationToSource relation_to_source_; void (NativeArray::*clone_)(const Element*, size_t);
GTEST_DISALLOW_ASSIGN_(NativeArray); GTEST_DISALLOW_ASSIGN_(NativeArray);
}; };
@ -1148,6 +1229,7 @@ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
::test_info_ =\ ::test_info_ =\
::testing::internal::MakeAndRegisterTestInfo(\ ::testing::internal::MakeAndRegisterTestInfo(\
#test_case_name, #test_name, NULL, NULL, \ #test_case_name, #test_name, NULL, NULL, \
::testing::internal::CodeLocation(__FILE__, __LINE__), \
(parent_id), \ (parent_id), \
parent_class::SetUpTestCase, \ parent_class::SetUpTestCase, \
parent_class::TearDownTestCase, \ parent_class::TearDownTestCase, \
@ -1156,3 +1238,4 @@ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\
void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody() void GTEST_TEST_CLASS_NAME_(test_case_name, test_name)::TestBody()
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_ #endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_INTERNAL_H_

View File

@ -110,7 +110,12 @@ class linked_ptr_internal {
MutexLock lock(&g_linked_ptr_mutex); MutexLock lock(&g_linked_ptr_mutex);
linked_ptr_internal const* p = ptr; linked_ptr_internal const* p = ptr;
while (p->next_ != ptr) p = p->next_; while (p->next_ != ptr) {
assert(p->next_ != this &&
"Trying to join() a linked ring we are already in. "
"Is GMock thread safety enabled?");
p = p->next_;
}
p->next_ = this; p->next_ = this;
next_ = ptr; next_ = ptr;
} }
@ -123,7 +128,12 @@ class linked_ptr_internal {
if (next_ == this) return true; if (next_ == this) return true;
linked_ptr_internal const* p = next_; linked_ptr_internal const* p = next_;
while (p->next_ != this) p = p->next_; while (p->next_ != this) {
assert(p->next_ != next_ &&
"Trying to depart() a linked ring we are not in. "
"Is GMock thread safety enabled?");
p = p->next_;
}
p->next_ = next_; p->next_ = next_;
return false; return false;
} }

View File

@ -40,7 +40,7 @@
// and at most 10 arguments in Combine. Please contact // and at most 10 arguments in Combine. Please contact
// googletestframework@googlegroups.com if you need more. // googletestframework@googlegroups.com if you need more.
// Please note that the number of arguments to Combine is limited // Please note that the number of arguments to Combine is limited
// by the maximum arity of the implementation of tr1::tuple which is // by the maximum arity of the implementation of tuple which is
// currently set at 10. // currently set at 10.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
@ -79,7 +79,10 @@ class ValueArray1 {
explicit ValueArray1(T1 v1) : v1_(v1) {} explicit ValueArray1(T1 v1) : v1_(v1) {}
template <typename T> template <typename T>
operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); } operator ParamGenerator<T>() const {
const T array[] = {static_cast<T>(v1_)};
return ValuesIn(array);
}
private: private:
// No implementation - assignment is unsupported. // No implementation - assignment is unsupported.
@ -3157,9 +3160,9 @@ class ValueArray50 {
// //
template <typename T1, typename T2> template <typename T1, typename T2>
class CartesianProductGenerator2 class CartesianProductGenerator2
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2> > { : public ParamGeneratorInterface< ::testing::tuple<T1, T2> > {
public: public:
typedef ::std::tr1::tuple<T1, T2> ParamType; typedef ::testing::tuple<T1, T2> ParamType;
CartesianProductGenerator2(const ParamGenerator<T1>& g1, CartesianProductGenerator2(const ParamGenerator<T1>& g1,
const ParamGenerator<T2>& g2) const ParamGenerator<T2>& g2)
@ -3272,9 +3275,9 @@ class CartesianProductGenerator2
template <typename T1, typename T2, typename T3> template <typename T1, typename T2, typename T3>
class CartesianProductGenerator3 class CartesianProductGenerator3
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3> > { : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3> > {
public: public:
typedef ::std::tr1::tuple<T1, T2, T3> ParamType; typedef ::testing::tuple<T1, T2, T3> ParamType;
CartesianProductGenerator3(const ParamGenerator<T1>& g1, CartesianProductGenerator3(const ParamGenerator<T1>& g1,
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3) const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3)
@ -3404,9 +3407,9 @@ class CartesianProductGenerator3
template <typename T1, typename T2, typename T3, typename T4> template <typename T1, typename T2, typename T3, typename T4>
class CartesianProductGenerator4 class CartesianProductGenerator4
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4> > { : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4> > {
public: public:
typedef ::std::tr1::tuple<T1, T2, T3, T4> ParamType; typedef ::testing::tuple<T1, T2, T3, T4> ParamType;
CartesianProductGenerator4(const ParamGenerator<T1>& g1, CartesianProductGenerator4(const ParamGenerator<T1>& g1,
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3, const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
@ -3555,9 +3558,9 @@ class CartesianProductGenerator4
template <typename T1, typename T2, typename T3, typename T4, typename T5> template <typename T1, typename T2, typename T3, typename T4, typename T5>
class CartesianProductGenerator5 class CartesianProductGenerator5
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5> > { : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5> > {
public: public:
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5> ParamType; typedef ::testing::tuple<T1, T2, T3, T4, T5> ParamType;
CartesianProductGenerator5(const ParamGenerator<T1>& g1, CartesianProductGenerator5(const ParamGenerator<T1>& g1,
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3, const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
@ -3723,10 +3726,10 @@ class CartesianProductGenerator5
template <typename T1, typename T2, typename T3, typename T4, typename T5, template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6> typename T6>
class CartesianProductGenerator6 class CartesianProductGenerator6
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5,
T6> > { T6> > {
public: public:
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> ParamType; typedef ::testing::tuple<T1, T2, T3, T4, T5, T6> ParamType;
CartesianProductGenerator6(const ParamGenerator<T1>& g1, CartesianProductGenerator6(const ParamGenerator<T1>& g1,
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3, const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
@ -3909,10 +3912,10 @@ class CartesianProductGenerator6
template <typename T1, typename T2, typename T3, typename T4, typename T5, template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7> typename T6, typename T7>
class CartesianProductGenerator7 class CartesianProductGenerator7
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
T7> > { T7> > {
public: public:
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType; typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7> ParamType;
CartesianProductGenerator7(const ParamGenerator<T1>& g1, CartesianProductGenerator7(const ParamGenerator<T1>& g1,
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3, const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
@ -4112,10 +4115,10 @@ class CartesianProductGenerator7
template <typename T1, typename T2, typename T3, typename T4, typename T5, template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8> typename T6, typename T7, typename T8>
class CartesianProductGenerator8 class CartesianProductGenerator8
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
T7, T8> > { T7, T8> > {
public: public:
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType; typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8> ParamType;
CartesianProductGenerator8(const ParamGenerator<T1>& g1, CartesianProductGenerator8(const ParamGenerator<T1>& g1,
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3, const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
@ -4334,10 +4337,10 @@ class CartesianProductGenerator8
template <typename T1, typename T2, typename T3, typename T4, typename T5, template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9> typename T6, typename T7, typename T8, typename T9>
class CartesianProductGenerator9 class CartesianProductGenerator9
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
T7, T8, T9> > { T7, T8, T9> > {
public: public:
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType; typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9> ParamType;
CartesianProductGenerator9(const ParamGenerator<T1>& g1, CartesianProductGenerator9(const ParamGenerator<T1>& g1,
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3, const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
@ -4573,10 +4576,10 @@ class CartesianProductGenerator9
template <typename T1, typename T2, typename T3, typename T4, typename T5, template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10> typename T6, typename T7, typename T8, typename T9, typename T10>
class CartesianProductGenerator10 class CartesianProductGenerator10
: public ParamGeneratorInterface< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, : public ParamGeneratorInterface< ::testing::tuple<T1, T2, T3, T4, T5, T6,
T7, T8, T9, T10> > { T7, T8, T9, T10> > {
public: public:
typedef ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType; typedef ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10> ParamType;
CartesianProductGenerator10(const ParamGenerator<T1>& g1, CartesianProductGenerator10(const ParamGenerator<T1>& g1,
const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3, const ParamGenerator<T2>& g2, const ParamGenerator<T3>& g3,
@ -4838,8 +4841,8 @@ class CartesianProductHolder2 {
CartesianProductHolder2(const Generator1& g1, const Generator2& g2) CartesianProductHolder2(const Generator1& g1, const Generator2& g2)
: g1_(g1), g2_(g2) {} : g1_(g1), g2_(g2) {}
template <typename T1, typename T2> template <typename T1, typename T2>
operator ParamGenerator< ::std::tr1::tuple<T1, T2> >() const { operator ParamGenerator< ::testing::tuple<T1, T2> >() const {
return ParamGenerator< ::std::tr1::tuple<T1, T2> >( return ParamGenerator< ::testing::tuple<T1, T2> >(
new CartesianProductGenerator2<T1, T2>( new CartesianProductGenerator2<T1, T2>(
static_cast<ParamGenerator<T1> >(g1_), static_cast<ParamGenerator<T1> >(g1_),
static_cast<ParamGenerator<T2> >(g2_))); static_cast<ParamGenerator<T2> >(g2_)));
@ -4860,8 +4863,8 @@ CartesianProductHolder3(const Generator1& g1, const Generator2& g2,
const Generator3& g3) const Generator3& g3)
: g1_(g1), g2_(g2), g3_(g3) {} : g1_(g1), g2_(g2), g3_(g3) {}
template <typename T1, typename T2, typename T3> template <typename T1, typename T2, typename T3>
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >() const { operator ParamGenerator< ::testing::tuple<T1, T2, T3> >() const {
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3> >( return ParamGenerator< ::testing::tuple<T1, T2, T3> >(
new CartesianProductGenerator3<T1, T2, T3>( new CartesianProductGenerator3<T1, T2, T3>(
static_cast<ParamGenerator<T1> >(g1_), static_cast<ParamGenerator<T1> >(g1_),
static_cast<ParamGenerator<T2> >(g2_), static_cast<ParamGenerator<T2> >(g2_),
@ -4885,8 +4888,8 @@ CartesianProductHolder4(const Generator1& g1, const Generator2& g2,
const Generator3& g3, const Generator4& g4) const Generator3& g3, const Generator4& g4)
: g1_(g1), g2_(g2), g3_(g3), g4_(g4) {} : g1_(g1), g2_(g2), g3_(g3), g4_(g4) {}
template <typename T1, typename T2, typename T3, typename T4> template <typename T1, typename T2, typename T3, typename T4>
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >() const { operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4> >() const {
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4> >( return ParamGenerator< ::testing::tuple<T1, T2, T3, T4> >(
new CartesianProductGenerator4<T1, T2, T3, T4>( new CartesianProductGenerator4<T1, T2, T3, T4>(
static_cast<ParamGenerator<T1> >(g1_), static_cast<ParamGenerator<T1> >(g1_),
static_cast<ParamGenerator<T2> >(g2_), static_cast<ParamGenerator<T2> >(g2_),
@ -4912,8 +4915,8 @@ CartesianProductHolder5(const Generator1& g1, const Generator2& g2,
const Generator3& g3, const Generator4& g4, const Generator5& g5) const Generator3& g3, const Generator4& g4, const Generator5& g5)
: g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {} : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5) {}
template <typename T1, typename T2, typename T3, typename T4, typename T5> template <typename T1, typename T2, typename T3, typename T4, typename T5>
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >() const { operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5> >() const {
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5> >( return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5> >(
new CartesianProductGenerator5<T1, T2, T3, T4, T5>( new CartesianProductGenerator5<T1, T2, T3, T4, T5>(
static_cast<ParamGenerator<T1> >(g1_), static_cast<ParamGenerator<T1> >(g1_),
static_cast<ParamGenerator<T2> >(g2_), static_cast<ParamGenerator<T2> >(g2_),
@ -4943,8 +4946,8 @@ CartesianProductHolder6(const Generator1& g1, const Generator2& g2,
: g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {} : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6) {}
template <typename T1, typename T2, typename T3, typename T4, typename T5, template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6> typename T6>
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >() const { operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6> >() const {
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6> >( return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6> >(
new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>( new CartesianProductGenerator6<T1, T2, T3, T4, T5, T6>(
static_cast<ParamGenerator<T1> >(g1_), static_cast<ParamGenerator<T1> >(g1_),
static_cast<ParamGenerator<T2> >(g2_), static_cast<ParamGenerator<T2> >(g2_),
@ -4976,9 +4979,9 @@ CartesianProductHolder7(const Generator1& g1, const Generator2& g2,
: g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {} : g1_(g1), g2_(g2), g3_(g3), g4_(g4), g5_(g5), g6_(g6), g7_(g7) {}
template <typename T1, typename T2, typename T3, typename T4, typename T5, template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7> typename T6, typename T7>
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6,
T7> >() const { T7> >() const {
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7> >( return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7> >(
new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>( new CartesianProductGenerator7<T1, T2, T3, T4, T5, T6, T7>(
static_cast<ParamGenerator<T1> >(g1_), static_cast<ParamGenerator<T1> >(g1_),
static_cast<ParamGenerator<T2> >(g2_), static_cast<ParamGenerator<T2> >(g2_),
@ -5014,9 +5017,9 @@ CartesianProductHolder8(const Generator1& g1, const Generator2& g2,
g8_(g8) {} g8_(g8) {}
template <typename T1, typename T2, typename T3, typename T4, typename T5, template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8> typename T6, typename T7, typename T8>
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7,
T8> >() const { T8> >() const {
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >( return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8> >(
new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>( new CartesianProductGenerator8<T1, T2, T3, T4, T5, T6, T7, T8>(
static_cast<ParamGenerator<T1> >(g1_), static_cast<ParamGenerator<T1> >(g1_),
static_cast<ParamGenerator<T2> >(g2_), static_cast<ParamGenerator<T2> >(g2_),
@ -5055,9 +5058,9 @@ CartesianProductHolder9(const Generator1& g1, const Generator2& g2,
g9_(g9) {} g9_(g9) {}
template <typename T1, typename T2, typename T3, typename T4, typename T5, template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9> typename T6, typename T7, typename T8, typename T9>
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
T9> >() const { T9> >() const {
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8,
T9> >( T9> >(
new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>( new CartesianProductGenerator9<T1, T2, T3, T4, T5, T6, T7, T8, T9>(
static_cast<ParamGenerator<T1> >(g1_), static_cast<ParamGenerator<T1> >(g1_),
@ -5099,10 +5102,10 @@ CartesianProductHolder10(const Generator1& g1, const Generator2& g2,
g9_(g9), g10_(g10) {} g9_(g9), g10_(g10) {}
template <typename T1, typename T2, typename T3, typename T4, typename T5, template <typename T1, typename T2, typename T3, typename T4, typename T5,
typename T6, typename T7, typename T8, typename T9, typename T10> typename T6, typename T7, typename T8, typename T9, typename T10>
operator ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, operator ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9,
T9, T10> >() const { T10> >() const {
return ParamGenerator< ::std::tr1::tuple<T1, T2, T3, T4, T5, T6, T7, T8, return ParamGenerator< ::testing::tuple<T1, T2, T3, T4, T5, T6, T7, T8, T9,
T9, T10> >( T10> >(
new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9, new CartesianProductGenerator10<T1, T2, T3, T4, T5, T6, T7, T8, T9,
T10>( T10>(
static_cast<ParamGenerator<T1> >(g1_), static_cast<ParamGenerator<T1> >(g1_),

View File

@ -39,7 +39,7 @@ $var maxtuple = 10 $$ Maximum number of Combine arguments we want to support.
// and at most $maxtuple arguments in Combine. Please contact // and at most $maxtuple arguments in Combine. Please contact
// googletestframework@googlegroups.com if you need more. // googletestframework@googlegroups.com if you need more.
// Please note that the number of arguments to Combine is limited // Please note that the number of arguments to Combine is limited
// by the maximum arity of the implementation of tr1::tuple which is // by the maximum arity of the implementation of tuple which is
// currently set at $maxtuple. // currently set at $maxtuple.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_ #ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PARAM_UTIL_GENERATED_H_
@ -72,29 +72,14 @@ internal::ParamGenerator<typename Container::value_type> ValuesIn(
namespace internal { namespace internal {
// Used in the Values() function to provide polymorphic capabilities. // Used in the Values() function to provide polymorphic capabilities.
template <typename T1> $range i 1..n
class ValueArray1 {
public:
explicit ValueArray1(T1 v1) : v1_(v1) {}
template <typename T>
operator ParamGenerator<T>() const { return ValuesIn(&v1_, &v1_ + 1); }
private:
// No implementation - assignment is unsupported.
void operator=(const ValueArray1& other);
const T1 v1_;
};
$range i 2..n
$for i [[ $for i [[
$range j 1..i $range j 1..i
template <$for j, [[typename T$j]]> template <$for j, [[typename T$j]]>
class ValueArray$i { class ValueArray$i {
public: public:
ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {} $if i==1 [[explicit ]]ValueArray$i($for j, [[T$j v$j]]) : $for j, [[v$(j)_(v$j)]] {}
template <typename T> template <typename T>
operator ParamGenerator<T>() const { operator ParamGenerator<T>() const {
@ -128,9 +113,9 @@ $range k 2..i
template <$for j, [[typename T$j]]> template <$for j, [[typename T$j]]>
class CartesianProductGenerator$i class CartesianProductGenerator$i
: public ParamGeneratorInterface< ::std::tr1::tuple<$for j, [[T$j]]> > { : public ParamGeneratorInterface< ::testing::tuple<$for j, [[T$j]]> > {
public: public:
typedef ::std::tr1::tuple<$for j, [[T$j]]> ParamType; typedef ::testing::tuple<$for j, [[T$j]]> ParamType;
CartesianProductGenerator$i($for j, [[const ParamGenerator<T$j>& g$j]]) CartesianProductGenerator$i($for j, [[const ParamGenerator<T$j>& g$j]])
: $for j, [[g$(j)_(g$j)]] {} : $for j, [[g$(j)_(g$j)]] {}
@ -269,8 +254,8 @@ class CartesianProductHolder$i {
CartesianProductHolder$i($for j, [[const Generator$j& g$j]]) CartesianProductHolder$i($for j, [[const Generator$j& g$j]])
: $for j, [[g$(j)_(g$j)]] {} : $for j, [[g$(j)_(g$j)]] {}
template <$for j, [[typename T$j]]> template <$for j, [[typename T$j]]>
operator ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >() const { operator ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >() const {
return ParamGenerator< ::std::tr1::tuple<$for j, [[T$j]]> >( return ParamGenerator< ::testing::tuple<$for j, [[T$j]]> >(
new CartesianProductGenerator$i<$for j, [[T$j]]>( new CartesianProductGenerator$i<$for j, [[T$j]]>(
$for j,[[ $for j,[[

View File

@ -58,7 +58,7 @@ namespace internal {
// TEST_P macro is used to define two tests with the same name // TEST_P macro is used to define two tests with the same name
// but in different namespaces. // but in different namespaces.
GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name, GTEST_API_ void ReportInvalidTestCaseType(const char* test_case_name,
const char* file, int line); CodeLocation code_location);
template <typename> class ParamGeneratorInterface; template <typename> class ParamGeneratorInterface;
template <typename> class ParamGenerator; template <typename> class ParamGenerator;
@ -450,8 +450,9 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
// A function that returns an instance of appropriate generator type. // A function that returns an instance of appropriate generator type.
typedef ParamGenerator<ParamType>(GeneratorCreationFunc)(); typedef ParamGenerator<ParamType>(GeneratorCreationFunc)();
explicit ParameterizedTestCaseInfo(const char* name) explicit ParameterizedTestCaseInfo(
: test_case_name_(name) {} const char* name, CodeLocation code_location)
: test_case_name_(name), code_location_(code_location) {}
// Test case base name for display purposes. // Test case base name for display purposes.
virtual const string& GetTestCaseName() const { return test_case_name_; } virtual const string& GetTestCaseName() const { return test_case_name_; }
@ -510,6 +511,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
test_name_stream.GetString().c_str(), test_name_stream.GetString().c_str(),
NULL, // No type parameter. NULL, // No type parameter.
PrintToString(*param_it).c_str(), PrintToString(*param_it).c_str(),
code_location_,
GetTestCaseTypeId(), GetTestCaseTypeId(),
TestCase::SetUpTestCase, TestCase::SetUpTestCase,
TestCase::TearDownTestCase, TestCase::TearDownTestCase,
@ -541,6 +543,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
InstantiationContainer; InstantiationContainer;
const string test_case_name_; const string test_case_name_;
CodeLocation code_location_;
TestInfoContainer tests_; TestInfoContainer tests_;
InstantiationContainer instantiations_; InstantiationContainer instantiations_;
@ -568,8 +571,7 @@ class ParameterizedTestCaseRegistry {
template <class TestCase> template <class TestCase>
ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder( ParameterizedTestCaseInfo<TestCase>* GetTestCasePatternHolder(
const char* test_case_name, const char* test_case_name,
const char* file, CodeLocation code_location) {
int line) {
ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL; ParameterizedTestCaseInfo<TestCase>* typed_test_info = NULL;
for (TestCaseInfoContainer::iterator it = test_case_infos_.begin(); for (TestCaseInfoContainer::iterator it = test_case_infos_.begin();
it != test_case_infos_.end(); ++it) { it != test_case_infos_.end(); ++it) {
@ -578,7 +580,7 @@ class ParameterizedTestCaseRegistry {
// Complain about incorrect usage of Google Test facilities // Complain about incorrect usage of Google Test facilities
// and terminate the program since we cannot guaranty correct // and terminate the program since we cannot guaranty correct
// test case setup and tear-down in this case. // test case setup and tear-down in this case.
ReportInvalidTestCaseType(test_case_name, file, line); ReportInvalidTestCaseType(test_case_name, code_location);
posix::Abort(); posix::Abort();
} else { } else {
// At this point we are sure that the object we found is of the same // At this point we are sure that the object we found is of the same
@ -591,7 +593,8 @@ class ParameterizedTestCaseRegistry {
} }
} }
if (typed_test_info == NULL) { if (typed_test_info == NULL) {
typed_test_info = new ParameterizedTestCaseInfo<TestCase>(test_case_name); typed_test_info = new ParameterizedTestCaseInfo<TestCase>(
test_case_name, code_location);
test_case_infos_.push_back(typed_test_info); test_case_infos_.push_back(typed_test_info);
} }
return typed_test_info; return typed_test_info;

View File

@ -0,0 +1,93 @@
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// The Google C++ Testing Framework (Google Test)
//
// This header file defines the GTEST_OS_* macro.
// It is separate from gtest-port.h so that custom/gtest-port.h can include it.
#ifndef GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
#define GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_
// Determines the platform on which Google Test is compiled.
#ifdef __CYGWIN__
# define GTEST_OS_CYGWIN 1
#elif defined __SYMBIAN32__
# define GTEST_OS_SYMBIAN 1
#elif defined _WIN32
# define GTEST_OS_WINDOWS 1
# ifdef _WIN32_WCE
# define GTEST_OS_WINDOWS_MOBILE 1
# elif defined(__MINGW__) || defined(__MINGW32__)
# define GTEST_OS_WINDOWS_MINGW 1
# elif defined(WINAPI_FAMILY)
# include <winapifamily.h>
# if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
# define GTEST_OS_WINDOWS_DESKTOP 1
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP)
# define GTEST_OS_WINDOWS_PHONE 1
# elif WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)
# define GTEST_OS_WINDOWS_RT 1
# else
// WINAPI_FAMILY defined but no known partition matched.
// Default to desktop.
# define GTEST_OS_WINDOWS_DESKTOP 1
# endif
# else
# define GTEST_OS_WINDOWS_DESKTOP 1
# endif // _WIN32_WCE
#elif defined __APPLE__
# define GTEST_OS_MAC 1
# if TARGET_OS_IPHONE
# define GTEST_OS_IOS 1
# endif
#elif defined __FreeBSD__
# define GTEST_OS_FREEBSD 1
#elif defined __linux__
# define GTEST_OS_LINUX 1
# if defined __ANDROID__
# define GTEST_OS_LINUX_ANDROID 1
# endif
#elif defined __MVS__
# define GTEST_OS_ZOS 1
#elif defined(__sun) && defined(__SVR4)
# define GTEST_OS_SOLARIS 1
#elif defined(_AIX)
# define GTEST_OS_AIX 1
#elif defined(__hpux)
# define GTEST_OS_HPUX 1
#elif defined __native_client__
# define GTEST_OS_NACL 1
#elif defined __OpenBSD__
# define GTEST_OS_OPENBSD 1
#elif defined __QNX__
# define GTEST_OS_QNX 1
#endif // __CYGWIN__
#endif // GTEST_INCLUDE_GTEST_INTERNAL_GTEST_PORT_ARCH_H_

File diff suppressed because it is too large Load Diff

View File

@ -68,9 +68,9 @@
// Indicates that this translation unit is part of Google Test's // Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is // implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick is to // included, or there will be a compiler error. This trick exists to
// prevent a user from accidentally including gtest-internal-inl.h in // prevent the accidental inclusion of gtest-internal-inl.h in the
// his code. // user's code.
#define GTEST_IMPLEMENTATION_ 1 #define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_ #undef GTEST_IMPLEMENTATION_
@ -169,6 +169,14 @@ KilledBySignal::KilledBySignal(int signum) : signum_(signum) {
// KilledBySignal function-call operator. // KilledBySignal function-call operator.
bool KilledBySignal::operator()(int exit_status) const { bool KilledBySignal::operator()(int exit_status) const {
# if defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
{
bool result;
if (GTEST_KILLED_BY_SIGNAL_OVERRIDE_(signum_, exit_status, &result)) {
return result;
}
}
# endif // defined(GTEST_KILLED_BY_SIGNAL_OVERRIDE_)
return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_; return WIFSIGNALED(exit_status) && WTERMSIG(exit_status) == signum_;
} }
# endif // !GTEST_OS_WINDOWS # endif // !GTEST_OS_WINDOWS
@ -985,6 +993,8 @@ void StackLowerThanAddress(const void* ptr, bool* result) {
*result = (&dummy < ptr); *result = (&dummy < ptr);
} }
// Make sure AddressSanitizer does not tamper with the stack here.
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
bool StackGrowsDown() { bool StackGrowsDown() {
int dummy; int dummy;
bool result; bool result;
@ -1202,26 +1212,6 @@ bool DefaultDeathTestFactory::Create(const char* statement, const RE* regex,
return true; return true;
} }
// Splits a given string on a given delimiter, populating a given
// vector with the fields. GTEST_HAS_DEATH_TEST implies that we have
// ::std::string, so we can use it here.
static void SplitString(const ::std::string& str, char delimiter,
::std::vector< ::std::string>* dest) {
::std::vector< ::std::string> parsed;
::std::string::size_type pos = 0;
while (::testing::internal::AlwaysTrue()) {
const ::std::string::size_type colon = str.find(delimiter, pos);
if (colon == ::std::string::npos) {
parsed.push_back(str.substr(pos));
break;
} else {
parsed.push_back(str.substr(pos, colon - pos));
pos = colon + 1;
}
}
dest->swap(parsed);
}
# if GTEST_OS_WINDOWS # if GTEST_OS_WINDOWS
// Recreates the pipe and event handles from the provided parameters, // Recreates the pipe and event handles from the provided parameters,
// signals the event, and returns a file descriptor wrapped around the pipe // signals the event, and returns a file descriptor wrapped around the pipe

View File

@ -97,7 +97,7 @@ static bool IsPathSeparator(char c) {
// Returns the current working directory, or "" if unsuccessful. // Returns the current working directory, or "" if unsuccessful.
FilePath FilePath::GetCurrentDir() { FilePath FilePath::GetCurrentDir() {
#if GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
// Windows CE doesn't have a current directory, so we just return // Windows CE doesn't have a current directory, so we just return
// something reasonable. // something reasonable.
return FilePath(kCurrentDirectoryString); return FilePath(kCurrentDirectoryString);
@ -106,7 +106,14 @@ FilePath FilePath::GetCurrentDir() {
return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); return FilePath(_getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd);
#else #else
char cwd[GTEST_PATH_MAX_ + 1] = { '\0' }; char cwd[GTEST_PATH_MAX_ + 1] = { '\0' };
return FilePath(getcwd(cwd, sizeof(cwd)) == NULL ? "" : cwd); char* result = getcwd(cwd, sizeof(cwd));
# if GTEST_OS_NACL
// getcwd will likely fail in NaCl due to the sandbox, so return something
// reasonable. The user may have provided a shim implementation for getcwd,
// however, so fallback only when failure is detected.
return FilePath(result == NULL ? kCurrentDirectoryString : cwd);
# endif // GTEST_OS_NACL
return FilePath(result == NULL ? "" : cwd);
#endif // GTEST_OS_WINDOWS_MOBILE #endif // GTEST_OS_WINDOWS_MOBILE
} }

View File

@ -40,7 +40,7 @@
// GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is // GTEST_IMPLEMENTATION_ is defined to 1 iff the current translation unit is
// part of Google Test's implementation; otherwise it's undefined. // part of Google Test's implementation; otherwise it's undefined.
#if !GTEST_IMPLEMENTATION_ #if !GTEST_IMPLEMENTATION_
// A user is trying to include this from his code - just say no. // If this file is included from the user's code, just say no.
# error "gtest-internal-inl.h is part of Google Test's internal implementation." # error "gtest-internal-inl.h is part of Google Test's internal implementation."
# error "It must not be included except by Google Test itself." # error "It must not be included except by Google Test itself."
#endif // GTEST_IMPLEMENTATION_ #endif // GTEST_IMPLEMENTATION_
@ -100,6 +100,7 @@ const char kShuffleFlag[] = "shuffle";
const char kStackTraceDepthFlag[] = "stack_trace_depth"; const char kStackTraceDepthFlag[] = "stack_trace_depth";
const char kStreamResultToFlag[] = "stream_result_to"; const char kStreamResultToFlag[] = "stream_result_to";
const char kThrowOnFailureFlag[] = "throw_on_failure"; const char kThrowOnFailureFlag[] = "throw_on_failure";
const char kFlagfileFlag[] = "flagfile";
// A valid random seed must be in [1, kMaxRandomSeed]. // A valid random seed must be in [1, kMaxRandomSeed].
const int kMaxRandomSeed = 99999; const int kMaxRandomSeed = 99999;
@ -432,6 +433,10 @@ class OsStackTraceGetterInterface {
// CurrentStackTrace() will use to find and hide Google Test stack frames. // CurrentStackTrace() will use to find and hide Google Test stack frames.
virtual void UponLeavingGTest() = 0; virtual void UponLeavingGTest() = 0;
// This string is inserted in place of stack frames that are part of
// Google Test's implementation.
static const char* const kElidedFramesMarker;
private: private:
GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface); GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetterInterface);
}; };
@ -439,26 +444,12 @@ class OsStackTraceGetterInterface {
// A working implementation of the OsStackTraceGetterInterface interface. // A working implementation of the OsStackTraceGetterInterface interface.
class OsStackTraceGetter : public OsStackTraceGetterInterface { class OsStackTraceGetter : public OsStackTraceGetterInterface {
public: public:
OsStackTraceGetter() : caller_frame_(NULL) {} OsStackTraceGetter() {}
virtual string CurrentStackTrace(int max_depth, int skip_count) virtual string CurrentStackTrace(int max_depth, int skip_count);
GTEST_LOCK_EXCLUDED_(mutex_); virtual void UponLeavingGTest();
virtual void UponLeavingGTest() GTEST_LOCK_EXCLUDED_(mutex_);
// This string is inserted in place of stack frames that are part of
// Google Test's implementation.
static const char* const kElidedFramesMarker;
private: private:
Mutex mutex_; // protects all internal state
// We save the stack frame below the frame that calls user code.
// We do this because the address of the frame immediately below
// the user code changes between the call to UponLeavingGTest()
// and any calls to CurrentStackTrace() from within the user code.
void* caller_frame_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter); GTEST_DISALLOW_COPY_AND_ASSIGN_(OsStackTraceGetter);
}; };
@ -968,32 +959,6 @@ GTEST_API_ void ParseGoogleTestFlagsOnly(int* argc, wchar_t** argv);
// platform. // platform.
GTEST_API_ std::string GetLastErrnoDescription(); GTEST_API_ std::string GetLastErrnoDescription();
# if GTEST_OS_WINDOWS
// Provides leak-safe Windows kernel handle ownership.
class AutoHandle {
public:
AutoHandle() : handle_(INVALID_HANDLE_VALUE) {}
explicit AutoHandle(HANDLE handle) : handle_(handle) {}
~AutoHandle() { Reset(); }
HANDLE Get() const { return handle_; }
void Reset() { Reset(INVALID_HANDLE_VALUE); }
void Reset(HANDLE handle) {
if (handle != handle_) {
if (handle_ != INVALID_HANDLE_VALUE)
::CloseHandle(handle_);
handle_ = handle;
}
}
private:
HANDLE handle_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(AutoHandle);
};
# endif // GTEST_OS_WINDOWS
// Attempts to parse a string into a positive integer pointed to by the // Attempts to parse a string into a positive integer pointed to by the
// number parameter. Returns true if that is possible. // number parameter. Returns true if that is possible.
// GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use // GTEST_HAS_DEATH_TEST implies that we have ::std::string, so we can use

View File

@ -35,15 +35,16 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <fstream>
#if GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS
# include <windows.h> // For TerminateProcess() # include <windows.h>
#elif GTEST_OS_WINDOWS
# include <io.h> # include <io.h>
# include <sys/stat.h> # include <sys/stat.h>
# include <map> // Used in ThreadLocal.
#else #else
# include <unistd.h> # include <unistd.h>
#endif // GTEST_OS_WINDOWS_MOBILE #endif // GTEST_OS_WINDOWS
#if GTEST_OS_MAC #if GTEST_OS_MAC
# include <mach/mach_init.h> # include <mach/mach_init.h>
@ -53,6 +54,7 @@
#if GTEST_OS_QNX #if GTEST_OS_QNX
# include <devctl.h> # include <devctl.h>
# include <fcntl.h>
# include <sys/procfs.h> # include <sys/procfs.h>
#endif // GTEST_OS_QNX #endif // GTEST_OS_QNX
@ -63,9 +65,9 @@
// Indicates that this translation unit is part of Google Test's // Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is // implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick is to // included, or there will be a compiler error. This trick exists to
// prevent a user from accidentally including gtest-internal-inl.h in // prevent the accidental inclusion of gtest-internal-inl.h in the
// his code. // user's code.
#define GTEST_IMPLEMENTATION_ 1 #define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_ #undef GTEST_IMPLEMENTATION_
@ -82,10 +84,31 @@ const int kStdOutFileno = STDOUT_FILENO;
const int kStdErrFileno = STDERR_FILENO; const int kStdErrFileno = STDERR_FILENO;
#endif // _MSC_VER #endif // _MSC_VER
#if GTEST_OS_MAC #if GTEST_OS_LINUX
namespace {
template <typename T>
T ReadProcFileField(const string& filename, int field) {
std::string dummy;
std::ifstream file(filename.c_str());
while (field-- > 0) {
file >> dummy;
}
T output = 0;
file >> output;
return output;
}
} // namespace
// Returns the number of active threads, or 0 when there is an error.
size_t GetThreadCount() {
const string filename =
(Message() << "/proc/" << getpid() << "/stat").GetString();
return ReadProcFileField<int>(filename, 19);
}
#elif GTEST_OS_MAC
// Returns the number of threads running in the process, or 0 to indicate that
// we cannot detect it.
size_t GetThreadCount() { size_t GetThreadCount() {
const task_t task = mach_task_self(); const task_t task = mach_task_self();
mach_msg_type_number_t thread_count; mach_msg_type_number_t thread_count;
@ -131,7 +154,390 @@ size_t GetThreadCount() {
return 0; return 0;
} }
#endif // GTEST_OS_MAC #endif // GTEST_OS_LINUX
#if GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
void SleepMilliseconds(int n) {
::Sleep(n);
}
AutoHandle::AutoHandle()
: handle_(INVALID_HANDLE_VALUE) {}
AutoHandle::AutoHandle(Handle handle)
: handle_(handle) {}
AutoHandle::~AutoHandle() {
Reset();
}
AutoHandle::Handle AutoHandle::Get() const {
return handle_;
}
void AutoHandle::Reset() {
Reset(INVALID_HANDLE_VALUE);
}
void AutoHandle::Reset(HANDLE handle) {
// Resetting with the same handle we already own is invalid.
if (handle_ != handle) {
if (IsCloseable()) {
::CloseHandle(handle_);
}
handle_ = handle;
} else {
GTEST_CHECK_(!IsCloseable())
<< "Resetting a valid handle to itself is likely a programmer error "
"and thus not allowed.";
}
}
bool AutoHandle::IsCloseable() const {
// Different Windows APIs may use either of these values to represent an
// invalid handle.
return handle_ != NULL && handle_ != INVALID_HANDLE_VALUE;
}
Notification::Notification()
: event_(::CreateEvent(NULL, // Default security attributes.
TRUE, // Do not reset automatically.
FALSE, // Initially unset.
NULL)) { // Anonymous event.
GTEST_CHECK_(event_.Get() != NULL);
}
void Notification::Notify() {
GTEST_CHECK_(::SetEvent(event_.Get()) != FALSE);
}
void Notification::WaitForNotification() {
GTEST_CHECK_(
::WaitForSingleObject(event_.Get(), INFINITE) == WAIT_OBJECT_0);
}
Mutex::Mutex()
: type_(kDynamic),
owner_thread_id_(0),
critical_section_init_phase_(0),
critical_section_(new CRITICAL_SECTION) {
::InitializeCriticalSection(critical_section_);
}
Mutex::~Mutex() {
// Static mutexes are leaked intentionally. It is not thread-safe to try
// to clean them up.
// TODO(yukawa): Switch to Slim Reader/Writer (SRW) Locks, which requires
// nothing to clean it up but is available only on Vista and later.
// http://msdn.microsoft.com/en-us/library/windows/desktop/aa904937.aspx
if (type_ == kDynamic) {
::DeleteCriticalSection(critical_section_);
delete critical_section_;
critical_section_ = NULL;
}
}
void Mutex::Lock() {
ThreadSafeLazyInit();
::EnterCriticalSection(critical_section_);
owner_thread_id_ = ::GetCurrentThreadId();
}
void Mutex::Unlock() {
ThreadSafeLazyInit();
// We don't protect writing to owner_thread_id_ here, as it's the
// caller's responsibility to ensure that the current thread holds the
// mutex when this is called.
owner_thread_id_ = 0;
::LeaveCriticalSection(critical_section_);
}
// Does nothing if the current thread holds the mutex. Otherwise, crashes
// with high probability.
void Mutex::AssertHeld() {
ThreadSafeLazyInit();
GTEST_CHECK_(owner_thread_id_ == ::GetCurrentThreadId())
<< "The current thread is not holding the mutex @" << this;
}
// Initializes owner_thread_id_ and critical_section_ in static mutexes.
void Mutex::ThreadSafeLazyInit() {
// Dynamic mutexes are initialized in the constructor.
if (type_ == kStatic) {
switch (
::InterlockedCompareExchange(&critical_section_init_phase_, 1L, 0L)) {
case 0:
// If critical_section_init_phase_ was 0 before the exchange, we
// are the first to test it and need to perform the initialization.
owner_thread_id_ = 0;
critical_section_ = new CRITICAL_SECTION;
::InitializeCriticalSection(critical_section_);
// Updates the critical_section_init_phase_ to 2 to signal
// initialization complete.
GTEST_CHECK_(::InterlockedCompareExchange(
&critical_section_init_phase_, 2L, 1L) ==
1L);
break;
case 1:
// Somebody else is already initializing the mutex; spin until they
// are done.
while (::InterlockedCompareExchange(&critical_section_init_phase_,
2L,
2L) != 2L) {
// Possibly yields the rest of the thread's time slice to other
// threads.
::Sleep(0);
}
break;
case 2:
break; // The mutex is already initialized and ready for use.
default:
GTEST_CHECK_(false)
<< "Unexpected value of critical_section_init_phase_ "
<< "while initializing a static mutex.";
}
}
}
namespace {
class ThreadWithParamSupport : public ThreadWithParamBase {
public:
static HANDLE CreateThread(Runnable* runnable,
Notification* thread_can_start) {
ThreadMainParam* param = new ThreadMainParam(runnable, thread_can_start);
DWORD thread_id;
// TODO(yukawa): Consider to use _beginthreadex instead.
HANDLE thread_handle = ::CreateThread(
NULL, // Default security.
0, // Default stack size.
&ThreadWithParamSupport::ThreadMain,
param, // Parameter to ThreadMainStatic
0x0, // Default creation flags.
&thread_id); // Need a valid pointer for the call to work under Win98.
GTEST_CHECK_(thread_handle != NULL) << "CreateThread failed with error "
<< ::GetLastError() << ".";
if (thread_handle == NULL) {
delete param;
}
return thread_handle;
}
private:
struct ThreadMainParam {
ThreadMainParam(Runnable* runnable, Notification* thread_can_start)
: runnable_(runnable),
thread_can_start_(thread_can_start) {
}
scoped_ptr<Runnable> runnable_;
// Does not own.
Notification* thread_can_start_;
};
static DWORD WINAPI ThreadMain(void* ptr) {
// Transfers ownership.
scoped_ptr<ThreadMainParam> param(static_cast<ThreadMainParam*>(ptr));
if (param->thread_can_start_ != NULL)
param->thread_can_start_->WaitForNotification();
param->runnable_->Run();
return 0;
}
// Prohibit instantiation.
ThreadWithParamSupport();
GTEST_DISALLOW_COPY_AND_ASSIGN_(ThreadWithParamSupport);
};
} // namespace
ThreadWithParamBase::ThreadWithParamBase(Runnable *runnable,
Notification* thread_can_start)
: thread_(ThreadWithParamSupport::CreateThread(runnable,
thread_can_start)) {
}
ThreadWithParamBase::~ThreadWithParamBase() {
Join();
}
void ThreadWithParamBase::Join() {
GTEST_CHECK_(::WaitForSingleObject(thread_.Get(), INFINITE) == WAIT_OBJECT_0)
<< "Failed to join the thread with error " << ::GetLastError() << ".";
}
// Maps a thread to a set of ThreadIdToThreadLocals that have values
// instantiated on that thread and notifies them when the thread exits. A
// ThreadLocal instance is expected to persist until all threads it has
// values on have terminated.
class ThreadLocalRegistryImpl {
public:
// Registers thread_local_instance as having value on the current thread.
// Returns a value that can be used to identify the thread from other threads.
static ThreadLocalValueHolderBase* GetValueOnCurrentThread(
const ThreadLocalBase* thread_local_instance) {
DWORD current_thread = ::GetCurrentThreadId();
MutexLock lock(&mutex_);
ThreadIdToThreadLocals* const thread_to_thread_locals =
GetThreadLocalsMapLocked();
ThreadIdToThreadLocals::iterator thread_local_pos =
thread_to_thread_locals->find(current_thread);
if (thread_local_pos == thread_to_thread_locals->end()) {
thread_local_pos = thread_to_thread_locals->insert(
std::make_pair(current_thread, ThreadLocalValues())).first;
StartWatcherThreadFor(current_thread);
}
ThreadLocalValues& thread_local_values = thread_local_pos->second;
ThreadLocalValues::iterator value_pos =
thread_local_values.find(thread_local_instance);
if (value_pos == thread_local_values.end()) {
value_pos =
thread_local_values
.insert(std::make_pair(
thread_local_instance,
linked_ptr<ThreadLocalValueHolderBase>(
thread_local_instance->NewValueForCurrentThread())))
.first;
}
return value_pos->second.get();
}
static void OnThreadLocalDestroyed(
const ThreadLocalBase* thread_local_instance) {
std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders;
// Clean up the ThreadLocalValues data structure while holding the lock, but
// defer the destruction of the ThreadLocalValueHolderBases.
{
MutexLock lock(&mutex_);
ThreadIdToThreadLocals* const thread_to_thread_locals =
GetThreadLocalsMapLocked();
for (ThreadIdToThreadLocals::iterator it =
thread_to_thread_locals->begin();
it != thread_to_thread_locals->end();
++it) {
ThreadLocalValues& thread_local_values = it->second;
ThreadLocalValues::iterator value_pos =
thread_local_values.find(thread_local_instance);
if (value_pos != thread_local_values.end()) {
value_holders.push_back(value_pos->second);
thread_local_values.erase(value_pos);
// This 'if' can only be successful at most once, so theoretically we
// could break out of the loop here, but we don't bother doing so.
}
}
}
// Outside the lock, let the destructor for 'value_holders' deallocate the
// ThreadLocalValueHolderBases.
}
static void OnThreadExit(DWORD thread_id) {
GTEST_CHECK_(thread_id != 0) << ::GetLastError();
std::vector<linked_ptr<ThreadLocalValueHolderBase> > value_holders;
// Clean up the ThreadIdToThreadLocals data structure while holding the
// lock, but defer the destruction of the ThreadLocalValueHolderBases.
{
MutexLock lock(&mutex_);
ThreadIdToThreadLocals* const thread_to_thread_locals =
GetThreadLocalsMapLocked();
ThreadIdToThreadLocals::iterator thread_local_pos =
thread_to_thread_locals->find(thread_id);
if (thread_local_pos != thread_to_thread_locals->end()) {
ThreadLocalValues& thread_local_values = thread_local_pos->second;
for (ThreadLocalValues::iterator value_pos =
thread_local_values.begin();
value_pos != thread_local_values.end();
++value_pos) {
value_holders.push_back(value_pos->second);
}
thread_to_thread_locals->erase(thread_local_pos);
}
}
// Outside the lock, let the destructor for 'value_holders' deallocate the
// ThreadLocalValueHolderBases.
}
private:
// In a particular thread, maps a ThreadLocal object to its value.
typedef std::map<const ThreadLocalBase*,
linked_ptr<ThreadLocalValueHolderBase> > ThreadLocalValues;
// Stores all ThreadIdToThreadLocals having values in a thread, indexed by
// thread's ID.
typedef std::map<DWORD, ThreadLocalValues> ThreadIdToThreadLocals;
// Holds the thread id and thread handle that we pass from
// StartWatcherThreadFor to WatcherThreadFunc.
typedef std::pair<DWORD, HANDLE> ThreadIdAndHandle;
static void StartWatcherThreadFor(DWORD thread_id) {
// The returned handle will be kept in thread_map and closed by
// watcher_thread in WatcherThreadFunc.
HANDLE thread = ::OpenThread(SYNCHRONIZE | THREAD_QUERY_INFORMATION,
FALSE,
thread_id);
GTEST_CHECK_(thread != NULL);
// We need to to pass a valid thread ID pointer into CreateThread for it
// to work correctly under Win98.
DWORD watcher_thread_id;
HANDLE watcher_thread = ::CreateThread(
NULL, // Default security.
0, // Default stack size
&ThreadLocalRegistryImpl::WatcherThreadFunc,
reinterpret_cast<LPVOID>(new ThreadIdAndHandle(thread_id, thread)),
CREATE_SUSPENDED,
&watcher_thread_id);
GTEST_CHECK_(watcher_thread != NULL);
// Give the watcher thread the same priority as ours to avoid being
// blocked by it.
::SetThreadPriority(watcher_thread,
::GetThreadPriority(::GetCurrentThread()));
::ResumeThread(watcher_thread);
::CloseHandle(watcher_thread);
}
// Monitors exit from a given thread and notifies those
// ThreadIdToThreadLocals about thread termination.
static DWORD WINAPI WatcherThreadFunc(LPVOID param) {
const ThreadIdAndHandle* tah =
reinterpret_cast<const ThreadIdAndHandle*>(param);
GTEST_CHECK_(
::WaitForSingleObject(tah->second, INFINITE) == WAIT_OBJECT_0);
OnThreadExit(tah->first);
::CloseHandle(tah->second);
delete tah;
return 0;
}
// Returns map of thread local instances.
static ThreadIdToThreadLocals* GetThreadLocalsMapLocked() {
mutex_.AssertHeld();
static ThreadIdToThreadLocals* map = new ThreadIdToThreadLocals;
return map;
}
// Protects access to GetThreadLocalsMapLocked() and its return value.
static Mutex mutex_;
// Protects access to GetThreadMapLocked() and its return value.
static Mutex thread_map_mutex_;
};
Mutex ThreadLocalRegistryImpl::mutex_(Mutex::kStaticMutex);
Mutex ThreadLocalRegistryImpl::thread_map_mutex_(Mutex::kStaticMutex);
ThreadLocalValueHolderBase* ThreadLocalRegistry::GetValueOnCurrentThread(
const ThreadLocalBase* thread_local_instance) {
return ThreadLocalRegistryImpl::GetValueOnCurrentThread(
thread_local_instance);
}
void ThreadLocalRegistry::OnThreadLocalDestroyed(
const ThreadLocalBase* thread_local_instance) {
ThreadLocalRegistryImpl::OnThreadLocalDestroyed(thread_local_instance);
}
#endif // GTEST_IS_THREADSAFE && GTEST_OS_WINDOWS
#if GTEST_USES_POSIX_RE #if GTEST_USES_POSIX_RE
@ -481,7 +887,6 @@ GTEST_API_ ::std::string FormatCompilerIndependentFileLocation(
return file_name + ":" + StreamableToString(line); return file_name + ":" + StreamableToString(line);
} }
GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line) GTestLog::GTestLog(GTestLogSeverity severity, const char* file, int line)
: severity_(severity) { : severity_(severity) {
const char* const marker = const char* const marker =
@ -502,10 +907,7 @@ GTestLog::~GTestLog() {
} }
// Disable Microsoft deprecation warnings for POSIX functions called from // Disable Microsoft deprecation warnings for POSIX functions called from
// this class (creat, dup, dup2, and close) // this class (creat, dup, dup2, and close)
#ifdef _MSC_VER GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
# pragma warning(push)
# pragma warning(disable: 4996)
#endif // _MSC_VER
#if GTEST_HAS_STREAM_REDIRECTION #if GTEST_HAS_STREAM_REDIRECTION
@ -581,12 +983,6 @@ class CapturedStream {
} }
private: private:
// Reads the entire content of a file as an std::string.
static std::string ReadEntireFile(FILE* file);
// Returns the size (in bytes) of a file.
static size_t GetFileSize(FILE* file);
const int fd_; // A stream to capture. const int fd_; // A stream to capture.
int uncaptured_fd_; int uncaptured_fd_;
// Name of the temporary file holding the stderr output. // Name of the temporary file holding the stderr output.
@ -595,38 +991,7 @@ class CapturedStream {
GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream); GTEST_DISALLOW_COPY_AND_ASSIGN_(CapturedStream);
}; };
// Returns the size (in bytes) of a file. GTEST_DISABLE_MSC_WARNINGS_POP_()
size_t CapturedStream::GetFileSize(FILE* file) {
fseek(file, 0, SEEK_END);
return static_cast<size_t>(ftell(file));
}
// Reads the entire content of a file as a string.
std::string CapturedStream::ReadEntireFile(FILE* file) {
const size_t file_size = GetFileSize(file);
char* const buffer = new char[file_size];
size_t bytes_last_read = 0; // # of bytes read in the last fread()
size_t bytes_read = 0; // # of bytes read so far
fseek(file, 0, SEEK_SET);
// Keeps reading the file until we cannot read further or the
// pre-determined file size is reached.
do {
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
bytes_read += bytes_last_read;
} while (bytes_last_read > 0 && bytes_read < file_size);
const std::string content(buffer, bytes_read);
delete[] buffer;
return content;
}
# ifdef _MSC_VER
# pragma warning(pop)
# endif // _MSC_VER
static CapturedStream* g_captured_stderr = NULL; static CapturedStream* g_captured_stderr = NULL;
static CapturedStream* g_captured_stdout = NULL; static CapturedStream* g_captured_stdout = NULL;
@ -672,6 +1037,51 @@ std::string GetCapturedStderr() {
#endif // GTEST_HAS_STREAM_REDIRECTION #endif // GTEST_HAS_STREAM_REDIRECTION
std::string TempDir() {
#if GTEST_OS_WINDOWS_MOBILE
return "\\temp\\";
#elif GTEST_OS_WINDOWS
const char* temp_dir = posix::GetEnv("TEMP");
if (temp_dir == NULL || temp_dir[0] == '\0')
return "\\temp\\";
else if (temp_dir[strlen(temp_dir) - 1] == '\\')
return temp_dir;
else
return std::string(temp_dir) + "\\";
#elif GTEST_OS_LINUX_ANDROID
return "/sdcard/";
#else
return "/tmp/";
#endif // GTEST_OS_WINDOWS_MOBILE
}
size_t GetFileSize(FILE* file) {
fseek(file, 0, SEEK_END);
return static_cast<size_t>(ftell(file));
}
std::string ReadEntireFile(FILE* file) {
const size_t file_size = GetFileSize(file);
char* const buffer = new char[file_size];
size_t bytes_last_read = 0; // # of bytes read in the last fread()
size_t bytes_read = 0; // # of bytes read so far
fseek(file, 0, SEEK_SET);
// Keeps reading the file until we cannot read further or the
// pre-determined file size is reached.
do {
bytes_last_read = fread(buffer+bytes_read, 1, file_size-bytes_read, file);
bytes_read += bytes_last_read;
} while (bytes_last_read > 0 && bytes_read < file_size);
const std::string content(buffer, bytes_read);
delete[] buffer;
return content;
}
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
// A copy of all command line arguments. Set by InitGoogleTest(). // A copy of all command line arguments. Set by InitGoogleTest().

View File

@ -45,6 +45,7 @@
#include "gtest/gtest-printers.h" #include "gtest/gtest-printers.h"
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <cwchar>
#include <ostream> // NOLINT #include <ostream> // NOLINT
#include <string> #include <string>
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
@ -58,6 +59,7 @@ using ::std::ostream;
// Prints a segment of bytes in the given object. // Prints a segment of bytes in the given object.
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start, void PrintByteSegmentInObjectTo(const unsigned char* obj_bytes, size_t start,
size_t count, ostream* os) { size_t count, ostream* os) {
char text[5] = ""; char text[5] = "";
@ -256,6 +258,7 @@ void PrintTo(wchar_t wc, ostream* os) {
template <typename CharType> template <typename CharType>
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static void PrintCharsAsStringTo( static void PrintCharsAsStringTo(
const CharType* begin, size_t len, ostream* os) { const CharType* begin, size_t len, ostream* os) {
const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\""; const char* const kQuoteBegin = sizeof(CharType) == 1 ? "\"" : "L\"";
@ -279,6 +282,7 @@ static void PrintCharsAsStringTo(
template <typename CharType> template <typename CharType>
GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_ GTEST_ATTRIBUTE_NO_SANITIZE_MEMORY_
GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_ GTEST_ATTRIBUTE_NO_SANITIZE_ADDRESS_
GTEST_ATTRIBUTE_NO_SANITIZE_THREAD_
static void UniversalPrintCharArray( static void UniversalPrintCharArray(
const CharType* begin, size_t len, ostream* os) { const CharType* begin, size_t len, ostream* os) {
// The code // The code
@ -335,7 +339,7 @@ void PrintTo(const wchar_t* s, ostream* os) {
*os << "NULL"; *os << "NULL";
} else { } else {
*os << ImplicitCast_<const void*>(s) << " pointing to "; *os << ImplicitCast_<const void*>(s) << " pointing to ";
PrintCharsAsStringTo(s, wcslen(s), os); PrintCharsAsStringTo(s, std::wcslen(s), os);
} }
} }
#endif // wchar_t is native #endif // wchar_t is native

View File

@ -35,9 +35,9 @@
// Indicates that this translation unit is part of Google Test's // Indicates that this translation unit is part of Google Test's
// implementation. It must come before gtest-internal-inl.h is // implementation. It must come before gtest-internal-inl.h is
// included, or there will be a compiler error. This trick is to // included, or there will be a compiler error. This trick exists to
// prevent a user from accidentally including gtest-internal-inl.h in // prevent the accidental inclusion of gtest-internal-inl.h in the
// his code. // user's code.
#define GTEST_IMPLEMENTATION_ 1 #define GTEST_IMPLEMENTATION_ 1
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
#undef GTEST_IMPLEMENTATION_ #undef GTEST_IMPLEMENTATION_

View File

@ -45,33 +45,41 @@ static const char* SkipSpaces(const char* str) {
return str; return str;
} }
static std::vector<std::string> SplitIntoTestNames(const char* src) {
std::vector<std::string> name_vec;
src = SkipSpaces(src);
for (; src != NULL; src = SkipComma(src)) {
name_vec.push_back(StripTrailingSpaces(GetPrefixUntilComma(src)));
}
return name_vec;
}
// 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 // registered_tests_; returns registered_tests if successful, or
// aborts the program otherwise. // aborts the program otherwise.
const char* TypedTestCasePState::VerifyRegisteredTestNames( const char* TypedTestCasePState::VerifyRegisteredTestNames(
const char* file, int line, const char* registered_tests) { const char* file, int line, const char* registered_tests) {
typedef ::std::set<const char*>::const_iterator DefinedTestIter; typedef RegisteredTestsMap::const_iterator RegisteredTestIter;
registered_ = true; registered_ = true;
// Skip initial whitespace in registered_tests since some std::vector<std::string> name_vec = SplitIntoTestNames(registered_tests);
// preprocessors prefix stringizied literals with whitespace.
registered_tests = SkipSpaces(registered_tests);
Message errors; Message errors;
::std::set<std::string> tests;
for (const char* names = registered_tests; names != NULL; std::set<std::string> tests;
names = SkipComma(names)) { for (std::vector<std::string>::const_iterator name_it = name_vec.begin();
const std::string name = GetPrefixUntilComma(names); name_it != name_vec.end(); ++name_it) {
const std::string& name = *name_it;
if (tests.count(name) != 0) { if (tests.count(name) != 0) {
errors << "Test " << name << " is listed more than once.\n"; errors << "Test " << name << " is listed more than once.\n";
continue; continue;
} }
bool found = false; bool found = false;
for (DefinedTestIter it = defined_test_names_.begin(); for (RegisteredTestIter it = registered_tests_.begin();
it != defined_test_names_.end(); it != registered_tests_.end();
++it) { ++it) {
if (name == *it) { if (name == it->first) {
found = true; found = true;
break; break;
} }
@ -85,11 +93,11 @@ const char* TypedTestCasePState::VerifyRegisteredTestNames(
} }
} }
for (DefinedTestIter it = defined_test_names_.begin(); for (RegisteredTestIter it = registered_tests_.begin();
it != defined_test_names_.end(); it != registered_tests_.end();
++it) { ++it) {
if (tests.count(*it) == 0) { if (tests.count(it->first) == 0) {
errors << "You forgot to list test " << *it << ".\n"; errors << "You forgot to list test " << it->first << ".\n";
} }
} }

View File

@ -32,6 +32,7 @@
// The Google C++ Testing Framework (Google Test) // The Google C++ Testing Framework (Google Test)
#include "gtest/gtest.h" #include "gtest/gtest.h"
#include "gtest/internal/custom/gtest.h"
#include "gtest/gtest-spi.h" #include "gtest/gtest-spi.h"
#include <ctype.h> #include <ctype.h>
@ -46,6 +47,8 @@
#include <algorithm> #include <algorithm>
#include <iomanip> #include <iomanip>
#include <limits> #include <limits>
#include <list>
#include <map>
#include <ostream> // NOLINT #include <ostream> // NOLINT
#include <sstream> #include <sstream>
#include <vector> #include <vector>
@ -80,6 +83,7 @@
#elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE. #elif GTEST_OS_WINDOWS_MOBILE // We are on Windows CE.
# include <windows.h> // NOLINT # include <windows.h> // NOLINT
# undef min
#elif GTEST_OS_WINDOWS // We are on Windows proper. #elif GTEST_OS_WINDOWS // We are on Windows proper.
@ -102,6 +106,7 @@
// cpplint thinks that the header is already included, so we want to // cpplint thinks that the header is already included, so we want to
// silence it. // silence it.
# include <windows.h> // NOLINT # include <windows.h> // NOLINT
# undef min
#else #else
@ -124,6 +129,8 @@
#if GTEST_CAN_STREAM_RESULTS_ #if GTEST_CAN_STREAM_RESULTS_
# include <arpa/inet.h> // NOLINT # include <arpa/inet.h> // NOLINT
# include <netdb.h> // NOLINT # include <netdb.h> // NOLINT
# include <sys/socket.h> // NOLINT
# include <sys/types.h> // NOLINT
#endif #endif
// Indicates that this translation unit is part of Google Test's // Indicates that this translation unit is part of Google Test's
@ -183,6 +190,12 @@ bool g_help_flag = false;
} // namespace internal } // namespace internal
static const char* GetDefaultFilter() { static const char* GetDefaultFilter() {
#ifdef GTEST_TEST_FILTER_ENV_VAR_
const char* const testbridge_test_only = getenv(GTEST_TEST_FILTER_ENV_VAR_);
if (testbridge_test_only != NULL) {
return testbridge_test_only;
}
#endif // GTEST_TEST_FILTER_ENV_VAR_
return kUniversalFilter; return kUniversalFilter;
} }
@ -283,6 +296,13 @@ GTEST_DEFINE_bool_(
"if exceptions are enabled or exit the program with a non-zero code " "if exceptions are enabled or exit the program with a non-zero code "
"otherwise."); "otherwise.");
#if GTEST_USE_OWN_FLAGFILE_FLAG_
GTEST_DEFINE_string_(
flagfile,
internal::StringFromGTestEnv("flagfile", ""),
"This flag specifies the flagfile to read command-line flags from.");
#endif // GTEST_USE_OWN_FLAGFILE_FLAG_
namespace internal { namespace internal {
// Generates a random number from [0, range), using a Linear // Generates a random number from [0, range), using a Linear
@ -772,8 +792,12 @@ int UnitTestImpl::test_to_run_count() const {
// CurrentOsStackTraceExceptTop(1), Foo() will be included in the // CurrentOsStackTraceExceptTop(1), Foo() will be included in the
// trace but Bar() and CurrentOsStackTraceExceptTop() won't. // trace but Bar() and CurrentOsStackTraceExceptTop() won't.
std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) { std::string UnitTestImpl::CurrentOsStackTraceExceptTop(int skip_count) {
(void)skip_count; return os_stack_trace_getter()->CurrentStackTrace(
return ""; static_cast<int>(GTEST_FLAG(stack_trace_depth)),
skip_count + 1
// Skips the user-specified number of frames plus this function
// itself.
); // NOLINT
} }
// Returns the current time in milliseconds. // Returns the current time in milliseconds.
@ -802,21 +826,13 @@ TimeInMillis GetTimeInMillis() {
#elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_ #elif GTEST_OS_WINDOWS && !GTEST_HAS_GETTIMEOFDAY_
__timeb64 now; __timeb64 now;
# ifdef _MSC_VER
// MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996 // MSVC 8 deprecates _ftime64(), so we want to suppress warning 4996
// (deprecated function) there. // (deprecated function) there.
// TODO(kenton@google.com): Use GetTickCount()? Or use // TODO(kenton@google.com): Use GetTickCount()? Or use
// SystemTimeToFileTime() // SystemTimeToFileTime()
# pragma warning(push) // Saves the current warning state. GTEST_DISABLE_MSC_WARNINGS_PUSH_(4996)
# pragma warning(disable:4996) // Temporarily disables warning 4996.
_ftime64(&now); _ftime64(&now);
# pragma warning(pop) // Restores the warning state. GTEST_DISABLE_MSC_WARNINGS_POP_()
# else
_ftime64(&now);
# endif // _MSC_VER
return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm; return static_cast<TimeInMillis>(now.time) * 1000 + now.millitm;
#elif GTEST_HAS_GETTIMEOFDAY_ #elif GTEST_HAS_GETTIMEOFDAY_
@ -901,6 +917,23 @@ static void StreamWideCharsToMessage(const wchar_t* wstr, size_t length,
#endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING #endif // GTEST_HAS_STD_WSTRING || GTEST_HAS_GLOBAL_WSTRING
void SplitString(const ::std::string& str, char delimiter,
::std::vector< ::std::string>* dest) {
::std::vector< ::std::string> parsed;
::std::string::size_type pos = 0;
while (::testing::internal::AlwaysTrue()) {
const ::std::string::size_type colon = str.find(delimiter, pos);
if (colon == ::std::string::npos) {
parsed.push_back(str.substr(pos));
break;
} else {
parsed.push_back(str.substr(pos, colon - pos));
pos = colon + 1;
}
}
dest->swap(parsed);
}
} // namespace internal } // namespace internal
// Constructs an empty Message. // Constructs an empty Message.
@ -956,6 +989,13 @@ AssertionResult::AssertionResult(const AssertionResult& other)
static_cast< ::std::string*>(NULL)) { static_cast< ::std::string*>(NULL)) {
} }
// Swaps two AssertionResults.
void AssertionResult::swap(AssertionResult& other) {
using std::swap;
swap(success_, other.success_);
swap(message_, other.message_);
}
// Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE. // Returns the assertion's negation. Used with EXPECT/ASSERT_FALSE.
AssertionResult AssertionResult::operator!() const { AssertionResult AssertionResult::operator!() const {
AssertionResult negation(!success_); AssertionResult negation(!success_);
@ -982,6 +1022,276 @@ AssertionResult AssertionFailure(const Message& message) {
namespace internal { namespace internal {
namespace edit_distance {
std::vector<EditType> CalculateOptimalEdits(const std::vector<size_t>& left,
const std::vector<size_t>& right) {
std::vector<std::vector<double> > costs(
left.size() + 1, std::vector<double>(right.size() + 1));
std::vector<std::vector<EditType> > best_move(
left.size() + 1, std::vector<EditType>(right.size() + 1));
// Populate for empty right.
for (size_t l_i = 0; l_i < costs.size(); ++l_i) {
costs[l_i][0] = static_cast<double>(l_i);
best_move[l_i][0] = kRemove;
}
// Populate for empty left.
for (size_t r_i = 1; r_i < costs[0].size(); ++r_i) {
costs[0][r_i] = static_cast<double>(r_i);
best_move[0][r_i] = kAdd;
}
for (size_t l_i = 0; l_i < left.size(); ++l_i) {
for (size_t r_i = 0; r_i < right.size(); ++r_i) {
if (left[l_i] == right[r_i]) {
// Found a match. Consume it.
costs[l_i + 1][r_i + 1] = costs[l_i][r_i];
best_move[l_i + 1][r_i + 1] = kMatch;
continue;
}
const double add = costs[l_i + 1][r_i];
const double remove = costs[l_i][r_i + 1];
const double replace = costs[l_i][r_i];
if (add < remove && add < replace) {
costs[l_i + 1][r_i + 1] = add + 1;
best_move[l_i + 1][r_i + 1] = kAdd;
} else if (remove < add && remove < replace) {
costs[l_i + 1][r_i + 1] = remove + 1;
best_move[l_i + 1][r_i + 1] = kRemove;
} else {
// We make replace a little more expensive than add/remove to lower
// their priority.
costs[l_i + 1][r_i + 1] = replace + 1.00001;
best_move[l_i + 1][r_i + 1] = kReplace;
}
}
}
// Reconstruct the best path. We do it in reverse order.
std::vector<EditType> best_path;
for (size_t l_i = left.size(), r_i = right.size(); l_i > 0 || r_i > 0;) {
EditType move = best_move[l_i][r_i];
best_path.push_back(move);
l_i -= move != kAdd;
r_i -= move != kRemove;
}
std::reverse(best_path.begin(), best_path.end());
return best_path;
}
namespace {
// Helper class to convert string into ids with deduplication.
class InternalStrings {
public:
size_t GetId(const std::string& str) {
IdMap::iterator it = ids_.find(str);
if (it != ids_.end()) return it->second;
size_t id = ids_.size();
return ids_[str] = id;
}
private:
typedef std::map<std::string, size_t> IdMap;
IdMap ids_;
};
} // namespace
std::vector<EditType> CalculateOptimalEdits(
const std::vector<std::string>& left,
const std::vector<std::string>& right) {
std::vector<size_t> left_ids, right_ids;
{
InternalStrings intern_table;
for (size_t i = 0; i < left.size(); ++i) {
left_ids.push_back(intern_table.GetId(left[i]));
}
for (size_t i = 0; i < right.size(); ++i) {
right_ids.push_back(intern_table.GetId(right[i]));
}
}
return CalculateOptimalEdits(left_ids, right_ids);
}
namespace {
// Helper class that holds the state for one hunk and prints it out to the
// stream.
// It reorders adds/removes when possible to group all removes before all
// adds. It also adds the hunk header before printint into the stream.
class Hunk {
public:
Hunk(size_t left_start, size_t right_start)
: left_start_(left_start),
right_start_(right_start),
adds_(),
removes_(),
common_() {}
void PushLine(char edit, const char* line) {
switch (edit) {
case ' ':
++common_;
FlushEdits();
hunk_.push_back(std::make_pair(' ', line));
break;
case '-':
++removes_;
hunk_removes_.push_back(std::make_pair('-', line));
break;
case '+':
++adds_;
hunk_adds_.push_back(std::make_pair('+', line));
break;
}
}
void PrintTo(std::ostream* os) {
PrintHeader(os);
FlushEdits();
for (std::list<std::pair<char, const char*> >::const_iterator it =
hunk_.begin();
it != hunk_.end(); ++it) {
*os << it->first << it->second << "\n";
}
}
bool has_edits() const { return adds_ || removes_; }
private:
void FlushEdits() {
hunk_.splice(hunk_.end(), hunk_removes_);
hunk_.splice(hunk_.end(), hunk_adds_);
}
// Print a unified diff header for one hunk.
// The format is
// "@@ -<left_start>,<left_length> +<right_start>,<right_length> @@"
// where the left/right parts are ommitted if unnecessary.
void PrintHeader(std::ostream* ss) const {
*ss << "@@ ";
if (removes_) {
*ss << "-" << left_start_ << "," << (removes_ + common_);
}
if (removes_ && adds_) {
*ss << " ";
}
if (adds_) {
*ss << "+" << right_start_ << "," << (adds_ + common_);
}
*ss << " @@\n";
}
size_t left_start_, right_start_;
size_t adds_, removes_, common_;
std::list<std::pair<char, const char*> > hunk_, hunk_adds_, hunk_removes_;
};
} // namespace
// Create a list of diff hunks in Unified diff format.
// Each hunk has a header generated by PrintHeader above plus a body with
// lines prefixed with ' ' for no change, '-' for deletion and '+' for
// addition.
// 'context' represents the desired unchanged prefix/suffix around the diff.
// If two hunks are close enough that their contexts overlap, then they are
// joined into one hunk.
std::string CreateUnifiedDiff(const std::vector<std::string>& left,
const std::vector<std::string>& right,
size_t context) {
const std::vector<EditType> edits = CalculateOptimalEdits(left, right);
size_t l_i = 0, r_i = 0, edit_i = 0;
std::stringstream ss;
while (edit_i < edits.size()) {
// Find first edit.
while (edit_i < edits.size() && edits[edit_i] == kMatch) {
++l_i;
++r_i;
++edit_i;
}
// Find the first line to include in the hunk.
const size_t prefix_context = std::min(l_i, context);
Hunk hunk(l_i - prefix_context + 1, r_i - prefix_context + 1);
for (size_t i = prefix_context; i > 0; --i) {
hunk.PushLine(' ', left[l_i - i].c_str());
}
// Iterate the edits until we found enough suffix for the hunk or the input
// is over.
size_t n_suffix = 0;
for (; edit_i < edits.size(); ++edit_i) {
if (n_suffix >= context) {
// Continue only if the next hunk is very close.
std::vector<EditType>::const_iterator it = edits.begin() + edit_i;
while (it != edits.end() && *it == kMatch) ++it;
if (it == edits.end() || (it - edits.begin()) - edit_i >= context) {
// There is no next edit or it is too far away.
break;
}
}
EditType edit = edits[edit_i];
// Reset count when a non match is found.
n_suffix = edit == kMatch ? n_suffix + 1 : 0;
if (edit == kMatch || edit == kRemove || edit == kReplace) {
hunk.PushLine(edit == kMatch ? ' ' : '-', left[l_i].c_str());
}
if (edit == kAdd || edit == kReplace) {
hunk.PushLine('+', right[r_i].c_str());
}
// Advance indices, depending on edit type.
l_i += edit != kAdd;
r_i += edit != kRemove;
}
if (!hunk.has_edits()) {
// We are done. We don't want this hunk.
break;
}
hunk.PrintTo(&ss);
}
return ss.str();
}
} // namespace edit_distance
namespace {
// The string representation of the values received in EqFailure() are already
// escaped. Split them on escaped '\n' boundaries. Leave all other escaped
// characters the same.
std::vector<std::string> SplitEscapedString(const std::string& str) {
std::vector<std::string> lines;
size_t start = 0, end = str.size();
if (end > 2 && str[0] == '"' && str[end - 1] == '"') {
++start;
--end;
}
bool escaped = false;
for (size_t i = start; i + 1 < end; ++i) {
if (escaped) {
escaped = false;
if (str[i] == 'n') {
lines.push_back(str.substr(start, i - start - 1));
start = i + 1;
}
} else {
escaped = str[i] == '\\';
}
}
lines.push_back(str.substr(start, end - start));
return lines;
}
} // namespace
// Constructs and returns the message for an equality assertion // Constructs and returns the message for an equality assertion
// (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure. // (e.g. ASSERT_EQ, EXPECT_STREQ, etc) failure.
// //
@ -1016,6 +1326,17 @@ AssertionResult EqFailure(const char* expected_expression,
msg << "\nWhich is: " << expected_value; msg << "\nWhich is: " << expected_value;
} }
if (!expected_value.empty() && !actual_value.empty()) {
const std::vector<std::string> expected_lines =
SplitEscapedString(expected_value);
const std::vector<std::string> actual_lines =
SplitEscapedString(actual_value);
if (expected_lines.size() > 1 || actual_lines.size() > 1) {
msg << "\nWith diff:\n"
<< edit_distance::CreateUnifiedDiff(expected_lines, actual_lines);
}
}
return AssertionFailure() << msg; return AssertionFailure() << msg;
} }
@ -1887,14 +2208,15 @@ int TestResult::test_property_count() const {
// Creates a Test object. // Creates a Test object.
// The c'tor saves the values of all Google Test flags. // The c'tor saves the states of all flags.
Test::Test() Test::Test()
: gtest_flag_saver_(new internal::GTestFlagSaver) { : gtest_flag_saver_(new GTEST_FLAG_SAVER_) {
} }
// The d'tor restores the values of all Google Test flags. // The d'tor restores the states of all flags. The actual work is
// done by the d'tor of the gtest_flag_saver_ field, and thus not
// visible here.
Test::~Test() { Test::~Test() {
delete gtest_flag_saver_;
} }
// Sets up the test fixture. // Sets up the test fixture.
@ -1963,8 +2285,8 @@ bool Test::HasSameFixtureClass() {
const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId();
if (first_is_TEST || this_is_TEST) { if (first_is_TEST || this_is_TEST) {
// The user mixed TEST and TEST_F in this test case - we'll tell // Both TEST and TEST_F appear in same test case, which is incorrect.
// him/her how to fix it. // Tell the user how to fix this.
// Gets the name of the TEST and the name of the TEST_F. Note // Gets the name of the TEST and the name of the TEST_F. Note
// that first_is_TEST and this_is_TEST cannot both be true, as // that first_is_TEST and this_is_TEST cannot both be true, as
@ -1984,8 +2306,8 @@ bool Test::HasSameFixtureClass() {
<< "want to change the TEST to TEST_F or move it to another test\n" << "want to change the TEST to TEST_F or move it to another test\n"
<< "case."; << "case.";
} else { } else {
// The user defined two fixture classes with the same name in // Two fixture classes with the same name appear in two different
// two namespaces - we'll tell him/her how to fix it. // namespaces, which is not allowed. Tell the user how to fix this.
ADD_FAILURE() ADD_FAILURE()
<< "All tests in the same test case must use the same test fixture\n" << "All tests in the same test case must use the same test fixture\n"
<< "class. However, in test case " << "class. However, in test case "
@ -2178,12 +2500,14 @@ TestInfo::TestInfo(const std::string& a_test_case_name,
const std::string& a_name, const std::string& a_name,
const char* a_type_param, const char* a_type_param,
const char* a_value_param, const char* a_value_param,
internal::CodeLocation a_code_location,
internal::TypeId fixture_class_id, internal::TypeId fixture_class_id,
internal::TestFactoryBase* factory) internal::TestFactoryBase* factory)
: test_case_name_(a_test_case_name), : test_case_name_(a_test_case_name),
name_(a_name), name_(a_name),
type_param_(a_type_param ? new std::string(a_type_param) : NULL), type_param_(a_type_param ? new std::string(a_type_param) : NULL),
value_param_(a_value_param ? new std::string(a_value_param) : NULL), value_param_(a_value_param ? new std::string(a_value_param) : NULL),
location_(a_code_location),
fixture_class_id_(fixture_class_id), fixture_class_id_(fixture_class_id),
should_run_(false), should_run_(false),
is_disabled_(false), is_disabled_(false),
@ -2207,6 +2531,7 @@ namespace internal {
// 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 value-parameterized test. // or NULL if this is not a value-parameterized test.
// 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 case // 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 // tear_down_tc: pointer to the function that tears down the test case
@ -2218,20 +2543,21 @@ TestInfo* MakeAndRegisterTestInfo(
const char* name, const char* name,
const char* type_param, const char* type_param,
const char* value_param, const char* value_param,
CodeLocation code_location,
TypeId fixture_class_id, TypeId fixture_class_id,
SetUpTestCaseFunc set_up_tc, SetUpTestCaseFunc set_up_tc,
TearDownTestCaseFunc tear_down_tc, TearDownTestCaseFunc tear_down_tc,
TestFactoryBase* factory) { TestFactoryBase* factory) {
TestInfo* const test_info = TestInfo* const test_info =
new TestInfo(test_case_name, name, type_param, value_param, new TestInfo(test_case_name, name, type_param, value_param,
fixture_class_id, factory); code_location, fixture_class_id, factory);
GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info); GetUnitTestImpl()->AddTestInfo(set_up_tc, tear_down_tc, test_info);
return test_info; return test_info;
} }
#if GTEST_HAS_PARAM_TEST #if GTEST_HAS_PARAM_TEST
void ReportInvalidTestCaseType(const char* test_case_name, void ReportInvalidTestCaseType(const char* test_case_name,
const char* file, int line) { CodeLocation code_location) {
Message errors; Message errors;
errors errors
<< "Attempted redefinition of test case " << test_case_name << ".\n" << "Attempted redefinition of test case " << test_case_name << ".\n"
@ -2243,7 +2569,9 @@ void ReportInvalidTestCaseType(const char* test_case_name,
<< "probably rename one of the classes to put the tests into different\n" << "probably rename one of the classes to put the tests into different\n"
<< "test cases."; << "test cases.";
fprintf(stderr, "%s %s", FormatFileLocation(file, line).c_str(), fprintf(stderr, "%s %s",
FormatFileLocation(code_location.file.c_str(),
code_location.line).c_str(),
errors.GetString().c_str()); errors.GetString().c_str());
} }
#endif // GTEST_HAS_PARAM_TEST #endif // GTEST_HAS_PARAM_TEST
@ -2554,7 +2882,8 @@ enum GTestColor {
COLOR_YELLOW COLOR_YELLOW
}; };
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \
!GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
// Returns the character attribute for the given color. // Returns the character attribute for the given color.
WORD GetColorAttribute(GTestColor color) { WORD GetColorAttribute(GTestColor color) {
@ -2599,6 +2928,8 @@ bool ShouldUseColor(bool stdout_is_tty) {
String::CStringEquals(term, "xterm-256color") || String::CStringEquals(term, "xterm-256color") ||
String::CStringEquals(term, "screen") || String::CStringEquals(term, "screen") ||
String::CStringEquals(term, "screen-256color") || String::CStringEquals(term, "screen-256color") ||
String::CStringEquals(term, "rxvt-unicode") ||
String::CStringEquals(term, "rxvt-unicode-256color") ||
String::CStringEquals(term, "linux") || String::CStringEquals(term, "linux") ||
String::CStringEquals(term, "cygwin"); String::CStringEquals(term, "cygwin");
return stdout_is_tty && term_supports_color; return stdout_is_tty && term_supports_color;
@ -2622,8 +2953,9 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
#if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || GTEST_OS_IOS #if GTEST_OS_WINDOWS_MOBILE || GTEST_OS_SYMBIAN || GTEST_OS_ZOS || \
const bool use_color = false; GTEST_OS_IOS || GTEST_OS_WINDOWS_PHONE || GTEST_OS_WINDOWS_RT
const bool use_color = AlwaysFalse();
#else #else
static const bool in_color_mode = static const bool in_color_mode =
ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0); ShouldUseColor(posix::IsATTY(posix::FileNo(stdout)) != 0);
@ -2637,7 +2969,8 @@ void ColoredPrintf(GTestColor color, const char* fmt, ...) {
return; return;
} }
#if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE #if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_MOBILE && \
!GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE); const HANDLE stdout_handle = GetStdHandle(STD_OUTPUT_HANDLE);
// Gets the current text color. // Gets the current text color.
@ -3212,34 +3545,39 @@ std::string XmlUnitTestResultPrinter::RemoveInvalidXmlCharacters(
// Formats the given time in milliseconds as seconds. // Formats the given time in milliseconds as seconds.
std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) { std::string FormatTimeInMillisAsSeconds(TimeInMillis ms) {
::std::stringstream ss; ::std::stringstream ss;
ss << ms/1000.0; ss << (static_cast<double>(ms) * 1e-3);
return ss.str(); return ss.str();
} }
static bool PortableLocaltime(time_t seconds, struct tm* out) {
#if defined(_MSC_VER)
return localtime_s(out, &seconds) == 0;
#elif defined(__MINGW32__) || defined(__MINGW64__)
// MINGW <time.h> provides neither localtime_r nor localtime_s, but uses
// Windows' localtime(), which has a thread-local tm buffer.
struct tm* tm_ptr = localtime(&seconds); // NOLINT
if (tm_ptr == NULL)
return false;
*out = *tm_ptr;
return true;
#else
return localtime_r(&seconds, out) != NULL;
#endif
}
// Converts the given epoch time in milliseconds to a date string in the ISO // Converts the given epoch time in milliseconds to a date string in the ISO
// 8601 format, without the timezone information. // 8601 format, without the timezone information.
std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) { std::string FormatEpochTimeInMillisAsIso8601(TimeInMillis ms) {
// Using non-reentrant version as localtime_r is not portable. struct tm time_struct;
time_t seconds = static_cast<time_t>(ms / 1000); if (!PortableLocaltime(static_cast<time_t>(ms / 1000), &time_struct))
#ifdef _MSC_VER return "";
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4996) // Temporarily disables warning 4996
// (function or variable may be unsafe).
const struct tm* const time_struct = localtime(&seconds); // NOLINT
# pragma warning(pop) // Restores the warning state again.
#else
const struct tm* const time_struct = localtime(&seconds); // NOLINT
#endif
if (time_struct == NULL)
return ""; // Invalid ms value
// YYYY-MM-DDThh:mm:ss // YYYY-MM-DDThh:mm:ss
return StreamableToString(time_struct->tm_year + 1900) + "-" + return StreamableToString(time_struct.tm_year + 1900) + "-" +
String::FormatIntWidth2(time_struct->tm_mon + 1) + "-" + String::FormatIntWidth2(time_struct.tm_mon + 1) + "-" +
String::FormatIntWidth2(time_struct->tm_mday) + "T" + String::FormatIntWidth2(time_struct.tm_mday) + "T" +
String::FormatIntWidth2(time_struct->tm_hour) + ":" + String::FormatIntWidth2(time_struct.tm_hour) + ":" +
String::FormatIntWidth2(time_struct->tm_min) + ":" + String::FormatIntWidth2(time_struct.tm_min) + ":" +
String::FormatIntWidth2(time_struct->tm_sec); String::FormatIntWidth2(time_struct.tm_sec);
} }
// Streams an XML CDATA section, escaping invalid CDATA sequences as needed. // Streams an XML CDATA section, escaping invalid CDATA sequences as needed.
@ -3502,26 +3840,15 @@ ScopedTrace::~ScopedTrace()
// class OsStackTraceGetter // class OsStackTraceGetter
// Returns the current OS stack trace as an std::string. Parameters: const char* const OsStackTraceGetterInterface::kElidedFramesMarker =
// "... " GTEST_NAME_ " internal frames ...";
// max_depth - the maximum number of stack frames to be included
// in the trace. string OsStackTraceGetter::CurrentStackTrace(int /*max_depth*/,
// skip_count - the number of top frames to be skipped; doesn't count int /*skip_count*/) {
// against max_depth.
//
string OsStackTraceGetter::CurrentStackTrace(int /* max_depth */,
int /* skip_count */)
GTEST_LOCK_EXCLUDED_(mutex_) {
return ""; return "";
} }
void OsStackTraceGetter::UponLeavingGTest() void OsStackTraceGetter::UponLeavingGTest() {}
GTEST_LOCK_EXCLUDED_(mutex_) {
}
const char* const
OsStackTraceGetter::kElidedFramesMarker =
"... " GTEST_NAME_ " internal frames ...";
// A helper class that creates the premature-exit file in its // A helper class that creates the premature-exit file in its
// constructor and deletes the file in its destructor. // constructor and deletes the file in its destructor.
@ -3812,7 +4139,7 @@ void UnitTest::AddTestPartResult(
// with another testing framework) and specify the former on the // with another testing framework) and specify the former on the
// command line for debugging. // command line for debugging.
if (GTEST_FLAG(break_on_failure)) { if (GTEST_FLAG(break_on_failure)) {
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
// Using DebugBreak on Windows allows gtest to still break into a debugger // Using DebugBreak on Windows allows gtest to still break into a debugger
// when a failure happens and both the --gtest_break_on_failure and // when a failure happens and both the --gtest_break_on_failure and
// the --gtest_catch_exceptions flags are specified. // the --gtest_catch_exceptions flags are specified.
@ -3890,7 +4217,7 @@ int UnitTest::Run() {
// process. In either case the user does not want to see pop-up dialogs // process. In either case the user does not want to see pop-up dialogs
// about crashes - they are expected. // about crashes - they are expected.
if (impl()->catch_exceptions() || in_death_test_child_process) { if (impl()->catch_exceptions() || in_death_test_child_process) {
# if !GTEST_OS_WINDOWS_MOBILE # if !GTEST_OS_WINDOWS_MOBILE && !GTEST_OS_WINDOWS_PHONE && !GTEST_OS_WINDOWS_RT
// SetErrorMode doesn't exist on CE. // SetErrorMode doesn't exist on CE.
SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT | SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOALIGNMENTFAULTEXCEPT |
SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);
@ -3993,17 +4320,10 @@ namespace internal {
UnitTestImpl::UnitTestImpl(UnitTest* parent) UnitTestImpl::UnitTestImpl(UnitTest* parent)
: parent_(parent), : parent_(parent),
#ifdef _MSC_VER GTEST_DISABLE_MSC_WARNINGS_PUSH_(4355 /* using this in initializer */)
# pragma warning(push) // Saves the current warning state.
# pragma warning(disable:4355) // Temporarily disables warning 4355
// (using this in initializer).
default_global_test_part_result_reporter_(this), default_global_test_part_result_reporter_(this),
default_per_thread_test_part_result_reporter_(this), default_per_thread_test_part_result_reporter_(this),
# pragma warning(pop) // Restores the warning state again. GTEST_DISABLE_MSC_WARNINGS_POP_()
#else
default_global_test_part_result_reporter_(this),
default_per_thread_test_part_result_reporter_(this),
#endif // _MSC_VER
global_test_part_result_repoter_( global_test_part_result_repoter_(
&default_global_test_part_result_reporter_), &default_global_test_part_result_reporter_),
per_thread_test_part_result_reporter_( per_thread_test_part_result_reporter_(
@ -4583,7 +4903,11 @@ void UnitTestImpl::set_os_stack_trace_getter(
// getter, and returns it. // getter, and returns it.
OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() { OsStackTraceGetterInterface* UnitTestImpl::os_stack_trace_getter() {
if (os_stack_trace_getter_ == NULL) { if (os_stack_trace_getter_ == NULL) {
#ifdef GTEST_OS_STACK_TRACE_GETTER_
os_stack_trace_getter_ = new GTEST_OS_STACK_TRACE_GETTER_;
#else
os_stack_trace_getter_ = new OsStackTraceGetter; os_stack_trace_getter_ = new OsStackTraceGetter;
#endif // GTEST_OS_STACK_TRACE_GETTER_
} }
return os_stack_trace_getter_; return os_stack_trace_getter_;
@ -4882,21 +5206,8 @@ static const char kColorEncodedHelpMessage[] =
"(not one in your own code or tests), please report it to\n" "(not one in your own code or tests), please report it to\n"
"@G<" GTEST_DEV_EMAIL_ ">@D.\n"; "@G<" GTEST_DEV_EMAIL_ ">@D.\n";
// Parses the command line for Google Test flags, without initializing bool ParseGoogleTestFlag(const char* const arg) {
// other parts of Google Test. The type parameter CharType can be return ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
// instantiated to either char or wchar_t.
template <typename CharType>
void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
for (int i = 1; i < *argc; i++) {
const std::string arg_string = StreamableToString(argv[i]);
const char* const arg = arg_string.c_str();
using internal::ParseBoolFlag;
using internal::ParseInt32Flag;
using internal::ParseStringFlag;
// Do we see a Google Test flag?
if (ParseBoolFlag(arg, kAlsoRunDisabledTestsFlag,
&GTEST_FLAG(also_run_disabled_tests)) || &GTEST_FLAG(also_run_disabled_tests)) ||
ParseBoolFlag(arg, kBreakOnFailureFlag, ParseBoolFlag(arg, kBreakOnFailureFlag,
&GTEST_FLAG(break_on_failure)) || &GTEST_FLAG(break_on_failure)) ||
@ -4921,9 +5232,63 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
ParseStringFlag(arg, kStreamResultToFlag, ParseStringFlag(arg, kStreamResultToFlag,
&GTEST_FLAG(stream_result_to)) || &GTEST_FLAG(stream_result_to)) ||
ParseBoolFlag(arg, kThrowOnFailureFlag, ParseBoolFlag(arg, kThrowOnFailureFlag,
&GTEST_FLAG(throw_on_failure)) &GTEST_FLAG(throw_on_failure));
) { }
// Yes. Shift the remainder of the argv list left by one. Note
#if GTEST_USE_OWN_FLAGFILE_FLAG_
void LoadFlagsFromFile(const std::string& path) {
FILE* flagfile = posix::FOpen(path.c_str(), "r");
if (!flagfile) {
fprintf(stderr,
"Unable to open file \"%s\"\n",
GTEST_FLAG(flagfile).c_str());
fflush(stderr);
exit(EXIT_FAILURE);
}
std::string contents(ReadEntireFile(flagfile));
posix::FClose(flagfile);
std::vector<std::string> lines;
SplitString(contents, '\n', &lines);
for (size_t i = 0; i < lines.size(); ++i) {
if (lines[i].empty())
continue;
if (!ParseGoogleTestFlag(lines[i].c_str()))
g_help_flag = true;
}
}
#endif // GTEST_USE_OWN_FLAGFILE_FLAG_
// Parses the command line for Google Test flags, without initializing
// other parts of Google Test. The type parameter CharType can be
// instantiated to either char or wchar_t.
template <typename CharType>
void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
for (int i = 1; i < *argc; i++) {
const std::string arg_string = StreamableToString(argv[i]);
const char* const arg = arg_string.c_str();
using internal::ParseBoolFlag;
using internal::ParseInt32Flag;
using internal::ParseStringFlag;
bool remove_flag = false;
if (ParseGoogleTestFlag(arg)) {
remove_flag = true;
#if GTEST_USE_OWN_FLAGFILE_FLAG_
} else if (ParseStringFlag(arg, kFlagfileFlag, &GTEST_FLAG(flagfile))) {
LoadFlagsFromFile(GTEST_FLAG(flagfile));
remove_flag = true;
#endif // GTEST_USE_OWN_FLAGFILE_FLAG_
} else if (arg_string == "--help" || arg_string == "-h" ||
arg_string == "-?" || arg_string == "/?" ||
HasGoogleTestFlagPrefix(arg)) {
// Both help flag and unrecognized Google Test flags (excluding
// internal ones) trigger help display.
g_help_flag = true;
}
if (remove_flag) {
// Shift the remainder of the argv list left by one. Note
// that argv has (*argc + 1) elements, the last one always being // that argv has (*argc + 1) elements, the last one always being
// NULL. The following loop moves the trailing NULL element as // NULL. The following loop moves the trailing NULL element as
// well. // well.
@ -4937,12 +5302,6 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
// We also need to decrement the iterator as we just removed // We also need to decrement the iterator as we just removed
// an element. // an element.
i--; i--;
} else if (arg_string == "--help" || arg_string == "-h" ||
arg_string == "-?" || arg_string == "/?" ||
HasGoogleTestFlagPrefix(arg)) {
// Both help flag and unrecognized Google Test flags (excluding
// internal ones) trigger help display.
g_help_flag = true;
} }
} }