1 // Copyright 2015 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 "chrome/browser/chromeos/file_system_provider/queue.h"
9 #include "base/files/file.h"
10 #include "base/run_loop.h"
11 #include "content/public/test/test_browser_thread_bundle.h"
12 #include "testing/gtest/include/gtest/gtest.h"
15 namespace file_system_provider
{
18 void OnAbort(int* abort_counter
) {
22 AbortCallback
OnRun(int* run_counter
, int* abort_counter
) {
24 return base::Bind(&OnAbort
, abort_counter
);
27 #if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST)
29 AbortCallback
OnRunNonAbortable(int* run_counter
, int* abort_counter
) {
31 return AbortCallback();
38 class FileSystemProviderQueueTest
: public testing::Test
{
40 FileSystemProviderQueueTest() {}
41 ~FileSystemProviderQueueTest() override
{}
43 content::TestBrowserThreadBundle thread_bundle_
;
46 TEST_F(FileSystemProviderQueueTest
, NewToken
) {
48 EXPECT_EQ(1u, queue
.NewToken());
49 EXPECT_EQ(2u, queue
.NewToken());
50 EXPECT_EQ(3u, queue
.NewToken());
53 TEST_F(FileSystemProviderQueueTest
, Enqueue_OneAtOnce
) {
55 const size_t first_token
= queue
.NewToken();
56 int first_counter
= 0;
57 int first_abort_counter
= 0;
58 queue
.Enqueue(first_token
,
59 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
61 const size_t second_token
= queue
.NewToken();
62 int second_counter
= 0;
63 int second_abort_counter
= 0;
64 queue
.Enqueue(second_token
,
65 base::Bind(&OnRun
, &second_counter
, &second_abort_counter
));
67 base::RunLoop().RunUntilIdle();
68 EXPECT_EQ(1, first_counter
);
69 EXPECT_EQ(0, first_abort_counter
);
70 EXPECT_EQ(0, second_counter
);
71 EXPECT_EQ(0, second_abort_counter
);
73 // Complete the first task, which should not run the second one, yet.
74 queue
.Complete(first_token
);
75 base::RunLoop().RunUntilIdle();
76 EXPECT_EQ(1, first_counter
);
77 EXPECT_EQ(0, first_abort_counter
);
78 EXPECT_EQ(0, second_counter
);
79 EXPECT_EQ(0, second_abort_counter
);
81 // Removing the first task from the queue should run the second task.
82 queue
.Remove(first_token
);
83 base::RunLoop().RunUntilIdle();
84 EXPECT_EQ(1, first_counter
);
85 EXPECT_EQ(0, first_abort_counter
);
86 EXPECT_EQ(1, second_counter
);
87 EXPECT_EQ(0, second_abort_counter
);
89 const size_t third_token
= queue
.NewToken();
90 int third_counter
= 0;
91 int third_abort_counter
= 0;
92 queue
.Enqueue(third_token
,
93 base::Bind(&OnRun
, &third_counter
, &third_abort_counter
));
95 // The second task is still running, so the third one is blocked.
96 base::RunLoop().RunUntilIdle();
97 EXPECT_EQ(1, first_counter
);
98 EXPECT_EQ(0, first_abort_counter
);
99 EXPECT_EQ(1, second_counter
);
100 EXPECT_EQ(0, second_abort_counter
);
101 EXPECT_EQ(0, third_counter
);
102 EXPECT_EQ(0, third_abort_counter
);
104 // After aborting the second task, the third should run.
105 queue
.Abort(second_token
);
106 queue
.Remove(second_token
);
107 base::RunLoop().RunUntilIdle();
108 EXPECT_EQ(1, first_counter
);
109 EXPECT_EQ(0, first_abort_counter
);
110 EXPECT_EQ(1, second_counter
);
111 EXPECT_EQ(1, second_abort_counter
);
112 EXPECT_EQ(1, third_counter
);
113 EXPECT_EQ(0, third_abort_counter
);
116 TEST_F(FileSystemProviderQueueTest
, Enqueue_WhilePreviousNotRemoved
) {
118 const size_t first_token
= queue
.NewToken();
119 int first_counter
= 0;
120 int first_abort_counter
= 0;
121 queue
.Enqueue(first_token
,
122 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
124 base::RunLoop().RunUntilIdle();
125 queue
.Complete(first_token
);
127 // Enqueuing a new task must not start it, once the queue is filled with a
129 const size_t second_token
= queue
.NewToken();
130 int second_counter
= 0;
131 int second_abort_counter
= 0;
132 queue
.Enqueue(second_token
,
133 base::Bind(&OnRun
, &second_counter
, &second_abort_counter
));
135 base::RunLoop().RunUntilIdle();
136 EXPECT_EQ(0, second_counter
);
137 EXPECT_EQ(0, second_abort_counter
);
140 TEST_F(FileSystemProviderQueueTest
, Enqueue_MultipleAtOnce
) {
142 const size_t first_token
= queue
.NewToken();
143 int first_counter
= 0;
144 int first_abort_counter
= 0;
145 queue
.Enqueue(first_token
,
146 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
148 const size_t second_token
= queue
.NewToken();
149 int second_counter
= 0;
150 int second_abort_counter
= 0;
151 queue
.Enqueue(second_token
,
152 base::Bind(&OnRun
, &second_counter
, &second_abort_counter
));
154 const size_t third_token
= queue
.NewToken();
155 int third_counter
= 0;
156 int third_abort_counter
= 0;
157 queue
.Enqueue(third_token
,
158 base::Bind(&OnRun
, &third_counter
, &third_abort_counter
));
160 base::RunLoop().RunUntilIdle();
161 EXPECT_EQ(1, first_counter
);
162 EXPECT_EQ(0, first_abort_counter
);
163 EXPECT_EQ(1, second_counter
);
164 EXPECT_EQ(0, second_abort_counter
);
165 EXPECT_EQ(0, third_counter
);
166 EXPECT_EQ(0, third_abort_counter
);
168 // Completing and removing the second task, should start the last one.
169 queue
.Complete(second_token
);
170 queue
.Remove(second_token
);
171 base::RunLoop().RunUntilIdle();
172 EXPECT_EQ(1, first_counter
);
173 EXPECT_EQ(0, first_abort_counter
);
174 EXPECT_EQ(1, second_counter
);
175 EXPECT_EQ(0, second_abort_counter
);
176 EXPECT_EQ(1, third_counter
);
177 EXPECT_EQ(0, third_abort_counter
);
180 #if !defined(NDEBUG) && defined(GTEST_HAS_DEATH_TEST)
182 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_DuplicatedTokens
) {
184 const size_t first_token
= queue
.NewToken();
185 int first_counter
= 0;
186 int first_abort_counter
= 0;
187 queue
.Enqueue(first_token
,
188 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
190 // Use the first token on purpose.
191 int second_counter
= 0;
192 int second_abort_counter
= 0;
193 EXPECT_DEATH(queue
.Enqueue(first_token
, base::Bind(&OnRun
, &second_counter
,
194 &second_abort_counter
)),
198 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_CompleteNotStarted
) {
200 const size_t first_token
= queue
.NewToken();
201 int first_counter
= 0;
202 int first_abort_counter
= 0;
203 queue
.Enqueue(first_token
,
204 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
206 // Completing and removing the first task, which however hasn't started.
207 // That should not invoke the second task.
208 EXPECT_DEATH(queue
.Complete(first_token
), "");
209 EXPECT_DEATH(queue
.Remove(first_token
), "");
212 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_RemoveNotCompletedNorAborted
) {
214 const size_t first_token
= queue
.NewToken();
215 int first_counter
= 0;
216 int first_abort_counter
= 0;
217 queue
.Enqueue(first_token
,
218 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
220 base::RunLoop().RunUntilIdle();
222 // Remove before completing.
223 EXPECT_DEATH(queue
.Remove(first_token
), "");
226 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_CompleteAfterAborting
) {
228 const size_t first_token
= queue
.NewToken();
229 int first_counter
= 0;
230 int first_abort_counter
= 0;
231 queue
.Enqueue(first_token
,
232 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
234 base::RunLoop().RunUntilIdle();
237 std::vector
<base::File::Error
> first_abort_callback_log
;
238 queue
.Abort(first_token
);
240 EXPECT_DEATH(queue
.Complete(first_token
), "");
243 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_AbortAfterCompleting
) {
245 const size_t first_token
= queue
.NewToken();
246 int first_counter
= 0;
247 int first_abort_counter
= 0;
248 queue
.Enqueue(first_token
,
249 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
251 base::RunLoop().RunUntilIdle();
253 queue
.Complete(first_token
);
254 EXPECT_DEATH(queue
.Abort(first_token
), "");
257 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_CompleteTwice
) {
259 const size_t first_token
= queue
.NewToken();
260 int first_counter
= 0;
261 int first_abort_counter
= 0;
262 queue
.Enqueue(first_token
,
263 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
265 base::RunLoop().RunUntilIdle();
267 queue
.Complete(first_token
);
268 EXPECT_DEATH(queue
.Complete(first_token
), "");
271 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_AbortTwice
) {
273 const size_t first_token
= queue
.NewToken();
274 int first_counter
= 0;
275 int first_abort_counter
= 0;
276 queue
.Enqueue(first_token
,
277 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
279 base::RunLoop().RunUntilIdle();
281 queue
.Abort(first_token
);
282 EXPECT_DEATH(queue
.Abort(first_token
), "");
285 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_IsAbortedWhileNotInQueue
) {
287 EXPECT_DEATH(queue
.IsAborted(1234), "");
290 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_IsAbortedAfterRemoved
) {
292 const size_t first_token
= queue
.NewToken();
293 int first_counter
= 0;
294 int first_abort_counter
= 0;
295 queue
.Enqueue(first_token
,
296 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
298 base::RunLoop().RunUntilIdle();
300 queue
.Abort(first_token
);
301 queue
.Remove(first_token
);
302 EXPECT_DEATH(queue
.IsAborted(first_token
), "");
305 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_RemoveTwice
) {
307 const size_t first_token
= queue
.NewToken();
308 int first_counter
= 0;
309 int first_abort_counter
= 0;
310 queue
.Enqueue(first_token
,
311 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
313 base::RunLoop().RunUntilIdle();
315 queue
.Complete(first_token
);
316 queue
.Remove(first_token
);
317 EXPECT_DEATH(queue
.Complete(first_token
), "");
320 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_AbortAfterRemoving
) {
322 const size_t first_token
= queue
.NewToken();
323 int first_counter
= 0;
324 int first_abort_counter
= 0;
325 queue
.Enqueue(first_token
,
326 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
328 base::RunLoop().RunUntilIdle();
330 queue
.Complete(first_token
);
331 queue
.Remove(first_token
);
332 EXPECT_DEATH(queue
.Abort(first_token
), "");
335 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_CompleteAfterRemoving
) {
337 const size_t first_token
= queue
.NewToken();
338 int first_counter
= 0;
339 int first_abort_counter
= 0;
340 queue
.Enqueue(first_token
,
341 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
343 base::RunLoop().RunUntilIdle();
345 queue
.Complete(first_token
);
346 queue
.Remove(first_token
);
347 EXPECT_DEATH(queue
.Complete(first_token
), "");
350 TEST_F(FileSystemProviderQueueTest
, InvalidUsage_AbortNonAbortable
) {
352 const size_t first_token
= queue
.NewToken();
353 int first_counter
= 0;
354 int first_abort_counter
= 0;
355 queue
.Enqueue(first_token
, base::Bind(&OnRunNonAbortable
, &first_counter
,
356 &first_abort_counter
));
358 base::RunLoop().RunUntilIdle();
360 EXPECT_DEATH(queue
.Abort(first_token
), "");
365 TEST_F(FileSystemProviderQueueTest
, Enqueue_Abort
) {
367 const size_t first_token
= queue
.NewToken();
368 int first_counter
= 0;
369 int first_abort_counter
= 0;
370 queue
.Enqueue(first_token
,
371 base::Bind(&OnRun
, &first_counter
, &first_abort_counter
));
373 const size_t second_token
= queue
.NewToken();
374 int second_counter
= 0;
375 int second_abort_counter
= 0;
376 queue
.Enqueue(second_token
,
377 base::Bind(&OnRun
, &second_counter
, &second_abort_counter
));
379 base::RunLoop().RunUntilIdle();
380 EXPECT_EQ(1, first_counter
);
381 EXPECT_EQ(0, first_abort_counter
);
382 EXPECT_EQ(0, second_counter
);
383 EXPECT_EQ(0, second_abort_counter
);
385 // Abort the first task while it's being executed.
386 EXPECT_FALSE(queue
.IsAborted(first_token
));
387 queue
.Abort(first_token
);
388 EXPECT_TRUE(queue
.IsAborted(first_token
));
389 queue
.Remove(first_token
);
391 // Abort the second task, before it's started.
392 EXPECT_EQ(0, second_counter
);
393 EXPECT_FALSE(queue
.IsAborted(second_token
));
394 queue
.Abort(second_token
);
395 EXPECT_TRUE(queue
.IsAborted(second_token
));
396 queue
.Remove(second_token
);
398 base::RunLoop().RunUntilIdle();
399 EXPECT_EQ(1, first_counter
);
400 EXPECT_EQ(1, first_abort_counter
);
401 EXPECT_EQ(0, second_counter
);
402 EXPECT_EQ(0, second_abort_counter
);
405 } // namespace file_system_provider
406 } // namespace chromeos