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 RLZ library.
6//
7// These tests should not be executed on the build server:
8// - They assert for the failed cases.
9// - They modify machine state (registry).
10//
11// These tests require write access to HKLM and HKCU.
12//
13// The "GGLA" brand is used to test the normal code flow of the code, and the
14// "TEST" brand is used to test the supplementary brand code code flow.
15
16#include "base/posix/eintr_wrapper.h"
17#include "base/logging.h"
18#include "base/memory/scoped_ptr.h"
19#include "testing/gmock/include/gmock/gmock.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
22#include "rlz/lib/financial_ping.h"
23#include "rlz/lib/rlz_lib.h"
24#include "rlz/lib/rlz_value_store.h"
25#include "rlz/test/rlz_test_helpers.h"
26
27#if defined(OS_WIN)
28#include <Windows.h>
29#include "rlz/win/lib/machine_deal.h"
30#endif
31
32#if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
33#include "base/mac/scoped_nsautorelease_pool.h"
34#include "base/threading/thread.h"
35#include "net/url_request/url_request_test_util.h"
36#endif
37
38
39class MachineDealCodeHelper
40#if defined(OS_WIN)
41    : public rlz_lib::MachineDealCode
42#endif
43    {
44 public:
45  static bool Clear() {
46#if defined(OS_WIN)
47    return rlz_lib::MachineDealCode::Clear();
48#else
49    return true;
50#endif
51  }
52
53 private:
54  MachineDealCodeHelper() {}
55  ~MachineDealCodeHelper() {}
56};
57
58class RlzLibTest : public RlzLibTestBase {
59};
60
61TEST_F(RlzLibTest, RecordProductEvent) {
62  char cgi_50[50];
63
64  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
65  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
66      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
67  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
68                                             cgi_50, 50));
69  EXPECT_STREQ("events=I7S", cgi_50);
70
71  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
72      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
73  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
74                                             cgi_50, 50));
75  EXPECT_STREQ("events=I7S,W1I", cgi_50);
76
77  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
78      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
79  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
80                                             cgi_50, 50));
81  EXPECT_STREQ("events=I7S,W1I", cgi_50);
82}
83
84TEST_F(RlzLibTest, ClearProductEvent) {
85  char cgi_50[50];
86
87  // Clear 1 of 1 events.
88  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
89  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
90      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
91  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
92                                             cgi_50, 50));
93  EXPECT_STREQ("events=I7S", cgi_50);
94  EXPECT_TRUE(rlz_lib::ClearProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
95      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
96  EXPECT_FALSE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
97                                              cgi_50, 50));
98  EXPECT_STREQ("", cgi_50);
99
100  // Clear 1 of 2 events.
101  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
102  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
103      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
104  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
105      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
106  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
107                                             cgi_50, 50));
108  EXPECT_STREQ("events=I7S,W1I", cgi_50);
109  EXPECT_TRUE(rlz_lib::ClearProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
110      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
111  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
112                                             cgi_50, 50));
113  EXPECT_STREQ("events=W1I", cgi_50);
114
115  // Clear a non-recorded event.
116  EXPECT_TRUE(rlz_lib::ClearProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
117      rlz_lib::IETB_SEARCH_BOX, rlz_lib::FIRST_SEARCH));
118  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
119                                             cgi_50, 50));
120  EXPECT_STREQ("events=W1I", cgi_50);
121}
122
123
124TEST_F(RlzLibTest, GetProductEventsAsCgi) {
125  char cgi_50[50];
126  char cgi_1[1];
127
128  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
129  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
130      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
131  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
132                                             cgi_50, 50));
133  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
134      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
135
136  EXPECT_FALSE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
137                                              cgi_1, 1));
138  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
139                                             cgi_50, 50));
140  EXPECT_STREQ("events=I7S,W1I", cgi_50);
141}
142
143TEST_F(RlzLibTest, ClearAllAllProductEvents) {
144  char cgi_50[50];
145
146  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
147  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
148      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
149  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
150                                             cgi_50, 50));
151  EXPECT_STREQ("events=I7S", cgi_50);
152
153  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
154  EXPECT_FALSE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
155                                              cgi_50, 50));
156  EXPECT_STREQ("", cgi_50);
157}
158
159TEST_F(RlzLibTest, SetAccessPointRlz) {
160  char rlz_50[50];
161  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, ""));
162  EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, rlz_50, 50));
163  EXPECT_STREQ("", rlz_50);
164
165  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, "IeTbRlz"));
166  EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, rlz_50, 50));
167  EXPECT_STREQ("IeTbRlz", rlz_50);
168}
169
170TEST_F(RlzLibTest, GetAccessPointRlz) {
171  char rlz_1[1];
172  char rlz_50[50];
173  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, ""));
174  EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, rlz_1, 1));
175  EXPECT_STREQ("", rlz_1);
176
177  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, "IeTbRlz"));
178  EXPECT_FALSE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, rlz_1, 1));
179  EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, rlz_50, 50));
180  EXPECT_STREQ("IeTbRlz", rlz_50);
181}
182
183TEST_F(RlzLibTest, GetPingParams) {
184  MachineDealCodeHelper::Clear();
185
186  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX,
187      "TbRlzValue"));
188  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IE_HOME_PAGE, ""));
189
190  char cgi[2048];
191  rlz_lib::AccessPoint points[] =
192    {rlz_lib::IETB_SEARCH_BOX, rlz_lib::NO_ACCESS_POINT,
193     rlz_lib::NO_ACCESS_POINT};
194
195  EXPECT_TRUE(rlz_lib::GetPingParams(rlz_lib::TOOLBAR_NOTIFIER, points,
196                                     cgi, 2048));
197  EXPECT_STREQ("rep=2&rlz=T4:TbRlzValue", cgi);
198
199#if defined(OS_WIN)
200  EXPECT_TRUE(rlz_lib::MachineDealCode::Set("dcc_value"));
201#define DCC_PARAM "&dcc=dcc_value"
202#else
203#define DCC_PARAM ""
204#endif
205
206  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, ""));
207  EXPECT_TRUE(rlz_lib::GetPingParams(rlz_lib::TOOLBAR_NOTIFIER, points,
208                                     cgi, 2048));
209  EXPECT_STREQ("rep=2&rlz=T4:" DCC_PARAM, cgi);
210
211  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX,
212              "TbRlzValue"));
213  EXPECT_FALSE(rlz_lib::GetPingParams(rlz_lib::TOOLBAR_NOTIFIER, points,
214                                      cgi, 23 + strlen(DCC_PARAM)));
215  EXPECT_STREQ("", cgi);
216  EXPECT_TRUE(rlz_lib::GetPingParams(rlz_lib::TOOLBAR_NOTIFIER, points,
217                                     cgi, 24 + strlen(DCC_PARAM)));
218  EXPECT_STREQ("rep=2&rlz=T4:TbRlzValue" DCC_PARAM, cgi);
219
220  EXPECT_TRUE(GetAccessPointRlz(rlz_lib::IE_HOME_PAGE, cgi, 2048));
221  points[2] = rlz_lib::IE_HOME_PAGE;
222  EXPECT_TRUE(rlz_lib::GetPingParams(rlz_lib::TOOLBAR_NOTIFIER, points,
223                                     cgi, 2048));
224  EXPECT_STREQ("rep=2&rlz=T4:TbRlzValue" DCC_PARAM, cgi);
225}
226
227TEST_F(RlzLibTest, IsPingResponseValid) {
228  const char* kBadPingResponses[] = {
229    // No checksum.
230    "version: 3.0.914.7250\r\n"
231    "url: http://www.corp.google.com/~av/45/opt/SearchWithGoogleUpdate.exe\r\n"
232    "launch-action: custom-action\r\n"
233    "launch-target: SearchWithGoogleUpdate.exe\r\n"
234    "signature: c08a3f4438e1442c4fe5678ee147cf6c5516e5d62bb64e\r\n"
235    "rlz: 1R1_____en__252\r\n"
236    "rlzXX: 1R1_____en__250\r\n",
237
238    // Invalid checksum.
239    "version: 3.0.914.7250\r\n"
240    "url: http://www.corp.google.com/~av/45/opt/SearchWithGoogleUpdate.exe\r\n"
241    "launch-action: custom-action\r\n"
242    "launch-target: SearchWithGoogleUpdate.exe\r\n"
243    "signature: c08a3f4438e1442c4fe5678ee147cf6c5516e5d62bb64e\r\n"
244    "rlz: 1R1_____en__252\r\n"
245    "rlzXX: 1R1_____en__250\r\n"
246    "rlzT4  1T4_____en__251\r\n"
247    "rlzT4: 1T4_____en__252\r\n"
248    "rlz\r\n"
249    "crc32: B12CC79A",
250
251    // Misplaced checksum.
252    "version: 3.0.914.7250\r\n"
253    "url: http://www.corp.google.com/~av/45/opt/SearchWithGoogleUpdate.exe\r\n"
254    "launch-action: custom-action\r\n"
255    "launch-target: SearchWithGoogleUpdate.exe\r\n"
256    "signature: c08a3f4438e1442c4fe5678ee147cf6c5516e5d62bb64e\r\n"
257    "rlz: 1R1_____en__252\r\n"
258    "rlzXX: 1R1_____en__250\r\n"
259    "crc32: B12CC79C\r\n"
260    "rlzT4  1T4_____en__251\r\n"
261    "rlzT4: 1T4_____en__252\r\n"
262    "rlz\r\n",
263
264    NULL
265  };
266
267  const char* kGoodPingResponses[] = {
268    "version: 3.0.914.7250\r\n"
269    "url: http://www.corp.google.com/~av/45/opt/SearchWithGoogleUpdate.exe\r\n"
270    "launch-action: custom-action\r\n"
271    "launch-target: SearchWithGoogleUpdate.exe\r\n"
272    "signature: c08a3f4438e1442c4fe5678ee147cf6c5516e5d62bb64e\r\n"
273    "rlz: 1R1_____en__252\r\n"
274    "rlzXX: 1R1_____en__250\r\n"
275    "rlzT4  1T4_____en__251\r\n"
276    "rlzT4: 1T4_____en__252\r\n"
277    "rlz\r\n"
278    "crc32: D6FD55A3",
279
280    "version: 3.0.914.7250\r\n"
281    "url: http://www.corp.google.com/~av/45/opt/SearchWithGoogleUpdate.exe\r\n"
282    "launch-action: custom-action\r\n"
283    "launch-target: SearchWithGoogleUpdate.exe\r\n"
284    "signature: c08a3f4438e1442c4fe5678ee147cf6c5516e5d62bb64e\r\n"
285    "rlz: 1R1_____en__252\r\n"
286    "rlzXX: 1R1_____en__250\r\n"
287    "rlzT4  1T4_____en__251\r\n"
288    "rlzT4: 1T4_____en__252\r\n"
289    "rlz\r\n"
290    "crc32: D6FD55A3\r\n"
291    "extradata: not checksummed",
292
293    NULL
294  };
295
296  for (int i = 0; kBadPingResponses[i]; i++)
297    EXPECT_FALSE(rlz_lib::IsPingResponseValid(kBadPingResponses[i], NULL));
298
299  for (int i = 0; kGoodPingResponses[i]; i++)
300    EXPECT_TRUE(rlz_lib::IsPingResponseValid(kGoodPingResponses[i], NULL));
301}
302
303TEST_F(RlzLibTest, ParsePingResponse) {
304  const char* kPingResponse =
305    "version: 3.0.914.7250\r\n"
306    "url: http://www.corp.google.com/~av/45/opt/SearchWithGoogleUpdate.exe\r\n"
307    "launch-action: custom-action\r\n"
308    "launch-target: SearchWithGoogleUpdate.exe\r\n"
309    "signature: c08a3f4438e1442c4fe5678ee147cf6c5516e5d62bb64e\r\n"
310    "rlz: 1R1_____en__252\r\n"  // Invalid RLZ - no access point.
311    "rlzXX: 1R1_____en__250\r\n"  // Invalid RLZ - bad access point.
312    "rlzT4  1T4_____en__251\r\n"  // Invalid RLZ - missing colon.
313    "rlzT4: 1T4_____en__252\r\n"  // GoodRLZ.
314    "events: I7S,W1I\r\n"  // Clear all events.
315    "rlz\r\n"
316    "dcc: dcc_value\r\n"
317    "crc32: F9070F81";
318
319#if defined(OS_WIN)
320  EXPECT_TRUE(rlz_lib::MachineDealCode::Set("dcc_value2"));
321#endif
322
323  // Record some product events to check that they get cleared.
324  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
325      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
326  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
327      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
328
329  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(
330      rlz_lib::IETB_SEARCH_BOX, "TbRlzValue"));
331
332  EXPECT_TRUE(rlz_lib::ParsePingResponse(rlz_lib::TOOLBAR_NOTIFIER,
333                                         kPingResponse));
334
335#if defined(OS_WIN)
336  EXPECT_TRUE(rlz_lib::MachineDealCode::Set("dcc_value"));
337#endif
338  EXPECT_TRUE(rlz_lib::ParsePingResponse(rlz_lib::TOOLBAR_NOTIFIER,
339                                         kPingResponse));
340
341  char value[50];
342  EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, value, 50));
343  EXPECT_STREQ("1T4_____en__252", value);
344  EXPECT_FALSE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
345                                              value, 50));
346  EXPECT_STREQ("", value);
347
348  const char* kPingResponse2 =
349    "rlzT4:    1T4_____de__253  \r\n"  // Good with extra spaces.
350    "crc32: 321334F5\r\n";
351  EXPECT_TRUE(rlz_lib::ParsePingResponse(rlz_lib::TOOLBAR_NOTIFIER,
352                                         kPingResponse2));
353  EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, value, 50));
354  EXPECT_STREQ("1T4_____de__253", value);
355
356  const char* kPingResponse3 =
357    "crc32: 0\r\n";  // Good RLZ - empty response.
358  EXPECT_TRUE(rlz_lib::ParsePingResponse(rlz_lib::TOOLBAR_NOTIFIER,
359                                         kPingResponse3));
360  EXPECT_STREQ("1T4_____de__253", value);
361}
362
363// Test whether a stateful event will only be sent in financial pings once.
364TEST_F(RlzLibTest, ParsePingResponseWithStatefulEvents) {
365  const char* kPingResponse =
366    "version: 3.0.914.7250\r\n"
367    "url: http://www.corp.google.com/~av/45/opt/SearchWithGoogleUpdate.exe\r\n"
368    "launch-action: custom-action\r\n"
369    "launch-target: SearchWithGoogleUpdate.exe\r\n"
370    "signature: c08a3f4438e1442c4fe5678ee147cf6c5516e5d62bb64e\r\n"
371    "rlzT4: 1T4_____en__252\r\n"  // GoodRLZ.
372    "events: I7S,W1I\r\n"         // Clear all events.
373    "stateful-events: W1I\r\n"    // W1I as an stateful event.
374    "rlz\r\n"
375    "dcc: dcc_value\r\n"
376    "crc32: 55191759";
377
378  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
379
380  // Record some product events to check that they get cleared.
381  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
382      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
383  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
384      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
385
386  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(
387      rlz_lib::IETB_SEARCH_BOX, "TbRlzValue"));
388
389  EXPECT_TRUE(rlz_lib::ParsePingResponse(rlz_lib::TOOLBAR_NOTIFIER,
390                                         kPingResponse));
391
392  // Check all the events sent earlier are cleared.
393  char value[50];
394  EXPECT_FALSE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
395                                              value, 50));
396  EXPECT_STREQ("", value);
397
398  // Record both events (one is stateless and the other is stateful) again.
399  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
400      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
401  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
402      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
403
404  // Check the stateful event won't be sent again while the stateless one will.
405  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
406                                             value, 50));
407  EXPECT_STREQ("events=I7S", value);
408
409  // Test that stateful events are cleared by ClearAllProductEvents().  After
410  // calling it, trying to record a stateful again should result in it being
411  // recorded again.
412  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
413  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
414      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
415  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
416                                             value, 50));
417  EXPECT_STREQ("events=W1I", value);
418}
419
420class URLRequestRAII {
421 public:
422  URLRequestRAII(net::URLRequestContextGetter* context) {
423    rlz_lib::SetURLRequestContext(context);
424  }
425  ~URLRequestRAII() {
426    rlz_lib::SetURLRequestContext(NULL);
427  }
428};
429
430TEST_F(RlzLibTest, SendFinancialPing) {
431  // We don't really check a value or result in this test. All this does is
432  // attempt to ping the financial server, which you can verify in Fiddler.
433  // TODO: Make this a measurable test.
434
435#if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
436#if defined(OS_MACOSX)
437  base::mac::ScopedNSAutoreleasePool pool;
438#endif
439
440  base::Thread::Options options;
441  options.message_loop_type = base::MessageLoop::TYPE_IO;
442
443  base::Thread io_thread("rlz_unittest_io_thread");
444  ASSERT_TRUE(io_thread.StartWithOptions(options));
445
446  scoped_refptr<net::TestURLRequestContextGetter> context =
447      new net::TestURLRequestContextGetter(
448          io_thread.message_loop()->message_loop_proxy());
449  rlz_lib::SetURLRequestContext(context.get());
450
451  URLRequestRAII set_context(context.get());
452#endif
453
454  MachineDealCodeHelper::Clear();
455#if defined(OS_WIN)
456  EXPECT_TRUE(rlz_lib::MachineDealCode::Set("dcc_value"));
457#endif
458
459  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX,
460      "TbRlzValue"));
461
462  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
463  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
464      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
465  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
466      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
467
468  rlz_lib::AccessPoint points[] =
469    {rlz_lib::IETB_SEARCH_BOX, rlz_lib::NO_ACCESS_POINT,
470     rlz_lib::NO_ACCESS_POINT};
471
472  std::string request;
473  rlz_lib::SendFinancialPing(rlz_lib::TOOLBAR_NOTIFIER, points,
474      "swg", "GGLA", "SwgProductId1234", "en-UK", false,
475      /*skip_time_check=*/true);
476}
477
478#if defined(RLZ_NETWORK_IMPLEMENTATION_CHROME_NET)
479
480void ResetContext() {
481  rlz_lib::SetURLRequestContext(NULL);
482}
483
484TEST_F(RlzLibTest, SendFinancialPingDuringShutdown) {
485  // rlz_lib::SendFinancialPing fails when this is set.
486  if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
487    return;
488
489#if defined(OS_MACOSX)
490  base::mac::ScopedNSAutoreleasePool pool;
491#endif
492
493  base::Thread::Options options;
494  options.message_loop_type = base::MessageLoop::TYPE_IO;
495
496  base::Thread io_thread("rlz_unittest_io_thread");
497  ASSERT_TRUE(io_thread.StartWithOptions(options));
498
499  scoped_refptr<net::TestURLRequestContextGetter> context =
500      new net::TestURLRequestContextGetter(
501          io_thread.message_loop()->message_loop_proxy());
502  rlz_lib::SetURLRequestContext(context.get());
503
504  URLRequestRAII set_context(context.get());
505
506  rlz_lib::AccessPoint points[] =
507    {rlz_lib::IETB_SEARCH_BOX, rlz_lib::NO_ACCESS_POINT,
508     rlz_lib::NO_ACCESS_POINT};
509  rlz_lib::test::ResetSendFinancialPingInterrupted();
510  EXPECT_FALSE(rlz_lib::test::WasSendFinancialPingInterrupted());
511
512  base::MessageLoop loop;
513  loop.PostTask(FROM_HERE, base::Bind(&ResetContext));
514  std::string request;
515  EXPECT_FALSE(rlz_lib::SendFinancialPing(rlz_lib::TOOLBAR_NOTIFIER, points,
516      "swg", "GGLA", "SwgProductId1234", "en-UK", false,
517      /*skip_time_check=*/true));
518
519  EXPECT_TRUE(rlz_lib::test::WasSendFinancialPingInterrupted());
520  rlz_lib::test::ResetSendFinancialPingInterrupted();
521}
522#endif
523
524TEST_F(RlzLibTest, ClearProductState) {
525  MachineDealCodeHelper::Clear();
526
527  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX,
528      "TbRlzValue"));
529  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::GD_DESKBAND,
530      "GdbRlzValue"));
531
532  rlz_lib::AccessPoint points[] =
533      { rlz_lib::IETB_SEARCH_BOX, rlz_lib::NO_ACCESS_POINT };
534
535  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
536      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
537  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
538      rlz_lib::IETB_SEARCH_BOX, rlz_lib::INSTALL));
539
540  rlz_lib::AccessPoint points2[] =
541    { rlz_lib::IETB_SEARCH_BOX,
542      rlz_lib::GD_DESKBAND,
543      rlz_lib::NO_ACCESS_POINT };
544
545  char cgi[2048];
546  EXPECT_TRUE(rlz_lib::GetPingParams(rlz_lib::TOOLBAR_NOTIFIER, points2,
547                                     cgi, 2048));
548  EXPECT_STREQ("rep=2&rlz=T4:TbRlzValue,D1:GdbRlzValue", cgi);
549
550  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
551                                             cgi, 2048));
552  std::string events(cgi);
553  EXPECT_LT(0u, events.find("I7S"));
554  EXPECT_LT(0u, events.find("T4I"));
555  EXPECT_LT(0u, events.find("T4R"));
556
557  rlz_lib::ClearProductState(rlz_lib::TOOLBAR_NOTIFIER, points);
558
559  EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX,
560                                         cgi, 2048));
561  EXPECT_STREQ("", cgi);
562  EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::GD_DESKBAND,
563                                         cgi, 2048));
564  EXPECT_STREQ("GdbRlzValue", cgi);
565
566  EXPECT_FALSE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
567                                              cgi, 2048));
568  EXPECT_STREQ("", cgi);
569}
570
571#if defined(OS_WIN)
572template<class T>
573class typed_buffer_ptr {
574  scoped_ptr<char[]> buffer_;
575
576 public:
577  typed_buffer_ptr() {
578  }
579
580  explicit typed_buffer_ptr(size_t size) : buffer_(new char[size]) {
581  }
582
583  void reset(size_t size) {
584    buffer_.reset(new char[size]);
585  }
586
587  operator T*() {
588    return reinterpret_cast<T*>(buffer_.get());
589  }
590};
591
592namespace rlz_lib {
593bool HasAccess(PSID sid, ACCESS_MASK access_mask, ACL* dacl);
594}
595
596bool EmptyAcl(ACL* acl) {
597  ACL_SIZE_INFORMATION info;
598  bool ret = GetAclInformation(acl, &info, sizeof(info), AclSizeInformation);
599  EXPECT_TRUE(ret);
600
601  for (DWORD i = 0; i < info.AceCount && ret; ++i) {
602    ret = DeleteAce(acl, 0);
603    EXPECT_TRUE(ret);
604  }
605
606  return ret;
607}
608
609TEST_F(RlzLibTest, HasAccess) {
610  // Create a SID that represents ALL USERS.
611  DWORD users_sid_size = SECURITY_MAX_SID_SIZE;
612  typed_buffer_ptr<SID> users_sid(users_sid_size);
613  CreateWellKnownSid(WinBuiltinUsersSid, NULL, users_sid, &users_sid_size);
614
615  // RLZ always asks for KEY_ALL_ACCESS access to the key.  This is what we
616  // test here.
617
618  // No ACL mean no access.
619  EXPECT_FALSE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, NULL));
620
621  // Create an ACL for these tests.
622  const DWORD kMaxAclSize = 1024;
623  typed_buffer_ptr<ACL> dacl(kMaxAclSize);
624  InitializeAcl(dacl, kMaxAclSize, ACL_REVISION);
625
626  // Empty DACL mean no access.
627  EXPECT_FALSE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, dacl));
628
629  // ACE without all needed privileges should mean no access.
630  EXPECT_TRUE(AddAccessAllowedAce(dacl, ACL_REVISION, KEY_READ, users_sid));
631  EXPECT_FALSE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, dacl));
632
633  // ACE without all needed privileges should mean no access.
634  EXPECT_TRUE(EmptyAcl(dacl));
635  EXPECT_TRUE(AddAccessAllowedAce(dacl, ACL_REVISION, KEY_WRITE, users_sid));
636  EXPECT_FALSE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, dacl));
637
638  // A deny ACE before an allow ACE should not give access.
639  EXPECT_TRUE(EmptyAcl(dacl));
640  EXPECT_TRUE(AddAccessDeniedAce(dacl, ACL_REVISION, KEY_ALL_ACCESS,
641                                 users_sid));
642  EXPECT_TRUE(AddAccessAllowedAce(dacl, ACL_REVISION, KEY_ALL_ACCESS,
643                                  users_sid));
644  EXPECT_FALSE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, dacl));
645
646  // A deny ACE before an allow ACE should not give access.
647  EXPECT_TRUE(EmptyAcl(dacl));
648  EXPECT_TRUE(AddAccessDeniedAce(dacl, ACL_REVISION, KEY_READ, users_sid));
649  EXPECT_TRUE(AddAccessAllowedAce(dacl, ACL_REVISION, KEY_ALL_ACCESS,
650                                  users_sid));
651  EXPECT_FALSE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, dacl));
652
653
654  // An allow ACE without all required bits should not give access.
655  EXPECT_TRUE(EmptyAcl(dacl));
656  EXPECT_TRUE(AddAccessAllowedAce(dacl, ACL_REVISION, KEY_WRITE, users_sid));
657  EXPECT_FALSE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, dacl));
658
659  // An allow ACE with all required bits should give access.
660  EXPECT_TRUE(EmptyAcl(dacl));
661  EXPECT_TRUE(AddAccessAllowedAce(dacl, ACL_REVISION, KEY_ALL_ACCESS,
662                                  users_sid));
663  EXPECT_TRUE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, dacl));
664
665  // A deny ACE after an allow ACE should not give access.
666  EXPECT_TRUE(EmptyAcl(dacl));
667  EXPECT_TRUE(AddAccessAllowedAce(dacl, ACL_REVISION, KEY_ALL_ACCESS,
668                                  users_sid));
669  EXPECT_TRUE(AddAccessDeniedAce(dacl, ACL_REVISION, KEY_READ, users_sid));
670  EXPECT_TRUE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, dacl));
671
672  // An inherit-only allow ACE should not give access.
673  EXPECT_TRUE(EmptyAcl(dacl));
674  EXPECT_TRUE(AddAccessAllowedAceEx(dacl, ACL_REVISION, INHERIT_ONLY_ACE,
675                                    KEY_ALL_ACCESS, users_sid));
676  EXPECT_FALSE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, dacl));
677
678  // An inherit-only deny ACE should not apply.
679  EXPECT_TRUE(EmptyAcl(dacl));
680  EXPECT_TRUE(AddAccessDeniedAceEx(dacl, ACL_REVISION, INHERIT_ONLY_ACE,
681                                   KEY_ALL_ACCESS, users_sid));
682  EXPECT_TRUE(AddAccessAllowedAce(dacl, ACL_REVISION, KEY_ALL_ACCESS,
683                                  users_sid));
684  EXPECT_TRUE(rlz_lib::HasAccess(users_sid, KEY_ALL_ACCESS, dacl));
685}
686#endif
687
688TEST_F(RlzLibTest, BrandingRecordProductEvent) {
689  // Don't run these tests if a supplementary brand is already in place.  That
690  // way we can control the branding.
691  if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
692    return;
693
694  char cgi_50[50];
695
696  // Record different events for the same product with diffrent branding, and
697  // make sure that the information remains separate.
698  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
699  {
700    rlz_lib::SupplementaryBranding branding("TEST");
701    EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
702  }
703
704  // Test that recording events with the default brand and a supplementary
705  // brand don't overwrite each other.
706
707  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
708      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
709  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
710                                             cgi_50, 50));
711  EXPECT_STREQ("events=I7S", cgi_50);
712
713  {
714    rlz_lib::SupplementaryBranding branding("TEST");
715    EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
716        rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::INSTALL));
717    EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
718                                               cgi_50, 50));
719    EXPECT_STREQ("events=I7I", cgi_50);
720  }
721
722  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
723                                             cgi_50, 50));
724  EXPECT_STREQ("events=I7S", cgi_50);
725}
726
727TEST_F(RlzLibTest, BrandingSetAccessPointRlz) {
728  // Don't run these tests if a supplementary brand is already in place.  That
729  // way we can control the branding.
730  if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
731    return;
732
733  char rlz_50[50];
734
735  // Test that setting RLZ strings with the default brand and a supplementary
736  // brand don't overwrite each other.
737
738  EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, "IeTbRlz"));
739  EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, rlz_50, 50));
740  EXPECT_STREQ("IeTbRlz", rlz_50);
741
742  {
743    rlz_lib::SupplementaryBranding branding("TEST");
744
745    EXPECT_TRUE(rlz_lib::SetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, "SuppRlz"));
746    EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, rlz_50,
747                                           50));
748    EXPECT_STREQ("SuppRlz", rlz_50);
749  }
750
751  EXPECT_TRUE(rlz_lib::GetAccessPointRlz(rlz_lib::IETB_SEARCH_BOX, rlz_50, 50));
752  EXPECT_STREQ("IeTbRlz", rlz_50);
753
754}
755
756TEST_F(RlzLibTest, BrandingWithStatefulEvents) {
757  // Don't run these tests if a supplementary brand is already in place.  That
758  // way we can control the branding.
759  if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
760    return;
761
762  const char* kPingResponse =
763    "version: 3.0.914.7250\r\n"
764    "url: http://www.corp.google.com/~av/45/opt/SearchWithGoogleUpdate.exe\r\n"
765    "launch-action: custom-action\r\n"
766    "launch-target: SearchWithGoogleUpdate.exe\r\n"
767    "signature: c08a3f4438e1442c4fe5678ee147cf6c5516e5d62bb64e\r\n"
768    "rlzT4: 1T4_____en__252\r\n"  // GoodRLZ.
769    "events: I7S,W1I\r\n"         // Clear all events.
770    "stateful-events: W1I\r\n"    // W1I as an stateful event.
771    "rlz\r\n"
772    "dcc: dcc_value\r\n"
773    "crc32: 55191759";
774
775  EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
776  {
777    rlz_lib::SupplementaryBranding branding("TEST");
778    EXPECT_TRUE(rlz_lib::ClearAllProductEvents(rlz_lib::TOOLBAR_NOTIFIER));
779  }
780
781  // Record some product events for the default and supplementary brand.
782  // Check that they get cleared only for the default brand.
783  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
784      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
785  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
786      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
787
788  {
789    rlz_lib::SupplementaryBranding branding("TEST");
790    EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
791        rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
792    EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
793        rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
794  }
795
796  EXPECT_TRUE(rlz_lib::ParsePingResponse(rlz_lib::TOOLBAR_NOTIFIER,
797                                         kPingResponse));
798
799  // Check all the events sent earlier are cleared only for default brand.
800  char value[50];
801  EXPECT_FALSE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
802                                              value, 50));
803  EXPECT_STREQ("", value);
804
805  {
806    rlz_lib::SupplementaryBranding branding("TEST");
807    EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
808                                               value, 50));
809    EXPECT_STREQ("events=I7S,W1I", value);
810  }
811
812  // Record both events (one is stateless and the other is stateful) again.
813  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
814      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
815  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
816      rlz_lib::IE_HOME_PAGE, rlz_lib::INSTALL));
817
818  // Check the stateful event won't be sent again while the stateless one will.
819  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
820                                             value, 50));
821  EXPECT_STREQ("events=I7S", value);
822
823  {
824    rlz_lib::SupplementaryBranding branding("TEST");
825    EXPECT_TRUE(rlz_lib::ParsePingResponse(rlz_lib::TOOLBAR_NOTIFIER,
826                                           kPingResponse));
827
828    EXPECT_FALSE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
829                                                value, 50));
830    EXPECT_STREQ("", value);
831  }
832
833  EXPECT_TRUE(rlz_lib::GetProductEventsAsCgi(rlz_lib::TOOLBAR_NOTIFIER,
834                                             value, 50));
835  EXPECT_STREQ("events=I7S", value);
836}
837
838#if defined(OS_POSIX)
839class ReadonlyRlzDirectoryTest : public RlzLibTestNoMachineState {
840 protected:
841  virtual void SetUp() OVERRIDE;
842};
843
844void ReadonlyRlzDirectoryTest::SetUp() {
845  RlzLibTestNoMachineState::SetUp();
846  // Make the rlz directory non-writeable.
847  int chmod_result = chmod(temp_dir_.path().value().c_str(), 0500);
848  ASSERT_EQ(0, chmod_result);
849}
850
851TEST_F(ReadonlyRlzDirectoryTest, WriteFails) {
852  // The rlz test runner runs every test twice: Once normally, and once with
853  // a SupplementaryBranding on the stack. In the latter case, the rlz lock
854  // has already been acquired before the rlz directory got changed to
855  // read-only, which makes this test pointless. So run it only in the first
856  // pass.
857  if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
858    return;
859
860  EXPECT_FALSE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
861      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::SET_TO_GOOGLE));
862}
863
864// Regression test for http://crbug.com/121255
865TEST_F(ReadonlyRlzDirectoryTest, SupplementaryBrandingDoesNotCrash) {
866  // See the comment at the top of WriteFails.
867  if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
868    return;
869
870  rlz_lib::SupplementaryBranding branding("TEST");
871  EXPECT_FALSE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
872      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::INSTALL));
873}
874
875// Regression test for http://crbug.com/141108
876TEST_F(RlzLibTest, ConcurrentStoreAccessWithProcessExitsWhileLockHeld) {
877  // See the comment at the top of WriteFails.
878  if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
879    return;
880
881  std::vector<pid_t> pids;
882  for (int i = 0; i < 10; ++i) {
883    pid_t pid = fork();
884    ASSERT_NE(-1, pid);
885    if (pid == 0) {
886      // Child.
887      {
888        // SupplementaryBranding is a RAII object for the rlz lock.
889        rlz_lib::SupplementaryBranding branding("TEST");
890
891        // Simulate a crash while holding the lock in some of the children.
892        if (i > 0 && i % 3 == 0)
893          _exit(0);
894
895        // Note: Since this is in a forked child, a failing expectation won't
896        // make the test fail. It does however cause lots of "check failed"
897        // error output. The parent process will then check the exit code
898        // below to make the test fail.
899        bool success = rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
900            rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::INSTALL);
901        EXPECT_TRUE(success);
902        _exit(success ? 0 : 1);
903      }
904      _exit(0);
905    } else {
906      // Parent.
907      pids.push_back(pid);
908    }
909  }
910
911  int status;
912  for (size_t i = 0; i < pids.size(); ++i) {
913    if (HANDLE_EINTR(waitpid(pids[i], &status, 0)) != -1)
914      EXPECT_TRUE(WIFEXITED(status) && WEXITSTATUS(status) == 0);
915  }
916
917  // No child should have the lock at this point, not even the crashed ones.
918  EXPECT_TRUE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
919      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::INSTALL));
920}
921
922TEST_F(RlzLibTest, LockAcquistionSucceedsButStoreFileCannotBeCreated) {
923  // See the comment at the top of WriteFails.
924  if (!rlz_lib::SupplementaryBranding::GetBrand().empty())
925    return;
926
927  // Create a directory where the rlz file is supposed to appear. This way,
928  // the lock file can be created successfully, but creation of the rlz file
929  // itself will fail.
930  int mkdir_result = mkdir(rlz_lib::testing::RlzStoreFilenameStr().c_str(),
931                           0500);
932  ASSERT_EQ(0, mkdir_result);
933
934  rlz_lib::SupplementaryBranding branding("TEST");
935  EXPECT_FALSE(rlz_lib::RecordProductEvent(rlz_lib::TOOLBAR_NOTIFIER,
936      rlz_lib::IE_DEFAULT_SEARCH, rlz_lib::INSTALL));
937}
938
939#endif
940