Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / installer / util / delete_tree_work_item_unittest.cc
blob48f321f438a4bce8db5fe063929be221e1c80f5a
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.
5 #include <windows.h>
7 #include <fstream>
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/strings/string_util.h"
15 #include "chrome/installer/util/delete_tree_work_item.h"
16 #include "chrome/installer/util/work_item.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 namespace {
21 class DeleteTreeWorkItemTest : public testing::Test {
22 protected:
23 void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
25 // The temporary directory used to contain the test operations.
26 base::ScopedTempDir temp_dir_;
29 // Simple function to dump some text into a new file.
30 void CreateTextFile(const std::wstring& filename,
31 const std::wstring& contents) {
32 std::ofstream file;
33 file.open(filename.c_str());
34 ASSERT_TRUE(file.is_open());
35 file << contents;
36 file.close();
39 const wchar_t text_content_1[] = L"delete me";
41 } // namespace
43 // Delete a tree without key path. Everything should be deleted.
44 TEST_F(DeleteTreeWorkItemTest, DeleteTreeNoKeyPath) {
45 // Create tree to be deleted.
46 base::FilePath dir_name_delete(temp_dir_.path());
47 dir_name_delete = dir_name_delete.AppendASCII("to_be_delete");
48 base::CreateDirectory(dir_name_delete);
49 ASSERT_TRUE(base::PathExists(dir_name_delete));
51 base::FilePath dir_name_delete_1(dir_name_delete);
52 dir_name_delete_1 = dir_name_delete_1.AppendASCII("1");
53 base::CreateDirectory(dir_name_delete_1);
54 ASSERT_TRUE(base::PathExists(dir_name_delete_1));
56 base::FilePath dir_name_delete_2(dir_name_delete);
57 dir_name_delete_2 = dir_name_delete_2.AppendASCII("2");
58 base::CreateDirectory(dir_name_delete_2);
59 ASSERT_TRUE(base::PathExists(dir_name_delete_2));
61 base::FilePath file_name_delete_1(dir_name_delete_1);
62 file_name_delete_1 = file_name_delete_1.AppendASCII("File_1.txt");
63 CreateTextFile(file_name_delete_1.value(), text_content_1);
64 ASSERT_TRUE(base::PathExists(file_name_delete_1));
66 base::FilePath file_name_delete_2(dir_name_delete_2);
67 file_name_delete_2 = file_name_delete_2.AppendASCII("File_2.txt");
68 CreateTextFile(file_name_delete_2.value(), text_content_1);
69 ASSERT_TRUE(base::PathExists(file_name_delete_2));
71 // Test Do().
72 base::ScopedTempDir temp_dir;
73 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
75 std::vector<base::FilePath> key_files;
76 scoped_ptr<DeleteTreeWorkItem> work_item(
77 WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(),
78 key_files));
79 EXPECT_TRUE(work_item->Do());
81 // everything should be gone
82 EXPECT_FALSE(base::PathExists(file_name_delete_1));
83 EXPECT_FALSE(base::PathExists(file_name_delete_2));
84 EXPECT_FALSE(base::PathExists(dir_name_delete));
86 work_item->Rollback();
87 // everything should come back
88 EXPECT_TRUE(base::PathExists(file_name_delete_1));
89 EXPECT_TRUE(base::PathExists(file_name_delete_2));
90 EXPECT_TRUE(base::PathExists(dir_name_delete));
94 // Delete a tree with keypath but not in use. Everything should be gone.
95 // Rollback should bring back everything
96 TEST_F(DeleteTreeWorkItemTest, DeleteTree) {
97 // Create tree to be deleted
98 base::FilePath dir_name_delete(temp_dir_.path());
99 dir_name_delete = dir_name_delete.AppendASCII("to_be_delete");
100 base::CreateDirectory(dir_name_delete);
101 ASSERT_TRUE(base::PathExists(dir_name_delete));
103 base::FilePath dir_name_delete_1(dir_name_delete);
104 dir_name_delete_1 = dir_name_delete_1.AppendASCII("1");
105 base::CreateDirectory(dir_name_delete_1);
106 ASSERT_TRUE(base::PathExists(dir_name_delete_1));
108 base::FilePath dir_name_delete_2(dir_name_delete);
109 dir_name_delete_2 = dir_name_delete_2.AppendASCII("2");
110 base::CreateDirectory(dir_name_delete_2);
111 ASSERT_TRUE(base::PathExists(dir_name_delete_2));
113 base::FilePath file_name_delete_1(dir_name_delete_1);
114 file_name_delete_1 = file_name_delete_1.AppendASCII("File_1.txt");
115 CreateTextFile(file_name_delete_1.value(), text_content_1);
116 ASSERT_TRUE(base::PathExists(file_name_delete_1));
118 base::FilePath file_name_delete_2(dir_name_delete_2);
119 file_name_delete_2 = file_name_delete_2.AppendASCII("File_2.txt");
120 CreateTextFile(file_name_delete_2.value(), text_content_1);
121 ASSERT_TRUE(base::PathExists(file_name_delete_2));
123 // test Do()
124 base::ScopedTempDir temp_dir;
125 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
127 std::vector<base::FilePath> key_files(1, file_name_delete_1);
128 scoped_ptr<DeleteTreeWorkItem> work_item(
129 WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(),
130 key_files));
131 EXPECT_TRUE(work_item->Do());
133 // everything should be gone
134 EXPECT_FALSE(base::PathExists(file_name_delete_1));
135 EXPECT_FALSE(base::PathExists(file_name_delete_2));
136 EXPECT_FALSE(base::PathExists(dir_name_delete));
138 work_item->Rollback();
139 // everything should come back
140 EXPECT_TRUE(base::PathExists(file_name_delete_1));
141 EXPECT_TRUE(base::PathExists(file_name_delete_2));
142 EXPECT_TRUE(base::PathExists(dir_name_delete));
145 // Delete a tree with key_path in use. Everything should still be there.
146 TEST_F(DeleteTreeWorkItemTest, DeleteTreeInUse) {
147 // Create tree to be deleted
148 base::FilePath dir_name_delete(temp_dir_.path());
149 dir_name_delete = dir_name_delete.AppendASCII("to_be_delete");
150 base::CreateDirectory(dir_name_delete);
151 ASSERT_TRUE(base::PathExists(dir_name_delete));
153 base::FilePath dir_name_delete_1(dir_name_delete);
154 dir_name_delete_1 = dir_name_delete_1.AppendASCII("1");
155 base::CreateDirectory(dir_name_delete_1);
156 ASSERT_TRUE(base::PathExists(dir_name_delete_1));
158 base::FilePath dir_name_delete_2(dir_name_delete);
159 dir_name_delete_2 = dir_name_delete_2.AppendASCII("2");
160 base::CreateDirectory(dir_name_delete_2);
161 ASSERT_TRUE(base::PathExists(dir_name_delete_2));
163 base::FilePath file_name_delete_1(dir_name_delete_1);
164 file_name_delete_1 = file_name_delete_1.AppendASCII("File_1.txt");
165 CreateTextFile(file_name_delete_1.value(), text_content_1);
166 ASSERT_TRUE(base::PathExists(file_name_delete_1));
168 base::FilePath file_name_delete_2(dir_name_delete_2);
169 file_name_delete_2 = file_name_delete_2.AppendASCII("File_2.txt");
170 CreateTextFile(file_name_delete_2.value(), text_content_1);
171 ASSERT_TRUE(base::PathExists(file_name_delete_2));
173 // Create a key path file.
174 base::FilePath key_path(dir_name_delete);
175 key_path = key_path.AppendASCII("key_file.exe");
177 wchar_t exe_full_path_str[MAX_PATH];
178 ::GetModuleFileNameW(NULL, exe_full_path_str, MAX_PATH);
179 base::FilePath exe_full_path(exe_full_path_str);
181 base::CopyFile(exe_full_path, key_path);
182 ASSERT_TRUE(base::PathExists(key_path));
184 VLOG(1) << "copy ourself from " << exe_full_path.value()
185 << " to " << key_path.value();
187 // Run the key path file to keep it in use.
188 STARTUPINFOW si = {sizeof(si)};
189 PROCESS_INFORMATION pi = {0};
190 base::FilePath::StringType writable_key_path = key_path.value();
191 ASSERT_TRUE(
192 ::CreateProcessW(NULL, &writable_key_path[0],
193 NULL, NULL, FALSE, CREATE_NO_WINDOW | CREATE_SUSPENDED,
194 NULL, NULL, &si, &pi));
196 // test Do().
198 base::ScopedTempDir temp_dir;
199 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
201 std::vector<base::FilePath> key_paths(1, key_path);
202 scoped_ptr<DeleteTreeWorkItem> work_item(
203 WorkItem::CreateDeleteTreeWorkItem(dir_name_delete, temp_dir.path(),
204 key_paths));
206 // delete should fail as file in use.
207 EXPECT_FALSE(work_item->Do());
210 // verify everything is still there.
211 EXPECT_TRUE(base::PathExists(key_path));
212 EXPECT_TRUE(base::PathExists(file_name_delete_1));
213 EXPECT_TRUE(base::PathExists(file_name_delete_2));
215 TerminateProcess(pi.hProcess, 0);
216 // make sure the handle is closed.
217 WaitForSingleObject(pi.hProcess, INFINITE);