Chromium Code Reviews| Index: base/task_scheduler/scheduler_worker_unittest.cc |
| diff --git a/base/task_scheduler/scheduler_worker_unittest.cc b/base/task_scheduler/scheduler_worker_unittest.cc |
| index b65d50c07c3fb5db64ba8df08031bc6934ef10a5..0d02021f10e9267baa9faff9f94b36bf11d7b4f3 100644 |
| --- a/base/task_scheduler/scheduler_worker_unittest.cc |
| +++ b/base/task_scheduler/scheduler_worker_unittest.cc |
| @@ -19,6 +19,7 @@ |
| #include "base/task_scheduler/sequence.h" |
| #include "base/task_scheduler/task.h" |
| #include "base/task_scheduler/task_tracker.h" |
| +#include "base/test/test_timeouts.h" |
| #include "base/threading/platform_thread.h" |
| #include "base/time/time.h" |
| #include "build/build_config.h" |
| @@ -355,16 +356,13 @@ namespace { |
| class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate { |
| public: |
| - ControllableDetachDelegate(TaskTracker* task_tracker) |
| - : task_tracker_(task_tracker), |
| - work_processed_(WaitableEvent::ResetPolicy::MANUAL, |
| + ControllableDetachDelegate() |
| + : work_processed_(WaitableEvent::ResetPolicy::MANUAL, |
| WaitableEvent::InitialState::NOT_SIGNALED), |
| detach_requested_(WaitableEvent::ResetPolicy::MANUAL, |
| WaitableEvent::InitialState::NOT_SIGNALED), |
| detached_(WaitableEvent::ResetPolicy::MANUAL, |
| - WaitableEvent::InitialState::NOT_SIGNALED) { |
| - EXPECT_TRUE(task_tracker_); |
| - } |
| + WaitableEvent::InitialState::NOT_SIGNALED) {} |
| ~ControllableDetachDelegate() override = default; |
| @@ -383,7 +381,7 @@ class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate { |
| std::unique_ptr<Task> task(new Task( |
| FROM_HERE, Bind(&WaitableEvent::Signal, Unretained(&work_processed_)), |
| TaskTraits(), TimeDelta())); |
| - EXPECT_TRUE(task_tracker_->WillPostTask(task.get())); |
| + EXPECT_TRUE(task_tracker_.WillPostTask(task.get())); |
| sequence->PushTask(std::move(task)); |
| return sequence; |
| } |
| @@ -419,8 +417,12 @@ class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate { |
| void set_can_detach(bool can_detach) { can_detach_ = can_detach; } |
| + // This delegate owns the TaskTracker because during detachment, threads may |
| + // outlive the test case. |
|
fdoray
2017/02/08 17:59:02
I think this is no longer true if you do https://c
robliao
2017/02/11 02:13:34
That is true. Removed.
|
| + TaskTracker* task_tracker() { return &task_tracker_; } |
| + |
| private: |
| - TaskTracker* const task_tracker_; |
| + TaskTracker task_tracker_; |
| bool work_requested_ = false; |
| bool can_detach_ = false; |
| WaitableEvent work_processed_; |
| @@ -433,16 +435,14 @@ class ControllableDetachDelegate : public SchedulerWorkerDefaultDelegate { |
| } // namespace |
| TEST(TaskSchedulerWorkerTest, WorkerDetaches) { |
| - TaskTracker task_tracker; |
| // Will be owned by SchedulerWorker. |
| ControllableDetachDelegate* delegate = |
| - new StrictMock<ControllableDetachDelegate>(&task_tracker); |
| + new StrictMock<ControllableDetachDelegate>(); |
| delegate->set_can_detach(true); |
| EXPECT_CALL(*delegate, OnMainEntry(_)); |
| - std::unique_ptr<SchedulerWorker> worker = |
| - SchedulerWorker::Create( |
| - ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, |
| - SchedulerWorker::InitialState::ALIVE); |
| + std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( |
| + ThreadPriority::NORMAL, WrapUnique(delegate), delegate->task_tracker(), |
| + SchedulerWorker::InitialState::ALIVE); |
| worker->WakeUp(); |
| delegate->WaitForWorkToRun(); |
| Mock::VerifyAndClear(delegate); |
| @@ -451,17 +451,31 @@ TEST(TaskSchedulerWorkerTest, WorkerDetaches) { |
| ASSERT_FALSE(worker->ThreadAliveForTesting()); |
| } |
| +TEST(TaskSchedulerWorkerTest, WorkerDetachesAndSelfDestroys) { |
| + // This test shouldn't crash or leak resources. |
| + // Will be owned by SchedulerWorker. |
| + ControllableDetachDelegate* delegate = |
| + new StrictMock<ControllableDetachDelegate>(); |
| + delegate->set_can_detach(true); |
| + EXPECT_CALL(*delegate, OnMainEntry(_)); |
| + std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( |
| + ThreadPriority::NORMAL, WrapUnique(delegate), delegate->task_tracker(), |
| + SchedulerWorker::InitialState::ALIVE); |
| + worker->WakeUp(); |
| + SchedulerWorker::DestroyAfterDetachment(std::move(worker)); |
| + // Give a chance for the other thread to clean up. |
|
fdoray
2017/02/08 17:59:02
You could signal an event in ~ControllableDetachDe
robliao
2017/02/11 02:13:34
I went with a refcounted event instead.
|
| + PlatformThread::Sleep(TestTimeouts::tiny_timeout()); |
| +} |
| + |
| TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) { |
| - TaskTracker task_tracker; |
| // Will be owned by SchedulerWorker. |
| ControllableDetachDelegate* delegate = |
| - new StrictMock<ControllableDetachDelegate>(&task_tracker); |
| + new StrictMock<ControllableDetachDelegate>(); |
| delegate->set_can_detach(true); |
| EXPECT_CALL(*delegate, OnMainEntry(_)); |
| - std::unique_ptr<SchedulerWorker> worker = |
| - SchedulerWorker::Create( |
| - ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, |
| - SchedulerWorker::InitialState::ALIVE); |
| + std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( |
| + ThreadPriority::NORMAL, WrapUnique(delegate), delegate->task_tracker(), |
| + SchedulerWorker::InitialState::ALIVE); |
| worker->WakeUp(); |
| delegate->WaitForWorkToRun(); |
| Mock::VerifyAndClear(delegate); |
| @@ -484,14 +498,12 @@ TEST(TaskSchedulerWorkerTest, WorkerDetachesAndWakes) { |
| } |
| TEST(TaskSchedulerWorkerTest, CreateDetached) { |
| - TaskTracker task_tracker; |
| // Will be owned by SchedulerWorker. |
| ControllableDetachDelegate* delegate = |
| - new StrictMock<ControllableDetachDelegate>(&task_tracker); |
| - std::unique_ptr<SchedulerWorker> worker = |
| - SchedulerWorker::Create( |
| - ThreadPriority::NORMAL, WrapUnique(delegate), &task_tracker, |
| - SchedulerWorker::InitialState::DETACHED); |
| + new StrictMock<ControllableDetachDelegate>(); |
| + std::unique_ptr<SchedulerWorker> worker = SchedulerWorker::Create( |
| + ThreadPriority::NORMAL, WrapUnique(delegate), delegate->task_tracker(), |
| + SchedulerWorker::InitialState::DETACHED); |
| ASSERT_FALSE(worker->ThreadAliveForTesting()); |
| EXPECT_CALL(*delegate, OnMainEntry(worker.get())); |
| worker->WakeUp(); |