aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.ac6
-rw-r--r--include/gtest/gtest.h15
-rw-r--r--include/gtest/internal/gtest-internal.h37
-rw-r--r--src/gtest-internal-inl.h4
-rw-r--r--src/gtest.cc21
-rw-r--r--test/gtest_unittest.cc28
6 files changed, 95 insertions, 16 deletions
diff --git a/configure.ac b/configure.ac
index 9a61217a..e19bbef7 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 dae26473..38fcd7d8 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<test_fixture>())
// 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 d439c00b..9e353b63 100644
--- a/include/gtest/internal/gtest-internal.h
+++ b/include/gtest/internal/gtest-internal.h
@@ -485,20 +485,39 @@ typedef FloatingPoint<double> 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 <typename T>
+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<T>::dummy_ for different Ts as an "optimization".
+ static bool dummy_;
+};
+
+template <typename T>
+bool TypeIdHelper<T>::dummy_ = false;
// GetTypeId<T>() 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 <typename T>
-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<T>::dummy_ variable for each T used to instantiate
+ // the template. Therefore, the address of dummy_ is guaranteed to
+ // be unique.
+ return &(TypeIdHelper<T>::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 0f2bcfba..faf9464d 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 4a67b7a2..968efb22 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<Test>();
+}
+
+// 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<Test>();
+ 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<Test>();
+ 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 0864d6eb..d926a744 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<int>(), GetTypeId<int>());
+ EXPECT_EQ(GetTypeId<Test>(), GetTypeId<Test>());
+}
+
+class SubClassOfTest : public Test {};
+class AnotherSubClassOfTest : public Test {};
+
+TEST(GetTypeIdTest, ReturnsDifferentValuesForDifferentTypes) {
+ EXPECT_NE(GetTypeId<int>(), GetTypeId<const int>());
+ EXPECT_NE(GetTypeId<int>(), GetTypeId<char>());
+ EXPECT_NE(GetTypeId<int>(), GetTestTypeId());
+ EXPECT_NE(GetTypeId<SubClassOfTest>(), GetTestTypeId());
+ EXPECT_NE(GetTypeId<AnotherSubClassOfTest>(), GetTestTypeId());
+ EXPECT_NE(GetTypeId<AnotherSubClassOfTest>(), GetTypeId<SubClassOfTest>());
+}
+
+// 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) {