Home | History | Annotate | Download | only in download
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "base/files/file_path.h"
      6 #include "base/files/file_util.h"
      7 #include "base/files/scoped_temp_dir.h"
      8 #include "base/memory/weak_ptr.h"
      9 #include "base/message_loop/message_loop.h"
     10 #include "base/observer_list.h"
     11 #include "base/strings/stringprintf.h"
     12 #include "base/test/test_file_util.h"
     13 #include "chrome/browser/download/download_path_reservation_tracker.h"
     14 #include "chrome/browser/download/download_target_determiner.h"
     15 #include "content/public/test/mock_download_item.h"
     16 #include "content/public/test/test_browser_thread.h"
     17 #include "testing/gmock/include/gmock/gmock.h"
     18 #include "testing/gtest/include/gtest/gtest.h"
     19 
     20 using content::BrowserThread;
     21 using content::DownloadItem;
     22 using content::MockDownloadItem;
     23 using testing::AnyNumber;
     24 using testing::Return;
     25 using testing::ReturnRef;
     26 using testing::ReturnRefOfCopy;
     27 
     28 namespace {
     29 
     30 class DownloadPathReservationTrackerTest : public testing::Test {
     31  public:
     32   DownloadPathReservationTrackerTest();
     33 
     34   // testing::Test
     35   virtual void SetUp() OVERRIDE;
     36   virtual void TearDown() OVERRIDE;
     37 
     38   MockDownloadItem* CreateDownloadItem(int32 id);
     39   base::FilePath GetPathInDownloadsDirectory(
     40       const base::FilePath::CharType* suffix);
     41   bool IsPathInUse(const base::FilePath& path);
     42   void CallGetReservedPath(
     43       DownloadItem* download_item,
     44       const base::FilePath& target_path,
     45       bool create_directory,
     46       DownloadPathReservationTracker::FilenameConflictAction conflict_action,
     47       base::FilePath* return_path,
     48       bool* return_verified);
     49 
     50   const base::FilePath& default_download_path() const {
     51     return default_download_path_;
     52   }
     53   void set_default_download_path(const base::FilePath& path) {
     54     default_download_path_ = path;
     55   }
     56   // Creates a name of form 'a'*repeat + suffix
     57   base::FilePath GetLongNamePathInDownloadsDirectory(
     58       size_t repeat, const base::FilePath::CharType* suffix);
     59 
     60  protected:
     61   base::ScopedTempDir test_download_dir_;
     62   base::FilePath default_download_path_;
     63   base::MessageLoopForUI message_loop_;
     64   content::TestBrowserThread ui_thread_;
     65   content::TestBrowserThread file_thread_;
     66 
     67  private:
     68   void TestReservedPathCallback(base::FilePath* return_path,
     69                                 bool* return_verified, bool* did_run_callback,
     70                                 const base::FilePath& path, bool verified);
     71 };
     72 
     73 DownloadPathReservationTrackerTest::DownloadPathReservationTrackerTest()
     74     : ui_thread_(BrowserThread::UI, &message_loop_),
     75       file_thread_(BrowserThread::FILE, &message_loop_) {
     76 }
     77 
     78 void DownloadPathReservationTrackerTest::SetUp() {
     79   ASSERT_TRUE(test_download_dir_.CreateUniqueTempDir());
     80   set_default_download_path(test_download_dir_.path());
     81 }
     82 
     83 void DownloadPathReservationTrackerTest::TearDown() {
     84   message_loop_.RunUntilIdle();
     85 }
     86 
     87 MockDownloadItem* DownloadPathReservationTrackerTest::CreateDownloadItem(
     88     int32 id) {
     89   MockDownloadItem* item = new ::testing::StrictMock<MockDownloadItem>;
     90   EXPECT_CALL(*item, GetId())
     91       .WillRepeatedly(Return(id));
     92   EXPECT_CALL(*item, GetTargetFilePath())
     93       .WillRepeatedly(ReturnRefOfCopy(base::FilePath()));
     94   EXPECT_CALL(*item, GetState())
     95       .WillRepeatedly(Return(DownloadItem::IN_PROGRESS));
     96   return item;
     97 }
     98 
     99 base::FilePath DownloadPathReservationTrackerTest::GetPathInDownloadsDirectory(
    100     const base::FilePath::CharType* suffix) {
    101   return default_download_path().Append(suffix).NormalizePathSeparators();
    102 }
    103 
    104 bool DownloadPathReservationTrackerTest::IsPathInUse(
    105     const base::FilePath& path) {
    106   return DownloadPathReservationTracker::IsPathInUseForTesting(path);
    107 }
    108 
    109 void DownloadPathReservationTrackerTest::CallGetReservedPath(
    110     DownloadItem* download_item,
    111     const base::FilePath& target_path,
    112     bool create_directory,
    113     DownloadPathReservationTracker::FilenameConflictAction conflict_action,
    114     base::FilePath* return_path,
    115     bool* return_verified) {
    116   // Weak pointer factory to prevent the callback from running after this
    117   // function has returned.
    118   base::WeakPtrFactory<DownloadPathReservationTrackerTest> weak_ptr_factory(
    119       this);
    120   bool did_run_callback = false;
    121   DownloadPathReservationTracker::GetReservedPath(
    122       download_item,
    123       target_path,
    124       default_download_path(),
    125       create_directory,
    126       conflict_action,
    127       base::Bind(&DownloadPathReservationTrackerTest::TestReservedPathCallback,
    128                  weak_ptr_factory.GetWeakPtr(), return_path, return_verified,
    129                  &did_run_callback));
    130   message_loop_.RunUntilIdle();
    131   EXPECT_TRUE(did_run_callback);
    132 }
    133 
    134 void DownloadPathReservationTrackerTest::TestReservedPathCallback(
    135     base::FilePath* return_path, bool* return_verified, bool* did_run_callback,
    136     const base::FilePath& path, bool verified) {
    137   *did_run_callback = true;
    138   *return_path = path;
    139   *return_verified = verified;
    140 }
    141 
    142 base::FilePath
    143 DownloadPathReservationTrackerTest::GetLongNamePathInDownloadsDirectory(
    144     size_t repeat, const base::FilePath::CharType* suffix) {
    145   return GetPathInDownloadsDirectory(
    146       (base::FilePath::StringType(repeat, FILE_PATH_LITERAL('a'))
    147           + suffix).c_str());
    148 }
    149 
    150 void SetDownloadItemState(content::MockDownloadItem* download_item,
    151                           content::DownloadItem::DownloadState state) {
    152   EXPECT_CALL(*download_item, GetState())
    153       .WillRepeatedly(Return(state));
    154   download_item->NotifyObserversDownloadUpdated();
    155 }
    156 
    157 }  // namespace
    158 
    159 // A basic reservation is acquired and committed.
    160 TEST_F(DownloadPathReservationTrackerTest, BasicReservation) {
    161   scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    162   base::FilePath path(
    163       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
    164   ASSERT_FALSE(IsPathInUse(path));
    165 
    166   base::FilePath reserved_path;
    167   bool verified = false;
    168   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    169     DownloadPathReservationTracker::OVERWRITE;
    170   bool create_directory = false;
    171   CallGetReservedPath(
    172       item.get(),
    173       path,
    174       create_directory,
    175       conflict_action,
    176       &reserved_path,
    177       &verified);
    178   EXPECT_TRUE(IsPathInUse(path));
    179   EXPECT_TRUE(verified);
    180   EXPECT_EQ(path.value(), reserved_path.value());
    181 
    182   // Destroying the item should release the reservation.
    183   SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    184   item.reset();
    185   message_loop_.RunUntilIdle();
    186   EXPECT_FALSE(IsPathInUse(path));
    187 }
    188 
    189 // A download that is interrupted should lose its reservation.
    190 TEST_F(DownloadPathReservationTrackerTest, InterruptedDownload) {
    191   scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    192   base::FilePath path(
    193       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
    194   ASSERT_FALSE(IsPathInUse(path));
    195 
    196   base::FilePath reserved_path;
    197   bool verified = false;
    198   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    199     DownloadPathReservationTracker::OVERWRITE;
    200   bool create_directory = false;
    201   CallGetReservedPath(
    202       item.get(),
    203       path,
    204       create_directory,
    205       conflict_action,
    206       &reserved_path,
    207       &verified);
    208   EXPECT_TRUE(IsPathInUse(path));
    209   EXPECT_TRUE(verified);
    210   EXPECT_EQ(path.value(), reserved_path.value());
    211 
    212   // Once the download is interrupted, the path should become available again.
    213   SetDownloadItemState(item.get(), DownloadItem::INTERRUPTED);
    214   message_loop_.RunUntilIdle();
    215   EXPECT_FALSE(IsPathInUse(path));
    216 }
    217 
    218 // A completed download should also lose its reservation.
    219 TEST_F(DownloadPathReservationTrackerTest, CompleteDownload) {
    220   scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    221   base::FilePath path(
    222       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
    223   ASSERT_FALSE(IsPathInUse(path));
    224 
    225   base::FilePath reserved_path;
    226   bool verified = false;
    227   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    228     DownloadPathReservationTracker::OVERWRITE;
    229   bool create_directory = false;
    230   CallGetReservedPath(
    231       item.get(),
    232       path,
    233       create_directory,
    234       conflict_action,
    235       &reserved_path,
    236       &verified);
    237   EXPECT_TRUE(IsPathInUse(path));
    238   EXPECT_TRUE(verified);
    239   EXPECT_EQ(path.value(), reserved_path.value());
    240 
    241   // Once the download completes, the path should become available again. For a
    242   // real download, at this point only the path reservation will be released.
    243   // The path wouldn't be available since it is occupied on disk by the
    244   // completed download.
    245   SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    246   message_loop_.RunUntilIdle();
    247   EXPECT_FALSE(IsPathInUse(path));
    248 }
    249 
    250 // If there are files on the file system, a unique reservation should uniquify
    251 // around it.
    252 TEST_F(DownloadPathReservationTrackerTest, ConflictingFiles) {
    253   scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    254   base::FilePath path(
    255       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
    256   base::FilePath path1(
    257       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")));
    258   // Create a file at |path|, and a .crdownload file at |path1|.
    259   ASSERT_EQ(0, base::WriteFile(path, "", 0));
    260   ASSERT_EQ(0,
    261             base::WriteFile(
    262                 DownloadTargetDeterminer::GetCrDownloadPath(path1), "", 0));
    263   ASSERT_TRUE(IsPathInUse(path));
    264 
    265   base::FilePath reserved_path;
    266   bool verified = false;
    267   bool create_directory = false;
    268   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    269     DownloadPathReservationTracker::UNIQUIFY;
    270   CallGetReservedPath(
    271       item.get(),
    272       path,
    273       create_directory,
    274       conflict_action,
    275       &reserved_path,
    276       &verified);
    277   EXPECT_TRUE(IsPathInUse(path));
    278   EXPECT_TRUE(IsPathInUse(reserved_path));
    279   EXPECT_TRUE(verified);
    280   // The path should be uniquified, skipping over foo.txt but not over
    281   // "foo (1).txt.crdownload"
    282   EXPECT_EQ(
    283       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")).value(),
    284       reserved_path.value());
    285 
    286   SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    287   item.reset();
    288   message_loop_.RunUntilIdle();
    289   EXPECT_TRUE(IsPathInUse(path));
    290   EXPECT_FALSE(IsPathInUse(reserved_path));
    291 }
    292 
    293 // Multiple reservations for the same path should uniquify around each other.
    294 TEST_F(DownloadPathReservationTrackerTest, ConflictingReservations) {
    295   scoped_ptr<MockDownloadItem> item1(CreateDownloadItem(1));
    296   base::FilePath path(
    297       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
    298   base::FilePath uniquified_path(
    299       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo (1).txt")));
    300   ASSERT_FALSE(IsPathInUse(path));
    301   ASSERT_FALSE(IsPathInUse(uniquified_path));
    302 
    303   base::FilePath reserved_path1;
    304   bool verified = false;
    305   bool create_directory = false;
    306 
    307   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    308     DownloadPathReservationTracker::UNIQUIFY;
    309   CallGetReservedPath(
    310       item1.get(),
    311       path,
    312       create_directory,
    313       conflict_action,
    314       &reserved_path1,
    315       &verified);
    316   EXPECT_TRUE(IsPathInUse(path));
    317   EXPECT_TRUE(verified);
    318 
    319 
    320   {
    321     // Requesting a reservation for the same path with uniquification results in
    322     // a uniquified path.
    323     scoped_ptr<MockDownloadItem> item2(CreateDownloadItem(2));
    324     base::FilePath reserved_path2;
    325     CallGetReservedPath(
    326         item2.get(),
    327         path,
    328         create_directory,
    329         conflict_action,
    330         &reserved_path2,
    331         &verified);
    332     EXPECT_TRUE(IsPathInUse(path));
    333     EXPECT_TRUE(IsPathInUse(uniquified_path));
    334     EXPECT_EQ(uniquified_path.value(), reserved_path2.value());
    335     SetDownloadItemState(item2.get(), DownloadItem::COMPLETE);
    336   }
    337   message_loop_.RunUntilIdle();
    338   EXPECT_TRUE(IsPathInUse(path));
    339   EXPECT_FALSE(IsPathInUse(uniquified_path));
    340 
    341   {
    342     // Since the previous download item was removed, requesting a reservation
    343     // for the same path should result in the same uniquified path.
    344     scoped_ptr<MockDownloadItem> item2(CreateDownloadItem(2));
    345     base::FilePath reserved_path2;
    346     CallGetReservedPath(
    347         item2.get(),
    348         path,
    349         create_directory,
    350         conflict_action,
    351         &reserved_path2,
    352         &verified);
    353     EXPECT_TRUE(IsPathInUse(path));
    354     EXPECT_TRUE(IsPathInUse(uniquified_path));
    355     EXPECT_EQ(uniquified_path.value(), reserved_path2.value());
    356     SetDownloadItemState(item2.get(), DownloadItem::COMPLETE);
    357   }
    358   message_loop_.RunUntilIdle();
    359 
    360   // Now acquire an overwriting reservation. We should end up with the same
    361   // non-uniquified path for both reservations.
    362   scoped_ptr<MockDownloadItem> item3(CreateDownloadItem(2));
    363   base::FilePath reserved_path3;
    364   conflict_action = DownloadPathReservationTracker::OVERWRITE;
    365   CallGetReservedPath(
    366       item3.get(),
    367       path,
    368       create_directory,
    369       conflict_action,
    370       &reserved_path3,
    371       &verified);
    372   EXPECT_TRUE(IsPathInUse(path));
    373   EXPECT_FALSE(IsPathInUse(uniquified_path));
    374 
    375   EXPECT_EQ(path.value(), reserved_path1.value());
    376   EXPECT_EQ(path.value(), reserved_path3.value());
    377 
    378   SetDownloadItemState(item1.get(), DownloadItem::COMPLETE);
    379   SetDownloadItemState(item3.get(), DownloadItem::COMPLETE);
    380 }
    381 
    382 // If a unique path cannot be determined after trying kMaxUniqueFiles
    383 // uniquifiers, then the callback should notified that verification failed, and
    384 // the returned path should be set to the original requested path.
    385 TEST_F(DownloadPathReservationTrackerTest, UnresolvedConflicts) {
    386   base::FilePath path(
    387       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
    388   scoped_ptr<MockDownloadItem>
    389       items[DownloadPathReservationTracker::kMaxUniqueFiles + 1];
    390   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    391     DownloadPathReservationTracker::UNIQUIFY;
    392   bool create_directory = false;
    393 
    394   // Create |kMaxUniqueFiles + 1| reservations for |path|. The first reservation
    395   // will have no uniquifier. The |kMaxUniqueFiles| remaining reservations do.
    396   for (int i = 0; i <= DownloadPathReservationTracker::kMaxUniqueFiles; i++) {
    397     base::FilePath reserved_path;
    398     base::FilePath expected_path;
    399     bool verified = false;
    400     if (i > 0) {
    401       expected_path =
    402           path.InsertBeforeExtensionASCII(base::StringPrintf(" (%d)", i));
    403     } else {
    404       expected_path = path;
    405     }
    406     items[i].reset(CreateDownloadItem(i));
    407     EXPECT_FALSE(IsPathInUse(expected_path));
    408     CallGetReservedPath(
    409         items[i].get(),
    410         path,
    411         create_directory,
    412         conflict_action,
    413         &reserved_path,
    414         &verified);
    415     EXPECT_TRUE(IsPathInUse(expected_path));
    416     EXPECT_EQ(expected_path.value(), reserved_path.value());
    417     EXPECT_TRUE(verified);
    418   }
    419   // The next reservation for |path| will fail to be unique.
    420   scoped_ptr<MockDownloadItem> item(
    421       CreateDownloadItem(DownloadPathReservationTracker::kMaxUniqueFiles + 1));
    422   base::FilePath reserved_path;
    423   bool verified = true;
    424   CallGetReservedPath(
    425       item.get(),
    426       path,
    427       create_directory,
    428       conflict_action,
    429       &reserved_path,
    430       &verified);
    431   EXPECT_FALSE(verified);
    432   EXPECT_EQ(path.value(), reserved_path.value());
    433 
    434   SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    435   for (int i = 0; i <= DownloadPathReservationTracker::kMaxUniqueFiles; i++)
    436     SetDownloadItemState(items[i].get(), DownloadItem::COMPLETE);
    437 }
    438 
    439 // If the target directory is unwriteable, then callback should be notified that
    440 // verification failed.
    441 TEST_F(DownloadPathReservationTrackerTest, UnwriteableDirectory) {
    442   scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    443   base::FilePath path(
    444       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
    445   base::FilePath dir(path.DirName());
    446   ASSERT_FALSE(IsPathInUse(path));
    447 
    448   {
    449     // Scope for FilePermissionRestorer
    450     base::FilePermissionRestorer restorer(dir);
    451     EXPECT_TRUE(base::MakeFileUnwritable(dir));
    452     base::FilePath reserved_path;
    453     bool verified = true;
    454     DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    455       DownloadPathReservationTracker::OVERWRITE;
    456     bool create_directory = false;
    457     CallGetReservedPath(
    458         item.get(),
    459         path,
    460         create_directory,
    461         conflict_action,
    462         &reserved_path,
    463         &verified);
    464     // Verification fails.
    465     EXPECT_FALSE(verified);
    466     EXPECT_EQ(path.BaseName().value(), reserved_path.BaseName().value());
    467   }
    468   SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    469 }
    470 
    471 // If the default download directory doesn't exist, then it should be
    472 // created. But only if we are actually going to create the download path there.
    473 TEST_F(DownloadPathReservationTrackerTest, CreateDefaultDownloadPath) {
    474   base::FilePath path(
    475       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo/foo.txt")));
    476   base::FilePath dir(path.DirName());
    477   ASSERT_FALSE(base::DirectoryExists(dir));
    478   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    479     DownloadPathReservationTracker::OVERWRITE;
    480   bool create_directory = false;
    481 
    482   {
    483     scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    484     base::FilePath reserved_path;
    485     bool verified = true;
    486     CallGetReservedPath(
    487         item.get(),
    488         path,
    489         create_directory,
    490         conflict_action,
    491         &reserved_path,
    492         &verified);
    493     // Verification fails because the directory doesn't exist.
    494     EXPECT_FALSE(verified);
    495     SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    496   }
    497   ASSERT_FALSE(IsPathInUse(path));
    498   {
    499     scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    500     base::FilePath reserved_path;
    501     bool verified = true;
    502     set_default_download_path(dir);
    503     CallGetReservedPath(
    504         item.get(),
    505         path,
    506         create_directory,
    507         conflict_action,
    508         &reserved_path,
    509         &verified);
    510     // Verification succeeds because the directory is created.
    511     EXPECT_TRUE(verified);
    512     EXPECT_TRUE(base::DirectoryExists(dir));
    513     SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    514   }
    515 }
    516 
    517 // If the target path of the download item changes, the reservation should be
    518 // updated to match.
    519 TEST_F(DownloadPathReservationTrackerTest, UpdatesToTargetPath) {
    520   scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    521   base::FilePath path(
    522       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("foo.txt")));
    523   ASSERT_FALSE(IsPathInUse(path));
    524 
    525   base::FilePath reserved_path;
    526   bool verified = false;
    527   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    528     DownloadPathReservationTracker::OVERWRITE;
    529   bool create_directory = false;
    530   CallGetReservedPath(
    531       item.get(),
    532       path,
    533       create_directory,
    534       conflict_action,
    535       &reserved_path,
    536       &verified);
    537   EXPECT_TRUE(IsPathInUse(path));
    538   EXPECT_TRUE(verified);
    539   EXPECT_EQ(path.value(), reserved_path.value());
    540 
    541   // The target path is initially empty. If an OnDownloadUpdated() is issued in
    542   // this state, we shouldn't lose the reservation.
    543   ASSERT_EQ(base::FilePath::StringType(), item->GetTargetFilePath().value());
    544   item->NotifyObserversDownloadUpdated();
    545   message_loop_.RunUntilIdle();
    546   EXPECT_TRUE(IsPathInUse(path));
    547 
    548   // If the target path changes, we should update the reservation to match.
    549   base::FilePath new_target_path(
    550       GetPathInDownloadsDirectory(FILE_PATH_LITERAL("bar.txt")));
    551   ASSERT_FALSE(IsPathInUse(new_target_path));
    552   EXPECT_CALL(*item, GetTargetFilePath())
    553       .WillRepeatedly(ReturnRef(new_target_path));
    554   item->NotifyObserversDownloadUpdated();
    555   message_loop_.RunUntilIdle();
    556   EXPECT_FALSE(IsPathInUse(path));
    557   EXPECT_TRUE(IsPathInUse(new_target_path));
    558 
    559   // Destroying the item should release the reservation.
    560   SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    561   item.reset();
    562   message_loop_.RunUntilIdle();
    563   EXPECT_FALSE(IsPathInUse(new_target_path));
    564 }
    565 
    566 // Tests for long name truncation. On other platforms automatic truncation
    567 // is not performed (yet).
    568 #if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_CHROMEOS)
    569 
    570 TEST_F(DownloadPathReservationTrackerTest, BasicTruncation) {
    571   int real_max_length =
    572       base::GetMaximumPathComponentLength(default_download_path());
    573   ASSERT_NE(-1, real_max_length);
    574 
    575   // TODO(kinaba): the current implementation leaves spaces for appending
    576   // ".crdownload". So take it into account. Should be removed in the future.
    577   const size_t max_length = real_max_length - 11;
    578 
    579   scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    580   base::FilePath path(GetLongNamePathInDownloadsDirectory(
    581       max_length, FILE_PATH_LITERAL(".txt")));
    582   ASSERT_FALSE(IsPathInUse(path));
    583 
    584   base::FilePath reserved_path;
    585   bool verified = false;
    586   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    587     DownloadPathReservationTracker::OVERWRITE;
    588   bool create_directory = false;
    589   CallGetReservedPath(
    590       item.get(),
    591       path,
    592       create_directory,
    593       conflict_action,
    594       &reserved_path,
    595       &verified);
    596   EXPECT_TRUE(IsPathInUse(reserved_path));
    597   EXPECT_TRUE(verified);
    598   // The file name length is truncated to max_length.
    599   EXPECT_EQ(max_length, reserved_path.BaseName().value().size());
    600   // But the extension is kept unchanged.
    601   EXPECT_EQ(path.Extension(), reserved_path.Extension());
    602   SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    603 }
    604 
    605 TEST_F(DownloadPathReservationTrackerTest, TruncationConflict) {
    606   int real_max_length =
    607       base::GetMaximumPathComponentLength(default_download_path());
    608   ASSERT_NE(-1, real_max_length);
    609   const size_t max_length = real_max_length - 11;
    610 
    611   scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    612   base::FilePath path(GetLongNamePathInDownloadsDirectory(
    613       max_length, FILE_PATH_LITERAL(".txt")));
    614   base::FilePath path0(GetLongNamePathInDownloadsDirectory(
    615       max_length - 4, FILE_PATH_LITERAL(".txt")));
    616   base::FilePath path1(GetLongNamePathInDownloadsDirectory(
    617       max_length - 8, FILE_PATH_LITERAL(" (1).txt")));
    618   base::FilePath path2(GetLongNamePathInDownloadsDirectory(
    619       max_length - 8, FILE_PATH_LITERAL(" (2).txt")));
    620   ASSERT_FALSE(IsPathInUse(path));
    621   // "aaa...aaaaaaa.txt" (truncated path) and
    622   // "aaa...aaa (1).txt" (truncated and first uniquification try) exists.
    623   // "aaa...aaa (2).txt" should be used.
    624   ASSERT_EQ(0, base::WriteFile(path0, "", 0));
    625   ASSERT_EQ(0, base::WriteFile(path1, "", 0));
    626 
    627   base::FilePath reserved_path;
    628   bool verified = false;
    629   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    630     DownloadPathReservationTracker::UNIQUIFY;
    631   bool create_directory = false;
    632   CallGetReservedPath(
    633       item.get(),
    634       path,
    635       create_directory,
    636       conflict_action,
    637       &reserved_path,
    638       &verified);
    639   EXPECT_TRUE(IsPathInUse(reserved_path));
    640   EXPECT_TRUE(verified);
    641   EXPECT_EQ(path2, reserved_path);
    642   SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    643 }
    644 
    645 TEST_F(DownloadPathReservationTrackerTest, TruncationFail) {
    646   int real_max_length =
    647       base::GetMaximumPathComponentLength(default_download_path());
    648   ASSERT_NE(-1, real_max_length);
    649   const size_t max_length = real_max_length - 11;
    650 
    651   scoped_ptr<MockDownloadItem> item(CreateDownloadItem(1));
    652   base::FilePath path(GetPathInDownloadsDirectory(
    653       (FILE_PATH_LITERAL("a.") +
    654           base::FilePath::StringType(max_length, 'b')).c_str()));
    655   ASSERT_FALSE(IsPathInUse(path));
    656 
    657   base::FilePath reserved_path;
    658   bool verified = false;
    659   DownloadPathReservationTracker::FilenameConflictAction conflict_action =
    660     DownloadPathReservationTracker::OVERWRITE;
    661   bool create_directory = false;
    662   CallGetReservedPath(
    663       item.get(),
    664       path,
    665       create_directory,
    666       conflict_action,
    667       &reserved_path,
    668       &verified);
    669   // We cannot truncate a path with very long extension.
    670   EXPECT_FALSE(verified);
    671   SetDownloadItemState(item.get(), DownloadItem::COMPLETE);
    672 }
    673 
    674 #endif
    675