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