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/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 
     20 namespace {
     21 class 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.
     33 void 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.
     43 std::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 
     53 const wchar_t kTextContent1[] = L"Gooooooooooooooooooooogle";
     54 const wchar_t kTextContent2[] = L"Overwrite Me";
     55 };  // namespace
     56 
     57 // Move one directory from source to destination when destination does not
     58 // exist.
     59 TEST_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.
    108 TEST_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.
    167 TEST_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.
    208 TEST_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.
    256 TEST_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.
    319 TEST_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.
    390 TEST_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.
    463 TEST_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