[SyncFS] Build indexes from FileTracker entries on disk.
[chromium-blink-merge.git] / base / win / registry_unittest.cc
blob84074b385862cdd6edeb6f277f536e9594e017a4
1 // Copyright (c) 2011 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.
5 #include "base/win/registry.h"
7 #include <cstring>
8 #include <vector>
10 #include "base/compiler_specific.h"
11 #include "base/stl_util.h"
12 #include "base/win/windows_version.h"
13 #include "testing/gtest/include/gtest/gtest.h"
15 namespace base {
16 namespace win {
18 namespace {
20 class RegistryTest : public testing::Test {
21 protected:
22 #if defined(_WIN64)
23 static const REGSAM kNativeViewMask = KEY_WOW64_64KEY;
24 static const REGSAM kRedirectedViewMask = KEY_WOW64_32KEY;
25 #else
26 static const REGSAM kNativeViewMask = KEY_WOW64_32KEY;
27 static const REGSAM kRedirectedViewMask = KEY_WOW64_64KEY;
28 #endif // _WIN64
30 RegistryTest() {}
31 virtual void SetUp() OVERRIDE {
32 // Create a temporary key.
33 RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS);
34 key.DeleteKey(kRootKey);
35 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
36 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, kRootKey, KEY_READ));
37 foo_software_key_ = L"Software\\";
38 foo_software_key_ += kRootKey;
39 foo_software_key_ += L"\\Foo";
42 virtual void TearDown() OVERRIDE {
43 // Clean up the temporary key.
44 RegKey key(HKEY_CURRENT_USER, L"", KEY_SET_VALUE);
45 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
46 ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
49 static bool IsRedirectorPresent() {
50 #if defined(_WIN64)
51 return true;
52 #else
53 return OSInfo::GetInstance()->wow64_status() == OSInfo::WOW64_ENABLED;
54 #endif
57 const wchar_t* const kRootKey = L"Base_Registry_Unittest";
58 std::wstring foo_software_key_;
60 private:
61 DISALLOW_COPY_AND_ASSIGN(RegistryTest);
64 // static
65 const REGSAM RegistryTest::kNativeViewMask;
66 const REGSAM RegistryTest::kRedirectedViewMask;
68 TEST_F(RegistryTest, ValueTest) {
69 RegKey key;
71 std::wstring foo_key(kRootKey);
72 foo_key += L"\\Foo";
73 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
74 KEY_READ));
77 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
78 KEY_READ | KEY_SET_VALUE));
79 ASSERT_TRUE(key.Valid());
81 const wchar_t kStringValueName[] = L"StringValue";
82 const wchar_t kDWORDValueName[] = L"DWORDValue";
83 const wchar_t kInt64ValueName[] = L"Int64Value";
84 const wchar_t kStringData[] = L"string data";
85 const DWORD kDWORDData = 0xdeadbabe;
86 const int64 kInt64Data = 0xdeadbabedeadbabeLL;
88 // Test value creation
89 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kStringValueName, kStringData));
90 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kDWORDValueName, kDWORDData));
91 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kInt64ValueName, &kInt64Data,
92 sizeof(kInt64Data), REG_QWORD));
93 EXPECT_EQ(3U, key.GetValueCount());
94 EXPECT_TRUE(key.HasValue(kStringValueName));
95 EXPECT_TRUE(key.HasValue(kDWORDValueName));
96 EXPECT_TRUE(key.HasValue(kInt64ValueName));
98 // Test Read
99 std::wstring string_value;
100 DWORD dword_value = 0;
101 int64 int64_value = 0;
102 ASSERT_EQ(ERROR_SUCCESS, key.ReadValue(kStringValueName, &string_value));
103 ASSERT_EQ(ERROR_SUCCESS, key.ReadValueDW(kDWORDValueName, &dword_value));
104 ASSERT_EQ(ERROR_SUCCESS, key.ReadInt64(kInt64ValueName, &int64_value));
105 EXPECT_STREQ(kStringData, string_value.c_str());
106 EXPECT_EQ(kDWORDData, dword_value);
107 EXPECT_EQ(kInt64Data, int64_value);
109 // Make sure out args are not touched if ReadValue fails
110 const wchar_t* kNonExistent = L"NonExistent";
111 ASSERT_NE(ERROR_SUCCESS, key.ReadValue(kNonExistent, &string_value));
112 ASSERT_NE(ERROR_SUCCESS, key.ReadValueDW(kNonExistent, &dword_value));
113 ASSERT_NE(ERROR_SUCCESS, key.ReadInt64(kNonExistent, &int64_value));
114 EXPECT_STREQ(kStringData, string_value.c_str());
115 EXPECT_EQ(kDWORDData, dword_value);
116 EXPECT_EQ(kInt64Data, int64_value);
118 // Test delete
119 ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kStringValueName));
120 ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kDWORDValueName));
121 ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kInt64ValueName));
122 EXPECT_EQ(0U, key.GetValueCount());
123 EXPECT_FALSE(key.HasValue(kStringValueName));
124 EXPECT_FALSE(key.HasValue(kDWORDValueName));
125 EXPECT_FALSE(key.HasValue(kInt64ValueName));
129 TEST_F(RegistryTest, BigValueIteratorTest) {
130 RegKey key;
131 std::wstring foo_key(kRootKey);
132 foo_key += L"\\Foo";
133 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
134 KEY_READ));
135 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
136 KEY_READ | KEY_SET_VALUE));
137 ASSERT_TRUE(key.Valid());
139 // Create a test value that is larger than MAX_PATH.
140 std::wstring data(MAX_PATH * 2, L'a');
142 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(data.c_str(), data.c_str()));
144 RegistryValueIterator iterator(HKEY_CURRENT_USER, foo_key.c_str());
145 ASSERT_TRUE(iterator.Valid());
146 EXPECT_STREQ(data.c_str(), iterator.Name());
147 EXPECT_STREQ(data.c_str(), iterator.Value());
148 // ValueSize() is in bytes, including NUL.
149 EXPECT_EQ((MAX_PATH * 2 + 1) * sizeof(wchar_t), iterator.ValueSize());
150 ++iterator;
151 EXPECT_FALSE(iterator.Valid());
154 TEST_F(RegistryTest, TruncatedCharTest) {
155 RegKey key;
156 std::wstring foo_key(kRootKey);
157 foo_key += L"\\Foo";
158 ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
159 KEY_READ));
160 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
161 KEY_READ | KEY_SET_VALUE));
162 ASSERT_TRUE(key.Valid());
164 const wchar_t kName[] = L"name";
165 // kData size is not a multiple of sizeof(wchar_t).
166 const uint8 kData[] = { 1, 2, 3, 4, 5 };
167 EXPECT_EQ(5, arraysize(kData));
168 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kName, kData,
169 arraysize(kData), REG_BINARY));
171 RegistryValueIterator iterator(HKEY_CURRENT_USER, foo_key.c_str());
172 ASSERT_TRUE(iterator.Valid());
173 EXPECT_STREQ(kName, iterator.Name());
174 // ValueSize() is in bytes.
175 ASSERT_EQ(arraysize(kData), iterator.ValueSize());
176 // Value() is NUL terminated.
177 int end = (iterator.ValueSize() + sizeof(wchar_t) - 1) / sizeof(wchar_t);
178 EXPECT_NE(L'\0', iterator.Value()[end-1]);
179 EXPECT_EQ(L'\0', iterator.Value()[end]);
180 EXPECT_EQ(0, std::memcmp(kData, iterator.Value(), arraysize(kData)));
181 ++iterator;
182 EXPECT_FALSE(iterator.Valid());
185 TEST_F(RegistryTest, RecursiveDelete) {
186 RegKey key;
187 // Create kRootKey->Foo
188 // \->Bar (TestValue)
189 // \->Foo (TestValue)
190 // \->Bar
191 // \->Foo
192 // \->Moo
193 // \->Foo
194 // and delete kRootKey->Foo
195 std::wstring foo_key(kRootKey);
196 foo_key += L"\\Foo";
197 ASSERT_EQ(ERROR_SUCCESS,
198 key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
199 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
200 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
201 ASSERT_EQ(ERROR_SUCCESS,
202 key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
203 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Moo", KEY_WRITE));
204 ASSERT_EQ(ERROR_SUCCESS,
205 key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
206 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
207 foo_key += L"\\Bar";
208 ASSERT_EQ(ERROR_SUCCESS,
209 key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
210 foo_key += L"\\Foo";
211 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
212 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
213 ASSERT_EQ(ERROR_SUCCESS,
214 key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
216 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
217 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Bar"));
218 ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo"));
219 ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Bar\\Foo"));
220 ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Bar"));
221 ASSERT_EQ(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Foo"));
223 ASSERT_EQ(ERROR_SUCCESS,
224 key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
225 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
226 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
227 ASSERT_EQ(ERROR_SUCCESS,
228 key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
229 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L""));
230 ASSERT_NE(ERROR_SUCCESS,
231 key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
233 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
234 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"Foo"));
235 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Foo"));
236 ASSERT_NE(ERROR_SUCCESS,
237 key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
240 // This test requires running as an Administrator as it tests redirected
241 // registry writes to HKLM\Software
242 // http://msdn.microsoft.com/en-us/library/windows/desktop/aa384253.aspx
243 // TODO(wfh): flaky test on Vista. See http://crbug.com/377917
244 TEST_F(RegistryTest, DISABLED_Wow64RedirectedFromNative) {
245 if (!IsRedirectorPresent())
246 return;
248 RegKey key;
250 // Test redirected key access from non-redirected.
251 ASSERT_EQ(ERROR_SUCCESS,
252 key.Create(HKEY_LOCAL_MACHINE,
253 foo_software_key_.c_str(),
254 KEY_WRITE | kRedirectedViewMask));
255 ASSERT_NE(ERROR_SUCCESS,
256 key.Open(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(), KEY_READ));
257 ASSERT_NE(ERROR_SUCCESS,
258 key.Open(HKEY_LOCAL_MACHINE,
259 foo_software_key_.c_str(),
260 KEY_READ | kNativeViewMask));
262 // Open the non-redirected view of the parent and try to delete the test key.
263 ASSERT_EQ(ERROR_SUCCESS,
264 key.Open(HKEY_LOCAL_MACHINE, L"Software", KEY_SET_VALUE));
265 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
266 ASSERT_EQ(ERROR_SUCCESS,
267 key.Open(HKEY_LOCAL_MACHINE,
268 L"Software",
269 KEY_SET_VALUE | kNativeViewMask));
270 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
272 // Open the redirected view and delete the key created above.
273 ASSERT_EQ(ERROR_SUCCESS,
274 key.Open(HKEY_LOCAL_MACHINE,
275 L"Software",
276 KEY_SET_VALUE | kRedirectedViewMask));
277 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
280 // Test for the issue found in http://crbug.com/384587 where OpenKey would call
281 // Close() and reset wow64_access_ flag to 0 and cause a NOTREACHED to hit on a
282 // subsequent OpenKey call.
283 TEST_F(RegistryTest, SameWowFlags) {
284 RegKey key;
286 ASSERT_EQ(ERROR_SUCCESS,
287 key.Open(HKEY_LOCAL_MACHINE,
288 L"Software",
289 KEY_READ | KEY_WOW64_64KEY));
290 ASSERT_EQ(ERROR_SUCCESS,
291 key.OpenKey(L"Microsoft",
292 KEY_READ | KEY_WOW64_64KEY));
293 ASSERT_EQ(ERROR_SUCCESS,
294 key.OpenKey(L"Windows",
295 KEY_READ | KEY_WOW64_64KEY));
298 // TODO(wfh): flaky test on Vista. See http://crbug.com/377917
299 TEST_F(RegistryTest, DISABLED_Wow64NativeFromRedirected) {
300 if (!IsRedirectorPresent())
301 return;
302 RegKey key;
304 // Test non-redirected key access from redirected.
305 ASSERT_EQ(ERROR_SUCCESS,
306 key.Create(HKEY_LOCAL_MACHINE,
307 foo_software_key_.c_str(),
308 KEY_WRITE | kNativeViewMask));
309 ASSERT_EQ(ERROR_SUCCESS,
310 key.Open(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(), KEY_READ));
311 ASSERT_NE(ERROR_SUCCESS,
312 key.Open(HKEY_LOCAL_MACHINE,
313 foo_software_key_.c_str(),
314 KEY_READ | kRedirectedViewMask));
316 // Open the redirected view of the parent and try to delete the test key
317 // from the non-redirected view.
318 ASSERT_EQ(ERROR_SUCCESS,
319 key.Open(HKEY_LOCAL_MACHINE,
320 L"Software",
321 KEY_SET_VALUE | kRedirectedViewMask));
322 ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
324 ASSERT_EQ(ERROR_SUCCESS,
325 key.Open(HKEY_LOCAL_MACHINE,
326 L"Software",
327 KEY_SET_VALUE | kNativeViewMask));
328 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
331 TEST_F(RegistryTest, OpenSubKey) {
332 RegKey key;
333 ASSERT_EQ(ERROR_SUCCESS,
334 key.Open(HKEY_CURRENT_USER,
335 kRootKey,
336 KEY_READ | KEY_CREATE_SUB_KEY));
338 ASSERT_NE(ERROR_SUCCESS, key.OpenKey(L"foo", KEY_READ));
339 ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"foo", KEY_READ));
340 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
341 ASSERT_EQ(ERROR_SUCCESS, key.OpenKey(L"foo", KEY_READ));
343 std::wstring foo_key(kRootKey);
344 foo_key += L"\\Foo";
345 ASSERT_EQ(ERROR_SUCCESS,
346 key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
348 ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
349 ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"foo"));
352 } // namespace
354 } // namespace win
355 } // namespace base