OLD | NEW |
| (Empty) |
1 // Copyright 2003-2010 Google Inc. | |
2 // | |
3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
4 // you may not use this file except in compliance with the License. | |
5 // You may obtain a copy of the License at | |
6 // | |
7 // http://www.apache.org/licenses/LICENSE-2.0 | |
8 // | |
9 // Unless required by applicable law or agreed to in writing, software | |
10 // distributed under the License is distributed on an "AS IS" BASIS, | |
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
12 // See the License for the specific language governing permissions and | |
13 // limitations under the License. | |
14 // ======================================================================== | |
15 | |
16 #include <ATLComTime.h> | |
17 #include <atltypes.h> | |
18 #include <atlwin.h> | |
19 #include <map> | |
20 #include <vector> | |
21 #include "omaha/base/app_util.h" | |
22 #include "omaha/base/atl_regexp.h" | |
23 #include "omaha/base/constants.h" | |
24 #include "omaha/base/dynamic_link_kernel32.h" | |
25 #include "omaha/base/file.h" | |
26 #include "omaha/base/module_utils.h" | |
27 #include "omaha/base/path.h" | |
28 #include "omaha/base/shell.h" | |
29 #include "omaha/base/string.h" | |
30 #include "omaha/base/time.h" | |
31 #include "omaha/base/user_info.h" | |
32 #include "omaha/base/utils.h" | |
33 #include "omaha/base/scoped_any.h" | |
34 #include "omaha/base/system_info.h" | |
35 #include "omaha/base/vistautil.h" | |
36 #include "omaha/testing/unit_test.h" | |
37 | |
38 namespace omaha { | |
39 | |
40 // Make sure that the time functions work. | |
41 TEST(UtilsTest, Time) { | |
42 // TODO(omaha): - add a test from string to time and back again. | |
43 // Further test the time converters. | |
44 time64 now = GetCurrent100NSTime(); | |
45 ASSERT_TRUE(StringToTime(TimeToString(now)) == now); | |
46 | |
47 // Test GetTimeCategory. | |
48 ASSERT_EQ(PAST, | |
49 GetTimeCategory(static_cast<time64>(0))); | |
50 ASSERT_EQ(PRESENT, | |
51 GetTimeCategory(static_cast<time64>(now))); | |
52 ASSERT_EQ(PRESENT, | |
53 GetTimeCategory(static_cast<time64>(now - kDaysTo100ns))); | |
54 ASSERT_EQ(PRESENT, | |
55 GetTimeCategory(static_cast<time64>(now - 365 * kDaysTo100ns))); | |
56 // A little bit in the future is also considered present. | |
57 ASSERT_EQ(PRESENT, | |
58 GetTimeCategory(static_cast<time64>(now + kDaysTo100ns))); | |
59 ASSERT_EQ(PRESENT, | |
60 GetTimeCategory(static_cast<time64>( | |
61 now - 30 * 365 * kDaysTo100ns))); | |
62 ASSERT_EQ(PAST, | |
63 GetTimeCategory(static_cast<time64>( | |
64 now - 50 * 365 * kDaysTo100ns))); | |
65 ASSERT_EQ(FUTURE, | |
66 GetTimeCategory(static_cast<time64>(now + kDaysTo100ns * 6))); | |
67 ASSERT_EQ(FUTURE, | |
68 GetTimeCategory(static_cast<time64>(now + 365 * kDaysTo100ns))); | |
69 | |
70 // Test IsValidTime. | |
71 ASSERT_FALSE(IsValidTime(static_cast<time64>(0))); | |
72 ASSERT_TRUE(IsValidTime(static_cast<time64>(now))); | |
73 ASSERT_TRUE(IsValidTime(static_cast<time64>(now - 365 * kDaysTo100ns))); | |
74 ASSERT_TRUE(IsValidTime(static_cast<time64>(now - 10 * 365 * kDaysTo100ns))); | |
75 ASSERT_TRUE(IsValidTime(static_cast<time64>(now + kDaysTo100ns))); | |
76 ASSERT_FALSE(IsValidTime(static_cast<time64>(now - 50 * 365 * kDaysTo100ns))); | |
77 ASSERT_FALSE(IsValidTime(static_cast<time64>(now + 50 * 365 * kDaysTo100ns))); | |
78 ASSERT_FALSE(IsValidTime(static_cast<time64>(now + kDaysTo100ns * 6))); | |
79 } | |
80 | |
81 TEST(UtilsTest, GetFolderPath_Success) { | |
82 CString path; | |
83 EXPECT_SUCCEEDED(GetFolderPath(CSIDL_PROGRAM_FILES, &path)); | |
84 BOOL isWow64 = FALSE; | |
85 EXPECT_SUCCEEDED(Kernel32::IsWow64Process(GetCurrentProcess(), &isWow64)); | |
86 CString expected_path = isWow64 ? | |
87 _T("C:\\Program Files (x86)") : _T("C:\\Program Files"); | |
88 EXPECT_STREQ(expected_path, path); | |
89 } | |
90 | |
91 TEST(UtilsTest, GetFolderPath_Errors) { | |
92 CString path; | |
93 EXPECT_EQ(E_INVALIDARG, GetFolderPath(0x7fff, &path)); | |
94 EXPECT_TRUE(path.IsEmpty()); | |
95 EXPECT_EQ(E_INVALIDARG, GetFolderPath(CSIDL_PROGRAM_FILES, NULL)); | |
96 } | |
97 | |
98 TEST(UtilsTest, CallEntryPoint0) { | |
99 HRESULT hr(E_FAIL); | |
100 ASSERT_FAILED(CallEntryPoint0(L"random-nonsense.dll", "foobar", &hr)); | |
101 } | |
102 | |
103 TEST(UtilsTest, ReadEntireFile) { | |
104 TCHAR directory[MAX_PATH] = {0}; | |
105 ASSERT_TRUE(GetModuleDirectory(NULL, directory)); | |
106 CString file_name; | |
107 file_name.Format(_T("%s\\unittest_support\\declaration.txt"), directory); | |
108 | |
109 std::vector<byte> buffer; | |
110 ASSERT_FAILED(ReadEntireFile(L"C:\\F00Bar\\ImaginaryFile", 0, &buffer)); | |
111 | |
112 ASSERT_SUCCEEDED(ReadEntireFile(file_name, 0, &buffer)); | |
113 ASSERT_EQ(9405, buffer.size()); | |
114 buffer.resize(0); | |
115 ASSERT_FAILED(ReadEntireFile(L"C:\\WINDOWS\\Greenstone.bmp", 1000, &buffer)); | |
116 } | |
117 | |
118 // TODO(omaha): Need a test for WriteEntireFile | |
119 // TEST(UtilsTest, WriteEntireFile) { | |
120 // } | |
121 | |
122 TEST(UtilsTest, RegSplitKeyvalueName) { | |
123 CString key_name, value_name; | |
124 ASSERT_SUCCEEDED(RegSplitKeyvalueName(CString(L"HKLM\\Foo\\"), | |
125 &key_name, | |
126 &value_name)); | |
127 ASSERT_STREQ(key_name, L"HKLM\\Foo"); | |
128 ASSERT_TRUE(value_name.IsEmpty()); | |
129 | |
130 ASSERT_SUCCEEDED(RegSplitKeyvalueName(CString(L"HKLM\\Foo\\(default)"), | |
131 &key_name, | |
132 &value_name)); | |
133 ASSERT_STREQ(key_name, L"HKLM\\Foo"); | |
134 ASSERT_TRUE(value_name.IsEmpty()); | |
135 | |
136 ASSERT_SUCCEEDED(RegSplitKeyvalueName(CString(L"HKLM\\Foo\\Bar"), | |
137 &key_name, | |
138 &value_name)); | |
139 ASSERT_STREQ(key_name, L"HKLM\\Foo"); | |
140 ASSERT_STREQ(value_name, L"Bar"); | |
141 } | |
142 | |
143 TEST(UtilsTest, ExpandEnvLikeStrings) { | |
144 std::map<CString, CString> mapping; | |
145 ASSERT_SUCCEEDED(Shell::GetSpecialFolderKeywordsMapping(&mapping)); | |
146 | |
147 CString out; | |
148 ASSERT_SUCCEEDED(ExpandEnvLikeStrings( | |
149 L"Foo%WINDOWS%Bar%SYSTEM%Zebra%WINDOWS%%SYSTEM%", mapping, &out)); | |
150 | |
151 // This should work, but CmpHelperSTRCASEEQ is not overloaded for wchars. | |
152 // ASSERT_STRCASEEQ(out, L"FooC:\\WINDOWSBarC:\\WINDOWS\\system32Zebra" | |
153 // L"C:\\WINDOWSC:\\WINDOWS\\system32"); | |
154 ASSERT_EQ(out.CompareNoCase(L"FooC:\\WINDOWSBarC:\\WINDOWS\\system32Zebra" | |
155 L"C:\\WINDOWSC:\\WINDOWS\\system32"), | |
156 0); | |
157 ASSERT_FAILED(ExpandEnvLikeStrings(L"Foo%WINDOWS%%BAR%Zebra", mapping, &out)); | |
158 } | |
159 | |
160 TEST(UtilsTest, GetCurrentProcessHandle) { | |
161 scoped_process proc; | |
162 ASSERT_SUCCEEDED(GetCurrentProcessHandle(address(proc))); | |
163 ASSERT_TRUE(valid(proc)); | |
164 } | |
165 | |
166 TEST(UtilsTest, DuplicateTokenIntoCurrentProcess) { | |
167 CAccessToken process_token; | |
168 EXPECT_TRUE(process_token.GetProcessToken(TOKEN_ALL_ACCESS)); | |
169 | |
170 CAccessToken duplicated_token; | |
171 EXPECT_SUCCEEDED(DuplicateTokenIntoCurrentProcess(::GetCurrentProcess(), | |
172 process_token.GetHandle(), | |
173 &duplicated_token)); | |
174 | |
175 CSid process_sid; | |
176 EXPECT_TRUE(process_token.GetUser(&process_sid)); | |
177 | |
178 CSid duplicated_sid; | |
179 EXPECT_TRUE(duplicated_token.GetUser(&duplicated_sid)); | |
180 | |
181 EXPECT_STREQ(process_sid.Sid(), duplicated_sid.Sid()); | |
182 } | |
183 | |
184 TEST(UtilsTest, IsGuid) { | |
185 EXPECT_FALSE(IsGuid(NULL)); | |
186 EXPECT_FALSE(IsGuid(_T(""))); | |
187 EXPECT_FALSE(IsGuid(_T("{}"))); | |
188 EXPECT_FALSE(IsGuid(_T("a"))); | |
189 EXPECT_FALSE(IsGuid(_T("CA3045BFA6B14fb8A0EFA615CEFE452C"))); | |
190 | |
191 // Missing {} | |
192 EXPECT_FALSE(IsGuid(_T("CA3045BF-A6B1-4fb8-A0EF-A615CEFE452C"))); | |
193 | |
194 // Invalid char X | |
195 EXPECT_FALSE(IsGuid(_T("{XA3045BF-A6B1-4fb8-A0EF-A615CEFE452C}"))); | |
196 | |
197 // Invalid binary char 0x200 | |
198 EXPECT_FALSE(IsGuid(_T("{\0x200a3045bf-a6b1-4fb8-a0ef-a615cefe452c}"))); | |
199 | |
200 // Missing - | |
201 EXPECT_FALSE(IsGuid(_T("{CA3045BFA6B14fb8A0EFA615CEFE452C}"))); | |
202 | |
203 // Double quotes | |
204 EXPECT_FALSE(IsGuid(_T("\"{ca3045bf-a6b1-4fb8-a0ef-a615cefe452c}\""))); | |
205 | |
206 EXPECT_TRUE(IsGuid(_T("{00000000-0000-0000-0000-000000000000}"))); | |
207 EXPECT_TRUE(IsGuid(_T("{CA3045BF-A6B1-4fb8-A0EF-A615CEFE452C}"))); | |
208 EXPECT_TRUE(IsGuid(_T("{ca3045bf-a6b1-4fb8-a0ef-a615cefe452c}"))); | |
209 } | |
210 | |
211 // GUIDs cannot be compared in GTest because there is no << operator. Therefore, | |
212 // we must treat them as strings. All these tests rely on GuidToString working. | |
213 #define EXPECT_GUID_EQ(expected, actual) \ | |
214 EXPECT_STREQ(GuidToString(expected), GuidToString(actual)) | |
215 | |
216 TEST(UtilsTest, StringToGuidSafe_InvalidString) { | |
217 GUID guid = {0}; | |
218 | |
219 EXPECT_EQ(E_INVALIDARG, StringToGuidSafe(_T(""), &guid)); | |
220 EXPECT_EQ(E_INVALIDARG, StringToGuidSafe(_T("{}"), &guid)); | |
221 EXPECT_EQ(E_INVALIDARG, StringToGuidSafe(_T("a"), &guid)); | |
222 EXPECT_EQ(E_INVALIDARG, | |
223 StringToGuidSafe(_T("CA3045BFA6B14fb8A0EFA615CEFE452C"), &guid)); | |
224 | |
225 // Missing {} | |
226 EXPECT_EQ(E_INVALIDARG, | |
227 StringToGuidSafe(_T("CA3045BF-A6B1-4fb8-A0EF-A615CEFE452C"), &guid)); | |
228 | |
229 // Invalid char X | |
230 EXPECT_EQ(CO_E_IIDSTRING, | |
231 StringToGuidSafe(_T("{XA3045BF-A6B1-4fb8-A0EF-A615CEFE452C}"), &guid)); | |
232 | |
233 // Invalid binary char 0x200 | |
234 EXPECT_EQ(E_INVALIDARG, | |
235 StringToGuidSafe(_T("{\0x200a3045bf-a6b1-4fb8-a0ef-a615cefe452c}"), | |
236 &guid)); | |
237 | |
238 // Missing - | |
239 EXPECT_EQ(E_INVALIDARG, | |
240 StringToGuidSafe(_T("{CA3045BFA6B14fb8A0EFA615CEFE452C}"), &guid)); | |
241 | |
242 // Double quotes | |
243 EXPECT_EQ(E_INVALIDARG, | |
244 StringToGuidSafe(_T("\"{ca3045bf-a6b1-4fb8-a0ef-a615cefe452c}\""), | |
245 &guid)); | |
246 } | |
247 | |
248 TEST(UtilsTest, StringToGuidSafe_ValidString) { | |
249 const GUID kExpectedGuid = {0xCA3045BF, 0xA6B1, 0x4FB8, | |
250 {0xA0, 0xEF, 0xA6, 0x15, 0xCE, 0xFE, 0x45, 0x2C}}; | |
251 GUID guid = kExpectedGuid; | |
252 | |
253 EXPECT_SUCCEEDED( | |
254 StringToGuidSafe(_T("{00000000-0000-0000-0000-000000000000}"), &guid)); | |
255 EXPECT_GUID_EQ(GUID_NULL, guid); | |
256 | |
257 guid = GUID_NULL; | |
258 EXPECT_SUCCEEDED( | |
259 StringToGuidSafe(_T("{CA3045BF-A6B1-4fb8-A0EF-A615CEFE452C}"), &guid)); | |
260 EXPECT_GUID_EQ(kExpectedGuid, guid); | |
261 | |
262 guid = GUID_NULL; | |
263 EXPECT_SUCCEEDED( | |
264 StringToGuidSafe(_T("{ca3045bf-a6b1-4fb8-a0ef-a615cefe452c}"), &guid)); | |
265 EXPECT_GUID_EQ(kExpectedGuid, guid); | |
266 } | |
267 | |
268 TEST(UtilsTest, VersionFromString_ValidVersion) { | |
269 EXPECT_EQ(MAKEDLLVERULL(42, 1, 21, 12345), | |
270 VersionFromString(_T("42.1.21.12345"))); | |
271 } | |
272 | |
273 TEST(UtilsTest, VersionFromString_VersionZero) { | |
274 EXPECT_EQ(0, VersionFromString(_T("0.0.0.0"))); | |
275 } | |
276 | |
277 TEST(UtilsTest, VersionFromString_VersionUpperLimits) { | |
278 EXPECT_EQ(MAKEDLLVERULL(0xffff, 0xffff, 0xffff, 0xffff), | |
279 VersionFromString(_T("65535.65535.65535.65535"))); | |
280 EXPECT_EQ(0, VersionFromString(_T("65536.65536.65536.65536"))); | |
281 EXPECT_EQ(0, VersionFromString(_T("1.2.65536.65536"))); | |
282 } | |
283 | |
284 TEST(UtilsTest, VersionFromString_IntegerOverflow) { | |
285 EXPECT_EQ(0, VersionFromString(_T("1.2.3.4294967296"))); | |
286 } | |
287 | |
288 TEST(UtilsTest, VersionFromString_NegativeVersion) { | |
289 EXPECT_EQ(0, VersionFromString(_T("1.2.3.-22"))); | |
290 } | |
291 | |
292 TEST(UtilsTest, VersionFromString_TooFewElements) { | |
293 EXPECT_EQ(0, VersionFromString(_T("1.1.1"))); | |
294 } | |
295 | |
296 TEST(UtilsTest, VersionFromString_ExtraPeriod) { | |
297 EXPECT_EQ(0, VersionFromString(_T("1.1.2.3."))); | |
298 } | |
299 | |
300 TEST(UtilsTest, VersionFromString_TooManyElements) { | |
301 EXPECT_EQ(0, VersionFromString(_T("1.1.2.3.4"))); | |
302 } | |
303 | |
304 TEST(UtilsTest, VersionFromString_Char) { | |
305 EXPECT_EQ(0, VersionFromString(_T("1.B.3.4"))); | |
306 EXPECT_EQ(0, VersionFromString(_T("1.2.3.B"))); | |
307 EXPECT_EQ(0, VersionFromString(_T("1.2.3.9B"))); | |
308 } | |
309 | |
310 TEST(UtilsTest, StringFromVersion_ValidVersion) { | |
311 EXPECT_STREQ(_T("42.1.21.12345"), | |
312 StringFromVersion(MAKEDLLVERULL(42, 1, 21, 12345))); | |
313 } | |
314 | |
315 TEST(UtilsTest, StringFromVersion_VersionZero) { | |
316 EXPECT_STREQ(_T("0.0.0.0"), StringFromVersion(0)); | |
317 } | |
318 | |
319 TEST(UtilsTest, StringFromVersion_VersionUpperLimits) { | |
320 EXPECT_STREQ( | |
321 _T("65535.65535.65535.65535"), | |
322 StringFromVersion(MAKEDLLVERULL(0xffff, 0xffff, 0xffff, 0xffff))); | |
323 } | |
324 | |
325 TEST(UtilsTest, IsLocalSystemSid) { | |
326 EXPECT_TRUE(IsLocalSystemSid(kLocalSystemSid)); | |
327 EXPECT_TRUE(IsLocalSystemSid(_T("S-1-5-18"))); | |
328 EXPECT_TRUE(IsLocalSystemSid(_T("s-1-5-18"))); | |
329 | |
330 EXPECT_FALSE(IsLocalSystemSid(_T(""))); | |
331 EXPECT_FALSE(IsLocalSystemSid(_T("S-1-5-17"))); | |
332 } | |
333 | |
334 // There is a very small probability the test could fail. | |
335 TEST(UtilsTest, GenRandom) { | |
336 int random_int = 0; | |
337 EXPECT_TRUE(GenRandom(&random_int, sizeof(random_int))); | |
338 EXPECT_NE(random_int, 0); | |
339 | |
340 int another_random_int = 0; | |
341 EXPECT_TRUE(GenRandom(&another_random_int, sizeof(another_random_int))); | |
342 EXPECT_NE(another_random_int, 0); | |
343 | |
344 EXPECT_NE(random_int, another_random_int); | |
345 } | |
346 | |
347 // Counts instances of the class. | |
348 class Counter { | |
349 public: | |
350 Counter() { | |
351 ++instance_count_; | |
352 } | |
353 ~Counter() { | |
354 --instance_count_; | |
355 } | |
356 static int instance_count() { return instance_count_; } | |
357 private: | |
358 static int instance_count_; | |
359 DISALLOW_EVIL_CONSTRUCTORS(Counter); | |
360 }; | |
361 | |
362 int Counter::instance_count_ = 0; | |
363 | |
364 // Checks if the functor is actually calling the destructor of the type. | |
365 TEST(UtilsTest, DeleteFun) { | |
366 EXPECT_EQ(Counter::instance_count(), 0); | |
367 Counter* counter = new Counter; | |
368 EXPECT_EQ(Counter::instance_count(), 1); | |
369 DeleteFun().operator()(counter); | |
370 EXPECT_EQ(Counter::instance_count(), 0); | |
371 | |
372 // Checks if the template can be instantiated for some common built in types. | |
373 int* pointer_int = NULL; | |
374 DeleteFun().operator()(pointer_int); | |
375 | |
376 const char* pointer_char = NULL; | |
377 DeleteFun().operator()(pointer_char); | |
378 } | |
379 | |
380 TEST(UtilsTest, IsUserLoggedOn) { | |
381 bool is_logged_on(false); | |
382 ASSERT_HRESULT_SUCCEEDED(IsUserLoggedOn(&is_logged_on)); | |
383 ASSERT_TRUE(is_logged_on); | |
384 } | |
385 | |
386 TEST(UtilsTest, IsClickOnceDisabled) { | |
387 EXPECT_FALSE(IsClickOnceDisabled()); | |
388 } | |
389 | |
390 TEST(UtilsTest, ConfigureRunAtStartup) { | |
391 const TCHAR kRunKeyPath[] = | |
392 _T("HKCU\\Software\\Microsoft\\Windows\\CurrentVersion\\Run"); | |
393 | |
394 RegKey::DeleteKey(kRegistryHiveOverrideRoot, true); | |
395 OverrideRegistryHives(kRegistryHiveOverrideRoot); | |
396 | |
397 EXPECT_FALSE(RegKey::HasKey(kRunKeyPath)); | |
398 | |
399 EXPECT_EQ(HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND), | |
400 ConfigureRunAtStartup(USER_KEY_NAME, _T("FooApp"), | |
401 _T("\"foo.exe\""), false)); | |
402 EXPECT_FALSE(RegKey::HasKey(kRunKeyPath)); | |
403 | |
404 EXPECT_SUCCEEDED(ConfigureRunAtStartup(USER_KEY_NAME, _T("FooApp"), | |
405 _T("\"C:\\foo.exe\" /x"), true)); | |
406 CString value; | |
407 EXPECT_SUCCEEDED(RegKey::GetValue(kRunKeyPath, _T("FooApp"), &value)); | |
408 EXPECT_STREQ(_T("\"C:\\foo.exe\" /x"), value); | |
409 | |
410 EXPECT_SUCCEEDED(ConfigureRunAtStartup(USER_KEY_NAME, _T("FooApp"), | |
411 _T("\"foo.exe\""), false)); | |
412 EXPECT_FALSE(RegKey::HasValue(kRunKeyPath, _T("FooApp"))); | |
413 EXPECT_TRUE(RegKey::HasKey(kRunKeyPath)); | |
414 | |
415 RestoreRegistryHives(); | |
416 EXPECT_SUCCEEDED(RegKey::DeleteKey(kRegistryHiveOverrideRoot, true)); | |
417 } | |
418 | |
419 TEST(UtilsTest, ValidPath) { | |
420 CString cmd_line = | |
421 _T("\"C:\\Program Files\\Internet Explorer\\iexplore.exe\" -nohome"); | |
422 CString exe_path; | |
423 EXPECT_SUCCEEDED(GetExePathFromCommandLine(cmd_line, &exe_path)); | |
424 EXPECT_STREQ(_T("C:\\Program Files\\Internet Explorer\\iexplore.exe"), | |
425 exe_path); | |
426 } | |
427 | |
428 TEST(UtilsTest, InvalidPath) { | |
429 CString cmd_line = _T(""); | |
430 CString exe_path; | |
431 EXPECT_FAILED(GetExePathFromCommandLine(cmd_line, &exe_path)); | |
432 EXPECT_TRUE(exe_path.IsEmpty()); | |
433 } | |
434 | |
435 TEST(UtilsTest, PinModuleIntoProcess) { | |
436 const TCHAR module_name[] = _T("icmp.dll"); | |
437 const void* kNullModule = NULL; | |
438 | |
439 // The module should not be loaded at this time. | |
440 EXPECT_EQ(kNullModule, ::GetModuleHandle(module_name)); | |
441 | |
442 // Loads and unloads the module. | |
443 { | |
444 scoped_library module(::LoadLibrary(module_name)); | |
445 EXPECT_TRUE(module); | |
446 EXPECT_NE(kNullModule, ::GetModuleHandle(module_name)); | |
447 } | |
448 EXPECT_EQ(kNullModule, ::GetModuleHandle(module_name)); | |
449 | |
450 // Loads, pins, and unloads the module. | |
451 { | |
452 scoped_library module(::LoadLibrary(module_name)); | |
453 EXPECT_TRUE(module); | |
454 EXPECT_NE(kNullModule, ::GetModuleHandle(module_name)); | |
455 PinModuleIntoProcess(module_name); | |
456 } | |
457 EXPECT_NE(kNullModule, ::GetModuleHandle(module_name)); | |
458 } | |
459 | |
460 // Assumes Windows is installed on the C: drive. | |
461 TEST(UtilsTest, GetEnvironmentVariableAsString) { | |
462 EXPECT_STREQ(_T("C:"), GetEnvironmentVariableAsString(_T("SystemDrive"))); | |
463 EXPECT_STREQ(_T("Windows_NT"), GetEnvironmentVariableAsString(_T("OS"))); | |
464 EXPECT_STREQ(_T(""), GetEnvironmentVariableAsString(_T("FOO"))); | |
465 } | |
466 | |
467 TEST(UtilsTest, IsWindowsInstalling_Normal) { | |
468 EXPECT_FALSE(IsWindowsInstalling()); | |
469 } | |
470 | |
471 TEST(UtilsTest, IsWindowsInstalling_Installing_Vista_InvalidValues) { | |
472 if (!vista_util::IsVistaOrLater()) { | |
473 return; | |
474 } | |
475 | |
476 RegKey::DeleteKey(kRegistryHiveOverrideRoot, true); | |
477 OverrideRegistryHives(kRegistryHiveOverrideRoot); | |
478 | |
479 EXPECT_SUCCEEDED(RegKey::SetValue( | |
480 _T("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State"), | |
481 _T("ImageState"), | |
482 _T(""))); | |
483 EXPECT_FALSE(IsWindowsInstalling()); | |
484 | |
485 EXPECT_SUCCEEDED(RegKey::SetValue( | |
486 _T("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State"), | |
487 _T("ImageState"), | |
488 _T("foo"))); | |
489 EXPECT_FALSE(IsWindowsInstalling()); | |
490 | |
491 EXPECT_SUCCEEDED(RegKey::SetValue( | |
492 _T("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State"), | |
493 _T("ImageState"), | |
494 static_cast<DWORD>(1))); | |
495 ExpectAsserts expect_asserts; // RegKey asserts because value type is wrong. | |
496 EXPECT_FALSE(IsWindowsInstalling()); | |
497 | |
498 RestoreRegistryHives(); | |
499 EXPECT_SUCCEEDED(RegKey::DeleteKey(kRegistryHiveOverrideRoot, true)); | |
500 } | |
501 | |
502 TEST(UtilsTest, IsWindowsInstalling_Installing_Vista_ValidStates) { | |
503 if (!vista_util::IsVistaOrLater()) { | |
504 return; | |
505 } | |
506 | |
507 RegKey::DeleteKey(kRegistryHiveOverrideRoot, true); | |
508 OverrideRegistryHives(kRegistryHiveOverrideRoot); | |
509 | |
510 // These states return false in the original implementation. | |
511 EXPECT_SUCCEEDED(RegKey::SetValue( | |
512 _T("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State"), | |
513 _T("ImageState"), | |
514 _T("IMAGE_STATE_COMPLETE"))); | |
515 EXPECT_FALSE(IsWindowsInstalling()); | |
516 | |
517 EXPECT_SUCCEEDED(RegKey::SetValue( | |
518 _T("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State"), | |
519 _T("ImageState"), | |
520 _T("IMAGE_STATE_GENERALIZE_RESEAL_TO_OOBE"))); | |
521 EXPECT_FALSE(IsWindowsInstalling()); | |
522 | |
523 EXPECT_SUCCEEDED(RegKey::SetValue( | |
524 _T("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State"), | |
525 _T("ImageState"), | |
526 _T("IMAGE_STATE_SPECIALIZE_RESEAL_TO_OOBE"))); | |
527 EXPECT_FALSE(IsWindowsInstalling()); | |
528 | |
529 // These states are specified in the original implementation. | |
530 EXPECT_SUCCEEDED(RegKey::SetValue( | |
531 _T("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State"), | |
532 _T("ImageState"), | |
533 _T("IMAGE_STATE_UNDEPLOYABLE"))); | |
534 EXPECT_TRUE(IsWindowsInstalling()); | |
535 | |
536 EXPECT_SUCCEEDED(RegKey::SetValue( | |
537 _T("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State"), | |
538 _T("ImageState"), | |
539 _T("IMAGE_STATE_GENERALIZE_RESEAL_TO_AUDIT"))); | |
540 EXPECT_TRUE(IsWindowsInstalling()); | |
541 | |
542 EXPECT_SUCCEEDED(RegKey::SetValue( | |
543 _T("HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Setup\\State"), | |
544 _T("ImageState"), | |
545 _T("IMAGE_STATE_SPECIALIZE_RESEAL_TO_AUDIT"))); | |
546 EXPECT_TRUE(IsWindowsInstalling()); | |
547 | |
548 RestoreRegistryHives(); | |
549 EXPECT_SUCCEEDED(RegKey::DeleteKey(kRegistryHiveOverrideRoot, true)); | |
550 } | |
551 | |
552 TEST(UtilsTest, AddAllowedAce) { | |
553 CString test_file_path = ConcatenatePath( | |
554 app_util::GetCurrentModuleDirectory(), _T("TestAddAllowedAce.exe")); | |
555 EXPECT_SUCCEEDED(File::Remove(test_file_path)); | |
556 | |
557 EXPECT_SUCCEEDED(File::Copy( | |
558 ConcatenatePath(app_util::GetCurrentModuleDirectory(), | |
559 _T("GoogleUpdate.exe")), | |
560 test_file_path, | |
561 false)); | |
562 | |
563 CDacl dacl; | |
564 EXPECT_TRUE(AtlGetDacl(test_file_path, SE_FILE_OBJECT, &dacl)); | |
565 const int original_ace_count = dacl.GetAceCount(); | |
566 | |
567 EXPECT_SUCCEEDED(AddAllowedAce(test_file_path, | |
568 SE_FILE_OBJECT, | |
569 Sids::Dialup(), | |
570 FILE_GENERIC_READ, | |
571 0)); | |
572 | |
573 dacl.SetEmpty(); | |
574 EXPECT_TRUE(AtlGetDacl(test_file_path, SE_FILE_OBJECT, &dacl)); | |
575 EXPECT_EQ(original_ace_count + 1, dacl.GetAceCount()); | |
576 | |
577 // Add the same access. No ACE is added. | |
578 EXPECT_SUCCEEDED(AddAllowedAce(test_file_path, | |
579 SE_FILE_OBJECT, | |
580 Sids::Dialup(), | |
581 FILE_GENERIC_READ, | |
582 0)); | |
583 dacl.SetEmpty(); | |
584 EXPECT_TRUE(AtlGetDacl(test_file_path, SE_FILE_OBJECT, &dacl)); | |
585 EXPECT_EQ(original_ace_count + 1, dacl.GetAceCount()); | |
586 | |
587 // Add a subset of the existing access. No ACE is added. | |
588 EXPECT_EQ(FILE_READ_ATTRIBUTES, FILE_GENERIC_READ & FILE_READ_ATTRIBUTES); | |
589 EXPECT_SUCCEEDED(AddAllowedAce(test_file_path, | |
590 SE_FILE_OBJECT, | |
591 Sids::Dialup(), | |
592 FILE_READ_ATTRIBUTES, | |
593 0)); | |
594 dacl.SetEmpty(); | |
595 EXPECT_TRUE(AtlGetDacl(test_file_path, SE_FILE_OBJECT, &dacl)); | |
596 EXPECT_EQ(original_ace_count + 1, dacl.GetAceCount()); | |
597 | |
598 // Add more access. An ACE is added. | |
599 EXPECT_SUCCEEDED(AddAllowedAce(test_file_path, | |
600 SE_FILE_OBJECT, | |
601 Sids::Dialup(), | |
602 FILE_ALL_ACCESS, | |
603 0)); | |
604 dacl.SetEmpty(); | |
605 EXPECT_TRUE(AtlGetDacl(test_file_path, SE_FILE_OBJECT, &dacl)); | |
606 EXPECT_EQ(original_ace_count + 2, dacl.GetAceCount()); | |
607 | |
608 // TODO(omaha): An assert occurs because the ACE flags are being used on a | |
609 // file object. Add a new test to use a registry key. | |
610 ExpectAsserts expect_asserts; | |
611 | |
612 // Different ACE flags. An ACE is added. | |
613 const BYTE kTestAce = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE; | |
614 const BYTE kTestAceSubset = CONTAINER_INHERIT_ACE; | |
615 EXPECT_SUCCEEDED(AddAllowedAce(test_file_path, | |
616 SE_FILE_OBJECT, | |
617 Sids::Dialup(), | |
618 FILE_ALL_ACCESS, | |
619 kTestAce)); | |
620 dacl.SetEmpty(); | |
621 EXPECT_TRUE(AtlGetDacl(test_file_path, SE_FILE_OBJECT, &dacl)); | |
622 EXPECT_EQ(original_ace_count + 3, dacl.GetAceCount()); | |
623 | |
624 // Subset of existing ACE flags. An ACE is added because flags must be exact. | |
625 EXPECT_SUCCEEDED(AddAllowedAce(test_file_path, | |
626 SE_FILE_OBJECT, | |
627 Sids::Dialup(), | |
628 FILE_ALL_ACCESS, | |
629 kTestAceSubset)); | |
630 dacl.SetEmpty(); | |
631 EXPECT_TRUE(AtlGetDacl(test_file_path, SE_FILE_OBJECT, &dacl)); | |
632 EXPECT_EQ(original_ace_count + 4, dacl.GetAceCount()); | |
633 | |
634 // Same flags. An ACE should not be added because all values match. | |
635 // TODO(omaha): This does not work, possibly because the object is a file. | |
636 // Try the test using a registry key. | |
637 EXPECT_SUCCEEDED(AddAllowedAce(test_file_path, | |
638 SE_FILE_OBJECT, | |
639 Sids::Dialup(), | |
640 FILE_ALL_ACCESS, | |
641 kTestAceSubset)); | |
642 dacl.SetEmpty(); | |
643 EXPECT_TRUE(AtlGetDacl(test_file_path, SE_FILE_OBJECT, &dacl)); | |
644 EXPECT_EQ(original_ace_count + 5, dacl.GetAceCount()); | |
645 | |
646 EXPECT_SUCCEEDED(File::Remove(test_file_path)); | |
647 } | |
648 | |
649 TEST(UtilsTest, CreateForegroundParentWindowForUAC) { | |
650 CWindow foreground_parent; | |
651 foreground_parent.Attach(CreateForegroundParentWindowForUAC()); | |
652 EXPECT_TRUE(foreground_parent.IsWindow()); | |
653 EXPECT_TRUE(foreground_parent.IsWindowVisible()); | |
654 | |
655 CRect foreground_rect; | |
656 EXPECT_TRUE(foreground_parent.GetWindowRect(&foreground_rect)); | |
657 EXPECT_EQ(0, foreground_rect.Width()); | |
658 EXPECT_EQ(0, foreground_rect.Height()); | |
659 | |
660 EXPECT_TRUE((WS_POPUP | WS_VISIBLE) & foreground_parent.GetStyle()); | |
661 EXPECT_TRUE(WS_EX_TOOLWINDOW & foreground_parent.GetExStyle()); | |
662 | |
663 EXPECT_TRUE(foreground_parent.DestroyWindow()); | |
664 } | |
665 | |
666 // Test the atomic exchange of pointer values. | |
667 TEST(UtilsTest, interlocked_exchange_pointer) { | |
668 const int i = 10; | |
669 const int j = 20; | |
670 | |
671 const int* volatile pi = &i; | |
672 const int* pj = &j; | |
673 | |
674 const int* old_pi = pi; | |
675 | |
676 // pi and pj point to i and j respectively. | |
677 EXPECT_EQ(10, *pi); | |
678 EXPECT_EQ(20, *pj); | |
679 | |
680 // After the exchange pi<-pj, both pointers point to the same value, in this | |
681 // case j. | |
682 int* result = interlocked_exchange_pointer(const_cast<int**>(&pi), pj); | |
683 EXPECT_EQ(*pj, *pi); | |
684 EXPECT_EQ(old_pi, result); | |
685 EXPECT_EQ(10, *old_pi); | |
686 EXPECT_EQ(20, *pi); | |
687 | |
688 // Exchanging a pointer with self is idempotent. | |
689 old_pi = interlocked_exchange_pointer(const_cast<int**>(&pi), pi); | |
690 EXPECT_EQ(pi, old_pi); | |
691 EXPECT_EQ(20, *pi); | |
692 | |
693 // Exchanging a pointer with NULL. | |
694 interlocked_exchange_pointer(const_cast<int**>(&pi), static_cast<int*>(NULL)); | |
695 EXPECT_EQ(NULL, pi); | |
696 } | |
697 | |
698 TEST(UtilsTest, GetGuid) { | |
699 CString guid; | |
700 EXPECT_HRESULT_SUCCEEDED(GetGuid(&guid)); | |
701 | |
702 // ATL regexp has many problems including: | |
703 // * not supporting {n} to repeat a previous item n times. | |
704 // * not allowing matching on - unless the items around the dash are | |
705 // enclosed in {}. | |
706 AtlRE guid_regex(_T("^{\\{{\\h\\h\\h\\h\\h\\h\\h\\h}-{\\h\\h\\h\\h}-{\\h\\h\\h
\\h}-{\\h\\h\\h\\h}-{\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h\\h}\\}}$")); // NOLINT | |
707 | |
708 CString matched_guid; | |
709 EXPECT_TRUE(AtlRE::PartialMatch(guid, guid_regex, &matched_guid)); | |
710 EXPECT_STREQ(guid, matched_guid); | |
711 | |
712 // Missing {}. | |
713 guid = _T("5F5280C6-9674-429b-9FEB-551914EF96B8"); | |
714 EXPECT_FALSE(AtlRE::PartialMatch(guid, guid_regex)); | |
715 | |
716 // Missing -. | |
717 guid = _T("{5F5280C6.9674-429b-9FEB-551914EF96B8}"); | |
718 EXPECT_FALSE(AtlRE::PartialMatch(guid, guid_regex)); | |
719 | |
720 // Whitespaces. | |
721 guid = _T(" {5F5280C6.9674-429b-9FEB-551914EF96B8}"); | |
722 EXPECT_FALSE(AtlRE::PartialMatch(guid, guid_regex)); | |
723 | |
724 guid = _T("{5F5280C6.9674-429b-9FEB-551914EF96B8} "); | |
725 EXPECT_FALSE(AtlRE::PartialMatch(guid, guid_regex)); | |
726 | |
727 // Empty string. | |
728 guid = _T(""); | |
729 EXPECT_FALSE(AtlRE::PartialMatch(guid, guid_regex)); | |
730 } | |
731 | |
732 TEST(UtilsTest, GetMessageForSystemErrorCode) { | |
733 CString message = GetMessageForSystemErrorCode(99); | |
734 EXPECT_TRUE(message.IsEmpty()); | |
735 | |
736 message = GetMessageForSystemErrorCode(ERROR_TOO_MANY_SEMAPHORES); | |
737 EXPECT_FALSE(message.IsEmpty()); | |
738 } | |
739 | |
740 TEST(UtilsTest, CeilingDivide) { | |
741 EXPECT_EQ(0, CeilingDivide(0, 1)); | |
742 EXPECT_EQ(1, CeilingDivide(1, 1)); | |
743 EXPECT_EQ(1, CeilingDivide(1, 2)); | |
744 EXPECT_EQ(2, CeilingDivide(6, 3)); | |
745 EXPECT_EQ(4, CeilingDivide(7, 2)); | |
746 } | |
747 | |
748 } // namespace omaha | |
749 | |
OLD | NEW |