NaCl: Update revision in DEPS, r12770 -> r12773
[chromium-blink-merge.git] / chrome / browser / captive_portal / captive_portal_service_unittest.cc
blobf03e15552c88a9ef1725e978d486c1e1a063d7e6
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/captive_portal/testing_utils.h"
14 #include "chrome/browser/chrome_notification_types.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/pref_names.h"
17 #include "chrome/test/base/testing_profile.h"
18 #include "chrome/test/base/ui_test_utils.h"
19 #include "content/public/browser/notification_details.h"
20 #include "content/public/browser/notification_observer.h"
21 #include "content/public/browser/notification_registrar.h"
22 #include "content/public/browser/notification_source.h"
23 #include "content/public/test/test_browser_thread_bundle.h"
24 #include "net/base/net_errors.h"
25 #include "testing/gtest/include/gtest/gtest.h"
27 namespace captive_portal {
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 Result captive_portal_result() const { return captive_portal_result_; }
49 int num_results_received() const { return num_results_received_; }
51 private:
52 virtual void Observe(int type,
53 const content::NotificationSource& source,
54 const content::NotificationDetails& details) OVERRIDE {
55 ASSERT_EQ(type, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT);
56 ASSERT_EQ(profile_, content::Source<Profile>(source).ptr());
58 CaptivePortalService::Results *results =
59 content::Details<CaptivePortalService::Results>(details).ptr();
61 EXPECT_EQ(captive_portal_result_, results->previous_result);
62 EXPECT_EQ(captive_portal_service_->last_detection_result(),
63 results->result);
65 captive_portal_result_ = results->result;
66 ++num_results_received_;
69 Result captive_portal_result_;
70 int num_results_received_;
72 Profile* profile_;
73 CaptivePortalService* captive_portal_service_;
75 content::NotificationRegistrar registrar_;
77 DISALLOW_COPY_AND_ASSIGN(CaptivePortalObserver);
80 } // namespace
82 class CaptivePortalServiceTest : public testing::Test,
83 public CaptivePortalDetectorTestBase {
84 public:
85 CaptivePortalServiceTest()
86 : old_captive_portal_testing_state_(
87 CaptivePortalService::get_state_for_testing()) {
90 virtual ~CaptivePortalServiceTest() {
91 CaptivePortalService::set_state_for_testing(
92 old_captive_portal_testing_state_);
95 // |enable_service| is whether or not the captive portal service itself
96 // should be disabled. This is different from enabling the captive portal
97 // detection preference.
98 void Initialize(CaptivePortalService::TestingState testing_state) {
99 CaptivePortalService::set_state_for_testing(testing_state);
101 profile_.reset(new TestingProfile());
102 service_.reset(new CaptivePortalService(profile_.get()));
103 service_->set_time_ticks_for_testing(base::TimeTicks::Now());
105 // Use no delays for most tests.
106 set_initial_backoff_no_portal(base::TimeDelta());
107 set_initial_backoff_portal(base::TimeDelta());
109 set_detector(&service_->captive_portal_detector_);
110 SetTime(base::Time::Now());
112 // Disable jitter, so can check exact values.
113 set_jitter_factor(0.0);
115 // These values make checking exponential backoff easier.
116 set_multiply_factor(2.0);
117 set_maximum_backoff(base::TimeDelta::FromSeconds(1600));
119 // This means backoff starts after the second "failure", which is the third
120 // captive portal test in a row that ends up with the same result. Since
121 // the first request uses no delay, this means the delays will be in
122 // the pattern 0, 0, 100, 200, 400, etc. There are two zeros because the
123 // first check never has a delay, and the first check to have a new result
124 // is followed by no delay.
125 set_num_errors_to_ignore(1);
127 EnableCaptivePortalDetectionPreference(true);
130 // Sets the captive portal checking preference.
131 void EnableCaptivePortalDetectionPreference(bool enabled) {
132 profile()->GetPrefs()->SetBoolean(prefs::kAlternateErrorPagesEnabled,
133 enabled);
136 // Triggers a captive portal check, then simulates the URL request
137 // returning with the specified |net_error| and |status_code|. If |net_error|
138 // is not OK, |status_code| is ignored. Expects the CaptivePortalService to
139 // return |expected_result|.
141 // |expected_delay_secs| is the expected value of GetTimeUntilNextRequest().
142 // The function makes sure the value is as expected, and then simulates
143 // waiting for that period of time before running the test.
145 // If |response_headers| is non-NULL, the response will use it as headers
146 // for the simulate URL request. It must use single linefeeds as line breaks.
147 void RunTest(Result expected_result,
148 int net_error,
149 int status_code,
150 int expected_delay_secs,
151 const char* response_headers) {
152 base::TimeDelta expected_delay =
153 base::TimeDelta::FromSeconds(expected_delay_secs);
155 ASSERT_EQ(CaptivePortalService::STATE_IDLE, service()->state());
156 ASSERT_EQ(expected_delay, GetTimeUntilNextRequest());
158 AdvanceTime(expected_delay);
159 ASSERT_EQ(base::TimeDelta(), GetTimeUntilNextRequest());
161 CaptivePortalObserver observer(profile(), service());
162 service()->DetectCaptivePortal();
164 EXPECT_EQ(CaptivePortalService::STATE_TIMER_RUNNING, service()->state());
165 EXPECT_FALSE(FetchingURL());
166 ASSERT_TRUE(TimerRunning());
168 base::RunLoop().RunUntilIdle();
169 EXPECT_EQ(CaptivePortalService::STATE_CHECKING_FOR_PORTAL,
170 service()->state());
171 ASSERT_TRUE(FetchingURL());
172 EXPECT_FALSE(TimerRunning());
174 CompleteURLFetch(net_error, status_code, response_headers);
176 EXPECT_FALSE(FetchingURL());
177 EXPECT_FALSE(TimerRunning());
178 EXPECT_EQ(1, observer.num_results_received());
179 EXPECT_EQ(expected_result, observer.captive_portal_result());
182 // Runs a test when the captive portal service is disabled.
183 void RunDisabledTest(int expected_delay_secs) {
184 base::TimeDelta expected_delay =
185 base::TimeDelta::FromSeconds(expected_delay_secs);
187 ASSERT_EQ(CaptivePortalService::STATE_IDLE, service()->state());
188 ASSERT_EQ(expected_delay, GetTimeUntilNextRequest());
190 AdvanceTime(expected_delay);
191 ASSERT_EQ(base::TimeDelta(), GetTimeUntilNextRequest());
193 CaptivePortalObserver observer(profile(), service());
194 service()->DetectCaptivePortal();
196 EXPECT_EQ(CaptivePortalService::STATE_TIMER_RUNNING, service()->state());
197 EXPECT_FALSE(FetchingURL());
198 ASSERT_TRUE(TimerRunning());
200 base::RunLoop().RunUntilIdle();
201 EXPECT_FALSE(FetchingURL());
202 EXPECT_FALSE(TimerRunning());
203 EXPECT_EQ(1, observer.num_results_received());
204 EXPECT_EQ(RESULT_INTERNET_CONNECTED, observer.captive_portal_result());
207 // Tests exponential backoff. Prior to calling, the relevant recheck settings
208 // must be set to have a minimum time of 100 seconds, with 2 checks before
209 // starting exponential backoff.
210 void RunBackoffTest(Result expected_result, int net_error, int status_code) {
211 RunTest(expected_result, net_error, status_code, 0, NULL);
212 RunTest(expected_result, net_error, status_code, 0, NULL);
213 RunTest(expected_result, net_error, status_code, 100, NULL);
214 RunTest(expected_result, net_error, status_code, 200, NULL);
215 RunTest(expected_result, net_error, status_code, 400, NULL);
216 RunTest(expected_result, net_error, status_code, 800, NULL);
217 RunTest(expected_result, net_error, status_code, 1600, NULL);
218 RunTest(expected_result, net_error, status_code, 1600, NULL);
221 // Changes test time for the service and service's captive portal
222 // detector.
223 void AdvanceTime(const base::TimeDelta& delta) {
224 service()->advance_time_ticks_for_testing(delta);
225 CaptivePortalDetectorTestBase::AdvanceTime(delta);
228 bool TimerRunning() {
229 return service()->TimerRunning();
232 base::TimeDelta GetTimeUntilNextRequest() {
233 return service()->backoff_entry_->GetTimeUntilRelease();
236 void set_initial_backoff_no_portal(
237 base::TimeDelta initial_backoff_no_portal) {
238 service()->recheck_policy().initial_backoff_no_portal_ms =
239 initial_backoff_no_portal.InMilliseconds();
242 void set_initial_backoff_portal(base::TimeDelta initial_backoff_portal) {
243 service()->recheck_policy().initial_backoff_portal_ms =
244 initial_backoff_portal.InMilliseconds();
247 void set_maximum_backoff(base::TimeDelta maximum_backoff) {
248 service()->recheck_policy().backoff_policy.maximum_backoff_ms =
249 maximum_backoff.InMilliseconds();
252 void set_num_errors_to_ignore(int num_errors_to_ignore) {
253 service()->recheck_policy().backoff_policy.num_errors_to_ignore =
254 num_errors_to_ignore;
257 void set_multiply_factor(double multiply_factor) {
258 service()->recheck_policy().backoff_policy.multiply_factor =
259 multiply_factor;
262 void set_jitter_factor(double jitter_factor) {
263 service()->recheck_policy().backoff_policy.jitter_factor = jitter_factor;
266 TestingProfile* profile() { return profile_.get(); }
268 CaptivePortalService* service() { return service_.get(); }
270 private:
271 // Stores the initial CaptivePortalService::TestingState so it can be restored
272 // after the test.
273 const CaptivePortalService::TestingState old_captive_portal_testing_state_;
275 content::TestBrowserThreadBundle thread_bundle_;
277 // Note that the construction order of these matters.
278 scoped_ptr<TestingProfile> profile_;
279 scoped_ptr<CaptivePortalService> service_;
282 // Verify that an observer doesn't get messages from the wrong profile.
283 TEST_F(CaptivePortalServiceTest, CaptivePortalTwoProfiles) {
284 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
285 TestingProfile profile2;
286 scoped_ptr<CaptivePortalService> service2(
287 new CaptivePortalService(&profile2));
288 CaptivePortalObserver observer2(&profile2, service2.get());
290 RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
291 EXPECT_EQ(0, observer2.num_results_received());
294 // Checks exponential backoff when the Internet is connected.
295 TEST_F(CaptivePortalServiceTest, CaptivePortalRecheckInternetConnected) {
296 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
298 // This value should have no effect on this test, until the end.
299 set_initial_backoff_portal(base::TimeDelta::FromSeconds(1));
301 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
302 RunBackoffTest(RESULT_INTERNET_CONNECTED, net::OK, 204);
304 // Make sure that getting a new result resets the timer.
305 RunTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 1600, NULL);
306 RunTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 0, NULL);
307 RunTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 1, NULL);
308 RunTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 2, NULL);
311 // Checks exponential backoff when there's an HTTP error.
312 TEST_F(CaptivePortalServiceTest, CaptivePortalRecheckError) {
313 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
315 // This value should have no effect on this test.
316 set_initial_backoff_portal(base::TimeDelta::FromDays(1));
318 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
319 RunBackoffTest(RESULT_NO_RESPONSE, net::OK, 500);
321 // Make sure that getting a new result resets the timer.
322 RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 1600, NULL);
323 RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
324 RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 100, NULL);
327 // Checks exponential backoff when there's a captive portal.
328 TEST_F(CaptivePortalServiceTest, CaptivePortalRecheckBehindPortal) {
329 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
331 // This value should have no effect on this test, until the end.
332 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(250));
334 set_initial_backoff_portal(base::TimeDelta::FromSeconds(100));
335 RunBackoffTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200);
337 // Make sure that getting a new result resets the timer.
338 RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 1600, NULL);
339 RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
340 RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 250, NULL);
343 // Check that everything works as expected when captive portal checking is
344 // disabled, including throttling. Then enables it again and runs another test.
345 TEST_F(CaptivePortalServiceTest, CaptivePortalPrefDisabled) {
346 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
348 // This value should have no effect on this test.
349 set_initial_backoff_no_portal(base::TimeDelta::FromDays(1));
351 set_initial_backoff_portal(base::TimeDelta::FromSeconds(100));
353 EnableCaptivePortalDetectionPreference(false);
355 RunDisabledTest(0);
356 for (int i = 0; i < 6; ++i)
357 RunDisabledTest(100);
359 EnableCaptivePortalDetectionPreference(true);
361 RunTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 0, NULL);
364 // Check that disabling the captive portal service while a check is running
365 // works.
366 TEST_F(CaptivePortalServiceTest, CaptivePortalPrefDisabledWhileRunning) {
367 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
368 CaptivePortalObserver observer(profile(), service());
370 // Needed to create the URLFetcher, even if it never returns any results.
371 service()->DetectCaptivePortal();
373 base::RunLoop().RunUntilIdle();
374 EXPECT_TRUE(FetchingURL());
375 EXPECT_FALSE(TimerRunning());
377 EnableCaptivePortalDetectionPreference(false);
378 EXPECT_FALSE(FetchingURL());
379 EXPECT_TRUE(TimerRunning());
380 EXPECT_EQ(0, observer.num_results_received());
382 base::RunLoop().RunUntilIdle();
384 EXPECT_FALSE(FetchingURL());
385 EXPECT_FALSE(TimerRunning());
386 EXPECT_EQ(1, observer.num_results_received());
388 EXPECT_EQ(RESULT_INTERNET_CONNECTED, observer.captive_portal_result());
391 // Check that disabling the captive portal service while a check is pending
392 // works.
393 TEST_F(CaptivePortalServiceTest, CaptivePortalPrefDisabledWhilePending) {
394 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
395 set_initial_backoff_no_portal(base::TimeDelta::FromDays(1));
397 CaptivePortalObserver observer(profile(), service());
398 service()->DetectCaptivePortal();
399 EXPECT_FALSE(FetchingURL());
400 EXPECT_TRUE(TimerRunning());
402 EnableCaptivePortalDetectionPreference(false);
403 EXPECT_FALSE(FetchingURL());
404 EXPECT_TRUE(TimerRunning());
405 EXPECT_EQ(0, observer.num_results_received());
407 base::RunLoop().RunUntilIdle();
409 EXPECT_FALSE(FetchingURL());
410 EXPECT_FALSE(TimerRunning());
411 EXPECT_EQ(1, observer.num_results_received());
413 EXPECT_EQ(RESULT_INTERNET_CONNECTED, observer.captive_portal_result());
416 // Check that disabling the captive portal service while a check is pending
417 // works.
418 TEST_F(CaptivePortalServiceTest, CaptivePortalPrefEnabledWhilePending) {
419 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
421 EnableCaptivePortalDetectionPreference(false);
422 RunDisabledTest(0);
424 CaptivePortalObserver observer(profile(), service());
425 service()->DetectCaptivePortal();
426 EXPECT_FALSE(FetchingURL());
427 EXPECT_TRUE(TimerRunning());
429 EnableCaptivePortalDetectionPreference(true);
430 EXPECT_FALSE(FetchingURL());
431 EXPECT_TRUE(TimerRunning());
433 base::RunLoop().RunUntilIdle();
434 ASSERT_TRUE(FetchingURL());
435 EXPECT_FALSE(TimerRunning());
437 CompleteURLFetch(net::OK, 200, NULL);
438 EXPECT_FALSE(FetchingURL());
439 EXPECT_FALSE(TimerRunning());
441 EXPECT_EQ(1, observer.num_results_received());
442 EXPECT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, observer.captive_portal_result());
445 // Checks that disabling for browser tests works as expected.
446 TEST_F(CaptivePortalServiceTest, CaptivePortalDisableForTests) {
447 Initialize(CaptivePortalService::DISABLED_FOR_TESTING);
448 RunDisabledTest(0);
451 // Checks that jitter gives us values in the correct range.
452 TEST_F(CaptivePortalServiceTest, CaptivePortalJitter) {
453 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
454 set_jitter_factor(0.3);
455 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
456 RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
457 RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
459 for (int i = 0; i < 50; ++i) {
460 int interval_sec = GetTimeUntilNextRequest().InSeconds();
461 // Allow for roundoff, though shouldn't be necessary.
462 EXPECT_LE(69, interval_sec);
463 EXPECT_LE(interval_sec, 101);
467 // Check a Retry-After header that contains a delay in seconds.
468 TEST_F(CaptivePortalServiceTest, CaptivePortalRetryAfterSeconds) {
469 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
470 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
471 const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 101\n\n";
473 // Check that Retry-After headers work both on the first request to return a
474 // result and on subsequent requests.
475 RunTest(RESULT_NO_RESPONSE, net::OK, 503, 0, retry_after);
476 RunTest(RESULT_NO_RESPONSE, net::OK, 503, 101, retry_after);
477 RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 101, NULL);
479 // Make sure that there's no effect on the next captive portal check after
480 // login.
481 EXPECT_EQ(base::TimeDelta::FromSeconds(0), GetTimeUntilNextRequest());
484 // Check that the RecheckPolicy is still respected on 503 responses with
485 // Retry-After headers.
486 TEST_F(CaptivePortalServiceTest, CaptivePortalRetryAfterSecondsTooShort) {
487 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
488 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
489 const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 99\n\n";
491 RunTest(RESULT_NO_RESPONSE, net::OK, 503, 0, retry_after);
492 // Normally would be no delay on the first check with a new result.
493 RunTest(RESULT_NO_RESPONSE, net::OK, 503, 99, retry_after);
494 EXPECT_EQ(base::TimeDelta::FromSeconds(100), GetTimeUntilNextRequest());
497 // Check a Retry-After header that contains a date.
498 TEST_F(CaptivePortalServiceTest, CaptivePortalRetryAfterDate) {
499 Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
500 set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(50));
502 // base has a function to get a time in the right format from a string, but
503 // not the other way around.
504 base::Time start_time;
505 ASSERT_TRUE(
506 base::Time::FromString("Tue, 17 Apr 2012 18:02:00 GMT", &start_time));
507 SetTime(start_time);
509 RunTest(RESULT_NO_RESPONSE,
510 net::OK,
511 503,
513 "HTTP/1.1 503 OK\nRetry-After: Tue, 17 Apr 2012 18:02:51 GMT\n\n");
514 EXPECT_EQ(base::TimeDelta::FromSeconds(51), GetTimeUntilNextRequest());
517 } // namespace captive_portal