1 // Copyright 2013 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/drive/sync/entry_update_performer.h"
7 #include "base/callback_helpers.h"
8 #include "base/files/file_util.h"
10 #include "base/task_runner_util.h"
11 #include "chrome/browser/chromeos/drive/file_cache.h"
12 #include "chrome/browser/chromeos/drive/file_system/download_operation.h"
13 #include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
14 #include "chrome/browser/chromeos/drive/job_scheduler.h"
15 #include "chrome/browser/chromeos/drive/resource_metadata.h"
16 #include "chrome/browser/drive/drive_api_util.h"
17 #include "chrome/browser/drive/fake_drive_service.h"
18 #include "content/public/test/test_utils.h"
19 #include "google_apis/drive/drive_api_parser.h"
20 #include "google_apis/drive/test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h"
26 class EntryUpdatePerformerTest : public file_system::OperationTestBase {
28 virtual void SetUp() override {
29 OperationTestBase::SetUp();
30 performer_.reset(new EntryUpdatePerformer(blocking_task_runner(),
35 loader_controller()));
38 // Stores |content| to the cache and mark it as dirty.
39 FileError StoreAndMarkDirty(const std::string& local_id,
40 const std::string& content) {
42 if (!base::CreateTemporaryFileInDir(temp_dir(), &path) ||
43 !google_apis::test_util::WriteStringToFile(path, content))
44 return FILE_ERROR_FAILED;
46 // Store the file to cache.
47 FileError error = FILE_ERROR_FAILED;
48 base::PostTaskAndReplyWithResult(
49 blocking_task_runner(),
51 base::Bind(&FileCache::Store,
52 base::Unretained(cache()),
53 local_id, std::string(), path,
54 FileCache::FILE_OPERATION_COPY),
55 google_apis::test_util::CreateCopyResultCallback(&error));
56 content::RunAllBlockingPoolTasksUntilIdle();
60 scoped_ptr<EntryUpdatePerformer> performer_;
63 TEST_F(EntryUpdatePerformerTest, UpdateEntry) {
64 base::FilePath src_path(
65 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
66 base::FilePath dest_path(
67 FILE_PATH_LITERAL("drive/root/Directory 1/Sub Directory Folder"));
69 ResourceEntry src_entry, dest_entry;
70 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &src_entry));
71 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(dest_path, &dest_entry));
73 // Update local entry.
74 base::Time new_last_modified = base::Time::FromInternalValue(
75 src_entry.file_info().last_modified()) + base::TimeDelta::FromSeconds(1);
76 base::Time new_last_accessed = base::Time::FromInternalValue(
77 src_entry.file_info().last_accessed()) + base::TimeDelta::FromSeconds(2);
79 src_entry.set_parent_local_id(dest_entry.local_id());
80 src_entry.set_title("Moved" + src_entry.title());
81 src_entry.mutable_file_info()->set_last_modified(
82 new_last_modified.ToInternalValue());
83 src_entry.mutable_file_info()->set_last_accessed(
84 new_last_accessed.ToInternalValue());
85 src_entry.set_metadata_edit_state(ResourceEntry::DIRTY);
87 FileError error = FILE_ERROR_FAILED;
88 base::PostTaskAndReplyWithResult(
89 blocking_task_runner(),
91 base::Bind(&ResourceMetadata::RefreshEntry,
92 base::Unretained(metadata()),
94 google_apis::test_util::CreateCopyResultCallback(&error));
95 content::RunAllBlockingPoolTasksUntilIdle();
96 EXPECT_EQ(FILE_ERROR_OK, error);
98 // Perform server side update.
99 error = FILE_ERROR_FAILED;
100 performer_->UpdateEntry(
101 src_entry.local_id(),
102 ClientContext(USER_INITIATED),
103 google_apis::test_util::CreateCopyResultCallback(&error));
104 content::RunAllBlockingPoolTasksUntilIdle();
105 EXPECT_EQ(FILE_ERROR_OK, error);
107 // Verify the file is updated on the server.
108 google_apis::GDataErrorCode gdata_error = google_apis::GDATA_OTHER_ERROR;
109 scoped_ptr<google_apis::FileResource> gdata_entry;
110 fake_service()->GetFileResource(
111 src_entry.resource_id(),
112 google_apis::test_util::CreateCopyResultCallback(&gdata_error,
114 content::RunAllBlockingPoolTasksUntilIdle();
115 EXPECT_EQ(google_apis::HTTP_SUCCESS, gdata_error);
116 ASSERT_TRUE(gdata_entry);
118 EXPECT_EQ(src_entry.title(), gdata_entry->title());
119 EXPECT_EQ(new_last_modified, gdata_entry->modified_date());
120 EXPECT_EQ(new_last_accessed, gdata_entry->last_viewed_by_me_date());
122 ASSERT_FALSE(gdata_entry->parents().empty());
123 EXPECT_EQ(dest_entry.resource_id(), gdata_entry->parents()[0].file_id());
126 // Tests updating metadata of a file with a non-dirty cache file.
127 TEST_F(EntryUpdatePerformerTest, UpdateEntry_WithNonDirtyCache) {
128 base::FilePath src_path(
129 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
131 // Download the file content to prepare a non-dirty cache file.
132 file_system::DownloadOperation download_operation(
133 blocking_task_runner(), delegate(), scheduler(), metadata(), cache(),
135 FileError error = FILE_ERROR_FAILED;
136 base::FilePath cache_file_path;
137 scoped_ptr<ResourceEntry> src_entry;
138 download_operation.EnsureFileDownloadedByPath(
140 ClientContext(USER_INITIATED),
141 GetFileContentInitializedCallback(),
142 google_apis::GetContentCallback(),
143 google_apis::test_util::CreateCopyResultCallback(
144 &error, &cache_file_path, &src_entry));
145 content::RunAllBlockingPoolTasksUntilIdle();
146 EXPECT_EQ(FILE_ERROR_OK, error);
147 ASSERT_TRUE(src_entry);
149 // Update the entry locally.
150 src_entry->set_title("Updated" + src_entry->title());
151 src_entry->set_metadata_edit_state(ResourceEntry::DIRTY);
153 error = FILE_ERROR_FAILED;
154 base::PostTaskAndReplyWithResult(
155 blocking_task_runner(),
157 base::Bind(&ResourceMetadata::RefreshEntry,
158 base::Unretained(metadata()),
160 google_apis::test_util::CreateCopyResultCallback(&error));
161 content::RunAllBlockingPoolTasksUntilIdle();
162 EXPECT_EQ(FILE_ERROR_OK, error);
164 // Perform server side update. This shouldn't fail. (crbug.com/358590)
165 error = FILE_ERROR_FAILED;
166 performer_->UpdateEntry(
167 src_entry->local_id(),
168 ClientContext(USER_INITIATED),
169 google_apis::test_util::CreateCopyResultCallback(&error));
170 content::RunAllBlockingPoolTasksUntilIdle();
171 EXPECT_EQ(FILE_ERROR_OK, error);
173 // Verify the file is updated on the server.
174 google_apis::GDataErrorCode gdata_error = google_apis::GDATA_OTHER_ERROR;
175 scoped_ptr<google_apis::FileResource> gdata_entry;
176 fake_service()->GetFileResource(
177 src_entry->resource_id(),
178 google_apis::test_util::CreateCopyResultCallback(&gdata_error,
180 content::RunAllBlockingPoolTasksUntilIdle();
181 EXPECT_EQ(google_apis::HTTP_SUCCESS, gdata_error);
182 ASSERT_TRUE(gdata_entry);
183 EXPECT_EQ(src_entry->title(), gdata_entry->title());
186 TEST_F(EntryUpdatePerformerTest, UpdateEntry_NotFound) {
187 const std::string id = "this ID should result in NOT_FOUND";
188 FileError error = FILE_ERROR_FAILED;
189 performer_->UpdateEntry(
190 id, ClientContext(USER_INITIATED),
191 google_apis::test_util::CreateCopyResultCallback(&error));
192 content::RunAllBlockingPoolTasksUntilIdle();
193 EXPECT_EQ(FILE_ERROR_NOT_FOUND, error);
196 TEST_F(EntryUpdatePerformerTest, UpdateEntry_ContentUpdate) {
197 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/File 1.txt"));
198 const std::string kResourceId("2_file_resource_id");
200 const std::string local_id = GetLocalId(kFilePath);
201 EXPECT_FALSE(local_id.empty());
203 const std::string kTestFileContent = "I'm being uploaded! Yay!";
204 EXPECT_EQ(FILE_ERROR_OK, StoreAndMarkDirty(local_id, kTestFileContent));
206 int64 original_changestamp =
207 fake_service()->about_resource().largest_change_id();
209 // The callback will be called upon completion of UpdateEntry().
210 FileError error = FILE_ERROR_FAILED;
211 performer_->UpdateEntry(
213 ClientContext(USER_INITIATED),
214 google_apis::test_util::CreateCopyResultCallback(&error));
215 content::RunAllBlockingPoolTasksUntilIdle();
216 EXPECT_EQ(FILE_ERROR_OK, error);
218 // Check that the server has received an update.
219 EXPECT_LT(original_changestamp,
220 fake_service()->about_resource().largest_change_id());
222 // Check that the file size is updated to that of the updated content.
223 google_apis::GDataErrorCode gdata_error = google_apis::GDATA_OTHER_ERROR;
224 scoped_ptr<google_apis::FileResource> server_entry;
225 fake_service()->GetFileResource(
227 google_apis::test_util::CreateCopyResultCallback(&gdata_error,
229 content::RunAllBlockingPoolTasksUntilIdle();
230 EXPECT_EQ(google_apis::HTTP_SUCCESS, gdata_error);
231 EXPECT_EQ(static_cast<int64>(kTestFileContent.size()),
232 server_entry->file_size());
234 // Make sure that the cache is no longer dirty.
236 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
237 EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
240 TEST_F(EntryUpdatePerformerTest, UpdateEntry_ContentUpdateMd5Check) {
241 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/File 1.txt"));
242 const std::string kResourceId("2_file_resource_id");
244 const std::string local_id = GetLocalId(kFilePath);
245 EXPECT_FALSE(local_id.empty());
247 const std::string kTestFileContent = "I'm being uploaded! Yay!";
248 EXPECT_EQ(FILE_ERROR_OK, StoreAndMarkDirty(local_id, kTestFileContent));
250 int64 original_changestamp =
251 fake_service()->about_resource().largest_change_id();
253 // The callback will be called upon completion of UpdateEntry().
254 FileError error = FILE_ERROR_FAILED;
255 performer_->UpdateEntry(
257 ClientContext(USER_INITIATED),
258 google_apis::test_util::CreateCopyResultCallback(&error));
259 content::RunAllBlockingPoolTasksUntilIdle();
260 EXPECT_EQ(FILE_ERROR_OK, error);
262 // Check that the server has received an update.
263 EXPECT_LT(original_changestamp,
264 fake_service()->about_resource().largest_change_id());
266 // Check that the file size is updated to that of the updated content.
267 google_apis::GDataErrorCode gdata_error = google_apis::GDATA_OTHER_ERROR;
268 scoped_ptr<google_apis::FileResource> server_entry;
269 fake_service()->GetFileResource(
271 google_apis::test_util::CreateCopyResultCallback(&gdata_error,
273 content::RunAllBlockingPoolTasksUntilIdle();
274 EXPECT_EQ(google_apis::HTTP_SUCCESS, gdata_error);
275 EXPECT_EQ(static_cast<int64>(kTestFileContent.size()),
276 server_entry->file_size());
278 // Make sure that the cache is no longer dirty.
280 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
281 EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
283 // Again mark the cache file dirty.
284 scoped_ptr<base::ScopedClosureRunner> file_closer;
285 error = FILE_ERROR_FAILED;
286 base::PostTaskAndReplyWithResult(
287 blocking_task_runner(),
289 base::Bind(&FileCache::OpenForWrite,
290 base::Unretained(cache()),
293 google_apis::test_util::CreateCopyResultCallback(&error));
294 content::RunAllBlockingPoolTasksUntilIdle();
295 EXPECT_EQ(FILE_ERROR_OK, error);
298 // And call UpdateEntry again.
299 // In this case, although the file is marked as dirty, but the content
300 // hasn't been changed. Thus, the actual uploading should be skipped.
301 original_changestamp = fake_service()->about_resource().largest_change_id();
302 error = FILE_ERROR_FAILED;
303 performer_->UpdateEntry(
305 ClientContext(USER_INITIATED),
306 google_apis::test_util::CreateCopyResultCallback(&error));
307 content::RunAllBlockingPoolTasksUntilIdle();
308 EXPECT_EQ(FILE_ERROR_OK, error);
310 EXPECT_EQ(original_changestamp,
311 fake_service()->about_resource().largest_change_id());
313 // Make sure that the cache is no longer dirty.
314 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
315 EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
318 TEST_F(EntryUpdatePerformerTest, UpdateEntry_OpenedForWrite) {
319 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/File 1.txt"));
320 const std::string kResourceId("2_file_resource_id");
322 const std::string local_id = GetLocalId(kFilePath);
323 EXPECT_FALSE(local_id.empty());
325 const std::string kTestFileContent = "I'm being uploaded! Yay!";
326 EXPECT_EQ(FILE_ERROR_OK, StoreAndMarkDirty(local_id, kTestFileContent));
328 // Emulate a situation where someone is writing to the file.
329 scoped_ptr<base::ScopedClosureRunner> file_closer;
330 FileError error = FILE_ERROR_FAILED;
331 base::PostTaskAndReplyWithResult(
332 blocking_task_runner(),
334 base::Bind(&FileCache::OpenForWrite,
335 base::Unretained(cache()),
338 google_apis::test_util::CreateCopyResultCallback(&error));
339 content::RunAllBlockingPoolTasksUntilIdle();
340 EXPECT_EQ(FILE_ERROR_OK, error);
342 // Update. This should not clear the dirty bit.
343 error = FILE_ERROR_FAILED;
344 performer_->UpdateEntry(
346 ClientContext(USER_INITIATED),
347 google_apis::test_util::CreateCopyResultCallback(&error));
348 content::RunAllBlockingPoolTasksUntilIdle();
349 EXPECT_EQ(FILE_ERROR_OK, error);
351 // Make sure that the cache is still dirty.
353 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
354 EXPECT_TRUE(entry.file_specific_info().cache_state().is_dirty());
359 // Update. This should clear the dirty bit.
360 error = FILE_ERROR_FAILED;
361 performer_->UpdateEntry(
363 ClientContext(USER_INITIATED),
364 google_apis::test_util::CreateCopyResultCallback(&error));
365 content::RunAllBlockingPoolTasksUntilIdle();
366 EXPECT_EQ(FILE_ERROR_OK, error);
368 // Make sure that the cache is no longer dirty.
369 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
370 EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
373 TEST_F(EntryUpdatePerformerTest, UpdateEntry_UploadNewFile) {
374 // Create a new file locally.
375 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/New File.txt"));
377 ResourceEntry parent;
378 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath.DirName(), &parent));
381 entry.set_parent_local_id(parent.local_id());
382 entry.set_title(kFilePath.BaseName().AsUTF8Unsafe());
383 entry.mutable_file_specific_info()->set_content_mime_type("text/plain");
384 entry.set_metadata_edit_state(ResourceEntry::DIRTY);
386 FileError error = FILE_ERROR_FAILED;
387 std::string local_id;
388 base::PostTaskAndReplyWithResult(
389 blocking_task_runner(),
391 base::Bind(&internal::ResourceMetadata::AddEntry,
392 base::Unretained(metadata()),
395 google_apis::test_util::CreateCopyResultCallback(&error));
396 content::RunAllBlockingPoolTasksUntilIdle();
397 EXPECT_EQ(FILE_ERROR_OK, error);
399 // Update. This should result in creating a new file on the server.
400 error = FILE_ERROR_FAILED;
401 performer_->UpdateEntry(
403 ClientContext(USER_INITIATED),
404 google_apis::test_util::CreateCopyResultCallback(&error));
405 content::RunAllBlockingPoolTasksUntilIdle();
406 EXPECT_EQ(FILE_ERROR_OK, error);
408 // The entry got a resource ID.
409 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
410 EXPECT_FALSE(entry.resource_id().empty());
411 EXPECT_EQ(ResourceEntry::CLEAN, entry.metadata_edit_state());
413 // Make sure that the cache is no longer dirty.
414 EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
416 // Make sure that we really created a file.
417 google_apis::GDataErrorCode status = google_apis::GDATA_OTHER_ERROR;
418 scoped_ptr<google_apis::FileResource> server_entry;
419 fake_service()->GetFileResource(
421 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
422 content::RunAllBlockingPoolTasksUntilIdle();
423 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
424 ASSERT_TRUE(server_entry);
425 EXPECT_FALSE(server_entry->IsDirectory());
428 TEST_F(EntryUpdatePerformerTest, UpdateEntry_NewFileOpendForWrite) {
429 // Create a new file locally.
430 const base::FilePath kFilePath(FILE_PATH_LITERAL("drive/root/New File.txt"));
432 ResourceEntry parent;
433 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath.DirName(), &parent));
436 entry.set_parent_local_id(parent.local_id());
437 entry.set_title(kFilePath.BaseName().AsUTF8Unsafe());
438 entry.mutable_file_specific_info()->set_content_mime_type("text/plain");
439 entry.set_metadata_edit_state(ResourceEntry::DIRTY);
441 FileError error = FILE_ERROR_FAILED;
442 std::string local_id;
443 base::PostTaskAndReplyWithResult(
444 blocking_task_runner(),
446 base::Bind(&internal::ResourceMetadata::AddEntry,
447 base::Unretained(metadata()),
450 google_apis::test_util::CreateCopyResultCallback(&error));
451 content::RunAllBlockingPoolTasksUntilIdle();
452 EXPECT_EQ(FILE_ERROR_OK, error);
454 const std::string kTestFileContent = "This is a new file.";
455 EXPECT_EQ(FILE_ERROR_OK, StoreAndMarkDirty(local_id, kTestFileContent));
457 // Emulate a situation where someone is writing to the file.
458 scoped_ptr<base::ScopedClosureRunner> file_closer;
459 error = FILE_ERROR_FAILED;
460 base::PostTaskAndReplyWithResult(
461 blocking_task_runner(),
463 base::Bind(&FileCache::OpenForWrite,
464 base::Unretained(cache()),
467 google_apis::test_util::CreateCopyResultCallback(&error));
468 content::RunAllBlockingPoolTasksUntilIdle();
469 EXPECT_EQ(FILE_ERROR_OK, error);
471 // Update, but no update is performed because the file is opened.
472 error = FILE_ERROR_FAILED;
473 performer_->UpdateEntry(
475 ClientContext(USER_INITIATED),
476 google_apis::test_util::CreateCopyResultCallback(&error));
477 content::RunAllBlockingPoolTasksUntilIdle();
478 EXPECT_EQ(FILE_ERROR_OK, error);
480 // The entry hasn't got a resource ID yet.
481 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
482 EXPECT_TRUE(entry.resource_id().empty());
487 // Update. This should result in creating a new file on the server.
488 error = FILE_ERROR_FAILED;
489 performer_->UpdateEntry(
491 ClientContext(USER_INITIATED),
492 google_apis::test_util::CreateCopyResultCallback(&error));
493 content::RunAllBlockingPoolTasksUntilIdle();
494 EXPECT_EQ(FILE_ERROR_OK, error);
496 // The entry got a resource ID.
497 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
498 EXPECT_FALSE(entry.resource_id().empty());
499 EXPECT_EQ(ResourceEntry::CLEAN, entry.metadata_edit_state());
502 TEST_F(EntryUpdatePerformerTest, UpdateEntry_CreateDirectory) {
503 // Create a new directory locally.
504 const base::FilePath kPath(FILE_PATH_LITERAL("drive/root/New Directory"));
506 ResourceEntry parent;
507 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kPath.DirName(), &parent));
510 entry.set_parent_local_id(parent.local_id());
511 entry.set_title(kPath.BaseName().AsUTF8Unsafe());
512 entry.mutable_file_info()->set_is_directory(true);
513 entry.set_metadata_edit_state(ResourceEntry::DIRTY);
515 FileError error = FILE_ERROR_FAILED;
516 std::string local_id;
517 base::PostTaskAndReplyWithResult(
518 blocking_task_runner(),
520 base::Bind(&internal::ResourceMetadata::AddEntry,
521 base::Unretained(metadata()),
524 google_apis::test_util::CreateCopyResultCallback(&error));
525 content::RunAllBlockingPoolTasksUntilIdle();
526 EXPECT_EQ(FILE_ERROR_OK, error);
528 // Update. This should result in creating a new directory on the server.
529 error = FILE_ERROR_FAILED;
530 performer_->UpdateEntry(
532 ClientContext(USER_INITIATED),
533 google_apis::test_util::CreateCopyResultCallback(&error));
534 content::RunAllBlockingPoolTasksUntilIdle();
535 EXPECT_EQ(FILE_ERROR_OK, error);
537 // The entry got a resource ID.
538 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kPath, &entry));
539 EXPECT_FALSE(entry.resource_id().empty());
540 EXPECT_EQ(ResourceEntry::CLEAN, entry.metadata_edit_state());
542 // Make sure that we really created a directory.
543 google_apis::GDataErrorCode status = google_apis::GDATA_OTHER_ERROR;
544 scoped_ptr<google_apis::FileResource> server_entry;
545 fake_service()->GetFileResource(
547 google_apis::test_util::CreateCopyResultCallback(&status, &server_entry));
548 content::RunAllBlockingPoolTasksUntilIdle();
549 EXPECT_EQ(google_apis::HTTP_SUCCESS, status);
550 ASSERT_TRUE(server_entry);
551 EXPECT_TRUE(server_entry->IsDirectory());
554 TEST_F(EntryUpdatePerformerTest, UpdateEntry_InsufficientPermission) {
555 base::FilePath src_path(
556 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
558 ResourceEntry src_entry;
559 EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &src_entry));
561 // Update local entry.
562 ResourceEntry updated_entry(src_entry);
563 updated_entry.set_title("Moved" + src_entry.title());
564 updated_entry.set_metadata_edit_state(ResourceEntry::DIRTY);
566 FileError error = FILE_ERROR_FAILED;
567 base::PostTaskAndReplyWithResult(
568 blocking_task_runner(),
570 base::Bind(&ResourceMetadata::RefreshEntry,
571 base::Unretained(metadata()),
573 google_apis::test_util::CreateCopyResultCallback(&error));
574 content::RunAllBlockingPoolTasksUntilIdle();
575 EXPECT_EQ(FILE_ERROR_OK, error);
577 // Set user permission to forbid server side update.
578 EXPECT_EQ(google_apis::HTTP_SUCCESS, fake_service()->SetUserPermission(
579 src_entry.resource_id(), google_apis::drive::PERMISSION_ROLE_READER));
581 // Try to perform update.
582 error = FILE_ERROR_FAILED;
583 performer_->UpdateEntry(
584 src_entry.local_id(),
585 ClientContext(USER_INITIATED),
586 google_apis::test_util::CreateCopyResultCallback(&error));
587 content::RunAllBlockingPoolTasksUntilIdle();
588 EXPECT_EQ(FILE_ERROR_OK, error);
590 // This should result in reverting the local change.
591 ResourceEntry result_entry;
592 EXPECT_EQ(FILE_ERROR_OK,
593 GetLocalResourceEntryById(src_entry.local_id(), &result_entry));
594 EXPECT_EQ(src_entry.title(), result_entry.title());
597 } // namespace internal