From c440a6923aa65d5be64134a6f430a5867a63df3f Mon Sep 17 00:00:00 2001 From: shiqian Date: Mon, 24 Nov 2008 20:13:22 +0000 Subject: Enables the Python tests to run with 2.3 (necessary for testing on Mac OS X Tiger); also fixes gtest_output_test when built with xcode. --- configure.ac | 6 +++--- include/gtest/gtest.h | 15 +++++++++++-- include/gtest/internal/gtest-internal.h | 37 +++++++++++++++++++++++++-------- src/gtest-internal-inl.h | 4 ++++ src/gtest.cc | 21 +++++++++++++++++-- test/gtest_unittest.cc | 28 +++++++++++++++++++++++++ 6 files changed, 95 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 9a61217..e19bbef 100644 --- a/configure.ac +++ b/configure.ac @@ -29,13 +29,13 @@ AC_PROG_LIBTOOL # TODO(chandlerc@google.com): Currently we aren't running the Python tests # against the interpreter detected by AM_PATH_PYTHON, and so we condition # HAVE_PYTHON by requiring "python" to be in the PATH, and that interpreter's -# version to be >= 2.4. This will allow the scripts to use a "/usr/bin/env" +# version to be >= 2.3. This will allow the scripts to use a "/usr/bin/env" # hashbang. -#AM_PATH_PYTHON([2.4],,[:]) +#AM_PATH_PYTHON([2.3],,[:]) PYTHON= # We *do not* allow the user to specify a python interpreter AC_PATH_PROG([PYTHON],[python],[:]) AS_IF([test "$PYTHON" != ":"], - [AM_PYTHON_CHECK_VERSION([$PYTHON],[2.4],[:],[PYTHON=":"])]) + [AM_PYTHON_CHECK_VERSION([$PYTHON],[2.3],[:],[PYTHON=":"])]) AM_CONDITIONAL([HAVE_PYTHON],[test "$PYTHON" != ":"]) # TODO(chandlerc@google.com) Check for the necessary system headers. diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h index dae2647..38fcd7d 100644 --- a/include/gtest/gtest.h +++ b/include/gtest/gtest.h @@ -1259,8 +1259,18 @@ AssertionResult DoubleLE(const char* expr1, const char* expr2, // EXPECT_TRUE(foo.StatusIsOK()); // } +// Note that we call GetTestTypeId() instead of GetTypeId< +// ::testing::Test>() here to get the type ID of testing::Test. This +// is to work around a suspected linker bug when using Google Test as +// a framework on Mac OS X. The bug causes GetTypeId< +// ::testing::Test>() to return different values depending on whether +// the call is from the Google Test framework itself or from user test +// code. GetTestTypeId() is guaranteed to always return the same +// value, as it always calls GetTypeId<>() from the Google Test +// framework. #define TEST(test_case_name, test_name)\ - GTEST_TEST_(test_case_name, test_name, ::testing::Test) + GTEST_TEST_(test_case_name, test_name,\ + ::testing::Test, ::testing::internal::GetTestTypeId()) // Defines a test that uses a test fixture. @@ -1290,7 +1300,8 @@ AssertionResult DoubleLE(const char* expr1, const char* expr2, // } #define TEST_F(test_fixture, test_name)\ - GTEST_TEST_(test_fixture, test_name, test_fixture) + GTEST_TEST_(test_fixture, test_name, test_fixture,\ + ::testing::internal::GetTypeId()) // Use this macro in main() to run all tests. It returns 0 if all // tests are successful, or 1 otherwise. diff --git a/include/gtest/internal/gtest-internal.h b/include/gtest/internal/gtest-internal.h index d439c00..9e353b6 100644 --- a/include/gtest/internal/gtest-internal.h +++ b/include/gtest/internal/gtest-internal.h @@ -485,20 +485,39 @@ typedef FloatingPoint Double; // used to hold such IDs. The user should treat TypeId as an opaque // type: the only operation allowed on TypeId values is to compare // them for equality using the == operator. -typedef void* TypeId; +typedef const void* TypeId; + +template +class TypeIdHelper { + public: + // dummy_ must not have a const type. Otherwise an overly eager + // compiler (e.g. MSVC 7.1 & 8.0) may try to merge + // TypeIdHelper::dummy_ for different Ts as an "optimization". + static bool dummy_; +}; + +template +bool TypeIdHelper::dummy_ = false; // GetTypeId() returns the ID of type T. Different values will be // returned for different types. Calling the function twice with the // same type argument is guaranteed to return the same ID. template -inline TypeId GetTypeId() { - static bool dummy = false; - // The compiler is required to create an instance of the static - // variable dummy for each T used to instantiate the template. - // Therefore, the address of dummy is guaranteed to be unique. - return &dummy; +TypeId GetTypeId() { + // The compiler is required to allocate a different + // TypeIdHelper::dummy_ variable for each T used to instantiate + // the template. Therefore, the address of dummy_ is guaranteed to + // be unique. + return &(TypeIdHelper::dummy_); } +// Returns the type ID of ::testing::Test. Always call this instead +// of GetTypeId< ::testing::Test>() to get the type ID of +// ::testing::Test, as the latter may give the wrong result due to a +// suspected linker bug when compiling Google Test as a Mac OS X +// framework. +TypeId GetTestTypeId(); + // Defines the abstract factory interface that creates instances // of a Test object. class TestFactoryBase { @@ -829,7 +848,7 @@ int GetFailedPartCount(const TestResult* result); test_case_name##_##test_name##_Test // Helper macro for defining tests. -#define GTEST_TEST_(test_case_name, test_name, parent_class)\ +#define GTEST_TEST_(test_case_name, test_name, parent_class, parent_id)\ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ public:\ GTEST_TEST_CLASS_NAME_(test_case_name, test_name)() {}\ @@ -844,7 +863,7 @@ class GTEST_TEST_CLASS_NAME_(test_case_name, test_name) : public parent_class {\ ::test_info_ =\ ::testing::internal::MakeAndRegisterTestInfo(\ #test_case_name, #test_name, "", "", \ - ::testing::internal::GetTypeId< parent_class >(), \ + (parent_id), \ parent_class::SetUpTestCase, \ parent_class::TearDownTestCase, \ new ::testing::internal::TestFactoryImpl<\ diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h index 0f2bcfb..faf9464 100644 --- a/src/gtest-internal-inl.h +++ b/src/gtest-internal-inl.h @@ -76,6 +76,10 @@ GTEST_DECLARE_bool_(show_internal_stack_frames); namespace internal { +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +extern const TypeId kTestTypeIdInGoogleTest; + // Names of the flags (needed for parsing Google Test flags). const char kBreakOnFailureFlag[] = "break_on_failure"; const char kCatchExceptionsFlag[] = "catch_exceptions"; diff --git a/src/gtest.cc b/src/gtest.cc index 4a67b7a..968efb2 100644 --- a/src/gtest.cc +++ b/src/gtest.cc @@ -515,6 +515,23 @@ void ScopedFakeTestPartResultReporter::ReportTestPartResult( namespace internal { +// Returns the type ID of ::testing::Test. We should always call this +// instead of GetTypeId< ::testing::Test>() to get the type ID of +// testing::Test. This is to work around a suspected linker bug when +// using Google Test as a framework on Mac OS X. The bug causes +// GetTypeId< ::testing::Test>() to return different values depending +// on whether the call is from the Google Test framework itself or +// from user test code. GetTestTypeId() is guaranteed to always +// return the same value, as it always calls GetTypeId<>() from the +// gtest.cc, which is within the Google Test framework. +TypeId GetTestTypeId() { + return GetTypeId(); +} + +// The value of GetTestTypeId() as seen from within the Google Test +// library. This is solely for testing GetTestTypeId(). +extern const TypeId kTestTypeIdInGoogleTest = GetTestTypeId(); + // This predicate-formatter checks that 'results' contains a test part // failure of the given type and that the failure message contains the // given substring. @@ -1924,9 +1941,9 @@ bool Test::HasSameFixtureClass() { if (this_fixture_id != first_fixture_id) { // Is the first test defined using TEST? - const bool first_is_TEST = first_fixture_id == internal::GetTypeId(); + const bool first_is_TEST = first_fixture_id == internal::GetTestTypeId(); // Is this test defined using TEST? - const bool this_is_TEST = this_fixture_id == internal::GetTypeId(); + const bool this_is_TEST = this_fixture_id == internal::GetTestTypeId(); if (first_is_TEST || this_is_TEST) { // The user mixed TEST and TEST_F in this test case - we'll tell diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc index 0864d6e..d926a74 100644 --- a/test/gtest_unittest.cc +++ b/test/gtest_unittest.cc @@ -105,12 +105,15 @@ using testing::TPRT_FATAL_FAILURE; using testing::TPRT_NONFATAL_FAILURE; using testing::TPRT_SUCCESS; using testing::UnitTest; +using testing::internal::kTestTypeIdInGoogleTest; using testing::internal::AppendUserMessage; using testing::internal::CodePointToUtf8; using testing::internal::EqFailure; using testing::internal::FloatingPoint; using testing::internal::GetCurrentOsStackTraceExceptTop; using testing::internal::GetFailedPartCount; +using testing::internal::GetTestTypeId; +using testing::internal::GetTypeId; using testing::internal::GTestFlagSaver; using testing::internal::Int32; using testing::internal::List; @@ -126,6 +129,31 @@ using testing::internal::WideStringToUtf8; // This line tests that we can define tests in an unnamed namespace. namespace { +// Tests GetTypeId. + +TEST(GetTypeIdTest, ReturnsSameValueForSameType) { + EXPECT_EQ(GetTypeId(), GetTypeId()); + EXPECT_EQ(GetTypeId(), GetTypeId()); +} + +class SubClassOfTest : public Test {}; +class AnotherSubClassOfTest : public Test {}; + +TEST(GetTypeIdTest, ReturnsDifferentValuesForDifferentTypes) { + EXPECT_NE(GetTypeId(), GetTypeId()); + EXPECT_NE(GetTypeId(), GetTypeId()); + EXPECT_NE(GetTypeId(), GetTestTypeId()); + EXPECT_NE(GetTypeId(), GetTestTypeId()); + EXPECT_NE(GetTypeId(), GetTestTypeId()); + EXPECT_NE(GetTypeId(), GetTypeId()); +} + +// Verifies that GetTestTypeId() returns the same value, no matter it +// is called from inside Google Test or outside of it. +TEST(GetTestTypeIdTest, ReturnsTheSameValueInsideOrOutsideOfGoogleTest) { + EXPECT_EQ(kTestTypeIdInGoogleTest, GetTestTypeId()); +} + // Tests FormatTimeInMillisAsSeconds(). TEST(FormatTimeInMillisAsSecondsTest, FormatsZero) { -- cgit v0.12