1 // Copyright (c) 2011 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 <string> 6 #include <set> 7 8 #include "base/file_util.h" 9 #include "base/memory/scoped_ptr.h" 10 #include "base/stl_util-inl.h" 11 #include "base/string_util.h" 12 #include "build/build_config.h" 13 #include "chrome/browser/download/download_file.h" 14 #include "chrome/browser/download/download_file_manager.h" 15 #include "chrome/browser/download/download_item.h" 16 #include "chrome/browser/download/download_manager.h" 17 #include "chrome/browser/download/download_prefs.h" 18 #include "chrome/browser/download/download_status_updater.h" 19 #include "chrome/browser/download/download_util.h" 20 #include "chrome/browser/download/mock_download_manager.h" 21 #include "chrome/browser/history/download_create_info.h" 22 #include "chrome/browser/prefs/pref_service.h" 23 #include "chrome/common/pref_names.h" 24 #include "chrome/test/testing_profile.h" 25 #include "content/browser/browser_thread.h" 26 #include "testing/gmock/include/gmock/gmock.h" 27 #include "testing/gmock_mutant.h" 28 #include "testing/gtest/include/gtest/gtest.h" 29 30 class DownloadManagerTest : public testing::Test { 31 public: 32 static const char* kTestData; 33 static const size_t kTestDataLen; 34 35 DownloadManagerTest() 36 : profile_(new TestingProfile()), 37 download_manager_(new MockDownloadManager(&download_status_updater_)), 38 ui_thread_(BrowserThread::UI, &message_loop_), 39 file_thread_(BrowserThread::FILE, &message_loop_) { 40 download_manager_->Init(profile_.get()); 41 } 42 43 ~DownloadManagerTest() { 44 download_manager_->Shutdown(); 45 // profile_ must outlive download_manager_, so we explicitly delete 46 // download_manager_ first. 47 download_manager_ = NULL; 48 profile_.reset(NULL); 49 message_loop_.RunAllPending(); 50 } 51 52 void AddDownloadToFileManager(int id, DownloadFile* download_file) { 53 file_manager()->downloads_[id] = download_file; 54 } 55 56 void OnAllDataSaved(int32 download_id, int64 size, const std::string& hash) { 57 download_manager_->OnAllDataSaved(download_id, size, hash); 58 } 59 60 void FileSelected(const FilePath& path, int index, void* params) { 61 download_manager_->FileSelected(path, index, params); 62 } 63 64 void AttachDownloadItem(DownloadCreateInfo* info) { 65 download_manager_->AttachDownloadItem(info); 66 } 67 68 void OnDownloadError(int32 download_id, int64 size, int os_error) { 69 download_manager_->OnDownloadError(download_id, size, os_error); 70 } 71 72 // Get the download item with ID |id|. 73 DownloadItem* GetActiveDownloadItem(int32 id) { 74 if (ContainsKey(download_manager_->active_downloads_, id)) 75 return download_manager_->active_downloads_[id]; 76 return NULL; 77 } 78 79 protected: 80 DownloadStatusUpdater download_status_updater_; 81 scoped_ptr<TestingProfile> profile_; 82 scoped_refptr<DownloadManager> download_manager_; 83 scoped_refptr<DownloadFileManager> file_manager_; 84 MessageLoopForUI message_loop_; 85 BrowserThread ui_thread_; 86 BrowserThread file_thread_; 87 88 DownloadFileManager* file_manager() { 89 if (!file_manager_) { 90 file_manager_ = new DownloadFileManager(NULL); 91 download_manager_->file_manager_ = file_manager_; 92 } 93 return file_manager_; 94 } 95 96 // Make sure download item |id| was set with correct safety state for 97 // given |is_dangerous_file| and |is_dangerous_url|. 98 bool VerifySafetyState(bool is_dangerous_file, 99 bool is_dangerous_url, 100 int id) { 101 DownloadItem::SafetyState safety_state = 102 download_manager_->GetDownloadItem(id)->safety_state(); 103 return (is_dangerous_file || is_dangerous_url) ? 104 safety_state != DownloadItem::SAFE : safety_state == DownloadItem::SAFE; 105 } 106 107 DISALLOW_COPY_AND_ASSIGN(DownloadManagerTest); 108 }; 109 110 const char* DownloadManagerTest::kTestData = "a;sdlfalsdfjalsdkfjad"; 111 const size_t DownloadManagerTest::kTestDataLen = 112 strlen(DownloadManagerTest::kTestData); 113 114 namespace { 115 116 const struct { 117 const char* url; 118 const char* mime_type; 119 bool save_as; 120 bool prompt_for_download; 121 bool expected_save_as; 122 } kStartDownloadCases[] = { 123 { "http://www.foo.com/dont-open.html", 124 "text/html", 125 false, 126 false, 127 false, }, 128 { "http://www.foo.com/save-as.html", 129 "text/html", 130 true, 131 false, 132 true, }, 133 { "http://www.foo.com/always-prompt.html", 134 "text/html", 135 false, 136 true, 137 true, }, 138 { "http://www.foo.com/user-script-text-html-mimetype.user.js", 139 "text/html", 140 false, 141 false, 142 false, }, 143 { "http://www.foo.com/extensionless-extension", 144 "application/x-chrome-extension", 145 true, 146 false, 147 true, }, 148 { "http://www.foo.com/save-as.pdf", 149 "application/pdf", 150 true, 151 false, 152 true, }, 153 { "http://www.foo.com/sometimes_prompt.pdf", 154 "application/pdf", 155 false, 156 true, 157 false, }, 158 { "http://www.foo.com/always_prompt.jar", 159 "application/jar", 160 false, 161 true, 162 true, }, 163 }; 164 165 const struct { 166 FilePath::StringType suggested_path; 167 bool is_dangerous_file; 168 bool is_dangerous_url; 169 bool finish_before_rename; 170 int expected_rename_count; 171 } kDownloadRenameCases[] = { 172 // Safe download, download finishes BEFORE file name determined. 173 // Renamed twice (linear path through UI). Crdownload file does not need 174 // to be deleted. 175 { FILE_PATH_LITERAL("foo.zip"), 176 false, false, true, 2, }, 177 // Dangerous download (file is dangerous or download URL is not safe or both), 178 // download finishes BEFORE file name determined. Needs to be renamed only 179 // once. 180 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), 181 true, false, true, 1, }, 182 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), 183 false, true, true, 1, }, 184 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), 185 true, true, true, 1, }, 186 // Safe download, download finishes AFTER file name determined. 187 // Needs to be renamed twice. 188 { FILE_PATH_LITERAL("foo.zip"), 189 false, false, false, 2, }, 190 // Dangerous download, download finishes AFTER file name determined. 191 // Needs to be renamed only once. 192 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), 193 true, false, false, 1, }, 194 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), 195 false, true, false, 1, }, 196 { FILE_PATH_LITERAL("Unconfirmed xxx.crdownload"), 197 true, true, false, 1, }, 198 }; 199 200 class MockDownloadFile : public DownloadFile { 201 public: 202 MockDownloadFile(DownloadCreateInfo* info, DownloadManager* manager) 203 : DownloadFile(info, manager), renamed_count_(0) { } 204 virtual ~MockDownloadFile() { Destructed(); } 205 MOCK_METHOD1(Rename, bool(const FilePath&)); 206 MOCK_METHOD0(Destructed, void()); 207 208 bool TestMultipleRename( 209 int expected_count, const FilePath& expected, 210 const FilePath& path) { 211 ++renamed_count_; 212 EXPECT_EQ(expected_count, renamed_count_); 213 EXPECT_EQ(expected.value(), path.value()); 214 return true; 215 } 216 217 private: 218 int renamed_count_; 219 }; 220 221 // This is an observer that records what download IDs have opened a select 222 // file dialog. 223 class SelectFileObserver : public DownloadManager::Observer { 224 public: 225 explicit SelectFileObserver(DownloadManager* download_manager) 226 : download_manager_(download_manager) { 227 DCHECK(download_manager_.get()); 228 download_manager_->AddObserver(this); 229 } 230 231 ~SelectFileObserver() { 232 download_manager_->RemoveObserver(this); 233 } 234 235 // Downloadmanager::Observer functions. 236 virtual void ModelChanged() {} 237 virtual void ManagerGoingDown() {} 238 virtual void SelectFileDialogDisplayed(int32 id) { 239 file_dialog_ids_.insert(id); 240 } 241 242 bool ShowedFileDialogForId(int32 id) { 243 return file_dialog_ids_.find(id) != file_dialog_ids_.end(); 244 } 245 246 private: 247 std::set<int32> file_dialog_ids_; 248 scoped_refptr<DownloadManager> download_manager_; 249 }; 250 251 // This observer tracks the progress of |DownloadItem|s. 252 class ItemObserver : public DownloadItem::Observer { 253 public: 254 explicit ItemObserver(DownloadItem* tracked) 255 : tracked_(tracked), states_hit_(0), 256 was_updated_(false), was_opened_(false) { 257 DCHECK(tracked_); 258 tracked_->AddObserver(this); 259 // Record the initial state. 260 OnDownloadUpdated(tracked_); 261 } 262 ~ItemObserver() { 263 tracked_->RemoveObserver(this); 264 } 265 266 bool hit_state(int state) const { 267 return (1 << state) & states_hit_; 268 } 269 bool was_updated() const { return was_updated_; } 270 bool was_opened() const { return was_opened_; } 271 272 private: 273 // DownloadItem::Observer methods 274 virtual void OnDownloadUpdated(DownloadItem* download) { 275 DCHECK_EQ(tracked_, download); 276 states_hit_ |= (1 << download->state()); 277 was_updated_ = true; 278 } 279 virtual void OnDownloadOpened(DownloadItem* download) { 280 DCHECK_EQ(tracked_, download); 281 states_hit_ |= (1 << download->state()); 282 was_opened_ = true; 283 } 284 285 DownloadItem* tracked_; 286 int states_hit_; 287 bool was_updated_; 288 bool was_opened_; 289 }; 290 291 } // namespace 292 293 #if !defined(OS_CHROMEOS) 294 295 TEST_F(DownloadManagerTest, StartDownload) { 296 BrowserThread io_thread(BrowserThread::IO, &message_loop_); 297 PrefService* prefs = profile_->GetPrefs(); 298 prefs->SetFilePath(prefs::kDownloadDefaultDirectory, FilePath()); 299 download_manager_->download_prefs()->EnableAutoOpenBasedOnExtension( 300 FilePath(FILE_PATH_LITERAL("example.pdf"))); 301 302 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kStartDownloadCases); ++i) { 303 prefs->SetBoolean(prefs::kPromptForDownload, 304 kStartDownloadCases[i].prompt_for_download); 305 306 SelectFileObserver observer(download_manager_); 307 DownloadCreateInfo* info = new DownloadCreateInfo; 308 info->download_id = static_cast<int>(i); 309 info->prompt_user_for_save_location = kStartDownloadCases[i].save_as; 310 info->url_chain.push_back(GURL(kStartDownloadCases[i].url)); 311 info->mime_type = kStartDownloadCases[i].mime_type; 312 download_manager_->CreateDownloadItem(info); 313 314 DownloadFile* download_file(new DownloadFile(info, download_manager_)); 315 AddDownloadToFileManager(info->download_id, download_file); 316 download_file->Initialize(false); 317 download_manager_->StartDownload(info); 318 message_loop_.RunAllPending(); 319 320 // NOTE: At this point, |AttachDownloadItem| will have been run if we don't 321 // need to prompt the user, so |info| could have been destructed. 322 // This means that we can't check any of its values. 323 // However, SelectFileObserver will have recorded any attempt to open the 324 // select file dialog. 325 EXPECT_EQ(kStartDownloadCases[i].expected_save_as, 326 observer.ShowedFileDialogForId(i)); 327 328 // If the Save As dialog pops up, it never reached 329 // DownloadManager::AttachDownloadItem(), and never deleted info or 330 // completed. This cleans up info. 331 // Note that DownloadManager::FileSelectionCanceled() is never called. 332 if (observer.ShowedFileDialogForId(i)) { 333 delete info; 334 } 335 } 336 } 337 338 #endif // !defined(OS_CHROMEOS) 339 340 TEST_F(DownloadManagerTest, DownloadRenameTest) { 341 using ::testing::_; 342 using ::testing::CreateFunctor; 343 using ::testing::Invoke; 344 using ::testing::Return; 345 346 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kDownloadRenameCases); ++i) { 347 // |info| will be destroyed in download_manager_. 348 DownloadCreateInfo* info(new DownloadCreateInfo); 349 info->download_id = static_cast<int>(i); 350 info->prompt_user_for_save_location = false; 351 info->url_chain.push_back(GURL()); 352 info->is_dangerous_file = kDownloadRenameCases[i].is_dangerous_file; 353 info->is_dangerous_url = kDownloadRenameCases[i].is_dangerous_url; 354 FilePath new_path(kDownloadRenameCases[i].suggested_path); 355 356 MockDownloadFile* download_file( 357 new MockDownloadFile(info, download_manager_)); 358 AddDownloadToFileManager(info->download_id, download_file); 359 360 // |download_file| is owned by DownloadFileManager. 361 ::testing::Mock::AllowLeak(download_file); 362 EXPECT_CALL(*download_file, Destructed()).Times(1); 363 364 if (kDownloadRenameCases[i].expected_rename_count == 1) { 365 EXPECT_CALL(*download_file, Rename(new_path)).WillOnce(Return(true)); 366 } else { 367 ASSERT_EQ(2, kDownloadRenameCases[i].expected_rename_count); 368 FilePath crdownload(download_util::GetCrDownloadPath(new_path)); 369 EXPECT_CALL(*download_file, Rename(_)) 370 .WillOnce(testing::WithArgs<0>(Invoke(CreateFunctor( 371 download_file, &MockDownloadFile::TestMultipleRename, 372 1, crdownload)))) 373 .WillOnce(testing::WithArgs<0>(Invoke(CreateFunctor( 374 download_file, &MockDownloadFile::TestMultipleRename, 375 2, new_path)))); 376 } 377 download_manager_->CreateDownloadItem(info); 378 379 if (kDownloadRenameCases[i].finish_before_rename) { 380 OnAllDataSaved(i, 1024, std::string("fake_hash")); 381 message_loop_.RunAllPending(); 382 FileSelected(new_path, i, info); 383 } else { 384 FileSelected(new_path, i, info); 385 message_loop_.RunAllPending(); 386 OnAllDataSaved(i, 1024, std::string("fake_hash")); 387 } 388 389 message_loop_.RunAllPending(); 390 EXPECT_TRUE(VerifySafetyState(kDownloadRenameCases[i].is_dangerous_file, 391 kDownloadRenameCases[i].is_dangerous_url, 392 i)); 393 } 394 } 395 396 TEST_F(DownloadManagerTest, DownloadInterruptTest) { 397 using ::testing::_; 398 using ::testing::CreateFunctor; 399 using ::testing::Invoke; 400 using ::testing::Return; 401 402 // |info| will be destroyed in download_manager_. 403 DownloadCreateInfo* info(new DownloadCreateInfo); 404 info->download_id = static_cast<int>(0); 405 info->prompt_user_for_save_location = false; 406 info->url_chain.push_back(GURL()); 407 info->is_dangerous_file = false; 408 info->is_dangerous_url = false; 409 const FilePath new_path(FILE_PATH_LITERAL("foo.zip")); 410 const FilePath cr_path(download_util::GetCrDownloadPath(new_path)); 411 412 MockDownloadFile* download_file( 413 new MockDownloadFile(info, download_manager_)); 414 AddDownloadToFileManager(info->download_id, download_file); 415 416 // |download_file| is owned by DownloadFileManager. 417 ::testing::Mock::AllowLeak(download_file); 418 EXPECT_CALL(*download_file, Destructed()).Times(1); 419 420 EXPECT_CALL(*download_file, Rename(cr_path)).WillOnce(Return(true)); 421 422 download_manager_->CreateDownloadItem(info); 423 424 DownloadItem* download = GetActiveDownloadItem(0); 425 ASSERT_TRUE(download != NULL); 426 427 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state()); 428 scoped_ptr<ItemObserver> observer(new ItemObserver(download)); 429 430 download_file->AppendDataToFile(kTestData, kTestDataLen); 431 432 info->path = new_path; 433 AttachDownloadItem(info); 434 message_loop_.RunAllPending(); 435 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); 436 437 OnDownloadError(0, 1024, -6); 438 message_loop_.RunAllPending(); 439 440 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL); 441 EXPECT_EQ(DownloadItem::INTERRUPTED, download->state()); 442 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); 443 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED)); 444 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE)); 445 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); 446 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); 447 EXPECT_TRUE(observer->was_updated()); 448 EXPECT_FALSE(observer->was_opened()); 449 450 download->Cancel(true); 451 452 EXPECT_EQ(DownloadItem::INTERRUPTED, download->state()); 453 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); 454 EXPECT_TRUE(observer->hit_state(DownloadItem::INTERRUPTED)); 455 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE)); 456 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); 457 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); 458 EXPECT_TRUE(observer->was_updated()); 459 EXPECT_FALSE(observer->was_opened()); 460 } 461 462 TEST_F(DownloadManagerTest, DownloadCancelTest) { 463 using ::testing::_; 464 using ::testing::CreateFunctor; 465 using ::testing::Invoke; 466 using ::testing::Return; 467 468 // |info| will be destroyed in download_manager_. 469 DownloadCreateInfo* info(new DownloadCreateInfo); 470 info->download_id = static_cast<int>(0); 471 info->prompt_user_for_save_location = false; 472 info->url_chain.push_back(GURL()); 473 info->is_dangerous_file = false; 474 info->is_dangerous_url = false; 475 const FilePath new_path(FILE_PATH_LITERAL("foo.zip")); 476 const FilePath cr_path(download_util::GetCrDownloadPath(new_path)); 477 478 MockDownloadFile* download_file( 479 new MockDownloadFile(info, download_manager_)); 480 AddDownloadToFileManager(info->download_id, download_file); 481 482 // |download_file| is owned by DownloadFileManager. 483 ::testing::Mock::AllowLeak(download_file); 484 EXPECT_CALL(*download_file, Destructed()).Times(1); 485 486 EXPECT_CALL(*download_file, Rename(cr_path)).WillOnce(Return(true)); 487 488 download_manager_->CreateDownloadItem(info); 489 490 DownloadItem* download = GetActiveDownloadItem(0); 491 ASSERT_TRUE(download != NULL); 492 493 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state()); 494 scoped_ptr<ItemObserver> observer(new ItemObserver(download)); 495 496 info->path = new_path; 497 AttachDownloadItem(info); 498 message_loop_.RunAllPending(); 499 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); 500 501 download_file->AppendDataToFile(kTestData, kTestDataLen); 502 503 download->Cancel(false); 504 message_loop_.RunAllPending(); 505 506 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); 507 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); 508 EXPECT_TRUE(observer->hit_state(DownloadItem::CANCELLED)); 509 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED)); 510 EXPECT_FALSE(observer->hit_state(DownloadItem::COMPLETE)); 511 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); 512 EXPECT_TRUE(observer->was_updated()); 513 EXPECT_FALSE(observer->was_opened()); 514 515 EXPECT_FALSE(file_util::PathExists(new_path)); 516 EXPECT_FALSE(file_util::PathExists(cr_path)); 517 } 518 519 TEST_F(DownloadManagerTest, DownloadOverwriteTest) { 520 using ::testing::_; 521 using ::testing::CreateFunctor; 522 using ::testing::Invoke; 523 using ::testing::Return; 524 525 // Create a temporary directory. 526 ScopedTempDir temp_dir_; 527 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 528 529 // File names we're using. 530 const FilePath new_path(temp_dir_.path().AppendASCII("foo.txt")); 531 const FilePath cr_path(download_util::GetCrDownloadPath(new_path)); 532 EXPECT_FALSE(file_util::PathExists(new_path)); 533 534 // Create the file that we will overwrite. Will be automatically cleaned 535 // up when temp_dir_ is destroyed. 536 FILE* fp = file_util::OpenFile(new_path, "w"); 537 file_util::CloseFile(fp); 538 EXPECT_TRUE(file_util::PathExists(new_path)); 539 540 // Construct the unique file name that normally would be created, but 541 // which we will override. 542 int uniquifier = download_util::GetUniquePathNumber(new_path); 543 FilePath unique_new_path = new_path; 544 EXPECT_NE(0, uniquifier); 545 download_util::AppendNumberToPath(&unique_new_path, uniquifier); 546 547 // |info| will be destroyed in download_manager_. 548 DownloadCreateInfo* info(new DownloadCreateInfo); 549 info->download_id = static_cast<int>(0); 550 info->prompt_user_for_save_location = true; 551 info->url_chain.push_back(GURL()); 552 info->is_dangerous_file = false; 553 info->is_dangerous_url = false; 554 555 download_manager_->CreateDownloadItem(info); 556 557 DownloadItem* download = GetActiveDownloadItem(0); 558 ASSERT_TRUE(download != NULL); 559 560 EXPECT_EQ(DownloadItem::IN_PROGRESS, download->state()); 561 scoped_ptr<ItemObserver> observer(new ItemObserver(download)); 562 563 // Create and initialize the download file. We're bypassing the first part 564 // of the download process and skipping to the part after the final file 565 // name has been chosen, so we need to initialize the download file 566 // properly. 567 DownloadFile* download_file( 568 new DownloadFile(info, download_manager_)); 569 download_file->Rename(cr_path); 570 // This creates the .crdownload version of the file. 571 download_file->Initialize(false); 572 // |download_file| is owned by DownloadFileManager. 573 AddDownloadToFileManager(info->download_id, download_file); 574 575 info->path = new_path; 576 AttachDownloadItem(info); 577 message_loop_.RunAllPending(); 578 EXPECT_TRUE(GetActiveDownloadItem(0) != NULL); 579 580 download_file->AppendDataToFile(kTestData, kTestDataLen); 581 582 // Finish the download. 583 OnAllDataSaved(0, kTestDataLen, ""); 584 message_loop_.RunAllPending(); 585 586 // Download is complete. 587 EXPECT_TRUE(GetActiveDownloadItem(0) == NULL); 588 EXPECT_TRUE(observer->hit_state(DownloadItem::IN_PROGRESS)); 589 EXPECT_FALSE(observer->hit_state(DownloadItem::CANCELLED)); 590 EXPECT_FALSE(observer->hit_state(DownloadItem::INTERRUPTED)); 591 EXPECT_TRUE(observer->hit_state(DownloadItem::COMPLETE)); 592 EXPECT_FALSE(observer->hit_state(DownloadItem::REMOVING)); 593 EXPECT_TRUE(observer->was_updated()); 594 EXPECT_FALSE(observer->was_opened()); 595 EXPECT_EQ(DownloadItem::COMPLETE, download->state()); 596 597 EXPECT_TRUE(file_util::PathExists(new_path)); 598 EXPECT_FALSE(file_util::PathExists(cr_path)); 599 EXPECT_FALSE(file_util::PathExists(unique_new_path)); 600 std::string file_contents; 601 EXPECT_TRUE(file_util::ReadFileToString(new_path, &file_contents)); 602 EXPECT_EQ(std::string(kTestData), file_contents); 603 } 604