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/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "base/path_service.h"
12 #include "base/strings/string_util.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 virtual void SetUp() {
30 // Create a temporary key for testing
31 RegKey
key(HKEY_CURRENT_USER
, L
"", KEY_ALL_ACCESS
);
32 key
.DeleteKey(kTestRoot
);
33 ASSERT_NE(ERROR_SUCCESS
, key
.Open(HKEY_CURRENT_USER
, kTestRoot
, KEY_READ
));
34 ASSERT_EQ(ERROR_SUCCESS
,
35 key
.Create(HKEY_CURRENT_USER
, kTestRoot
, KEY_READ
));
37 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
40 virtual void TearDown() {
41 logging::CloseLogFile();
43 // Clean up the temporary key
44 RegKey
key(HKEY_CURRENT_USER
, L
"", KEY_ALL_ACCESS
);
45 ASSERT_EQ(ERROR_SUCCESS
, key
.DeleteKey(kTestRoot
));
48 base::ScopedTempDir temp_dir_
;
53 // Execute a WorkItem list successfully and then rollback.
54 TEST_F(WorkItemListTest
, ExecutionSuccess
) {
55 scoped_ptr
<WorkItemList
> work_item_list(WorkItem::CreateWorkItemList());
56 scoped_ptr
<WorkItem
> work_item
;
58 base::FilePath
top_dir_to_create(temp_dir_
.path());
59 top_dir_to_create
= top_dir_to_create
.AppendASCII("a");
60 base::FilePath
dir_to_create(top_dir_to_create
);
61 dir_to_create
= dir_to_create
.AppendASCII("b");
62 ASSERT_FALSE(base::PathExists(dir_to_create
));
64 work_item
.reset(reinterpret_cast<WorkItem
*>(
65 WorkItem::CreateCreateDirWorkItem(dir_to_create
)));
66 work_item_list
->AddWorkItem(work_item
.release());
68 std::wstring
key_to_create(kTestRoot
);
69 key_to_create
.push_back(base::FilePath::kSeparators
[0]);
70 key_to_create
.append(L
"ExecutionSuccess");
72 work_item
.reset(reinterpret_cast<WorkItem
*>(
73 WorkItem::CreateCreateRegKeyWorkItem(HKEY_CURRENT_USER
, key_to_create
)));
74 work_item_list
->AddWorkItem(work_item
.release());
76 std::wstring
name(kName
);
77 std::wstring
data(kDataStr
);
78 work_item
.reset(reinterpret_cast<WorkItem
*>(
79 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER
, key_to_create
,
81 work_item_list
->AddWorkItem(work_item
.release());
83 EXPECT_TRUE(work_item_list
->Do());
85 // Verify all WorkItems have been executed.
87 EXPECT_EQ(ERROR_SUCCESS
,
88 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
89 std::wstring read_out
;
90 EXPECT_EQ(ERROR_SUCCESS
, key
.ReadValue(name
.c_str(), &read_out
));
91 EXPECT_EQ(0, read_out
.compare(kDataStr
));
93 EXPECT_TRUE(base::PathExists(dir_to_create
));
95 work_item_list
->Rollback();
97 // Verify everything is rolled back.
98 // The value must have been deleted first in roll back otherwise the key
99 // can not be deleted.
100 EXPECT_NE(ERROR_SUCCESS
,
101 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
102 EXPECT_FALSE(base::PathExists(top_dir_to_create
));
105 // Execute a WorkItem list. Fail in the middle. Rollback what has been done.
106 TEST_F(WorkItemListTest
, ExecutionFailAndRollback
) {
107 scoped_ptr
<WorkItemList
> work_item_list(WorkItem::CreateWorkItemList());
108 scoped_ptr
<WorkItem
> work_item
;
110 base::FilePath
top_dir_to_create(temp_dir_
.path());
111 top_dir_to_create
= top_dir_to_create
.AppendASCII("a");
112 base::FilePath
dir_to_create(top_dir_to_create
);
113 dir_to_create
= dir_to_create
.AppendASCII("b");
114 ASSERT_FALSE(base::PathExists(dir_to_create
));
116 work_item
.reset(reinterpret_cast<WorkItem
*>(
117 WorkItem::CreateCreateDirWorkItem(dir_to_create
)));
118 work_item_list
->AddWorkItem(work_item
.release());
120 std::wstring
key_to_create(kTestRoot
);
121 key_to_create
.push_back(base::FilePath::kSeparators
[0]);
122 key_to_create
.append(L
"ExecutionFail");
124 work_item
.reset(reinterpret_cast<WorkItem
*>(
125 WorkItem::CreateCreateRegKeyWorkItem(HKEY_CURRENT_USER
, key_to_create
)));
126 work_item_list
->AddWorkItem(work_item
.release());
128 std::wstring
not_created_key(kTestRoot
);
129 not_created_key
.push_back(base::FilePath::kSeparators
[0]);
130 not_created_key
.append(L
"NotCreated");
131 std::wstring
name(kName
);
132 std::wstring
data(kDataStr
);
133 work_item
.reset(reinterpret_cast<WorkItem
*>(
134 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER
, not_created_key
,
135 name
, data
, false)));
136 work_item_list
->AddWorkItem(work_item
.release());
138 // This one will not be executed because we will fail early.
139 work_item
.reset(reinterpret_cast<WorkItem
*>(
140 WorkItem::CreateCreateRegKeyWorkItem(HKEY_CURRENT_USER
,
142 work_item_list
->AddWorkItem(work_item
.release());
144 EXPECT_FALSE(work_item_list
->Do());
146 // Verify the first 2 WorkItems have been executed.
148 EXPECT_EQ(ERROR_SUCCESS
,
149 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
151 EXPECT_TRUE(base::PathExists(dir_to_create
));
152 // The last one should not be there.
153 EXPECT_NE(ERROR_SUCCESS
,
154 key
.Open(HKEY_CURRENT_USER
, not_created_key
.c_str(), KEY_READ
));
156 work_item_list
->Rollback();
158 // Verify everything is rolled back.
159 EXPECT_NE(ERROR_SUCCESS
,
160 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
161 EXPECT_FALSE(base::PathExists(top_dir_to_create
));
164 TEST_F(WorkItemListTest
, ConditionalExecutionSuccess
) {
165 scoped_ptr
<WorkItemList
> work_item_list(WorkItem::CreateWorkItemList());
166 scoped_ptr
<WorkItem
> work_item
;
168 base::FilePath
top_dir_to_create(temp_dir_
.path());
169 top_dir_to_create
= top_dir_to_create
.AppendASCII("a");
170 base::FilePath
dir_to_create(top_dir_to_create
);
171 dir_to_create
= dir_to_create
.AppendASCII("b");
172 ASSERT_FALSE(base::PathExists(dir_to_create
));
174 work_item
.reset(reinterpret_cast<WorkItem
*>(
175 WorkItem::CreateCreateDirWorkItem(dir_to_create
)));
176 work_item_list
->AddWorkItem(work_item
.release());
178 scoped_ptr
<WorkItemList
> conditional_work_item_list(
179 WorkItem::CreateConditionalWorkItemList(
180 new ConditionRunIfFileExists(dir_to_create
)));
182 std::wstring
key_to_create(kTestRoot
);
183 key_to_create
.push_back(base::FilePath::kSeparators
[0]);
184 key_to_create
.append(L
"ExecutionSuccess");
185 work_item
.reset(reinterpret_cast<WorkItem
*>(
186 WorkItem::CreateCreateRegKeyWorkItem(HKEY_CURRENT_USER
, key_to_create
)));
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
, key_to_create
,
193 name
, data
, false)));
194 conditional_work_item_list
->AddWorkItem(work_item
.release());
196 work_item_list
->AddWorkItem(conditional_work_item_list
.release());
198 EXPECT_TRUE(work_item_list
->Do());
200 // Verify all WorkItems have been executed.
202 EXPECT_EQ(ERROR_SUCCESS
,
203 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
204 std::wstring read_out
;
205 EXPECT_EQ(ERROR_SUCCESS
, key
.ReadValue(name
.c_str(), &read_out
));
206 EXPECT_EQ(0, read_out
.compare(kDataStr
));
208 EXPECT_TRUE(base::PathExists(dir_to_create
));
210 work_item_list
->Rollback();
212 // Verify everything is rolled back.
213 // The value must have been deleted first in roll back otherwise the key
214 // can not be deleted.
215 EXPECT_NE(ERROR_SUCCESS
,
216 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
217 EXPECT_FALSE(base::PathExists(top_dir_to_create
));
220 TEST_F(WorkItemListTest
, ConditionalExecutionConditionFailure
) {
221 scoped_ptr
<WorkItemList
> work_item_list(WorkItem::CreateWorkItemList());
222 scoped_ptr
<WorkItem
> work_item
;
224 base::FilePath
top_dir_to_create(temp_dir_
.path());
225 top_dir_to_create
= top_dir_to_create
.AppendASCII("a");
226 base::FilePath
dir_to_create(top_dir_to_create
);
227 dir_to_create
= dir_to_create
.AppendASCII("b");
228 ASSERT_FALSE(base::PathExists(dir_to_create
));
230 work_item
.reset(reinterpret_cast<WorkItem
*>(
231 WorkItem::CreateCreateDirWorkItem(dir_to_create
)));
232 work_item_list
->AddWorkItem(work_item
.release());
234 scoped_ptr
<WorkItemList
> conditional_work_item_list(
235 WorkItem::CreateConditionalWorkItemList(
236 new ConditionRunIfFileExists(dir_to_create
.AppendASCII("c"))));
238 std::wstring
key_to_create(kTestRoot
);
239 key_to_create
.push_back(base::FilePath::kSeparators
[0]);
240 key_to_create
.append(L
"ExecutionSuccess");
241 work_item
.reset(reinterpret_cast<WorkItem
*>(
242 WorkItem::CreateCreateRegKeyWorkItem(HKEY_CURRENT_USER
, key_to_create
)));
243 conditional_work_item_list
->AddWorkItem(work_item
.release());
245 std::wstring
name(kName
);
246 std::wstring
data(kDataStr
);
247 work_item
.reset(reinterpret_cast<WorkItem
*>(
248 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER
, key_to_create
,
249 name
, data
, false)));
250 conditional_work_item_list
->AddWorkItem(work_item
.release());
252 work_item_list
->AddWorkItem(conditional_work_item_list
.release());
254 EXPECT_TRUE(work_item_list
->Do());
256 // Verify that the WorkItems added as part of the conditional list have NOT
259 EXPECT_NE(ERROR_SUCCESS
,
260 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
261 std::wstring read_out
;
262 EXPECT_NE(ERROR_SUCCESS
, key
.ReadValue(name
.c_str(), &read_out
));
265 // Verify that the other work item was executed.
266 EXPECT_TRUE(base::PathExists(dir_to_create
));
268 work_item_list
->Rollback();
270 // Verify everything is rolled back.
271 // The value must have been deleted first in roll back otherwise the key
272 // can not be deleted.
273 EXPECT_NE(ERROR_SUCCESS
,
274 key
.Open(HKEY_CURRENT_USER
, key_to_create
.c_str(), KEY_READ
));
275 EXPECT_FALSE(base::PathExists(top_dir_to_create
));