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_system/download_operation.h"
12 #include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
13 #include "components/drive/drive_api_util.h"
14 #include "components/drive/file_cache.h"
15 #include "components/drive/job_scheduler.h"
16 #include "components/drive/resource_metadata.h"
17 #include "components/drive/service/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 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::DriveApiErrorCode gdata_error
= google_apis::DRIVE_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 TEST_F(EntryUpdatePerformerTest
, UpdateEntry_SetProperties
) {
127 base::FilePath
entry_path(
128 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
131 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(entry_path
, &entry
));
133 Property
* const first_property
= entry
.mutable_new_properties()->Add();
134 first_property
->set_key("hello");
135 first_property
->set_value("world");
136 first_property
->set_visibility(Property_Visibility_PUBLIC
);
138 Property
* const second_property
= entry
.mutable_new_properties()->Add();
139 second_property
->set_key("this");
140 second_property
->set_value("will-change");
141 second_property
->set_visibility(Property_Visibility_PUBLIC
);
142 entry
.set_metadata_edit_state(ResourceEntry::DIRTY
);
144 FileError error
= FILE_ERROR_FAILED
;
145 base::PostTaskAndReplyWithResult(
146 blocking_task_runner(), FROM_HERE
,
147 base::Bind(&ResourceMetadata::RefreshEntry
, base::Unretained(metadata()),
149 google_apis::test_util::CreateCopyResultCallback(&error
));
150 content::RunAllBlockingPoolTasksUntilIdle();
151 EXPECT_EQ(FILE_ERROR_OK
, error
);
153 // Perform server side update.
154 error
= FILE_ERROR_FAILED
;
155 performer_
->UpdateEntry(
156 entry
.local_id(), ClientContext(USER_INITIATED
),
157 google_apis::test_util::CreateCopyResultCallback(&error
));
159 // Add a new property during an update.
160 Property
* const property
= entry
.mutable_new_properties()->Add();
161 property
->set_key("tokyo");
162 property
->set_value("kyoto");
163 property
->set_visibility(Property_Visibility_PUBLIC
);
165 // Modify an existing property during an update.
166 second_property
->set_value("changed");
168 // Change the resource entry during an update.
169 base::PostTaskAndReplyWithResult(
170 blocking_task_runner(), FROM_HERE
,
171 base::Bind(&ResourceMetadata::RefreshEntry
, base::Unretained(metadata()),
173 google_apis::test_util::CreateCopyResultCallback(&error
));
175 // Wait until the update is fully completed.
176 content::RunAllBlockingPoolTasksUntilIdle();
177 EXPECT_EQ(FILE_ERROR_OK
, error
);
179 // List of synced properties should be removed from the proto.
180 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(entry_path
, &entry
));
181 ASSERT_EQ(2, entry
.new_properties().size());
182 EXPECT_EQ("changed", entry
.new_properties().Get(0).value());
183 EXPECT_EQ("tokyo", entry
.new_properties().Get(1).key());
186 // Tests updating metadata of a file with a non-dirty cache file.
187 TEST_F(EntryUpdatePerformerTest
, UpdateEntry_WithNonDirtyCache
) {
188 base::FilePath
src_path(
189 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
191 // Download the file content to prepare a non-dirty cache file.
192 file_system::DownloadOperation
download_operation(
193 blocking_task_runner(), delegate(), scheduler(), metadata(), cache(),
195 FileError error
= FILE_ERROR_FAILED
;
196 base::FilePath cache_file_path
;
197 scoped_ptr
<ResourceEntry
> src_entry
;
198 download_operation
.EnsureFileDownloadedByPath(
200 ClientContext(USER_INITIATED
),
201 GetFileContentInitializedCallback(),
202 google_apis::GetContentCallback(),
203 google_apis::test_util::CreateCopyResultCallback(
204 &error
, &cache_file_path
, &src_entry
));
205 content::RunAllBlockingPoolTasksUntilIdle();
206 EXPECT_EQ(FILE_ERROR_OK
, error
);
207 ASSERT_TRUE(src_entry
);
209 // Update the entry locally.
210 src_entry
->set_title("Updated" + src_entry
->title());
211 src_entry
->set_metadata_edit_state(ResourceEntry::DIRTY
);
213 error
= FILE_ERROR_FAILED
;
214 base::PostTaskAndReplyWithResult(
215 blocking_task_runner(),
217 base::Bind(&ResourceMetadata::RefreshEntry
,
218 base::Unretained(metadata()),
220 google_apis::test_util::CreateCopyResultCallback(&error
));
221 content::RunAllBlockingPoolTasksUntilIdle();
222 EXPECT_EQ(FILE_ERROR_OK
, error
);
224 // Perform server side update. This shouldn't fail. (crbug.com/358590)
225 error
= FILE_ERROR_FAILED
;
226 performer_
->UpdateEntry(
227 src_entry
->local_id(),
228 ClientContext(USER_INITIATED
),
229 google_apis::test_util::CreateCopyResultCallback(&error
));
230 content::RunAllBlockingPoolTasksUntilIdle();
231 EXPECT_EQ(FILE_ERROR_OK
, error
);
233 // Verify the file is updated on the server.
234 google_apis::DriveApiErrorCode gdata_error
= google_apis::DRIVE_OTHER_ERROR
;
235 scoped_ptr
<google_apis::FileResource
> gdata_entry
;
236 fake_service()->GetFileResource(
237 src_entry
->resource_id(),
238 google_apis::test_util::CreateCopyResultCallback(&gdata_error
,
240 content::RunAllBlockingPoolTasksUntilIdle();
241 EXPECT_EQ(google_apis::HTTP_SUCCESS
, gdata_error
);
242 ASSERT_TRUE(gdata_entry
);
243 EXPECT_EQ(src_entry
->title(), gdata_entry
->title());
246 TEST_F(EntryUpdatePerformerTest
, UpdateEntry_NotFound
) {
247 const std::string id
= "this ID should result in NOT_FOUND";
248 FileError error
= FILE_ERROR_FAILED
;
249 performer_
->UpdateEntry(
250 id
, ClientContext(USER_INITIATED
),
251 google_apis::test_util::CreateCopyResultCallback(&error
));
252 content::RunAllBlockingPoolTasksUntilIdle();
253 EXPECT_EQ(FILE_ERROR_NOT_FOUND
, error
);
256 TEST_F(EntryUpdatePerformerTest
, UpdateEntry_ContentUpdate
) {
257 const base::FilePath
kFilePath(FILE_PATH_LITERAL("drive/root/File 1.txt"));
258 const std::string
kResourceId("2_file_resource_id");
260 const std::string local_id
= GetLocalId(kFilePath
);
261 EXPECT_FALSE(local_id
.empty());
263 const std::string kTestFileContent
= "I'm being uploaded! Yay!";
264 EXPECT_EQ(FILE_ERROR_OK
, StoreAndMarkDirty(local_id
, kTestFileContent
));
266 int64 original_changestamp
=
267 fake_service()->about_resource().largest_change_id();
269 // The callback will be called upon completion of UpdateEntry().
270 FileError error
= FILE_ERROR_FAILED
;
271 performer_
->UpdateEntry(
273 ClientContext(USER_INITIATED
),
274 google_apis::test_util::CreateCopyResultCallback(&error
));
275 content::RunAllBlockingPoolTasksUntilIdle();
276 EXPECT_EQ(FILE_ERROR_OK
, error
);
278 // Check that the server has received an update.
279 EXPECT_LT(original_changestamp
,
280 fake_service()->about_resource().largest_change_id());
282 // Check that the file size is updated to that of the updated content.
283 google_apis::DriveApiErrorCode gdata_error
= google_apis::DRIVE_OTHER_ERROR
;
284 scoped_ptr
<google_apis::FileResource
> server_entry
;
285 fake_service()->GetFileResource(
287 google_apis::test_util::CreateCopyResultCallback(&gdata_error
,
289 content::RunAllBlockingPoolTasksUntilIdle();
290 EXPECT_EQ(google_apis::HTTP_SUCCESS
, gdata_error
);
291 EXPECT_EQ(static_cast<int64
>(kTestFileContent
.size()),
292 server_entry
->file_size());
294 // Make sure that the cache is no longer dirty.
296 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kFilePath
, &entry
));
297 EXPECT_FALSE(entry
.file_specific_info().cache_state().is_dirty());
300 TEST_F(EntryUpdatePerformerTest
, UpdateEntry_ContentUpdateMd5Check
) {
301 const base::FilePath
kFilePath(FILE_PATH_LITERAL("drive/root/File 1.txt"));
302 const std::string
kResourceId("2_file_resource_id");
304 const std::string local_id
= GetLocalId(kFilePath
);
305 EXPECT_FALSE(local_id
.empty());
307 const std::string kTestFileContent
= "I'm being uploaded! Yay!";
308 EXPECT_EQ(FILE_ERROR_OK
, StoreAndMarkDirty(local_id
, kTestFileContent
));
310 int64 original_changestamp
=
311 fake_service()->about_resource().largest_change_id();
313 // The callback will be called upon completion of UpdateEntry().
314 FileError error
= FILE_ERROR_FAILED
;
315 performer_
->UpdateEntry(
317 ClientContext(USER_INITIATED
),
318 google_apis::test_util::CreateCopyResultCallback(&error
));
319 content::RunAllBlockingPoolTasksUntilIdle();
320 EXPECT_EQ(FILE_ERROR_OK
, error
);
322 // Check that the server has received an update.
323 EXPECT_LT(original_changestamp
,
324 fake_service()->about_resource().largest_change_id());
326 // Check that the file size is updated to that of the updated content.
327 google_apis::DriveApiErrorCode gdata_error
= google_apis::DRIVE_OTHER_ERROR
;
328 scoped_ptr
<google_apis::FileResource
> server_entry
;
329 fake_service()->GetFileResource(
331 google_apis::test_util::CreateCopyResultCallback(&gdata_error
,
333 content::RunAllBlockingPoolTasksUntilIdle();
334 EXPECT_EQ(google_apis::HTTP_SUCCESS
, gdata_error
);
335 EXPECT_EQ(static_cast<int64
>(kTestFileContent
.size()),
336 server_entry
->file_size());
338 // Make sure that the cache is no longer dirty.
340 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kFilePath
, &entry
));
341 EXPECT_FALSE(entry
.file_specific_info().cache_state().is_dirty());
343 // Again mark the cache file dirty.
344 scoped_ptr
<base::ScopedClosureRunner
> file_closer
;
345 error
= FILE_ERROR_FAILED
;
346 base::PostTaskAndReplyWithResult(
347 blocking_task_runner(),
349 base::Bind(&FileCache::OpenForWrite
,
350 base::Unretained(cache()),
353 google_apis::test_util::CreateCopyResultCallback(&error
));
354 content::RunAllBlockingPoolTasksUntilIdle();
355 EXPECT_EQ(FILE_ERROR_OK
, error
);
358 // And call UpdateEntry again.
359 // In this case, although the file is marked as dirty, but the content
360 // hasn't been changed. Thus, the actual uploading should be skipped.
361 original_changestamp
= fake_service()->about_resource().largest_change_id();
362 error
= FILE_ERROR_FAILED
;
363 performer_
->UpdateEntry(
365 ClientContext(USER_INITIATED
),
366 google_apis::test_util::CreateCopyResultCallback(&error
));
367 content::RunAllBlockingPoolTasksUntilIdle();
368 EXPECT_EQ(FILE_ERROR_OK
, error
);
370 EXPECT_EQ(original_changestamp
,
371 fake_service()->about_resource().largest_change_id());
373 // Make sure that the cache is no longer dirty.
374 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kFilePath
, &entry
));
375 EXPECT_FALSE(entry
.file_specific_info().cache_state().is_dirty());
378 TEST_F(EntryUpdatePerformerTest
, UpdateEntry_OpenedForWrite
) {
379 const base::FilePath
kFilePath(FILE_PATH_LITERAL("drive/root/File 1.txt"));
380 const std::string
kResourceId("2_file_resource_id");
382 const std::string local_id
= GetLocalId(kFilePath
);
383 EXPECT_FALSE(local_id
.empty());
385 const std::string kTestFileContent
= "I'm being uploaded! Yay!";
386 EXPECT_EQ(FILE_ERROR_OK
, StoreAndMarkDirty(local_id
, kTestFileContent
));
388 // Emulate a situation where someone is writing to the file.
389 scoped_ptr
<base::ScopedClosureRunner
> file_closer
;
390 FileError error
= FILE_ERROR_FAILED
;
391 base::PostTaskAndReplyWithResult(
392 blocking_task_runner(),
394 base::Bind(&FileCache::OpenForWrite
,
395 base::Unretained(cache()),
398 google_apis::test_util::CreateCopyResultCallback(&error
));
399 content::RunAllBlockingPoolTasksUntilIdle();
400 EXPECT_EQ(FILE_ERROR_OK
, error
);
402 // Update. This should not clear the dirty bit.
403 error
= FILE_ERROR_FAILED
;
404 performer_
->UpdateEntry(
406 ClientContext(USER_INITIATED
),
407 google_apis::test_util::CreateCopyResultCallback(&error
));
408 content::RunAllBlockingPoolTasksUntilIdle();
409 EXPECT_EQ(FILE_ERROR_OK
, error
);
411 // Make sure that the cache is still dirty.
413 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kFilePath
, &entry
));
414 EXPECT_TRUE(entry
.file_specific_info().cache_state().is_dirty());
419 // Update. This should clear the dirty bit.
420 error
= FILE_ERROR_FAILED
;
421 performer_
->UpdateEntry(
423 ClientContext(USER_INITIATED
),
424 google_apis::test_util::CreateCopyResultCallback(&error
));
425 content::RunAllBlockingPoolTasksUntilIdle();
426 EXPECT_EQ(FILE_ERROR_OK
, error
);
428 // Make sure that the cache is no longer dirty.
429 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kFilePath
, &entry
));
430 EXPECT_FALSE(entry
.file_specific_info().cache_state().is_dirty());
433 TEST_F(EntryUpdatePerformerTest
, UpdateEntry_UploadNewFile
) {
434 // Create a new file locally.
435 const base::FilePath
kFilePath(FILE_PATH_LITERAL("drive/root/New File.txt"));
437 ResourceEntry parent
;
438 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kFilePath
.DirName(), &parent
));
441 entry
.set_parent_local_id(parent
.local_id());
442 entry
.set_title(kFilePath
.BaseName().AsUTF8Unsafe());
443 entry
.mutable_file_specific_info()->set_content_mime_type("text/plain");
444 entry
.set_metadata_edit_state(ResourceEntry::DIRTY
);
446 FileError error
= FILE_ERROR_FAILED
;
447 std::string local_id
;
448 base::PostTaskAndReplyWithResult(
449 blocking_task_runner(),
451 base::Bind(&internal::ResourceMetadata::AddEntry
,
452 base::Unretained(metadata()),
455 google_apis::test_util::CreateCopyResultCallback(&error
));
456 content::RunAllBlockingPoolTasksUntilIdle();
457 EXPECT_EQ(FILE_ERROR_OK
, error
);
459 // Update. This should result in creating a new file on the server.
460 error
= FILE_ERROR_FAILED
;
461 performer_
->UpdateEntry(
463 ClientContext(USER_INITIATED
),
464 google_apis::test_util::CreateCopyResultCallback(&error
));
465 content::RunAllBlockingPoolTasksUntilIdle();
466 EXPECT_EQ(FILE_ERROR_OK
, error
);
468 // The entry got a resource ID.
469 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kFilePath
, &entry
));
470 EXPECT_FALSE(entry
.resource_id().empty());
471 EXPECT_EQ(ResourceEntry::CLEAN
, entry
.metadata_edit_state());
473 // Make sure that the cache is no longer dirty.
474 EXPECT_FALSE(entry
.file_specific_info().cache_state().is_dirty());
476 // Make sure that we really created a file.
477 google_apis::DriveApiErrorCode status
= google_apis::DRIVE_OTHER_ERROR
;
478 scoped_ptr
<google_apis::FileResource
> server_entry
;
479 fake_service()->GetFileResource(
481 google_apis::test_util::CreateCopyResultCallback(&status
, &server_entry
));
482 content::RunAllBlockingPoolTasksUntilIdle();
483 EXPECT_EQ(google_apis::HTTP_SUCCESS
, status
);
484 ASSERT_TRUE(server_entry
);
485 EXPECT_FALSE(server_entry
->IsDirectory());
488 TEST_F(EntryUpdatePerformerTest
, UpdateEntry_NewFileOpendForWrite
) {
489 // Create a new file locally.
490 const base::FilePath
kFilePath(FILE_PATH_LITERAL("drive/root/New File.txt"));
492 ResourceEntry parent
;
493 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kFilePath
.DirName(), &parent
));
496 entry
.set_parent_local_id(parent
.local_id());
497 entry
.set_title(kFilePath
.BaseName().AsUTF8Unsafe());
498 entry
.mutable_file_specific_info()->set_content_mime_type("text/plain");
499 entry
.set_metadata_edit_state(ResourceEntry::DIRTY
);
501 FileError error
= FILE_ERROR_FAILED
;
502 std::string local_id
;
503 base::PostTaskAndReplyWithResult(
504 blocking_task_runner(),
506 base::Bind(&internal::ResourceMetadata::AddEntry
,
507 base::Unretained(metadata()),
510 google_apis::test_util::CreateCopyResultCallback(&error
));
511 content::RunAllBlockingPoolTasksUntilIdle();
512 EXPECT_EQ(FILE_ERROR_OK
, error
);
514 const std::string kTestFileContent
= "This is a new file.";
515 EXPECT_EQ(FILE_ERROR_OK
, StoreAndMarkDirty(local_id
, kTestFileContent
));
517 // Emulate a situation where someone is writing to the file.
518 scoped_ptr
<base::ScopedClosureRunner
> file_closer
;
519 error
= FILE_ERROR_FAILED
;
520 base::PostTaskAndReplyWithResult(
521 blocking_task_runner(),
523 base::Bind(&FileCache::OpenForWrite
,
524 base::Unretained(cache()),
527 google_apis::test_util::CreateCopyResultCallback(&error
));
528 content::RunAllBlockingPoolTasksUntilIdle();
529 EXPECT_EQ(FILE_ERROR_OK
, error
);
531 // Update, but no update is performed because the file is opened.
532 error
= FILE_ERROR_FAILED
;
533 performer_
->UpdateEntry(
535 ClientContext(USER_INITIATED
),
536 google_apis::test_util::CreateCopyResultCallback(&error
));
537 content::RunAllBlockingPoolTasksUntilIdle();
538 EXPECT_EQ(FILE_ERROR_OK
, error
);
540 // The entry hasn't got a resource ID yet.
541 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kFilePath
, &entry
));
542 EXPECT_TRUE(entry
.resource_id().empty());
547 // Update. This should result in creating a new file on the server.
548 error
= FILE_ERROR_FAILED
;
549 performer_
->UpdateEntry(
551 ClientContext(USER_INITIATED
),
552 google_apis::test_util::CreateCopyResultCallback(&error
));
553 content::RunAllBlockingPoolTasksUntilIdle();
554 EXPECT_EQ(FILE_ERROR_OK
, error
);
556 // The entry got a resource ID.
557 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kFilePath
, &entry
));
558 EXPECT_FALSE(entry
.resource_id().empty());
559 EXPECT_EQ(ResourceEntry::CLEAN
, entry
.metadata_edit_state());
562 TEST_F(EntryUpdatePerformerTest
, UpdateEntry_CreateDirectory
) {
563 // Create a new directory locally.
564 const base::FilePath
kPath(FILE_PATH_LITERAL("drive/root/New Directory"));
566 ResourceEntry parent
;
567 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kPath
.DirName(), &parent
));
570 entry
.set_parent_local_id(parent
.local_id());
571 entry
.set_title(kPath
.BaseName().AsUTF8Unsafe());
572 entry
.mutable_file_info()->set_is_directory(true);
573 entry
.set_metadata_edit_state(ResourceEntry::DIRTY
);
575 FileError error
= FILE_ERROR_FAILED
;
576 std::string local_id
;
577 base::PostTaskAndReplyWithResult(
578 blocking_task_runner(),
580 base::Bind(&internal::ResourceMetadata::AddEntry
,
581 base::Unretained(metadata()),
584 google_apis::test_util::CreateCopyResultCallback(&error
));
585 content::RunAllBlockingPoolTasksUntilIdle();
586 EXPECT_EQ(FILE_ERROR_OK
, error
);
588 // Update. This should result in creating a new directory on the server.
589 error
= FILE_ERROR_FAILED
;
590 performer_
->UpdateEntry(
592 ClientContext(USER_INITIATED
),
593 google_apis::test_util::CreateCopyResultCallback(&error
));
594 content::RunAllBlockingPoolTasksUntilIdle();
595 EXPECT_EQ(FILE_ERROR_OK
, error
);
597 // The entry got a resource ID.
598 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(kPath
, &entry
));
599 EXPECT_FALSE(entry
.resource_id().empty());
600 EXPECT_EQ(ResourceEntry::CLEAN
, entry
.metadata_edit_state());
602 // Make sure that we really created a directory.
603 google_apis::DriveApiErrorCode status
= google_apis::DRIVE_OTHER_ERROR
;
604 scoped_ptr
<google_apis::FileResource
> server_entry
;
605 fake_service()->GetFileResource(
607 google_apis::test_util::CreateCopyResultCallback(&status
, &server_entry
));
608 content::RunAllBlockingPoolTasksUntilIdle();
609 EXPECT_EQ(google_apis::HTTP_SUCCESS
, status
);
610 ASSERT_TRUE(server_entry
);
611 EXPECT_TRUE(server_entry
->IsDirectory());
614 TEST_F(EntryUpdatePerformerTest
, UpdateEntry_InsufficientPermission
) {
615 base::FilePath
src_path(
616 FILE_PATH_LITERAL("drive/root/Directory 1/SubDirectory File 1.txt"));
618 ResourceEntry src_entry
;
619 EXPECT_EQ(FILE_ERROR_OK
, GetLocalResourceEntry(src_path
, &src_entry
));
621 // Update local entry.
622 ResourceEntry
updated_entry(src_entry
);
623 updated_entry
.set_title("Moved" + src_entry
.title());
624 updated_entry
.set_metadata_edit_state(ResourceEntry::DIRTY
);
626 FileError error
= FILE_ERROR_FAILED
;
627 base::PostTaskAndReplyWithResult(
628 blocking_task_runner(),
630 base::Bind(&ResourceMetadata::RefreshEntry
,
631 base::Unretained(metadata()),
633 google_apis::test_util::CreateCopyResultCallback(&error
));
634 content::RunAllBlockingPoolTasksUntilIdle();
635 EXPECT_EQ(FILE_ERROR_OK
, error
);
637 // Set user permission to forbid server side update.
638 EXPECT_EQ(google_apis::HTTP_SUCCESS
, fake_service()->SetUserPermission(
639 src_entry
.resource_id(), google_apis::drive::PERMISSION_ROLE_READER
));
641 // Try to perform update.
642 error
= FILE_ERROR_FAILED
;
643 performer_
->UpdateEntry(
644 src_entry
.local_id(),
645 ClientContext(USER_INITIATED
),
646 google_apis::test_util::CreateCopyResultCallback(&error
));
647 content::RunAllBlockingPoolTasksUntilIdle();
648 EXPECT_EQ(FILE_ERROR_OK
, error
);
650 // This should result in reverting the local change.
651 ResourceEntry result_entry
;
652 EXPECT_EQ(FILE_ERROR_OK
,
653 GetLocalResourceEntryById(src_entry
.local_id(), &result_entry
));
654 EXPECT_EQ(src_entry
.title(), result_entry
.title());
657 } // namespace internal