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/files/file_path.h" 8 #include "base/memory/scoped_ptr.h" 9 #include "base/strings/string_util.h" 10 #include "base/win/registry.h" 11 #include "chrome/installer/util/set_reg_value_work_item.h" 12 #include "chrome/installer/util/work_item.h" 13 #include "testing/gtest/include/gtest/gtest.h" 14 15 using base::win::RegKey; 16 17 namespace { 18 19 const wchar_t kTestRoot[] = L"TempTemp"; 20 const wchar_t kDataStr1[] = L"data_111"; 21 const wchar_t kDataStr2[] = L"data_222"; 22 const wchar_t kNameStr[] = L"name_str"; 23 const wchar_t kNameDword[] = L"name_dword"; 24 25 const DWORD dword1 = 0; 26 const DWORD dword2 = 1; 27 28 class SetRegValueWorkItemTest : public testing::Test { 29 protected: 30 virtual void SetUp() { 31 // Create a temporary key for testing 32 RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS); 33 key.DeleteKey(kTestRoot); 34 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kTestRoot, KEY_READ)); 35 ASSERT_EQ(ERROR_SUCCESS, 36 key.Create(HKEY_CURRENT_USER, kTestRoot, KEY_READ)); 37 } 38 virtual void TearDown() { 39 logging::CloseLogFile(); 40 // Clean up the temporary key 41 RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS); 42 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kTestRoot)); 43 } 44 }; 45 46 } // namespace 47 48 // Write a new value without overwrite flag. The value should be set. 49 TEST_F(SetRegValueWorkItemTest, WriteNewNonOverwrite) { 50 RegKey key; 51 52 std::wstring parent_key(kTestRoot); 53 parent_key.append(&base::FilePath::kSeparators[0], 1); 54 parent_key.append(L"WriteNewNonOverwrite"); 55 ASSERT_EQ(ERROR_SUCCESS, 56 key.Create(HKEY_CURRENT_USER, parent_key.c_str(), KEY_READ)); 57 58 std::wstring name_str(kNameStr); 59 std::wstring data_str(kDataStr1); 60 scoped_ptr<SetRegValueWorkItem> work_item1( 61 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 62 parent_key, 63 WorkItem::kWow64Default, 64 name_str, 65 data_str, 66 false)); 67 68 std::wstring name_dword(kNameDword); 69 scoped_ptr<SetRegValueWorkItem> work_item2( 70 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 71 parent_key, 72 WorkItem::kWow64Default, 73 name_dword, 74 dword1, 75 false)); 76 77 EXPECT_TRUE(work_item1->Do()); 78 EXPECT_TRUE(work_item2->Do()); 79 80 std::wstring read_out; 81 DWORD read_dword; 82 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name_str.c_str(), &read_out)); 83 EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(name_dword.c_str(), &read_dword)); 84 EXPECT_EQ(read_out, kDataStr1); 85 EXPECT_EQ(read_dword, dword1); 86 87 work_item1->Rollback(); 88 work_item2->Rollback(); 89 90 // Rollback should delete the value. 91 EXPECT_FALSE(key.HasValue(name_str.c_str())); 92 EXPECT_FALSE(key.HasValue(name_dword.c_str())); 93 } 94 95 // Write a new value with overwrite flag. The value should be set. 96 TEST_F(SetRegValueWorkItemTest, WriteNewOverwrite) { 97 RegKey key; 98 99 std::wstring parent_key(kTestRoot); 100 parent_key.append(&base::FilePath::kSeparators[0], 1); 101 parent_key.append(L"WriteNewOverwrite"); 102 ASSERT_EQ(ERROR_SUCCESS, 103 key.Create(HKEY_CURRENT_USER, parent_key.c_str(), KEY_READ)); 104 105 std::wstring name_str(kNameStr); 106 std::wstring data_str(kDataStr1); 107 scoped_ptr<SetRegValueWorkItem> work_item1( 108 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 109 parent_key, 110 WorkItem::kWow64Default, 111 name_str, 112 data_str, 113 true)); 114 115 std::wstring name_dword(kNameDword); 116 scoped_ptr<SetRegValueWorkItem> work_item2( 117 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 118 parent_key, 119 WorkItem::kWow64Default, 120 name_dword, 121 dword1, 122 true)); 123 124 EXPECT_TRUE(work_item1->Do()); 125 EXPECT_TRUE(work_item2->Do()); 126 127 std::wstring read_out; 128 DWORD read_dword; 129 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name_str.c_str(), &read_out)); 130 EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(name_dword.c_str(), &read_dword)); 131 EXPECT_EQ(read_out, kDataStr1); 132 EXPECT_EQ(read_dword, dword1); 133 134 work_item1->Rollback(); 135 work_item2->Rollback(); 136 137 // Rollback should delete the value. 138 EXPECT_FALSE(key.HasValue(name_str.c_str())); 139 EXPECT_FALSE(key.HasValue(name_dword.c_str())); 140 } 141 142 // Write to an existing value without overwrite flag. There should be 143 // no change. 144 TEST_F(SetRegValueWorkItemTest, WriteExistingNonOverwrite) { 145 RegKey key; 146 147 std::wstring parent_key(kTestRoot); 148 parent_key.append(&base::FilePath::kSeparators[0], 1); 149 parent_key.append(L"WriteExistingNonOverwrite"); 150 ASSERT_EQ(ERROR_SUCCESS, 151 key.Create(HKEY_CURRENT_USER, parent_key.c_str(), 152 KEY_READ | KEY_SET_VALUE)); 153 154 // First test REG_SZ value. 155 // Write data to the value we are going to set. 156 std::wstring name(kNameStr); 157 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(name.c_str(), kDataStr1)); 158 159 std::wstring data(kDataStr2); 160 scoped_ptr<SetRegValueWorkItem> work_item( 161 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 162 parent_key, 163 WorkItem::kWow64Default, 164 name, 165 data, 166 false)); 167 EXPECT_TRUE(work_item->Do()); 168 169 std::wstring read_out; 170 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name.c_str(), &read_out)); 171 EXPECT_EQ(0, read_out.compare(kDataStr1)); 172 173 work_item->Rollback(); 174 EXPECT_TRUE(key.HasValue(name.c_str())); 175 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name.c_str(), &read_out)); 176 EXPECT_EQ(read_out, kDataStr1); 177 178 // Now test REG_DWORD value. 179 // Write data to the value we are going to set. 180 name.assign(kNameDword); 181 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(name.c_str(), dword1)); 182 work_item.reset(WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 183 parent_key, 184 WorkItem::kWow64Default, 185 name, 186 dword2, 187 false)); 188 EXPECT_TRUE(work_item->Do()); 189 190 DWORD read_dword; 191 EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(name.c_str(), &read_dword)); 192 EXPECT_EQ(read_dword, dword1); 193 194 work_item->Rollback(); 195 EXPECT_TRUE(key.HasValue(name.c_str())); 196 EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(name.c_str(), &read_dword)); 197 EXPECT_EQ(read_dword, dword1); 198 } 199 200 // Write to an existing value with overwrite flag. The value should be 201 // overwritten. 202 TEST_F(SetRegValueWorkItemTest, WriteExistingOverwrite) { 203 RegKey key; 204 205 std::wstring parent_key(kTestRoot); 206 parent_key.append(&base::FilePath::kSeparators[0], 1); 207 parent_key.append(L"WriteExistingOverwrite"); 208 ASSERT_EQ(ERROR_SUCCESS, 209 key.Create(HKEY_CURRENT_USER, parent_key.c_str(), 210 KEY_READ | KEY_SET_VALUE)); 211 212 // First test REG_SZ value. 213 // Write data to the value we are going to set. 214 std::wstring name(kNameStr); 215 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(name.c_str(), kDataStr1)); 216 217 std::wstring name_empty(L"name_empty"); 218 ASSERT_EQ(ERROR_SUCCESS, RegSetValueEx(key.Handle(), name_empty.c_str(), NULL, 219 REG_SZ, NULL, 0)); 220 221 std::wstring data(kDataStr2); 222 scoped_ptr<SetRegValueWorkItem> work_item1( 223 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 224 parent_key, 225 WorkItem::kWow64Default, 226 name, 227 data, 228 true)); 229 scoped_ptr<SetRegValueWorkItem> work_item2( 230 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 231 parent_key, 232 WorkItem::kWow64Default, 233 name_empty, 234 data, 235 true)); 236 237 EXPECT_TRUE(work_item1->Do()); 238 EXPECT_TRUE(work_item2->Do()); 239 240 std::wstring read_out; 241 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name.c_str(), &read_out)); 242 EXPECT_EQ(0, read_out.compare(kDataStr2)); 243 244 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name_empty.c_str(), &read_out)); 245 EXPECT_EQ(0, read_out.compare(kDataStr2)); 246 247 work_item1->Rollback(); 248 work_item2->Rollback(); 249 250 EXPECT_TRUE(key.HasValue(name.c_str())); 251 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name.c_str(), &read_out)); 252 EXPECT_EQ(read_out, kDataStr1); 253 254 DWORD type = 0; 255 DWORD size = 0; 256 EXPECT_EQ(ERROR_SUCCESS, key.ReadValue(name_empty.c_str(), NULL, &size, 257 &type)); 258 EXPECT_EQ(REG_SZ, type); 259 EXPECT_EQ(0, size); 260 261 // Now test REG_DWORD value. 262 // Write data to the value we are going to set. 263 name.assign(kNameDword); 264 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(name.c_str(), dword1)); 265 scoped_ptr<SetRegValueWorkItem> work_item3( 266 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 267 parent_key, 268 WorkItem::kWow64Default, 269 name, 270 dword2, 271 true)); 272 EXPECT_TRUE(work_item3->Do()); 273 274 DWORD read_dword; 275 EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(name.c_str(), &read_dword)); 276 EXPECT_EQ(read_dword, dword2); 277 278 work_item3->Rollback(); 279 EXPECT_TRUE(key.HasValue(name.c_str())); 280 EXPECT_EQ(ERROR_SUCCESS, key.ReadValueDW(name.c_str(), &read_dword)); 281 EXPECT_EQ(read_dword, dword1); 282 } 283 284 // Write a value to a non-existing key. This should fail. 285 TEST_F(SetRegValueWorkItemTest, WriteNonExistingKey) { 286 RegKey key; 287 288 std::wstring parent_key(kTestRoot); 289 parent_key.append(&base::FilePath::kSeparators[0], 1); 290 parent_key.append(L"WriteNonExistingKey"); 291 292 std::wstring name(L"name"); 293 std::wstring data(kDataStr1); 294 scoped_ptr<SetRegValueWorkItem> work_item( 295 WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 296 parent_key, 297 WorkItem::kWow64Default, 298 name, 299 data, 300 false)); 301 EXPECT_FALSE(work_item->Do()); 302 303 work_item.reset(WorkItem::CreateSetRegValueWorkItem(HKEY_CURRENT_USER, 304 parent_key, 305 WorkItem::kWow64Default, 306 name, 307 dword1, 308 false)); 309 EXPECT_FALSE(work_item->Do()); 310 } 311