delete_tree_work_item_unittest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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/scoped_temp_dir.h" 12#include "base/logging.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/path_service.h" 15#include "base/strings/string_util.h" 16#include "chrome/installer/util/delete_tree_work_item.h" 17#include "chrome/installer/util/work_item.h" 18#include "testing/gtest/include/gtest/gtest.h" 19 20namespace { 21 22class DeleteTreeWorkItemTest : public testing::Test { 23 protected: 24 virtual void SetUp() { 25 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 26 } 27 28 // The temporary directory used to contain the test operations. 29 base::ScopedTempDir temp_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::ofstream file; 36 file.open(filename.c_str()); 37 ASSERT_TRUE(file.is_open()); 38 file << contents; 39 file.close(); 40} 41 42const wchar_t text_content_1[] = L"delete me"; 43 44} // namespace 45 46// Delete a tree without key path. Everything should be deleted. 47TEST_F(DeleteTreeWorkItemTest, DeleteTreeNoKeyPath) { 48 // Create tree to be deleted. 49 base::FilePath dir_name_delete(temp_dir_.path()); 50 dir_name_delete = dir_name_delete.AppendASCII("to_be_delete"); 51 base::CreateDirectory(dir_name_delete); 52 ASSERT_TRUE(base::PathExists(dir_name_delete)); 53 54 base::FilePath dir_name_delete_1(dir_name_delete); 55 dir_name_delete_1 = dir_name_delete_1.AppendASCII("1"); 56 base::CreateDirectory(dir_name_delete_1); 57 ASSERT_TRUE(base::PathExists(dir_name_delete_1)); 58 59 base::FilePath dir_name_delete_2(dir_name_delete); 60 dir_name_delete_2 = dir_name_delete_2.AppendASCII("2"); 61 base::CreateDirectory(dir_name_delete_2); 62 ASSERT_TRUE(base::PathExists(dir_name_delete_2)); 63 64 base::FilePath file_name_delete_1(dir_name_delete_1); 65 file_name_delete_1 = file_name_delete_1.AppendASCII("File_1.txt"); 66 CreateTextFile(file_name_delete_1.value(), text_content_1); 67 ASSERT_TRUE(base::PathExists(file_name_delete_1)); 68 69 base::FilePath file_name_delete_2(dir_name_delete_2); 70 file_name_delete_2 = file_name_delete_2.AppendASCII("File_2.txt"); 71 CreateTextFile(file_name_delete_2.value(), text_content_1); 72 ASSERT_TRUE(base::PathExists(file_name_delete_2)); 73 74 // Test Do(). 75 base::ScopedTempDir temp_dir; 76 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 77 78 std::vector<base::FilePath> key_files; 79 scoped_ptr<DeleteTreeWorkItem> work_item( 80 WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(), 81 key_files)); 82 EXPECT_TRUE(work_item->Do()); 83 84 // everything should be gone 85 EXPECT_FALSE(base::PathExists(file_name_delete_1)); 86 EXPECT_FALSE(base::PathExists(file_name_delete_2)); 87 EXPECT_FALSE(base::PathExists(dir_name_delete)); 88 89 work_item->Rollback(); 90 // everything should come back 91 EXPECT_TRUE(base::PathExists(file_name_delete_1)); 92 EXPECT_TRUE(base::PathExists(file_name_delete_2)); 93 EXPECT_TRUE(base::PathExists(dir_name_delete)); 94} 95 96 97// Delete a tree with keypath but not in use. Everything should be gone. 98// Rollback should bring back everything 99TEST_F(DeleteTreeWorkItemTest, DeleteTree) { 100 // Create tree to be deleted 101 base::FilePath dir_name_delete(temp_dir_.path()); 102 dir_name_delete = dir_name_delete.AppendASCII("to_be_delete"); 103 base::CreateDirectory(dir_name_delete); 104 ASSERT_TRUE(base::PathExists(dir_name_delete)); 105 106 base::FilePath dir_name_delete_1(dir_name_delete); 107 dir_name_delete_1 = dir_name_delete_1.AppendASCII("1"); 108 base::CreateDirectory(dir_name_delete_1); 109 ASSERT_TRUE(base::PathExists(dir_name_delete_1)); 110 111 base::FilePath dir_name_delete_2(dir_name_delete); 112 dir_name_delete_2 = dir_name_delete_2.AppendASCII("2"); 113 base::CreateDirectory(dir_name_delete_2); 114 ASSERT_TRUE(base::PathExists(dir_name_delete_2)); 115 116 base::FilePath file_name_delete_1(dir_name_delete_1); 117 file_name_delete_1 = file_name_delete_1.AppendASCII("File_1.txt"); 118 CreateTextFile(file_name_delete_1.value(), text_content_1); 119 ASSERT_TRUE(base::PathExists(file_name_delete_1)); 120 121 base::FilePath file_name_delete_2(dir_name_delete_2); 122 file_name_delete_2 = file_name_delete_2.AppendASCII("File_2.txt"); 123 CreateTextFile(file_name_delete_2.value(), text_content_1); 124 ASSERT_TRUE(base::PathExists(file_name_delete_2)); 125 126 // test Do() 127 base::ScopedTempDir temp_dir; 128 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 129 130 std::vector<base::FilePath> key_files(1, file_name_delete_1); 131 scoped_ptr<DeleteTreeWorkItem> work_item( 132 WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(), 133 key_files)); 134 EXPECT_TRUE(work_item->Do()); 135 136 // everything should be gone 137 EXPECT_FALSE(base::PathExists(file_name_delete_1)); 138 EXPECT_FALSE(base::PathExists(file_name_delete_2)); 139 EXPECT_FALSE(base::PathExists(dir_name_delete)); 140 141 work_item->Rollback(); 142 // everything should come back 143 EXPECT_TRUE(base::PathExists(file_name_delete_1)); 144 EXPECT_TRUE(base::PathExists(file_name_delete_2)); 145 EXPECT_TRUE(base::PathExists(dir_name_delete)); 146} 147 148// Delete a tree with key_path in use. Everything should still be there. 149TEST_F(DeleteTreeWorkItemTest, DeleteTreeInUse) { 150 // Create tree to be deleted 151 base::FilePath dir_name_delete(temp_dir_.path()); 152 dir_name_delete = dir_name_delete.AppendASCII("to_be_delete"); 153 base::CreateDirectory(dir_name_delete); 154 ASSERT_TRUE(base::PathExists(dir_name_delete)); 155 156 base::FilePath dir_name_delete_1(dir_name_delete); 157 dir_name_delete_1 = dir_name_delete_1.AppendASCII("1"); 158 base::CreateDirectory(dir_name_delete_1); 159 ASSERT_TRUE(base::PathExists(dir_name_delete_1)); 160 161 base::FilePath dir_name_delete_2(dir_name_delete); 162 dir_name_delete_2 = dir_name_delete_2.AppendASCII("2"); 163 base::CreateDirectory(dir_name_delete_2); 164 ASSERT_TRUE(base::PathExists(dir_name_delete_2)); 165 166 base::FilePath file_name_delete_1(dir_name_delete_1); 167 file_name_delete_1 = file_name_delete_1.AppendASCII("File_1.txt"); 168 CreateTextFile(file_name_delete_1.value(), text_content_1); 169 ASSERT_TRUE(base::PathExists(file_name_delete_1)); 170 171 base::FilePath file_name_delete_2(dir_name_delete_2); 172 file_name_delete_2 = file_name_delete_2.AppendASCII("File_2.txt"); 173 CreateTextFile(file_name_delete_2.value(), text_content_1); 174 ASSERT_TRUE(base::PathExists(file_name_delete_2)); 175 176 // Create a key path file. 177 base::FilePath key_path(dir_name_delete); 178 key_path = key_path.AppendASCII("key_file.exe"); 179 180 wchar_t exe_full_path_str[MAX_PATH]; 181 ::GetModuleFileNameW(NULL, exe_full_path_str, MAX_PATH); 182 base::FilePath exe_full_path(exe_full_path_str); 183 184 base::CopyFile(exe_full_path, key_path); 185 ASSERT_TRUE(base::PathExists(key_path)); 186 187 VLOG(1) << "copy ourself from " << exe_full_path.value() 188 << " to " << key_path.value(); 189 190 // Run the key path file to keep it in use. 191 STARTUPINFOW si = {sizeof(si)}; 192 PROCESS_INFORMATION pi = {0}; 193 base::FilePath::StringType writable_key_path = key_path.value(); 194 ASSERT_TRUE( 195 ::CreateProcessW(NULL, &writable_key_path[0], 196 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED, 197 NULL, NULL, &si, &pi)); 198 199 // test Do(). 200 { 201 base::ScopedTempDir temp_dir; 202 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 203 204 std::vector<base::FilePath> key_paths(1, key_path); 205 scoped_ptr<DeleteTreeWorkItem> work_item( 206 WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(), 207 key_paths)); 208 209 // delete should fail as file in use. 210 EXPECT_FALSE(work_item->Do()); 211 } 212 213 // verify everything is still there. 214 EXPECT_TRUE(base::PathExists(key_path)); 215 EXPECT_TRUE(base::PathExists(file_name_delete_1)); 216 EXPECT_TRUE(base::PathExists(file_name_delete_2)); 217 218 TerminateProcess(pi.hProcess, 0); 219 // make sure the handle is closed. 220 WaitForSingleObject(pi.hProcess, INFINITE); 221} 222