Add ENABLE_MEDIA_ROUTER define to builds other than Android and iOS.
[chromium-blink-merge.git] / chrome / browser / captive_portal / captive_portal_service_unittest.cc
blobc835721baf66093672082d1357bcf8a606eef231
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/captive_portal/captive_portal_service.h"
7 #include "base/basictypes.h"
8 #include "base/bind.h"
9 #include "base/command_line.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/run_loop.h"
12 #include "base/test/test_timeouts.h"
13 #include "chrome/browser/chrome_notification_types.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/pref_names.h"
16 #include "chrome/test/base/testing_profile.h"
17 #include "components/captive_portal/captive_portal_testing_utils.h"
18 #include "content/public/browser/notification_details.h"
19 #include "content/public/browser/notification_observer.h"
20 #include "content/public/browser/notification_registrar.h"
21 #include "content/public/browser/notification_source.h"
22 #include "content/public/test/test_browser_thread_bundle.h"
23 #include "net/base/net_errors.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using captive_portal::CaptivePortalDetectorTestBase;
27 using captive_portal::CaptivePortalResult;
29 namespace {
31 // An observer watches the CaptivePortalDetector. It tracks the last
32 // received result and the total number of received results.
33 class CaptivePortalObserver : public content::NotificationObserver {
34 public:
35 CaptivePortalObserver(Profile* profile,
36 CaptivePortalService* captive_portal_service)
37 : captive_portal_result_(
38 captive_portal_service->last_detection_result()),
39 num_results_received_(0),
40 profile_(profile),
41 captive_portal_service_(captive_portal_service) {
42 registrar_.Add(this,
43 chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
44 content::Source<Profile>(profile_));
47 CaptivePortalResult captive_portal_result() const {
48 return captive_portal_result_;
51 int num_results_received() const { return num_results_received_; }
53 private:
54 void Observe(int type,
55 const content::NotificationSource& source,
56 const content::NotificationDetails& details) override {
57 ASSERT_EQ(type, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT);
58 ASSERT_EQ(profile_, content::Source<Profile>(source).ptr());
60 CaptivePortalService::Results *results =
61 content::Details<CaptivePortalService::Results>(details).ptr();
63 EXPECT_EQ(captive_portal_result_, results->previous_result);
64 EXPECT_EQ(captive_portal_service_->last_detection_result(),
65 results->result);
67 captive_portal_result_ = results->result;
68 ++num_results_received_;
71 CaptivePortalResult captive_portal_result_;
72 int num_results_received_;
74 Profile* profile_;
75 CaptivePortalService* captive_portal_service_;
77 content::NotificationRegistrar registrar_;
79 DISALLOW_COPY_AND_ASSIGN(CaptivePortalObserver);
82 } // namespace
84 class CaptivePortalServiceTest : public testing::Test,
85 public CaptivePortalDetectorTestBase {
86 public:
87 CaptivePortalServiceTest()
88 : old_captive_portal_testing_state_(
89 CaptivePortalService::get_state_for_testing()) {
92 ~CaptivePortalServiceTest() override {
93 CaptivePortalService::set_state_for_testing(
94 old_captive_portal_testing_state_);
97 // |enable_service| is whether or not the captive portal service itself
98 // should be disabled. This is different from enabling the captive portal
99 // detection preference.
100 void Initialize(CaptivePortalService::TestingState testing_state) {
101 CaptivePortalService::set_state_for_testing(testing_state);
103 profile_.reset(new TestingProfile());
104 service_.reset(new CaptivePortalService(profile_.get()));
105 service_->set_time_ticks_for_testing(base::TimeTicks::Now());
107 // Use no delays for most tests.
108 set_initial_backoff_no_portal(base::TimeDelta());
109 set_initial_backoff_portal(base::TimeDelta());
111 set_detector(&service_->captive_portal_detector_);
112 SetTime(base::Time::Now());
114 // Disable jitter, so can check exact values.
115 set_jitter_factor(0.0);
117 // These values make checking exponential backoff easier.
118 set_multiply_factor(2.0);
119 set_maximum_backoff(base::TimeDelta::FromSeconds(1600));
121 // This means backoff starts after the second "failure", which is the third
122 // captive portal test in a row that ends up with the same result. Since
123 // the first request uses no delay, this means the delays will be in
124 // the pattern 0, 0, 100, 200, 400, etc. There are two zeros because the
125 // first check never has a delay, and the first check to have a new result
126 // is followed by no delay.
127 set_num_errors_to_ignore(1);
129 EnableCaptivePortalDetectionPreference(true);
132 // Sets the captive portal checking preference.
133 void EnableCaptivePortalDetectionPreference(bool enabled) {
134 profile()->GetPrefs()->SetBoolean(prefs::kAlternateErrorPagesEnabled,
135 enabled);
138 // Triggers a captive portal check, then simulates the URL request
139 // returning with the specified |net_error| and |status_code|. If |net_error|
140 // is not OK, |status_code| is ignored. Expects the CaptivePortalService to
141 // return |expected_result|.
143 // |expected_delay_secs| is the expected value of GetTimeUntilNextRequest().
144 // The function makes sure the value is as expected, and then simulates
145 // waiting for that period of time before running the test.
147 // If |response_headers| is non-NULL, the response will use it as headers
148 // for the simulate URL request. It must use single linefeeds as line breaks.
149 void RunTest(CaptivePortalResult expected_result,
150 int net_error,
151 int status_code,
152 int expected_delay_secs,
153 const char* response_headers) {
154 base::TimeDelta expected_delay =
155 base::TimeDelta::FromSeconds(expected_delay_secs);
157 ASSERT_EQ(CaptivePortalService::STATE_IDLE, service()->state());
158 ASSERT_EQ(expected_delay, GetTimeUntilNextRequest());
160 AdvanceTime(expected_delay);
161 ASSERT_EQ(base::TimeDelta(), GetTimeUntilNextRequest());
163 CaptivePortalObserver observer(profile(), service());
164 service()->DetectCaptivePortal();
166 EXPECT_EQ(CaptivePortalService::STATE_TIMER_RUNNING, service()->state());
167 EXPECT_FALSE(FetchingURL());
168 ASSERT_TRUE(TimerRunning());
170 base::RunLoop().RunUntilIdle();
171 EXPECT_EQ(CaptivePortalService::STATE_CHECKING_FOR_PORTAL,
172 service()->state());
173 ASSERT_TRUE(FetchingURL());
174 EXPECT_FALSE(TimerRunning());
176 CompleteURLFetch(net_error, status_code, response_headers);
178 EXPECT_FALSE(FetchingURL());
179 EXPECT_FALSE(TimerRunning());
180 EXPECT_EQ(1, observer.num_results_received());
181 EXPECT_EQ(expected_result, observer.captive_portal_result());
184 // Runs a test when the captive portal service is disabled.
185 void RunDisabledTest(int expected_delay_secs) {
186 base::TimeDelta expected_delay =
187 base::TimeDelta::FromSeconds(expected_delay_secs);
189 ASSERT_EQ(CaptivePortalService::STATE_IDLE, service()->state());
190 ASSERT_EQ(expected_delay, GetTimeUntilNextRequest());
192 AdvanceTime(expected_delay);
193 ASSERT_EQ(base::TimeDelta(), GetTimeUntilNextRequest());
195 CaptivePortalObserver observer(profile(), service());
196 service()->DetectCaptivePortal();
198 EXPECT_EQ(CaptivePortalService::STATE_TIMER_RUNNING, service()->state());
199 EXPECT_FALSE(FetchingURL());
200 ASSERT_TRUE(TimerRunning());
202 base::RunLoop().RunUntilIdle();
203 EXPECT_FALSE(FetchingURL());
204 EXPECT_FALSE(TimerRunning());
205 EXPECT_EQ(1, observer.num_results_received());
206 EXPECT_EQ(captive_portal::RESULT_INTERNET_CONNECTED,
207 observer.captive_portal_result());
210 // Tests exponential backoff. Prior to calling, the relevant recheck settings
211 // must be set to have a minimum time of 100 seconds, with 2 checks before
212 // starting exponential backoff.
213 void RunBackoffTest(CaptivePortalResult expected_result,
214 int net_error,
215 int status_code) {
216 RunTest(expected_result, net_error, status_code, 0, NULL);
217 RunTest(expected_result, net_error, status_code, 0, NULL);
218 RunTest(expected_result, net_error, status_code, 100, NULL);
219 RunTest(expected_result, net_error, status_code, 200, NULL);
220 RunTest(expected_result, net_error, status_code, 400, NULL);
221 RunTest(expected_result, net_error, status_code, 800, NULL);
222 RunTest(expected_result, net_error, status_code, 1600, NULL);
223 RunTest(expected_result, net_error, status_code, 1600, NULL);
226 // Changes test time for the service and service's captive portal
227 // detector.
228 void AdvanceTime(const base::TimeDelta& delta) {
229 service()->advance_time_ticks_for_testing(delta);
230 CaptivePortalDetectorTestBase::AdvanceTime(delta);
233 bool TimerRunning() {
234 return service()->TimerRunning();
237 base::TimeDelta GetTimeUntilNextRequest() {
238 return service()->backoff_entry_->GetTimeUntilRelease();
241 void set_initial_backoff_no_portal(
242 base::TimeDelta initial_backoff_no_portal) {
243 service()->recheck_policy().initial_backoff_no_portal_ms =
244 initial_backoff_no_portal.InMilliseconds();
247 void set_initial_backoff_portal(base::TimeDelta initial_backoff_portal) {
248 service()->recheck_policy().initial_backoff_portal_ms =
249 initial_backoff_portal.InMilliseconds();
252 void set_maximum_backoff(base::TimeDelta maximum_backoff) {
253 service()->recheck_policy().backoff_policy.maximum_backoff_ms =
254 maximum_backoff.InMilliseconds();
257 void set_num_errors_to_ignore(int num_errors_to_ignore) {
258 service()->recheck_policy().backoff_policy.num_errors_to_ignore =
259 num_errors_to_ignore;
262 void set_multiply_factor(double multiply_factor) {
263 service()->recheck_policy().backoff_policy.multiply_factor =
264 multiply_factor;
267 void set_jitter_factor(double jitter_factor) {
268 service()->recheck_policy().backoff_policy.jitter_factor = jitter_factor;
271 TestingProfile* profile() { return profile_.get(); }
273 CaptivePortalService* service() { return service_.get(); }
275 private:
276 // Stores the initial CaptivePortalService::TestingState so it can be restored
277 // after the test.
278 const CaptivePortalService::TestingState old_captive_portal_testing_state_;
280 content::TestBrowserThreadBundle thread_bundle_;
282 // Note that the construction order of these matters.
283 scoped_ptr<TestingProfile> profile_;
284 scoped_ptr<CaptivePortalService> service_;
287 // Verify that an observer doesn't get messages from the wrong profile.
288 TEST_F(CaptivePortalServiceTest, CaptivePortalTwoProfiles) {
289 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
290 TestingProfile profile2;
291 scoped_ptr<CaptivePortalService> service2(
292 new CaptivePortalService(&profile2));
293 CaptivePortalObserver observer2(&profile2, service2.get());
295 RunTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
296 EXPECT_EQ(0, observer2.num_results_received());
299 // Checks exponential backoff when the Internet is connected.
300 TEST_F(CaptivePortalServiceTest, CaptivePortalRecheckInternetConnected) {
301 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
303 // This value should have no effect on this test, until the end.
304 set_initial_backoff_portal(base::TimeDelta::FromSeconds(1));
306 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
307 RunBackoffTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204);
309 // Make sure that getting a new result resets the timer.
310 RunTest(
311 captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 1600, NULL);
312 RunTest(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 0, NULL);
313 RunTest(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 1, NULL);
314 RunTest(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 2, NULL);
317 // Checks exponential backoff when there's an HTTP error.
318 TEST_F(CaptivePortalServiceTest, CaptivePortalRecheckError) {
319 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
321 // This value should have no effect on this test.
322 set_initial_backoff_portal(base::TimeDelta::FromDays(1));
324 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
325 RunBackoffTest(captive_portal::RESULT_NO_RESPONSE, net::OK, 500);
327 // Make sure that getting a new result resets the timer.
328 RunTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204, 1600, NULL);
329 RunTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
330 RunTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204, 100, NULL);
333 // Checks exponential backoff when there's a captive portal.
334 TEST_F(CaptivePortalServiceTest, CaptivePortalRecheckBehindPortal) {
335 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
337 // This value should have no effect on this test, until the end.
338 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(250));
340 set_initial_backoff_portal(base::TimeDelta::FromSeconds(100));
341 RunBackoffTest(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200);
343 // Make sure that getting a new result resets the timer.
344 RunTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204, 1600, NULL);
345 RunTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
346 RunTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204, 250, NULL);
349 // Check that everything works as expected when captive portal checking is
350 // disabled, including throttling. Then enables it again and runs another test.
351 TEST_F(CaptivePortalServiceTest, CaptivePortalPrefDisabled) {
352 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
354 // This value should have no effect on this test.
355 set_initial_backoff_no_portal(base::TimeDelta::FromDays(1));
357 set_initial_backoff_portal(base::TimeDelta::FromSeconds(100));
359 EnableCaptivePortalDetectionPreference(false);
361 RunDisabledTest(0);
362 for (int i = 0; i < 6; ++i)
363 RunDisabledTest(100);
365 EnableCaptivePortalDetectionPreference(true);
367 RunTest(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 0, NULL);
370 // Check that disabling the captive portal service while a check is running
371 // works.
372 TEST_F(CaptivePortalServiceTest, CaptivePortalPrefDisabledWhileRunning) {
373 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
374 CaptivePortalObserver observer(profile(), service());
376 // Needed to create the URLFetcher, even if it never returns any results.
377 service()->DetectCaptivePortal();
379 base::RunLoop().RunUntilIdle();
380 EXPECT_TRUE(FetchingURL());
381 EXPECT_FALSE(TimerRunning());
383 EnableCaptivePortalDetectionPreference(false);
384 EXPECT_FALSE(FetchingURL());
385 EXPECT_TRUE(TimerRunning());
386 EXPECT_EQ(0, observer.num_results_received());
388 base::RunLoop().RunUntilIdle();
390 EXPECT_FALSE(FetchingURL());
391 EXPECT_FALSE(TimerRunning());
392 EXPECT_EQ(1, observer.num_results_received());
394 EXPECT_EQ(captive_portal::RESULT_INTERNET_CONNECTED,
395 observer.captive_portal_result());
398 // Check that disabling the captive portal service while a check is pending
399 // works.
400 TEST_F(CaptivePortalServiceTest, CaptivePortalPrefDisabledWhilePending) {
401 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
402 set_initial_backoff_no_portal(base::TimeDelta::FromDays(1));
404 CaptivePortalObserver observer(profile(), service());
405 service()->DetectCaptivePortal();
406 EXPECT_FALSE(FetchingURL());
407 EXPECT_TRUE(TimerRunning());
409 EnableCaptivePortalDetectionPreference(false);
410 EXPECT_FALSE(FetchingURL());
411 EXPECT_TRUE(TimerRunning());
412 EXPECT_EQ(0, observer.num_results_received());
414 base::RunLoop().RunUntilIdle();
416 EXPECT_FALSE(FetchingURL());
417 EXPECT_FALSE(TimerRunning());
418 EXPECT_EQ(1, observer.num_results_received());
420 EXPECT_EQ(captive_portal::RESULT_INTERNET_CONNECTED,
421 observer.captive_portal_result());
424 // Check that disabling the captive portal service while a check is pending
425 // works.
426 TEST_F(CaptivePortalServiceTest, CaptivePortalPrefEnabledWhilePending) {
427 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
429 EnableCaptivePortalDetectionPreference(false);
430 RunDisabledTest(0);
432 CaptivePortalObserver observer(profile(), service());
433 service()->DetectCaptivePortal();
434 EXPECT_FALSE(FetchingURL());
435 EXPECT_TRUE(TimerRunning());
437 EnableCaptivePortalDetectionPreference(true);
438 EXPECT_FALSE(FetchingURL());
439 EXPECT_TRUE(TimerRunning());
441 base::RunLoop().RunUntilIdle();
442 ASSERT_TRUE(FetchingURL());
443 EXPECT_FALSE(TimerRunning());
445 CompleteURLFetch(net::OK, 200, NULL);
446 EXPECT_FALSE(FetchingURL());
447 EXPECT_FALSE(TimerRunning());
449 EXPECT_EQ(1, observer.num_results_received());
450 EXPECT_EQ(captive_portal::RESULT_BEHIND_CAPTIVE_PORTAL,
451 observer.captive_portal_result());
454 // Checks that disabling for browser tests works as expected.
455 TEST_F(CaptivePortalServiceTest, CaptivePortalDisableForTests) {
456 Initialize(CaptivePortalService::DISABLED_FOR_TESTING);
457 RunDisabledTest(0);
460 // Checks that jitter gives us values in the correct range.
461 TEST_F(CaptivePortalServiceTest, CaptivePortalJitter) {
462 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
463 set_jitter_factor(0.3);
464 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
465 RunTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
466 RunTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
468 for (int i = 0; i < 50; ++i) {
469 int interval_sec = GetTimeUntilNextRequest().InSeconds();
470 // Allow for roundoff, though shouldn't be necessary.
471 EXPECT_LE(69, interval_sec);
472 EXPECT_LE(interval_sec, 101);
476 // Check a Retry-After header that contains a delay in seconds.
477 TEST_F(CaptivePortalServiceTest, CaptivePortalRetryAfterSeconds) {
478 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
479 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
480 const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 101\n\n";
482 // Check that Retry-After headers work both on the first request to return a
483 // result and on subsequent requests.
484 RunTest(captive_portal::RESULT_NO_RESPONSE, net::OK, 503, 0, retry_after);
485 RunTest(captive_portal::RESULT_NO_RESPONSE, net::OK, 503, 101, retry_after);
486 RunTest(captive_portal::RESULT_INTERNET_CONNECTED, net::OK, 204, 101, NULL);
488 // Make sure that there's no effect on the next captive portal check after
489 // login.
490 EXPECT_EQ(base::TimeDelta::FromSeconds(0), GetTimeUntilNextRequest());
493 // Check that the RecheckPolicy is still respected on 503 responses with
494 // Retry-After headers.
495 TEST_F(CaptivePortalServiceTest, CaptivePortalRetryAfterSecondsTooShort) {
496 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
497 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
498 const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 99\n\n";
500 RunTest(captive_portal::RESULT_NO_RESPONSE, net::OK, 503, 0, retry_after);
501 // Normally would be no delay on the first check with a new result.
502 RunTest(captive_portal::RESULT_NO_RESPONSE, net::OK, 503, 99, retry_after);
503 EXPECT_EQ(base::TimeDelta::FromSeconds(100), GetTimeUntilNextRequest());
506 // Check a Retry-After header that contains a date.
507 TEST_F(CaptivePortalServiceTest, CaptivePortalRetryAfterDate) {
508 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
509 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(50));
511 // base has a function to get a time in the right format from a string, but
512 // not the other way around.
513 base::Time start_time;
514 ASSERT_TRUE(
515 base::Time::FromString("Tue, 17 Apr 2012 18:02:00 GMT", &start_time));
516 SetTime(start_time);
518 RunTest(captive_portal::RESULT_NO_RESPONSE,
519 net::OK,
520 503,
522 "HTTP/1.1 503 OK\nRetry-After: Tue, 17 Apr 2012 18:02:51 GMT\n\n");
523 EXPECT_EQ(base::TimeDelta::FromSeconds(51), GetTimeUntilNextRequest());