work_item_list_unittest.cc revision 868fa2fe829687343ffae624259930155e16dbd8
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(file_util::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(reinterpret_cast<WorkItem*>(
73      WorkItem::CreateCreateRegKeyWorkItem(HKEY_CURRENT_USER, key_to_create)));
74  work_item_list->AddWorkItem(work_item.release());
75
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,
80                                          name, data, false)));
81  work_item_list->AddWorkItem(work_item.release());
82
83  EXPECT_TRUE(work_item_list->Do());
84
85  // Verify all WorkItems have been executed.
86  RegKey key;
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));
92  key.Close();
93  EXPECT_TRUE(file_util::PathExists(dir_to_create));
94
95  work_item_list->Rollback();
96
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(file_util::PathExists(top_dir_to_create));
103}
104
105// Execute a WorkItem list. Fail in the middle. Rollback what has been done.
106TEST_F(WorkItemListTest, ExecutionFailAndRollback) {
107  scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList());
108  scoped_ptr<WorkItem> work_item;
109
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(file_util::PathExists(dir_to_create));
115
116  work_item.reset(reinterpret_cast<WorkItem*>(
117      WorkItem::CreateCreateDirWorkItem(dir_to_create)));
118  work_item_list->AddWorkItem(work_item.release());
119
120  std::wstring key_to_create(kTestRoot);
121  key_to_create.push_back(base::FilePath::kSeparators[0]);
122  key_to_create.append(L"ExecutionFail");
123
124  work_item.reset(reinterpret_cast<WorkItem*>(
125      WorkItem::CreateCreateRegKeyWorkItem(HKEY_CURRENT_USER, key_to_create)));
126  work_item_list->AddWorkItem(work_item.release());
127
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());
137
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,
141                                           not_created_key)));
142  work_item_list->AddWorkItem(work_item.release());
143
144  EXPECT_FALSE(work_item_list->Do());
145
146  // Verify the first 2 WorkItems have been executed.
147  RegKey key;
148  EXPECT_EQ(ERROR_SUCCESS,
149      key.Open(HKEY_CURRENT_USER, key_to_create.c_str(), KEY_READ));
150  key.Close();
151  EXPECT_TRUE(file_util::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));
155
156  work_item_list->Rollback();
157
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(file_util::PathExists(top_dir_to_create));
162}
163
164TEST_F(WorkItemListTest, ConditionalExecutionSuccess) {
165  scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList());
166  scoped_ptr<WorkItem> work_item;
167
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(file_util::PathExists(dir_to_create));
173
174  work_item.reset(reinterpret_cast<WorkItem*>(
175      WorkItem::CreateCreateDirWorkItem(dir_to_create)));
176  work_item_list->AddWorkItem(work_item.release());
177
178  scoped_ptr<WorkItemList> conditional_work_item_list(
179      WorkItem::CreateConditionalWorkItemList(
180          new ConditionRunIfFileExists(dir_to_create)));
181
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());
188
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());
195
196  work_item_list->AddWorkItem(conditional_work_item_list.release());
197
198  EXPECT_TRUE(work_item_list->Do());
199
200  // Verify all WorkItems have been executed.
201  RegKey key;
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));
207  key.Close();
208  EXPECT_TRUE(file_util::PathExists(dir_to_create));
209
210  work_item_list->Rollback();
211
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(file_util::PathExists(top_dir_to_create));
218}
219
220TEST_F(WorkItemListTest, ConditionalExecutionConditionFailure) {
221  scoped_ptr<WorkItemList> work_item_list(WorkItem::CreateWorkItemList());
222  scoped_ptr<WorkItem> work_item;
223
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(file_util::PathExists(dir_to_create));
229
230  work_item.reset(reinterpret_cast<WorkItem*>(
231      WorkItem::CreateCreateDirWorkItem(dir_to_create)));
232  work_item_list->AddWorkItem(work_item.release());
233
234  scoped_ptr<WorkItemList> conditional_work_item_list(
235      WorkItem::CreateConditionalWorkItemList(
236          new ConditionRunIfFileExists(dir_to_create.AppendASCII("c"))));
237
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());
244
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());
251
252  work_item_list->AddWorkItem(conditional_work_item_list.release());
253
254  EXPECT_TRUE(work_item_list->Do());
255
256  // Verify that the WorkItems added as part of the conditional list have NOT
257  // been executed.
258  RegKey key;
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));
263  key.Close();
264
265  // Verify that the other work item was executed.
266  EXPECT_TRUE(file_util::PathExists(dir_to_create));
267
268  work_item_list->Rollback();
269
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(file_util::PathExists(top_dir_to_create));
276}
277