// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/observer_list.h"
#include "base/strings/stringprintf.h"
#include "base/test/test_file_util.h"
#include "chrome/browser/download/download_path_reservation_tracker.h"
#include "chrome/browser/download/download_target_determiner.h"
#include "content/public/test/mock_download_item.h"
#include "content/public/test/test_browser_thread.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"

using content::BrowserThread;
using content::DownloadItem;
using content::MockDownloadItem;
using testing::AnyNumber;
using testing::Return;
using testing::ReturnRef;
using testing::ReturnRefOfCopy;

namespace {

class DownloadPathReservationTrackerTest : public testing::Test {
 public:
  DownloadPathReservationTrackerTest();

  // testing::Test
  void SetUp() override;
  void TearDown() override;

  MockDownloadItem* CreateDownloadItem(int32 id);
  base::FilePath GetPathInDownloadsDirectory(
      const base::FilePath::CharType* suffix);
  bool IsPathInUse(const base::FilePath& path);
  void CallGetReservedPath(
      DownloadItem* download_item,
      const base::FilePath& target_path,
      bool create_directory,
      DownloadPathReservationTracker::FilenameConflictAction conflict_action,
      base::FilePath* return_path,
      bool* return_verified);

  const base::FilePath& default_download_path() const {
    return default_download_path_;
  }
  void set_default_download_path(const base::FilePath& path) {
    default_download_path_ = path;
  }
  // Creates a name of form 'a'*repeat + suffix
  base::FilePath GetLongNamePathInDownloadsDirectory(
      size_t repeat, const base::FilePath::CharType* suffix);

 protected:
  base::ScopedTempDir test_download_dir_;
  base::FilePath default_download_path_;
  base::MessageLoopForUI message_loop_;
  content::TestBrowserThread ui_thread_;
  content::TestBrowserThread file_thread_;

 private:
  void TestReservedPathCallback(base::FilePath* return_path,
                                bool* return_verified, bool* did_run_callback,
                                const base::FilePath& path, bool verified);
};

DownloadPathReservationTrackerTest::DownloadPathReservationTrackerTest()
    : ui_thread_(BrowserThread::UI, &message_loop_),
      file_thread_(BrowserThread::FILE, &message_loop_) {
}

void DownloadPathReservationTrackerTest::SetUp() {
  ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
  set_default_download_path(test_download_dir_.path());
}

void DownloadPathReservationTrackerTest::TearDown() {
  message_loop_.RunUntilIdle();
}

MockDownloadItem* DownloadPathReservationTrackerTest::CreateDownloadItem(
    int32 id) {
  MockDownloadItem* item = new ::testing::StrictMock<MockDownloadItem>;
  EXPECT_CALL(*item, GetId())
      .WillRepeatedly(Return(id));
  EXPECT_CALL(*item, GetTargetFilePath())
      .WillRepeatedly(ReturnRefOfCopy(base::FilePath()));
  EXPECT_CALL(*item, GetState())
      .WillRepeatedly(Return(DownloadItem::IN_PROGRESS));
  return item;
}

base::FilePath DownloadPathReservationTrackerTest::GetPathInDownloadsDirectory(
    const base::FilePath::CharType* suffix) {
  return default_download_path().Append(suffix).NormalizePathSeparators();
}

bool DownloadPathReservationTrackerTest::IsPathInUse(
    const base::FilePath& path) {
  return DownloadPathReservationTracker::IsPathInUseForTesting(path);
}

void DownloadPathReservationTrackerTest::CallGetReservedPath(
    DownloadItem* download_item,
    const base::FilePath& target_path,
    bool create_directory,
    DownloadPathReservationTracker::FilenameConflictAction conflict_action,
    base::FilePath* return_path,
    bool* return_verified) {
  // Weak pointer factory to prevent the callback from running after this
  // function has returned.
  base::WeakPtrFactory<DownloadPathReservationTrackerTest> weak_ptr_factory(
      this);
  bool did_run_callback = false;
  DownloadPathReservationTracker::GetReservedPath(
      download_item,
      target_path,
      default_download_path(),
      create_directory,
      conflict_action,
      base::Bind(&DownloadPathReservationTrackerTest::TestReservedPathCallback,
                 weak_ptr_factory.GetWeakPtr(), return_path, return_verified,
                 &did_run_callback));
  message_loop_.RunUntilIdle();
  EXPECT_TRUE(did_run_callback);
}

void DownloadPathReservationTrackerTest::TestReservedPathCallback(
    base::FilePath* return_path, bool* return_verified, bool* did_run_callback,
    const base::FilePath& path, bool verified) {
  *did_run_callback = true;
  *return_path = path;
  *return_verified = verified;
}

base::FilePath
DownloadPathReservationTrackerTest::GetLongNamePathInDownloadsDirectory(
    size_t repeat, const base::FilePath::CharType* suffix) {
  return GetPathInDownloadsDirectory(
      (base::FilePath::StringType(repeat, FILE_PATH_LITERAL('a'))
          + suffix).c_str());
}

void SetDownloadItemState(content::MockDownloadItem* download_item,
                          content::DownloadItem::DownloadState state) {
  EXPECT_CALL(*download_item, GetState())
      .WillRepeatedly(Return(state));
  download_item->NotifyObserversDownloadUpdated();
}

}  // namespace

// A basic reservation is acquired and committed.
TEST_F(DownloadPathReservationTrackerTest, BasicReservation) {
  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
  base::FilePath path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
  ASSERT_FALSE(IsPathInUse(path));

  base::FilePath reserved_path;
  bool verified = false;
  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::OVERWRITE;
  bool create_directory = false;
  CallGetReservedPath(
      item.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path,
      &verified);
  EXPECT_TRUE(IsPathInUse(path));
  EXPECT_TRUE(verified);
  EXPECT_EQ(path.value(), reserved_path.value());

  // Destroying the item should release the reservation.
  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
  item.reset();
  message_loop_.RunUntilIdle();
  EXPECT_FALSE(IsPathInUse(path));
}

// A download that is interrupted should lose its reservation.
TEST_F(DownloadPathReservationTrackerTest, InterruptedDownload) {
  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
  base::FilePath path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
  ASSERT_FALSE(IsPathInUse(path));

  base::FilePath reserved_path;
  bool verified = false;
  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::OVERWRITE;
  bool create_directory = false;
  CallGetReservedPath(
      item.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path,
      &verified);
  EXPECT_TRUE(IsPathInUse(path));
  EXPECT_TRUE(verified);
  EXPECT_EQ(path.value(), reserved_path.value());

  // Once the download is interrupted, the path should become available again.
  SetDownloadItemState(item.get(), DownloadItem::INTERRUPTED);
  message_loop_.RunUntilIdle();
  EXPECT_FALSE(IsPathInUse(path));
}

// A completed download should also lose its reservation.
TEST_F(DownloadPathReservationTrackerTest, CompleteDownload) {
  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
  base::FilePath path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
  ASSERT_FALSE(IsPathInUse(path));

  base::FilePath reserved_path;
  bool verified = false;
  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::OVERWRITE;
  bool create_directory = false;
  CallGetReservedPath(
      item.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path,
      &verified);
  EXPECT_TRUE(IsPathInUse(path));
  EXPECT_TRUE(verified);
  EXPECT_EQ(path.value(), reserved_path.value());

  // Once the download completes, the path should become available again. For a
  // real download, at this point only the path reservation will be released.
  // The path wouldn't be available since it is occupied on disk by the
  // completed download.
  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
  message_loop_.RunUntilIdle();
  EXPECT_FALSE(IsPathInUse(path));
}

// If there are files on the file system, a unique reservation should uniquify
// around it.
TEST_F(DownloadPathReservationTrackerTest, ConflictingFiles) {
  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
  base::FilePath path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
  base::FilePath path1(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")));
  // Create a file at |path|, and a .crdownload file at |path1|.
  ASSERT_EQ(0, base::WriteFile(path, "", 0));
  ASSERT_EQ(0,
            base::WriteFile(
                DownloadTargetDeterminer::GetCrDownloadPath(path1), "", 0));
  ASSERT_TRUE(IsPathInUse(path));

  base::FilePath reserved_path;
  bool verified = false;
  bool create_directory = false;
  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::UNIQUIFY;
  CallGetReservedPath(
      item.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path,
      &verified);
  EXPECT_TRUE(IsPathInUse(path));
  EXPECT_TRUE(IsPathInUse(reserved_path));
  EXPECT_TRUE(verified);
  // The path should be uniquified, skipping over foo.txt but not over
  // "foo (1).txt.crdownload"
  EXPECT_EQ(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")).value(),
      reserved_path.value());

  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
  item.reset();
  message_loop_.RunUntilIdle();
  EXPECT_TRUE(IsPathInUse(path));
  EXPECT_FALSE(IsPathInUse(reserved_path));
}

// Multiple reservations for the same path should uniquify around each other.
TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) {
  scoped_ptr<MockDownloadItem> item1(CreateDownloadItem(1));
  base::FilePath path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
  base::FilePath uniquified_path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")));
  ASSERT_FALSE(IsPathInUse(path));
  ASSERT_FALSE(IsPathInUse(uniquified_path));

  base::FilePath reserved_path1;
  bool verified = false;
  bool create_directory = false;

  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::UNIQUIFY;
  CallGetReservedPath(
      item1.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path1,
      &verified);
  EXPECT_TRUE(IsPathInUse(path));
  EXPECT_TRUE(verified);


  {
    // Requesting a reservation for the same path with uniquification results in
    // a uniquified path.
    scoped_ptr<MockDownloadItem> item2(CreateDownloadItem(2));
    base::FilePath reserved_path2;
    CallGetReservedPath(
        item2.get(),
        path,
        create_directory,
        conflict_action,
        &reserved_path2,
        &verified);
    EXPECT_TRUE(IsPathInUse(path));
    EXPECT_TRUE(IsPathInUse(uniquified_path));
    EXPECT_EQ(uniquified_path.value(), reserved_path2.value());
    SetDownloadItemState(item2.get(), DownloadItem::COMPLETE);
  }
  message_loop_.RunUntilIdle();
  EXPECT_TRUE(IsPathInUse(path));
  EXPECT_FALSE(IsPathInUse(uniquified_path));

  {
    // Since the previous download item was removed, requesting a reservation
    // for the same path should result in the same uniquified path.
    scoped_ptr<MockDownloadItem> item2(CreateDownloadItem(2));
    base::FilePath reserved_path2;
    CallGetReservedPath(
        item2.get(),
        path,
        create_directory,
        conflict_action,
        &reserved_path2,
        &verified);
    EXPECT_TRUE(IsPathInUse(path));
    EXPECT_TRUE(IsPathInUse(uniquified_path));
    EXPECT_EQ(uniquified_path.value(), reserved_path2.value());
    SetDownloadItemState(item2.get(), DownloadItem::COMPLETE);
  }
  message_loop_.RunUntilIdle();

  // Now acquire an overwriting reservation. We should end up with the same
  // non-uniquified path for both reservations.
  scoped_ptr<MockDownloadItem> item3(CreateDownloadItem(2));
  base::FilePath reserved_path3;
  conflict_action = DownloadPathReservationTracker::OVERWRITE;
  CallGetReservedPath(
      item3.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path3,
      &verified);
  EXPECT_TRUE(IsPathInUse(path));
  EXPECT_FALSE(IsPathInUse(uniquified_path));

  EXPECT_EQ(path.value(), reserved_path1.value());
  EXPECT_EQ(path.value(), reserved_path3.value());

  SetDownloadItemState(item1.get(), DownloadItem::COMPLETE);
  SetDownloadItemState(item3.get(), DownloadItem::COMPLETE);
}

// If a unique path cannot be determined after trying kMaxUniqueFiles
// uniquifiers, then the callback should notified that verification failed, and
// the returned path should be set to the original requested path.
TEST_F(DownloadPathReservationTrackerTest, UnresolvedConflicts) {
  base::FilePath path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
  scoped_ptr<MockDownloadItem>
      items[DownloadPathReservationTracker::kMaxUniqueFiles + 1];
  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::UNIQUIFY;
  bool create_directory = false;

  // Create |kMaxUniqueFiles + 1| reservations for |path|. The first reservation
  // will have no uniquifier. The |kMaxUniqueFiles| remaining reservations do.
  for (int i = 0; i <= DownloadPathReservationTracker::kMaxUniqueFiles; i++) {
    base::FilePath reserved_path;
    base::FilePath expected_path;
    bool verified = false;
    if (i > 0) {
      expected_path =
          path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", i));
    } else {
      expected_path = path;
    }
    items[i].reset(CreateDownloadItem(i));
    EXPECT_FALSE(IsPathInUse(expected_path));
    CallGetReservedPath(
        items[i].get(),
        path,
        create_directory,
        conflict_action,
        &reserved_path,
        &verified);
    EXPECT_TRUE(IsPathInUse(expected_path));
    EXPECT_EQ(expected_path.value(), reserved_path.value());
    EXPECT_TRUE(verified);
  }
  // The next reservation for |path| will fail to be unique.
  scoped_ptr<MockDownloadItem> item(
      CreateDownloadItem(DownloadPathReservationTracker::kMaxUniqueFiles + 1));
  base::FilePath reserved_path;
  bool verified = true;
  CallGetReservedPath(
      item.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path,
      &verified);
  EXPECT_FALSE(verified);
  EXPECT_EQ(path.value(), reserved_path.value());

  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
  for (int i = 0; i <= DownloadPathReservationTracker::kMaxUniqueFiles; i++)
    SetDownloadItemState(items[i].get(), DownloadItem::COMPLETE);
}

// If the target directory is unwriteable, then callback should be notified that
// verification failed.
TEST_F(DownloadPathReservationTrackerTest, UnwriteableDirectory) {
  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
  base::FilePath path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
  base::FilePath dir(path.DirName());
  ASSERT_FALSE(IsPathInUse(path));

  {
    // Scope for FilePermissionRestorer
    base::FilePermissionRestorer restorer(dir);
    EXPECT_TRUE(base::MakeFileUnwritable(dir));
    base::FilePath reserved_path;
    bool verified = true;
    DownloadPathReservationTracker::FilenameConflictAction conflict_action =
      DownloadPathReservationTracker::OVERWRITE;
    bool create_directory = false;
    CallGetReservedPath(
        item.get(),
        path,
        create_directory,
        conflict_action,
        &reserved_path,
        &verified);
    // Verification fails.
    EXPECT_FALSE(verified);
    EXPECT_EQ(path.BaseName().value(), reserved_path.BaseName().value());
  }
  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
}

// If the default download directory doesn't exist, then it should be
// created. But only if we are actually going to create the download path there.
TEST_F(DownloadPathReservationTrackerTest, CreateDefaultDownloadPath) {
  base::FilePath path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo/foo.txt")));
  base::FilePath dir(path.DirName());
  ASSERT_FALSE(base::DirectoryExists(dir));
  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::OVERWRITE;
  bool create_directory = false;

  {
    scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    base::FilePath reserved_path;
    bool verified = true;
    CallGetReservedPath(
        item.get(),
        path,
        create_directory,
        conflict_action,
        &reserved_path,
        &verified);
    // Verification fails because the directory doesn't exist.
    EXPECT_FALSE(verified);
    SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
  }
  ASSERT_FALSE(IsPathInUse(path));
  {
    scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    base::FilePath reserved_path;
    bool verified = true;
    set_default_download_path(dir);
    CallGetReservedPath(
        item.get(),
        path,
        create_directory,
        conflict_action,
        &reserved_path,
        &verified);
    // Verification succeeds because the directory is created.
    EXPECT_TRUE(verified);
    EXPECT_TRUE(base::DirectoryExists(dir));
    SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
  }
}

// If the target path of the download item changes, the reservation should be
// updated to match.
TEST_F(DownloadPathReservationTrackerTest, UpdatesToTargetPath) {
  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
  base::FilePath path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
  ASSERT_FALSE(IsPathInUse(path));

  base::FilePath reserved_path;
  bool verified = false;
  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::OVERWRITE;
  bool create_directory = false;
  CallGetReservedPath(
      item.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path,
      &verified);
  EXPECT_TRUE(IsPathInUse(path));
  EXPECT_TRUE(verified);
  EXPECT_EQ(path.value(), reserved_path.value());

  // The target path is initially empty. If an OnDownloadUpdated() is issued in
  // this state, we shouldn't lose the reservation.
  ASSERT_EQ(base::FilePath::StringType(), item->GetTargetFilePath().value());
  item->NotifyObserversDownloadUpdated();
  message_loop_.RunUntilIdle();
  EXPECT_TRUE(IsPathInUse(path));

  // If the target path changes, we should update the reservation to match.
  base::FilePath new_target_path(
      GetPathInDownloadsDirectory(FILE_PATH_LITERAL("bar.txt")));
  ASSERT_FALSE(IsPathInUse(new_target_path));
  EXPECT_CALL(*item, GetTargetFilePath())
      .WillRepeatedly(ReturnRef(new_target_path));
  item->NotifyObserversDownloadUpdated();
  message_loop_.RunUntilIdle();
  EXPECT_FALSE(IsPathInUse(path));
  EXPECT_TRUE(IsPathInUse(new_target_path));

  // Destroying the item should release the reservation.
  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
  item.reset();
  message_loop_.RunUntilIdle();
  EXPECT_FALSE(IsPathInUse(new_target_path));
}

// Tests for long name truncation. On other platforms automatic truncation
// is not performed (yet).
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)

TEST_F(DownloadPathReservationTrackerTest, BasicTruncation) {
  int real_max_length =
      base::GetMaximumPathComponentLength(default_download_path());
  ASSERT_NE(-1, real_max_length);

  // TODO(kinaba): the current implementation leaves spaces for appending
  // ".crdownload". So take it into account. Should be removed in the future.
  const size_t max_length = real_max_length - 11;

  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
  base::FilePath path(GetLongNamePathInDownloadsDirectory(
      max_length, FILE_PATH_LITERAL(".txt")));
  ASSERT_FALSE(IsPathInUse(path));

  base::FilePath reserved_path;
  bool verified = false;
  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::OVERWRITE;
  bool create_directory = false;
  CallGetReservedPath(
      item.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path,
      &verified);
  EXPECT_TRUE(IsPathInUse(reserved_path));
  EXPECT_TRUE(verified);
  // The file name length is truncated to max_length.
  EXPECT_EQ(max_length, reserved_path.BaseName().value().size());
  // But the extension is kept unchanged.
  EXPECT_EQ(path.Extension(), reserved_path.Extension());
  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
}

TEST_F(DownloadPathReservationTrackerTest, TruncationConflict) {
  int real_max_length =
      base::GetMaximumPathComponentLength(default_download_path());
  ASSERT_NE(-1, real_max_length);
  const size_t max_length = real_max_length - 11;

  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
  base::FilePath path(GetLongNamePathInDownloadsDirectory(
      max_length, FILE_PATH_LITERAL(".txt")));
  base::FilePath path0(GetLongNamePathInDownloadsDirectory(
      max_length - 4, FILE_PATH_LITERAL(".txt")));
  base::FilePath path1(GetLongNamePathInDownloadsDirectory(
      max_length - 8, FILE_PATH_LITERAL(" (1).txt")));
  base::FilePath path2(GetLongNamePathInDownloadsDirectory(
      max_length - 8, FILE_PATH_LITERAL(" (2).txt")));
  ASSERT_FALSE(IsPathInUse(path));
  // "aaa...aaaaaaa.txt" (truncated path) and
  // "aaa...aaa (1).txt" (truncated and first uniquification try) exists.
  // "aaa...aaa (2).txt" should be used.
  ASSERT_EQ(0, base::WriteFile(path0, "", 0));
  ASSERT_EQ(0, base::WriteFile(path1, "", 0));

  base::FilePath reserved_path;
  bool verified = false;
  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::UNIQUIFY;
  bool create_directory = false;
  CallGetReservedPath(
      item.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path,
      &verified);
  EXPECT_TRUE(IsPathInUse(reserved_path));
  EXPECT_TRUE(verified);
  EXPECT_EQ(path2, reserved_path);
  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
}

TEST_F(DownloadPathReservationTrackerTest, TruncationFail) {
  int real_max_length =
      base::GetMaximumPathComponentLength(default_download_path());
  ASSERT_NE(-1, real_max_length);
  const size_t max_length = real_max_length - 11;

  scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
  base::FilePath path(GetPathInDownloadsDirectory(
      (FILE_PATH_LITERAL("a.") +
          base::FilePath::StringType(max_length, 'b')).c_str()));
  ASSERT_FALSE(IsPathInUse(path));

  base::FilePath reserved_path;
  bool verified = false;
  DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    DownloadPathReservationTracker::OVERWRITE;
  bool create_directory = false;
  CallGetReservedPath(
      item.get(),
      path,
      create_directory,
      conflict_action,
      &reserved_path,
      &verified);
  // We cannot truncate a path with very long extension.
  EXPECT_FALSE(verified);
  SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
}

#endif
