move_tree_work_item_unittest.cc revision a3f7b4e666c476898878fa745f637129375cd889
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 <windows.h> 6 7#include <fstream> 8 9#include "base/base_paths.h" 10#include "base/file_util.h" 11#include "base/files/memory_mapped_file.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/path_service.h" 14#include "base/strings/string_util.h" 15#include "chrome/installer/util/installer_util_test_common.h" 16#include "chrome/installer/util/move_tree_work_item.h" 17#include "chrome/installer/util/work_item.h" 18#include "testing/gtest/include/gtest/gtest.h" 19 20namespace { 21class MoveTreeWorkItemTest : public testing::Test { 22 protected: 23 virtual void SetUp() { 24 ASSERT_TRUE(temp_from_dir_.CreateUniqueTempDir()); 25 ASSERT_TRUE(temp_to_dir_.CreateUniqueTempDir()); 26 } 27 28 base::ScopedTempDir temp_from_dir_; 29 base::ScopedTempDir temp_to_dir_; 30}; 31 32// Simple function to dump some text into a new file. 33void CreateTextFile(const std::wstring& filename, 34 const std::wstring& contents) { 35 std::wofstream file; 36 file.open(WideToASCII(filename).c_str()); 37 ASSERT_TRUE(file.is_open()); 38 file << contents; 39 file.close(); 40} 41 42// Simple function to read text from a file. 43std::wstring ReadTextFile(const base::FilePath& path) { 44 WCHAR contents[64]; 45 std::wifstream file; 46 file.open(WideToASCII(path.value()).c_str()); 47 EXPECT_TRUE(file.is_open()); 48 file.getline(contents, arraysize(contents)); 49 file.close(); 50 return std::wstring(contents); 51} 52 53const wchar_t kTextContent1[] = L"Gooooooooooooooooooooogle"; 54const wchar_t kTextContent2[] = L"Overwrite Me"; 55}; // namespace 56 57// Move one directory from source to destination when destination does not 58// exist. 59TEST_F(MoveTreeWorkItemTest, MoveDirectory) { 60 // Create two level deep source dir 61 base::FilePath from_dir1(temp_from_dir_.path()); 62 from_dir1 = from_dir1.AppendASCII("From_Dir1"); 63 file_util::CreateDirectory(from_dir1); 64 ASSERT_TRUE(base::PathExists(from_dir1)); 65 66 base::FilePath from_dir2(from_dir1); 67 from_dir2 = from_dir2.AppendASCII("From_Dir2"); 68 file_util::CreateDirectory(from_dir2); 69 ASSERT_TRUE(base::PathExists(from_dir2)); 70 71 base::FilePath from_file(from_dir2); 72 from_file = from_file.AppendASCII("From_File"); 73 CreateTextFile(from_file.value(), kTextContent1); 74 ASSERT_TRUE(base::PathExists(from_file)); 75 76 // Generate destination path 77 base::FilePath to_dir(temp_from_dir_.path()); 78 to_dir = to_dir.AppendASCII("To_Dir"); 79 ASSERT_FALSE(base::PathExists(to_dir)); 80 81 base::FilePath to_file(to_dir); 82 to_file = to_file.AppendASCII("From_Dir2"); 83 to_file = to_file.AppendASCII("From_File"); 84 ASSERT_FALSE(base::PathExists(to_file)); 85 86 // test Do() 87 scoped_ptr<MoveTreeWorkItem> work_item( 88 WorkItem::CreateMoveTreeWorkItem(from_dir1, 89 to_dir, 90 temp_to_dir_.path(), 91 WorkItem::ALWAYS_MOVE)); 92 EXPECT_TRUE(work_item->Do()); 93 94 EXPECT_FALSE(base::PathExists(from_dir1)); 95 EXPECT_TRUE(base::PathExists(to_dir)); 96 EXPECT_TRUE(base::PathExists(to_file)); 97 98 // test rollback() 99 work_item->Rollback(); 100 101 EXPECT_TRUE(base::PathExists(from_dir1)); 102 EXPECT_TRUE(base::PathExists(from_file)); 103 EXPECT_FALSE(base::PathExists(to_dir)); 104} 105 106// Move one directory from source to destination when destination already 107// exists. 108TEST_F(MoveTreeWorkItemTest, MoveDirectoryDestExists) { 109 // Create two level deep source dir 110 base::FilePath from_dir1(temp_from_dir_.path()); 111 from_dir1 = from_dir1.AppendASCII("From_Dir1"); 112 file_util::CreateDirectory(from_dir1); 113 ASSERT_TRUE(base::PathExists(from_dir1)); 114 115 base::FilePath from_dir2(from_dir1); 116 from_dir2 = from_dir2.AppendASCII("From_Dir2"); 117 file_util::CreateDirectory(from_dir2); 118 ASSERT_TRUE(base::PathExists(from_dir2)); 119 120 base::FilePath from_file(from_dir2); 121 from_file = from_file.AppendASCII("From_File"); 122 CreateTextFile(from_file.value(), kTextContent1); 123 ASSERT_TRUE(base::PathExists(from_file)); 124 125 // Create destination path 126 base::FilePath to_dir(temp_from_dir_.path()); 127 to_dir = to_dir.AppendASCII("To_Dir"); 128 file_util::CreateDirectory(to_dir); 129 ASSERT_TRUE(base::PathExists(to_dir)); 130 131 base::FilePath orig_to_file(to_dir); 132 orig_to_file = orig_to_file.AppendASCII("To_File"); 133 CreateTextFile(orig_to_file.value(), kTextContent2); 134 ASSERT_TRUE(base::PathExists(orig_to_file)); 135 136 base::FilePath new_to_file(to_dir); 137 new_to_file = new_to_file.AppendASCII("From_Dir2"); 138 new_to_file = new_to_file.AppendASCII("From_File"); 139 ASSERT_FALSE(base::PathExists(new_to_file)); 140 141 // test Do(), don't check for duplicates. 142 scoped_ptr<MoveTreeWorkItem> work_item( 143 WorkItem::CreateMoveTreeWorkItem(from_dir1, 144 to_dir, 145 temp_to_dir_.path(), 146 WorkItem::ALWAYS_MOVE)); 147 EXPECT_TRUE(work_item->Do()); 148 149 EXPECT_FALSE(base::PathExists(from_dir1)); 150 EXPECT_TRUE(base::PathExists(to_dir)); 151 EXPECT_TRUE(base::PathExists(new_to_file)); 152 EXPECT_FALSE(base::PathExists(orig_to_file)); 153 154 // test rollback() 155 work_item->Rollback(); 156 157 EXPECT_TRUE(base::PathExists(from_dir1)); 158 EXPECT_TRUE(base::PathExists(to_dir)); 159 EXPECT_FALSE(base::PathExists(new_to_file)); 160 EXPECT_TRUE(base::PathExists(orig_to_file)); 161 EXPECT_EQ(0, ReadTextFile(orig_to_file).compare(kTextContent2)); 162 EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1)); 163} 164 165// Move one file from source to destination when destination does not 166// exist. 167TEST_F(MoveTreeWorkItemTest, MoveAFile) { 168 // Create a file inside source dir 169 base::FilePath from_dir(temp_from_dir_.path()); 170 from_dir = from_dir.AppendASCII("From_Dir"); 171 file_util::CreateDirectory(from_dir); 172 ASSERT_TRUE(base::PathExists(from_dir)); 173 174 base::FilePath from_file(from_dir); 175 from_file = from_file.AppendASCII("From_File"); 176 CreateTextFile(from_file.value(), kTextContent1); 177 ASSERT_TRUE(base::PathExists(from_file)); 178 179 // Generate destination file name 180 base::FilePath to_file(temp_from_dir_.path()); 181 to_file = to_file.AppendASCII("To_File"); 182 ASSERT_FALSE(base::PathExists(to_file)); 183 184 // test Do() 185 scoped_ptr<MoveTreeWorkItem> work_item( 186 WorkItem::CreateMoveTreeWorkItem(from_file, 187 to_file, 188 temp_to_dir_.path(), 189 WorkItem::ALWAYS_MOVE)); 190 EXPECT_TRUE(work_item->Do()); 191 192 EXPECT_TRUE(base::PathExists(from_dir)); 193 EXPECT_FALSE(base::PathExists(from_file)); 194 EXPECT_TRUE(base::PathExists(to_file)); 195 EXPECT_EQ(0, ReadTextFile(to_file).compare(kTextContent1)); 196 197 // test rollback() 198 work_item->Rollback(); 199 200 EXPECT_TRUE(base::PathExists(from_dir)); 201 EXPECT_TRUE(base::PathExists(from_file)); 202 EXPECT_FALSE(base::PathExists(to_file)); 203 EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1)); 204} 205 206// Move one file from source to destination when destination already 207// exists. 208TEST_F(MoveTreeWorkItemTest, MoveFileDestExists) { 209 // Create a file inside source dir 210 base::FilePath from_dir(temp_from_dir_.path()); 211 from_dir = from_dir.AppendASCII("From_Dir"); 212 file_util::CreateDirectory(from_dir); 213 ASSERT_TRUE(base::PathExists(from_dir)); 214 215 base::FilePath from_file(from_dir); 216 from_file = from_file.AppendASCII("From_File"); 217 CreateTextFile(from_file.value(), kTextContent1); 218 ASSERT_TRUE(base::PathExists(from_file)); 219 220 // Create destination path 221 base::FilePath to_dir(temp_from_dir_.path()); 222 to_dir = to_dir.AppendASCII("To_Dir"); 223 file_util::CreateDirectory(to_dir); 224 ASSERT_TRUE(base::PathExists(to_dir)); 225 226 base::FilePath to_file(to_dir); 227 to_file = to_file.AppendASCII("To_File"); 228 CreateTextFile(to_file.value(), kTextContent2); 229 ASSERT_TRUE(base::PathExists(to_file)); 230 231 // test Do() 232 scoped_ptr<MoveTreeWorkItem> work_item( 233 WorkItem::CreateMoveTreeWorkItem(from_file, 234 to_dir, 235 temp_to_dir_.path(), 236 WorkItem::ALWAYS_MOVE)); 237 EXPECT_TRUE(work_item->Do()); 238 239 EXPECT_TRUE(base::PathExists(from_dir)); 240 EXPECT_FALSE(base::PathExists(from_file)); 241 EXPECT_TRUE(base::PathExists(to_dir)); 242 EXPECT_FALSE(base::PathExists(to_file)); 243 EXPECT_EQ(0, ReadTextFile(to_dir).compare(kTextContent1)); 244 245 // test rollback() 246 work_item->Rollback(); 247 248 EXPECT_TRUE(base::PathExists(from_dir)); 249 EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1)); 250 EXPECT_TRUE(base::PathExists(to_dir)); 251 EXPECT_EQ(0, ReadTextFile(to_file).compare(kTextContent2)); 252} 253 254// Move one file from source to destination when destination already 255// exists and is in use. 256TEST_F(MoveTreeWorkItemTest, MoveFileDestInUse) { 257 // Create a file inside source dir 258 base::FilePath from_dir(temp_from_dir_.path()); 259 from_dir = from_dir.AppendASCII("From_Dir"); 260 file_util::CreateDirectory(from_dir); 261 ASSERT_TRUE(base::PathExists(from_dir)); 262 263 base::FilePath from_file(from_dir); 264 from_file = from_file.AppendASCII("From_File"); 265 CreateTextFile(from_file.value(), kTextContent1); 266 ASSERT_TRUE(base::PathExists(from_file)); 267 268 // Create an executable in destination path by copying ourself to it. 269 base::FilePath to_dir(temp_from_dir_.path()); 270 to_dir = to_dir.AppendASCII("To_Dir"); 271 file_util::CreateDirectory(to_dir); 272 ASSERT_TRUE(base::PathExists(to_dir)); 273 274 wchar_t exe_full_path_str[MAX_PATH]; 275 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH); 276 base::FilePath exe_full_path(exe_full_path_str); 277 base::FilePath to_file(to_dir); 278 to_file = to_file.AppendASCII("To_File"); 279 base::CopyFile(exe_full_path, to_file); 280 ASSERT_TRUE(base::PathExists(to_file)); 281 282 // Run the executable in destination path 283 STARTUPINFOW si = {sizeof(si)}; 284 PROCESS_INFORMATION pi = {0}; 285 ASSERT_TRUE(::CreateProcess(NULL, 286 const_cast<wchar_t*>(to_file.value().c_str()), 287 NULL, NULL, FALSE, 288 CREATE_NO_WINDOW | CREATE_SUSPENDED, 289 NULL, NULL, &si, &pi)); 290 291 // test Do() 292 scoped_ptr<MoveTreeWorkItem> work_item( 293 WorkItem::CreateMoveTreeWorkItem(from_file, 294 to_file, 295 temp_to_dir_.path(), 296 WorkItem::ALWAYS_MOVE)); 297 EXPECT_TRUE(work_item->Do()); 298 299 EXPECT_TRUE(base::PathExists(from_dir)); 300 EXPECT_FALSE(base::PathExists(from_file)); 301 EXPECT_TRUE(base::PathExists(to_dir)); 302 EXPECT_EQ(0, ReadTextFile(to_file).compare(kTextContent1)); 303 304 // test rollback() 305 work_item->Rollback(); 306 307 EXPECT_TRUE(base::PathExists(from_dir)); 308 EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1)); 309 EXPECT_TRUE(base::PathExists(to_dir)); 310 EXPECT_TRUE(base::ContentsEqual(exe_full_path, to_file)); 311 312 TerminateProcess(pi.hProcess, 0); 313 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0); 314 CloseHandle(pi.hProcess); 315 CloseHandle(pi.hThread); 316} 317 318// Move one file that is in use to destination. 319TEST_F(MoveTreeWorkItemTest, MoveFileInUse) { 320 // Create an executable for source by copying ourself to a new source dir. 321 base::FilePath from_dir(temp_from_dir_.path()); 322 from_dir = from_dir.AppendASCII("From_Dir"); 323 file_util::CreateDirectory(from_dir); 324 ASSERT_TRUE(base::PathExists(from_dir)); 325 326 wchar_t exe_full_path_str[MAX_PATH]; 327 ::GetModuleFileName(NULL, exe_full_path_str, MAX_PATH); 328 base::FilePath exe_full_path(exe_full_path_str); 329 base::FilePath from_file(from_dir); 330 from_file = from_file.AppendASCII("From_File"); 331 base::CopyFile(exe_full_path, from_file); 332 ASSERT_TRUE(base::PathExists(from_file)); 333 334 // Create a destination source dir and generate destination file name. 335 base::FilePath to_dir(temp_from_dir_.path()); 336 to_dir = to_dir.AppendASCII("To_Dir"); 337 file_util::CreateDirectory(to_dir); 338 ASSERT_TRUE(base::PathExists(to_dir)); 339 340 base::FilePath to_file(to_dir); 341 to_file = to_file.AppendASCII("To_File"); 342 CreateTextFile(to_file.value(), kTextContent1); 343 ASSERT_TRUE(base::PathExists(to_file)); 344 345 // Run the executable in source path 346 STARTUPINFOW si = {sizeof(si)}; 347 PROCESS_INFORMATION pi = {0}; 348 ASSERT_TRUE(::CreateProcess(NULL, 349 const_cast<wchar_t*>(from_file.value().c_str()), 350 NULL, NULL, FALSE, 351 CREATE_NO_WINDOW | CREATE_SUSPENDED, 352 NULL, NULL, &si, &pi)); 353 354 // test Do() 355 scoped_ptr<MoveTreeWorkItem> work_item( 356 WorkItem::CreateMoveTreeWorkItem(from_file, 357 to_file, 358 temp_to_dir_.path(), 359 WorkItem::ALWAYS_MOVE)); 360 EXPECT_TRUE(work_item->Do()); 361 362 EXPECT_TRUE(base::PathExists(from_dir)); 363 EXPECT_FALSE(base::PathExists(from_file)); 364 EXPECT_TRUE(base::PathExists(to_dir)); 365 EXPECT_TRUE(base::ContentsEqual(exe_full_path, to_file)); 366 367 // Close the process and make sure all the conditions after Do() are 368 // still true. 369 TerminateProcess(pi.hProcess, 0); 370 EXPECT_TRUE(WaitForSingleObject(pi.hProcess, 10000) == WAIT_OBJECT_0); 371 CloseHandle(pi.hProcess); 372 CloseHandle(pi.hThread); 373 374 EXPECT_TRUE(base::PathExists(from_dir)); 375 EXPECT_FALSE(base::PathExists(from_file)); 376 EXPECT_TRUE(base::PathExists(to_dir)); 377 EXPECT_TRUE(base::ContentsEqual(exe_full_path, to_file)); 378 379 // test rollback() 380 work_item->Rollback(); 381 382 EXPECT_TRUE(base::PathExists(from_dir)); 383 EXPECT_TRUE(base::ContentsEqual(exe_full_path, from_file)); 384 EXPECT_TRUE(base::PathExists(to_dir)); 385 EXPECT_EQ(0, ReadTextFile(to_file).compare(kTextContent1)); 386} 387 388// Move one directory from source to destination when destination already 389// exists. 390TEST_F(MoveTreeWorkItemTest, MoveDirectoryDestExistsCheckForDuplicatesFull) { 391 // Create two level deep source dir 392 base::FilePath from_dir1(temp_from_dir_.path()); 393 from_dir1 = from_dir1.AppendASCII("From_Dir1"); 394 file_util::CreateDirectory(from_dir1); 395 ASSERT_TRUE(base::PathExists(from_dir1)); 396 397 base::FilePath from_dir2(from_dir1); 398 from_dir2 = from_dir2.AppendASCII("From_Dir2"); 399 file_util::CreateDirectory(from_dir2); 400 ASSERT_TRUE(base::PathExists(from_dir2)); 401 402 base::FilePath from_file(from_dir2); 403 from_file = from_file.AppendASCII("From_File"); 404 CreateTextFile(from_file.value(), kTextContent1); 405 ASSERT_TRUE(base::PathExists(from_file)); 406 407 // // Create a file hierarchy identical to the one in the source directory. 408 base::FilePath to_dir(temp_from_dir_.path()); 409 to_dir = to_dir.AppendASCII("To_Dir"); 410 ASSERT_TRUE(installer::test::CopyFileHierarchy(from_dir1, to_dir)); 411 412 // Lock one of the files in the to destination directory to prevent moves. 413 base::FilePath orig_to_file( 414 to_dir.AppendASCII("From_Dir2").AppendASCII("From_File")); 415 base::MemoryMappedFile mapped_file; 416 EXPECT_TRUE(mapped_file.Initialize(orig_to_file)); 417 418 // First check that we can't do the regular Move(). 419 scoped_ptr<MoveTreeWorkItem> work_item( 420 WorkItem::CreateMoveTreeWorkItem(from_dir1, 421 to_dir, 422 temp_to_dir_.path(), 423 WorkItem::ALWAYS_MOVE)); 424 EXPECT_FALSE(work_item->Do()); 425 work_item->Rollback(); 426 427 // Now test Do() with the check for duplicates. This should pass. 428 work_item.reset( 429 WorkItem::CreateMoveTreeWorkItem(from_dir1, 430 to_dir, 431 temp_to_dir_.path(), 432 WorkItem::CHECK_DUPLICATES)); 433 EXPECT_TRUE(work_item->Do()); 434 435 // Make sure that we "moved" the files, i.e. that the source directory isn't 436 // there anymore, 437 EXPECT_FALSE(base::PathExists(from_dir1)); 438 // Make sure that the original directory structure and file are still present. 439 EXPECT_TRUE(base::PathExists(to_dir)); 440 EXPECT_TRUE(base::PathExists(orig_to_file)); 441 // Make sure that the backup path is not empty. 442 EXPECT_FALSE(file_util::IsDirectoryEmpty(temp_to_dir_.path())); 443 444 // Check that the work item believes the source to have been moved. 445 EXPECT_TRUE(work_item->source_moved_to_backup_); 446 EXPECT_FALSE(work_item->moved_to_dest_path_); 447 EXPECT_FALSE(work_item->moved_to_backup_); 448 449 // test rollback() 450 work_item->Rollback(); 451 452 // Once we rollback all the original files should still be there, as should 453 // the source files. 454 EXPECT_TRUE(base::PathExists(from_dir1)); 455 EXPECT_TRUE(base::PathExists(to_dir)); 456 EXPECT_TRUE(base::PathExists(orig_to_file)); 457 EXPECT_EQ(0, ReadTextFile(orig_to_file).compare(kTextContent1)); 458 EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1)); 459} 460 461// Move one directory from source to destination when destination already 462// exists but contains only a subset of the files in source. 463TEST_F(MoveTreeWorkItemTest, MoveDirectoryDestExistsCheckForDuplicatesPartial) { 464 // Create two level deep source dir 465 base::FilePath from_dir1(temp_from_dir_.path()); 466 from_dir1 = from_dir1.AppendASCII("From_Dir1"); 467 file_util::CreateDirectory(from_dir1); 468 ASSERT_TRUE(base::PathExists(from_dir1)); 469 470 base::FilePath from_dir2(from_dir1); 471 from_dir2 = from_dir2.AppendASCII("From_Dir2"); 472 file_util::CreateDirectory(from_dir2); 473 ASSERT_TRUE(base::PathExists(from_dir2)); 474 475 base::FilePath from_file(from_dir2); 476 from_file = from_file.AppendASCII("From_File"); 477 CreateTextFile(from_file.value(), kTextContent1); 478 ASSERT_TRUE(base::PathExists(from_file)); 479 480 base::FilePath from_file2(from_dir2); 481 from_file2 = from_file2.AppendASCII("From_File2"); 482 CreateTextFile(from_file2.value(), kTextContent2); 483 ASSERT_TRUE(base::PathExists(from_file2)); 484 485 // Create destination path 486 base::FilePath to_dir(temp_from_dir_.path()); 487 to_dir = to_dir.AppendASCII("To_Dir"); 488 file_util::CreateDirectory(to_dir); 489 ASSERT_TRUE(base::PathExists(to_dir)); 490 491 // Create a sub-directory of the same name as in the source directory. 492 base::FilePath to_dir2(to_dir); 493 to_dir2 = to_dir2.AppendASCII("From_Dir2"); 494 file_util::CreateDirectory(to_dir2); 495 ASSERT_TRUE(base::PathExists(to_dir2)); 496 497 // Create one of the files in the to sub-directory, but not the other. 498 base::FilePath orig_to_file(to_dir2); 499 orig_to_file = orig_to_file.AppendASCII("From_File"); 500 CreateTextFile(orig_to_file.value(), kTextContent1); 501 ASSERT_TRUE(base::PathExists(orig_to_file)); 502 503 // test Do(), check for duplicates. 504 scoped_ptr<MoveTreeWorkItem> work_item( 505 WorkItem::CreateMoveTreeWorkItem(from_dir1, 506 to_dir, 507 temp_to_dir_.path(), 508 WorkItem::CHECK_DUPLICATES)); 509 EXPECT_TRUE(work_item->Do()); 510 511 // Make sure that we "moved" the files, i.e. that the source directory isn't 512 // there anymore, 513 EXPECT_FALSE(base::PathExists(from_dir1)); 514 // Make sure that the original directory structure and file are still present. 515 EXPECT_TRUE(base::PathExists(to_dir)); 516 EXPECT_TRUE(base::PathExists(orig_to_file)); 517 // Make sure that the backup path is not empty. 518 EXPECT_FALSE(file_util::IsDirectoryEmpty(temp_to_dir_.path())); 519 // Make sure that the "new" file is also present. 520 base::FilePath new_to_file2(to_dir2); 521 new_to_file2 = new_to_file2.AppendASCII("From_File2"); 522 EXPECT_TRUE(base::PathExists(new_to_file2)); 523 524 // Check that the work item believes that this was a regular move. 525 EXPECT_FALSE(work_item->source_moved_to_backup_); 526 EXPECT_TRUE(work_item->moved_to_dest_path_); 527 EXPECT_TRUE(work_item->moved_to_backup_); 528 529 // test rollback() 530 work_item->Rollback(); 531 532 // Once we rollback all the original files should still be there, as should 533 // the source files. 534 EXPECT_TRUE(base::PathExists(from_dir1)); 535 EXPECT_TRUE(base::PathExists(to_dir)); 536 EXPECT_TRUE(base::PathExists(orig_to_file)); 537 EXPECT_EQ(0, ReadTextFile(orig_to_file).compare(kTextContent1)); 538 EXPECT_EQ(0, ReadTextFile(from_file).compare(kTextContent1)); 539 540 // Also, after rollback the new "to" file should be gone. 541 EXPECT_FALSE(base::PathExists(new_to_file2)); 542} 543