1a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
2a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// found in the LICENSE file.
4a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
5a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "content/browser/startup_task_runner.h"
6a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
7a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/bind.h"
8a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/bind_helpers.h"
9a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/callback.h"
10a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/location.h"
11a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/run_loop.h"
12a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "base/task_runner.h"
13a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
14a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
15a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
16a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
17a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace content {
18a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)namespace {
19a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
20a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using base::Closure;
21a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using testing::_;
22a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using testing::Assign;
23a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using testing::Invoke;
24a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)using testing::WithArg;
25a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int observer_calls = 0;
274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)int task_count = 0;
28a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)int observer_result;
29a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)base::Closure task;
30a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
31a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// I couldn't get gMock's SaveArg to compile, hence had to save the argument
32a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// this way
33a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool SaveTaskArg(const Closure& arg) {
34a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  task = arg;
35a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return true;
36a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
37a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
38a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void Observer(int result) {
394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  observer_calls++;
40a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  observer_result = result;
41a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
42a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
43a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class StartupTaskRunnerTest : public testing::Test {
44a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public:
45a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
46a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual void SetUp() {
47a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    last_task_ = 0;
484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    observer_calls = 0;
494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    task_count = 0;
50a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
51a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
52a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int Task1() {
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    last_task_ = 1;
544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    task_count++;
55a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return 0;
56a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
57a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
58a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int Task2() {
59a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    last_task_ = 2;
604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    task_count++;
61a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return 0;
62a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
63a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
64a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int FailingTask() {
65a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    // Task returning failure
66a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    last_task_ = 3;
674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    task_count++;
68a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return 1;
69a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
70a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
71a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int GetLastTask() { return last_task_; }
72a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
73a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) private:
74a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
75a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  int last_task_;
76a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
77a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
78a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// We can't use the real message loop, even if we want to, since doing so on
79a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// Android requires a complex Java infrastructure. The test would have to built
80a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// as a content_shell test; but content_shell startup invokes the class we are
81a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// trying to test.
82a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)//
83a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// The mocks are not directly in TaskRunnerProxy because reference counted
84a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// objects seem to confuse the mocking framework
85a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
86a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class MockTaskRunner {
87a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public:
88a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  MOCK_METHOD3(
89a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      PostDelayedTask,
90a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
91a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  MOCK_METHOD3(
92a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      PostNonNestableDelayedTask,
93a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      bool(const tracked_objects::Location&, const Closure&, base::TimeDelta));
94a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
95a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
96a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)class TaskRunnerProxy : public base::SingleThreadTaskRunner {
97a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) public:
98a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  TaskRunnerProxy(MockTaskRunner* mock) : mock_(mock) {}
99a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual bool RunsTasksOnCurrentThread() const OVERRIDE { return true; }
100a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual bool PostDelayedTask(const tracked_objects::Location& location,
101a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               const Closure& closure,
102a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                               base::TimeDelta delta) OVERRIDE {
103a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return mock_->PostDelayedTask(location, closure, delta);
104a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
105a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual bool PostNonNestableDelayedTask(
106a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      const tracked_objects::Location& location,
107a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      const Closure& closure,
108a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::TimeDelta delta) OVERRIDE {
109a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return mock_->PostNonNestableDelayedTask(location, closure, delta);
110a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
111a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
112a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) private:
113a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  MockTaskRunner* mock_;
114a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  virtual ~TaskRunnerProxy() {}
115a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)};
116a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
117a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(StartupTaskRunnerTest, SynchronousExecution) {
118a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  MockTaskRunner mock_runner;
119a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
120a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
121a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
122a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
123a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
124424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  StartupTaskRunner runner(base::Bind(&Observer), proxy);
125a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
126a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StartupTask task1 =
127a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
128424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.AddTask(task1);
129a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 0);
130a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StartupTask task2 =
131a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
132424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.AddTask(task2);
133a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
134a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Nothing should run until we tell them to.
135a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 0);
136424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.RunAllTasksNow();
137a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
138a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // On an immediate StartupTaskRunner the tasks should now all have run.
139a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 2);
140a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(task_count, 2);
1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(observer_calls, 1);
143a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(observer_result, 0);
1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Running the tasks asynchronously shouldn't do anything
1464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // In particular Post... should not be called
1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  runner.StartRunningTasksAsync();
1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // No more tasks should be run and the observer should not have been called
1504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // again
1514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(task_count, 2);
1524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(observer_calls, 1);
153a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
154a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
155a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(StartupTaskRunnerTest, NullObserver) {
156a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  MockTaskRunner mock_runner;
157a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
158a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
159a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
160a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
161a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
162424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  StartupTaskRunner runner(base::Callback<void(int)>(), proxy);
163a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
164a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StartupTask task1 =
165a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
166424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.AddTask(task1);
167a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 0);
168a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StartupTask task2 =
169a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
170424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.AddTask(task2);
171a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
172a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Nothing should run until we tell them to.
173a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 0);
174424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.RunAllTasksNow();
175a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
176a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // On an immediate StartupTaskRunner the tasks should now all have run.
177a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 2);
1784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(task_count, 2);
1794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Running the tasks asynchronously shouldn't do anything
1814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // In particular Post... should not be called
1824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  runner.StartRunningTasksAsync();
1834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
1844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // No more tasks should have been run
1854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(task_count, 2);
186a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
1874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(observer_calls, 0);
188a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
189a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
190a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(StartupTaskRunnerTest, SynchronousExecutionFailedTask) {
191a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  MockTaskRunner mock_runner;
192a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
193a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
194a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
195a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_CALL(mock_runner, PostNonNestableDelayedTask(_, _, _)).Times(0);
196a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
197424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  StartupTaskRunner runner(base::Bind(&Observer), proxy);
198a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
199a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StartupTask task3 =
200a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this));
201424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.AddTask(task3);
202a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 0);
203a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StartupTask task2 =
204a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
205424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.AddTask(task2);
206a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
207a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Nothing should run until we tell them to.
208a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 0);
209424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.RunAllTasksNow();
210a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
211a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Only the first task should have run, since it failed
212a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 3);
2134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(task_count, 1);
2144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(observer_calls, 1);
215a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(observer_result, 1);
2164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // After a failed task all remaining tasks should be cancelled
2184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // In particular Post... should not be called by running asynchronously
2194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  runner.StartRunningTasksAsync();
2204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // The observer should only be called the first time the queue completes and
2224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // no more tasks should have run
2234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(observer_calls, 1);
2244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(task_count, 1);
225a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
226a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
227a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(StartupTaskRunnerTest, AsynchronousExecution) {
228a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
229a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  MockTaskRunner mock_runner;
230a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
231a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
232a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
233a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_CALL(
234a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      mock_runner,
235a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      PostNonNestableDelayedTask(_, _, base::TimeDelta::FromMilliseconds(0)))
236a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      .Times(testing::Between(2, 3))
237a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      .WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
238a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
239424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  StartupTaskRunner runner(base::Bind(&Observer), proxy);
240a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
241a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StartupTask task1 =
242a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&StartupTaskRunnerTest::Task1, base::Unretained(this));
243424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.AddTask(task1);
244a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StartupTask task2 =
245a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
246424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.AddTask(task2);
247a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
248a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Nothing should run until we tell them to.
249a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 0);
250424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.StartRunningTasksAsync();
251a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
252a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // No tasks should have run yet, since we the message loop hasn't run.
253a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 0);
254a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
255a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Fake the actual message loop. Each time a task is run a new task should
256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // be added to the queue, hence updating "task". The loop should actually run
257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // at most 3 times (once for each task plus possibly once for the observer),
258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // the "4" is a backstop.
2594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (int i = 0; i < 4 && observer_calls == 0; i++) {
260a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    task.Run();
261a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    EXPECT_EQ(i + 1, GetLastTask());
262a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
2634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(task_count, 2);
2644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(observer_calls, 1);
265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(observer_result, 0);
2664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Check that running synchronously now doesn't do anything
2684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
2694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  runner.RunAllTasksNow();
2704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(task_count, 2);
2714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(observer_calls, 1);
272a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
273a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
274a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)TEST_F(StartupTaskRunnerTest, AsynchronousExecutionFailedTask) {
275a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
276a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  MockTaskRunner mock_runner;
277a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  scoped_refptr<TaskRunnerProxy> proxy = new TaskRunnerProxy(&mock_runner);
278a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
279a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_CALL(mock_runner, PostDelayedTask(_, _, _)).Times(0);
280a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_CALL(
281a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      mock_runner,
282a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      PostNonNestableDelayedTask(_, _, base::TimeDelta::FromMilliseconds(0)))
283a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      .Times(testing::Between(1, 2))
284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      .WillRepeatedly(WithArg<1>(Invoke(SaveTaskArg)));
285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
286424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  StartupTaskRunner runner(base::Bind(&Observer), proxy);
287a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
288a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StartupTask task3 =
289a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&StartupTaskRunnerTest::FailingTask, base::Unretained(this));
290424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.AddTask(task3);
291a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  StartupTask task2 =
292a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      base::Bind(&StartupTaskRunnerTest::Task2, base::Unretained(this));
293424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.AddTask(task2);
294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
295a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Nothing should run until we tell them to.
296a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 0);
297424c4d7b64af9d0d8fd9624f381f469654d5e3d2Torne (Richard Coles)  runner.StartRunningTasksAsync();
298a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // No tasks should have run yet, since we the message loop hasn't run.
300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 0);
301a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
302a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Fake the actual message loop. Each time a task is run a new task should
303a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // be added to the queue, hence updating "task". The loop should actually run
304a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // at most twice (once for the failed task plus possibly once for the
305a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // observer), the "4" is a backstop.
3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  for (int i = 0; i < 4 && observer_calls == 0; i++) {
307a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    task.Run();
308a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  }
309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(GetLastTask(), 3);
3104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(task_count, 1);
311a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
3124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(observer_calls, 1);
313a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  EXPECT_EQ(observer_result, 1);
3144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)
3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  // Check that running synchronously now doesn't do anything
3164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  runner.RunAllTasksNow();
3174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(observer_calls, 1);
3184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  EXPECT_EQ(task_count, 1);
319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace
321a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}  // namespace content
322