Externals: Update gtest to r733
This commit is contained in:
parent
3d6ee7313d
commit
67d0e81cf3
|
@ -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.
|
|
@ -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, \
|
||||||
>est_##prefix##test_case_name##_EvalGenerator_, \
|
>est_##prefix##test_case_name##_EvalGenerator_, \
|
||||||
__FILE__, __LINE__)
|
__FILE__, __LINE__)
|
||||||
|
|
|
@ -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, \
|
||||||
>est_##prefix##test_case_name##_EvalGenerator_, \
|
>est_##prefix##test_case_name##_EvalGenerator_, \
|
||||||
__FILE__, __LINE__)
|
__FILE__, __LINE__)
|
||||||
|
|
|
@ -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_
|
||||||
|
|
|
@ -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__), \
|
||||||
|
>EST_TYPED_TEST_CASE_P_STATE_(CaseName), \
|
||||||
|
#CaseName, GTEST_REGISTERED_TEST_NAMES_(CaseName))
|
||||||
|
|
||||||
#endif // GTEST_HAS_TYPED_TEST_P
|
#endif // GTEST_HAS_TYPED_TEST_P
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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_
|
|
@ -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_
|
|
@ -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_
|
|
@ -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 Wagner–Fischer 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_
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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_),
|
||||||
|
|
|
@ -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,[[
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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().
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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_
|
||||||
|
|
|
@ -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";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
|
||||||
>EST_FLAG(also_run_disabled_tests)) ||
|
>EST_FLAG(also_run_disabled_tests)) ||
|
||||||
ParseBoolFlag(arg, kBreakOnFailureFlag,
|
ParseBoolFlag(arg, kBreakOnFailureFlag,
|
||||||
>EST_FLAG(break_on_failure)) ||
|
>EST_FLAG(break_on_failure)) ||
|
||||||
|
@ -4921,9 +5232,63 @@ void ParseGoogleTestFlagsOnlyImpl(int* argc, CharType** argv) {
|
||||||
ParseStringFlag(arg, kStreamResultToFlag,
|
ParseStringFlag(arg, kStreamResultToFlag,
|
||||||
>EST_FLAG(stream_result_to)) ||
|
>EST_FLAG(stream_result_to)) ||
|
||||||
ParseBoolFlag(arg, kThrowOnFailureFlag,
|
ParseBoolFlag(arg, kThrowOnFailureFlag,
|
||||||
>EST_FLAG(throw_on_failure))
|
>EST_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, >EST_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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue