Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(385)

Side by Side Diff: webkit/fileapi/syncable/local_file_sync_context_unittest.cc

Issue 15806012: Move webkit/fileapi/syncable/* code to webkit/browser/fileapi (final!) (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "webkit/fileapi/syncable/local_file_sync_context.h"
6
7 #include <vector>
8
9 #include "base/bind.h"
10 #include "base/file_util.h"
11 #include "base/files/file_path.h"
12 #include "base/message_loop.h"
13 #include "base/platform_file.h"
14 #include "base/single_thread_task_runner.h"
15 #include "base/stl_util.h"
16 #include "base/threading/thread.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18 #include "webkit/blob/mock_blob_url_request_context.h"
19 #include "webkit/browser/fileapi/file_system_context.h"
20 #include "webkit/browser/fileapi/file_system_operation.h"
21 #include "webkit/browser/fileapi/isolated_context.h"
22 #include "webkit/fileapi/syncable/canned_syncable_file_system.h"
23 #include "webkit/fileapi/syncable/file_change.h"
24 #include "webkit/fileapi/syncable/local_file_change_tracker.h"
25 #include "webkit/fileapi/syncable/sync_file_metadata.h"
26 #include "webkit/fileapi/syncable/sync_status_code.h"
27 #include "webkit/fileapi/syncable/syncable_file_system_util.h"
28
29 #define FPL FILE_PATH_LITERAL
30
31 using fileapi::FileSystemContext;
32 using fileapi::FileSystemURL;
33 using fileapi::FileSystemURLSet;
34
35 // This tests LocalFileSyncContext behavior in multi-thread /
36 // multi-file-system-context environment.
37 // Basic combined tests (single-thread / single-file-system-context)
38 // that involve LocalFileSyncContext are also in
39 // syncable_file_system_unittests.cc.
40
41 namespace sync_file_system {
42
43 namespace {
44 const char kOrigin1[] = "http://example.com";
45 const char kOrigin2[] = "http://chromium.org";
46 const char kServiceName[] = "test";
47 }
48
49 class LocalFileSyncContextTest : public testing::Test {
50 protected:
51 LocalFileSyncContextTest()
52 : status_(SYNC_FILE_ERROR_FAILED),
53 file_error_(base::PLATFORM_FILE_ERROR_FAILED),
54 async_modify_finished_(false),
55 has_inflight_prepare_for_sync_(false) {}
56
57 virtual void SetUp() OVERRIDE {
58 EXPECT_TRUE(RegisterSyncableFileSystem(kServiceName));
59
60 io_thread_.reset(new base::Thread("Thread_IO"));
61 io_thread_->StartWithOptions(
62 base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
63
64 file_thread_.reset(new base::Thread("Thread_File"));
65 file_thread_->Start();
66
67 ui_task_runner_ = base::MessageLoop::current()->message_loop_proxy();
68 io_task_runner_ = io_thread_->message_loop_proxy();
69 file_task_runner_ = file_thread_->message_loop_proxy();
70 }
71
72 virtual void TearDown() OVERRIDE {
73 EXPECT_TRUE(RevokeSyncableFileSystem(kServiceName));
74 io_thread_->Stop();
75 file_thread_->Stop();
76 }
77
78 void StartPrepareForSync(FileSystemContext* file_system_context,
79 const FileSystemURL& url,
80 SyncFileMetadata* metadata,
81 FileChangeList* changes) {
82 ASSERT_TRUE(changes != NULL);
83 ASSERT_FALSE(has_inflight_prepare_for_sync_);
84 status_ = SYNC_STATUS_UNKNOWN;
85 has_inflight_prepare_for_sync_ = true;
86 sync_context_->PrepareForSync(
87 file_system_context,
88 url,
89 base::Bind(&LocalFileSyncContextTest::DidPrepareForSync,
90 base::Unretained(this), metadata, changes));
91 }
92
93 SyncStatusCode PrepareForSync(FileSystemContext* file_system_context,
94 const FileSystemURL& url,
95 SyncFileMetadata* metadata,
96 FileChangeList* changes) {
97 StartPrepareForSync(file_system_context, url, metadata, changes);
98 base::MessageLoop::current()->Run();
99 return status_;
100 }
101
102 base::Closure GetPrepareForSyncClosure(FileSystemContext* file_system_context,
103 const FileSystemURL& url,
104 SyncFileMetadata* metadata,
105 FileChangeList* changes) {
106 return base::Bind(&LocalFileSyncContextTest::StartPrepareForSync,
107 base::Unretained(this),
108 base::Unretained(file_system_context),
109 url, metadata, changes);
110 }
111
112 void DidPrepareForSync(SyncFileMetadata* metadata_out,
113 FileChangeList* changes_out,
114 SyncStatusCode status,
115 const LocalFileSyncInfo& sync_file_info) {
116 ASSERT_TRUE(ui_task_runner_->RunsTasksOnCurrentThread());
117 has_inflight_prepare_for_sync_ = false;
118 status_ = status;
119 *metadata_out = sync_file_info.metadata;
120 *changes_out = sync_file_info.changes;
121 base::MessageLoop::current()->Quit();
122 }
123
124 SyncStatusCode ApplyRemoteChange(FileSystemContext* file_system_context,
125 const FileChange& change,
126 const base::FilePath& local_path,
127 const FileSystemURL& url,
128 SyncFileType expected_file_type) {
129 SCOPED_TRACE(testing::Message() << "ApplyChange for " <<
130 url.DebugString());
131
132 // First we should call PrepareForSync to disable writing.
133 SyncFileMetadata metadata;
134 FileChangeList changes;
135 EXPECT_EQ(SYNC_STATUS_OK,
136 PrepareForSync(file_system_context, url, &metadata, &changes));
137 EXPECT_EQ(expected_file_type, metadata.file_type);
138
139 status_ = SYNC_STATUS_UNKNOWN;
140 sync_context_->ApplyRemoteChange(
141 file_system_context, change, local_path, url,
142 base::Bind(&LocalFileSyncContextTest::DidApplyRemoteChange,
143 base::Unretained(this)));
144 base::MessageLoop::current()->Run();
145 return status_;
146 }
147
148 void DidApplyRemoteChange(SyncStatusCode status) {
149 base::MessageLoop::current()->Quit();
150 status_ = status;
151 }
152
153 void StartModifyFileOnIOThread(CannedSyncableFileSystem* file_system,
154 const FileSystemURL& url) {
155 async_modify_finished_ = false;
156 ASSERT_TRUE(file_system != NULL);
157 if (!io_task_runner_->RunsTasksOnCurrentThread()) {
158 ASSERT_TRUE(ui_task_runner_->RunsTasksOnCurrentThread());
159 io_task_runner_->PostTask(
160 FROM_HERE,
161 base::Bind(&LocalFileSyncContextTest::StartModifyFileOnIOThread,
162 base::Unretained(this), file_system, url));
163 return;
164 }
165 ASSERT_TRUE(io_task_runner_->RunsTasksOnCurrentThread());
166 file_error_ = base::PLATFORM_FILE_ERROR_FAILED;
167 file_system->NewOperation()->Truncate(
168 url, 1, base::Bind(&LocalFileSyncContextTest::DidModifyFile,
169 base::Unretained(this)));
170 }
171
172 base::PlatformFileError WaitUntilModifyFileIsDone() {
173 while (!async_modify_finished_)
174 base::MessageLoop::current()->RunUntilIdle();
175 return file_error_;
176 }
177
178 void DidModifyFile(base::PlatformFileError error) {
179 if (!ui_task_runner_->RunsTasksOnCurrentThread()) {
180 ASSERT_TRUE(io_task_runner_->RunsTasksOnCurrentThread());
181 ui_task_runner_->PostTask(
182 FROM_HERE,
183 base::Bind(&LocalFileSyncContextTest::DidModifyFile,
184 base::Unretained(this), error));
185 return;
186 }
187 ASSERT_TRUE(ui_task_runner_->RunsTasksOnCurrentThread());
188 file_error_ = error;
189 async_modify_finished_ = true;
190 }
191
192 // These need to remain until the very end.
193 scoped_ptr<base::Thread> io_thread_;
194 scoped_ptr<base::Thread> file_thread_;
195 base::MessageLoop loop_;
196
197 scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_;
198 scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner_;
199 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
200
201 scoped_refptr<LocalFileSyncContext> sync_context_;
202
203 SyncStatusCode status_;
204 base::PlatformFileError file_error_;
205 bool async_modify_finished_;
206 bool has_inflight_prepare_for_sync_;
207 };
208
209 TEST_F(LocalFileSyncContextTest, ConstructAndDestruct) {
210 sync_context_ = new LocalFileSyncContext(
211 ui_task_runner_, io_task_runner_);
212 sync_context_->ShutdownOnUIThread();
213 }
214
215 TEST_F(LocalFileSyncContextTest, InitializeFileSystemContext) {
216 CannedSyncableFileSystem file_system(GURL(kOrigin1), kServiceName,
217 io_task_runner_, file_task_runner_);
218 file_system.SetUp();
219
220 sync_context_ = new LocalFileSyncContext(ui_task_runner_, io_task_runner_);
221
222 // Initializes file_system using |sync_context_|.
223 EXPECT_EQ(SYNC_STATUS_OK,
224 file_system.MaybeInitializeFileSystemContext(sync_context_));
225
226 // Make sure everything's set up for file_system to be able to handle
227 // syncable file system operations.
228 EXPECT_TRUE(file_system.file_system_context()->sync_context() != NULL);
229 EXPECT_TRUE(file_system.file_system_context()->change_tracker() != NULL);
230 EXPECT_EQ(sync_context_.get(),
231 file_system.file_system_context()->sync_context());
232
233 // Calling MaybeInitialize for the same context multiple times must be ok.
234 EXPECT_EQ(SYNC_STATUS_OK,
235 file_system.MaybeInitializeFileSystemContext(sync_context_));
236 EXPECT_EQ(sync_context_.get(),
237 file_system.file_system_context()->sync_context());
238
239 // Opens the file_system, perform some operation and see if the change tracker
240 // correctly captures the change.
241 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.OpenFileSystem());
242
243 const FileSystemURL kURL(file_system.URL("foo"));
244 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.CreateFile(kURL));
245
246 FileSystemURLSet urls;
247 file_system.GetChangedURLsInTracker(&urls);
248 ASSERT_EQ(1U, urls.size());
249 EXPECT_TRUE(ContainsKey(urls, kURL));
250
251 // Finishing the test.
252 sync_context_->ShutdownOnUIThread();
253 file_system.TearDown();
254 }
255
256 TEST_F(LocalFileSyncContextTest, MultipleFileSystemContexts) {
257 CannedSyncableFileSystem file_system1(GURL(kOrigin1), kServiceName,
258 io_task_runner_, file_task_runner_);
259 CannedSyncableFileSystem file_system2(GURL(kOrigin2), kServiceName,
260 io_task_runner_, file_task_runner_);
261 file_system1.SetUp();
262 file_system2.SetUp();
263
264 sync_context_ = new LocalFileSyncContext(ui_task_runner_, io_task_runner_);
265
266 // Initializes file_system1 and file_system2.
267 EXPECT_EQ(SYNC_STATUS_OK,
268 file_system1.MaybeInitializeFileSystemContext(sync_context_));
269 EXPECT_EQ(SYNC_STATUS_OK,
270 file_system2.MaybeInitializeFileSystemContext(sync_context_));
271
272 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system1.OpenFileSystem());
273 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system2.OpenFileSystem());
274
275 const FileSystemURL kURL1(file_system1.URL("foo"));
276 const FileSystemURL kURL2(file_system2.URL("bar"));
277
278 // Creates a file in file_system1.
279 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system1.CreateFile(kURL1));
280
281 // file_system1's tracker must have recorded the change.
282 FileSystemURLSet urls;
283 file_system1.GetChangedURLsInTracker(&urls);
284 ASSERT_EQ(1U, urls.size());
285 EXPECT_TRUE(ContainsKey(urls, kURL1));
286
287 // file_system1's tracker must have no change.
288 urls.clear();
289 file_system2.GetChangedURLsInTracker(&urls);
290 ASSERT_TRUE(urls.empty());
291
292 // Creates a directory in file_system2.
293 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system2.CreateDirectory(kURL2));
294
295 // file_system1's tracker must have the change for kURL1 as before.
296 urls.clear();
297 file_system1.GetChangedURLsInTracker(&urls);
298 ASSERT_EQ(1U, urls.size());
299 EXPECT_TRUE(ContainsKey(urls, kURL1));
300
301 // file_system2's tracker now must have the change for kURL2.
302 urls.clear();
303 file_system2.GetChangedURLsInTracker(&urls);
304 ASSERT_EQ(1U, urls.size());
305 EXPECT_TRUE(ContainsKey(urls, kURL2));
306
307 SyncFileMetadata metadata;
308 FileChangeList changes;
309 EXPECT_EQ(SYNC_STATUS_OK,
310 PrepareForSync(file_system1.file_system_context(), kURL1,
311 &metadata, &changes));
312 EXPECT_EQ(1U, changes.size());
313 EXPECT_TRUE(changes.list().back().IsFile());
314 EXPECT_TRUE(changes.list().back().IsAddOrUpdate());
315 EXPECT_EQ(SYNC_FILE_TYPE_FILE, metadata.file_type);
316 EXPECT_EQ(0, metadata.size);
317
318 changes.clear();
319 EXPECT_EQ(SYNC_STATUS_OK,
320 PrepareForSync(file_system2.file_system_context(), kURL2,
321 &metadata, &changes));
322 EXPECT_EQ(1U, changes.size());
323 EXPECT_FALSE(changes.list().back().IsFile());
324 EXPECT_TRUE(changes.list().back().IsAddOrUpdate());
325 EXPECT_EQ(SYNC_FILE_TYPE_DIRECTORY, metadata.file_type);
326 EXPECT_EQ(0, metadata.size);
327
328 sync_context_->ShutdownOnUIThread();
329 sync_context_ = NULL;
330
331 file_system1.TearDown();
332 file_system2.TearDown();
333 }
334
335 // LocalFileSyncContextTest.PrepareSyncWhileWriting is flaky on android.
336 // http://crbug.com/239793
337 #if defined(OS_ANDROID)
338 #define MAYBE_PrepareSyncWhileWriting DISABLED_PrepareSyncWhileWriting
339 #else
340 #define MAYBE_PrepareSyncWhileWriting PrepareSyncWhileWriting
341 #endif
342 TEST_F(LocalFileSyncContextTest, MAYBE_PrepareSyncWhileWriting) {
343 CannedSyncableFileSystem file_system(GURL(kOrigin1), kServiceName,
344 io_task_runner_, file_task_runner_);
345 file_system.SetUp();
346 sync_context_ = new LocalFileSyncContext(ui_task_runner_, io_task_runner_);
347 EXPECT_EQ(SYNC_STATUS_OK,
348 file_system.MaybeInitializeFileSystemContext(sync_context_));
349
350 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.OpenFileSystem());
351
352 const FileSystemURL kURL1(file_system.URL("foo"));
353
354 // Creates a file in file_system.
355 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.CreateFile(kURL1));
356
357 // Kick file write on IO thread.
358 StartModifyFileOnIOThread(&file_system, kURL1);
359
360 // Until the operation finishes PrepareForSync should return BUSY error.
361 SyncFileMetadata metadata;
362 metadata.file_type = SYNC_FILE_TYPE_UNKNOWN;
363 FileChangeList changes;
364 EXPECT_EQ(SYNC_STATUS_FILE_BUSY,
365 PrepareForSync(file_system.file_system_context(),
366 kURL1, &metadata, &changes));
367 EXPECT_EQ(SYNC_FILE_TYPE_FILE, metadata.file_type);
368
369 // Register PrepareForSync method to be invoked when kURL1 becomes
370 // syncable. (Actually this may be done after all operations are done
371 // on IO thread in this test.)
372 metadata.file_type = SYNC_FILE_TYPE_UNKNOWN;
373 changes.clear();
374 sync_context_->RegisterURLForWaitingSync(
375 kURL1, GetPrepareForSyncClosure(file_system.file_system_context(),
376 kURL1, &metadata, &changes));
377
378 // Wait for the completion.
379 EXPECT_EQ(base::PLATFORM_FILE_OK, WaitUntilModifyFileIsDone());
380
381 // The PrepareForSync must have been started; wait until DidPrepareForSync
382 // is done.
383 base::MessageLoop::current()->Run();
384 ASSERT_FALSE(has_inflight_prepare_for_sync_);
385
386 // Now PrepareForSync should have run and returned OK.
387 EXPECT_EQ(SYNC_STATUS_OK, status_);
388 EXPECT_EQ(1U, changes.size());
389 EXPECT_TRUE(changes.list().back().IsFile());
390 EXPECT_TRUE(changes.list().back().IsAddOrUpdate());
391 EXPECT_EQ(SYNC_FILE_TYPE_FILE, metadata.file_type);
392 EXPECT_EQ(1, metadata.size);
393
394 sync_context_->ShutdownOnUIThread();
395 sync_context_ = NULL;
396 file_system.TearDown();
397 }
398
399 TEST_F(LocalFileSyncContextTest, ApplyRemoteChangeForDeletion) {
400 CannedSyncableFileSystem file_system(GURL(kOrigin1), kServiceName,
401 io_task_runner_, file_task_runner_);
402 file_system.SetUp();
403
404 sync_context_ = new LocalFileSyncContext(ui_task_runner_, io_task_runner_);
405 ASSERT_EQ(SYNC_STATUS_OK,
406 file_system.MaybeInitializeFileSystemContext(sync_context_));
407 ASSERT_EQ(base::PLATFORM_FILE_OK, file_system.OpenFileSystem());
408
409 // Record the initial usage (likely 0).
410 int64 initial_usage = -1;
411 int64 quota = -1;
412 EXPECT_EQ(quota::kQuotaStatusOk,
413 file_system.GetUsageAndQuota(&initial_usage, &quota));
414
415 // Create a file and directory in the file_system.
416 const FileSystemURL kFile(file_system.URL("file"));
417 const FileSystemURL kDir(file_system.URL("dir"));
418 const FileSystemURL kChild(file_system.URL("dir/child"));
419
420 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.CreateFile(kFile));
421 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.CreateDirectory(kDir));
422 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.CreateFile(kChild));
423
424 // file_system's change tracker must have recorded the creation.
425 FileSystemURLSet urls;
426 file_system.GetChangedURLsInTracker(&urls);
427 ASSERT_EQ(3U, urls.size());
428 ASSERT_TRUE(ContainsKey(urls, kFile));
429 ASSERT_TRUE(ContainsKey(urls, kDir));
430 ASSERT_TRUE(ContainsKey(urls, kChild));
431 for (FileSystemURLSet::iterator iter = urls.begin();
432 iter != urls.end(); ++iter) {
433 file_system.ClearChangeForURLInTracker(*iter);
434 }
435
436 // At this point the usage must be greater than the initial usage.
437 int64 new_usage = -1;
438 EXPECT_EQ(quota::kQuotaStatusOk,
439 file_system.GetUsageAndQuota(&new_usage, &quota));
440 EXPECT_GT(new_usage, initial_usage);
441
442 // Now let's apply remote deletion changes.
443 FileChange change(FileChange::FILE_CHANGE_DELETE,
444 SYNC_FILE_TYPE_FILE);
445 EXPECT_EQ(SYNC_STATUS_OK,
446 ApplyRemoteChange(file_system.file_system_context(),
447 change, base::FilePath(), kFile,
448 SYNC_FILE_TYPE_FILE));
449
450 // The implementation doesn't check file type for deletion, and it must be ok
451 // even if we don't know if the deletion change was for a file or a directory.
452 change = FileChange(FileChange::FILE_CHANGE_DELETE,
453 SYNC_FILE_TYPE_UNKNOWN);
454 EXPECT_EQ(SYNC_STATUS_OK,
455 ApplyRemoteChange(file_system.file_system_context(),
456 change, base::FilePath(), kDir,
457 SYNC_FILE_TYPE_DIRECTORY));
458
459 // Check the directory/files are deleted successfully.
460 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
461 file_system.FileExists(kFile));
462 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
463 file_system.DirectoryExists(kDir));
464 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
465 file_system.FileExists(kChild));
466
467 // The changes applied by ApplyRemoteChange should not be recorded in
468 // the change tracker.
469 urls.clear();
470 file_system.GetChangedURLsInTracker(&urls);
471 EXPECT_TRUE(urls.empty());
472
473 // The quota usage data must have reflected the deletion.
474 EXPECT_EQ(quota::kQuotaStatusOk,
475 file_system.GetUsageAndQuota(&new_usage, &quota));
476 EXPECT_EQ(new_usage, initial_usage);
477
478 sync_context_->ShutdownOnUIThread();
479 sync_context_ = NULL;
480 file_system.TearDown();
481 }
482
483 TEST_F(LocalFileSyncContextTest, ApplyRemoteChangeForAddOrUpdate) {
484 base::ScopedTempDir temp_dir;
485 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
486
487 CannedSyncableFileSystem file_system(GURL(kOrigin1), kServiceName,
488 io_task_runner_, file_task_runner_);
489 file_system.SetUp();
490
491 sync_context_ = new LocalFileSyncContext(ui_task_runner_, io_task_runner_);
492 ASSERT_EQ(SYNC_STATUS_OK,
493 file_system.MaybeInitializeFileSystemContext(sync_context_));
494 ASSERT_EQ(base::PLATFORM_FILE_OK, file_system.OpenFileSystem());
495
496 const FileSystemURL kFile1(file_system.URL("file1"));
497 const FileSystemURL kFile2(file_system.URL("file2"));
498 const FileSystemURL kDir(file_system.URL("dir"));
499
500 const char kTestFileData0[] = "0123456789";
501 const char kTestFileData1[] = "Lorem ipsum!";
502 const char kTestFileData2[] = "This is sample test data.";
503
504 // Create kFile1 and populate it with kTestFileData0.
505 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.CreateFile(kFile1));
506 EXPECT_EQ(static_cast<int64>(arraysize(kTestFileData0) - 1),
507 file_system.WriteString(kFile1, kTestFileData0));
508
509 // kFile2 and kDir are not there yet.
510 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
511 file_system.FileExists(kFile2));
512 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND,
513 file_system.DirectoryExists(kDir));
514
515 // file_system's change tracker must have recorded the creation.
516 FileSystemURLSet urls;
517 file_system.GetChangedURLsInTracker(&urls);
518 ASSERT_EQ(1U, urls.size());
519 EXPECT_TRUE(ContainsKey(urls, kFile1));
520 file_system.ClearChangeForURLInTracker(*urls.begin());
521
522 // Prepare temporary files which represent the remote file data.
523 const base::FilePath kFilePath1(temp_dir.path().Append(FPL("file1")));
524 const base::FilePath kFilePath2(temp_dir.path().Append(FPL("file2")));
525
526 ASSERT_EQ(static_cast<int>(arraysize(kTestFileData1) - 1),
527 file_util::WriteFile(kFilePath1, kTestFileData1,
528 arraysize(kTestFileData1) - 1));
529 ASSERT_EQ(static_cast<int>(arraysize(kTestFileData2) - 1),
530 file_util::WriteFile(kFilePath2, kTestFileData2,
531 arraysize(kTestFileData2) - 1));
532
533 // Record the usage.
534 int64 usage = -1, new_usage = -1;
535 int64 quota = -1;
536 EXPECT_EQ(quota::kQuotaStatusOk,
537 file_system.GetUsageAndQuota(&usage, &quota));
538
539 // Here in the local filesystem we have:
540 // * kFile1 with kTestFileData0
541 //
542 // In the remote side let's assume we have:
543 // * kFile1 with kTestFileData1
544 // * kFile2 with kTestFileData2
545 // * kDir
546 //
547 // By calling ApplyChange's:
548 // * kFile1 will be updated to have kTestFileData1
549 // * kFile2 will be created
550 // * kDir will be created
551
552 // Apply the remote change to kFile1 (which will update the file).
553 FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
554 SYNC_FILE_TYPE_FILE);
555 EXPECT_EQ(SYNC_STATUS_OK,
556 ApplyRemoteChange(file_system.file_system_context(),
557 change, kFilePath1, kFile1,
558 SYNC_FILE_TYPE_FILE));
559
560 // Check if the usage has been increased by (kTestFileData1 - kTestFileData0).
561 const int updated_size =
562 arraysize(kTestFileData1) - arraysize(kTestFileData0);
563 EXPECT_EQ(quota::kQuotaStatusOk,
564 file_system.GetUsageAndQuota(&new_usage, &quota));
565 EXPECT_EQ(updated_size, new_usage - usage);
566
567 // Apply remote changes to kFile2 and kDir (should create a file and
568 // directory respectively).
569 // They are non-existent yet so their expected file type (the last
570 // parameter of ApplyRemoteChange) are
571 // SYNC_FILE_TYPE_UNKNOWN.
572 change = FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
573 SYNC_FILE_TYPE_FILE);
574 EXPECT_EQ(SYNC_STATUS_OK,
575 ApplyRemoteChange(file_system.file_system_context(),
576 change, kFilePath2, kFile2,
577 SYNC_FILE_TYPE_UNKNOWN));
578
579 change = FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
580 SYNC_FILE_TYPE_DIRECTORY);
581 EXPECT_EQ(SYNC_STATUS_OK,
582 ApplyRemoteChange(file_system.file_system_context(),
583 change, base::FilePath(), kDir,
584 SYNC_FILE_TYPE_UNKNOWN));
585
586 // Calling ApplyRemoteChange with different file type should be handled as
587 // overwrite.
588 change =
589 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE, SYNC_FILE_TYPE_FILE);
590 EXPECT_EQ(SYNC_STATUS_OK,
591 ApplyRemoteChange(file_system.file_system_context(),
592 change,
593 kFilePath1,
594 kDir,
595 SYNC_FILE_TYPE_DIRECTORY));
596 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.FileExists(kDir));
597
598 change = FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
599 SYNC_FILE_TYPE_DIRECTORY);
600 EXPECT_EQ(SYNC_STATUS_OK,
601 ApplyRemoteChange(file_system.file_system_context(),
602 change,
603 kFilePath1,
604 kDir,
605 SYNC_FILE_TYPE_FILE));
606
607 // Creating a file/directory must have increased the usage more than
608 // the size of kTestFileData2.
609 new_usage = usage;
610 EXPECT_EQ(quota::kQuotaStatusOk,
611 file_system.GetUsageAndQuota(&new_usage, &quota));
612 EXPECT_GT(new_usage,
613 static_cast<int64>(usage + arraysize(kTestFileData2) - 1));
614
615 // The changes applied by ApplyRemoteChange should not be recorded in
616 // the change tracker.
617 urls.clear();
618 file_system.GetChangedURLsInTracker(&urls);
619 EXPECT_TRUE(urls.empty());
620
621 // Make sure all three files/directory exist.
622 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.FileExists(kFile1));
623 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.FileExists(kFile2));
624 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.DirectoryExists(kDir));
625
626 sync_context_->ShutdownOnUIThread();
627 file_system.TearDown();
628 }
629
630 TEST_F(LocalFileSyncContextTest, ApplyRemoteChangeForAddOrUpdate_NoParent) {
631 base::ScopedTempDir temp_dir;
632 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
633
634 CannedSyncableFileSystem file_system(GURL(kOrigin1), kServiceName,
635 io_task_runner_, file_task_runner_);
636 file_system.SetUp();
637
638 sync_context_ = new LocalFileSyncContext(ui_task_runner_, io_task_runner_);
639 ASSERT_EQ(SYNC_STATUS_OK,
640 file_system.MaybeInitializeFileSystemContext(sync_context_));
641 ASSERT_EQ(base::PLATFORM_FILE_OK, file_system.OpenFileSystem());
642
643 const char kTestFileData[] = "Lorem ipsum!";
644 const FileSystemURL kDir(file_system.URL("dir"));
645 const FileSystemURL kFile(file_system.URL("dir/file"));
646
647 // Either kDir or kFile not exist yet.
648 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, file_system.FileExists(kDir));
649 EXPECT_EQ(base::PLATFORM_FILE_ERROR_NOT_FOUND, file_system.FileExists(kFile));
650
651 // Prepare a temporary file which represents remote file data.
652 const base::FilePath kFilePath(temp_dir.path().Append(FPL("file")));
653 ASSERT_EQ(static_cast<int>(arraysize(kTestFileData) - 1),
654 file_util::WriteFile(kFilePath, kTestFileData,
655 arraysize(kTestFileData) - 1));
656
657 // Calling ApplyChange's with kFilePath should create
658 // kFile along with kDir.
659 FileChange change(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
660 SYNC_FILE_TYPE_FILE);
661 EXPECT_EQ(SYNC_STATUS_OK,
662 ApplyRemoteChange(file_system.file_system_context(),
663 change, kFilePath, kFile,
664 SYNC_FILE_TYPE_UNKNOWN));
665
666 // The changes applied by ApplyRemoteChange should not be recorded in
667 // the change tracker.
668 FileSystemURLSet urls;
669 urls.clear();
670 file_system.GetChangedURLsInTracker(&urls);
671 EXPECT_TRUE(urls.empty());
672
673 // Make sure kDir and kFile are created by ApplyRemoteChange.
674 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.FileExists(kFile));
675 EXPECT_EQ(base::PLATFORM_FILE_OK, file_system.DirectoryExists(kDir));
676
677 sync_context_->ShutdownOnUIThread();
678 file_system.TearDown();
679 }
680
681 } // namespace sync_file_system
OLDNEW
« no previous file with comments | « webkit/fileapi/syncable/local_file_sync_context.cc ('k') | webkit/fileapi/syncable/local_file_sync_status.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698