| 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
 | 
| 
 |