15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system/download_operation.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/files/file_util.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/task_runner_util.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/drive/fake_free_disk_space_getter.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/drive/file_cache.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/drive/file_change.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system/operation_test_base.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/drive/file_system_util.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/chromeos/drive/job_scheduler.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/drive/fake_drive_service.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_utils.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "google_apis/drive/test_util.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "third_party/cros_system_api/constants/cryptohome.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace drive {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace file_system {
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadOperationTest : public OperationTestBase {
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    OperationTestBase::SetUp();
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    operation_.reset(new DownloadOperation(
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        blocking_task_runner(), delegate(), scheduler(), metadata(), cache(),
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        temp_dir()));
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<DownloadOperation> operation_;
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DownloadOperationTest,
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       EnsureFileDownloadedByPath_FromServer_EnoughSpace) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ResourceEntry src_entry;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int64 file_size = src_entry.file_info().size();
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pretend we have enough space.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  fake_free_disk_space_getter()->set_default_value(
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_size + cryptohome::kMinFreeSpaceInBytes);
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FileError error = FILE_ERROR_FAILED;
49  base::FilePath file_path;
50  scoped_ptr<ResourceEntry> entry;
51  operation_->EnsureFileDownloadedByPath(
52      file_in_root,
53      ClientContext(USER_INITIATED),
54      GetFileContentInitializedCallback(),
55      google_apis::GetContentCallback(),
56      google_apis::test_util::CreateCopyResultCallback(
57          &error, &file_path, &entry));
58  content::RunAllBlockingPoolTasksUntilIdle();
59
60  EXPECT_EQ(FILE_ERROR_OK, error);
61  ASSERT_TRUE(entry);
62  EXPECT_FALSE(entry->file_specific_info().is_hosted_document());
63
64  // The transfered file is cached and the change of "offline available"
65  // attribute is notified.
66  EXPECT_EQ(1U, delegate()->get_changed_files().size());
67  EXPECT_EQ(1U, delegate()->get_changed_files().count(file_in_root));
68}
69
70TEST_F(DownloadOperationTest,
71       EnsureFileDownloadedByPath_FromServer_NoSpaceAtAll) {
72  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
73
74  // Pretend we have no space at all.
75  fake_free_disk_space_getter()->set_default_value(0);
76
77  FileError error = FILE_ERROR_OK;
78  base::FilePath file_path;
79  scoped_ptr<ResourceEntry> entry;
80  operation_->EnsureFileDownloadedByPath(
81      file_in_root,
82      ClientContext(USER_INITIATED),
83      GetFileContentInitializedCallback(),
84      google_apis::GetContentCallback(),
85      google_apis::test_util::CreateCopyResultCallback(
86          &error, &file_path, &entry));
87  content::RunAllBlockingPoolTasksUntilIdle();
88
89  EXPECT_EQ(FILE_ERROR_NO_LOCAL_SPACE, error);
90}
91
92TEST_F(DownloadOperationTest,
93       EnsureFileDownloadedByPath_FromServer_NoEnoughSpaceButCanFreeUp) {
94  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
95  ResourceEntry src_entry;
96  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
97  const int64 file_size = src_entry.file_info().size();
98
99  // Make another file cached.
100  // This file's cache file will be removed to free up the disk space.
101  base::FilePath cached_file(
102      FILE_PATH_LITERAL("drive/root/Duplicate Name.txt"));
103  FileError error = FILE_ERROR_FAILED;
104  base::FilePath file_path;
105  scoped_ptr<ResourceEntry> entry;
106  operation_->EnsureFileDownloadedByPath(
107      cached_file,
108      ClientContext(USER_INITIATED),
109      GetFileContentInitializedCallback(),
110      google_apis::GetContentCallback(),
111      google_apis::test_util::CreateCopyResultCallback(
112          &error, &file_path, &entry));
113  content::RunAllBlockingPoolTasksUntilIdle();
114  EXPECT_EQ(FILE_ERROR_OK, error);
115  ASSERT_TRUE(entry);
116  EXPECT_TRUE(entry->file_specific_info().cache_state().is_present());
117
118  // Pretend we have no space first (checked before downloading a file),
119  // but then start reporting we have space. This is to emulate that
120  // the disk space was freed up by removing temporary files.
121  fake_free_disk_space_getter()->set_default_value(
122      file_size + cryptohome::kMinFreeSpaceInBytes);
123  fake_free_disk_space_getter()->PushFakeValue(0);
124
125  operation_->EnsureFileDownloadedByPath(
126      file_in_root,
127      ClientContext(USER_INITIATED),
128      GetFileContentInitializedCallback(),
129      google_apis::GetContentCallback(),
130      google_apis::test_util::CreateCopyResultCallback(
131          &error, &file_path, &entry));
132  content::RunAllBlockingPoolTasksUntilIdle();
133
134  EXPECT_EQ(FILE_ERROR_OK, error);
135  ASSERT_TRUE(entry);
136  EXPECT_FALSE(entry->file_specific_info().is_hosted_document());
137
138  // The transfered file is cached and the change of "offline available"
139  // attribute is notified.
140  EXPECT_EQ(2U, delegate()->get_changed_files().size());
141  EXPECT_TRUE(delegate()->get_changed_files().count(file_in_root));
142  EXPECT_TRUE(delegate()->get_changed_files().count(cached_file));
143
144  // The cache for the other file should be removed in order to free up space.
145  ResourceEntry cached_file_entry;
146  EXPECT_EQ(FILE_ERROR_OK,
147            GetLocalResourceEntry(cached_file, &cached_file_entry));
148  EXPECT_FALSE(
149      cached_file_entry.file_specific_info().cache_state().is_present());
150}
151
152TEST_F(DownloadOperationTest,
153       EnsureFileDownloadedByPath_FromServer_EnoughSpaceButBecomeFull) {
154  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
155  ResourceEntry src_entry;
156  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
157  const int64 file_size = src_entry.file_info().size();
158
159  // Pretend we have enough space first (checked before downloading a file),
160  // but then start reporting we have not enough space. This is to emulate that
161  // the disk space becomes full after the file is downloaded for some reason
162  // (ex. the actual file was larger than the expected size).
163  fake_free_disk_space_getter()->PushFakeValue(
164      file_size + cryptohome::kMinFreeSpaceInBytes);
165  fake_free_disk_space_getter()->set_default_value(
166      cryptohome::kMinFreeSpaceInBytes - 1);
167
168  FileError error = FILE_ERROR_OK;
169  base::FilePath file_path;
170  scoped_ptr<ResourceEntry> entry;
171  operation_->EnsureFileDownloadedByPath(
172      file_in_root,
173      ClientContext(USER_INITIATED),
174      GetFileContentInitializedCallback(),
175      google_apis::GetContentCallback(),
176      google_apis::test_util::CreateCopyResultCallback(
177          &error, &file_path, &entry));
178  content::RunAllBlockingPoolTasksUntilIdle();
179
180  EXPECT_EQ(FILE_ERROR_NO_LOCAL_SPACE, error);
181}
182
183TEST_F(DownloadOperationTest, EnsureFileDownloadedByPath_FromCache) {
184  base::FilePath temp_file;
185  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir(), &temp_file));
186
187  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
188  ResourceEntry src_entry;
189  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
190
191  // Store something as cached version of this file.
192  FileError error = FILE_ERROR_OK;
193  base::PostTaskAndReplyWithResult(
194      blocking_task_runner(),
195      FROM_HERE,
196      base::Bind(&internal::FileCache::Store,
197                 base::Unretained(cache()),
198                 GetLocalId(file_in_root),
199                 src_entry.file_specific_info().md5(),
200                 temp_file,
201                 internal::FileCache::FILE_OPERATION_COPY),
202      google_apis::test_util::CreateCopyResultCallback(&error));
203  content::RunAllBlockingPoolTasksUntilIdle();
204  EXPECT_EQ(FILE_ERROR_OK, error);
205
206  base::FilePath file_path;
207  scoped_ptr<ResourceEntry> entry;
208  operation_->EnsureFileDownloadedByPath(
209      file_in_root,
210      ClientContext(USER_INITIATED),
211      GetFileContentInitializedCallback(),
212      google_apis::GetContentCallback(),
213      google_apis::test_util::CreateCopyResultCallback(
214          &error, &file_path, &entry));
215  content::RunAllBlockingPoolTasksUntilIdle();
216
217  EXPECT_EQ(FILE_ERROR_OK, error);
218  ASSERT_TRUE(entry);
219  EXPECT_FALSE(entry->file_specific_info().is_hosted_document());
220}
221
222TEST_F(DownloadOperationTest, EnsureFileDownloadedByPath_HostedDocument) {
223  base::FilePath file_in_root(FILE_PATH_LITERAL(
224      "drive/root/Document 1 excludeDir-test.gdoc"));
225
226  FileError error = FILE_ERROR_FAILED;
227  base::FilePath file_path;
228  scoped_ptr<ResourceEntry> entry;
229  operation_->EnsureFileDownloadedByPath(
230      file_in_root,
231      ClientContext(USER_INITIATED),
232      GetFileContentInitializedCallback(),
233      google_apis::GetContentCallback(),
234      google_apis::test_util::CreateCopyResultCallback(
235          &error, &file_path, &entry));
236  content::RunAllBlockingPoolTasksUntilIdle();
237
238  EXPECT_EQ(FILE_ERROR_OK, error);
239  ASSERT_TRUE(entry);
240  EXPECT_TRUE(entry->file_specific_info().is_hosted_document());
241  EXPECT_FALSE(file_path.empty());
242
243  EXPECT_EQ(GURL(entry->file_specific_info().alternate_url()),
244            util::ReadUrlFromGDocFile(file_path));
245  EXPECT_EQ(entry->resource_id(), util::ReadResourceIdFromGDocFile(file_path));
246  EXPECT_EQ(FILE_PATH_LITERAL(".gdoc"), file_path.Extension());
247}
248
249TEST_F(DownloadOperationTest, EnsureFileDownloadedByLocalId) {
250  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
251  ResourceEntry src_entry;
252  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
253
254  FileError error = FILE_ERROR_OK;
255  base::FilePath file_path;
256  scoped_ptr<ResourceEntry> entry;
257  operation_->EnsureFileDownloadedByLocalId(
258      GetLocalId(file_in_root),
259      ClientContext(USER_INITIATED),
260      GetFileContentInitializedCallback(),
261      google_apis::GetContentCallback(),
262      google_apis::test_util::CreateCopyResultCallback(
263          &error, &file_path, &entry));
264  content::RunAllBlockingPoolTasksUntilIdle();
265
266  EXPECT_EQ(FILE_ERROR_OK, error);
267  ASSERT_TRUE(entry);
268  EXPECT_FALSE(entry->file_specific_info().is_hosted_document());
269
270  // The transfered file is cached and the change of "offline available"
271  // attribute is notified.
272  EXPECT_EQ(1U, delegate()->get_changed_files().size());
273  EXPECT_EQ(1U, delegate()->get_changed_files().count(file_in_root));
274}
275
276TEST_F(DownloadOperationTest,
277       EnsureFileDownloadedByPath_WithGetContentCallback) {
278  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
279
280  {
281    FileError initialized_error = FILE_ERROR_FAILED;
282    scoped_ptr<ResourceEntry> entry, entry_dontcare;
283    base::FilePath local_path, local_path_dontcare;
284    google_apis::test_util::TestGetContentCallback get_content_callback;
285    FileError completion_error = FILE_ERROR_FAILED;
286    base::Closure cancel_download = operation_->EnsureFileDownloadedByPath(
287        file_in_root,
288        ClientContext(USER_INITIATED),
289        google_apis::test_util::CreateCopyResultCallback(
290            &initialized_error, &local_path, &entry),
291        get_content_callback.callback(),
292        google_apis::test_util::CreateCopyResultCallback(
293            &completion_error, &local_path_dontcare, &entry_dontcare));
294    content::RunAllBlockingPoolTasksUntilIdle();
295
296    // For the first time, file is downloaded from the remote server.
297    // In this case, |local_path| is empty.
298    EXPECT_EQ(FILE_ERROR_OK, initialized_error);
299    ASSERT_TRUE(entry);
300    ASSERT_TRUE(local_path.empty());
301    EXPECT_FALSE(cancel_download.is_null());
302    // Content is available through the second callback argument.
303    EXPECT_EQ(static_cast<size_t>(entry->file_info().size()),
304              get_content_callback.GetConcatenatedData().size());
305    EXPECT_EQ(FILE_ERROR_OK, completion_error);
306
307    // The transfered file is cached and the change of "offline available"
308    // attribute is notified.
309    EXPECT_EQ(1U, delegate()->get_changed_files().size());
310    EXPECT_EQ(1U, delegate()->get_changed_files().count(file_in_root));
311  }
312
313  {
314    FileError initialized_error = FILE_ERROR_FAILED;
315    scoped_ptr<ResourceEntry> entry, entry_dontcare;
316    base::FilePath local_path, local_path_dontcare;
317    google_apis::test_util::TestGetContentCallback get_content_callback;
318    FileError completion_error = FILE_ERROR_FAILED;
319    base::Closure cancel_download = operation_->EnsureFileDownloadedByPath(
320        file_in_root,
321        ClientContext(USER_INITIATED),
322        google_apis::test_util::CreateCopyResultCallback(
323            &initialized_error, &local_path, &entry),
324        get_content_callback.callback(),
325        google_apis::test_util::CreateCopyResultCallback(
326            &completion_error, &local_path_dontcare, &entry_dontcare));
327    content::RunAllBlockingPoolTasksUntilIdle();
328
329    // Try second download. In this case, the file should be cached, so
330    // |local_path| should not be empty.
331    EXPECT_EQ(FILE_ERROR_OK, initialized_error);
332    ASSERT_TRUE(entry);
333    ASSERT_TRUE(!local_path.empty());
334    EXPECT_FALSE(cancel_download.is_null());
335    // The content is available from the cache file.
336    EXPECT_TRUE(get_content_callback.data().empty());
337    int64 local_file_size = 0;
338    base::GetFileSize(local_path, &local_file_size);
339    EXPECT_EQ(entry->file_info().size(), local_file_size);
340    EXPECT_EQ(FILE_ERROR_OK, completion_error);
341  }
342}
343
344TEST_F(DownloadOperationTest, EnsureFileDownloadedByLocalId_FromCache) {
345  base::FilePath temp_file;
346  ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir(), &temp_file));
347
348  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
349  ResourceEntry src_entry;
350  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
351
352  // Store something as cached version of this file.
353  FileError error = FILE_ERROR_FAILED;
354  base::PostTaskAndReplyWithResult(
355      blocking_task_runner(),
356      FROM_HERE,
357      base::Bind(&internal::FileCache::Store,
358                 base::Unretained(cache()),
359                 GetLocalId(file_in_root),
360                 src_entry.file_specific_info().md5(),
361                 temp_file,
362                 internal::FileCache::FILE_OPERATION_COPY),
363      google_apis::test_util::CreateCopyResultCallback(&error));
364  content::RunAllBlockingPoolTasksUntilIdle();
365  EXPECT_EQ(FILE_ERROR_OK, error);
366
367  // The file is obtained from the cache.
368  // Hence the downloading should work even if the drive service is offline.
369  fake_service()->set_offline(true);
370
371  base::FilePath file_path;
372  scoped_ptr<ResourceEntry> entry;
373  operation_->EnsureFileDownloadedByLocalId(
374      GetLocalId(file_in_root),
375      ClientContext(USER_INITIATED),
376      GetFileContentInitializedCallback(),
377      google_apis::GetContentCallback(),
378      google_apis::test_util::CreateCopyResultCallback(
379          &error, &file_path, &entry));
380  content::RunAllBlockingPoolTasksUntilIdle();
381
382  EXPECT_EQ(FILE_ERROR_OK, error);
383  ASSERT_TRUE(entry);
384  EXPECT_FALSE(entry->file_specific_info().is_hosted_document());
385}
386
387TEST_F(DownloadOperationTest, EnsureFileDownloadedByPath_DirtyCache) {
388  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
389  ResourceEntry src_entry;
390  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
391
392  // Prepare a dirty file to store to cache that has a different size than
393  // stored in resource metadata.
394  base::FilePath dirty_file = temp_dir().AppendASCII("dirty.txt");
395  size_t dirty_size = src_entry.file_info().size() + 10;
396  google_apis::test_util::WriteStringToFile(dirty_file,
397                                            std::string(dirty_size, 'x'));
398
399  // Store the file as a cache, marking it to be dirty.
400  FileError error = FILE_ERROR_FAILED;
401  base::PostTaskAndReplyWithResult(
402      blocking_task_runner(),
403      FROM_HERE,
404      base::Bind(&internal::FileCache::Store,
405                 base::Unretained(cache()),
406                 GetLocalId(file_in_root),
407                 std::string(),
408                 dirty_file,
409                 internal::FileCache::FILE_OPERATION_COPY),
410      google_apis::test_util::CreateCopyResultCallback(&error));
411  content::RunAllBlockingPoolTasksUntilIdle();
412  EXPECT_EQ(FILE_ERROR_OK, error);
413
414  // Record values passed to GetFileContentInitializedCallback().
415  FileError init_error;
416  base::FilePath init_path;
417  scoped_ptr<ResourceEntry> init_entry;
418  base::FilePath file_path;
419  scoped_ptr<ResourceEntry> entry;
420  base::Closure cancel_callback = operation_->EnsureFileDownloadedByPath(
421      file_in_root,
422      ClientContext(USER_INITIATED),
423      google_apis::test_util::CreateCopyResultCallback(
424          &init_error, &init_path, &init_entry),
425      google_apis::GetContentCallback(),
426      google_apis::test_util::CreateCopyResultCallback(
427          &error, &file_path, &entry));
428  content::RunAllBlockingPoolTasksUntilIdle();
429
430  EXPECT_EQ(FILE_ERROR_OK, error);
431  // Check that the result of local modification is propagated.
432  EXPECT_EQ(static_cast<int64>(dirty_size), init_entry->file_info().size());
433  EXPECT_EQ(static_cast<int64>(dirty_size), entry->file_info().size());
434}
435
436TEST_F(DownloadOperationTest, EnsureFileDownloadedByPath_LocallyCreatedFile) {
437  // Add a new file with an empty resource ID.
438  base::FilePath file_path(FILE_PATH_LITERAL("drive/root/New File.txt"));
439  ResourceEntry parent;
440  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_path.DirName(), &parent));
441
442  ResourceEntry new_file;
443  new_file.set_title("New File.txt");
444  new_file.set_parent_local_id(parent.local_id());
445
446  FileError error = FILE_ERROR_FAILED;
447  std::string local_id;
448  base::PostTaskAndReplyWithResult(
449      blocking_task_runner(),
450      FROM_HERE,
451      base::Bind(&internal::ResourceMetadata::AddEntry,
452                 base::Unretained(metadata()),
453                 new_file,
454                 &local_id),
455      google_apis::test_util::CreateCopyResultCallback(&error));
456  content::RunAllBlockingPoolTasksUntilIdle();
457  EXPECT_EQ(FILE_ERROR_OK, error);
458
459  // Empty cache file should be returned.
460  base::FilePath cache_file_path;
461  scoped_ptr<ResourceEntry> entry;
462  operation_->EnsureFileDownloadedByPath(
463      file_path,
464      ClientContext(USER_INITIATED),
465      GetFileContentInitializedCallback(),
466      google_apis::GetContentCallback(),
467      google_apis::test_util::CreateCopyResultCallback(
468          &error, &cache_file_path, &entry));
469  content::RunAllBlockingPoolTasksUntilIdle();
470  EXPECT_EQ(FILE_ERROR_OK, error);
471
472  int64 cache_file_size = 0;
473  EXPECT_TRUE(base::GetFileSize(cache_file_path, &cache_file_size));
474  EXPECT_EQ(static_cast<int64>(0), cache_file_size);
475  ASSERT_TRUE(entry);
476  EXPECT_EQ(cache_file_size, entry->file_info().size());
477}
478
479TEST_F(DownloadOperationTest, CancelBeforeDownloadStarts) {
480  base::FilePath file_in_root(FILE_PATH_LITERAL("drive/root/File 1.txt"));
481  ResourceEntry src_entry;
482  ASSERT_EQ(FILE_ERROR_OK, GetLocalResourceEntry(file_in_root, &src_entry));
483
484  // Start operation.
485  FileError error = FILE_ERROR_OK;
486  base::FilePath file_path;
487  scoped_ptr<ResourceEntry> entry;
488  base::Closure cancel_closure = operation_->EnsureFileDownloadedByLocalId(
489      GetLocalId(file_in_root),
490      ClientContext(USER_INITIATED),
491      GetFileContentInitializedCallback(),
492      google_apis::GetContentCallback(),
493      google_apis::test_util::CreateCopyResultCallback(
494          &error, &file_path, &entry));
495
496  // Cancel immediately.
497  ASSERT_FALSE(cancel_closure.is_null());
498  cancel_closure.Run();
499  content::RunAllBlockingPoolTasksUntilIdle();
500
501  EXPECT_EQ(FILE_ERROR_ABORT, error);
502}
503
504}  // namespace file_system
505}  // namespace drive
506