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"
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
;
22 const TimeDelta kZero
;
26 class TaskQueueTest
: public testing::Test
{
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)));
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);
54 // Only one has been dispatched.
55 ASSERT_EQ(1U, dispatched_
.size());
56 EXPECT_EQ(1, dispatched_
.front());
60 ASSERT_EQ(1U, dispatched_
.size());
61 EXPECT_EQ(1, dispatched_
.front());
63 queue_
->MarkAsSucceeded(1);
66 ASSERT_EQ(1U, dispatched_
.size());
67 EXPECT_EQ(2, dispatched_
.front());
69 queue_
->MarkAsSucceeded(2);
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());
84 ASSERT_EQ(1U, dispatched_
.size());
85 EXPECT_EQ(1, dispatched_
.front());
87 queue_
->MarkAsSucceeded(1);
90 ASSERT_EQ(1U, dispatched_
.size());
91 EXPECT_EQ(2, dispatched_
.front());
93 queue_
->MarkAsSucceeded(2);
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());
106 queue_
->AddToQueue(1);
107 ASSERT_TRUE(mock_timer
->IsRunning());
108 ASSERT_EQ(kZero
, mock_timer
->GetCurrentDelay());
109 TimeDelta last_delay
= mock_timer
->GetCurrentDelay();
114 ASSERT_FALSE(mock_timer
->IsRunning());
115 ASSERT_EQ(1U, dispatched_
.size());
116 EXPECT_EQ(1, dispatched_
.front());
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();
128 ASSERT_FALSE(mock_timer
->IsRunning());
129 ASSERT_EQ(1U, dispatched_
.size());
130 EXPECT_EQ(1, dispatched_
.front());
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();
141 ASSERT_FALSE(mock_timer
->IsRunning());
142 ASSERT_EQ(1U, dispatched_
.size());
143 EXPECT_EQ(1, dispatched_
.front());
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();
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());
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();
177 ASSERT_EQ(1U, dispatched_
.size());
178 EXPECT_EQ(3, dispatched_
.front());
180 queue_
->MarkAsSucceeded(3);
181 ASSERT_FALSE(mock_timer
->IsRunning());
184 TEST_F(TaskQueueTest
, Cancel
) {
185 queue_
->AddToQueue(1);
188 ASSERT_EQ(1U, dispatched_
.size());
189 EXPECT_EQ(1, dispatched_
.front());
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
205 queue_
->AddToQueue(1);
206 ASSERT_TRUE(mock_timer
->IsRunning());
207 ASSERT_EQ(kZero
, mock_timer
->GetCurrentDelay());
210 ASSERT_FALSE(mock_timer
->IsRunning());
211 ASSERT_EQ(1U, dispatched_
.size());
212 EXPECT_EQ(1, dispatched_
.front());
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());
226 ASSERT_FALSE(mock_timer
->IsRunning());
227 ASSERT_EQ(1U, dispatched_
.size());
228 EXPECT_EQ(1, dispatched_
.front());
230 queue_
->MarkAsSucceeded(1);
233 } // namespace syncer