| 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 |