aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/gtest/gtest.h7
-rw-r--r--include/gtest/internal/gtest-port.h6
-rw-r--r--scons/SConscript2
-rw-r--r--src/gtest-internal-inl.h11
-rw-r--r--src/gtest-port.cc21
-rw-r--r--src/gtest.cc18
-rw-r--r--test/gtest-port_test.cc43
-rw-r--r--test/gtest_unittest.cc85
8 files changed, 189 insertions, 4 deletions
diff --git a/include/gtest/gtest.h b/include/gtest/gtest.h
index 6d87e035..26d76b26 100644
--- a/include/gtest/gtest.h
+++ b/include/gtest/gtest.h
@@ -272,6 +272,13 @@ class Test {
// Returns true iff the current test has a fatal failure.
static bool HasFatalFailure();
+ // Returns true iff the current test has a non-fatal failure.
+ static bool HasNonfatalFailure();
+
+ // Returns true iff the current test has a (either fatal or
+ // non-fatal) failure.
+ static bool HasFailure() { return HasFatalFailure() || HasNonfatalFailure(); }
+
// Logs a property for the current test. Only the last value for a given
// key is remembered.
// These are public static so they can be called from utility functions
diff --git a/include/gtest/internal/gtest-port.h b/include/gtest/internal/gtest-port.h
index 97736314..4267a58f 100644
--- a/include/gtest/internal/gtest-port.h
+++ b/include/gtest/internal/gtest-port.h
@@ -673,9 +673,9 @@ class ThreadLocal {
T value_;
};
-// There's no portable way to detect the number of threads, so we just
-// return 0 to indicate that we cannot detect it.
-inline size_t GetThreadCount() { return 0; }
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount();
// The above synchronization primitives have dummy implementations.
// Therefore Google Test is not thread-safe.
diff --git a/scons/SConscript b/scons/SConscript
index 91bf985b..6a7cc137 100644
--- a/scons/SConscript
+++ b/scons/SConscript
@@ -273,6 +273,8 @@ if env.get('GTEST_BUILD_SAMPLES', False):
GtestSample(env, 'sample2_unittest', gtest_main,
additional_sources=['../samples/sample2.cc'])
GtestSample(env, 'sample3_unittest', gtest_main)
+ GtestSample(env, 'sample4_unittest', gtest_main,
+ additional_sources=['../samples/sample4.cc'])
GtestSample(env, 'sample5_unittest', gtest_main,
additional_sources=[sample1_obj])
GtestSample(env, 'sample6_unittest', gtest_main)
diff --git a/src/gtest-internal-inl.h b/src/gtest-internal-inl.h
index dfc1e958..2a90edac 100644
--- a/src/gtest-internal-inl.h
+++ b/src/gtest-internal-inl.h
@@ -548,6 +548,9 @@ class TestResult {
// Returns true iff the test fatally failed.
bool HasFatalFailure() const;
+ // Returns true iff the test has a non-fatal failure.
+ bool HasNonfatalFailure() const;
+
// Returns the elapsed time, in milliseconds.
TimeInMillis elapsed_time() const { return elapsed_time_; }
@@ -575,6 +578,9 @@ class TestResult {
// Increments the death test count, returning the new count.
int increment_death_test_count() { return ++death_test_count_; }
+ // Clears the test part results.
+ void ClearTestPartResults() { test_part_results_.Clear(); }
+
// Clears the object.
void Clear();
private:
@@ -1300,6 +1306,11 @@ inline UnitTestImpl* GetUnitTestImpl() {
return UnitTest::GetInstance()->impl();
}
+// Clears all test part results of the current test.
+inline void ClearCurrentTestPartResults() {
+ GetUnitTestImpl()->current_test_result()->ClearTestPartResults();
+}
+
// Internal helper functions for implementing the simple regular
// expression matcher.
bool IsInSet(char ch, const char* str);
diff --git a/src/gtest-port.cc b/src/gtest-port.cc
index 166ff414..193f5323 100644
--- a/src/gtest-port.cc
+++ b/src/gtest-port.cc
@@ -42,6 +42,11 @@
#include <unistd.h>
#endif // GTEST_OS_WINDOWS
+#if GTEST_OS_MAC
+#include <mach/mach_init.h>
+#include <mach/task.h>
+#endif // GTEST_OS_MAC
+
#ifdef _WIN32_WCE
#include <windows.h> // For TerminateProcess()
#endif // _WIN32_WCE
@@ -69,6 +74,22 @@ const int kStdErrFileno = 2;
const int kStdErrFileno = STDERR_FILENO;
#endif // _MSC_VER
+// Returns the number of threads running in the process, or 0 to indicate that
+// we cannot detect it.
+size_t GetThreadCount() {
+#if GTEST_OS_MAC
+ mach_msg_type_number_t thread_count;
+ thread_act_port_array_t thread_list;
+ kern_return_t status = task_threads(mach_task_self(),
+ &thread_list, &thread_count);
+ return status == KERN_SUCCESS ? static_cast<size_t>(thread_count) : 0;
+#else
+ // There's no portable way to detect the number of threads, so we just
+ // return 0 to indicate that we cannot detect it.
+ return 0;
+#endif // GTEST_OS_MAC
+}
+
#if GTEST_USES_POSIX_RE
// Implements RE. Currently only needed for death tests.
diff --git a/src/gtest.cc b/src/gtest.cc
index ac5ed9d5..5903f2ae 100644
--- a/src/gtest.cc
+++ b/src/gtest.cc
@@ -1852,7 +1852,7 @@ int TestResult::failed_part_count() const {
}
// Returns true iff the test part fatally failed.
-static bool TestPartFatallyFailed(const TestPartResult & result) {
+static bool TestPartFatallyFailed(const TestPartResult& result) {
return result.fatally_failed();
}
@@ -1861,6 +1861,16 @@ bool TestResult::HasFatalFailure() const {
return test_part_results_.CountIf(TestPartFatallyFailed) > 0;
}
+// Returns true iff the test part non-fatally failed.
+static bool TestPartNonfatallyFailed(const TestPartResult& result) {
+ return result.nonfatally_failed();
+}
+
+// Returns true iff the test has a non-fatal failure.
+bool TestResult::HasNonfatalFailure() const {
+ return test_part_results_.CountIf(TestPartNonfatallyFailed) > 0;
+}
+
// Gets the number of all test parts. This is the sum of the number
// of successful test parts and the number of failed test parts.
int TestResult::total_part_count() const {
@@ -2059,6 +2069,12 @@ bool Test::HasFatalFailure() {
return internal::GetUnitTestImpl()->current_test_result()->HasFatalFailure();
}
+// Returns true iff the current test has a non-fatal failure.
+bool Test::HasNonfatalFailure() {
+ return internal::GetUnitTestImpl()->current_test_result()->
+ HasNonfatalFailure();
+}
+
// class TestInfo
// Constructs a TestInfo object. It assumes ownership of the test factory
diff --git a/test/gtest-port_test.cc b/test/gtest-port_test.cc
index 0bda6f5e..f4560f19 100644
--- a/test/gtest-port_test.cc
+++ b/test/gtest-port_test.cc
@@ -32,6 +32,11 @@
// This file tests the internal cross-platform support utilities.
#include <gtest/internal/gtest-port.h>
+
+#if GTEST_OS_MAC
+#include <pthread.h>
+#endif // GTEST_OS_MAC
+
#include <gtest/gtest.h>
#include <gtest/gtest-spi.h>
@@ -76,6 +81,44 @@ TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
GTEST_CHECK_(true) << "Check failed in switch case";
}
+#if GTEST_OS_MAC
+void* ThreadFunc(void* data) {
+ pthread_mutex_t* mutex = reinterpret_cast<pthread_mutex_t*>(data);
+ pthread_mutex_lock(mutex);
+ pthread_mutex_unlock(mutex);
+ return NULL;
+}
+
+TEST(GetThreadCountTest, ReturnsCorrectValue) {
+ EXPECT_EQ(1, GetThreadCount());
+ pthread_mutex_t mutex;
+ pthread_attr_t attr;
+ pthread_t thread_id;
+
+ // TODO(vladl@google.com): turn mutex into internal::Mutex for automatic
+ // destruction.
+ pthread_mutex_init(&mutex, NULL);
+ pthread_mutex_lock(&mutex);
+ ASSERT_EQ(0, pthread_attr_init(&attr));
+ ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
+
+ const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex);
+ ASSERT_EQ(0, pthread_attr_destroy(&attr));
+ ASSERT_EQ(0, status);
+ EXPECT_EQ(2, GetThreadCount());
+ pthread_mutex_unlock(&mutex);
+
+ void* dummy;
+ ASSERT_EQ(0, pthread_join(thread_id, &dummy));
+ EXPECT_EQ(1, GetThreadCount());
+ pthread_mutex_destroy(&mutex);
+}
+#else
+TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) {
+ EXPECT_EQ(0, GetThreadCount());
+}
+#endif // GTEST_OS_MAC
+
#if GTEST_HAS_DEATH_TEST
TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
diff --git a/test/gtest_unittest.cc b/test/gtest_unittest.cc
index 8e4b813c..d1c517b5 100644
--- a/test/gtest_unittest.cc
+++ b/test/gtest_unittest.cc
@@ -131,6 +131,7 @@ using testing::TPRT_SUCCESS;
using testing::UnitTest;
using testing::internal::kTestTypeIdInGoogleTest;
using testing::internal::AppendUserMessage;
+using testing::internal::ClearCurrentTestPartResults;
using testing::internal::CodePointToUtf8;
using testing::internal::EqFailure;
using testing::internal::FloatingPoint;
@@ -5456,3 +5457,87 @@ TEST(GetCurrentOsStackTraceExceptTopTest, ReturnsTheStackTrace) {
EXPECT_STREQ("", GetCurrentOsStackTraceExceptTop(unit_test, 0).c_str());
EXPECT_STREQ("", GetCurrentOsStackTraceExceptTop(unit_test, 1).c_str());
}
+
+TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsNoFailure) {
+ EXPECT_FALSE(HasNonfatalFailure());
+}
+
+static void FailFatally() { FAIL(); }
+
+TEST(HasNonfatalFailureTest, ReturnsFalseWhenThereIsOnlyFatalFailure) {
+ FailFatally();
+ const bool has_nonfatal_failure = HasNonfatalFailure();
+ ClearCurrentTestPartResults();
+ EXPECT_FALSE(has_nonfatal_failure);
+}
+
+TEST(HasNonfatalFailureTest, ReturnsTrueWhenThereIsNonfatalFailure) {
+ ADD_FAILURE();
+ const bool has_nonfatal_failure = HasNonfatalFailure();
+ ClearCurrentTestPartResults();
+ EXPECT_TRUE(has_nonfatal_failure);
+}
+
+TEST(HasNonfatalFailureTest, ReturnsTrueWhenThereAreFatalAndNonfatalFailures) {
+ FailFatally();
+ ADD_FAILURE();
+ const bool has_nonfatal_failure = HasNonfatalFailure();
+ ClearCurrentTestPartResults();
+ EXPECT_TRUE(has_nonfatal_failure);
+}
+
+// A wrapper for calling HasNonfatalFailure outside of a test body.
+static bool HasNonfatalFailureHelper() {
+ return testing::Test::HasNonfatalFailure();
+}
+
+TEST(HasNonfatalFailureTest, WorksOutsideOfTestBody) {
+ EXPECT_FALSE(HasNonfatalFailureHelper());
+}
+
+TEST(HasNonfatalFailureTest, WorksOutsideOfTestBody2) {
+ ADD_FAILURE();
+ const bool has_nonfatal_failure = HasNonfatalFailureHelper();
+ ClearCurrentTestPartResults();
+ EXPECT_TRUE(has_nonfatal_failure);
+}
+
+TEST(HasFailureTest, ReturnsFalseWhenThereIsNoFailure) {
+ EXPECT_FALSE(HasFailure());
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereIsFatalFailure) {
+ FailFatally();
+ const bool has_failure = HasFailure();
+ ClearCurrentTestPartResults();
+ EXPECT_TRUE(has_failure);
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereIsNonfatalFailure) {
+ ADD_FAILURE();
+ const bool has_failure = HasFailure();
+ ClearCurrentTestPartResults();
+ EXPECT_TRUE(has_failure);
+}
+
+TEST(HasFailureTest, ReturnsTrueWhenThereAreFatalAndNonfatalFailures) {
+ FailFatally();
+ ADD_FAILURE();
+ const bool has_failure = HasFailure();
+ ClearCurrentTestPartResults();
+ EXPECT_TRUE(has_failure);
+}
+
+// A wrapper for calling HasFailure outside of a test body.
+static bool HasFailureHelper() { return testing::Test::HasFailure(); }
+
+TEST(HasFailureTest, WorksOutsideOfTestBody) {
+ EXPECT_FALSE(HasFailureHelper());
+}
+
+TEST(HasFailureTest, WorksOutsideOfTestBody2) {
+ ADD_FAILURE();
+ const bool has_failure = HasFailureHelper();
+ ClearCurrentTestPartResults();
+ EXPECT_TRUE(has_failure);
+}