15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 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 "base/file_util.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/file_path.h"
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/weak_ptr.h"
99ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/observer_list.h"
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/stringprintf.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/test/test_file_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/download/download_path_reservation_tracker.h"
1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "chrome/browser/download/download_target_determiner.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/mock_download_item.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/test/test_browser_thread.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gmock/include/gmock/gmock.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::DownloadItem;
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::MockDownloadItem;
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::AnyNumber;
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::Return;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::ReturnRef;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using testing::ReturnRefOfCopy;
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class DownloadPathReservationTrackerTest : public testing::Test {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadPathReservationTrackerTest();
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // testing::Test
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() OVERRIDE;
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() OVERRIDE;
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockDownloadItem* CreateDownloadItem(int32 id);
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath GetPathInDownloadsDirectory(
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath::CharType* suffix);
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool IsPathInUse(const base::FilePath& path);
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CallGetReservedPath(
43868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      DownloadItem* download_item,
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const base::FilePath& target_path,
45c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      bool create_directory,
46c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DownloadPathReservationTracker::FilenameConflictAction conflict_action,
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::FilePath* return_path,
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bool* return_verified);
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const base::FilePath& default_download_path() const {
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return default_download_path_;
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void set_default_download_path(const base::FilePath& path) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default_download_path_ = path;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Creates a name of form 'a'*repeat + suffix
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath GetLongNamePathInDownloadsDirectory(
582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      size_t repeat, const base::FilePath::CharType* suffix);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir test_download_dir_;
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath default_download_path_;
6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoopForUI message_loop_;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread ui_thread_;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  content::TestBrowserThread file_thread_;
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void TestReservedPathCallback(base::FilePath* return_path,
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                bool* return_verified, bool* did_run_callback,
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                const base::FilePath& path, bool verified);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)DownloadPathReservationTrackerTest::DownloadPathReservationTrackerTest()
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : ui_thread_(BrowserThread::UI, &message_loop_),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      file_thread_(BrowserThread::FILE, &message_loop_) {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadPathReservationTrackerTest::SetUp() {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  set_default_download_path(test_download_dir_.path());
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadPathReservationTrackerTest::TearDown() {
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)MockDownloadItem* DownloadPathReservationTrackerTest::CreateDownloadItem(
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int32 id) {
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  MockDownloadItem* item = new ::testing::StrictMock<MockDownloadItem>;
90868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_CALL(*item, GetId())
91868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      .WillRepeatedly(Return(id));
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(*item, GetTargetFilePath())
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      .WillRepeatedly(ReturnRefOfCopy(base::FilePath()));
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_CALL(*item, GetState())
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      .WillRepeatedly(Return(DownloadItem::IN_PROGRESS));
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return item;
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath DownloadPathReservationTrackerTest::GetPathInDownloadsDirectory(
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath::CharType* suffix) {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return default_download_path().Append(suffix).NormalizePathSeparators();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool DownloadPathReservationTrackerTest::IsPathInUse(
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path) {
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return DownloadPathReservationTracker::IsPathInUseForTesting(path);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadPathReservationTrackerTest::CallGetReservedPath(
110868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DownloadItem* download_item,
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& target_path,
112c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool create_directory,
113c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::FilenameConflictAction conflict_action,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath* return_path,
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool* return_verified) {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Weak pointer factory to prevent the callback from running after this
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // function has returned.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::WeakPtrFactory<DownloadPathReservationTrackerTest> weak_ptr_factory(
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      this);
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool did_run_callback = false;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DownloadPathReservationTracker::GetReservedPath(
122c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      download_item,
123c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      target_path,
124c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      default_download_path(),
125c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
126c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      base::Bind(&DownloadPathReservationTrackerTest::TestReservedPathCallback,
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 weak_ptr_factory.GetWeakPtr(), return_path, return_verified,
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                 &did_run_callback));
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(did_run_callback);
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void DownloadPathReservationTrackerTest::TestReservedPathCallback(
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath* return_path, bool* return_verified, bool* did_run_callback,
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const base::FilePath& path, bool verified) {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *did_run_callback = true;
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *return_path = path;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *return_verified = verified;
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::FilePath
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)DownloadPathReservationTrackerTest::GetLongNamePathInDownloadsDirectory(
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    size_t repeat, const base::FilePath::CharType* suffix) {
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return GetPathInDownloadsDirectory(
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (base::FilePath::StringType(repeat, FILE_PATH_LITERAL('a'))
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          + suffix).c_str());
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SetDownloadItemState(content::MockDownloadItem* download_item,
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                          content::DownloadItem::DownloadState state) {
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  EXPECT_CALL(*download_item, GetState())
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      .WillRepeatedly(Return(state));
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  download_item->NotifyObserversDownloadUpdated();
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A basic reservation is acquired and committed.
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, BasicReservation) {
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(IsPathInUse(path));
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path;
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool verified = false;
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
169c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::OVERWRITE;
170c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
171c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
172868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item.get(),
173c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
174c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
175c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
176c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path,
177c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(path));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(verified);
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(path.value(), reserved_path.value());
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroying the item should release the reservation.
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item.reset();
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(IsPathInUse(path));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A download that is interrupted should lose its reservation.
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, InterruptedDownload) {
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(
1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(IsPathInUse(path));
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path;
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool verified = false;
198c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
199c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::OVERWRITE;
200c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
201c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item.get(),
203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
204c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
205c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
206c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path,
207c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(path));
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(verified);
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(path.value(), reserved_path.value());
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Once the download is interrupted, the path should become available again.
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item.get(), DownloadItem::INTERRUPTED);
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(IsPathInUse(path));
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// A completed download should also lose its reservation.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, CompleteDownload) {
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(IsPathInUse(path));
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool verified = false;
227c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
228c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::OVERWRITE;
229c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item.get(),
232c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
233c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
234c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
235c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path,
236c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(path));
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(verified);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(path.value(), reserved_path.value());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Once the download completes, the path should become available again. For a
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // real download, at this point only the path reservation will be released.
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The path wouldn't be available since it is occupied on disk by the
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // completed download.
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(IsPathInUse(path));
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If there are files on the file system, a unique reservation should uniquify
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// around it.
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, ConflictingFiles) {
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path1(
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")));
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a file at |path|, and a .crdownload file at |path1|.
259a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_EQ(0, base::WriteFile(path, "", 0));
26090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  ASSERT_EQ(0,
261a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)            base::WriteFile(
26290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)                DownloadTargetDeterminer::GetCrDownloadPath(path1), "", 0));
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(IsPathInUse(path));
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool verified = false;
267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
268c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
269c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::UNIQUIFY;
270c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item.get(),
272c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
273c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
274c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
275c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path,
276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(path));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(reserved_path));
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(verified);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The path should be uniquified, skipping over foo.txt but not over
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // "foo (1).txt.crdownload"
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")).value(),
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reserved_path.value());
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item.reset();
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(path));
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(IsPathInUse(reserved_path));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Multiple reservations for the same path should uniquify around each other.
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) {
295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item1(CreateDownloadItem(1));
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath uniquified_path(
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(IsPathInUse(path));
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(IsPathInUse(uniquified_path));
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path1;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool verified = false;
305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
306c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::UNIQUIFY;
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
310868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item1.get(),
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path1,
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(path));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(verified);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
319868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Requesting a reservation for the same path with uniquification results in
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // a uniquified path.
323cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<MockDownloadItem> item2(CreateDownloadItem(2));
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath reserved_path2;
325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CallGetReservedPath(
326868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        item2.get(),
327c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        path,
328c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        create_directory,
329c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        conflict_action,
330c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &reserved_path2,
331c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &verified);
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(IsPathInUse(path));
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(IsPathInUse(uniquified_path));
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(uniquified_path.value(), reserved_path2.value());
335cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SetDownloadItemState(item2.get(), DownloadItem::COMPLETE);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(path));
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(IsPathInUse(uniquified_path));
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Since the previous download item was removed, requesting a reservation
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // for the same path should result in the same uniquified path.
344cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<MockDownloadItem> item2(CreateDownloadItem(2));
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath reserved_path2;
346c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CallGetReservedPath(
347868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        item2.get(),
348c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        path,
349c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        create_directory,
350c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        conflict_action,
351c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &reserved_path2,
352c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &verified);
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(IsPathInUse(path));
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(IsPathInUse(uniquified_path));
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(uniquified_path.value(), reserved_path2.value());
356cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SetDownloadItemState(item2.get(), DownloadItem::COMPLETE);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Now acquire an overwriting reservation. We should end up with the same
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // non-uniquified path for both reservations.
362cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item3(CreateDownloadItem(2));
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path3;
364c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  conflict_action = DownloadPathReservationTracker::OVERWRITE;
365c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
366868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item3.get(),
367c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
368c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
369c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
370c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path3,
371c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(path));
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(IsPathInUse(uniquified_path));
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(path.value(), reserved_path1.value());
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(path.value(), reserved_path3.value());
377868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
378cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item1.get(), DownloadItem::COMPLETE);
379cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item3.get(), DownloadItem::COMPLETE);
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If a unique path cannot be determined after trying kMaxUniqueFiles
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// uniquifiers, then the callback should notified that verification failed, and
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the returned path should be set to the original requested path.
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, UnresolvedConflicts) {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem>
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      items[DownloadPathReservationTracker::kMaxUniqueFiles + 1];
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::UNIQUIFY;
392c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
393868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create |kMaxUniqueFiles + 1| reservations for |path|. The first reservation
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // will have no uniquifier. The |kMaxUniqueFiles| remaining reservations do.
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i <= DownloadPathReservationTracker::kMaxUniqueFiles; i++) {
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath reserved_path;
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath expected_path;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool verified = false;
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (i > 0) {
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      expected_path =
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", i));
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    } else {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      expected_path = path;
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    items[i].reset(CreateDownloadItem(i));
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(IsPathInUse(expected_path));
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CallGetReservedPath(
409868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        items[i].get(),
410c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        path,
411c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        create_directory,
412c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        conflict_action,
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &reserved_path,
414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &verified);
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(IsPathInUse(expected_path));
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(expected_path.value(), reserved_path.value());
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(verified);
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The next reservation for |path| will fail to be unique.
420cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item(
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      CreateDownloadItem(DownloadPathReservationTracker::kMaxUniqueFiles + 1));
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path;
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool verified = true;
424c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
425868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item.get(),
426c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
427c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
428c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
429c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path,
430c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(verified);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(path.value(), reserved_path.value());
433868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
434cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
435cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (int i = 0; i <= DownloadPathReservationTracker::kMaxUniqueFiles; i++)
436cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SetDownloadItemState(items[i].get(), DownloadItem::COMPLETE);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the target directory is unwriteable, then callback should be notified that
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// verification failed.
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, UnwriteableDirectory) {
442cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath dir(path.DirName());
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(IsPathInUse(path));
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Scope for PermissionRestorer
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    file_util::PermissionRestorer restorer(dir);
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(file_util::MakeFileUnwritable(dir));
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath reserved_path;
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool verified = true;
454c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::FilenameConflictAction conflict_action =
455c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      DownloadPathReservationTracker::OVERWRITE;
456c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool create_directory = false;
457c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CallGetReservedPath(
458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        item.get(),
459c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        path,
460c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        create_directory,
461c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        conflict_action,
462c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &reserved_path,
463c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &verified);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verification fails.
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(verified);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_EQ(path.BaseName().value(), reserved_path.BaseName().value());
4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
468cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the default download directory doesn't exist, then it should be
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// created. But only if we are actually going to create the download path there.
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, CreateDefaultDownloadPath) {
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo/foo.txt")));
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath dir(path.DirName());
4777dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  ASSERT_FALSE(base::DirectoryExists(dir));
478c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
479c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::OVERWRITE;
480c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
483cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath reserved_path;
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool verified = true;
486c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CallGetReservedPath(
487868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        item.get(),
488c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        path,
489c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        create_directory,
490c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        conflict_action,
491c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &reserved_path,
492c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &verified);
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verification fails because the directory doesn't exist.
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(verified);
495cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(IsPathInUse(path));
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
499cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    base::FilePath reserved_path;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool verified = true;
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    set_default_download_path(dir);
503c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    CallGetReservedPath(
504868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)        item.get(),
505c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        path,
506c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        create_directory,
507c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        conflict_action,
508c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &reserved_path,
509c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        &verified);
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Verification succeeds because the directory is created.
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(verified);
5127dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch    EXPECT_TRUE(base::DirectoryExists(dir));
513cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If the target path of the download item changes, the reservation should be
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// updated to match.
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, UpdatesToTargetPath) {
520cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(IsPathInUse(path));
5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path;
5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool verified = false;
527c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
528c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::OVERWRITE;
529c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
530c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
531868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item.get(),
532c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
533c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
534c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
535c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path,
536c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(path));
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(verified);
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(path.value(), reserved_path.value());
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The target path is initially empty. If an OnDownloadUpdated() is issued in
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // this state, we shouldn't lose the reservation.
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_EQ(base::FilePath::StringType(), item->GetTargetFilePath().value());
544cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  item->NotifyObserversDownloadUpdated();
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(path));
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the target path changes, we should update the reservation to match.
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath new_target_path(
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("bar.txt")));
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(IsPathInUse(new_target_path));
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_CALL(*item, GetTargetFilePath())
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      .WillRepeatedly(ReturnRef(new_target_path));
554cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  item->NotifyObserversDownloadUpdated();
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(IsPathInUse(path));
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(IsPathInUse(new_target_path));
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Destroying the item should release the reservation.
560cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  item.reset();
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  message_loop_.RunUntilIdle();
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(IsPathInUse(new_target_path));
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Tests for long name truncation. On other platforms automatic truncation
5672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// is not performed (yet).
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, BasicTruncation) {
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int real_max_length =
572a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::GetMaximumPathComponentLength(default_download_path());
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_NE(-1, real_max_length);
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // TODO(kinaba): the current implementation leaves spaces for appending
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ".crdownload". So take it into account. Should be removed in the future.
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t max_length = real_max_length - 11;
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
579cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(GetLongNamePathInDownloadsDirectory(
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_length, FILE_PATH_LITERAL(".txt")));
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(IsPathInUse(path));
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path;
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool verified = false;
586c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
587c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::OVERWRITE;
588c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
589c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
590868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item.get(),
591c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
592c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
593c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
594c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path,
595c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(IsPathInUse(reserved_path));
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(verified);
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The file name length is truncated to max_length.
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(max_length, reserved_path.BaseName().value().size());
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // But the extension is kept unchanged.
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(path.Extension(), reserved_path.Extension());
602cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, TruncationConflict) {
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int real_max_length =
607a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::GetMaximumPathComponentLength(default_download_path());
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_NE(-1, real_max_length);
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t max_length = real_max_length - 11;
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
611cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(GetLongNamePathInDownloadsDirectory(
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_length, FILE_PATH_LITERAL(".txt")));
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path0(GetLongNamePathInDownloadsDirectory(
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_length - 4, FILE_PATH_LITERAL(".txt")));
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path1(GetLongNamePathInDownloadsDirectory(
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_length - 8, FILE_PATH_LITERAL(" (1).txt")));
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path2(GetLongNamePathInDownloadsDirectory(
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      max_length - 8, FILE_PATH_LITERAL(" (2).txt")));
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(IsPathInUse(path));
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // "aaa...aaaaaaa.txt" (truncated path) and
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // "aaa...aaa (1).txt" (truncated and first uniquification try) exists.
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // "aaa...aaa (2).txt" should be used.
624a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_EQ(0, base::WriteFile(path0, "", 0));
625a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  ASSERT_EQ(0, base::WriteFile(path1, "", 0));
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path;
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool verified = false;
629c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::UNIQUIFY;
631c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
632c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
633868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item.get(),
634c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
635c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
636c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
637c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path,
638c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(IsPathInUse(reserved_path));
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_TRUE(verified);
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(path2, reserved_path);
642cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)TEST_F(DownloadPathReservationTrackerTest, TruncationFail) {
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int real_max_length =
647a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      base::GetMaximumPathComponentLength(default_download_path());
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_NE(-1, real_max_length);
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  const size_t max_length = real_max_length - 11;
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
651cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath path(GetPathInDownloadsDirectory(
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      (FILE_PATH_LITERAL("a.") +
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          base::FilePath::StringType(max_length, 'b')).c_str()));
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ASSERT_FALSE(IsPathInUse(path));
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath reserved_path;
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool verified = false;
659c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
660c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    DownloadPathReservationTracker::OVERWRITE;
661c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  bool create_directory = false;
662c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  CallGetReservedPath(
663868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      item.get(),
664c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      path,
665c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      create_directory,
666c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      conflict_action,
667c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &reserved_path,
668c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      &verified);
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // We cannot truncate a path with very long extension.
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_FALSE(verified);
671cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif
675