Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / metrics / variations / variations_service_unittest.cc
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 #include "chrome/browser/metrics/variations/variations_service.h"
6
7 #include <vector>
8
9 #include "base/base64.h"
10 #include "base/prefs/testing_pref_service.h"
11 #include "base/sha1.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_util.h"
14 #include "chrome/browser/web_resource/resource_request_allowed_notifier_test_util.h"
15 #include "chrome/common/pref_names.h"
16 #include "chrome/test/base/testing_browser_process.h"
17 #include "chrome/test/base/testing_pref_service_syncable.h"
18 #include "components/variations/proto/study.pb.h"
19 #include "components/variations/proto/variations_seed.pb.h"
20 #include "content/public/test/test_browser_thread.h"
21 #include "net/base/url_util.h"
22 #include "net/http/http_response_headers.h"
23 #include "net/http/http_status_code.h"
24 #include "net/url_request/test_url_fetcher_factory.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26
27 #if defined(OS_CHROMEOS)
28 #include "chrome/browser/chromeos/settings/cros_settings.h"
29 #include "chrome/browser/chromeos/settings/device_settings_service.h"
30 #include "chrome/browser/chromeos/settings/stub_cros_settings_provider.h"
31 #endif
32
33 namespace chrome_variations {
34
35 namespace {
36
37 // A test class used to validate expected functionality in VariationsService.
38 class TestVariationsService : public VariationsService {
39  public:
40   TestVariationsService(TestRequestAllowedNotifier* test_notifier,
41                         PrefService* local_state)
42       : VariationsService(test_notifier, local_state, NULL),
43         intercepts_fetch_(true),
44         fetch_attempted_(false),
45         seed_stored_(false) {
46     // Set this so StartRepeatedVariationsSeedFetch can be called in tests.
47     SetCreateTrialsFromSeedCalledForTesting(true);
48   }
49
50   ~TestVariationsService() override {}
51
52   void set_intercepts_fetch(bool value) {
53     intercepts_fetch_ = value;
54   }
55
56   bool fetch_attempted() const { return fetch_attempted_; }
57
58   bool seed_stored() const { return seed_stored_; }
59
60   void DoActualFetch() override {
61     if (intercepts_fetch_) {
62       fetch_attempted_ = true;
63       return;
64     }
65
66     VariationsService::DoActualFetch();
67   }
68
69  protected:
70   void StoreSeed(const std::string& seed_data,
71                  const std::string& seed_signature,
72                  const base::Time& date_fetched) override {
73     seed_stored_ = true;
74   }
75
76  private:
77   bool intercepts_fetch_;
78   bool fetch_attempted_;
79   bool seed_stored_;
80
81   DISALLOW_COPY_AND_ASSIGN(TestVariationsService);
82 };
83
84 class TestVariationsServiceObserver : public VariationsService::Observer {
85  public:
86   TestVariationsServiceObserver()
87       : best_effort_changes_notified_(0),
88         crticial_changes_notified_(0) {
89   }
90   ~TestVariationsServiceObserver() override {}
91
92   void OnExperimentChangesDetected(Severity severity) override {
93     switch (severity) {
94       case BEST_EFFORT:
95         ++best_effort_changes_notified_;
96         break;
97       case CRITICAL:
98         ++crticial_changes_notified_;
99         break;
100     }
101   }
102
103   int best_effort_changes_notified() const {
104     return best_effort_changes_notified_;
105   }
106
107   int crticial_changes_notified() const {
108     return crticial_changes_notified_;
109   }
110
111  private:
112   // Number of notification received with BEST_EFFORT severity.
113   int best_effort_changes_notified_;
114
115   // Number of notification received with CRITICAL severity.
116   int crticial_changes_notified_;
117
118   DISALLOW_COPY_AND_ASSIGN(TestVariationsServiceObserver);
119 };
120
121 // Populates |seed| with simple test data. The resulting seed will contain one
122 // study called "test", which contains one experiment called "abc" with
123 // probability weight 100. |seed|'s study field will be cleared before adding
124 // the new study.
125 variations::VariationsSeed CreateTestSeed() {
126   variations::VariationsSeed seed;
127   variations::Study* study = seed.add_study();
128   study->set_name("test");
129   study->set_default_experiment_name("abc");
130   variations::Study_Experiment* experiment = study->add_experiment();
131   experiment->set_name("abc");
132   experiment->set_probability_weight(100);
133   seed.set_serial_number("123");
134   return seed;
135 }
136
137 // Serializes |seed| to protobuf binary format.
138 std::string SerializeSeed(const variations::VariationsSeed& seed) {
139   std::string serialized_seed;
140   seed.SerializeToString(&serialized_seed);
141   return serialized_seed;
142 }
143
144 // Simulates a variations service response by setting a date header and the
145 // specified HTTP |response_code| on |fetcher|.
146 void SimulateServerResponse(int response_code, net::TestURLFetcher* fetcher) {
147   ASSERT_TRUE(fetcher);
148   scoped_refptr<net::HttpResponseHeaders> headers(
149       new net::HttpResponseHeaders("date:Wed, 13 Feb 2013 00:25:24 GMT\0\0"));
150   fetcher->set_response_headers(headers);
151   fetcher->set_response_code(response_code);
152 }
153
154 }  // namespace
155
156 class VariationsServiceTest : public ::testing::Test {
157  protected:
158   VariationsServiceTest() {}
159
160  private:
161 #if defined(OS_CHROMEOS)
162   // Not used directly. Initializes CrosSettings for testing.
163   chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
164   chromeos::ScopedTestCrosSettings test_cros_settings_;
165 #endif
166
167   DISALLOW_COPY_AND_ASSIGN(VariationsServiceTest);
168 };
169
170 #if !defined(OS_CHROMEOS)
171 TEST_F(VariationsServiceTest, VariationsURLIsValid) {
172 #if defined(OS_ANDROID)
173   // Android uses profile prefs as the PrefService to generate the URL.
174   TestingPrefServiceSyncable prefs;
175   VariationsService::RegisterProfilePrefs(prefs.registry());
176 #else
177   TestingPrefServiceSimple prefs;
178   VariationsService::RegisterPrefs(prefs.registry());
179 #endif
180   const std::string default_variations_url =
181       VariationsService::GetDefaultVariationsServerURLForTesting();
182
183   std::string value;
184   GURL url = VariationsService::GetVariationsServerURL(&prefs);
185   EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
186   EXPECT_FALSE(net::GetValueForKeyInQuery(url, "restrict", &value));
187
188   prefs.SetString(prefs::kVariationsRestrictParameter, "restricted");
189   url = VariationsService::GetVariationsServerURL(&prefs);
190   EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
191   EXPECT_TRUE(net::GetValueForKeyInQuery(url, "restrict", &value));
192   EXPECT_EQ("restricted", value);
193 }
194 #else
195 class VariationsServiceTestChromeOS : public VariationsServiceTest {
196  protected:
197   VariationsServiceTestChromeOS() {}
198
199   virtual void SetUp() override {
200     cros_settings_ = chromeos::CrosSettings::Get();
201     DCHECK(cros_settings_ != NULL);
202     // Remove the real DeviceSettingsProvider and replace it with a stub that
203     // allows modifications in a test.
204     device_settings_provider_ = cros_settings_->GetProvider(
205         chromeos::kReportDeviceVersionInfo);
206     EXPECT_TRUE(device_settings_provider_ != NULL);
207     EXPECT_TRUE(cros_settings_->RemoveSettingsProvider(
208         device_settings_provider_));
209     cros_settings_->AddSettingsProvider(&stub_settings_provider_);
210   }
211
212   virtual void TearDown() override {
213     // Restore the real DeviceSettingsProvider.
214     EXPECT_TRUE(
215         cros_settings_->RemoveSettingsProvider(&stub_settings_provider_));
216     cros_settings_->AddSettingsProvider(device_settings_provider_);
217   }
218
219   void SetVariationsRestrictParameterPolicyValue(std::string value) {
220     cros_settings_->SetString(chromeos::kVariationsRestrictParameter, value);
221   }
222
223  private:
224   chromeos::CrosSettings* cros_settings_;
225   chromeos::StubCrosSettingsProvider stub_settings_provider_;
226   chromeos::CrosSettingsProvider* device_settings_provider_;
227
228   DISALLOW_COPY_AND_ASSIGN(VariationsServiceTestChromeOS);
229 };
230
231 TEST_F(VariationsServiceTestChromeOS, VariationsURLIsValid) {
232   TestingPrefServiceSimple prefs;
233   VariationsService::RegisterPrefs(prefs.registry());
234   const std::string default_variations_url =
235       VariationsService::GetDefaultVariationsServerURLForTesting();
236
237   std::string value;
238   GURL url = VariationsService::GetVariationsServerURL(&prefs);
239   EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
240   EXPECT_FALSE(net::GetValueForKeyInQuery(url, "restrict", &value));
241
242   SetVariationsRestrictParameterPolicyValue("restricted");
243   url = VariationsService::GetVariationsServerURL(&prefs);
244   EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
245   EXPECT_TRUE(net::GetValueForKeyInQuery(url, "restrict", &value));
246   EXPECT_EQ("restricted", value);
247 }
248 #endif
249
250 TEST_F(VariationsServiceTest, VariationsURLHasOSNameParam) {
251   TestingPrefServiceSimple prefs;
252   VariationsService::RegisterPrefs(prefs.registry());
253   const GURL url = VariationsService::GetVariationsServerURL(&prefs);
254
255   std::string value;
256   EXPECT_TRUE(net::GetValueForKeyInQuery(url, "osname", &value));
257   EXPECT_FALSE(value.empty());
258 }
259
260 TEST_F(VariationsServiceTest, RequestsInitiallyNotAllowed) {
261   base::MessageLoopForUI message_loop;
262   content::TestBrowserThread ui_thread(content::BrowserThread::UI,
263                                        &message_loop);
264   TestingPrefServiceSimple prefs;
265   VariationsService::RegisterPrefs(prefs.registry());
266
267   // Pass ownership to TestVariationsService, but keep a weak pointer to
268   // manipulate it for this test.
269   TestRequestAllowedNotifier* test_notifier = new TestRequestAllowedNotifier;
270   TestVariationsService test_service(test_notifier, &prefs);
271
272   // Force the notifier to initially disallow requests.
273   test_notifier->SetRequestsAllowedOverride(false);
274   test_service.StartRepeatedVariationsSeedFetch();
275   EXPECT_FALSE(test_service.fetch_attempted());
276
277   test_notifier->NotifyObserver();
278   EXPECT_TRUE(test_service.fetch_attempted());
279 }
280
281 TEST_F(VariationsServiceTest, RequestsInitiallyAllowed) {
282   base::MessageLoopForUI message_loop;
283   content::TestBrowserThread ui_thread(content::BrowserThread::UI,
284                                        &message_loop);
285   TestingPrefServiceSimple prefs;
286   VariationsService::RegisterPrefs(prefs.registry());
287
288   // Pass ownership to TestVariationsService, but keep a weak pointer to
289   // manipulate it for this test.
290   TestRequestAllowedNotifier* test_notifier = new TestRequestAllowedNotifier;
291   TestVariationsService test_service(test_notifier, &prefs);
292
293   test_notifier->SetRequestsAllowedOverride(true);
294   test_service.StartRepeatedVariationsSeedFetch();
295   EXPECT_TRUE(test_service.fetch_attempted());
296 }
297
298 TEST_F(VariationsServiceTest, SeedStoredWhenOKStatus) {
299   base::MessageLoop message_loop;
300   content::TestBrowserThread io_thread(content::BrowserThread::IO,
301                                        &message_loop);
302   TestingPrefServiceSimple prefs;
303   VariationsService::RegisterPrefs(prefs.registry());
304
305   TestVariationsService service(new TestRequestAllowedNotifier, &prefs);
306   service.set_intercepts_fetch(false);
307
308   net::TestURLFetcherFactory factory;
309   service.DoActualFetch();
310
311   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
312   SimulateServerResponse(net::HTTP_OK, fetcher);
313   fetcher->SetResponseString(SerializeSeed(CreateTestSeed()));
314
315   EXPECT_FALSE(service.seed_stored());
316   service.OnURLFetchComplete(fetcher);
317   EXPECT_TRUE(service.seed_stored());
318 }
319
320 TEST_F(VariationsServiceTest, SeedNotStoredWhenNonOKStatus) {
321   const int non_ok_status_codes[] = {
322     net::HTTP_NO_CONTENT,
323     net::HTTP_NOT_MODIFIED,
324     net::HTTP_NOT_FOUND,
325     net::HTTP_INTERNAL_SERVER_ERROR,
326     net::HTTP_SERVICE_UNAVAILABLE,
327   };
328
329   base::MessageLoop message_loop;
330   content::TestBrowserThread io_thread(content::BrowserThread::IO,
331                                        &message_loop);
332   TestingPrefServiceSimple prefs;
333   VariationsService::RegisterPrefs(prefs.registry());
334
335   VariationsService service(new TestRequestAllowedNotifier, &prefs, NULL);
336   for (size_t i = 0; i < arraysize(non_ok_status_codes); ++i) {
337     net::TestURLFetcherFactory factory;
338     service.DoActualFetch();
339     EXPECT_TRUE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
340
341     net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
342     SimulateServerResponse(non_ok_status_codes[i], fetcher);
343     service.OnURLFetchComplete(fetcher);
344
345     EXPECT_TRUE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
346   }
347 }
348
349 TEST_F(VariationsServiceTest, SeedDateUpdatedOn304Status) {
350   base::MessageLoop message_loop;
351   content::TestBrowserThread io_thread(content::BrowserThread::IO,
352                                        &message_loop);
353   TestingPrefServiceSimple prefs;
354   VariationsService::RegisterPrefs(prefs.registry());
355
356   VariationsService service(new TestRequestAllowedNotifier, &prefs, NULL);
357   net::TestURLFetcherFactory factory;
358   service.DoActualFetch();
359   EXPECT_TRUE(
360       prefs.FindPreference(prefs::kVariationsSeedDate)->IsDefaultValue());
361
362   net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
363   SimulateServerResponse(net::HTTP_NOT_MODIFIED, fetcher);
364   service.OnURLFetchComplete(fetcher);
365   EXPECT_FALSE(
366       prefs.FindPreference(prefs::kVariationsSeedDate)->IsDefaultValue());
367 }
368
369 TEST_F(VariationsServiceTest, Observer) {
370   TestingPrefServiceSimple prefs;
371   VariationsService::RegisterPrefs(prefs.registry());
372   VariationsService service(new TestRequestAllowedNotifier, &prefs, NULL);
373
374   struct {
375     int normal_count;
376     int best_effort_count;
377     int critical_count;
378     int expected_best_effort_notifications;
379     int expected_crtical_notifications;
380   } cases[] = {
381       {0, 0, 0, 0, 0},
382       {1, 0, 0, 0, 0},
383       {10, 0, 0, 0, 0},
384       {0, 1, 0, 1, 0},
385       {0, 10, 0, 1, 0},
386       {0, 0, 1, 0, 1},
387       {0, 0, 10, 0, 1},
388       {0, 1, 1, 0, 1},
389       {1, 1, 1, 0, 1},
390       {1, 1, 0, 1, 0},
391       {1, 0, 1, 0, 1},
392   };
393
394   for (size_t i = 0; i < arraysize(cases); ++i) {
395     TestVariationsServiceObserver observer;
396     service.AddObserver(&observer);
397
398     variations::VariationsSeedSimulator::Result result;
399     result.normal_group_change_count = cases[i].normal_count;
400     result.kill_best_effort_group_change_count = cases[i].best_effort_count;
401     result.kill_critical_group_change_count = cases[i].critical_count;
402     service.NotifyObservers(result);
403
404     EXPECT_EQ(cases[i].expected_best_effort_notifications,
405               observer.best_effort_changes_notified()) << i;
406     EXPECT_EQ(cases[i].expected_crtical_notifications,
407               observer.crticial_changes_notified()) << i;
408
409     service.RemoveObserver(&observer);
410   }
411 }
412
413 }  // namespace chrome_variations