1 // Copyright (c) 2012 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 "webkit/fileapi/syncable/local_file_change_tracker.h"
10 #include "base/basictypes.h"
11 #include "base/files/scoped_temp_dir.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop.h"
14 #include "base/message_loop_proxy.h"
15 #include "base/stl_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17 #include "webkit/blob/mock_blob_url_request_context.h"
18 #include "webkit/browser/fileapi/file_system_task_runners.h"
19 #include "webkit/fileapi/file_system_context.h"
20 #include "webkit/fileapi/syncable/canned_syncable_file_system.h"
21 #include "webkit/fileapi/syncable/local_file_sync_context.h"
22 #include "webkit/fileapi/syncable/sync_status_code.h"
23 #include "webkit/fileapi/syncable/syncable_file_system_util.h"
24 #include "webkit/quota/quota_manager.h"
26 using fileapi::FileSystemContext
;
27 using fileapi::FileSystemURL
;
28 using fileapi::FileSystemURLSet
;
29 using webkit_blob::MockBlobURLRequestContext
;
30 using webkit_blob::ScopedTextBlob
;
32 namespace sync_file_system
{
34 class LocalFileChangeTrackerTest
: public testing::Test
{
36 LocalFileChangeTrackerTest()
37 : message_loop_(base::MessageLoop::TYPE_IO
),
38 file_system_(GURL("http://example.com"),
40 base::MessageLoopProxy::current(),
41 base::MessageLoopProxy::current()) {}
43 virtual void SetUp() OVERRIDE
{
46 sync_context_
= new LocalFileSyncContext(base::MessageLoopProxy::current(),
47 base::MessageLoopProxy::current());
48 ASSERT_EQ(sync_file_system::SYNC_STATUS_OK
,
49 file_system_
.MaybeInitializeFileSystemContext(sync_context_
));
52 virtual void TearDown() OVERRIDE
{
54 sync_context_
->ShutdownOnUIThread();
57 message_loop_
.RunUntilIdle();
58 file_system_
.TearDown();
59 // Make sure we don't leave the external filesystem.
60 // (CannedSyncableFileSystem::TearDown does not do this as there may be
61 // multiple syncable file systems registered for the name)
62 RevokeSyncableFileSystem("test");
66 FileSystemURL
URL(const std::string
& path
) {
67 return file_system_
.URL(path
);
70 FileSystemContext
* file_system_context() {
71 return file_system_
.file_system_context();
74 LocalFileChangeTracker
* change_tracker() {
75 return file_system_context()->change_tracker();
78 void VerifyAndClearChange(const FileSystemURL
& url
,
79 const FileChange
& expected_change
) {
80 SCOPED_TRACE(testing::Message() << url
.DebugString() <<
81 " expecting:" << expected_change
.DebugString());
82 // Get the changes for URL and verify.
83 FileChangeList changes
;
84 change_tracker()->GetChangesForURL(url
, &changes
);
85 ASSERT_EQ(1U, changes
.size());
86 SCOPED_TRACE(testing::Message() << url
.DebugString() <<
87 " actual:" << changes
.DebugString());
88 EXPECT_EQ(expected_change
, changes
.list()[0]);
90 // Clear the URL from the change tracker.
91 change_tracker()->ClearChangesForURL(url
);
94 void DropChangesInTracker() {
95 change_tracker()->DropAllChanges();
98 void RestoreChangesFromTrackerDB() {
99 change_tracker()->CollectLastDirtyChanges(file_system_context());
102 base::MessageLoop message_loop_
;
104 CannedSyncableFileSystem file_system_
;
105 scoped_refptr
<LocalFileSyncContext
> sync_context_
;
107 DISALLOW_COPY_AND_ASSIGN(LocalFileChangeTrackerTest
);
110 TEST_F(LocalFileChangeTrackerTest
, GetChanges
) {
111 EXPECT_EQ(base::PLATFORM_FILE_OK
, file_system_
.OpenFileSystem());
113 // Test URLs (no parent/child relationships, as we test such cases
114 // mainly in LocalFileSyncStatusTest).
115 const char kPath0
[] = "test/dir a/dir";
116 const char kPath1
[] = "test/dir b";
117 const char kPath2
[] = "test/foo.txt";
118 const char kPath3
[] = "test/bar";
119 const char kPath4
[] = "temporary/dir a";
120 const char kPath5
[] = "temporary/foo";
122 change_tracker()->OnCreateDirectory(URL(kPath0
));
123 change_tracker()->OnRemoveDirectory(URL(kPath0
)); // Offset the create.
124 change_tracker()->OnRemoveDirectory(URL(kPath1
));
125 change_tracker()->OnCreateDirectory(URL(kPath2
));
126 change_tracker()->OnRemoveFile(URL(kPath3
));
127 change_tracker()->OnModifyFile(URL(kPath4
));
128 change_tracker()->OnCreateFile(URL(kPath5
));
129 change_tracker()->OnRemoveFile(URL(kPath5
)); // Recorded as 'delete'.
131 FileSystemURLSet urls
;
132 file_system_
.GetChangedURLsInTracker(&urls
);
134 EXPECT_EQ(5U, urls
.size());
135 EXPECT_TRUE(ContainsKey(urls
, URL(kPath1
)));
136 EXPECT_TRUE(ContainsKey(urls
, URL(kPath2
)));
137 EXPECT_TRUE(ContainsKey(urls
, URL(kPath3
)));
138 EXPECT_TRUE(ContainsKey(urls
, URL(kPath4
)));
139 EXPECT_TRUE(ContainsKey(urls
, URL(kPath5
)));
141 // Changes for kPath0 must have been offset and removed.
142 EXPECT_FALSE(ContainsKey(urls
, URL(kPath0
)));
144 // GetNextChangedURLs only returns up to max_urls (i.e. 3) urls.
145 std::deque
<FileSystemURL
> urls_to_process
;
146 change_tracker()->GetNextChangedURLs(&urls_to_process
, 3);
147 ASSERT_EQ(3U, urls_to_process
.size());
149 // Let it return all.
150 urls_to_process
.clear();
151 change_tracker()->GetNextChangedURLs(&urls_to_process
, 0);
152 ASSERT_EQ(5U, urls_to_process
.size());
154 // The changes must be in the last-modified-time order.
155 EXPECT_EQ(URL(kPath1
), urls_to_process
[0]);
156 EXPECT_EQ(URL(kPath2
), urls_to_process
[1]);
157 EXPECT_EQ(URL(kPath3
), urls_to_process
[2]);
158 EXPECT_EQ(URL(kPath4
), urls_to_process
[3]);
159 EXPECT_EQ(URL(kPath5
), urls_to_process
[4]);
161 // Modify kPath4 again.
162 change_tracker()->OnModifyFile(URL(kPath4
));
164 // Now the order must be changed.
165 urls_to_process
.clear();
166 change_tracker()->GetNextChangedURLs(&urls_to_process
, 0);
167 ASSERT_EQ(5U, urls_to_process
.size());
168 EXPECT_EQ(URL(kPath1
), urls_to_process
[0]);
169 EXPECT_EQ(URL(kPath2
), urls_to_process
[1]);
170 EXPECT_EQ(URL(kPath3
), urls_to_process
[2]);
171 EXPECT_EQ(URL(kPath5
), urls_to_process
[3]);
172 EXPECT_EQ(URL(kPath4
), urls_to_process
[4]);
174 VerifyAndClearChange(URL(kPath1
),
175 FileChange(FileChange::FILE_CHANGE_DELETE
,
176 sync_file_system::SYNC_FILE_TYPE_DIRECTORY
));
177 VerifyAndClearChange(URL(kPath2
),
178 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
179 sync_file_system::SYNC_FILE_TYPE_DIRECTORY
));
180 VerifyAndClearChange(URL(kPath3
),
181 FileChange(FileChange::FILE_CHANGE_DELETE
,
182 sync_file_system::SYNC_FILE_TYPE_FILE
));
183 VerifyAndClearChange(URL(kPath4
),
184 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
185 sync_file_system::SYNC_FILE_TYPE_FILE
));
186 VerifyAndClearChange(URL(kPath5
),
187 FileChange(FileChange::FILE_CHANGE_DELETE
,
188 sync_file_system::SYNC_FILE_TYPE_FILE
));
191 TEST_F(LocalFileChangeTrackerTest
, RestoreCreateAndModifyChanges
) {
192 EXPECT_EQ(base::PLATFORM_FILE_OK
, file_system_
.OpenFileSystem());
194 FileSystemURLSet urls
;
196 const char kPath0
[] = "file a";
197 const char kPath1
[] = "dir a";
198 const char kPath2
[] = "dir a/dir";
199 const char kPath3
[] = "dir a/file a";
200 const char kPath4
[] = "dir a/file b";
202 file_system_
.GetChangedURLsInTracker(&urls
);
203 ASSERT_EQ(0U, urls
.size());
205 const GURL
blob_url("blob:test");
206 const std::string
kData("Lorem ipsum.");
207 MockBlobURLRequestContext
url_request_context(file_system_context());
208 ScopedTextBlob
blob(url_request_context
, blob_url
, kData
);
210 // Create files and nested directories.
211 EXPECT_EQ(base::PLATFORM_FILE_OK
,
212 file_system_
.CreateFile(URL(kPath0
))); // Creates a file.
213 EXPECT_EQ(base::PLATFORM_FILE_OK
,
214 file_system_
.CreateDirectory(URL(kPath1
))); // Creates a dir.
215 EXPECT_EQ(base::PLATFORM_FILE_OK
,
216 file_system_
.CreateDirectory(URL(kPath2
))); // Creates another dir.
217 EXPECT_EQ(base::PLATFORM_FILE_OK
,
218 file_system_
.CreateFile(URL(kPath3
))); // Creates a file.
219 EXPECT_EQ(base::PLATFORM_FILE_OK
,
220 file_system_
.TruncateFile(URL(kPath3
), 1)); // Modifies the file.
221 EXPECT_EQ(base::PLATFORM_FILE_OK
,
222 file_system_
.CreateFile(URL(kPath4
))); // Creates another file.
223 EXPECT_EQ(static_cast<int64
>(kData
.size()),
224 file_system_
.Write(&url_request_context
,
225 URL(kPath4
), blob_url
)); // Modifies the file.
227 // Verify the changes.
228 file_system_
.GetChangedURLsInTracker(&urls
);
229 EXPECT_EQ(5U, urls
.size());
231 // Reset the changes in in-memory tracker.
232 DropChangesInTracker();
234 // Make sure we have no in-memory changes in the tracker.
235 file_system_
.GetChangedURLsInTracker(&urls
);
236 ASSERT_EQ(0U, urls
.size());
238 RestoreChangesFromTrackerDB();
240 // Make sure the changes are restored from the DB.
241 file_system_
.GetChangedURLsInTracker(&urls
);
242 EXPECT_EQ(5U, urls
.size());
244 VerifyAndClearChange(URL(kPath0
),
245 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
246 sync_file_system::SYNC_FILE_TYPE_FILE
));
247 VerifyAndClearChange(URL(kPath1
),
248 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
249 sync_file_system::SYNC_FILE_TYPE_DIRECTORY
));
250 VerifyAndClearChange(URL(kPath2
),
251 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
252 sync_file_system::SYNC_FILE_TYPE_DIRECTORY
));
253 VerifyAndClearChange(URL(kPath3
),
254 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
255 sync_file_system::SYNC_FILE_TYPE_FILE
));
256 VerifyAndClearChange(URL(kPath4
),
257 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
258 sync_file_system::SYNC_FILE_TYPE_FILE
));
261 TEST_F(LocalFileChangeTrackerTest
, RestoreRemoveChanges
) {
262 EXPECT_EQ(base::PLATFORM_FILE_OK
, file_system_
.OpenFileSystem());
264 FileSystemURLSet urls
;
266 const char kPath0
[] = "file";
267 const char kPath1
[] = "dir a";
268 const char kPath2
[] = "dir b";
269 const char kPath3
[] = "dir b/file";
270 const char kPath4
[] = "dir b/dir c";
271 const char kPath5
[] = "dir b/dir c/file";
273 file_system_
.GetChangedURLsInTracker(&urls
);
274 ASSERT_EQ(0U, urls
.size());
276 // Creates and removes a same file.
277 EXPECT_EQ(base::PLATFORM_FILE_OK
,
278 file_system_
.CreateFile(URL(kPath0
)));
279 EXPECT_EQ(base::PLATFORM_FILE_OK
,
280 file_system_
.Remove(URL(kPath0
), false /* recursive */));
282 // Creates and removes a same directory.
283 EXPECT_EQ(base::PLATFORM_FILE_OK
,
284 file_system_
.CreateDirectory(URL(kPath1
)));
285 EXPECT_EQ(base::PLATFORM_FILE_OK
,
286 file_system_
.Remove(URL(kPath1
), false /* recursive */));
288 // Creates files and nested directories, then removes the parent directory.
289 EXPECT_EQ(base::PLATFORM_FILE_OK
,
290 file_system_
.CreateDirectory(URL(kPath2
)));
291 EXPECT_EQ(base::PLATFORM_FILE_OK
,
292 file_system_
.CreateFile(URL(kPath3
)));
293 EXPECT_EQ(base::PLATFORM_FILE_OK
,
294 file_system_
.CreateDirectory(URL(kPath4
)));
295 EXPECT_EQ(base::PLATFORM_FILE_OK
,
296 file_system_
.CreateFile(URL(kPath5
)));
297 EXPECT_EQ(base::PLATFORM_FILE_OK
,
298 file_system_
.Remove(URL(kPath2
), true /* recursive */));
300 file_system_
.GetChangedURLsInTracker(&urls
);
301 EXPECT_EQ(3U, urls
.size());
303 DropChangesInTracker();
305 // Make sure we have no in-memory changes in the tracker.
306 file_system_
.GetChangedURLsInTracker(&urls
);
307 ASSERT_EQ(0U, urls
.size());
309 RestoreChangesFromTrackerDB();
311 // Make sure the changes are restored from the DB.
312 file_system_
.GetChangedURLsInTracker(&urls
);
313 // Since directories to have been reverted (kPath1, kPath2, kPath4) are
314 // treated as FILE_CHANGE_DELETE, the number of changes should be 6.
315 EXPECT_EQ(6U, urls
.size());
317 VerifyAndClearChange(URL(kPath0
),
318 FileChange(FileChange::FILE_CHANGE_DELETE
,
319 sync_file_system::SYNC_FILE_TYPE_UNKNOWN
));
320 VerifyAndClearChange(URL(kPath1
),
321 FileChange(FileChange::FILE_CHANGE_DELETE
,
322 sync_file_system::SYNC_FILE_TYPE_UNKNOWN
));
323 VerifyAndClearChange(URL(kPath2
),
324 FileChange(FileChange::FILE_CHANGE_DELETE
,
325 sync_file_system::SYNC_FILE_TYPE_UNKNOWN
));
326 VerifyAndClearChange(URL(kPath3
),
327 FileChange(FileChange::FILE_CHANGE_DELETE
,
328 sync_file_system::SYNC_FILE_TYPE_UNKNOWN
));
329 VerifyAndClearChange(URL(kPath4
),
330 FileChange(FileChange::FILE_CHANGE_DELETE
,
331 sync_file_system::SYNC_FILE_TYPE_UNKNOWN
));
332 VerifyAndClearChange(URL(kPath5
),
333 FileChange(FileChange::FILE_CHANGE_DELETE
,
334 sync_file_system::SYNC_FILE_TYPE_UNKNOWN
));
337 TEST_F(LocalFileChangeTrackerTest
, RestoreCopyChanges
) {
338 EXPECT_EQ(base::PLATFORM_FILE_OK
, file_system_
.OpenFileSystem());
340 FileSystemURLSet urls
;
342 const char kPath0
[] = "file a";
343 const char kPath1
[] = "dir a";
344 const char kPath2
[] = "dir a/dir";
345 const char kPath3
[] = "dir a/file a";
346 const char kPath4
[] = "dir a/file b";
348 const char kPath0Copy
[] = "file b"; // To be copied from kPath0
349 const char kPath1Copy
[] = "dir b"; // To be copied from kPath1
350 const char kPath2Copy
[] = "dir b/dir"; // To be copied from kPath2
351 const char kPath3Copy
[] = "dir b/file a"; // To be copied from kPath3
352 const char kPath4Copy
[] = "dir b/file b"; // To be copied from kPath4
354 file_system_
.GetChangedURLsInTracker(&urls
);
355 ASSERT_EQ(0U, urls
.size());
357 const GURL
blob_url("blob:test");
358 const std::string
kData("Lorem ipsum.");
359 MockBlobURLRequestContext
url_request_context(file_system_context());
360 ScopedTextBlob
blob(url_request_context
, blob_url
, kData
);
362 // Create files and nested directories.
363 EXPECT_EQ(base::PLATFORM_FILE_OK
,
364 file_system_
.CreateFile(URL(kPath0
))); // Creates a file.
365 EXPECT_EQ(base::PLATFORM_FILE_OK
,
366 file_system_
.CreateDirectory(URL(kPath1
))); // Creates a dir.
367 EXPECT_EQ(base::PLATFORM_FILE_OK
,
368 file_system_
.CreateDirectory(URL(kPath2
))); // Creates another dir.
369 EXPECT_EQ(base::PLATFORM_FILE_OK
,
370 file_system_
.CreateFile(URL(kPath3
))); // Creates a file.
371 EXPECT_EQ(base::PLATFORM_FILE_OK
,
372 file_system_
.TruncateFile(URL(kPath3
), 1)); // Modifies the file.
373 EXPECT_EQ(base::PLATFORM_FILE_OK
,
374 file_system_
.CreateFile(URL(kPath4
))); // Creates another file.
375 EXPECT_EQ(static_cast<int64
>(kData
.size()),
376 file_system_
.Write(&url_request_context
,
377 URL(kPath4
), blob_url
)); // Modifies the file.
379 // Verify we have 5 changes for preparation.
380 file_system_
.GetChangedURLsInTracker(&urls
);
381 EXPECT_EQ(5U, urls
.size());
382 change_tracker()->ClearChangesForURL(URL(kPath0
));
383 change_tracker()->ClearChangesForURL(URL(kPath1
));
384 change_tracker()->ClearChangesForURL(URL(kPath2
));
385 change_tracker()->ClearChangesForURL(URL(kPath3
));
386 change_tracker()->ClearChangesForURL(URL(kPath4
));
388 // Make sure we have no changes.
389 file_system_
.GetChangedURLsInTracker(&urls
);
390 EXPECT_TRUE(urls
.empty());
392 // Copy the file and the parent directory.
393 EXPECT_EQ(base::PLATFORM_FILE_OK
,
394 file_system_
.Copy(URL(kPath0
), URL(kPath0Copy
))); // Copy the file.
395 EXPECT_EQ(base::PLATFORM_FILE_OK
,
396 file_system_
.Copy(URL(kPath1
), URL(kPath1Copy
))); // Copy the dir.
398 file_system_
.GetChangedURLsInTracker(&urls
);
399 EXPECT_EQ(5U, urls
.size());
400 DropChangesInTracker();
402 // Make sure we have no in-memory changes in the tracker.
403 file_system_
.GetChangedURLsInTracker(&urls
);
404 ASSERT_EQ(0U, urls
.size());
406 RestoreChangesFromTrackerDB();
408 // Make sure the changes are restored from the DB.
409 file_system_
.GetChangedURLsInTracker(&urls
);
410 EXPECT_EQ(5U, urls
.size());
412 VerifyAndClearChange(URL(kPath0Copy
),
413 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
414 sync_file_system::SYNC_FILE_TYPE_FILE
));
415 VerifyAndClearChange(URL(kPath1Copy
),
416 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
417 sync_file_system::SYNC_FILE_TYPE_DIRECTORY
));
418 VerifyAndClearChange(URL(kPath2Copy
),
419 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
420 sync_file_system::SYNC_FILE_TYPE_DIRECTORY
));
421 VerifyAndClearChange(URL(kPath3Copy
),
422 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
423 sync_file_system::SYNC_FILE_TYPE_FILE
));
424 VerifyAndClearChange(URL(kPath4Copy
),
425 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
426 sync_file_system::SYNC_FILE_TYPE_FILE
));
429 TEST_F(LocalFileChangeTrackerTest
, RestoreMoveChanges
) {
430 EXPECT_EQ(base::PLATFORM_FILE_OK
, file_system_
.OpenFileSystem());
432 FileSystemURLSet urls
;
434 const char kPath0
[] = "file a";
435 const char kPath1
[] = "dir a";
436 const char kPath2
[] = "dir a/file";
437 const char kPath3
[] = "dir a/dir";
438 const char kPath4
[] = "dir a/dir/file";
440 const char kPath5
[] = "file b"; // To be moved from kPath0.
441 const char kPath6
[] = "dir b"; // To be moved from kPath1.
442 const char kPath7
[] = "dir b/file"; // To be moved from kPath2.
443 const char kPath8
[] = "dir b/dir"; // To be moved from kPath3.
444 const char kPath9
[] = "dir b/dir/file"; // To be moved from kPath4.
446 file_system_
.GetChangedURLsInTracker(&urls
);
447 ASSERT_EQ(0U, urls
.size());
449 // Create files and nested directories.
450 EXPECT_EQ(base::PLATFORM_FILE_OK
,
451 file_system_
.CreateFile(URL(kPath0
)));
452 EXPECT_EQ(base::PLATFORM_FILE_OK
,
453 file_system_
.CreateDirectory(URL(kPath1
)));
454 EXPECT_EQ(base::PLATFORM_FILE_OK
,
455 file_system_
.CreateFile(URL(kPath2
)));
456 EXPECT_EQ(base::PLATFORM_FILE_OK
,
457 file_system_
.CreateDirectory(URL(kPath3
)));
458 EXPECT_EQ(base::PLATFORM_FILE_OK
,
459 file_system_
.CreateFile(URL(kPath4
)));
461 // Verify we have 5 changes for preparation.
462 file_system_
.GetChangedURLsInTracker(&urls
);
463 EXPECT_EQ(5U, urls
.size());
464 change_tracker()->ClearChangesForURL(URL(kPath0
));
465 change_tracker()->ClearChangesForURL(URL(kPath1
));
466 change_tracker()->ClearChangesForURL(URL(kPath2
));
467 change_tracker()->ClearChangesForURL(URL(kPath3
));
468 change_tracker()->ClearChangesForURL(URL(kPath4
));
470 // Make sure we have no changes.
471 file_system_
.GetChangedURLsInTracker(&urls
);
472 EXPECT_TRUE(urls
.empty());
474 // Move the file and the parent directory.
475 EXPECT_EQ(base::PLATFORM_FILE_OK
,
476 file_system_
.Move(URL(kPath0
), URL(kPath5
)));
477 EXPECT_EQ(base::PLATFORM_FILE_OK
,
478 file_system_
.Move(URL(kPath1
), URL(kPath6
)));
480 file_system_
.GetChangedURLsInTracker(&urls
);
481 EXPECT_EQ(10U, urls
.size());
483 DropChangesInTracker();
485 // Make sure we have no in-memory changes in the tracker.
486 file_system_
.GetChangedURLsInTracker(&urls
);
487 ASSERT_EQ(0U, urls
.size());
489 RestoreChangesFromTrackerDB();
491 // Make sure the changes are restored from the DB.
492 file_system_
.GetChangedURLsInTracker(&urls
);
493 // Deletion for children in the deleted directory cannot be restored,
494 // so we will only have 7 changes.
495 EXPECT_EQ(7U, urls
.size());
497 VerifyAndClearChange(URL(kPath0
),
498 FileChange(FileChange::FILE_CHANGE_DELETE
,
499 sync_file_system::SYNC_FILE_TYPE_UNKNOWN
));
500 VerifyAndClearChange(URL(kPath1
),
501 FileChange(FileChange::FILE_CHANGE_DELETE
,
502 sync_file_system::SYNC_FILE_TYPE_UNKNOWN
));
503 VerifyAndClearChange(URL(kPath5
),
504 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
505 sync_file_system::SYNC_FILE_TYPE_FILE
));
506 VerifyAndClearChange(URL(kPath6
),
507 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
508 sync_file_system::SYNC_FILE_TYPE_DIRECTORY
));
509 VerifyAndClearChange(URL(kPath7
),
510 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
511 sync_file_system::SYNC_FILE_TYPE_FILE
));
512 VerifyAndClearChange(URL(kPath8
),
513 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
514 sync_file_system::SYNC_FILE_TYPE_DIRECTORY
));
515 VerifyAndClearChange(URL(kPath9
),
516 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE
,
517 sync_file_system::SYNC_FILE_TYPE_FILE
));
520 TEST_F(LocalFileChangeTrackerTest
, NextChangedURLsWithRecursiveCopy
) {
521 EXPECT_EQ(base::PLATFORM_FILE_OK
, file_system_
.OpenFileSystem());
523 FileSystemURLSet urls
;
525 const char kPath0
[] = "dir a";
526 const char kPath1
[] = "dir a/file";
527 const char kPath2
[] = "dir a/dir";
529 const char kPath0Copy
[] = "dir b";
530 const char kPath1Copy
[] = "dir b/file";
531 const char kPath2Copy
[] = "dir b/dir";
533 // Creates kPath0,1,2 and then copies them all.
534 EXPECT_EQ(base::PLATFORM_FILE_OK
,
535 file_system_
.CreateDirectory(URL(kPath0
)));
536 EXPECT_EQ(base::PLATFORM_FILE_OK
,
537 file_system_
.CreateFile(URL(kPath1
)));
538 EXPECT_EQ(base::PLATFORM_FILE_OK
,
539 file_system_
.CreateDirectory(URL(kPath2
)));
540 EXPECT_EQ(base::PLATFORM_FILE_OK
,
541 file_system_
.Copy(URL(kPath0
), URL(kPath0Copy
)));
543 std::deque
<FileSystemURL
> urls_to_process
;
544 change_tracker()->GetNextChangedURLs(&urls_to_process
, 0);
545 ASSERT_EQ(6U, urls_to_process
.size());
547 // Creation must have occured first.
548 EXPECT_EQ(URL(kPath0
), urls_to_process
[0]);
549 EXPECT_EQ(URL(kPath1
), urls_to_process
[1]);
550 EXPECT_EQ(URL(kPath2
), urls_to_process
[2]);
552 // Then recursive copy took place. The exact order cannot be determined
553 // but the parent directory must have been created first.
554 EXPECT_EQ(URL(kPath0Copy
), urls_to_process
[3]);
555 EXPECT_TRUE(URL(kPath1Copy
) == urls_to_process
[4] ||
556 URL(kPath2Copy
) == urls_to_process
[4]);
557 EXPECT_TRUE(URL(kPath1Copy
) == urls_to_process
[5] ||
558 URL(kPath2Copy
) == urls_to_process
[5]);
561 TEST_F(LocalFileChangeTrackerTest
, NextChangedURLsWithRecursiveRemove
) {
562 EXPECT_EQ(base::PLATFORM_FILE_OK
, file_system_
.OpenFileSystem());
564 FileSystemURLSet urls
;
566 const char kPath0
[] = "dir a";
567 const char kPath1
[] = "dir a/file1";
568 const char kPath2
[] = "dir a/file2";
570 // Creates kPath0,1,2 and then removes them all.
571 EXPECT_EQ(base::PLATFORM_FILE_OK
,
572 file_system_
.CreateDirectory(URL(kPath0
)));
573 EXPECT_EQ(base::PLATFORM_FILE_OK
,
574 file_system_
.CreateFile(URL(kPath1
)));
575 EXPECT_EQ(base::PLATFORM_FILE_OK
,
576 file_system_
.CreateFile(URL(kPath2
)));
577 EXPECT_EQ(base::PLATFORM_FILE_OK
,
578 file_system_
.Remove(URL(kPath0
), true /* recursive */));
580 std::deque
<FileSystemURL
> urls_to_process
;
581 change_tracker()->GetNextChangedURLs(&urls_to_process
, 0);
583 // This is actually not really desirable, but since the directory
584 // creation and deletion have been offset now we only have two
585 // file deletion changes.
587 // NOTE: This will cause 2 local sync for deleting nonexistent files
588 // on the remote side.
590 // TODO(kinuko): For micro optimization we could probably restore the ADD
591 // change type (other than ADD_OR_UPDATE) and offset file ADD+DELETE
593 ASSERT_EQ(2U, urls_to_process
.size());
595 // The exact order of recursive removal cannot be determined.
596 EXPECT_TRUE(URL(kPath1
) == urls_to_process
[0] ||
597 URL(kPath2
) == urls_to_process
[0]);
598 EXPECT_TRUE(URL(kPath1
) == urls_to_process
[1] ||
599 URL(kPath2
) == urls_to_process
[1]);
602 } // namespace sync_file_system