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