Chromium Code Reviews| Index: base/task_scheduler/shutdown_manager_unittest.cc |
| diff --git a/base/task_scheduler/shutdown_manager_unittest.cc b/base/task_scheduler/shutdown_manager_unittest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..f51c40f5c78b95d152e287efc96027390ccf9d74 |
| --- /dev/null |
| +++ b/base/task_scheduler/shutdown_manager_unittest.cc |
| @@ -0,0 +1,239 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/task_scheduler/shutdown_manager.h" |
| + |
| +#include "base/macros.h" |
| +#include "base/threading/platform_thread.h" |
| +#include "base/threading/simple_thread.h" |
| +#include "testing/gtest/include/gtest/gtest.h" |
| + |
| +namespace base { |
| +namespace internal { |
| + |
| +namespace { |
| + |
| +class ThreadCallingShutdown : public SimpleThread { |
| + public: |
| + explicit ThreadCallingShutdown(ShutdownManager* manager) |
| + : SimpleThread("ThreadCallingShutdown"), |
| + manager_(manager), |
| + has_exited_(false) {} |
| + |
| + // Waits until manager_->Shutdown() has been called. |
| + void WaitUntilShutdownCalled() { |
| + while (!manager_->is_shutting_down_for_testing()) |
| + PlatformThread::Sleep(TimeDelta::FromMilliseconds(5)); |
|
gab
2016/02/23 22:28:23
5 seems arbitrary. How about PlatformThread::Yield
fdoray
2016/02/26 15:53:28
Done.
|
| + } |
| + |
| + // Returns true once the thread has exited. |
| + bool has_exited() const { return has_exited_; } |
| + |
| + private: |
| + void Run() override { |
| + manager_->Shutdown(); |
| + has_exited_ = true; |
| + } |
| + |
| + ShutdownManager* manager_; |
| + bool has_exited_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(ThreadCallingShutdown); |
| +}; |
| + |
| +} // namespace |
| + |
| +TEST(TaskSchedulerShutdownManagerTest, ShouldPostTaskBeforeShutdown) { |
| + ShutdownManager manager; |
| + EXPECT_TRUE( |
| + manager.ShouldPostTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| + EXPECT_TRUE(manager.ShouldPostTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| + EXPECT_TRUE(manager.ShouldPostTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| +} |
| + |
| +TEST(TaskSchedulerShutdownManagerTest, ShouldPostTaskAfterShutdownCompleted) { |
| + ShutdownManager manager; |
| + manager.Shutdown(); |
| + EXPECT_FALSE( |
| + manager.ShouldPostTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| + EXPECT_FALSE(manager.ShouldPostTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| + EXPECT_FALSE(manager.ShouldPostTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| +} |
| + |
| +TEST(TaskSchedulerShutdownManagerTest, ShouldScheduleTaskBeforeShutdown) { |
| + ShutdownManager manager; |
| + EXPECT_TRUE( |
| + manager.ShouldScheduleTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| + EXPECT_TRUE( |
| + manager.ShouldScheduleTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| + EXPECT_TRUE(manager.ShouldScheduleTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| +} |
| + |
| +TEST(TaskSchedulerShutdownManagerTest, |
| + ShouldScheduleTaskAfterShutdownCompleted) { |
| + ShutdownManager manager; |
| + manager.Shutdown(); |
| + EXPECT_FALSE( |
| + manager.ShouldScheduleTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| + EXPECT_FALSE( |
| + manager.ShouldScheduleTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| + EXPECT_FALSE( |
| + manager.ShouldScheduleTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| +} |
| + |
| +TEST(TaskSchedulerShutdownManagerTest, |
| + ShouldPostAndScheduleTaskDuringShutdown) { |
| + ShutdownManager manager; |
| + |
| + // Inform the manager that a BLOCK_SHUTDOWN task has been posted, to block |
| + // shutdown. |
| + EXPECT_TRUE(manager.ShouldPostTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| + |
| + // Call manager.Shutdown() on another thread. |
| + ThreadCallingShutdown thread(&manager); |
| + thread.Start(); |
| + thread.WaitUntilShutdownCalled(); |
| + EXPECT_FALSE(thread.has_exited()); |
| + |
| + // Check that only a BLOCK_SHUTDOWN task can be posted. |
| + EXPECT_FALSE( |
| + manager.ShouldPostTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| + EXPECT_FALSE(thread.has_exited()); |
| + EXPECT_FALSE(manager.ShouldPostTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| + EXPECT_FALSE(thread.has_exited()); |
| + EXPECT_TRUE(manager.ShouldPostTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| + EXPECT_FALSE(thread.has_exited()); |
| + |
| + // Check that only a BLOCK_SHUTDOWN task can be scheduled. |
| + EXPECT_FALSE( |
| + manager.ShouldScheduleTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| + EXPECT_FALSE(thread.has_exited()); |
| + EXPECT_FALSE( |
| + manager.ShouldScheduleTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| + EXPECT_FALSE(thread.has_exited()); |
| + EXPECT_TRUE(manager.ShouldScheduleTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| + EXPECT_FALSE(thread.has_exited()); |
| + |
| + // Unblock Shutdown(). |
| + manager.DidExecuteTask(TaskShutdownBehavior::BLOCK_SHUTDOWN); |
| + EXPECT_FALSE(thread.has_exited()); |
| + EXPECT_TRUE(manager.ShouldScheduleTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| + EXPECT_FALSE(thread.has_exited()); |
| + manager.DidExecuteTask(TaskShutdownBehavior::BLOCK_SHUTDOWN); |
| + |
| + // Wait until the thread calling manager.Shutdown() exits. |
| + thread.Join(); |
| + EXPECT_TRUE(thread.has_exited()); |
| +} |
| + |
| +TEST(TaskSchedulerShutdownManagerTest, |
| + ShutdownWithQueuedSkipAndContinueOnShutdownTasks) { |
| + ShutdownManager manager; |
| + |
| + // Inform |manager| that a CONTINUE_ON_SHUTDOWN task and a SKIP_ON_SHUTDOWN |
| + // task have been posted. |
| + EXPECT_TRUE( |
| + manager.ShouldPostTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| + EXPECT_TRUE(manager.ShouldPostTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| + |
| + // Call manager.Shutdown(). This call shouldn't block. |
| + manager.Shutdown(); |
| +} |
| + |
| +TEST(TaskSchedulerShutdownManagerTest, |
| + ShutdownScheduledContinueOnShutdownTasks) { |
| + ShutdownManager manager; |
| + |
| + // Inform |manager| that a SKIP_ON_SHUTDOWN task has been posted and |
| + // scheduled. |
| + EXPECT_TRUE( |
| + manager.ShouldPostTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| + EXPECT_TRUE( |
| + manager.ShouldScheduleTask(TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN)); |
| + |
| + // Call manager.Shutdown() on another thread. This call shouldn't block. |
| + manager.Shutdown(); |
| +} |
| + |
| +TEST(TaskSchedulerShutdownManagerTest, ShutdownScheduledSkipOnShutdownTasks) { |
| + ShutdownManager manager; |
| + |
| + // Inform |manager| that a SKIP_ON_SHUTDOWN task has been posted and |
| + // scheduled. |
| + EXPECT_TRUE(manager.ShouldPostTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| + EXPECT_TRUE( |
| + manager.ShouldScheduleTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN)); |
| + |
| + // Call manager.Shutdown() on another thread. This call should block until the |
| + // SKIP_ON_SHUTDOWN task has been executed. |
| + ThreadCallingShutdown thread(&manager); |
| + thread.Start(); |
| + thread.WaitUntilShutdownCalled(); |
| + EXPECT_FALSE(thread.has_exited()); |
| + |
| + // Inform |manager| that a SKIP_ON_SHUTDOWN task has been executed. |
| + manager.DidExecuteTask(TaskShutdownBehavior::SKIP_ON_SHUTDOWN); |
| + |
| + // Wait until the thread calling manager.Shutdown() exits. |
| + thread.Join(); |
| + EXPECT_TRUE(thread.has_exited()); |
| +} |
| + |
| +TEST(TaskSchedulerShutdownManagerTest, ShutdownWithQueuedBlockShutdownTasks) { |
|
gab
2016/02/23 22:28:23
I think ShouldPostAndScheduleTaskDuringShutdown al
fdoray
2016/02/26 15:53:28
I completely refactored the unit tests :)
|
| + ShutdownManager manager; |
| + |
| + // Inform |manager| that 2 BLOCK_SHUTDOWN task have been posted. |
| + EXPECT_TRUE(manager.ShouldPostTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| + EXPECT_TRUE(manager.ShouldPostTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| + |
| + // Call manager.Shutdown() on another thread. This call should block until |
| + // both BLOCK_SHUTDOWN tasks have been executed. |
| + ThreadCallingShutdown thread(&manager); |
| + thread.Start(); |
| + thread.WaitUntilShutdownCalled(); |
| + EXPECT_FALSE(thread.has_exited()); |
| + |
| + // Inform |manager| that the first BLOCK_SHUTDOWN task has been scheduled and |
| + // executed. |
| + EXPECT_TRUE(manager.ShouldScheduleTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| + EXPECT_FALSE(thread.has_exited()); |
| + manager.DidExecuteTask(TaskShutdownBehavior::BLOCK_SHUTDOWN); |
| + EXPECT_FALSE(thread.has_exited()); |
| + |
| + // Inform |manager| that the second BLOCK_SHUTDOWN task has been scheduled and |
| + // executed.. |
| + EXPECT_TRUE(manager.ShouldScheduleTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| + EXPECT_FALSE(thread.has_exited()); |
| + manager.DidExecuteTask(TaskShutdownBehavior::BLOCK_SHUTDOWN); |
| + |
| + // Wait until the thread calling manager.Shutdown() exits. |
| + thread.Join(); |
| + EXPECT_TRUE(thread.has_exited()); |
| +} |
| + |
| +TEST(TaskSchedulerShutdownManagerTest, |
| + ShutdownWithScheduledBlockShutdownTasks) { |
| + ShutdownManager manager; |
| + |
| + // Inform |manager| that a BLOCK_SHUTDOWN task have been posted and scheduled. |
| + EXPECT_TRUE(manager.ShouldPostTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| + EXPECT_TRUE(manager.ShouldScheduleTask(TaskShutdownBehavior::BLOCK_SHUTDOWN)); |
| + |
| + // Call manager.Shutdown() on another thread. This call should block until the |
| + // BLOCK_SHUTDOWN task has been executed. |
| + ThreadCallingShutdown thread(&manager); |
| + thread.Start(); |
| + thread.WaitUntilShutdownCalled(); |
| + EXPECT_FALSE(thread.has_exited()); |
| + |
| + // Inform |manager| that a BLOCK_SHUTDOWN task has been executed. |
| + manager.DidExecuteTask(TaskShutdownBehavior::BLOCK_SHUTDOWN); |
| + |
| + // Wait until the thread calling manager.Shutdown() exits. |
| + thread.Join(); |
| + EXPECT_TRUE(thread.has_exited()); |
| +} |
| + |
| +} // namespace internal |
| +} // namespace base |