Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / chrome / browser / web_resource / promo_resource_service_unittest.cc
blob27568352ec20b76e23da5d84f786ac502c5860d0
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.
5 #include <utility>
6 #include <vector>
8 #include "base/json/json_reader.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/time/time.h"
15 #include "base/values.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/prefs/browser_prefs.h"
18 #include "chrome/browser/web_resource/notification_promo.h"
19 #include "chrome/browser/web_resource/promo_resource_service.h"
20 #include "chrome/common/pref_names.h"
21 #include "chrome/common/url_constants.h"
22 #include "chrome/test/base/scoped_testing_local_state.h"
23 #include "chrome/test/base/testing_browser_process.h"
24 #include "net/url_request/test_url_fetcher_factory.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "third_party/icu/source/i18n/unicode/smpdtfmt.h"
28 namespace {
30 const char kDateFormat[] = "dd MMM yyyy HH:mm:ss zzzz";
32 bool YearFromNow(double* date_epoch, std::string* date_string) {
33 *date_epoch = (base::Time::Now() + base::TimeDelta::FromDays(365)).ToTimeT();
35 UErrorCode status = U_ZERO_ERROR;
36 icu::SimpleDateFormat simple_formatter(icu::UnicodeString(kDateFormat),
37 icu::Locale("en_US"),
38 status);
39 if (!U_SUCCESS(status))
40 return false;
42 icu::UnicodeString date_unicode_string;
43 simple_formatter.format(static_cast<UDate>(*date_epoch * 1000),
44 date_unicode_string,
45 status);
46 if (!U_SUCCESS(status))
47 return false;
49 return base::UTF16ToUTF8(date_unicode_string.getBuffer(),
50 static_cast<size_t>(date_unicode_string.length()),
51 date_string);
54 } // namespace
56 class PromoResourceServiceTest : public testing::Test {
57 public:
58 // |promo_resource_service_| must be created after |local_state_|.
59 PromoResourceServiceTest()
60 : local_state_(TestingBrowserProcess::GetGlobal()),
61 promo_resource_service_(new PromoResourceService) {}
63 protected:
64 ScopedTestingLocalState local_state_;
65 scoped_ptr<PromoResourceService> promo_resource_service_;
66 base::MessageLoop loop_;
69 class NotificationPromoTest {
70 public:
71 NotificationPromoTest()
72 : received_notification_(false),
73 start_(0.0),
74 end_(0.0),
75 num_groups_(0),
76 initial_segment_(0),
77 increment_(1),
78 time_slice_(0),
79 max_group_(0),
80 max_views_(0),
81 closed_(false) {}
83 void Init(const std::string& json,
84 const std::string& promo_text,
85 double start,
86 int num_groups, int initial_segment, int increment,
87 int time_slice, int max_group, int max_views) {
88 double year_from_now_epoch;
89 std::string year_from_now_string;
90 ASSERT_TRUE(YearFromNow(&year_from_now_epoch, &year_from_now_string));
92 std::vector<std::string> replacements;
93 replacements.push_back(year_from_now_string);
95 std::string json_with_end_date(
96 base::ReplaceStringPlaceholders(json, replacements, NULL));
97 base::Value* value(base::JSONReader::DeprecatedRead(json_with_end_date));
98 ASSERT_TRUE(value);
100 base::DictionaryValue* dict = NULL;
101 value->GetAsDictionary(&dict);
102 ASSERT_TRUE(dict);
103 test_json_.reset(dict);
105 promo_type_ = NotificationPromo::NTP_NOTIFICATION_PROMO;
106 promo_text_ = promo_text;
108 start_ = start;
109 end_ = year_from_now_epoch;
111 num_groups_ = num_groups;
112 initial_segment_ = initial_segment;
113 increment_ = increment;
114 time_slice_ = time_slice;
115 max_group_ = max_group;
117 max_views_ = max_views;
119 closed_ = false;
120 received_notification_ = false;
123 void InitPromoFromJson(bool should_receive_notification) {
124 notification_promo_.InitFromJson(*test_json_, promo_type_);
125 EXPECT_EQ(should_receive_notification,
126 notification_promo_.new_notification());
128 // Test the fields.
129 TestNotification();
132 void TestNotification() {
133 // Check values.
134 EXPECT_EQ(notification_promo_.promo_text_, promo_text_);
136 EXPECT_EQ(notification_promo_.start_, start_);
137 EXPECT_EQ(notification_promo_.end_, end_);
139 EXPECT_EQ(notification_promo_.num_groups_, num_groups_);
140 EXPECT_EQ(notification_promo_.initial_segment_, initial_segment_);
141 EXPECT_EQ(notification_promo_.increment_, increment_);
142 EXPECT_EQ(notification_promo_.time_slice_, time_slice_);
143 EXPECT_EQ(notification_promo_.max_group_, max_group_);
145 EXPECT_EQ(notification_promo_.max_views_, max_views_);
146 EXPECT_EQ(notification_promo_.closed_, closed_);
148 // Check group within bounds.
149 EXPECT_GE(notification_promo_.group_, 0);
150 EXPECT_LT(notification_promo_.group_, num_groups_);
152 // Views should be 0 for now.
153 EXPECT_EQ(notification_promo_.views_, 0);
156 // Create a new NotificationPromo from prefs and compare to current
157 // notification.
158 void TestInitFromPrefs() {
159 NotificationPromo prefs_notification_promo;
160 prefs_notification_promo.InitFromPrefs(promo_type_);
162 EXPECT_EQ(notification_promo_.prefs_,
163 prefs_notification_promo.prefs_);
164 EXPECT_EQ(notification_promo_.promo_text_,
165 prefs_notification_promo.promo_text_);
166 EXPECT_EQ(notification_promo_.start_,
167 prefs_notification_promo.start_);
168 EXPECT_EQ(notification_promo_.end_,
169 prefs_notification_promo.end_);
170 EXPECT_EQ(notification_promo_.num_groups_,
171 prefs_notification_promo.num_groups_);
172 EXPECT_EQ(notification_promo_.initial_segment_,
173 prefs_notification_promo.initial_segment_);
174 EXPECT_EQ(notification_promo_.increment_,
175 prefs_notification_promo.increment_);
176 EXPECT_EQ(notification_promo_.time_slice_,
177 prefs_notification_promo.time_slice_);
178 EXPECT_EQ(notification_promo_.max_group_,
179 prefs_notification_promo.max_group_);
180 EXPECT_EQ(notification_promo_.max_views_,
181 prefs_notification_promo.max_views_);
182 EXPECT_EQ(notification_promo_.group_,
183 prefs_notification_promo.group_);
184 EXPECT_EQ(notification_promo_.views_,
185 prefs_notification_promo.views_);
186 EXPECT_EQ(notification_promo_.closed_,
187 prefs_notification_promo.closed_);
190 void TestGroup() {
191 // Test out of range groups.
192 const int incr = num_groups_ / 20;
193 for (int i = max_group_; i < num_groups_; i += incr) {
194 notification_promo_.group_ = i;
195 EXPECT_FALSE(notification_promo_.CanShow());
198 // Test in-range groups.
199 for (int i = 0; i < max_group_; i += incr) {
200 notification_promo_.group_ = i;
201 EXPECT_TRUE(notification_promo_.CanShow());
204 // When max_group_ is 0, all groups pass.
205 notification_promo_.max_group_ = 0;
206 for (int i = 0; i < num_groups_; i += incr) {
207 notification_promo_.group_ = i;
208 EXPECT_TRUE(notification_promo_.CanShow());
210 notification_promo_.WritePrefs();
213 void TestViews() {
214 notification_promo_.views_ = notification_promo_.max_views_ - 2;
215 notification_promo_.WritePrefs();
217 NotificationPromo::HandleViewed(promo_type_);
218 NotificationPromo new_promo;
219 new_promo.InitFromPrefs(promo_type_);
220 EXPECT_EQ(new_promo.max_views_ - 1, new_promo.views_);
221 EXPECT_TRUE(new_promo.CanShow());
222 NotificationPromo::HandleViewed(promo_type_);
223 new_promo.InitFromPrefs(promo_type_);
224 EXPECT_EQ(new_promo.max_views_, new_promo.views_);
225 EXPECT_FALSE(new_promo.CanShow());
227 // Test out of range views.
228 for (int i = max_views_; i < max_views_ * 2; ++i) {
229 new_promo.views_ = i;
230 EXPECT_FALSE(new_promo.CanShow());
233 // Test in range views.
234 for (int i = 0; i < max_views_; ++i) {
235 new_promo.views_ = i;
236 EXPECT_TRUE(new_promo.CanShow());
238 new_promo.WritePrefs();
241 void TestClosed() {
242 NotificationPromo new_promo;
243 new_promo.InitFromPrefs(promo_type_);
244 EXPECT_FALSE(new_promo.closed_);
245 EXPECT_TRUE(new_promo.CanShow());
247 NotificationPromo::HandleClosed(promo_type_);
248 new_promo.InitFromPrefs(promo_type_);
249 EXPECT_TRUE(new_promo.closed_);
250 EXPECT_FALSE(new_promo.CanShow());
252 new_promo.closed_ = false;
253 EXPECT_TRUE(new_promo.CanShow());
254 new_promo.WritePrefs();
257 void TestPromoText() {
258 notification_promo_.promo_text_.clear();
259 EXPECT_FALSE(notification_promo_.CanShow());
261 notification_promo_.promo_text_ = promo_text_;
262 EXPECT_TRUE(notification_promo_.CanShow());
265 void TestTime() {
266 const double now = base::Time::Now().ToDoubleT();
267 const double qhour = 15 * 60;
269 notification_promo_.group_ = 0; // For simplicity.
271 notification_promo_.start_ = now - qhour;
272 notification_promo_.end_ = now + qhour;
273 EXPECT_TRUE(notification_promo_.CanShow());
275 // Start time has not arrived.
276 notification_promo_.start_ = now + qhour;
277 notification_promo_.end_ = now + qhour;
278 EXPECT_FALSE(notification_promo_.CanShow());
280 // End time has past.
281 notification_promo_.start_ = now - qhour;
282 notification_promo_.end_ = now - qhour;
283 EXPECT_FALSE(notification_promo_.CanShow());
285 notification_promo_.start_ = start_;
286 notification_promo_.end_ = end_;
287 EXPECT_TRUE(notification_promo_.CanShow());
290 void TestIncrement() {
291 const double now = base::Time::Now().ToDoubleT();
292 const double slice = 60;
294 notification_promo_.num_groups_ = 18;
295 notification_promo_.initial_segment_ = 5;
296 notification_promo_.increment_ = 3;
297 notification_promo_.time_slice_ = slice;
299 notification_promo_.start_ = now - 1;
300 notification_promo_.end_ = now + slice;
302 // Test initial segment.
303 notification_promo_.group_ = 4;
304 EXPECT_TRUE(notification_promo_.CanShow());
305 notification_promo_.group_ = 5;
306 EXPECT_FALSE(notification_promo_.CanShow());
308 // Test first increment.
309 notification_promo_.start_ -= slice;
310 notification_promo_.group_ = 7;
311 EXPECT_TRUE(notification_promo_.CanShow());
312 notification_promo_.group_ = 8;
313 EXPECT_FALSE(notification_promo_.CanShow());
315 // Test second increment.
316 notification_promo_.start_ -= slice;
317 notification_promo_.group_ = 10;
318 EXPECT_TRUE(notification_promo_.CanShow());
319 notification_promo_.group_ = 11;
320 EXPECT_FALSE(notification_promo_.CanShow());
322 // Test penultimate increment.
323 notification_promo_.start_ -= 2 * slice;
324 notification_promo_.group_ = 16;
325 EXPECT_TRUE(notification_promo_.CanShow());
326 notification_promo_.group_ = 17;
327 EXPECT_FALSE(notification_promo_.CanShow());
329 // Test last increment.
330 notification_promo_.start_ -= slice;
331 EXPECT_TRUE(notification_promo_.CanShow());
334 const NotificationPromo& promo() const { return notification_promo_; }
336 private:
337 NotificationPromo notification_promo_;
338 bool received_notification_;
339 scoped_ptr<base::DictionaryValue> test_json_;
341 NotificationPromo::PromoType promo_type_;
342 std::string promo_text_;
344 double start_;
345 double end_;
347 int num_groups_;
348 int initial_segment_;
349 int increment_;
350 int time_slice_;
351 int max_group_;
353 int max_views_;
355 bool closed_;
358 // Test that everything gets parsed correctly, notifications are sent,
359 // and CanShow() is handled correctly under variety of conditions.
360 // Additionally, test that the first string in |strings| is used if
361 // no payload.promo_short_message is specified in the JSON response.
362 TEST_F(PromoResourceServiceTest, NotificationPromoTest) {
363 // Check that prefs are set correctly.
364 NotificationPromoTest promo_test;
366 // Set up start date and promo line in a Dictionary as if parsed from the
367 // service. date[0].end is replaced with a date 1 year in the future.
368 promo_test.Init("{"
369 " \"ntp_notification_promo\": ["
370 " {"
371 " \"date\":"
372 " ["
373 " {"
374 " \"start\":\"3 Aug 1999 9:26:06 GMT\","
375 " \"end\":\"$1\""
376 " }"
377 " ],"
378 " \"strings\":"
379 " {"
380 " \"NTP4_HOW_DO_YOU_FEEL_ABOUT_CHROME\":"
381 " \"What do you think of Chrome?\""
382 " },"
383 " \"grouping\":"
384 " {"
385 " \"buckets\":1000,"
386 " \"segment\":200,"
387 " \"increment\":100,"
388 " \"increment_frequency\":3600,"
389 " \"increment_max\":400"
390 " },"
391 " \"payload\":"
392 " {"
393 " \"days_active\":7,"
394 " \"install_age_days\":21"
395 " },"
396 " \"max_views\":30"
397 " }"
398 " ]"
399 "}",
400 "What do you think of Chrome?",
401 // The starting date is in 1999 to make tests pass
402 // on Android devices with incorrect or unset date/time.
403 933672366, // unix epoch for 3 Aug 1999 9:26:06 GMT.
404 1000, 200, 100, 3600, 400, 30);
406 promo_test.InitPromoFromJson(true);
408 // Second time should not trigger a notification.
409 promo_test.InitPromoFromJson(false);
411 promo_test.TestInitFromPrefs();
413 // Test various conditions of CanShow.
414 // TestGroup Has the side effect of setting us to a passing group.
415 promo_test.TestGroup();
416 promo_test.TestViews();
417 promo_test.TestClosed();
418 promo_test.TestPromoText();
419 promo_test.TestTime();
420 promo_test.TestIncrement();
423 // Test that payload.promo_message_short is used if present.
424 TEST_F(PromoResourceServiceTest, NotificationPromoCompatNoStringsTest) {
425 // Check that prefs are set correctly.
426 NotificationPromoTest promo_test;
428 // Set up start date and promo line in a Dictionary as if parsed from the
429 // service. date[0].end is replaced with a date 1 year in the future.
430 promo_test.Init("{"
431 " \"ntp_notification_promo\": ["
432 " {"
433 " \"date\":"
434 " ["
435 " {"
436 " \"start\":\"3 Aug 1999 9:26:06 GMT\","
437 " \"end\":\"$1\""
438 " }"
439 " ],"
440 " \"grouping\":"
441 " {"
442 " \"buckets\":1000,"
443 " \"segment\":200,"
444 " \"increment\":100,"
445 " \"increment_frequency\":3600,"
446 " \"increment_max\":400"
447 " },"
448 " \"payload\":"
449 " {"
450 " \"promo_message_short\":"
451 " \"What do you think of Chrome?\","
452 " \"days_active\":7,"
453 " \"install_age_days\":21"
454 " },"
455 " \"max_views\":30"
456 " }"
457 " ]"
458 "}",
459 "What do you think of Chrome?",
460 // The starting date is in 1999 to make tests pass
461 // on Android devices with incorrect or unset date/time.
462 933672366, // unix epoch for 3 Aug 1999 9:26:06 GMT.
463 1000, 200, 100, 3600, 400, 30);
465 promo_test.InitPromoFromJson(true);
466 // Second time should not trigger a notification.
467 promo_test.InitPromoFromJson(false);
468 promo_test.TestInitFromPrefs();
471 // Test that strings.|payload.promo_message_short| is used if present.
472 TEST_F(PromoResourceServiceTest, NotificationPromoCompatPayloadStringsTest) {
473 // Check that prefs are set correctly.
474 NotificationPromoTest promo_test;
476 // Set up start date and promo line in a Dictionary as if parsed from the
477 // service. date[0].end is replaced with a date 1 year in the future.
478 promo_test.Init("{"
479 " \"ntp_notification_promo\": ["
480 " {"
481 " \"date\":"
482 " ["
483 " {"
484 " \"start\":\"3 Aug 1999 9:26:06 GMT\","
485 " \"end\":\"$1\""
486 " }"
487 " ],"
488 " \"grouping\":"
489 " {"
490 " \"buckets\":1000,"
491 " \"segment\":200,"
492 " \"increment\":100,"
493 " \"increment_frequency\":3600,"
494 " \"increment_max\":400"
495 " },"
496 " \"strings\":"
497 " {"
498 " \"bogus\":\"string\","
499 " \"GOOD_STRING\":"
500 " \"What do you think of Chrome?\""
501 " },"
502 " \"payload\":"
503 " {"
504 " \"promo_message_short\":"
505 " \"GOOD_STRING\","
506 " \"days_active\":7,"
507 " \"install_age_days\":21"
508 " },"
509 " \"max_views\":30"
510 " }"
511 " ]"
512 "}",
513 "What do you think of Chrome?",
514 // The starting date is in 1999 to make tests pass
515 // on Android devices with incorrect or unset date/time.
516 933672366, // unix epoch for 3 Aug 1999 9:26:06 GMT.
517 1000, 200, 100, 3600, 400, 30);
519 promo_test.InitPromoFromJson(true);
520 // Second time should not trigger a notification.
521 promo_test.InitPromoFromJson(false);
522 promo_test.TestInitFromPrefs();
525 TEST_F(PromoResourceServiceTest, PromoServerURLTest) {
526 GURL promo_server_url = NotificationPromo::PromoServerURL();
527 EXPECT_FALSE(promo_server_url.is_empty());
528 EXPECT_TRUE(promo_server_url.is_valid());
529 EXPECT_TRUE(promo_server_url.SchemeIs(url::kHttpsScheme));
530 // TODO(achuith): Test this better.
533 #if defined(ENABLE_APP_LIST)
534 TEST_F(PromoResourceServiceTest, AppLauncherPromoTest) {
535 // Check that prefs are set correctly.
536 NotificationPromoTest promo_test;
538 // Set up start date and promo line in a Dictionary as if parsed from the
539 // service. date[0].end is replaced with a date 1 year in the future.
540 promo_test.Init("{"
541 " \"ntp_notification_promo\": ["
542 " {"
543 " \"date\":"
544 " ["
545 " {"
546 " \"start\":\"3 Aug 1999 9:26:06 GMT\","
547 " \"end\":\"$1\""
548 " }"
549 " ],"
550 " \"grouping\":"
551 " {"
552 " \"buckets\":1000,"
553 " \"segment\":200,"
554 " \"increment\":100,"
555 " \"increment_frequency\":3600,"
556 " \"increment_max\":400"
557 " },"
558 " \"payload\":"
559 " {"
560 " \"promo_message_short\":"
561 " \"What do you think of Chrome?\","
562 " \"days_active\":7,"
563 " \"install_age_days\":21,"
564 " \"is_app_launcher_promo\":true"
565 " },"
566 " \"max_views\":30"
567 " }"
568 " ]"
569 "}",
570 "What do you think of Chrome?",
571 // The starting date is in 1999 to make tests pass
572 // on Android devices with incorrect or unset date/time.
573 933672366, // unix epoch for 3 Aug 1999 9:26:06 GMT.
574 1000, 200, 100, 3600, 400, 30);
575 promo_test.InitPromoFromJson(true);
576 local_state_.Get()->SetBoolean(prefs::kAppLauncherHasBeenEnabled, true);
577 EXPECT_FALSE(promo_test.promo().CanShow());
579 #endif