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// A test application for the FinancialPing class.
6//
7// These tests should not be executed on the build server:
8// - They modify machine state (registry).
9//
10// These tests require write access to HKCU and HKLM.
11//
12// The "GGLA" brand is used to test the normal code flow of the code, and the
13// "TEST" brand is used to test the supplementary brand code code flow.  In one
14// case below, the brand "GOOG" is used because the code wants to use a brand
15// that is neither of the two mentioned above.
16
17#include "rlz/lib/financial_ping.h"
18
19#include "base/basictypes.h"
20#include "base/logging.h"
21#include "base/strings/string_util.h"
22#include "base/strings/stringprintf.h"
23#include "base/strings/utf_string_conversions.h"
24#include "rlz/lib/lib_values.h"
25#include "rlz/lib/machine_id.h"
26#include "rlz/lib/rlz_lib.h"
27#include "rlz/lib/rlz_value_store.h"
28#include "rlz/test/rlz_test_helpers.h"
29#include "testing/gmock/include/gmock/gmock.h"
30#include "testing/gtest/include/gtest/gtest.h"
31
32#if defined(OS_WIN)
33#include "rlz/win/lib/machine_deal.h"
34#else
35#include "base/time/time.h"
36#endif
37
38namespace {
39
40// Must match the implementation in file_time.cc.
41int64 GetSystemTimeAsInt64() {
42#if defined(OS_WIN)
43  FILETIME now_as_file_time;
44  GetSystemTimeAsFileTime(&now_as_file_time);
45  LARGE_INTEGER integer;
46  integer.HighPart = now_as_file_time.dwHighDateTime;
47  integer.LowPart = now_as_file_time.dwLowDateTime;
48  return integer.QuadPart;
49#else
50  double now_seconds = base::Time::Now().ToDoubleT();
51  return static_cast<int64>(now_seconds * 1000 * 1000 * 10);
52#endif
53}
54
55// Ping times in 100-nanosecond intervals.
56const int64 k1MinuteInterval = 60LL * 10000000LL;  // 1 minute
57
58}  // namespace anonymous
59
60class FinancialPingTest : public RlzLibTestBase {
61};
62
63TEST_F(FinancialPingTest, FormRequest) {
64  std::string brand_string = rlz_lib::SupplementaryBranding::GetBrand();
65  const char* brand = brand_string.empty() ? "GGLA" : brand_string.c_str();
66
67#if defined(OS_WIN)
68  EXPECT_TRUE(rlz_lib::MachineDealCode::Set("dcc_value"));
69#define DCC_PARAM "&dcc=dcc_value"
70#else
71#define DCC_PARAM ""
72#endif
73
74  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX,
75      "TbRlzValue"));
76
77  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
78  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
79      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
80  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
81      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
82
83  rlz_lib::AccessPoint points[] =
84    {rlz_lib::IETB_SEARCH_BOX, rlz_lib::NO_ACCESS_POINT,
85     rlz_lib::NO_ACCESS_POINT};
86
87  std::string machine_id;
88  bool got_machine_id = rlz_lib::GetMachineId(&machine_id);
89
90  std::string request;
91  EXPECT_TRUE(rlz_lib::FinancialPing::FormRequest(rlz_lib::TOOLBAR_NOTIFIER,
92      points, "swg", brand, NULL, "en", false, &request));
93  std::string expected_response;
94  base::StringAppendF(&expected_response,
95      "/tools/pso/ping?as=swg&brand=%s&hl=en&"
96      "events=I7S,W1I&rep=2&rlz=T4:TbRlzValue" DCC_PARAM
97, brand);
98
99  if (got_machine_id)
100    base::StringAppendF(&expected_response, "&id=%s", machine_id.c_str());
101  EXPECT_EQ(expected_response, request);
102
103  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, ""));
104  EXPECT_TRUE(rlz_lib::FinancialPing::FormRequest(rlz_lib::TOOLBAR_NOTIFIER,
105      points, "swg", brand, "IdOk2", NULL, false, &request));
106  expected_response.clear();
107  base::StringAppendF(&expected_response,
108      "/tools/pso/ping?as=swg&brand=%s&pid=IdOk2&"
109      "events=I7S,W1I&rep=2&rlz=T4:" DCC_PARAM, brand);
110
111  if (got_machine_id)
112    base::StringAppendF(&expected_response, "&id=%s", machine_id.c_str());
113  EXPECT_EQ(expected_response, request);
114
115  EXPECT_TRUE(rlz_lib::FinancialPing::FormRequest(rlz_lib::TOOLBAR_NOTIFIER,
116      points, "swg", brand, "IdOk", NULL, true, &request));
117  expected_response.clear();
118  base::StringAppendF(&expected_response,
119      "/tools/pso/ping?as=swg&brand=%s&pid=IdOk&"
120      "events=I7S,W1I&rep=2&rlz=T4:" DCC_PARAM, brand);
121  EXPECT_EQ(expected_response, request);
122
123  EXPECT_TRUE(rlz_lib::FinancialPing::FormRequest(rlz_lib::TOOLBAR_NOTIFIER,
124      points, "swg", brand, NULL, NULL, true, &request));
125  expected_response.clear();
126  base::StringAppendF(&expected_response,
127      "/tools/pso/ping?as=swg&brand=%s&events=I7S,W1I&rep=2"
128      "&rlz=T4:" DCC_PARAM, brand);
129  EXPECT_EQ(expected_response, request);
130
131
132  // Clear all events.
133  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
134
135  // Clear all RLZs.
136  char rlz[rlz_lib::kMaxRlzLength + 1];
137  for (int ap = rlz_lib::NO_ACCESS_POINT + 1;
138       ap < rlz_lib::LAST_ACCESS_POINT; ap++) {
139    rlz[0] = 0;
140    rlz_lib::AccessPoint point = static_cast<rlz_lib::AccessPoint>(ap);
141    if (rlz_lib::GetAccessPointRlz(point, rlz, arraysize(rlz)) && rlz[0]) {
142      rlz_lib::SetAccessPointRlz(point, "");
143    }
144  }
145
146  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX,
147      "TbRlzValue"));
148  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::QUICK_SEARCH_BOX,
149      "QsbRlzValue"));
150  EXPECT_TRUE(rlz_lib::FinancialPing::FormRequest(rlz_lib::TOOLBAR_NOTIFIER,
151      points, "swg", brand, NULL, NULL, false, &request));
152  expected_response.clear();
153  base::StringAppendF(&expected_response,
154      "/tools/pso/ping?as=swg&brand=%s&rep=2&rlz=T4:TbRlzValue,"
155      "Q1:QsbRlzValue" DCC_PARAM, brand);
156  EXPECT_STREQ(expected_response.c_str(), request.c_str());
157
158  if (!GetAccessPointRlz(rlz_lib::IE_HOME_PAGE, rlz, arraysize(rlz))) {
159    points[2] = rlz_lib::IE_HOME_PAGE;
160    EXPECT_TRUE(rlz_lib::FinancialPing::FormRequest(rlz_lib::TOOLBAR_NOTIFIER,
161        points, "swg", brand, "MyId", "en-US", true, &request));
162    expected_response.clear();
163    base::StringAppendF(&expected_response,
164        "/tools/pso/ping?as=swg&brand=%s&hl=en-US&pid=MyId&rep=2"
165        "&rlz=T4:TbRlzValue,Q1:QsbRlzValue" DCC_PARAM, brand);
166  EXPECT_STREQ(expected_response.c_str(), request.c_str());
167  }
168}
169
170TEST_F(FinancialPingTest, FormRequestBadBrand) {
171  rlz_lib::AccessPoint points[] =
172    {rlz_lib::IETB_SEARCH_BOX, rlz_lib::NO_ACCESS_POINT,
173     rlz_lib::NO_ACCESS_POINT};
174
175  std::string request;
176  bool ok = rlz_lib::FinancialPing::FormRequest(rlz_lib::TOOLBAR_NOTIFIER,
177      points, "swg", "GOOG", NULL, "en", false, &request);
178  EXPECT_EQ(rlz_lib::SupplementaryBranding::GetBrand().empty(), ok);
179}
180
181
182static void SetLastPingTime(int64 time, rlz_lib::Product product) {
183  rlz_lib::ScopedRlzValueStoreLock lock;
184  rlz_lib::RlzValueStore* store = lock.GetStore();
185  ASSERT_TRUE(store);
186  ASSERT_TRUE(store->HasAccess(rlz_lib::RlzValueStore::kWriteAccess));
187  store->WritePingTime(product, time);
188}
189
190TEST_F(FinancialPingTest, IsPingTime) {
191  int64 now = GetSystemTimeAsInt64();
192  int64 last_ping = now - rlz_lib::kEventsPingInterval - k1MinuteInterval;
193  SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
194
195  // No events, last ping just over a day ago.
196  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
197  EXPECT_FALSE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
198                                                  false));
199
200  // Has events, last ping just over a day ago.
201  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
202      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
203  EXPECT_TRUE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
204                                                 false));
205
206  // Has events, last ping just under a day ago.
207  last_ping = now - rlz_lib::kEventsPingInterval + k1MinuteInterval;
208  SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
209  EXPECT_FALSE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
210                                                  false));
211
212  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
213
214  // No events, last ping just under a week ago.
215  last_ping = now - rlz_lib::kNoEventsPingInterval + k1MinuteInterval;
216  SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
217  EXPECT_FALSE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
218                                                  false));
219
220  // No events, last ping just over a week ago.
221  last_ping = now - rlz_lib::kNoEventsPingInterval - k1MinuteInterval;
222  SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
223  EXPECT_TRUE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
224                                                 false));
225
226  // Last ping was in future (invalid).
227  last_ping = now + k1MinuteInterval;
228  SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
229  EXPECT_TRUE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
230                                                 false));
231  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
232      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
233  EXPECT_TRUE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
234                                                 false));
235}
236
237TEST_F(FinancialPingTest, BrandingIsPingTime) {
238  // Don't run these tests if a supplementary brand is already in place.  That
239  // way we can control the branding.
240  if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
241    return;
242
243  int64 now = GetSystemTimeAsInt64();
244  int64 last_ping = now - rlz_lib::kEventsPingInterval - k1MinuteInterval;
245  SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
246
247  // Has events, last ping just over a day ago.
248  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
249      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
250  EXPECT_TRUE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
251                                                 false));
252
253  {
254    rlz_lib::SupplementaryBranding branding("TEST");
255    SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
256
257    // Has events, last ping just over a day ago.
258    EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
259        rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
260    EXPECT_TRUE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
261                                                   false));
262  }
263
264  last_ping = now - k1MinuteInterval;
265  SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
266
267  EXPECT_FALSE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
268                                                  false));
269
270  {
271    rlz_lib::SupplementaryBranding branding("TEST");
272    EXPECT_TRUE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
273                                                   false));
274  }
275}
276
277TEST_F(FinancialPingTest, ClearLastPingTime) {
278  int64 now = GetSystemTimeAsInt64();
279  int64 last_ping = now - rlz_lib::kEventsPingInterval + k1MinuteInterval;
280  SetLastPingTime(last_ping, rlz_lib::TOOLBAR_NOTIFIER);
281
282  // Has events, last ping just under a day ago.
283  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
284  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
285      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
286  EXPECT_FALSE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
287                                                  false));
288
289  EXPECT_TRUE(rlz_lib::FinancialPing::ClearLastPingTime(
290      rlz_lib::TOOLBAR_NOTIFIER));
291  EXPECT_TRUE(rlz_lib::FinancialPing::IsPingTime(rlz_lib::TOOLBAR_NOTIFIER,
292                                                 false));
293}
294