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..a43c6185a496b2159504075b6c4ff67b72663130 |
--- /dev/null |
+++ b/base/task_scheduler/shutdown_manager_unittest.cc |
@@ -0,0 +1,237 @@ |
+// 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/threading/platform_thread.h" |
+#include "base/threading/simple_thread.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+namespace base { |
+namespace task_scheduler { |
+ |
+namespace { |
+ |
+class ThreadCallingShutdown : public SimpleThread { |
+ public: |
+ 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)); |
+ } |
+ |
+ // 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_; |
+}; |
+ |
+} // 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) { |
+ 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 task_scheduler |
+} // namespace base |