Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / metrics / variations / variations_service_unittest.cc
blob6f67e9cd0e1923b10e6d88e3a066cca96c2d34cf
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/common/pref_names.h"
15 #include "chrome/test/base/testing_browser_process.h"
16 #include "chrome/test/base/testing_pref_service_syncable.h"
17 #include "components/variations/proto/study.pb.h"
18 #include "components/variations/proto/variations_seed.pb.h"
19 #include "components/web_resource/resource_request_allowed_notifier_test_util.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(web_resource::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 ~TestVariationsService() override {}
52 void set_intercepts_fetch(bool value) {
53 intercepts_fetch_ = value;
56 bool fetch_attempted() const { return fetch_attempted_; }
58 bool seed_stored() const { return seed_stored_; }
60 void DoActualFetch() override {
61 if (intercepts_fetch_) {
62 fetch_attempted_ = true;
63 return;
66 VariationsService::DoActualFetch();
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;
76 private:
77 bool intercepts_fetch_;
78 bool fetch_attempted_;
79 bool seed_stored_;
81 DISALLOW_COPY_AND_ASSIGN(TestVariationsService);
84 class TestVariationsServiceObserver : public VariationsService::Observer {
85 public:
86 TestVariationsServiceObserver()
87 : best_effort_changes_notified_(0),
88 crticial_changes_notified_(0) {
90 ~TestVariationsServiceObserver() override {}
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;
103 int best_effort_changes_notified() const {
104 return best_effort_changes_notified_;
107 int crticial_changes_notified() const {
108 return crticial_changes_notified_;
111 private:
112 // Number of notification received with BEST_EFFORT severity.
113 int best_effort_changes_notified_;
115 // Number of notification received with CRITICAL severity.
116 int crticial_changes_notified_;
118 DISALLOW_COPY_AND_ASSIGN(TestVariationsServiceObserver);
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;
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;
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);
154 // Helper class that abstracts away platform-specific details relating to the
155 // pref store used for the "restrict" param policy.
156 class TestVariationsPrefsStore {
157 public:
158 TestVariationsPrefsStore() {
159 #if defined(OS_ANDROID)
160 // Android uses profile prefs as the PrefService to generate the URL.
161 VariationsService::RegisterProfilePrefs(prefs_.registry());
162 #else
163 VariationsService::RegisterPrefs(prefs_.registry());
164 #endif
166 #if defined(OS_CHROMEOS)
167 cros_settings_ = chromeos::CrosSettings::Get();
168 DCHECK(cros_settings_ != NULL);
169 // Remove the real DeviceSettingsProvider and replace it with a stub that
170 // allows modifications in a test.
171 // TODO(asvitkine): Make a scoped helper class for this operation.
172 device_settings_provider_ = cros_settings_->GetProvider(
173 chromeos::kReportDeviceVersionInfo);
174 EXPECT_TRUE(device_settings_provider_ != NULL);
175 EXPECT_TRUE(cros_settings_->RemoveSettingsProvider(
176 device_settings_provider_));
177 cros_settings_->AddSettingsProvider(&stub_settings_provider_);
178 #endif
181 ~TestVariationsPrefsStore() {
182 #if defined(OS_CHROMEOS)
183 // Restore the real DeviceSettingsProvider.
184 EXPECT_TRUE(
185 cros_settings_->RemoveSettingsProvider(&stub_settings_provider_));
186 cros_settings_->AddSettingsProvider(device_settings_provider_);
187 #endif
190 void SetVariationsRestrictParameterPolicyValue(const std::string& value) {
191 #if defined(OS_CHROMEOS)
192 cros_settings_->SetString(chromeos::kVariationsRestrictParameter, value);
193 #else
194 prefs_.SetString(prefs::kVariationsRestrictParameter, value);
195 #endif
198 PrefService* prefs() { return &prefs_; }
200 private:
201 #if defined(OS_ANDROID)
202 // Android uses profile prefs as the PrefService to generate the URL.
203 TestingPrefServiceSyncable prefs_;
204 #else
205 TestingPrefServiceSimple prefs_;
206 #endif
208 #if defined(OS_CHROMEOS)
209 chromeos::CrosSettings* cros_settings_;
210 chromeos::StubCrosSettingsProvider stub_settings_provider_;
211 chromeos::CrosSettingsProvider* device_settings_provider_;
212 #endif
214 DISALLOW_COPY_AND_ASSIGN(TestVariationsPrefsStore);
217 } // namespace
219 class VariationsServiceTest : public ::testing::Test {
220 protected:
221 VariationsServiceTest() {}
223 private:
224 #if defined(OS_CHROMEOS)
225 // Not used directly. Initializes CrosSettings for testing.
226 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_;
227 chromeos::ScopedTestCrosSettings test_cros_settings_;
228 #endif
230 DISALLOW_COPY_AND_ASSIGN(VariationsServiceTest);
233 TEST_F(VariationsServiceTest, GetVariationsServerURL) {
234 TestVariationsPrefsStore prefs_store;
235 PrefService* prefs = prefs_store.prefs();
236 const std::string default_variations_url =
237 VariationsService::GetDefaultVariationsServerURLForTesting();
239 std::string value;
240 GURL url = VariationsService::GetVariationsServerURL(prefs, std::string());
241 EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
242 EXPECT_FALSE(net::GetValueForKeyInQuery(url, "restrict", &value));
244 prefs_store.SetVariationsRestrictParameterPolicyValue("restricted");
245 url = VariationsService::GetVariationsServerURL(prefs, std::string());
246 EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
247 EXPECT_TRUE(net::GetValueForKeyInQuery(url, "restrict", &value));
248 EXPECT_EQ("restricted", value);
250 // The override value should take precedence over what's in prefs.
251 url = VariationsService::GetVariationsServerURL(prefs, "override");
252 EXPECT_TRUE(StartsWithASCII(url.spec(), default_variations_url, true));
253 EXPECT_TRUE(net::GetValueForKeyInQuery(url, "restrict", &value));
254 EXPECT_EQ("override", value);
257 TEST_F(VariationsServiceTest, VariationsURLHasOSNameParam) {
258 TestingPrefServiceSimple prefs;
259 VariationsService::RegisterPrefs(prefs.registry());
260 const GURL url =
261 VariationsService::GetVariationsServerURL(&prefs, std::string());
263 std::string value;
264 EXPECT_TRUE(net::GetValueForKeyInQuery(url, "osname", &value));
265 EXPECT_FALSE(value.empty());
268 TEST_F(VariationsServiceTest, RequestsInitiallyNotAllowed) {
269 base::MessageLoopForUI message_loop;
270 content::TestBrowserThread ui_thread(content::BrowserThread::UI,
271 &message_loop);
272 TestingPrefServiceSimple prefs;
273 VariationsService::RegisterPrefs(prefs.registry());
275 // Pass ownership to TestVariationsService, but keep a weak pointer to
276 // manipulate it for this test.
277 web_resource::TestRequestAllowedNotifier* test_notifier =
278 new web_resource::TestRequestAllowedNotifier(&prefs);
279 TestVariationsService test_service(test_notifier, &prefs);
281 // Force the notifier to initially disallow requests.
282 test_notifier->SetRequestsAllowedOverride(false);
283 test_service.StartRepeatedVariationsSeedFetch();
284 EXPECT_FALSE(test_service.fetch_attempted());
286 test_notifier->NotifyObserver();
287 EXPECT_TRUE(test_service.fetch_attempted());
290 TEST_F(VariationsServiceTest, RequestsInitiallyAllowed) {
291 base::MessageLoopForUI message_loop;
292 content::TestBrowserThread ui_thread(content::BrowserThread::UI,
293 &message_loop);
294 TestingPrefServiceSimple prefs;
295 VariationsService::RegisterPrefs(prefs.registry());
297 // Pass ownership to TestVariationsService, but keep a weak pointer to
298 // manipulate it for this test.
299 web_resource::TestRequestAllowedNotifier* test_notifier =
300 new web_resource::TestRequestAllowedNotifier(&prefs);
301 TestVariationsService test_service(test_notifier, &prefs);
303 test_notifier->SetRequestsAllowedOverride(true);
304 test_service.StartRepeatedVariationsSeedFetch();
305 EXPECT_TRUE(test_service.fetch_attempted());
308 TEST_F(VariationsServiceTest, SeedStoredWhenOKStatus) {
309 base::MessageLoop message_loop;
310 content::TestBrowserThread io_thread(content::BrowserThread::IO,
311 &message_loop);
312 TestingPrefServiceSimple prefs;
313 VariationsService::RegisterPrefs(prefs.registry());
315 TestVariationsService service(
316 new web_resource::TestRequestAllowedNotifier(&prefs), &prefs);
317 service.variations_server_url_ =
318 VariationsService::GetVariationsServerURL(&prefs, std::string());
319 service.set_intercepts_fetch(false);
321 net::TestURLFetcherFactory factory;
322 service.DoActualFetch();
324 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
325 SimulateServerResponse(net::HTTP_OK, fetcher);
326 fetcher->SetResponseString(SerializeSeed(CreateTestSeed()));
328 EXPECT_FALSE(service.seed_stored());
329 service.OnURLFetchComplete(fetcher);
330 EXPECT_TRUE(service.seed_stored());
333 TEST_F(VariationsServiceTest, SeedNotStoredWhenNonOKStatus) {
334 const int non_ok_status_codes[] = {
335 net::HTTP_NO_CONTENT,
336 net::HTTP_NOT_MODIFIED,
337 net::HTTP_NOT_FOUND,
338 net::HTTP_INTERNAL_SERVER_ERROR,
339 net::HTTP_SERVICE_UNAVAILABLE,
342 base::MessageLoop message_loop;
343 content::TestBrowserThread io_thread(content::BrowserThread::IO,
344 &message_loop);
345 TestingPrefServiceSimple prefs;
346 VariationsService::RegisterPrefs(prefs.registry());
348 VariationsService service(
349 new web_resource::TestRequestAllowedNotifier(&prefs), &prefs, NULL);
350 service.variations_server_url_ =
351 VariationsService::GetVariationsServerURL(&prefs, std::string());
352 for (size_t i = 0; i < arraysize(non_ok_status_codes); ++i) {
353 net::TestURLFetcherFactory factory;
354 service.DoActualFetch();
355 EXPECT_TRUE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
357 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
358 SimulateServerResponse(non_ok_status_codes[i], fetcher);
359 service.OnURLFetchComplete(fetcher);
361 EXPECT_TRUE(prefs.FindPreference(prefs::kVariationsSeed)->IsDefaultValue());
365 TEST_F(VariationsServiceTest, SeedDateUpdatedOn304Status) {
366 base::MessageLoop message_loop;
367 content::TestBrowserThread io_thread(content::BrowserThread::IO,
368 &message_loop);
369 TestingPrefServiceSimple prefs;
370 VariationsService::RegisterPrefs(prefs.registry());
372 net::TestURLFetcherFactory factory;
373 VariationsService service(
374 new web_resource::TestRequestAllowedNotifier(&prefs), &prefs, NULL);
375 service.variations_server_url_ =
376 VariationsService::GetVariationsServerURL(&prefs, std::string());
377 service.DoActualFetch();
378 EXPECT_TRUE(
379 prefs.FindPreference(prefs::kVariationsSeedDate)->IsDefaultValue());
381 net::TestURLFetcher* fetcher = factory.GetFetcherByID(0);
382 SimulateServerResponse(net::HTTP_NOT_MODIFIED, fetcher);
383 service.OnURLFetchComplete(fetcher);
384 EXPECT_FALSE(
385 prefs.FindPreference(prefs::kVariationsSeedDate)->IsDefaultValue());
388 TEST_F(VariationsServiceTest, Observer) {
389 TestingPrefServiceSimple prefs;
390 VariationsService::RegisterPrefs(prefs.registry());
391 VariationsService service(
392 new web_resource::TestRequestAllowedNotifier(&prefs), &prefs, NULL);
394 struct {
395 int normal_count;
396 int best_effort_count;
397 int critical_count;
398 int expected_best_effort_notifications;
399 int expected_crtical_notifications;
400 } cases[] = {
401 {0, 0, 0, 0, 0},
402 {1, 0, 0, 0, 0},
403 {10, 0, 0, 0, 0},
404 {0, 1, 0, 1, 0},
405 {0, 10, 0, 1, 0},
406 {0, 0, 1, 0, 1},
407 {0, 0, 10, 0, 1},
408 {0, 1, 1, 0, 1},
409 {1, 1, 1, 0, 1},
410 {1, 1, 0, 1, 0},
411 {1, 0, 1, 0, 1},
414 for (size_t i = 0; i < arraysize(cases); ++i) {
415 TestVariationsServiceObserver observer;
416 service.AddObserver(&observer);
418 variations::VariationsSeedSimulator::Result result;
419 result.normal_group_change_count = cases[i].normal_count;
420 result.kill_best_effort_group_change_count = cases[i].best_effort_count;
421 result.kill_critical_group_change_count = cases[i].critical_count;
422 service.NotifyObservers(result);
424 EXPECT_EQ(cases[i].expected_best_effort_notifications,
425 observer.best_effort_changes_notified()) << i;
426 EXPECT_EQ(cases[i].expected_crtical_notifications,
427 observer.crticial_changes_notified()) << i;
429 service.RemoveObserver(&observer);
433 } // namespace chrome_variations