Roll src/third_party/WebKit f36d5e0:68b67cd (svn 193299:193303)
[chromium-blink-merge.git] / sync / internal_api / attachments / task_queue_unittest.cc
blob361d49c6dced7d08066875cdd92a1f566f2c920c
1 // Copyright 2014 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.
5 #include "sync/internal_api/public/attachments/task_queue.h"
7 #include <vector>
9 #include "base/bind.h"
10 #include "base/memory/weak_ptr.h"
11 #include "base/message_loop/message_loop.h"
12 #include "base/run_loop.h"
13 #include "base/timer/mock_timer.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using base::TimeDelta;
18 namespace syncer {
20 namespace {
22 const TimeDelta kZero;
24 } // namespace
26 class TaskQueueTest : public testing::Test {
27 protected:
28 TaskQueueTest() : weak_ptr_factory_(this) {
29 queue_.reset(new TaskQueue<int>(
30 base::Bind(&TaskQueueTest::Process, weak_ptr_factory_.GetWeakPtr()),
31 TimeDelta::FromMinutes(1),
32 TimeDelta::FromMinutes(8)));
35 void RunLoop() {
36 base::RunLoop run_loop;
37 run_loop.RunUntilIdle();
40 void Process(const int& task) { dispatched_.push_back(task); }
42 base::MessageLoop message_loop_;
43 scoped_ptr<TaskQueue<int> > queue_;
44 std::vector<int> dispatched_;
45 base::WeakPtrFactory<TaskQueueTest> weak_ptr_factory_;
48 // See that at most one task is dispatched at a time.
49 TEST_F(TaskQueueTest, AddToQueue_NoConcurrentTasks) {
50 queue_->AddToQueue(1);
51 queue_->AddToQueue(2);
52 RunLoop();
54 // Only one has been dispatched.
55 ASSERT_EQ(1U, dispatched_.size());
56 EXPECT_EQ(1, dispatched_.front());
57 RunLoop();
59 // Still only one.
60 ASSERT_EQ(1U, dispatched_.size());
61 EXPECT_EQ(1, dispatched_.front());
62 dispatched_.clear();
63 queue_->MarkAsSucceeded(1);
64 RunLoop();
66 ASSERT_EQ(1U, dispatched_.size());
67 EXPECT_EQ(2, dispatched_.front());
68 dispatched_.clear();
69 queue_->MarkAsSucceeded(2);
70 RunLoop();
72 ASSERT_TRUE(dispatched_.empty());
75 // See that that the queue ignores duplicate adds.
76 TEST_F(TaskQueueTest, AddToQueue_NoDuplicates) {
77 queue_->AddToQueue(1);
78 queue_->AddToQueue(1);
79 queue_->AddToQueue(2);
80 queue_->AddToQueue(1);
81 ASSERT_TRUE(dispatched_.empty());
82 RunLoop();
84 ASSERT_EQ(1U, dispatched_.size());
85 EXPECT_EQ(1, dispatched_.front());
86 dispatched_.clear();
87 queue_->MarkAsSucceeded(1);
88 RunLoop();
90 ASSERT_EQ(1U, dispatched_.size());
91 EXPECT_EQ(2, dispatched_.front());
92 dispatched_.clear();
93 queue_->MarkAsSucceeded(2);
94 RunLoop();
96 ASSERT_TRUE(dispatched_.empty());
99 // See that Retry works as expected.
100 TEST_F(TaskQueueTest, Retry) {
101 scoped_ptr<base::MockTimer> timer_to_pass(new base::MockTimer(false, false));
102 base::MockTimer* mock_timer = timer_to_pass.get();
103 queue_->SetTimerForTest(timer_to_pass.Pass());
105 // 1st attempt.
106 queue_->AddToQueue(1);
107 ASSERT_TRUE(mock_timer->IsRunning());
108 ASSERT_EQ(kZero, mock_timer->GetCurrentDelay());
109 TimeDelta last_delay = mock_timer->GetCurrentDelay();
110 mock_timer->Fire();
111 RunLoop();
113 // 2nd attempt.
114 ASSERT_FALSE(mock_timer->IsRunning());
115 ASSERT_EQ(1U, dispatched_.size());
116 EXPECT_EQ(1, dispatched_.front());
117 dispatched_.clear();
118 queue_->MarkAsFailed(1);
119 queue_->AddToQueue(1);
120 ASSERT_TRUE(mock_timer->IsRunning());
121 EXPECT_GT(mock_timer->GetCurrentDelay(), last_delay);
122 EXPECT_LE(mock_timer->GetCurrentDelay(), TimeDelta::FromMinutes(1));
123 last_delay = mock_timer->GetCurrentDelay();
124 mock_timer->Fire();
125 RunLoop();
127 // 3rd attempt.
128 ASSERT_FALSE(mock_timer->IsRunning());
129 ASSERT_EQ(1U, dispatched_.size());
130 EXPECT_EQ(1, dispatched_.front());
131 dispatched_.clear();
132 queue_->MarkAsFailed(1);
133 queue_->AddToQueue(1);
134 ASSERT_TRUE(mock_timer->IsRunning());
135 EXPECT_GT(mock_timer->GetCurrentDelay(), last_delay);
136 last_delay = mock_timer->GetCurrentDelay();
137 mock_timer->Fire();
138 RunLoop();
140 // Give up.
141 ASSERT_FALSE(mock_timer->IsRunning());
142 ASSERT_EQ(1U, dispatched_.size());
143 EXPECT_EQ(1, dispatched_.front());
144 dispatched_.clear();
145 queue_->Cancel(1);
146 ASSERT_FALSE(mock_timer->IsRunning());
148 // Try a different task. See the timer remains unchanged because the previous
149 // task was cancelled.
150 ASSERT_TRUE(dispatched_.empty());
151 queue_->AddToQueue(2);
152 ASSERT_TRUE(mock_timer->IsRunning());
153 EXPECT_GE(last_delay, mock_timer->GetCurrentDelay());
154 last_delay = mock_timer->GetCurrentDelay();
155 mock_timer->Fire();
156 RunLoop();
158 // Mark this one as succeeding, which will clear the backoff delay.
159 ASSERT_FALSE(mock_timer->IsRunning());
160 ASSERT_EQ(1U, dispatched_.size());
161 EXPECT_EQ(2, dispatched_.front());
162 dispatched_.clear();
163 queue_->MarkAsSucceeded(2);
164 ASSERT_FALSE(mock_timer->IsRunning());
166 // Add one last task and see that it's dispatched without delay because the
167 // previous one succeeded.
168 ASSERT_TRUE(dispatched_.empty());
169 queue_->AddToQueue(3);
170 ASSERT_TRUE(mock_timer->IsRunning());
171 EXPECT_LT(mock_timer->GetCurrentDelay(), last_delay);
172 last_delay = mock_timer->GetCurrentDelay();
173 mock_timer->Fire();
174 RunLoop();
176 // Clean up.
177 ASSERT_EQ(1U, dispatched_.size());
178 EXPECT_EQ(3, dispatched_.front());
179 dispatched_.clear();
180 queue_->MarkAsSucceeded(3);
181 ASSERT_FALSE(mock_timer->IsRunning());
184 TEST_F(TaskQueueTest, Cancel) {
185 queue_->AddToQueue(1);
186 RunLoop();
188 ASSERT_EQ(1U, dispatched_.size());
189 EXPECT_EQ(1, dispatched_.front());
190 dispatched_.clear();
191 queue_->Cancel(1);
192 RunLoop();
194 ASSERT_TRUE(dispatched_.empty());
197 // See that ResetBackoff resets the backoff delay.
198 TEST_F(TaskQueueTest, ResetBackoff) {
199 scoped_ptr<base::MockTimer> timer_to_pass(new base::MockTimer(false, false));
200 base::MockTimer* mock_timer = timer_to_pass.get();
201 queue_->SetTimerForTest(timer_to_pass.Pass());
203 // Add an item, mark it as failed, re-add it and see that we now have a
204 // backoff delay.
205 queue_->AddToQueue(1);
206 ASSERT_TRUE(mock_timer->IsRunning());
207 ASSERT_EQ(kZero, mock_timer->GetCurrentDelay());
208 mock_timer->Fire();
209 RunLoop();
210 ASSERT_FALSE(mock_timer->IsRunning());
211 ASSERT_EQ(1U, dispatched_.size());
212 EXPECT_EQ(1, dispatched_.front());
213 dispatched_.clear();
214 queue_->MarkAsFailed(1);
215 queue_->AddToQueue(1);
216 ASSERT_TRUE(mock_timer->IsRunning());
217 EXPECT_GT(mock_timer->GetCurrentDelay(), kZero);
218 EXPECT_LE(mock_timer->GetCurrentDelay(), TimeDelta::FromMinutes(1));
220 // Call ResetBackoff and see that there is no longer a delay.
221 queue_->ResetBackoff();
222 ASSERT_TRUE(mock_timer->IsRunning());
223 ASSERT_EQ(kZero, mock_timer->GetCurrentDelay());
224 mock_timer->Fire();
225 RunLoop();
226 ASSERT_FALSE(mock_timer->IsRunning());
227 ASSERT_EQ(1U, dispatched_.size());
228 EXPECT_EQ(1, dispatched_.front());
229 dispatched_.clear();
230 queue_->MarkAsSucceeded(1);
233 } // namespace syncer