Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(432)

Side by Side Diff: chrome/browser/rlz/rlz_unittest.cc

Issue 7736001: Adding unit tests to RLZ code. Refactoring RLZ code to make it more testable. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Removing all references to headless envvar Created 9 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/rlz/rlz.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/rlz/rlz.h" 5 #include "chrome/browser/rlz/rlz.h"
6 6
7 #include "base/memory/scoped_ptr.h"
8 #include "base/stringprintf.h"
7 #include "base/path_service.h" 9 #include "base/path_service.h"
10 #include "base/test/test_reg_util_win.h"
11 #include "base/utf_string_conversions.h"
8 #include "base/win/registry.h" 12 #include "base/win/registry.h"
13 #include "chrome/browser/autocomplete/autocomplete.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/chrome_notification_types.h"
16 #include "chrome/common/env_vars.h"
17 #include "chrome/installer/util/browser_distribution.h"
18 #include "chrome/installer/util/google_update_constants.h"
19 #include "content/browser/tab_contents/navigation_entry.h"
20 #include "content/common/notification_details.h"
21 #include "content/common/notification_service.h"
22 #include "content/common/notification_source.h"
9 #include "testing/gtest/include/gtest/gtest.h" 23 #include "testing/gtest/include/gtest/gtest.h"
10 24
11 using base::win::RegKey; 25 using base::win::RegKey;
26 using registry_util::RegistryOverrideManager;
27 using testing::AssertionResult;
28 using testing::AssertionSuccess;
29 using testing::AssertionFailure;
12 30
13 namespace { 31 namespace {
14 32
15 // Gets rid of registry leftovers from testing. Returns false if there 33 // Registry path to overridden hive.
16 // is nothing to clean. 34 const wchar_t kRlzTempHkcu[] = L"rlz_hkcu";
17 bool CleanValue(const wchar_t* key_name, const wchar_t* value) { 35 const wchar_t kRlzTempHklm[] = L"rlz_hklm";
18 RegKey key; 36
19 if (key.Open(HKEY_CURRENT_USER, key_name, KEY_READ | KEY_WRITE) != 37 // Dummy RLZ string for the access points.
20 ERROR_SUCCESS) 38 const char kOmniboxRlzString[] = "test_omnibox";
21 return false; 39 const char kHomepageRlzString[] = "test_homepage";
22 EXPECT_EQ(ERROR_SUCCESS, key.DeleteValue(value)); 40
23 return true; 41 // Some helper macros to test it a string contains/does not contain a substring.
24 } 42
25 43 AssertionResult CmpHelperSTRC(const char* str_expression,
26 // The chrome events RLZ key lives here. 44 const char* substr_expression,
27 const wchar_t kKeyName[] = L"Software\\Google\\Common\\Rlz\\Events\\C"; 45 const char* str,
46 const char* substr) {
47 if (NULL != strstr(str, substr)) {
48 return AssertionSuccess();
49 }
50
51 return AssertionFailure() << "Expected: (" << substr_expression << ") in ("
52 << str_expression << "), actual: '"
53 << substr << "' not in '" << str << "'";
54 }
55
56 AssertionResult CmpHelperSTRNC(const char* str_expression,
57 const char* substr_expression,
58 const char* str,
59 const char* substr) {
60 if (NULL == strstr(str, substr)) {
61 return AssertionSuccess();
62 }
63
64 return AssertionFailure() << "Expected: (" << substr_expression
65 << ") not in (" << str_expression << "), actual: '"
66 << substr << "' in '" << str << "'";
67 }
68
69 #define EXPECT_STR_CONTAINS(str, substr) \
70 EXPECT_PRED_FORMAT2(CmpHelperSTRC, str, substr)
71
72 #define EXPECT_STR_NOT_CONTAIN(str, substr) \
73 EXPECT_PRED_FORMAT2(CmpHelperSTRNC, str, substr)
28 74
29 } // namespace 75 } // namespace
30 76
31 TEST(RlzLibTest, RecordProductEvent) { 77 // Test class for RLZ tracker. Makes some member functions public and
32 DWORD recorded_value = 0; 78 // overrides others to make it easier to test.
33 EXPECT_TRUE(RLZTracker::RecordProductEvent(rlz_lib::CHROME, 79 class TestRLZTracker : public RLZTracker {
34 rlz_lib::CHROME_OMNIBOX, rlz_lib::FIRST_SEARCH)); 80 public:
35 const wchar_t kEvent1[] = L"C1F"; 81 using RLZTracker::DelayedInit;
36 RegKey key1; 82 using RLZTracker::Observe;
37 EXPECT_EQ(ERROR_SUCCESS, key1.Open(HKEY_CURRENT_USER, kKeyName, KEY_READ)); 83 using RLZTracker::RLZ_PAGETRANSITION_HOME_PAGE;
38 EXPECT_EQ(ERROR_SUCCESS, key1.ReadValueDW(kEvent1, &recorded_value)); 84
39 EXPECT_EQ(1, recorded_value); 85 TestRLZTracker() : pingnow_called_(false), assume_io_thread_(false) {
40 EXPECT_TRUE(CleanValue(kKeyName, kEvent1)); 86 set_tracker(this);
41 87 }
42 EXPECT_TRUE(RLZTracker::RecordProductEvent(rlz_lib::CHROME, 88
43 rlz_lib::CHROME_HOME_PAGE, rlz_lib::SET_TO_GOOGLE)); 89 virtual ~TestRLZTracker() {
44 const wchar_t kEvent2[] = L"C2S"; 90 set_tracker(NULL);
45 RegKey key2; 91 }
46 EXPECT_EQ(ERROR_SUCCESS, key2.Open(HKEY_CURRENT_USER, kKeyName, KEY_READ)); 92
47 DWORD value = 0; 93 bool pingnow_called() const {
48 EXPECT_EQ(ERROR_SUCCESS, key2.ReadValueDW(kEvent2, &recorded_value)); 94 return pingnow_called_;
49 EXPECT_EQ(1, recorded_value); 95 }
50 EXPECT_TRUE(CleanValue(kKeyName, kEvent2)); 96
51 } 97 bool assume_io_thread() const {
98 return assume_io_thread_;
99 }
100
101 void set_assume_io_thread(bool assume_io_thread) {
102 assume_io_thread_ = assume_io_thread;
103 }
104
105 private:
106 virtual void ScheduleDelayedInit(int delay) OVERRIDE {
107 // If the delay is 0, invoke the delayed init now. Otherwise,
108 // don't schedule anything, it will be manually called during tests.
109 if (delay == 0)
110 DelayedInit();
111 }
112
113 virtual void ScheduleFinancialPing() OVERRIDE {
114 PingNow(this);
115 }
116
117 virtual bool ScheduleGetAccessPointRlz(rlz_lib::AccessPoint point) OVERRIDE {
118 return !assume_io_thread_;
119 }
120
121 virtual bool SendFinancialPing(const std::wstring& brand,
122 const std::wstring& lang,
123 const std::wstring& referral,
124 bool exclude_id) OVERRIDE {
125 // Don't ping the server during tests.
126 pingnow_called_ = true;
127 return true;
128 }
129
130 bool pingnow_called_;
131 bool assume_io_thread_;
132
133 DISALLOW_COPY_AND_ASSIGN(TestRLZTracker);
134 };
135
136 class RlzLibTest : public testing::Test {
137 virtual void SetUp() OVERRIDE;
138 virtual void TearDown() OVERRIDE;
139
140 protected:
141 void SimulateOmniboxUsage();
142 void SimulateHomepageUsage();
143 void InvokeDelayedInit();
144
145 void ExpectEventRecorded(const char* event_name, bool expected);
146 void ExpectRlzPingSent(bool expected);
147
148 TestRLZTracker tracker_;
149 RegistryOverrideManager override_manager_;
150 };
151
152 void RlzLibTest::SetUp() {
153 testing::Test::SetUp();
154
155 // Before overriding HKLM for the tests, we need to set it up correctly
156 // so that the rlz_lib calls work. This needs to be done before we do the
157 // override.
158
159 std::wstring temp_hklm_path = base::StringPrintf(
160 L"%ls\\%ls",
161 RegistryOverrideManager::kTempTestKeyPath,
162 kRlzTempHklm);
163
164 base::win::RegKey hklm;
165 ASSERT_EQ(ERROR_SUCCESS, hklm.Create(HKEY_CURRENT_USER,
166 temp_hklm_path.c_str(),
167 KEY_READ));
168
169 std::wstring temp_hkcu_path = base::StringPrintf(
170 L"%ls\\%ls",
171 RegistryOverrideManager::kTempTestKeyPath,
172 kRlzTempHkcu);
173
174 base::win::RegKey hkcu;
175 ASSERT_EQ(ERROR_SUCCESS, hkcu.Create(HKEY_CURRENT_USER,
176 temp_hkcu_path.c_str(),
177 KEY_READ));
178
179 rlz_lib::InitializeTempHivesForTesting(hklm, hkcu);
180
181 // Its important to override HKLM before HKCU because of the registry
182 // initialization performed above.
183 override_manager_.OverrideRegistry(HKEY_LOCAL_MACHINE, kRlzTempHklm);
184 override_manager_.OverrideRegistry(HKEY_CURRENT_USER, kRlzTempHkcu);
185
186 // Make sure a non-organic brand code is set in the registry or the RLZTracker
187 // is pretty much a no-op.
188 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
189 std::wstring reg_path = dist->GetStateKey();
190 RegKey key(HKEY_CURRENT_USER, reg_path.c_str(), KEY_SET_VALUE);
191 ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(google_update::kRegRLZBrandField,
192 L"TEST"));
193 }
194
195 void RlzLibTest::TearDown() {
196 testing::Test::TearDown();
197 }
198
199 void RlzLibTest::SimulateOmniboxUsage() {
200 tracker_.Observe(chrome::NOTIFICATION_OMNIBOX_OPENED_URL,
201 NotificationService::AllSources(),
202 Details<AutocompleteLog>(NULL));
203 }
204
205 void RlzLibTest::SimulateHomepageUsage() {
206 NavigationEntry entry(NULL, 0, GURL(), GURL(), string16(),
207 TestRLZTracker::RLZ_PAGETRANSITION_HOME_PAGE);
208 tracker_.Observe(content::NOTIFICATION_NAV_ENTRY_PENDING,
209 NotificationService::AllSources(),
210 Details<NavigationEntry>(&entry));
211 }
212
213 void RlzLibTest::InvokeDelayedInit() {
214 tracker_.DelayedInit();
215 }
216
217 void RlzLibTest::ExpectEventRecorded(const char* event_name, bool expected) {
218 char cgi[rlz_lib::kMaxCgiLength];
219 GetProductEventsAsCgi(rlz_lib::CHROME, cgi, arraysize(cgi));
220 if (expected) {
221 EXPECT_STR_CONTAINS(cgi, event_name);
222 } else {
223 EXPECT_STR_NOT_CONTAIN(cgi, event_name);
224 }
225 }
226
227 void RlzLibTest::ExpectRlzPingSent(bool expected) {
228 EXPECT_EQ(expected, tracker_.pingnow_called());
229 }
230
231 TEST_F(RlzLibTest, RecordProductEvent) {
232 RLZTracker::RecordProductEvent(rlz_lib::CHROME, rlz_lib::CHROME_OMNIBOX,
233 rlz_lib::FIRST_SEARCH);
234
235 ExpectEventRecorded("C1F", true);
236 }
237
238 // The events that affect the different RLZ scenarios are the following:
239 //
240 // A: the user starts chrome for the first time
241 // B: the user stops chrome
242 // C: the user start a subsequent time
243 // D: the user stops chrome again
244 // I: the RLZTracker::DelayedInit() method is invoked
245 // X: the user performs a search using the omnibox
246 // Y: the user performs a search using the home page
247 //
248 // The events A to D happen in chronological order, but the other events
249 // may happen at any point between A-B or C-D, in no particular order.
250 //
251 // The visible results of the scenarios are:
252 //
253 // C1I event is recorded
254 // C2I event is recorded
255 // C1F event is recorded
256 // C2F event is recorded
257 // C1S event is recorded
258 // C2S event is recorded
259 // RLZ ping sent
260 //
261 // Variations on the above scenarios:
262 //
263 // - if the delay specified to InitRlzDelayed() is negative, then the RLZ
264 // ping should be sent out at the time of event X and not wait for I
265 //
266 // Also want to test that pre-warming the RLZ string cache works correctly.
267
268 TEST_F(RlzLibTest, QuickStopAfterStart) {
269 RLZTracker::InitRlzDelayed(true, 20, true, true);
270
271 // Omnibox events.
272 ExpectEventRecorded("C1I", false);
273 ExpectEventRecorded("C1S", false);
274 ExpectEventRecorded("C1F", false);
275
276 // Home page events.
277 ExpectEventRecorded("C2I", false);
278 ExpectEventRecorded("C2S", false);
279 ExpectEventRecorded("C2F", false);
280
281 ExpectRlzPingSent(false);
282 }
283
284 TEST_F(RlzLibTest, DelayedInitOnly) {
285 RLZTracker::InitRlzDelayed(true, 20, true, true);
286 InvokeDelayedInit();
287
288 // Omnibox events.
289 ExpectEventRecorded("C1I", true);
290 ExpectEventRecorded("C1S", true);
291 ExpectEventRecorded("C1F", false);
292
293 // Home page events.
294 ExpectEventRecorded("C2I", true);
295 ExpectEventRecorded("C2S", true);
296 ExpectEventRecorded("C2F", false);
297
298 ExpectRlzPingSent(true);
299 }
300
301 TEST_F(RlzLibTest, DelayedInitOnlyNoFirstRunNoRlzStrings) {
302 RLZTracker::InitRlzDelayed(false, 20, true, true);
303 InvokeDelayedInit();
304
305 // Omnibox events.
306 ExpectEventRecorded("C1I", true);
307 ExpectEventRecorded("C1S", true);
308 ExpectEventRecorded("C1F", false);
309
310 // Home page events.
311 ExpectEventRecorded("C2I", true);
312 ExpectEventRecorded("C2S", true);
313 ExpectEventRecorded("C2F", false);
314
315 ExpectRlzPingSent(true);
316 }
317
318 TEST_F(RlzLibTest, DelayedInitOnlyNoFirstRun) {
319 // Set some dummy RLZ strings to simulate that we already ran before and
320 // performed a successful ping to the RLZ server.
321 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, kOmniboxRlzString);
322 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_HOME_PAGE, kHomepageRlzString);
323
324 RLZTracker::InitRlzDelayed(false, 20, true, true);
325 InvokeDelayedInit();
326
327 // Omnibox events.
328 ExpectEventRecorded("C1I", true);
329 ExpectEventRecorded("C1S", false);
330 ExpectEventRecorded("C1F", false);
331
332 // Home page events.
333 ExpectEventRecorded("C2I", true);
334 ExpectEventRecorded("C2S", false);
335 ExpectEventRecorded("C2F", false);
336
337 ExpectRlzPingSent(true);
338 }
339
340 TEST_F(RlzLibTest, DelayedInitOnlyNoGoogleDefaultSearchOrHomepage) {
341 RLZTracker::InitRlzDelayed(true, 20, false, false);
342 InvokeDelayedInit();
343
344 // Omnibox events.
345 ExpectEventRecorded("C1I", true);
346 ExpectEventRecorded("C1S", false);
347 ExpectEventRecorded("C1F", false);
348
349 // Home page events.
350 ExpectEventRecorded("C2I", true);
351 ExpectEventRecorded("C2S", false);
352 ExpectEventRecorded("C2F", false);
353
354 ExpectRlzPingSent(true);
355 }
356
357 TEST_F(RlzLibTest, OmniboxUsageOnly) {
358 RLZTracker::InitRlzDelayed(true, 20, true, true);
359 SimulateOmniboxUsage();
360
361 // Omnibox events.
362 ExpectEventRecorded("C1I", false);
363 ExpectEventRecorded("C1S", false);
364 ExpectEventRecorded("C1F", true);
365
366 // Home page events.
367 ExpectEventRecorded("C2I", false);
368 ExpectEventRecorded("C2S", false);
369 ExpectEventRecorded("C2F", false);
370
371 ExpectRlzPingSent(false);
372 }
373
374 TEST_F(RlzLibTest, HomepageUsageOnly) {
375 RLZTracker::InitRlzDelayed(true, 20, true, true);
376 SimulateHomepageUsage();
377
378 // Omnibox events.
379 ExpectEventRecorded("C1I", false);
380 ExpectEventRecorded("C1S", false);
381 ExpectEventRecorded("C1F", false);
382
383 // Home page events.
384 ExpectEventRecorded("C2I", false);
385 ExpectEventRecorded("C2S", false);
386 ExpectEventRecorded("C2F", true);
387
388 ExpectRlzPingSent(false);
389 }
390
391 TEST_F(RlzLibTest, UsageBeforeDelayedInit) {
392 RLZTracker::InitRlzDelayed(true, 20, true, true);
393 SimulateOmniboxUsage();
394 SimulateHomepageUsage();
395 InvokeDelayedInit();
396
397 // Omnibox events.
398 ExpectEventRecorded("C1I", true);
399 ExpectEventRecorded("C1S", true);
400 ExpectEventRecorded("C1F", true);
401
402 // Home page events.
403 ExpectEventRecorded("C2I", true);
404 ExpectEventRecorded("C2S", true);
405 ExpectEventRecorded("C2F", true);
406
407 ExpectRlzPingSent(true);
408 }
409
410 TEST_F(RlzLibTest, OmniboxUsageAfterDelayedInit) {
411 RLZTracker::InitRlzDelayed(true, 20, true, true);
412 InvokeDelayedInit();
413 SimulateOmniboxUsage();
414 SimulateHomepageUsage();
415
416 // Omnibox events.
417 ExpectEventRecorded("C1I", true);
418 ExpectEventRecorded("C1S", true);
419 ExpectEventRecorded("C1F", true);
420
421 // Home page events.
422 ExpectEventRecorded("C2I", true);
423 ExpectEventRecorded("C2S", true);
424 ExpectEventRecorded("C2F", true);
425
426 ExpectRlzPingSent(true);
427 }
428
429 TEST_F(RlzLibTest, OmniboxUsageSendsPingWhenDelayNegative) {
430 RLZTracker::InitRlzDelayed(true, -20, true, true);
431 SimulateOmniboxUsage();
432
433 // Omnibox events.
434 ExpectEventRecorded("C1I", true);
435 ExpectEventRecorded("C1S", true);
436 ExpectEventRecorded("C1F", true);
437
438 // Home page events.
439 ExpectEventRecorded("C2I", true);
440 ExpectEventRecorded("C2S", true);
441 ExpectEventRecorded("C2F", false);
442
443 ExpectRlzPingSent(true);
444 }
445
446 TEST_F(RlzLibTest, HomepageUsageDoesNotSendPingWhenDelayNegative) {
447 RLZTracker::InitRlzDelayed(true, -20, true, true);
448 SimulateHomepageUsage();
449
450 // Omnibox events.
451 ExpectEventRecorded("C1I", false);
452 ExpectEventRecorded("C1S", false);
453 ExpectEventRecorded("C1F", false);
454
455 // Home page events.
456 ExpectEventRecorded("C2I", false);
457 ExpectEventRecorded("C2S", false);
458 ExpectEventRecorded("C2F", true);
459
460 ExpectRlzPingSent(false);
461 }
462
463 TEST_F(RlzLibTest, GetAccessPointRlzOnIoThread) {
464 // Set dummy RLZ string.
465 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, kOmniboxRlzString);
466
467 std::wstring rlz;
468
469 tracker_.set_assume_io_thread(true);
470 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
471 EXPECT_STREQ(kOmniboxRlzString, WideToUTF8(rlz).c_str());
472 }
473
474 TEST_F(RlzLibTest, GetAccessPointRlzNotOnIoThread) {
475 // Set dummy RLZ string.
476 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, kOmniboxRlzString);
477
478 std::wstring rlz;
479
480 tracker_.set_assume_io_thread(false);
481 EXPECT_FALSE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
482 }
483
484 TEST_F(RlzLibTest, GetAccessPointRlzIsCached) {
485 // Set dummy RLZ string.
486 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, kOmniboxRlzString);
487
488 std::wstring rlz;
489
490 tracker_.set_assume_io_thread(false);
491 EXPECT_FALSE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
492
493 tracker_.set_assume_io_thread(true);
494 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
495 EXPECT_STREQ(kOmniboxRlzString, WideToUTF8(rlz).c_str());
496
497 tracker_.set_assume_io_thread(false);
498 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
499 EXPECT_STREQ(kOmniboxRlzString, WideToUTF8(rlz).c_str());
500 }
501
502 TEST_F(RlzLibTest, PingInvalidatesRlzCache) {
503 // Set dummy RLZ string.
504 rlz_lib::SetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, kOmniboxRlzString);
505
506 std::wstring rlz;
507
508 // Prime the cache.
509 tracker_.set_assume_io_thread(true);
510 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
511 EXPECT_STREQ(kOmniboxRlzString, WideToUTF8(rlz).c_str());
512
513 // Make sure cache is valid.
514 tracker_.set_assume_io_thread(false);
515 EXPECT_TRUE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
516 EXPECT_STREQ(kOmniboxRlzString, WideToUTF8(rlz).c_str());
517
518 // Perform ping.
519 RLZTracker::InitRlzDelayed(true, 20, true, true);
520 InvokeDelayedInit();
521 ExpectRlzPingSent(true);
522
523 // Make sure cache is now invalid.
524 EXPECT_FALSE(RLZTracker::GetAccessPointRlz(rlz_lib::CHROME_OMNIBOX, &rlz));
525 }
526
527 TEST_F(RlzLibTest, ObserveHandlesBadArgs) {
528 NavigationEntry entry(NULL, 0, GURL(), GURL(), string16(),
529 PageTransition::LINK);
530 tracker_.Observe(content::NOTIFICATION_NAV_ENTRY_PENDING,
531 NotificationService::AllSources(),
532 Details<NavigationEntry>(NULL));
533 tracker_.Observe(content::NOTIFICATION_NAV_ENTRY_PENDING,
534 NotificationService::AllSources(),
535 Details<NavigationEntry>(&entry));
536 }
OLDNEW
« no previous file with comments | « chrome/browser/rlz/rlz.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698