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