Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(256)

Side by Side Diff: components/offline_pages/core/task_queue_unittest.cc

Issue 2359933007: [Offline pages] Introduces TaskQueue to serialize tasks that asynchronously access SQLStore (Closed)
Patch Set: Created 4 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "components/offline_pages/core/task_queue.h"
6
7 #include <memory>
8
9 #include "base/bind.h"
10 #include "base/test/test_simple_task_runner.h"
11 #include "base/threading/thread_task_runner_handle.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13
14 namespace offline_pages {
15
16 namespace {
17
18 enum class TaskState { NOT_STARTED, STEP_1, STEP_2, COMPLETED };
19
20 // Sample resource consumed by the task during execution. In this set of tests
21 // used to provide the capability to continue the task.
22 class ConsumedResource {
23 public:
24 void Step(const base::Closure& step_callback) { next_step_ = step_callback; }
25 void CompleteStep() {
26 base::Closure temp_ = next_step_;
27 next_step_.Reset();
28 temp_.Run();
29 }
30 bool HasNextStep() const { return !next_step_.is_null(); }
31
32 private:
33 base::Closure next_step_;
34 };
35
36 // Sample test task. This should not be used as a example of task implementation
37 // with respect to callback safety. Otherwise it captures the idea of splitting
38 // the work into multiple steps separated by potentially asynchronous calls
39 // spanning multiple threads.
40 class TestTask : public TaskQueue::Task {
41 public:
42 explicit TestTask(ConsumedResource* resource)
43 : resource_(resource),
44 state_(TaskState::NOT_STARTED),
45 leave_early_(false) {}
46 TestTask(ConsumedResource* resource, bool leave_early)
47 : resource_(resource),
48 state_(TaskState::NOT_STARTED),
49 leave_early_(leave_early) {}
50 ~TestTask() override {}
51
52 // Run is Step 1 in our case.
53 void Run() override {
54 state_ = TaskState::STEP_1;
55 resource_->Step(base::Bind(&TestTask::Step2, base::Unretained(this)));
56 }
57
58 void Step2() {
59 if (leave_early_) {
60 LastStep();
61 return;
62 }
63 state_ = TaskState::STEP_2;
64 resource_->Step(base::Bind(&TestTask::LastStep, base::Unretained(this)));
65 }
66
67 // This is step 3, but we conclude here.
68 void LastStep() {
69 state_ = TaskState::COMPLETED;
70 Complete();
71 }
72
73 TaskState state() const { return state_; }
74
75 private:
76 ConsumedResource* resource_;
77 TaskState state_;
78 bool leave_early_;
79 };
80
81 } // namespace
82
83 class OfflineTaskQueueTest : public testing::Test {
84 public:
85 OfflineTaskQueueTest();
86
87 void TaskCompleted(TaskQueue::Task* task);
88 void PumpLoop();
89
90 TaskQueue::Task* completed_task() const { return completed_task_; }
91
92 private:
93 TaskQueue::Task* completed_task_;
94 scoped_refptr<base::TestSimpleTaskRunner> task_runner_;
95 base::ThreadTaskRunnerHandle task_runner_handle_;
96 };
97
98 OfflineTaskQueueTest::OfflineTaskQueueTest()
99 : completed_task_(nullptr),
100 task_runner_(new base::TestSimpleTaskRunner),
101 task_runner_handle_(task_runner_) {}
102
103 void OfflineTaskQueueTest::PumpLoop() {
104 task_runner_->RunUntilIdle();
105 }
106
107 void OfflineTaskQueueTest::TaskCompleted(TaskQueue::Task* task) {
108 completed_task_ = task;
109 }
110
111 TEST_F(OfflineTaskQueueTest, RunTaskStepByStep) {
112 ConsumedResource resource;
113 TestTask task(&resource);
114 task.SetCompletionCallback(
115 base::ThreadTaskRunnerHandle::Get(),
116 base::Bind(&OfflineTaskQueueTest::TaskCompleted, base::Unretained(this)));
117
118 EXPECT_EQ(TaskState::NOT_STARTED, task.state());
119 task.Run();
120 EXPECT_EQ(TaskState::STEP_1, task.state());
121 EXPECT_TRUE(resource.HasNextStep());
122 resource.CompleteStep();
123 EXPECT_EQ(TaskState::STEP_2, task.state());
124 EXPECT_TRUE(resource.HasNextStep());
125 resource.CompleteStep();
126 EXPECT_EQ(TaskState::COMPLETED, task.state());
127 PumpLoop();
128 EXPECT_EQ(completed_task(), &task);
129 }
130
131 TEST_F(OfflineTaskQueueTest, AddAndRunSingleTask) {
132 ConsumedResource resource;
133 std::unique_ptr<TestTask> task(new TestTask(&resource));
134 TestTask* task_ptr = task.get();
135 TaskQueue queue;
136 EXPECT_EQ(TaskState::NOT_STARTED, task_ptr->state());
137 queue.AddTask(std::move(task));
138 EXPECT_TRUE(queue.HasTasks());
139 EXPECT_TRUE(queue.CurrentlyRunning());
140 EXPECT_EQ(TaskState::STEP_1, task_ptr->state());
141 EXPECT_TRUE(resource.HasNextStep());
142 resource.CompleteStep();
143
144 EXPECT_EQ(TaskState::STEP_2, task_ptr->state());
145 EXPECT_TRUE(resource.HasNextStep());
146 resource.CompleteStep();
147
148 EXPECT_EQ(TaskState::COMPLETED, task_ptr->state());
149 EXPECT_FALSE(resource.HasNextStep());
150 PumpLoop(); // Deletes task, task_ptr is invalid after that.
151
152 EXPECT_FALSE(queue.CurrentlyRunning());
153 EXPECT_FALSE(queue.HasTasks());
154 }
155
156 TEST_F(OfflineTaskQueueTest, AddAndRunMultipleTasks) {
157 ConsumedResource resource;
158 std::unique_ptr<TestTask> task_1(new TestTask(&resource));
159 TestTask* task_1_ptr = task_1.get();
160 std::unique_ptr<TestTask> task_2(new TestTask(&resource));
161 TestTask* task_2_ptr = task_2.get();
162
163 TaskQueue queue;
164 EXPECT_EQ(TaskState::NOT_STARTED, task_1_ptr->state());
165 EXPECT_EQ(TaskState::NOT_STARTED, task_2_ptr->state());
166 queue.AddTask(std::move(task_1));
167 queue.AddTask(std::move(task_2));
168 EXPECT_TRUE(queue.HasTasks());
169 EXPECT_TRUE(queue.CurrentlyRunning());
170 EXPECT_EQ(TaskState::STEP_1, task_1_ptr->state());
171 EXPECT_EQ(TaskState::NOT_STARTED, task_2_ptr->state());
172 resource.CompleteStep();
173
174 EXPECT_EQ(TaskState::STEP_2, task_1_ptr->state());
175 EXPECT_EQ(TaskState::NOT_STARTED, task_2_ptr->state());
176 resource.CompleteStep();
177
178 EXPECT_EQ(TaskState::COMPLETED, task_1_ptr->state());
179 EXPECT_EQ(TaskState::NOT_STARTED, task_2_ptr->state());
180 PumpLoop(); // Deletes task_1, task_1_ptr is invalid after that.
181 EXPECT_EQ(TaskState::STEP_1, task_2_ptr->state());
182 }
183
184 TEST_F(OfflineTaskQueueTest, LeaveEearly) {
185 ConsumedResource resource;
186 std::unique_ptr<TestTask> task(new TestTask(&resource, true));
187 TestTask* task_ptr = task.get();
188 TaskQueue queue;
189 EXPECT_EQ(TaskState::NOT_STARTED, task_ptr->state());
190 queue.AddTask(std::move(task));
191 EXPECT_TRUE(queue.HasTasks());
192 EXPECT_TRUE(queue.CurrentlyRunning());
193 EXPECT_EQ(TaskState::STEP_1, task_ptr->state());
194 EXPECT_TRUE(resource.HasNextStep());
195 resource.CompleteStep();
196
197 EXPECT_EQ(TaskState::COMPLETED, task_ptr->state());
198 EXPECT_FALSE(resource.HasNextStep());
199 PumpLoop(); // Deletes task, task_ptr is invalid after that.
200
201 EXPECT_FALSE(queue.CurrentlyRunning());
202 EXPECT_FALSE(queue.HasTasks());
203 }
204
205 } // namespace offline_pages
OLDNEW
« components/offline_pages/core/task_queue.cc ('K') | « components/offline_pages/core/task_queue.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698