Add GCMChannelStatusSyncer to schedule requests and enable/disable GCM
[chromium-blink-merge.git] / chrome / browser / metrics / variations / variations_service_unittest.cc
blobbd5e134d1fa305f0cca1da592a12e444d025fe96
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 "chrome/browser/metrics/variations/variations_service.h"
7 #include <vector>
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"
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
33 namespace chrome_variations {
35 namespace {
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);
50 virtual ~TestVariationsService() {
53 void set_intercepts_fetch(bool value) {
54 intercepts_fetch_ = value;
57 bool fetch_attempted() const { return fetch_attempted_; }
59 bool seed_stored() const { return seed_stored_; }
61 virtual void DoActualFetch() OVERRIDE {
62 if (intercepts_fetch_) {
63 fetch_attempted_ = true;
64 return;
67 VariationsService::DoActualFetch();
70 protected:
71 virtual void StoreSeed(const std::string& seed_data,
72 const std::string& seed_signature,
73 const base::Time& date_fetched) OVERRIDE {
74 seed_stored_ = true;
77 private:
78 bool intercepts_fetch_;
79 bool fetch_attempted_;
80 bool seed_stored_;
82 DISALLOW_COPY_AND_ASSIGN(TestVariationsService);
85 class TestVariationsServiceObserver : public VariationsService::Observer {
86 public:
87 TestVariationsServiceObserver()
88 : best_effort_changes_notified_(0),
89 crticial_changes_notified_(0) {
91 virtual ~TestVariationsServiceObserver() {
94 virtual void OnExperimentChangesDetected(Severity severity) OVERRIDE {
95 switch (severity) {
96 case BEST_EFFORT:
97 ++best_effort_changes_notified_;
98 break;
99 case CRITICAL:
100 ++crticial_changes_notified_;
101 break;
105 int best_effort_changes_notified() const {
106 return best_effort_changes_notified_;
109 int crticial_changes_notified() const {
110 return crticial_changes_notified_;
113 private:
114 // Number of notification received with BEST_EFFORT severity.
115 int best_effort_changes_notified_;
117 // Number of notification received with CRITICAL severity.
118 int crticial_changes_notified_;
120 DISALLOW_COPY_AND_ASSIGN(TestVariationsServiceObserver);
123 // Populates |seed| with simple test data. The resulting seed will contain one
124 // study called "test", which contains one experiment called "abc" with
125 // probability weight 100. |seed|'s study field will be cleared before adding
126 // the new study.
127 variations::VariationsSeed CreateTestSeed() {
128 variations::VariationsSeed seed;
129 variations::Study* study = seed.add_study();
130 study->set_name("test");
131 study->set_default_experiment_name("abc");
132 variations::Study_Experiment* experiment = study->add_experiment();
133 experiment->set_name("abc");
134 experiment->set_probability_weight(100);
135 seed.set_serial_number("123");
136 return seed;
139 // Serializes |seed| to protobuf binary format.
140 std::string SerializeSeed(const variations::VariationsSeed& seed) {
141 std::string serialized_seed;
142 seed.SerializeToString(&serialized_seed);
143 return serialized_seed;
146 // Simulates a variations service response by setting a date header and the
147 // specified HTTP |response_code| on |fetcher|.
148 void SimulateServerResponse(int response_code, net::TestURLFetcher* fetcher) {
149 ASSERT_TRUE(fetcher);
150 scoped_refptr<net::HttpResponseHeaders> headers(
151 new net::HttpResponseHeaders("date:Wed, 13 Feb 2013 00:25:24 GMT\0\0"));
152 fetcher->set_response_headers(headers);
153 fetcher->set_response_code(response_code);
156 } // namespace
158 class VariationsServiceTest : public ::testing::Test {
159 protected:
160 VariationsServiceTest() {}
162 private:
163 #if defined(OS_CHROMEOS)
164 // Not used directly. Initializes CrosSettings for testing.
165 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
166 chromeos::ScopedTestCrosSettings test_cros_settings_;
167 #endif
169 DISALLOW_COPY_AND_ASSIGN(VariationsServiceTest);
172 #if !defined(OS_CHROMEOS)
173 TEST_F(VariationsServiceTest, VariationsURLIsValid) {
174 #if defined(OS_ANDROID)
175 // Android uses profile prefs as the PrefService to generate the URL.
176 TestingPrefServiceSyncable prefs;
177 VariationsService::RegisterProfilePrefs(prefs.registry());
178 #else
179 TestingPrefServiceSimple prefs;
180 VariationsService::RegisterPrefs(prefs.registry());
181 #endif
182 const std::string default_variations_url =
183 VariationsService::GetDefaultVariationsServerURLForTesting();
185 std::string value;
186 GURL url = VariationsService::GetVariationsServerURL(&prefs);
187 EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
188 EXPECT_FALSE(net::GetValueForKeyInQuery(url, "restrict", &value));
190 prefs.SetString(prefs::kVariationsRestrictParameter, "restricted");
191 url = VariationsService::GetVariationsServerURL(&prefs);
192 EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
193 EXPECT_TRUE(net::GetValueForKeyInQuery(url, "restrict", &value));
194 EXPECT_EQ("restricted", value);
196 #else
197 class VariationsServiceTestChromeOS : public VariationsServiceTest {
198 protected:
199 VariationsServiceTestChromeOS() {}
201 virtual void SetUp() OVERRIDE {
202 cros_settings_ = chromeos::CrosSettings::Get();
203 DCHECK(cros_settings_ != NULL);
204 // Remove the real DeviceSettingsProvider and replace it with a stub that
205 // allows modifications in a test.
206 device_settings_provider_ = cros_settings_->GetProvider(
207 chromeos::kReportDeviceVersionInfo);
208 EXPECT_TRUE(device_settings_provider_ != NULL);
209 EXPECT_TRUE(cros_settings_->RemoveSettingsProvider(
210 device_settings_provider_));
211 cros_settings_->AddSettingsProvider(&stub_settings_provider_);
214 virtual void TearDown() OVERRIDE {
215 // Restore the real DeviceSettingsProvider.
216 EXPECT_TRUE(
217 cros_settings_->RemoveSettingsProvider(&stub_settings_provider_));
218 cros_settings_->AddSettingsProvider(device_settings_provider_);
221 void SetVariationsRestrictParameterPolicyValue(std::string value) {
222 cros_settings_->SetString(chromeos::kVariationsRestrictParameter, value);
225 private:
226 chromeos::CrosSettings* cros_settings_;
227 chromeos::StubCrosSettingsProvider stub_settings_provider_;
228 chromeos::CrosSettingsProvider* device_settings_provider_;
230 DISALLOW_COPY_AND_ASSIGN(VariationsServiceTestChromeOS);
233 TEST_F(VariationsServiceTestChromeOS, VariationsURLIsValid) {
234 TestingPrefServiceSimple prefs;
235 VariationsService::RegisterPrefs(prefs.registry());
236 const std::string default_variations_url =
237 VariationsService::GetDefaultVariationsServerURLForTesting();
239 std::string value;
240 GURL url = VariationsService::GetVariationsServerURL(&prefs);
241 EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
242 EXPECT_FALSE(net::GetValueForKeyInQuery(url, "restrict", &value));
244 SetVariationsRestrictParameterPolicyValue("restricted");
245 url = VariationsService::GetVariationsServerURL(&prefs);
246 EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
247 EXPECT_TRUE(net::GetValueForKeyInQuery(url, "restrict", &value));
248 EXPECT_EQ("restricted", value);
250 #endif
252 TEST_F(VariationsServiceTest, VariationsURLHasOSNameParam) {
253 TestingPrefServiceSimple prefs;
254 VariationsService::RegisterPrefs(prefs.registry());
255 const GURL url = VariationsService::GetVariationsServerURL(&prefs);
257 std::string value;
258 EXPECT_TRUE(net::GetValueForKeyInQuery(url, "osname", &value));
259 EXPECT_FALSE(value.empty());
262 TEST_F(VariationsServiceTest, RequestsInitiallyNotAllowed) {
263 base::MessageLoopForUI message_loop;
264 content::TestBrowserThread ui_thread(content::BrowserThread::UI,
265 &message_loop);
266 TestingPrefServiceSimple prefs;
267 VariationsService::RegisterPrefs(prefs.registry());
269 // Pass ownership to TestVariationsService, but keep a weak pointer to
270 // manipulate it for this test.
271 TestRequestAllowedNotifier* test_notifier = new TestRequestAllowedNotifier;
272 TestVariationsService test_service(test_notifier, &prefs);
274 // Force the notifier to initially disallow requests.
275 test_notifier->SetRequestsAllowedOverride(false);
276 test_service.StartRepeatedVariationsSeedFetch();
277 EXPECT_FALSE(test_service.fetch_attempted());
279 test_notifier->NotifyObserver();
280 EXPECT_TRUE(test_service.fetch_attempted());
283 TEST_F(VariationsServiceTest, RequestsInitiallyAllowed) {
284 base::MessageLoopForUI message_loop;
285 content::TestBrowserThread ui_thread(content::BrowserThread::UI,
286 &message_loop);
287 TestingPrefServiceSimple prefs;
288 VariationsService::RegisterPrefs(prefs.registry());
290 // Pass ownership to TestVariationsService, but keep a weak pointer to
291 // manipulate it for this test.
292 TestRequestAllowedNotifier* test_notifier = new TestRequestAllowedNotifier;
293 TestVariationsService test_service(test_notifier, &prefs);
295 test_notifier->SetRequestsAllowedOverride(true);
296 test_service.StartRepeatedVariationsSeedFetch();
297 EXPECT_TRUE(test_service.fetch_attempted());
300 TEST_F(VariationsServiceTest, SeedStoredWhenOKStatus) {
301 base::MessageLoop message_loop;
302 content::TestBrowserThread io_thread(content::BrowserThread::IO,
303 &message_loop);
304 TestingPrefServiceSimple prefs;
305 VariationsService::RegisterPrefs(prefs.registry());
307 TestVariationsService service(new TestRequestAllowedNotifier, &prefs);
308 service.set_intercepts_fetch(false);
310 net::TestURLFetcherFactory factory;
311 service.DoActualFetch();
313 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
314 SimulateServerResponse(net::HTTP_OK, fetcher);
315 fetcher->SetResponseString(SerializeSeed(CreateTestSeed()));
317 EXPECT_FALSE(service.seed_stored());
318 service.OnURLFetchComplete(fetcher);
319 EXPECT_TRUE(service.seed_stored());
322 TEST_F(VariationsServiceTest, SeedNotStoredWhenNonOKStatus) {
323 const int non_ok_status_codes[] = {
324 net::HTTP_NO_CONTENT,
325 net::HTTP_NOT_MODIFIED,
326 net::HTTP_NOT_FOUND,
327 net::HTTP_INTERNAL_SERVER_ERROR,
328 net::HTTP_SERVICE_UNAVAILABLE,
331 base::MessageLoop message_loop;
332 content::TestBrowserThread io_thread(content::BrowserThread::IO,
333 &message_loop);
334 TestingPrefServiceSimple prefs;
335 VariationsService::RegisterPrefs(prefs.registry());
337 VariationsService service(new TestRequestAllowedNotifier, &prefs, NULL);
338 for (size_t i = 0; i < arraysize(non_ok_status_codes); ++i) {
339 net::TestURLFetcherFactory factory;
340 service.DoActualFetch();
341 EXPECT_TRUE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
343 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
344 SimulateServerResponse(non_ok_status_codes[i], fetcher);
345 service.OnURLFetchComplete(fetcher);
347 EXPECT_TRUE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
351 TEST_F(VariationsServiceTest, SeedDateUpdatedOn304Status) {
352 base::MessageLoop message_loop;
353 content::TestBrowserThread io_thread(content::BrowserThread::IO,
354 &message_loop);
355 TestingPrefServiceSimple prefs;
356 VariationsService::RegisterPrefs(prefs.registry());
358 VariationsService service(new TestRequestAllowedNotifier, &prefs, NULL);
359 net::TestURLFetcherFactory factory;
360 service.DoActualFetch();
361 EXPECT_TRUE(
362 prefs.FindPreference(prefs::kVariationsSeedDate)->IsDefaultValue());
364 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
365 SimulateServerResponse(net::HTTP_NOT_MODIFIED, fetcher);
366 service.OnURLFetchComplete(fetcher);
367 EXPECT_FALSE(
368 prefs.FindPreference(prefs::kVariationsSeedDate)->IsDefaultValue());
371 TEST_F(VariationsServiceTest, Observer) {
372 TestingPrefServiceSimple prefs;
373 VariationsService::RegisterPrefs(prefs.registry());
374 VariationsService service(new TestRequestAllowedNotifier, &prefs, NULL);
376 struct {
377 int normal_count;
378 int best_effort_count;
379 int critical_count;
380 int expected_best_effort_notifications;
381 int expected_crtical_notifications;
382 } cases[] = {
383 {0, 0, 0, 0, 0},
384 {1, 0, 0, 0, 0},
385 {10, 0, 0, 0, 0},
386 {0, 1, 0, 1, 0},
387 {0, 10, 0, 1, 0},
388 {0, 0, 1, 0, 1},
389 {0, 0, 10, 0, 1},
390 {0, 1, 1, 0, 1},
391 {1, 1, 1, 0, 1},
392 {1, 1, 0, 1, 0},
393 {1, 0, 1, 0, 1},
396 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(cases); ++i) {
397 TestVariationsServiceObserver observer;
398 service.AddObserver(&observer);
400 variations::VariationsSeedSimulator::Result result;
401 result.normal_group_change_count = cases[i].normal_count;
402 result.kill_best_effort_group_change_count = cases[i].best_effort_count;
403 result.kill_critical_group_change_count = cases[i].critical_count;
404 service.NotifyObservers(result);
406 EXPECT_EQ(cases[i].expected_best_effort_notifications,
407 observer.best_effort_changes_notified()) << i;
408 EXPECT_EQ(cases[i].expected_crtical_notifications,
409 observer.crticial_changes_notified()) << i;
411 service.RemoveObserver(&observer);
415 } // namespace chrome_variations