1 // Copyright (c) 2012 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.
7 #include "base/base_paths.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/strings/string_util.h"
12 #include "base/test/test_reg_util_win.h"
13 #include "base/win/registry.h"
14 #include "chrome/installer/util/conditional_work_item_list.h"
15 #include "chrome/installer/util/work_item.h"
16 #include "chrome/installer/util/work_item_list.h"
17 #include "testing/gtest/include/gtest/gtest.h"
19 using base::win::RegKey
;
23 const wchar_t kTestRoot
[] = L
"ListList";
24 const wchar_t kDataStr
[] = L
"data_111";
25 const wchar_t kName
[] = L
"name";
27 class WorkItemListTest
: public testing::Test
{
29 void SetUp() override
{
30 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
31 registry_override_manager_
.OverrideRegistry(HKEY_CURRENT_USER
);
34 void TearDown() override
{ logging::CloseLogFile(); }
36 base::ScopedTempDir temp_dir_
;
37 registry_util::RegistryOverrideManager registry_override_manager_
;
42 // Execute a WorkItem list successfully and then rollback.
43 TEST_F(WorkItemListTest
, ExecutionSuccess
) {
44 scoped_ptr
<WorkItemList
> work_item_list(WorkItem::CreateWorkItemList());
45 scoped_ptr
<WorkItem
> work_item
;
47 base::FilePath
top_dir_to_create(temp_dir_
.path());
48 top_dir_to_create
= top_dir_to_create
.AppendASCII("a");
49 base::FilePath
dir_to_create(top_dir_to_create
);
50 dir_to_create
= dir_to_create
.AppendASCII("b");
51 ASSERT_FALSE(base::PathExists(dir_to_create
));
53 work_item
.reset(reinterpret_cast<WorkItem
*>(
54 WorkItem::CreateCreateDirWorkItem(dir_to_create
)));
55 work_item_list
->AddWorkItem(work_item
.release());
57 std::wstring
key_to_create(kTestRoot
);
58 key_to_create
.push_back(base::FilePath::kSeparators
[0]);
59 key_to_create
.append(L
"ExecutionSuccess");
62 reinterpret_cast<WorkItem
*>(WorkItem::CreateCreateRegKeyWorkItem(
63 HKEY_CURRENT_USER
, key_to_create
, WorkItem::kWow64Default
)));
64 work_item_list
->AddWorkItem(work_item
.release());
66 std::wstring
name(kName
);
67 std::wstring
data(kDataStr
);
68 work_item
.reset(reinterpret_cast<WorkItem
*>(
69 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER
,
71 WorkItem::kWow64Default
,
75 work_item_list
->AddWorkItem(work_item
.release());
77 EXPECT_TRUE(work_item_list
->Do());
79 // Verify all WorkItems have been executed.
81 EXPECT_EQ(ERROR_SUCCESS
,
82 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
83 std::wstring read_out
;
84 EXPECT_EQ(ERROR_SUCCESS
, key
.ReadValue(name
.c_str(), &read_out
));
85 EXPECT_EQ(0, read_out
.compare(kDataStr
));
87 EXPECT_TRUE(base::PathExists(dir_to_create
));
89 work_item_list
->Rollback();
91 // Verify everything is rolled back.
92 // The value must have been deleted first in roll back otherwise the key
93 // can not be deleted.
94 EXPECT_NE(ERROR_SUCCESS
,
95 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
96 EXPECT_FALSE(base::PathExists(top_dir_to_create
));
99 // Execute a WorkItem list. Fail in the middle. Rollback what has been done.
100 TEST_F(WorkItemListTest
, ExecutionFailAndRollback
) {
101 scoped_ptr
<WorkItemList
> work_item_list(WorkItem::CreateWorkItemList());
102 scoped_ptr
<WorkItem
> work_item
;
104 base::FilePath
top_dir_to_create(temp_dir_
.path());
105 top_dir_to_create
= top_dir_to_create
.AppendASCII("a");
106 base::FilePath
dir_to_create(top_dir_to_create
);
107 dir_to_create
= dir_to_create
.AppendASCII("b");
108 ASSERT_FALSE(base::PathExists(dir_to_create
));
110 work_item
.reset(reinterpret_cast<WorkItem
*>(
111 WorkItem::CreateCreateDirWorkItem(dir_to_create
)));
112 work_item_list
->AddWorkItem(work_item
.release());
114 std::wstring
key_to_create(kTestRoot
);
115 key_to_create
.push_back(base::FilePath::kSeparators
[0]);
116 key_to_create
.append(L
"ExecutionFail");
119 reinterpret_cast<WorkItem
*>(WorkItem::CreateCreateRegKeyWorkItem(
120 HKEY_CURRENT_USER
, key_to_create
, WorkItem::kWow64Default
)));
121 work_item_list
->AddWorkItem(work_item
.release());
123 std::wstring
not_created_key(kTestRoot
);
124 not_created_key
.push_back(base::FilePath::kSeparators
[0]);
125 not_created_key
.append(L
"NotCreated");
126 std::wstring
name(kName
);
127 std::wstring
data(kDataStr
);
128 work_item
.reset(reinterpret_cast<WorkItem
*>(
129 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER
,
131 WorkItem::kWow64Default
,
135 work_item_list
->AddWorkItem(work_item
.release());
137 // This one will not be executed because we will fail early.
139 reinterpret_cast<WorkItem
*>(WorkItem::CreateCreateRegKeyWorkItem(
140 HKEY_CURRENT_USER
, not_created_key
, WorkItem::kWow64Default
)));
141 work_item_list
->AddWorkItem(work_item
.release());
143 EXPECT_FALSE(work_item_list
->Do());
145 // Verify the first 2 WorkItems have been executed.
147 EXPECT_EQ(ERROR_SUCCESS
,
148 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
150 EXPECT_TRUE(base::PathExists(dir_to_create
));
151 // The last one should not be there.
152 EXPECT_NE(ERROR_SUCCESS
,
153 key
.Open(HKEY_CURRENT_USER
, not_created_key
.c_str(), KEY_READ
));
155 work_item_list
->Rollback();
157 // Verify everything is rolled back.
158 EXPECT_NE(ERROR_SUCCESS
,
159 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
160 EXPECT_FALSE(base::PathExists(top_dir_to_create
));
163 TEST_F(WorkItemListTest
, ConditionalExecutionSuccess
) {
164 scoped_ptr
<WorkItemList
> work_item_list(WorkItem::CreateWorkItemList());
165 scoped_ptr
<WorkItem
> work_item
;
167 base::FilePath
top_dir_to_create(temp_dir_
.path());
168 top_dir_to_create
= top_dir_to_create
.AppendASCII("a");
169 base::FilePath
dir_to_create(top_dir_to_create
);
170 dir_to_create
= dir_to_create
.AppendASCII("b");
171 ASSERT_FALSE(base::PathExists(dir_to_create
));
173 work_item
.reset(reinterpret_cast<WorkItem
*>(
174 WorkItem::CreateCreateDirWorkItem(dir_to_create
)));
175 work_item_list
->AddWorkItem(work_item
.release());
177 scoped_ptr
<WorkItemList
> conditional_work_item_list(
178 WorkItem::CreateConditionalWorkItemList(
179 new ConditionRunIfFileExists(dir_to_create
)));
181 std::wstring
key_to_create(kTestRoot
);
182 key_to_create
.push_back(base::FilePath::kSeparators
[0]);
183 key_to_create
.append(L
"ExecutionSuccess");
185 reinterpret_cast<WorkItem
*>(WorkItem::CreateCreateRegKeyWorkItem(
186 HKEY_CURRENT_USER
, key_to_create
, WorkItem::kWow64Default
)));
187 conditional_work_item_list
->AddWorkItem(work_item
.release());
189 std::wstring
name(kName
);
190 std::wstring
data(kDataStr
);
191 work_item
.reset(reinterpret_cast<WorkItem
*>(
192 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER
,
194 WorkItem::kWow64Default
,
198 conditional_work_item_list
->AddWorkItem(work_item
.release());
200 work_item_list
->AddWorkItem(conditional_work_item_list
.release());
202 EXPECT_TRUE(work_item_list
->Do());
204 // Verify all WorkItems have been executed.
206 EXPECT_EQ(ERROR_SUCCESS
,
207 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
208 std::wstring read_out
;
209 EXPECT_EQ(ERROR_SUCCESS
, key
.ReadValue(name
.c_str(), &read_out
));
210 EXPECT_EQ(0, read_out
.compare(kDataStr
));
212 EXPECT_TRUE(base::PathExists(dir_to_create
));
214 work_item_list
->Rollback();
216 // Verify everything is rolled back.
217 // The value must have been deleted first in roll back otherwise the key
218 // can not be deleted.
219 EXPECT_NE(ERROR_SUCCESS
,
220 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
221 EXPECT_FALSE(base::PathExists(top_dir_to_create
));
224 TEST_F(WorkItemListTest
, ConditionalExecutionConditionFailure
) {
225 scoped_ptr
<WorkItemList
> work_item_list(WorkItem::CreateWorkItemList());
226 scoped_ptr
<WorkItem
> work_item
;
228 base::FilePath
top_dir_to_create(temp_dir_
.path());
229 top_dir_to_create
= top_dir_to_create
.AppendASCII("a");
230 base::FilePath
dir_to_create(top_dir_to_create
);
231 dir_to_create
= dir_to_create
.AppendASCII("b");
232 ASSERT_FALSE(base::PathExists(dir_to_create
));
234 work_item
.reset(reinterpret_cast<WorkItem
*>(
235 WorkItem::CreateCreateDirWorkItem(dir_to_create
)));
236 work_item_list
->AddWorkItem(work_item
.release());
238 scoped_ptr
<WorkItemList
> conditional_work_item_list(
239 WorkItem::CreateConditionalWorkItemList(
240 new ConditionRunIfFileExists(dir_to_create
.AppendASCII("c"))));
242 std::wstring
key_to_create(kTestRoot
);
243 key_to_create
.push_back(base::FilePath::kSeparators
[0]);
244 key_to_create
.append(L
"ExecutionSuccess");
246 reinterpret_cast<WorkItem
*>(WorkItem::CreateCreateRegKeyWorkItem(
247 HKEY_CURRENT_USER
, key_to_create
, WorkItem::kWow64Default
)));
248 conditional_work_item_list
->AddWorkItem(work_item
.release());
250 std::wstring
name(kName
);
251 std::wstring
data(kDataStr
);
252 work_item
.reset(reinterpret_cast<WorkItem
*>(
253 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER
,
255 WorkItem::kWow64Default
,
259 conditional_work_item_list
->AddWorkItem(work_item
.release());
261 work_item_list
->AddWorkItem(conditional_work_item_list
.release());
263 EXPECT_TRUE(work_item_list
->Do());
265 // Verify that the WorkItems added as part of the conditional list have NOT
268 EXPECT_NE(ERROR_SUCCESS
,
269 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
270 std::wstring read_out
;
271 EXPECT_NE(ERROR_SUCCESS
, key
.ReadValue(name
.c_str(), &read_out
));
274 // Verify that the other work item was executed.
275 EXPECT_TRUE(base::PathExists(dir_to_create
));
277 work_item_list
->Rollback();
279 // Verify everything is rolled back.
280 // The value must have been deleted first in roll back otherwise the key
281 // can not be deleted.
282 EXPECT_NE(ERROR_SUCCESS
,
283 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
284 EXPECT_FALSE(base::PathExists(top_dir_to_create
));