summaryrefslogtreecommitdiff
path: root/base/task_scheduler/delayed_task_manager_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/task_scheduler/delayed_task_manager_unittest.cc')
-rw-r--r--base/task_scheduler/delayed_task_manager_unittest.cc209
1 files changed, 209 insertions, 0 deletions
diff --git a/base/task_scheduler/delayed_task_manager_unittest.cc b/base/task_scheduler/delayed_task_manager_unittest.cc
new file mode 100644
index 0000000000..67c797acde
--- /dev/null
+++ b/base/task_scheduler/delayed_task_manager_unittest.cc
@@ -0,0 +1,209 @@
+// 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/delayed_task_manager.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/bind.h"
+#include "base/memory/ptr_util.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/waitable_event.h"
+#include "base/task_scheduler/task.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/test_mock_time_task_runner.h"
+#include "base/threading/thread.h"
+#include "base/time/time.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace base {
+namespace internal {
+namespace {
+
+constexpr TimeDelta kLongDelay = TimeDelta::FromHours(1);
+
+class MockTask {
+ public:
+ MOCK_METHOD0(Run, void());
+};
+
+void RunTask(Task task) {
+ std::move(task.task).Run();
+}
+
+class TaskSchedulerDelayedTaskManagerTest : public testing::Test {
+ protected:
+ TaskSchedulerDelayedTaskManagerTest()
+ : delayed_task_manager_(
+ service_thread_task_runner_->DeprecatedGetMockTickClock()),
+ task_(FROM_HERE,
+ BindOnce(&MockTask::Run, Unretained(&mock_task_)),
+ TaskTraits(),
+ kLongDelay) {
+ // The constructor of Task computes |delayed_run_time| by adding |delay| to
+ // the real time. Recompute it by adding |delay| to the mock time.
+ task_.delayed_run_time =
+ service_thread_task_runner_->GetMockTickClock()->NowTicks() +
+ kLongDelay;
+ }
+ ~TaskSchedulerDelayedTaskManagerTest() override = default;
+
+ const scoped_refptr<TestMockTimeTaskRunner> service_thread_task_runner_ =
+ MakeRefCounted<TestMockTimeTaskRunner>();
+ DelayedTaskManager delayed_task_manager_;
+ testing::StrictMock<MockTask> mock_task_;
+ Task task_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TaskSchedulerDelayedTaskManagerTest);
+};
+
+} // namespace
+
+// Verify that a delayed task isn't forwarded before Start().
+TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskDoesNotRunBeforeStart) {
+ // Send |task| to the DelayedTaskManager.
+ delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
+
+ // Fast-forward time until the task is ripe for execution. Since Start() has
+ // not been called, the task should not be forwarded to RunTask() (MockTask is
+ // a StrictMock without expectations so test will fail if RunTask() runs it).
+ service_thread_task_runner_->FastForwardBy(kLongDelay);
+}
+
+// Verify that a delayed task added before Start() and whose delay expires after
+// Start() is forwarded when its delay expires.
+TEST_F(TaskSchedulerDelayedTaskManagerTest,
+ DelayedTaskPostedBeforeStartExpiresAfterStartRunsOnExpire) {
+ // Send |task| to the DelayedTaskManager.
+ delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
+
+ delayed_task_manager_.Start(service_thread_task_runner_);
+
+ // Run tasks on the service thread. Don't expect any forwarding to
+ // |task_target_| since the task isn't ripe for execution.
+ service_thread_task_runner_->RunUntilIdle();
+
+ // Fast-forward time until the task is ripe for execution. Expect the task to
+ // be forwarded to RunTask().
+ EXPECT_CALL(mock_task_, Run());
+ service_thread_task_runner_->FastForwardBy(kLongDelay);
+}
+
+// Verify that a delayed task added before Start() and whose delay expires
+// before Start() is forwarded when Start() is called.
+TEST_F(TaskSchedulerDelayedTaskManagerTest,
+ DelayedTaskPostedBeforeStartExpiresBeforeStartRunsOnStart) {
+ // Send |task| to the DelayedTaskManager.
+ delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
+
+ // Run tasks on the service thread. Don't expect any forwarding to
+ // |task_target_| since the task isn't ripe for execution.
+ service_thread_task_runner_->RunUntilIdle();
+
+ // Fast-forward time until the task is ripe for execution. Don't expect the
+ // task to be forwarded since Start() hasn't been called yet.
+ service_thread_task_runner_->FastForwardBy(kLongDelay);
+
+ // Start the DelayedTaskManager. Expect the task to be forwarded to RunTask().
+ EXPECT_CALL(mock_task_, Run());
+ delayed_task_manager_.Start(service_thread_task_runner_);
+ service_thread_task_runner_->RunUntilIdle();
+}
+
+// Verify that a delayed task added after Start() isn't forwarded before it is
+// ripe for execution.
+TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskDoesNotRunTooEarly) {
+ delayed_task_manager_.Start(service_thread_task_runner_);
+
+ // Send |task| to the DelayedTaskManager.
+ delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
+
+ // Run tasks that are ripe for execution. Don't expect any forwarding to
+ // RunTask().
+ service_thread_task_runner_->RunUntilIdle();
+}
+
+// Verify that a delayed task added after Start() is forwarded when it is ripe
+// for execution.
+TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTaskRunsAfterDelay) {
+ delayed_task_manager_.Start(service_thread_task_runner_);
+
+ // Send |task| to the DelayedTaskManager.
+ delayed_task_manager_.AddDelayedTask(std::move(task_), BindOnce(&RunTask));
+
+ // Fast-forward time. Expect the task to be forwarded to RunTask().
+ EXPECT_CALL(mock_task_, Run());
+ service_thread_task_runner_->FastForwardBy(kLongDelay);
+}
+
+// Verify that multiple delayed tasks added after Start() are forwarded when
+// they are ripe for execution.
+TEST_F(TaskSchedulerDelayedTaskManagerTest, DelayedTasksRunAfterDelay) {
+ delayed_task_manager_.Start(service_thread_task_runner_);
+
+ testing::StrictMock<MockTask> mock_task_a;
+ Task task_a(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_a)),
+ TaskTraits(), TimeDelta::FromHours(1));
+
+ testing::StrictMock<MockTask> mock_task_b;
+ Task task_b(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_b)),
+ TaskTraits(), TimeDelta::FromHours(2));
+
+ testing::StrictMock<MockTask> mock_task_c;
+ Task task_c(FROM_HERE, BindOnce(&MockTask::Run, Unretained(&mock_task_c)),
+ TaskTraits(), TimeDelta::FromHours(1));
+
+ // Send tasks to the DelayedTaskManager.
+ delayed_task_manager_.AddDelayedTask(std::move(task_a), BindOnce(&RunTask));
+ delayed_task_manager_.AddDelayedTask(std::move(task_b), BindOnce(&RunTask));
+ delayed_task_manager_.AddDelayedTask(std::move(task_c), BindOnce(&RunTask));
+
+ // Run tasks that are ripe for execution on the service thread. Don't expect
+ // any call to RunTask().
+ service_thread_task_runner_->RunUntilIdle();
+
+ // Fast-forward time. Expect |task_a| and |task_c| to be forwarded to
+ // |task_target_|.
+ EXPECT_CALL(mock_task_a, Run());
+ EXPECT_CALL(mock_task_c, Run());
+ service_thread_task_runner_->FastForwardBy(TimeDelta::FromHours(1));
+ testing::Mock::VerifyAndClear(&mock_task_a);
+ testing::Mock::VerifyAndClear(&mock_task_c);
+
+ // Fast-forward time. Expect |task_b| to be forwarded to RunTask().
+ EXPECT_CALL(mock_task_b, Run());
+ service_thread_task_runner_->FastForwardBy(TimeDelta::FromHours(1));
+ testing::Mock::VerifyAndClear(&mock_task_b);
+}
+
+TEST_F(TaskSchedulerDelayedTaskManagerTest, PostTaskDuringStart) {
+ Thread other_thread("Test");
+ other_thread.StartAndWaitForTesting();
+
+ WaitableEvent task_posted;
+
+ other_thread.task_runner()->PostTask(FROM_HERE, BindLambdaForTesting([&]() {
+ delayed_task_manager_.AddDelayedTask(
+ std::move(task_),
+ BindOnce(&RunTask));
+ task_posted.Signal();
+ }));
+
+ delayed_task_manager_.Start(service_thread_task_runner_);
+
+ // The test is testing a race between AddDelayedTask/Start but it still needs
+ // synchronization to ensure we don't do the final verification before the
+ // task itself is posted.
+ task_posted.Wait();
+
+ // Fast-forward time. Expect the task to be forwarded to RunTask().
+ EXPECT_CALL(mock_task_, Run());
+ service_thread_task_runner_->FastForwardBy(kLongDelay);
+}
+
+} // namespace internal
+} // namespace base