work_item_list_unittest.cc revision cedac228d2dd51db4b79ea1e72c7f249408ee061
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.
4
5#include <windows.h>
6
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"
18
19using base::win::RegKey;
20
21namespace {
22
23const wchar_t kTestRoot[] = L"ListList";
24const wchar_t kDataStr[] = L"data_111";
25const wchar_t kName[] = L"name";
26
27class WorkItemListTest : public testing::Test {
28 protected:
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));
36
37    ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
38  }
39
40  virtual void TearDown() {
41    logging::CloseLogFile();
42
43    // Clean up the temporary key
44    RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS);
45    ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kTestRoot));
46  }
47
48  base::ScopedTempDir temp_dir_;
49};
50
51}  // namespace
52
53// Execute a WorkItem list successfully and then rollback.
54TEST_F(WorkItemListTest, ExecutionSuccess) {
55  scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList());
56  scoped_ptr<WorkItem> work_item;
57
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));
63
64  work_item.reset(reinterpret_cast<WorkItem*>(
65      WorkItem::CreateCreateDirWorkItem(dir_to_create)));
66  work_item_list->AddWorkItem(work_item.release());
67
68  std::wstring key_to_create(kTestRoot);
69  key_to_create.push_back(base::FilePath::kSeparators[0]);
70  key_to_create.append(L"ExecutionSuccess");
71
72  work_item.reset(
73      reinterpret_cast<WorkItem*>(WorkItem::CreateCreateRegKeyWorkItem(
74          HKEY_CURRENT_USER, key_to_create, WorkItem::kWow64Default)));
75  work_item_list->AddWorkItem(work_item.release());
76
77  std::wstring name(kName);
78  std::wstring data(kDataStr);
79  work_item.reset(reinterpret_cast<WorkItem*>(
80      WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER,
81                                          key_to_create,
82                                          WorkItem::kWow64Default,
83                                          name,
84                                          data,
85                                          false)));
86  work_item_list->AddWorkItem(work_item.release());
87
88  EXPECT_TRUE(work_item_list->Do());
89
90  // Verify all WorkItems have been executed.
91  RegKey key;
92  EXPECT_EQ(ERROR_SUCCESS,
93      key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ));
94  std::wstring read_out;
95  EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name.c_str(), &read_out));
96  EXPECT_EQ(0, read_out.compare(kDataStr));
97  key.Close();
98  EXPECT_TRUE(base::PathExists(dir_to_create));
99
100  work_item_list->Rollback();
101
102  // Verify everything is rolled back.
103  // The value must have been deleted first in roll back otherwise the key
104  // can not be deleted.
105  EXPECT_NE(ERROR_SUCCESS,
106      key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ));
107  EXPECT_FALSE(base::PathExists(top_dir_to_create));
108}
109
110// Execute a WorkItem list. Fail in the middle. Rollback what has been done.
111TEST_F(WorkItemListTest, ExecutionFailAndRollback) {
112  scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList());
113  scoped_ptr<WorkItem> work_item;
114
115  base::FilePath top_dir_to_create(temp_dir_.path());
116  top_dir_to_create = top_dir_to_create.AppendASCII("a");
117  base::FilePath dir_to_create(top_dir_to_create);
118  dir_to_create = dir_to_create.AppendASCII("b");
119  ASSERT_FALSE(base::PathExists(dir_to_create));
120
121  work_item.reset(reinterpret_cast<WorkItem*>(
122      WorkItem::CreateCreateDirWorkItem(dir_to_create)));
123  work_item_list->AddWorkItem(work_item.release());
124
125  std::wstring key_to_create(kTestRoot);
126  key_to_create.push_back(base::FilePath::kSeparators[0]);
127  key_to_create.append(L"ExecutionFail");
128
129  work_item.reset(
130      reinterpret_cast<WorkItem*>(WorkItem::CreateCreateRegKeyWorkItem(
131          HKEY_CURRENT_USER, key_to_create, WorkItem::kWow64Default)));
132  work_item_list->AddWorkItem(work_item.release());
133
134  std::wstring not_created_key(kTestRoot);
135  not_created_key.push_back(base::FilePath::kSeparators[0]);
136  not_created_key.append(L"NotCreated");
137  std::wstring name(kName);
138  std::wstring data(kDataStr);
139  work_item.reset(reinterpret_cast<WorkItem*>(
140      WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER,
141                                          not_created_key,
142                                          WorkItem::kWow64Default,
143                                          name,
144                                          data,
145                                          false)));
146  work_item_list->AddWorkItem(work_item.release());
147
148  // This one will not be executed because we will fail early.
149  work_item.reset(
150      reinterpret_cast<WorkItem*>(WorkItem::CreateCreateRegKeyWorkItem(
151          HKEY_CURRENT_USER, not_created_key, WorkItem::kWow64Default)));
152  work_item_list->AddWorkItem(work_item.release());
153
154  EXPECT_FALSE(work_item_list->Do());
155
156  // Verify the first 2 WorkItems have been executed.
157  RegKey key;
158  EXPECT_EQ(ERROR_SUCCESS,
159      key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ));
160  key.Close();
161  EXPECT_TRUE(base::PathExists(dir_to_create));
162  // The last one should not be there.
163  EXPECT_NE(ERROR_SUCCESS,
164      key.Open(HKEY_CURRENT_USER, not_created_key.c_str(), KEY_READ));
165
166  work_item_list->Rollback();
167
168  // Verify everything is rolled back.
169  EXPECT_NE(ERROR_SUCCESS,
170      key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ));
171  EXPECT_FALSE(base::PathExists(top_dir_to_create));
172}
173
174TEST_F(WorkItemListTest, ConditionalExecutionSuccess) {
175  scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList());
176  scoped_ptr<WorkItem> work_item;
177
178  base::FilePath top_dir_to_create(temp_dir_.path());
179  top_dir_to_create = top_dir_to_create.AppendASCII("a");
180  base::FilePath dir_to_create(top_dir_to_create);
181  dir_to_create = dir_to_create.AppendASCII("b");
182  ASSERT_FALSE(base::PathExists(dir_to_create));
183
184  work_item.reset(reinterpret_cast<WorkItem*>(
185      WorkItem::CreateCreateDirWorkItem(dir_to_create)));
186  work_item_list->AddWorkItem(work_item.release());
187
188  scoped_ptr<WorkItemList> conditional_work_item_list(
189      WorkItem::CreateConditionalWorkItemList(
190          new ConditionRunIfFileExists(dir_to_create)));
191
192  std::wstring key_to_create(kTestRoot);
193  key_to_create.push_back(base::FilePath::kSeparators[0]);
194  key_to_create.append(L"ExecutionSuccess");
195  work_item.reset(
196      reinterpret_cast<WorkItem*>(WorkItem::CreateCreateRegKeyWorkItem(
197          HKEY_CURRENT_USER, key_to_create, WorkItem::kWow64Default)));
198  conditional_work_item_list->AddWorkItem(work_item.release());
199
200  std::wstring name(kName);
201  std::wstring data(kDataStr);
202  work_item.reset(reinterpret_cast<WorkItem*>(
203      WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER,
204                                          key_to_create,
205                                          WorkItem::kWow64Default,
206                                          name,
207                                          data,
208                                          false)));
209  conditional_work_item_list->AddWorkItem(work_item.release());
210
211  work_item_list->AddWorkItem(conditional_work_item_list.release());
212
213  EXPECT_TRUE(work_item_list->Do());
214
215  // Verify all WorkItems have been executed.
216  RegKey key;
217  EXPECT_EQ(ERROR_SUCCESS,
218      key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ));
219  std::wstring read_out;
220  EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name.c_str(), &read_out));
221  EXPECT_EQ(0, read_out.compare(kDataStr));
222  key.Close();
223  EXPECT_TRUE(base::PathExists(dir_to_create));
224
225  work_item_list->Rollback();
226
227  // Verify everything is rolled back.
228  // The value must have been deleted first in roll back otherwise the key
229  // can not be deleted.
230  EXPECT_NE(ERROR_SUCCESS,
231      key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ));
232  EXPECT_FALSE(base::PathExists(top_dir_to_create));
233}
234
235TEST_F(WorkItemListTest, ConditionalExecutionConditionFailure) {
236  scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList());
237  scoped_ptr<WorkItem> work_item;
238
239  base::FilePath top_dir_to_create(temp_dir_.path());
240  top_dir_to_create = top_dir_to_create.AppendASCII("a");
241  base::FilePath dir_to_create(top_dir_to_create);
242  dir_to_create = dir_to_create.AppendASCII("b");
243  ASSERT_FALSE(base::PathExists(dir_to_create));
244
245  work_item.reset(reinterpret_cast<WorkItem*>(
246      WorkItem::CreateCreateDirWorkItem(dir_to_create)));
247  work_item_list->AddWorkItem(work_item.release());
248
249  scoped_ptr<WorkItemList> conditional_work_item_list(
250      WorkItem::CreateConditionalWorkItemList(
251          new ConditionRunIfFileExists(dir_to_create.AppendASCII("c"))));
252
253  std::wstring key_to_create(kTestRoot);
254  key_to_create.push_back(base::FilePath::kSeparators[0]);
255  key_to_create.append(L"ExecutionSuccess");
256  work_item.reset(
257      reinterpret_cast<WorkItem*>(WorkItem::CreateCreateRegKeyWorkItem(
258          HKEY_CURRENT_USER, key_to_create, WorkItem::kWow64Default)));
259  conditional_work_item_list->AddWorkItem(work_item.release());
260
261  std::wstring name(kName);
262  std::wstring data(kDataStr);
263  work_item.reset(reinterpret_cast<WorkItem*>(
264      WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER,
265                                          key_to_create,
266                                          WorkItem::kWow64Default,
267                                          name,
268                                          data,
269                                          false)));
270  conditional_work_item_list->AddWorkItem(work_item.release());
271
272  work_item_list->AddWorkItem(conditional_work_item_list.release());
273
274  EXPECT_TRUE(work_item_list->Do());
275
276  // Verify that the WorkItems added as part of the conditional list have NOT
277  // been executed.
278  RegKey key;
279  EXPECT_NE(ERROR_SUCCESS,
280      key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ));
281  std::wstring read_out;
282  EXPECT_NE(ERROR_SUCCESS, key.ReadValue(name.c_str(), &read_out));
283  key.Close();
284
285  // Verify that the other work item was executed.
286  EXPECT_TRUE(base::PathExists(dir_to_create));
287
288  work_item_list->Rollback();
289
290  // Verify everything is rolled back.
291  // The value must have been deleted first in roll back otherwise the key
292  // can not be deleted.
293  EXPECT_NE(ERROR_SUCCESS,
294      key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ));
295  EXPECT_FALSE(base::PathExists(top_dir_to_create));
296}
297