Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / drive / sync / entry_update_performer_unittest.cc
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.
4
5 #include "chrome/browser/chromeos/drive/sync/entry_update_performer.h"
6
7 #include "base/callback_helpers.h"
8 #include "base/files/file_util.h"
9 #include "base/md5.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"
22
23 namespace drive {
24 namespace internal {
25
26 class EntryUpdatePerformerTest : public file_system::OperationTestBase {
27  protected:
28   virtual void SetUp() override {
29     OperationTestBase::SetUp();
30     performer_.reset(new EntryUpdatePerformer(blocking_task_runner(),
31                                               delegate(),
32                                               scheduler(),
33                                               metadata(),
34                                               cache(),
35                                               loader_controller()));
36   }
37
38   // Stores |content| to the cache and mark it as dirty.
39   FileError StoreAndMarkDirty(const std::string& local_id,
40                               const std::string& content) {
41     base::FilePath path;
42     if (!base::CreateTemporaryFileInDir(temp_dir(), &path) ||
43         !google_apis::test_util::WriteStringToFile(path, content))
44       return FILE_ERROR_FAILED;
45
46     // Store the file to cache.
47     FileError error = FILE_ERROR_FAILED;
48     base::PostTaskAndReplyWithResult(
49         blocking_task_runner(),
50         FROM_HERE,
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();
57     return error;
58   }
59
60   scoped_ptr<EntryUpdatePerformer> performer_;
61 };
62
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"));
68
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));
72
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);
78
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);
86
87   FileError error = FILE_ERROR_FAILED;
88   base::PostTaskAndReplyWithResult(
89       blocking_task_runner(),
90       FROM_HERE,
91       base::Bind(&ResourceMetadata::RefreshEntry,
92                  base::Unretained(metadata()),
93                  src_entry),
94       google_apis::test_util::CreateCopyResultCallback(&error));
95   content::RunAllBlockingPoolTasksUntilIdle();
96   EXPECT_EQ(FILE_ERROR_OK, error);
97
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);
106
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,
113                                                        &gdata_entry));
114   content::RunAllBlockingPoolTasksUntilIdle();
115   EXPECT_EQ(google_apis::HTTP_SUCCESS, gdata_error);
116   ASSERT_TRUE(gdata_entry);
117
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());
121
122   ASSERT_FALSE(gdata_entry->parents().empty());
123   EXPECT_EQ(dest_entry.resource_id(), gdata_entry->parents()[0].file_id());
124 }
125
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"));
130
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(),
134       temp_dir());
135   FileError error = FILE_ERROR_FAILED;
136   base::FilePath cache_file_path;
137   scoped_ptr<ResourceEntry> src_entry;
138   download_operation.EnsureFileDownloadedByPath(
139       src_path,
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);
148
149   // Update the entry locally.
150   src_entry->set_title("Updated" + src_entry->title());
151   src_entry->set_metadata_edit_state(ResourceEntry::DIRTY);
152
153   error = FILE_ERROR_FAILED;
154   base::PostTaskAndReplyWithResult(
155       blocking_task_runner(),
156       FROM_HERE,
157       base::Bind(&ResourceMetadata::RefreshEntry,
158                  base::Unretained(metadata()),
159                  *src_entry),
160       google_apis::test_util::CreateCopyResultCallback(&error));
161   content::RunAllBlockingPoolTasksUntilIdle();
162   EXPECT_EQ(FILE_ERROR_OK, error);
163
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);
172
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,
179                                                        &gdata_entry));
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());
184 }
185
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);
194 }
195
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");
199
200   const std::string local_id = GetLocalId(kFilePath);
201   EXPECT_FALSE(local_id.empty());
202
203   const std::string kTestFileContent = "I'm being uploaded! Yay!";
204   EXPECT_EQ(FILE_ERROR_OK, StoreAndMarkDirty(local_id, kTestFileContent));
205
206   int64 original_changestamp =
207       fake_service()->about_resource().largest_change_id();
208
209   // The callback will be called upon completion of UpdateEntry().
210   FileError error = FILE_ERROR_FAILED;
211   performer_->UpdateEntry(
212       local_id,
213       ClientContext(USER_INITIATED),
214       google_apis::test_util::CreateCopyResultCallback(&error));
215   content::RunAllBlockingPoolTasksUntilIdle();
216   EXPECT_EQ(FILE_ERROR_OK, error);
217
218   // Check that the server has received an update.
219   EXPECT_LT(original_changestamp,
220             fake_service()->about_resource().largest_change_id());
221
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(
226       kResourceId,
227       google_apis::test_util::CreateCopyResultCallback(&gdata_error,
228                                                        &server_entry));
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());
233
234   // Make sure that the cache is no longer dirty.
235   ResourceEntry entry;
236   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
237   EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
238 }
239
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");
243
244   const std::string local_id = GetLocalId(kFilePath);
245   EXPECT_FALSE(local_id.empty());
246
247   const std::string kTestFileContent = "I'm being uploaded! Yay!";
248   EXPECT_EQ(FILE_ERROR_OK, StoreAndMarkDirty(local_id, kTestFileContent));
249
250   int64 original_changestamp =
251       fake_service()->about_resource().largest_change_id();
252
253   // The callback will be called upon completion of UpdateEntry().
254   FileError error = FILE_ERROR_FAILED;
255   performer_->UpdateEntry(
256       local_id,
257       ClientContext(USER_INITIATED),
258       google_apis::test_util::CreateCopyResultCallback(&error));
259   content::RunAllBlockingPoolTasksUntilIdle();
260   EXPECT_EQ(FILE_ERROR_OK, error);
261
262   // Check that the server has received an update.
263   EXPECT_LT(original_changestamp,
264             fake_service()->about_resource().largest_change_id());
265
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(
270       kResourceId,
271       google_apis::test_util::CreateCopyResultCallback(&gdata_error,
272                                                        &server_entry));
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());
277
278   // Make sure that the cache is no longer dirty.
279   ResourceEntry entry;
280   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
281   EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
282
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(),
288       FROM_HERE,
289       base::Bind(&FileCache::OpenForWrite,
290                  base::Unretained(cache()),
291                  local_id,
292                  &file_closer),
293       google_apis::test_util::CreateCopyResultCallback(&error));
294   content::RunAllBlockingPoolTasksUntilIdle();
295   EXPECT_EQ(FILE_ERROR_OK, error);
296   file_closer.reset();
297
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(
304       local_id,
305       ClientContext(USER_INITIATED),
306       google_apis::test_util::CreateCopyResultCallback(&error));
307   content::RunAllBlockingPoolTasksUntilIdle();
308   EXPECT_EQ(FILE_ERROR_OK, error);
309
310   EXPECT_EQ(original_changestamp,
311             fake_service()->about_resource().largest_change_id());
312
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());
316 }
317
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");
321
322   const std::string local_id = GetLocalId(kFilePath);
323   EXPECT_FALSE(local_id.empty());
324
325   const std::string kTestFileContent = "I'm being uploaded! Yay!";
326   EXPECT_EQ(FILE_ERROR_OK, StoreAndMarkDirty(local_id, kTestFileContent));
327
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(),
333       FROM_HERE,
334       base::Bind(&FileCache::OpenForWrite,
335                  base::Unretained(cache()),
336                  local_id,
337                  &file_closer),
338       google_apis::test_util::CreateCopyResultCallback(&error));
339   content::RunAllBlockingPoolTasksUntilIdle();
340   EXPECT_EQ(FILE_ERROR_OK, error);
341
342   // Update. This should not clear the dirty bit.
343   error = FILE_ERROR_FAILED;
344   performer_->UpdateEntry(
345       local_id,
346       ClientContext(USER_INITIATED),
347       google_apis::test_util::CreateCopyResultCallback(&error));
348   content::RunAllBlockingPoolTasksUntilIdle();
349   EXPECT_EQ(FILE_ERROR_OK, error);
350
351   // Make sure that the cache is still dirty.
352   ResourceEntry entry;
353   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath, &entry));
354   EXPECT_TRUE(entry.file_specific_info().cache_state().is_dirty());
355
356   // Close the file.
357   file_closer.reset();
358
359   // Update. This should clear the dirty bit.
360   error = FILE_ERROR_FAILED;
361   performer_->UpdateEntry(
362       local_id,
363       ClientContext(USER_INITIATED),
364       google_apis::test_util::CreateCopyResultCallback(&error));
365   content::RunAllBlockingPoolTasksUntilIdle();
366   EXPECT_EQ(FILE_ERROR_OK, error);
367
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());
371 }
372
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"));
376
377   ResourceEntry parent;
378   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath.DirName(), &parent));
379
380   ResourceEntry entry;
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);
385
386   FileError error = FILE_ERROR_FAILED;
387   std::string local_id;
388   base::PostTaskAndReplyWithResult(
389       blocking_task_runner(),
390       FROM_HERE,
391       base::Bind(&internal::ResourceMetadata::AddEntry,
392                  base::Unretained(metadata()),
393                  entry,
394                  &local_id),
395       google_apis::test_util::CreateCopyResultCallback(&error));
396   content::RunAllBlockingPoolTasksUntilIdle();
397   EXPECT_EQ(FILE_ERROR_OK, error);
398
399   // Update. This should result in creating a new file on the server.
400   error = FILE_ERROR_FAILED;
401   performer_->UpdateEntry(
402       local_id,
403       ClientContext(USER_INITIATED),
404       google_apis::test_util::CreateCopyResultCallback(&error));
405   content::RunAllBlockingPoolTasksUntilIdle();
406   EXPECT_EQ(FILE_ERROR_OK, error);
407
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());
412
413   // Make sure that the cache is no longer dirty.
414   EXPECT_FALSE(entry.file_specific_info().cache_state().is_dirty());
415
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(
420       entry.resource_id(),
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());
426 }
427
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"));
431
432   ResourceEntry parent;
433   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kFilePath.DirName(), &parent));
434
435   ResourceEntry entry;
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);
440
441   FileError error = FILE_ERROR_FAILED;
442   std::string local_id;
443   base::PostTaskAndReplyWithResult(
444       blocking_task_runner(),
445       FROM_HERE,
446       base::Bind(&internal::ResourceMetadata::AddEntry,
447                  base::Unretained(metadata()),
448                  entry,
449                  &local_id),
450       google_apis::test_util::CreateCopyResultCallback(&error));
451   content::RunAllBlockingPoolTasksUntilIdle();
452   EXPECT_EQ(FILE_ERROR_OK, error);
453
454   const std::string kTestFileContent = "This is a new file.";
455   EXPECT_EQ(FILE_ERROR_OK, StoreAndMarkDirty(local_id, kTestFileContent));
456
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(),
462       FROM_HERE,
463       base::Bind(&FileCache::OpenForWrite,
464                  base::Unretained(cache()),
465                  local_id,
466                  &file_closer),
467       google_apis::test_util::CreateCopyResultCallback(&error));
468   content::RunAllBlockingPoolTasksUntilIdle();
469   EXPECT_EQ(FILE_ERROR_OK, error);
470
471   // Update, but no update is performed because the file is opened.
472   error = FILE_ERROR_FAILED;
473   performer_->UpdateEntry(
474       local_id,
475       ClientContext(USER_INITIATED),
476       google_apis::test_util::CreateCopyResultCallback(&error));
477   content::RunAllBlockingPoolTasksUntilIdle();
478   EXPECT_EQ(FILE_ERROR_OK, error);
479
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());
483
484   // Close the file.
485   file_closer.reset();
486
487   // Update. This should result in creating a new file on the server.
488   error = FILE_ERROR_FAILED;
489   performer_->UpdateEntry(
490       local_id,
491       ClientContext(USER_INITIATED),
492       google_apis::test_util::CreateCopyResultCallback(&error));
493   content::RunAllBlockingPoolTasksUntilIdle();
494   EXPECT_EQ(FILE_ERROR_OK, error);
495
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());
500 }
501
502 TEST_F(EntryUpdatePerformerTest, UpdateEntry_CreateDirectory) {
503   // Create a new directory locally.
504   const base::FilePath kPath(FILE_PATH_LITERAL("drive/root/New Directory"));
505
506   ResourceEntry parent;
507   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(kPath.DirName(), &parent));
508
509   ResourceEntry entry;
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);
514
515   FileError error = FILE_ERROR_FAILED;
516   std::string local_id;
517   base::PostTaskAndReplyWithResult(
518       blocking_task_runner(),
519       FROM_HERE,
520       base::Bind(&internal::ResourceMetadata::AddEntry,
521                  base::Unretained(metadata()),
522                  entry,
523                  &local_id),
524       google_apis::test_util::CreateCopyResultCallback(&error));
525   content::RunAllBlockingPoolTasksUntilIdle();
526   EXPECT_EQ(FILE_ERROR_OK, error);
527
528   // Update. This should result in creating a new directory on the server.
529   error = FILE_ERROR_FAILED;
530   performer_->UpdateEntry(
531       local_id,
532       ClientContext(USER_INITIATED),
533       google_apis::test_util::CreateCopyResultCallback(&error));
534   content::RunAllBlockingPoolTasksUntilIdle();
535   EXPECT_EQ(FILE_ERROR_OK, error);
536
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());
541
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(
546       entry.resource_id(),
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());
552 }
553
554 TEST_F(EntryUpdatePerformerTest, UpdateEntry_InsufficientPermission) {
555   base::FilePath src_path(
556       FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
557
558   ResourceEntry src_entry;
559   EXPECT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(src_path, &src_entry));
560
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);
565
566   FileError error = FILE_ERROR_FAILED;
567   base::PostTaskAndReplyWithResult(
568       blocking_task_runner(),
569       FROM_HERE,
570       base::Bind(&ResourceMetadata::RefreshEntry,
571                  base::Unretained(metadata()),
572                  updated_entry),
573       google_apis::test_util::CreateCopyResultCallback(&error));
574   content::RunAllBlockingPoolTasksUntilIdle();
575   EXPECT_EQ(FILE_ERROR_OK, error);
576
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));
580
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);
589
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());
595 }
596
597 }  // namespace internal
598 }  // namespace drive