| Index: base/threading/thread_unittest.cc
|
| diff --git a/base/threading/thread_unittest.cc b/base/threading/thread_unittest.cc
|
| index dfa04c6ac48fce2e445daccb4e14911bda951757..e1f54edb121e4a2880ba8631cc84d13cbf64b4b2 100644
|
| --- a/base/threading/thread_unittest.cc
|
| +++ b/base/threading/thread_unittest.cc
|
| @@ -9,14 +9,23 @@
|
| #include <vector>
|
|
|
| #include "base/bind.h"
|
| -#include "base/location.h"
|
| #include "base/single_thread_task_runner.h"
|
| #include "base/synchronization/waitable_event.h"
|
| #include "base/third_party/dynamic_annotations/dynamic_annotations.h"
|
| +#include "base/threading/platform_thread.h"
|
| #include "build/build_config.h"
|
| #include "testing/gtest/include/gtest/gtest.h"
|
| #include "testing/platform_test.h"
|
|
|
| +// Death tests misbehave on Android.
|
| +// TODO(gab): Remove this when https://codereview.chromium.org/2162053006
|
| +// lands.
|
| +#if DCHECK_IS_ON() && defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
|
| +#define EXPECT_DCHECK_DEATH(statement, regex) EXPECT_DEATH(statement, regex)
|
| +#else
|
| +#define EXPECT_DCHECK_DEATH(statement, regex)
|
| +#endif
|
| +
|
| using base::Thread;
|
|
|
| typedef PlatformTest ThreadTest;
|
| @@ -164,10 +173,47 @@ TEST_F(ThreadTest, StartWithOptions_StackSize) {
|
| event.Wait();
|
| }
|
|
|
| -TEST_F(ThreadTest, TwoTasks) {
|
| +TEST_F(ThreadTest, StartWithOptions_NonJoinable) {
|
| + Thread a("StartNonJoinable");
|
| + Thread::Options options;
|
| + options.joinable = false;
|
| + EXPECT_TRUE(a.StartWithOptions(options));
|
| + EXPECT_TRUE(a.message_loop());
|
| + EXPECT_TRUE(a.IsRunning());
|
| +
|
| + // Without this call this test is racy. The above IsRunning() succeeds because
|
| + // of an early-return condition while between Start() and Stop(), after
|
| + // invoking Stop() below this early-return condition is no longer satisfied
|
| + // and the real |is_running_| bit has to be checked. It could still be false
|
| + // if the message loop hasn't started for real in practice. This is only a
|
| + // requirement for this test because the non-joinable thread makes it possible
|
| + // to return from Stop() before the thread has even started.
|
| + EXPECT_TRUE(a.WaitUntilThreadStarted());
|
| +
|
| + // Make the thread block until |block_event| is signaled.
|
| + base::WaitableEvent block_event(
|
| + base::WaitableEvent::ResetPolicy::AUTOMATIC,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| + a.task_runner()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&base::WaitableEvent::Wait, base::Unretained(&block_event)));
|
| +
|
| + // Stop() shouldn't block despite the thread still being alive.
|
| + a.Stop();
|
| + EXPECT_TRUE(a.IsRunning());
|
| +
|
| + // Unblock the task and give a bit of extra time to unwind QuitWhenIdle().
|
| + block_event.Signal();
|
| + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
|
| +
|
| + // The thread should now have stopped on its own.
|
| + EXPECT_FALSE(a.IsRunning());
|
| +}
|
| +
|
| +TEST_F(ThreadTest, TwoTasksOnJoinableThread) {
|
| bool was_invoked = false;
|
| {
|
| - Thread a("TwoTasks");
|
| + Thread a("TwoTasksOnJoinableThread");
|
| EXPECT_TRUE(a.Start());
|
| EXPECT_TRUE(a.message_loop());
|
|
|
| @@ -231,6 +277,40 @@ TEST_F(ThreadTest, StartTwice) {
|
| EXPECT_FALSE(a.IsRunning());
|
| }
|
|
|
| +TEST_F(ThreadTest, StartTwiceNonJoinableNotAllowed) {
|
| + Thread a("StartTwiceNonJoinable");
|
| +
|
| + Thread::Options options;
|
| + options.joinable = false;
|
| + EXPECT_TRUE(a.StartWithOptions(options));
|
| + EXPECT_TRUE(a.message_loop());
|
| + EXPECT_TRUE(a.IsRunning());
|
| +
|
| + // Signaled when last task on |a| is processed.
|
| + base::WaitableEvent last_task_event(
|
| + base::WaitableEvent::ResetPolicy::AUTOMATIC,
|
| + base::WaitableEvent::InitialState::NOT_SIGNALED);
|
| + a.task_runner()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&base::WaitableEvent::Signal,
|
| + base::Unretained(&last_task_event)));
|
| +
|
| + // Stop() is non-blocking, but Yield() to |a|, wait for last task to be
|
| + // processed and a little more for QuitWhenIdle() to unwind before considering
|
| + // the thread "stopped".
|
| + a.Stop();
|
| + base::PlatformThread::YieldCurrentThread();
|
| + last_task_event.Wait();
|
| + base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
|
| +
|
| + // This test assumes that the above was sufficient to let the thread fully
|
| + // stop.
|
| + ASSERT_FALSE(a.IsRunning());
|
| +
|
| + // Restarting it should not be allowed.
|
| + EXPECT_DCHECK_DEATH(a.Start(), "");
|
| +}
|
| +
|
| TEST_F(ThreadTest, ThreadName) {
|
| Thread a("ThreadName");
|
| EXPECT_TRUE(a.Start());
|
|
|