"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "googletest/test/googletest-port-test.cc" between
googletest-release-1.11.0.tar.gz and googletest-release-1.12.0.tar.gz

About: GoogleTest is Google's (unit) testing and mocking framework for C++ tests.

googletest-port-test.cc  (googletest-release-1.11.0):googletest-port-test.cc  (googletest-release-1.12.0)
skipping to change at line 36 skipping to change at line 36
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// //
// This file tests the internal cross-platform support utilities. // This file tests the internal cross-platform support utilities.
#include <stdio.h> #include <stdio.h>
#include "gtest/internal/gtest-port.h" #include "gtest/internal/gtest-port.h"
#if GTEST_OS_MAC #if GTEST_OS_MAC
# include <time.h> #include <time.h>
#endif // GTEST_OS_MAC #endif // GTEST_OS_MAC
#include <chrono> // NOLINT
#include <list> #include <list>
#include <memory> #include <memory>
#include <thread> // NOLINT
#include <utility> // For std::pair and std::make_pair. #include <utility> // For std::pair and std::make_pair.
#include <vector> #include <vector>
#include "gtest/gtest.h"
#include "gtest/gtest-spi.h" #include "gtest/gtest-spi.h"
#include "gtest/gtest.h"
#include "src/gtest-internal-inl.h" #include "src/gtest-internal-inl.h"
using std::make_pair; using std::make_pair;
using std::pair; using std::pair;
namespace testing { namespace testing {
namespace internal { namespace internal {
TEST(IsXDigitTest, WorksForNarrowAscii) { TEST(IsXDigitTest, WorksForNarrowAscii) {
EXPECT_TRUE(IsXDigit('0')); EXPECT_TRUE(IsXDigit('0'));
skipping to change at line 239 skipping to change at line 241
TEST(GtestCheckSyntaxTest, WorksWithSwitch) { TEST(GtestCheckSyntaxTest, WorksWithSwitch) {
switch (0) { switch (0) {
case 1: case 1:
break; break;
default: default:
GTEST_CHECK_(true); GTEST_CHECK_(true);
} }
switch (0) switch (0)
case 0: case 0:
GTEST_CHECK_(true) << "Check failed in switch case"; GTEST_CHECK_(true) << "Check failed in switch case";
} }
// Verifies behavior of FormatFileLocation. // Verifies behavior of FormatFileLocation.
TEST(FormatFileLocationTest, FormatsFileLocation) { TEST(FormatFileLocationTest, FormatsFileLocation) {
EXPECT_PRED_FORMAT2(IsSubstring, "foo.cc", FormatFileLocation("foo.cc", 42)); EXPECT_PRED_FORMAT2(IsSubstring, "foo.cc", FormatFileLocation("foo.cc", 42));
EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation("foo.cc", 42)); EXPECT_PRED_FORMAT2(IsSubstring, "42", FormatFileLocation("foo.cc", 42));
} }
TEST(FormatFileLocationTest, FormatsUnknownFile) { TEST(FormatFileLocationTest, FormatsUnknownFile) {
EXPECT_PRED_FORMAT2(IsSubstring, "unknown file", EXPECT_PRED_FORMAT2(IsSubstring, "unknown file",
skipping to change at line 282 skipping to change at line 284
TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownLine) { TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownLine) {
EXPECT_EQ("foo.cc", FormatCompilerIndependentFileLocation("foo.cc", -1)); EXPECT_EQ("foo.cc", FormatCompilerIndependentFileLocation("foo.cc", -1));
} }
TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) { TEST(FormatCompilerIndependentFileLocationTest, FormatsUknownFileAndLine) {
EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(nullptr, -1)); EXPECT_EQ("unknown file", FormatCompilerIndependentFileLocation(nullptr, -1));
} }
#if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA || \ #if GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA || \
GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \ GTEST_OS_DRAGONFLY || GTEST_OS_FREEBSD || GTEST_OS_GNU_KFREEBSD || \
GTEST_OS_NETBSD || GTEST_OS_OPENBSD GTEST_OS_NETBSD || GTEST_OS_OPENBSD || GTEST_OS_GNU_HURD
void* ThreadFunc(void* data) { void* ThreadFunc(void* data) {
internal::Mutex* mutex = static_cast<internal::Mutex*>(data); internal::Mutex* mutex = static_cast<internal::Mutex*>(data);
mutex->Lock(); mutex->Lock();
mutex->Unlock(); mutex->Unlock();
return nullptr; return nullptr;
} }
TEST(GetThreadCountTest, ReturnsCorrectValue) { TEST(GetThreadCountTest, ReturnsCorrectValue) {
const size_t starting_count = GetThreadCount(); size_t starting_count;
pthread_t thread_id; size_t thread_count_after_create;
size_t thread_count_after_join;
// We can't guarantee that no other thread was created or destroyed between
// any two calls to GetThreadCount(). We make multiple attempts, hoping that
// background noise is not constant and we would see the "right" values at
// some point.
for (int attempt = 0; attempt < 20; ++attempt) {
starting_count = GetThreadCount();
pthread_t thread_id;
internal::Mutex mutex; internal::Mutex mutex;
{ {
internal::MutexLock lock(&mutex); internal::MutexLock lock(&mutex);
pthread_attr_t attr; pthread_attr_t attr;
ASSERT_EQ(0, pthread_attr_init(&attr)); ASSERT_EQ(0, pthread_attr_init(&attr));
ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE)); ASSERT_EQ(0, pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE));
const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex); const int status = pthread_create(&thread_id, &attr, &ThreadFunc, &mutex);
ASSERT_EQ(0, pthread_attr_destroy(&attr)); ASSERT_EQ(0, pthread_attr_destroy(&attr));
ASSERT_EQ(0, status); ASSERT_EQ(0, status);
EXPECT_EQ(starting_count + 1, GetThreadCount()); }
}
void* dummy; thread_count_after_create = GetThreadCount();
ASSERT_EQ(0, pthread_join(thread_id, &dummy));
// The OS may not immediately report the updated thread count after void* dummy;
// joining a thread, causing flakiness in this test. To counter that, we ASSERT_EQ(0, pthread_join(thread_id, &dummy));
// wait for up to .5 seconds for the OS to report the correct value.
for (int i = 0; i < 5; ++i) {
if (GetThreadCount() == starting_count)
break;
SleepMilliseconds(100); // Join before we decide whether we need to retry the test. Retry if an
// arbitrary other thread was created or destroyed in the meantime.
if (thread_count_after_create != starting_count + 1) continue;
// The OS may not immediately report the updated thread count after
// joining a thread, causing flakiness in this test. To counter that, we
// wait for up to .5 seconds for the OS to report the correct value.
bool thread_count_matches = false;
for (int i = 0; i < 5; ++i) {
thread_count_after_join = GetThreadCount();
if (thread_count_after_join == starting_count) {
thread_count_matches = true;
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
// Retry if an arbitrary other thread was created or destroyed.
if (!thread_count_matches) continue;
break;
} }
EXPECT_EQ(starting_count, GetThreadCount()); EXPECT_EQ(thread_count_after_create, starting_count + 1);
EXPECT_EQ(thread_count_after_join, starting_count);
} }
#else #else
TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) { TEST(GetThreadCountTest, ReturnsZeroWhenUnableToCountThreads) {
EXPECT_EQ(0U, GetThreadCount()); EXPECT_EQ(0U, GetThreadCount());
} }
#endif // GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA #endif // GTEST_OS_LINUX || GTEST_OS_MAC || GTEST_OS_QNX || GTEST_OS_FUCHSIA
TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) { TEST(GtestCheckDeathTest, DiesWithCorrectOutputOnFailure) {
const bool a_false_condition = false; const bool a_false_condition = false;
const char regex[] = const char regex[] =
#ifdef _MSC_VER #ifdef _MSC_VER
"googletest-port-test\\.cc\\(\\d+\\):" "googletest-port-test\\.cc\\(\\d+\\):"
#elif GTEST_USES_POSIX_RE #elif GTEST_USES_POSIX_RE
"googletest-port-test\\.cc:[0-9]+" "googletest-port-test\\.cc:[0-9]+"
#else #else
"googletest-port-test\\.cc:\\d+" "googletest-port-test\\.cc:\\d+"
#endif // _MSC_VER #endif // _MSC_VER
".*a_false_condition.*Extra info.*"; ".*a_false_condition.*Extra info.*";
EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(a_false_condition) << "Extra info", EXPECT_DEATH_IF_SUPPORTED(GTEST_CHECK_(a_false_condition) << "Extra info",
regex); regex);
} }
#if GTEST_HAS_DEATH_TEST #if GTEST_HAS_DEATH_TEST
TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) { TEST(GtestCheckDeathTest, LivesSilentlyOnSuccess) {
EXPECT_EXIT({ EXPECT_EXIT(
GTEST_CHECK_(true) << "Extra info"; {
::std::cerr << "Success\n"; GTEST_CHECK_(true) << "Extra info";
exit(0); }, ::std::cerr << "Success\n";
exit(0);
},
::testing::ExitedWithCode(0), "Success"); ::testing::ExitedWithCode(0), "Success");
} }
#endif // GTEST_HAS_DEATH_TEST #endif // GTEST_HAS_DEATH_TEST
// Verifies that Google Test choose regular expression engine appropriate to // Verifies that Google Test choose regular expression engine appropriate to
// the platform. The test will produce compiler errors in case of failure. // the platform. The test will produce compiler errors in case of failure.
// For simplicity, we only cover the most important platforms here. // For simplicity, we only cover the most important platforms here.
TEST(RegexEngineSelectionTest, SelectsCorrectRegexEngine) { TEST(RegexEngineSelectionTest, SelectsCorrectRegexEngine) {
#if !GTEST_USES_PCRE #if GTEST_HAS_ABSL
# if GTEST_HAS_POSIX_RE EXPECT_TRUE(GTEST_USES_RE2);
#elif GTEST_HAS_POSIX_RE
EXPECT_TRUE(GTEST_USES_POSIX_RE); EXPECT_TRUE(GTEST_USES_POSIX_RE);
#else
# else
EXPECT_TRUE(GTEST_USES_SIMPLE_RE); EXPECT_TRUE(GTEST_USES_SIMPLE_RE);
#endif
# endif
#endif // !GTEST_USES_PCRE
} }
#if GTEST_USES_POSIX_RE #if GTEST_USES_POSIX_RE
template <typename Str> template <typename Str>
class RETest : public ::testing::Test {}; class RETest : public ::testing::Test {};
// Defines StringTypes as the list of all string types that class RE // Defines StringTypes as the list of all string types that class RE
// supports. // supports.
typedef testing::Types< ::std::string, const char*> StringTypes; typedef testing::Types< ::std::string, const char*> StringTypes;
skipping to change at line 399 skipping to change at line 424
const RE simple(TypeParam("hello")); const RE simple(TypeParam("hello"));
EXPECT_STREQ("hello", simple.pattern()); EXPECT_STREQ("hello", simple.pattern());
const RE normal(TypeParam(".*(\\w+)")); const RE normal(TypeParam(".*(\\w+)"));
EXPECT_STREQ(".*(\\w+)", normal.pattern()); EXPECT_STREQ(".*(\\w+)", normal.pattern());
} }
// Tests that RE's constructors reject invalid regular expressions. // Tests that RE's constructors reject invalid regular expressions.
TYPED_TEST(RETest, RejectsInvalidRegex) { TYPED_TEST(RETest, RejectsInvalidRegex) {
EXPECT_NONFATAL_FAILURE({ EXPECT_NONFATAL_FAILURE(
const RE invalid(TypeParam("?")); { const RE invalid(TypeParam("?")); },
}, "\"?\" is not a valid POSIX Extended regular expression."); "\"?\" is not a valid POSIX Extended regular expression.");
} }
// Tests RE::FullMatch(). // Tests RE::FullMatch().
TYPED_TEST(RETest, FullMatchWorks) { TYPED_TEST(RETest, FullMatchWorks) {
const RE empty(TypeParam("")); const RE empty(TypeParam(""));
EXPECT_TRUE(RE::FullMatch(TypeParam(""), empty)); EXPECT_TRUE(RE::FullMatch(TypeParam(""), empty));
EXPECT_FALSE(RE::FullMatch(TypeParam("a"), empty)); EXPECT_FALSE(RE::FullMatch(TypeParam("a"), empty));
const RE re(TypeParam("a.*z")); const RE re(TypeParam("a.*z"));
EXPECT_TRUE(RE::FullMatch(TypeParam("az"), re)); EXPECT_TRUE(RE::FullMatch(TypeParam("az"), re));
skipping to change at line 795 skipping to change at line 820
TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetition) { TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetition) {
EXPECT_FALSE(MatchRegexAtHead(".+a", "abc")); EXPECT_FALSE(MatchRegexAtHead(".+a", "abc"));
EXPECT_FALSE(MatchRegexAtHead("a?b", "aab")); EXPECT_FALSE(MatchRegexAtHead("a?b", "aab"));
EXPECT_TRUE(MatchRegexAtHead(".*a", "bc12-ab")); EXPECT_TRUE(MatchRegexAtHead(".*a", "bc12-ab"));
EXPECT_TRUE(MatchRegexAtHead("a?b", "b")); EXPECT_TRUE(MatchRegexAtHead("a?b", "b"));
EXPECT_TRUE(MatchRegexAtHead("a?b", "ab")); EXPECT_TRUE(MatchRegexAtHead("a?b", "ab"));
} }
TEST(MatchRegexAtHeadTest, TEST(MatchRegexAtHeadTest, WorksWhenRegexStartsWithRepetionOfEscapeSequence) {
WorksWhenRegexStartsWithRepetionOfEscapeSequence) {
EXPECT_FALSE(MatchRegexAtHead("\\.+a", "abc")); EXPECT_FALSE(MatchRegexAtHead("\\.+a", "abc"));
EXPECT_FALSE(MatchRegexAtHead("\\s?b", " b")); EXPECT_FALSE(MatchRegexAtHead("\\s?b", " b"));
EXPECT_TRUE(MatchRegexAtHead("\\(*a", "((((ab")); EXPECT_TRUE(MatchRegexAtHead("\\(*a", "((((ab"));
EXPECT_TRUE(MatchRegexAtHead("\\^?b", "^b")); EXPECT_TRUE(MatchRegexAtHead("\\^?b", "^b"));
EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "b")); EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "b"));
EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "\\b")); EXPECT_TRUE(MatchRegexAtHead("\\\\?b", "\\b"));
} }
TEST(MatchRegexAtHeadTest, MatchesSequentially) { TEST(MatchRegexAtHeadTest, MatchesSequentially) {
skipping to change at line 852 skipping to change at line 876
TEST(RETest, ImplicitConstructorWorks) { TEST(RETest, ImplicitConstructorWorks) {
const RE empty(""); const RE empty("");
EXPECT_STREQ("", empty.pattern()); EXPECT_STREQ("", empty.pattern());
const RE simple("hello"); const RE simple("hello");
EXPECT_STREQ("hello", simple.pattern()); EXPECT_STREQ("hello", simple.pattern());
} }
// Tests that RE's constructors reject invalid regular expressions. // Tests that RE's constructors reject invalid regular expressions.
TEST(RETest, RejectsInvalidRegex) { TEST(RETest, RejectsInvalidRegex) {
EXPECT_NONFATAL_FAILURE({ EXPECT_NONFATAL_FAILURE({ const RE normal(NULL); },
const RE normal(NULL); "NULL is not a valid simple regular expression");
}, "NULL is not a valid simple regular expression");
EXPECT_NONFATAL_FAILURE({ const RE normal(".*(\\w+"); },
EXPECT_NONFATAL_FAILURE({ "'(' is unsupported");
const RE normal(".*(\\w+");
}, "'(' is unsupported"); EXPECT_NONFATAL_FAILURE({ const RE invalid("^?"); },
"'?' can only follow a repeatable token");
EXPECT_NONFATAL_FAILURE({
const RE invalid("^?");
}, "'?' can only follow a repeatable token");
} }
// Tests RE::FullMatch(). // Tests RE::FullMatch().
TEST(RETest, FullMatchWorks) { TEST(RETest, FullMatchWorks) {
const RE empty(""); const RE empty("");
EXPECT_TRUE(RE::FullMatch("", empty)); EXPECT_TRUE(RE::FullMatch("", empty));
EXPECT_FALSE(RE::FullMatch("a", empty)); EXPECT_FALSE(RE::FullMatch("a", empty));
const RE re1("a"); const RE re1("a");
EXPECT_TRUE(RE::FullMatch("a", re1)); EXPECT_TRUE(RE::FullMatch("a", re1));
skipping to change at line 1004 skipping to change at line 1025
TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) { TEST(ThreadWithParamTest, ConstructorExecutesThreadFunc) {
int i = 40; int i = 40;
ThreadWithParam<int*> thread(&AddTwo, &i, nullptr); ThreadWithParam<int*> thread(&AddTwo, &i, nullptr);
thread.Join(); thread.Join();
EXPECT_EQ(42, i); EXPECT_EQ(42, i);
} }
TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) { TEST(MutexDeathTest, AssertHeldShouldAssertWhenNotLocked) {
// AssertHeld() is flaky only in the presence of multiple threads accessing // AssertHeld() is flaky only in the presence of multiple threads accessing
// the lock. In this case, the test is robust. // the lock. In this case, the test is robust.
EXPECT_DEATH_IF_SUPPORTED({ EXPECT_DEATH_IF_SUPPORTED(
Mutex m; {
{ MutexLock lock(&m); } Mutex m;
m.AssertHeld(); { MutexLock lock(&m); }
}, m.AssertHeld();
"thread .*hold"); },
"thread .*hold");
} }
TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) { TEST(MutexTest, AssertHeldShouldNotAssertWhenLocked) {
Mutex m; Mutex m;
MutexLock lock(&m); MutexLock lock(&m);
m.AssertHeld(); m.AssertHeld();
} }
class AtomicCounterWithMutex { class AtomicCounterWithMutex {
public: public:
explicit AtomicCounterWithMutex(Mutex* mutex) : explicit AtomicCounterWithMutex(Mutex* mutex)
value_(0), mutex_(mutex), random_(42) {} : value_(0), mutex_(mutex), random_(42) {}
void Increment() { void Increment() {
MutexLock lock(mutex_); MutexLock lock(mutex_);
int temp = value_; int temp = value_;
{ {
// We need to put up a memory barrier to prevent reads and writes to // We need to put up a memory barrier to prevent reads and writes to
// value_ rearranged with the call to SleepMilliseconds when observed // value_ rearranged with the call to sleep_for when observed
// from other threads. // from other threads.
#if GTEST_HAS_PTHREAD #if GTEST_HAS_PTHREAD
// On POSIX, locking a mutex puts up a memory barrier. We cannot use // On POSIX, locking a mutex puts up a memory barrier. We cannot use
// Mutex and MutexLock here or rely on their memory barrier // Mutex and MutexLock here or rely on their memory barrier
// functionality as we are testing them here. // functionality as we are testing them here.
pthread_mutex_t memory_barrier_mutex; pthread_mutex_t memory_barrier_mutex;
GTEST_CHECK_POSIX_SUCCESS_( GTEST_CHECK_POSIX_SUCCESS_(
pthread_mutex_init(&memory_barrier_mutex, nullptr)); pthread_mutex_init(&memory_barrier_mutex, nullptr));
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex)); GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_lock(&memory_barrier_mutex));
SleepMilliseconds(static_cast<int>(random_.Generate(30))); std::this_thread::sleep_for(
std::chrono::milliseconds(random_.Generate(30)));
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex)); GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_unlock(&memory_barrier_mutex));
GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&memory_barrier_mutex)); GTEST_CHECK_POSIX_SUCCESS_(pthread_mutex_destroy(&memory_barrier_mutex));
#elif GTEST_OS_WINDOWS #elif GTEST_OS_WINDOWS
// On Windows, performing an interlocked access puts up a memory barrier. // On Windows, performing an interlocked access puts up a memory barrier.
volatile LONG dummy = 0; volatile LONG dummy = 0;
::InterlockedIncrement(&dummy); ::InterlockedIncrement(&dummy);
SleepMilliseconds(static_cast<int>(random_.Generate(30))); std::this_thread::sleep_for(
std::chrono::milliseconds(random_.Generate(30)));
::InterlockedIncrement(&dummy); ::InterlockedIncrement(&dummy);
#else #else
# error "Memory barrier not implemented on this platform." #error "Memory barrier not implemented on this platform."
#endif // GTEST_HAS_PTHREAD #endif // GTEST_HAS_PTHREAD
} }
value_ = temp + 1; value_ = temp + 1;
} }
int value() const { return value_; } int value() const { return value_; }
private: private:
volatile int value_; volatile int value_;
Mutex* const mutex_; // Protects value_. Mutex* const mutex_; // Protects value_.
Random random_; Random random_;
}; };
void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) { void CountingThreadFunc(pair<AtomicCounterWithMutex*, int> param) {
for (int i = 0; i < param.second; ++i) for (int i = 0; i < param.second; ++i) param.first->Increment();
param.first->Increment();
} }
// Tests that the mutex only lets one thread at a time to lock it. // Tests that the mutex only lets one thread at a time to lock it.
TEST(MutexTest, OnlyOneThreadCanLockAtATime) { TEST(MutexTest, OnlyOneThreadCanLockAtATime) {
Mutex mutex; Mutex mutex;
AtomicCounterWithMutex locked_counter(&mutex); AtomicCounterWithMutex locked_counter(&mutex);
typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType; typedef ThreadWithParam<pair<AtomicCounterWithMutex*, int> > ThreadType;
const int kCycleCount = 20; const int kCycleCount = 20;
const int kThreadCount = 7; const int kThreadCount = 7;
std::unique_ptr<ThreadType> counting_threads[kThreadCount]; std::unique_ptr<ThreadType> counting_threads[kThreadCount];
Notification threads_can_start; Notification threads_can_start;
// Creates and runs kThreadCount threads that increment locked_counter // Creates and runs kThreadCount threads that increment locked_counter
// kCycleCount times each. // kCycleCount times each.
for (int i = 0; i < kThreadCount; ++i) { for (int i = 0; i < kThreadCount; ++i) {
counting_threads[i].reset(new ThreadType(&CountingThreadFunc, counting_threads[i].reset(new ThreadType(
make_pair(&locked_counter, &CountingThreadFunc, make_pair(&locked_counter, kCycleCount),
kCycleCount), &threads_can_start));
&threads_can_start));
} }
threads_can_start.Notify(); threads_can_start.Notify();
for (int i = 0; i < kThreadCount; ++i) for (int i = 0; i < kThreadCount; ++i) counting_threads[i]->Join();
counting_threads[i]->Join();
// If the mutex lets more than one thread to increment the counter at a // If the mutex lets more than one thread to increment the counter at a
// time, they are likely to encounter a race condition and have some // time, they are likely to encounter a race condition and have some
// increments overwritten, resulting in the lower then expected counter // increments overwritten, resulting in the lower then expected counter
// value. // value.
EXPECT_EQ(kCycleCount * kThreadCount, locked_counter.value()); EXPECT_EQ(kCycleCount * kThreadCount, locked_counter.value());
} }
template <typename T> template <typename T>
void RunFromThread(void (func)(T), T param) { void RunFromThread(void(func)(T), T param) {
ThreadWithParam<T> thread(func, param, nullptr); ThreadWithParam<T> thread(func, param, nullptr);
thread.Join(); thread.Join();
} }
void RetrieveThreadLocalValue( void RetrieveThreadLocalValue(
pair<ThreadLocal<std::string>*, std::string*> param) { pair<ThreadLocal<std::string>*, std::string*> param) {
*param.second = param.first->get(); *param.second = param.first->get();
} }
TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) { TEST(ThreadLocalTest, ParameterizedConstructorSetsDefault) {
skipping to change at line 1164 skipping to change at line 1185
list_->clear(); list_->clear();
} }
private: private:
bool invoked_; bool invoked_;
#if GTEST_OS_WINDOWS #if GTEST_OS_WINDOWS
AutoHandle wait_event_; AutoHandle wait_event_;
#endif #endif
static std::vector<DestructorCall*>* const list_; static std::vector<DestructorCall*>* const list_;
GTEST_DISALLOW_COPY_AND_ASSIGN_(DestructorCall); DestructorCall(const DestructorCall&) = delete;
DestructorCall& operator=(const DestructorCall&) = delete;
}; };
std::vector<DestructorCall*>* const DestructorCall::list_ = std::vector<DestructorCall*>* const DestructorCall::list_ =
new std::vector<DestructorCall*>; new std::vector<DestructorCall*>;
// DestructorTracker keeps track of whether its instances have been // DestructorTracker keeps track of whether its instances have been
// destroyed. // destroyed.
class DestructorTracker { class DestructorTracker {
public: public:
DestructorTracker() : index_(GetNewIndex()) {} DestructorTracker() : index_(GetNewIndex()) {}
 End of changes. 36 change blocks. 
86 lines changed or deleted 108 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)