network_portal_detector_impl_unittest.cc revision 116680a4aac90f2aa7413d9095a592090648e557
1// Copyright (c) 2013 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 <algorithm>
6#include <vector>
7
8#include "base/command_line.h"
9#include "base/compiler_specific.h"
10#include "base/logging.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/metrics/histogram_base.h"
13#include "base/metrics/histogram_samples.h"
14#include "base/metrics/statistics_recorder.h"
15#include "base/run_loop.h"
16#include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
17#include "chrome/browser/chromeos/net/network_portal_detector_test_utils.h"
18#include "chrome/test/base/testing_profile.h"
19#include "chromeos/chromeos_switches.h"
20#include "chromeos/dbus/dbus_thread_manager.h"
21#include "chromeos/dbus/shill_device_client.h"
22#include "chromeos/dbus/shill_service_client.h"
23#include "chromeos/network/network_state.h"
24#include "chromeos/network/network_state_handler.h"
25#include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
26#include "components/captive_portal/captive_portal_detector.h"
27#include "components/captive_portal/captive_portal_testing_utils.h"
28#include "content/public/test/test_browser_thread_bundle.h"
29#include "dbus/object_path.h"
30#include "net/base/net_errors.h"
31#include "testing/gmock/include/gmock/gmock.h"
32#include "testing/gtest/include/gtest/gtest.h"
33#include "third_party/cros_system_api/dbus/service_constants.h"
34
35using testing::AnyNumber;
36using testing::Mock;
37using testing::_;
38
39namespace chromeos {
40
41namespace {
42
43// Service path / guid for stub networks.
44const char kStubEthernet[] = "stub_ethernet";
45const char kStubWireless1[] = "stub_wifi1";
46const char kStubWireless2[] = "stub_wifi2";
47const char kStubCellular[] = "stub_cellular";
48
49void ErrorCallbackFunction(const std::string& error_name,
50                           const std::string& error_message) {
51  LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
52}
53
54class MockObserver : public NetworkPortalDetector::Observer {
55 public:
56  virtual ~MockObserver() {}
57
58  MOCK_METHOD2(OnPortalDetectionCompleted,
59               void(const NetworkState* network,
60                    const NetworkPortalDetector::CaptivePortalState& state));
61};
62
63}  // namespace
64
65class NetworkPortalDetectorImplTest
66    : public testing::Test,
67      public captive_portal::CaptivePortalDetectorTestBase {
68 protected:
69  virtual void SetUp() {
70    CommandLine* cl = CommandLine::ForCurrentProcess();
71    cl->AppendSwitch(switches::kDisableNetworkPortalNotification);
72
73    DBusThreadManager::InitializeWithStub();
74    base::StatisticsRecorder::Initialize();
75    SetupNetworkHandler();
76
77    profile_.reset(new TestingProfile());
78    network_portal_detector_.reset(
79        new NetworkPortalDetectorImpl(profile_->GetRequestContext()));
80    network_portal_detector_->Enable(false);
81
82    set_detector(network_portal_detector_->captive_portal_detector_.get());
83
84    // Prevents flakiness due to message loop delays.
85    set_time_ticks(base::TimeTicks::Now());
86
87    if (base::HistogramBase* histogram =
88            base::StatisticsRecorder::FindHistogram(
89                "CaptivePortal.OOBE.DetectionResult")) {
90      original_samples_.reset(histogram->SnapshotSamples().release());
91    }
92  }
93
94  virtual void TearDown() {
95    network_portal_detector_.reset();
96    profile_.reset();
97    NetworkHandler::Shutdown();
98    DBusThreadManager::Shutdown();
99    PortalDetectorStrategy::reset_fields_for_testing();
100  }
101
102  void CheckPortalState(NetworkPortalDetector::CaptivePortalStatus status,
103                        int response_code,
104                        const std::string& guid) {
105    NetworkPortalDetector::CaptivePortalState state =
106        network_portal_detector()->GetCaptivePortalState(guid);
107    ASSERT_EQ(status, state.status);
108    ASSERT_EQ(response_code, state.response_code);
109  }
110
111  void CheckRequestTimeoutAndCompleteAttempt(int expected_attempt_count,
112                                             int expected_request_timeout_sec,
113                                             int net_error,
114                                             int status_code) {
115    ASSERT_TRUE(is_state_checking_for_portal());
116    ASSERT_EQ(expected_attempt_count, attempt_count());
117    ASSERT_EQ(base::TimeDelta::FromSeconds(expected_request_timeout_sec),
118              get_next_attempt_timeout());
119    CompleteURLFetch(net_error, status_code, NULL);
120  }
121
122  Profile* profile() { return profile_.get(); }
123
124  NetworkPortalDetectorImpl* network_portal_detector() {
125    return network_portal_detector_.get();
126  }
127
128  NetworkPortalDetectorImpl::State state() {
129    return network_portal_detector()->state();
130  }
131
132  bool start_detection_if_idle() {
133    return network_portal_detector()->StartDetectionIfIdle();
134  }
135
136  void enable_error_screen_strategy() {
137    network_portal_detector()->SetStrategy(
138        PortalDetectorStrategy::STRATEGY_ID_ERROR_SCREEN);
139  }
140
141  void disable_error_screen_strategy() {
142    network_portal_detector()->SetStrategy(
143        PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN);
144  }
145
146  void stop_detection() { network_portal_detector()->StopDetection(); }
147
148  bool attempt_timeout_is_cancelled() {
149    return network_portal_detector()->AttemptTimeoutIsCancelledForTesting();
150  }
151
152  base::TimeDelta get_next_attempt_timeout() {
153    return network_portal_detector()->strategy_->GetNextAttemptTimeout();
154  }
155
156  void set_next_attempt_timeout(const base::TimeDelta& timeout) {
157    PortalDetectorStrategy::set_next_attempt_timeout_for_testing(timeout);
158  }
159
160  bool is_state_idle() {
161    return (NetworkPortalDetectorImpl::STATE_IDLE == state());
162  }
163
164  bool is_state_portal_detection_pending() {
165    return (NetworkPortalDetectorImpl::STATE_PORTAL_CHECK_PENDING == state());
166  }
167
168  bool is_state_checking_for_portal() {
169    return (NetworkPortalDetectorImpl::STATE_CHECKING_FOR_PORTAL == state());
170  }
171
172  const base::TimeDelta& next_attempt_delay() {
173    return network_portal_detector()->next_attempt_delay_for_testing();
174  }
175
176  int attempt_count() {
177    return network_portal_detector()->attempt_count_for_testing();
178  }
179
180  void set_attempt_count(int ac) {
181    network_portal_detector()->set_attempt_count_for_testing(ac);
182  }
183
184  void set_delay_till_next_attempt(const base::TimeDelta& delta) {
185    PortalDetectorStrategy::set_delay_till_next_attempt_for_testing(delta);
186  }
187
188  void set_time_ticks(const base::TimeTicks& time_ticks) {
189    network_portal_detector()->set_time_ticks_for_testing(time_ticks);
190  }
191
192  void SetBehindPortal(const std::string& service_path) {
193    DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
194        dbus::ObjectPath(service_path),
195        shill::kStateProperty,
196        base::StringValue(shill::kStatePortal),
197        base::Bind(&base::DoNothing),
198        base::Bind(&ErrorCallbackFunction));
199    base::RunLoop().RunUntilIdle();
200  }
201
202  void SetNetworkDeviceEnabled(const std::string& type, bool enabled) {
203    NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
204        NetworkTypePattern::Primitive(type),
205        enabled,
206        network_handler::ErrorCallback());
207    base::RunLoop().RunUntilIdle();
208  }
209
210  void SetConnected(const std::string& service_path) {
211    DBusThreadManager::Get()->GetShillServiceClient()->Connect(
212        dbus::ObjectPath(service_path),
213        base::Bind(&base::DoNothing),
214        base::Bind(&ErrorCallbackFunction));
215    base::RunLoop().RunUntilIdle();
216  }
217
218  void SetDisconnected(const std::string& service_path) {
219    DBusThreadManager::Get()->GetShillServiceClient()->Disconnect(
220        dbus::ObjectPath(service_path),
221        base::Bind(&*base::DoNothing),
222        base::Bind(&ErrorCallbackFunction));
223    base::RunLoop().RunUntilIdle();
224  }
225
226  scoped_ptr<EnumHistogramChecker> MakeResultHistogramChecker() {
227    return scoped_ptr<EnumHistogramChecker>(
228               new EnumHistogramChecker(
229                   "CaptivePortal.OOBE.DetectionResult",
230                   NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT,
231                   original_samples_.get()));
232  }
233
234 private:
235  void AddService(const std::string& network_id,
236                  const std::string& type) {
237    DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
238        AddService(network_id /* service_path */,
239                   network_id /* guid */,
240                   network_id /* name */,
241                   type,
242                   shill::kStateIdle,
243                   true /* add_to_visible */);
244  }
245
246  void SetupDefaultShillState() {
247    base::RunLoop().RunUntilIdle();
248    DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
249        ClearServices();
250    AddService(kStubEthernet, shill::kTypeEthernet);
251    AddService(kStubWireless1, shill::kTypeWifi);
252    AddService(kStubWireless2, shill::kTypeWifi);
253    AddService(kStubCellular, shill::kTypeCellular);
254  }
255
256  void SetupNetworkHandler() {
257    SetupDefaultShillState();
258    NetworkHandler::Initialize();
259  }
260
261  content::TestBrowserThreadBundle thread_bundle_;
262  scoped_ptr<TestingProfile> profile_;
263  scoped_ptr<NetworkPortalDetectorImpl> network_portal_detector_;
264  scoped_ptr<base::HistogramSamples> original_samples_;
265};
266
267TEST_F(NetworkPortalDetectorImplTest, NoPortal) {
268  ASSERT_TRUE(is_state_idle());
269
270  SetConnected(kStubWireless1);
271
272  ASSERT_TRUE(is_state_checking_for_portal());
273  CheckPortalState(
274      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
275
276  CompleteURLFetch(net::OK, 204, NULL);
277
278  ASSERT_TRUE(is_state_idle());
279  CheckPortalState(
280      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
281  ASSERT_TRUE(
282      MakeResultHistogramChecker()
283          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
284          ->Check());
285}
286
287TEST_F(NetworkPortalDetectorImplTest, Portal) {
288  ASSERT_TRUE(is_state_idle());
289
290  // Check HTTP 200 response code.
291  SetConnected(kStubWireless1);
292  ASSERT_TRUE(is_state_checking_for_portal());
293
294  CompleteURLFetch(net::OK, 200, NULL);
295
296  ASSERT_TRUE(is_state_idle());
297  CheckPortalState(
298      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
299
300  // Check HTTP 301 response code.
301  SetConnected(kStubWireless2);
302  ASSERT_TRUE(is_state_checking_for_portal());
303
304  CompleteURLFetch(net::OK, 301, NULL);
305
306  ASSERT_TRUE(is_state_idle());
307  CheckPortalState(
308      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 301, kStubWireless2);
309
310  // Check HTTP 302 response code.
311  SetConnected(kStubEthernet);
312  ASSERT_TRUE(is_state_checking_for_portal());
313
314  CompleteURLFetch(net::OK, 302, NULL);
315
316  ASSERT_TRUE(is_state_idle());
317  CheckPortalState(
318      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 302, kStubEthernet);
319
320  ASSERT_TRUE(
321      MakeResultHistogramChecker()
322          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 3)
323          ->Check());
324}
325
326TEST_F(NetworkPortalDetectorImplTest, Online2Offline) {
327  ASSERT_TRUE(is_state_idle());
328
329  MockObserver observer;
330  network_portal_detector()->AddObserver(&observer);
331
332  NetworkPortalDetector::CaptivePortalState offline_state;
333  offline_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE;
334
335  // WiFi is in online state.
336  {
337    // When transitioning to a connected state, the network will transition to
338    // connecting states which will set the default network to NULL. This may
339    // get triggered multiple times.
340    EXPECT_CALL(observer, OnPortalDetectionCompleted(_, offline_state))
341        .Times(AnyNumber());
342
343    // Expect a single transition to an online state.
344    NetworkPortalDetector::CaptivePortalState online_state;
345    online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
346    online_state.response_code = 204;
347    EXPECT_CALL(observer, OnPortalDetectionCompleted(_, online_state)).Times(1);
348
349    SetConnected(kStubWireless1);
350    ASSERT_TRUE(is_state_checking_for_portal());
351
352    CompleteURLFetch(net::OK, 204, NULL);
353    ASSERT_TRUE(is_state_idle());
354
355    // Check that observer was notified about online state.
356    Mock::VerifyAndClearExpectations(&observer);
357  }
358
359  // WiFi is turned off.
360  {
361    EXPECT_CALL(observer, OnPortalDetectionCompleted(NULL, offline_state))
362        .Times(1);
363
364    SetDisconnected(kStubWireless1);
365    ASSERT_TRUE(is_state_idle());
366
367    // Check that observer was notified about offline state.
368    Mock::VerifyAndClearExpectations(&observer);
369  }
370
371  network_portal_detector()->RemoveObserver(&observer);
372
373  ASSERT_TRUE(
374      MakeResultHistogramChecker()
375          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
376          ->Check());
377}
378
379TEST_F(NetworkPortalDetectorImplTest, TwoNetworks) {
380  ASSERT_TRUE(is_state_idle());
381
382  SetConnected(kStubWireless1);
383  ASSERT_TRUE(is_state_checking_for_portal());
384
385  // WiFi is in portal state.
386  CompleteURLFetch(net::OK, 200, NULL);
387  ASSERT_TRUE(is_state_idle());
388
389  SetConnected(kStubEthernet);
390  ASSERT_TRUE(is_state_checking_for_portal());
391
392  // ethernet is in online state.
393  CompleteURLFetch(net::OK, 204, NULL);
394  ASSERT_TRUE(is_state_idle());
395  CheckPortalState(
396      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubEthernet);
397  CheckPortalState(
398      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
399
400  ASSERT_TRUE(
401      MakeResultHistogramChecker()
402          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
403          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 1)
404          ->Check());
405}
406
407TEST_F(NetworkPortalDetectorImplTest, NetworkChanged) {
408  ASSERT_TRUE(is_state_idle());
409
410  SetConnected(kStubWireless1);
411
412  // WiFi is in portal state.
413  fetcher()->set_response_code(200);
414  ASSERT_TRUE(is_state_checking_for_portal());
415
416  // Active network is changed during portal detection for WiFi.
417  SetConnected(kStubEthernet);
418
419  // Portal detection for WiFi is cancelled, portal detection for
420  // ethernet is initiated.
421  ASSERT_TRUE(is_state_checking_for_portal());
422
423  // ethernet is in online state.
424  CompleteURLFetch(net::OK, 204, NULL);
425  ASSERT_TRUE(is_state_idle());
426  CheckPortalState(
427      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubEthernet);
428
429  // As active network was changed during portal detection for wifi
430  // network, it's state must be unknown.
431  CheckPortalState(
432      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
433
434  ASSERT_TRUE(
435      MakeResultHistogramChecker()
436          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
437          ->Check());
438}
439
440TEST_F(NetworkPortalDetectorImplTest, NetworkStateNotChanged) {
441  ASSERT_TRUE(is_state_idle());
442
443  SetConnected(kStubWireless1);
444  ASSERT_TRUE(is_state_checking_for_portal());
445
446  CompleteURLFetch(net::OK, 204, NULL);
447
448  ASSERT_TRUE(is_state_idle());
449  CheckPortalState(
450      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
451
452  SetConnected(kStubWireless1);
453  ASSERT_TRUE(is_state_idle());
454
455  ASSERT_TRUE(
456      MakeResultHistogramChecker()
457          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
458          ->Check());
459}
460
461TEST_F(NetworkPortalDetectorImplTest, NetworkStateChanged) {
462  // Test for Portal -> Online -> Portal network state transitions.
463  ASSERT_TRUE(is_state_idle());
464
465  SetBehindPortal(kStubWireless1);
466  ASSERT_TRUE(is_state_checking_for_portal());
467
468  CompleteURLFetch(net::OK, 200, NULL);
469
470  ASSERT_TRUE(is_state_idle());
471  CheckPortalState(
472      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
473
474  SetConnected(kStubWireless1);
475  ASSERT_TRUE(is_state_checking_for_portal());
476
477  CompleteURLFetch(net::OK, 204, NULL);
478
479  ASSERT_TRUE(is_state_idle());
480  CheckPortalState(
481      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
482
483  SetBehindPortal(kStubWireless1);
484  ASSERT_TRUE(is_state_checking_for_portal());
485
486  CompleteURLFetch(net::OK, 200, NULL);
487
488  ASSERT_TRUE(is_state_idle());
489  CheckPortalState(
490      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
491
492  ASSERT_TRUE(
493      MakeResultHistogramChecker()
494          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
495          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 2)
496          ->Check());
497}
498
499TEST_F(NetworkPortalDetectorImplTest, PortalDetectionTimeout) {
500  ASSERT_TRUE(is_state_idle());
501
502  // For instantaneous timeout.
503  set_next_attempt_timeout(base::TimeDelta::FromSeconds(0));
504
505  ASSERT_TRUE(is_state_idle());
506  ASSERT_EQ(0, attempt_count());
507
508  SetConnected(kStubWireless1);
509  base::RunLoop().RunUntilIdle();
510
511  // First portal detection timeouts, next portal detection is
512  // scheduled.
513  ASSERT_TRUE(is_state_portal_detection_pending());
514  ASSERT_EQ(1, attempt_count());
515  ASSERT_EQ(base::TimeDelta::FromSeconds(3), next_attempt_delay());
516
517  ASSERT_TRUE(MakeResultHistogramChecker()->Check());
518}
519
520TEST_F(NetworkPortalDetectorImplTest, PortalDetectionRetryAfter) {
521  ASSERT_TRUE(is_state_idle());
522
523  const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 101\n\n";
524
525  ASSERT_TRUE(is_state_idle());
526  ASSERT_EQ(0, attempt_count());
527
528  SetConnected(kStubWireless1);
529  ASSERT_TRUE(is_state_checking_for_portal());
530  CompleteURLFetch(net::OK, 503, retry_after);
531
532  // First portal detection completed, next portal detection is
533  // scheduled after 101 seconds.
534  ASSERT_TRUE(is_state_portal_detection_pending());
535  ASSERT_EQ(1, attempt_count());
536  ASSERT_EQ(base::TimeDelta::FromSeconds(101), next_attempt_delay());
537
538  ASSERT_TRUE(MakeResultHistogramChecker()->Check());
539}
540
541TEST_F(NetworkPortalDetectorImplTest, PortalDetectorRetryAfterIsSmall) {
542  ASSERT_TRUE(is_state_idle());
543
544  const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 1\n\n";
545
546  ASSERT_TRUE(is_state_idle());
547  ASSERT_EQ(0, attempt_count());
548
549  SetConnected(kStubWireless1);
550  CompleteURLFetch(net::OK, 503, retry_after);
551
552  // First portal detection completed, next portal detection is
553  // scheduled after 3 seconds (due to minimum time between detection
554  // attemps).
555  ASSERT_TRUE(is_state_portal_detection_pending());
556  ASSERT_EQ(1, attempt_count());
557  ASSERT_EQ(base::TimeDelta::FromSeconds(3), next_attempt_delay());
558
559  ASSERT_TRUE(MakeResultHistogramChecker()->Check());
560}
561
562TEST_F(NetworkPortalDetectorImplTest, FirstAttemptFailed) {
563  ASSERT_TRUE(is_state_idle());
564
565  set_delay_till_next_attempt(base::TimeDelta());
566  const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 0\n\n";
567
568  ASSERT_TRUE(is_state_idle());
569  ASSERT_EQ(0, attempt_count());
570
571  SetConnected(kStubWireless1);
572
573  CompleteURLFetch(net::OK, 503, retry_after);
574  ASSERT_TRUE(is_state_portal_detection_pending());
575  ASSERT_EQ(1, attempt_count());
576  ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
577
578  // To run CaptivePortalDetector::DetectCaptivePortal().
579  base::RunLoop().RunUntilIdle();
580
581  CompleteURLFetch(net::OK, 204, NULL);
582  ASSERT_TRUE(is_state_idle());
583  ASSERT_EQ(2, attempt_count());
584  CheckPortalState(
585      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
586
587  ASSERT_TRUE(
588      MakeResultHistogramChecker()
589          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
590          ->Check());
591}
592
593TEST_F(NetworkPortalDetectorImplTest, AllAttemptsFailed) {
594  ASSERT_TRUE(is_state_idle());
595
596  set_delay_till_next_attempt(base::TimeDelta());
597  const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 0\n\n";
598
599  ASSERT_TRUE(is_state_idle());
600  ASSERT_EQ(0, attempt_count());
601
602  SetConnected(kStubWireless1);
603
604  CompleteURLFetch(net::OK, 503, retry_after);
605  ASSERT_TRUE(is_state_portal_detection_pending());
606  ASSERT_EQ(1, attempt_count());
607  ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
608
609  // To run CaptivePortalDetector::DetectCaptivePortal().
610  base::RunLoop().RunUntilIdle();
611
612  CompleteURLFetch(net::OK, 503, retry_after);
613  ASSERT_TRUE(is_state_portal_detection_pending());
614  ASSERT_EQ(2, attempt_count());
615  ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
616
617  // To run CaptivePortalDetector::DetectCaptivePortal().
618  base::RunLoop().RunUntilIdle();
619
620  CompleteURLFetch(net::OK, 503, retry_after);
621  ASSERT_TRUE(is_state_idle());
622  ASSERT_EQ(3, attempt_count());
623  CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE,
624                   503,
625                   kStubWireless1);
626
627  ASSERT_TRUE(
628      MakeResultHistogramChecker()
629          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE, 1)
630          ->Check());
631}
632
633TEST_F(NetworkPortalDetectorImplTest, ProxyAuthRequired) {
634  ASSERT_TRUE(is_state_idle());
635  set_delay_till_next_attempt(base::TimeDelta());
636
637  SetConnected(kStubWireless1);
638  CompleteURLFetch(net::OK, 407, NULL);
639  ASSERT_EQ(1, attempt_count());
640  ASSERT_TRUE(is_state_portal_detection_pending());
641
642  base::RunLoop().RunUntilIdle();
643  CompleteURLFetch(net::OK, 407, NULL);
644  ASSERT_EQ(2, attempt_count());
645  ASSERT_TRUE(is_state_portal_detection_pending());
646
647  base::RunLoop().RunUntilIdle();
648  CompleteURLFetch(net::OK, 407, NULL);
649  ASSERT_EQ(3, attempt_count());
650  ASSERT_TRUE(is_state_idle());
651
652  CheckPortalState(
653      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED,
654      407,
655      kStubWireless1);
656
657  ASSERT_TRUE(MakeResultHistogramChecker()
658                  ->Expect(NetworkPortalDetector::
659                               CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED,
660                           1)
661                  ->Check());
662}
663
664TEST_F(NetworkPortalDetectorImplTest, NoResponseButBehindPortal) {
665  ASSERT_TRUE(is_state_idle());
666  set_delay_till_next_attempt(base::TimeDelta());
667
668  SetBehindPortal(kStubWireless1);
669  ASSERT_TRUE(is_state_checking_for_portal());
670
671  CompleteURLFetch(
672      net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID, NULL);
673  ASSERT_EQ(1, attempt_count());
674  ASSERT_TRUE(is_state_portal_detection_pending());
675
676  // To run CaptivePortalDetector::DetectCaptivePortal().
677  base::RunLoop().RunUntilIdle();
678
679  CompleteURLFetch(
680      net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID, NULL);
681  ASSERT_EQ(2, attempt_count());
682  ASSERT_TRUE(is_state_portal_detection_pending());
683
684  // To run CaptivePortalDetector::DetectCaptivePortal().
685  base::RunLoop().RunUntilIdle();
686
687  CompleteURLFetch(
688      net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID, NULL);
689  ASSERT_EQ(3, attempt_count());
690  ASSERT_TRUE(is_state_idle());
691
692  CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL,
693                   net::URLFetcher::RESPONSE_CODE_INVALID,
694                   kStubWireless1);
695
696  ASSERT_TRUE(
697      MakeResultHistogramChecker()
698          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 1)
699          ->Check());
700}
701
702TEST_F(NetworkPortalDetectorImplTest,
703       DisableErrorScreenStrategyWhilePendingRequest) {
704  ASSERT_TRUE(is_state_idle());
705  set_attempt_count(3);
706  enable_error_screen_strategy();
707  ASSERT_TRUE(is_state_portal_detection_pending());
708  disable_error_screen_strategy();
709
710  // To run CaptivePortalDetector::DetectCaptivePortal().
711  base::MessageLoop::current()->RunUntilIdle();
712
713  ASSERT_TRUE(MakeResultHistogramChecker()->Check());
714}
715
716TEST_F(NetworkPortalDetectorImplTest, ErrorScreenStrategyForOnlineNetwork) {
717  ASSERT_TRUE(is_state_idle());
718  set_delay_till_next_attempt(base::TimeDelta());
719
720  SetConnected(kStubWireless1);
721  enable_error_screen_strategy();
722  // To run CaptivePortalDetector::DetectCaptivePortal().
723  base::RunLoop().RunUntilIdle();
724  CompleteURLFetch(net::OK, 204, NULL);
725
726  ASSERT_TRUE(is_state_portal_detection_pending());
727  CheckPortalState(
728      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
729
730  // To run CaptivePortalDetector::DetectCaptivePortal().
731  base::RunLoop().RunUntilIdle();
732
733  CompleteURLFetch(net::OK, 204, NULL);
734
735  ASSERT_TRUE(is_state_portal_detection_pending());
736  CheckPortalState(
737      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
738
739  // To run CaptivePortalDetector::DetectCaptivePortal().
740  base::RunLoop().RunUntilIdle();
741
742  disable_error_screen_strategy();
743
744  ASSERT_TRUE(is_state_portal_detection_pending());
745  // To run CaptivePortalDetector::DetectCaptivePortal().
746  base::RunLoop().RunUntilIdle();
747  ASSERT_TRUE(is_state_checking_for_portal());
748  CompleteURLFetch(net::OK, 204, NULL);
749
750  CheckPortalState(
751      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
752
753  ASSERT_TRUE(
754      MakeResultHistogramChecker()
755          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
756          ->Check());
757}
758
759TEST_F(NetworkPortalDetectorImplTest, ErrorScreenStrategyForPortalNetwork) {
760  ASSERT_TRUE(is_state_idle());
761  set_delay_till_next_attempt(base::TimeDelta());
762
763  enable_error_screen_strategy();
764  SetConnected(kStubWireless1);
765
766  CompleteURLFetch(
767      net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID, NULL);
768  ASSERT_EQ(1, attempt_count());
769  ASSERT_TRUE(is_state_portal_detection_pending());
770  CheckPortalState(
771      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
772
773  // To run CaptivePortalDetector::DetectCaptivePortal().
774  base::RunLoop().RunUntilIdle();
775
776  CompleteURLFetch(
777      net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID, NULL);
778  ASSERT_EQ(2, attempt_count());
779  ASSERT_TRUE(is_state_portal_detection_pending());
780  CheckPortalState(
781      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
782
783  // To run CaptivePortalDetector::DetectCaptivePortal().
784  base::RunLoop().RunUntilIdle();
785
786  CompleteURLFetch(net::OK, 200, NULL);
787  ASSERT_EQ(3, attempt_count());
788  ASSERT_TRUE(is_state_portal_detection_pending());
789  CheckPortalState(
790      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
791
792  // To run CaptivePortalDetector::DetectCaptivePortal().
793  base::RunLoop().RunUntilIdle();
794
795  disable_error_screen_strategy();
796
797  ASSERT_TRUE(is_state_portal_detection_pending());
798  CheckPortalState(
799      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
800
801  ASSERT_TRUE(
802      MakeResultHistogramChecker()
803          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 1)
804          ->Check());
805}
806
807TEST_F(NetworkPortalDetectorImplTest, DetectionTimeoutIsCancelled) {
808  ASSERT_TRUE(is_state_idle());
809  set_delay_till_next_attempt(base::TimeDelta());
810
811  SetConnected(kStubWireless1);
812  ASSERT_TRUE(is_state_checking_for_portal());
813  CheckPortalState(
814      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
815
816  stop_detection();
817
818  ASSERT_TRUE(is_state_idle());
819  ASSERT_TRUE(attempt_timeout_is_cancelled());
820  CheckPortalState(
821      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
822
823  ASSERT_TRUE(MakeResultHistogramChecker()->Check());
824}
825
826TEST_F(NetworkPortalDetectorImplTest, TestDetectionRestart) {
827  ASSERT_TRUE(is_state_idle());
828  set_delay_till_next_attempt(base::TimeDelta());
829
830  // First portal detection attempts determines ONLINE state.
831  SetConnected(kStubWireless1);
832  ASSERT_TRUE(is_state_checking_for_portal());
833  ASSERT_FALSE(start_detection_if_idle());
834
835  CompleteURLFetch(net::OK, 204, NULL);
836
837  CheckPortalState(
838      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
839  ASSERT_TRUE(is_state_idle());
840
841  // First portal detection attempts determines PORTAL state.
842  ASSERT_TRUE(start_detection_if_idle());
843  ASSERT_TRUE(is_state_portal_detection_pending());
844  ASSERT_FALSE(start_detection_if_idle());
845
846  base::RunLoop().RunUntilIdle();
847  ASSERT_TRUE(is_state_checking_for_portal());
848  CompleteURLFetch(net::OK, 200, NULL);
849
850  CheckPortalState(
851      NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
852  ASSERT_TRUE(is_state_idle());
853
854  ASSERT_TRUE(
855      MakeResultHistogramChecker()
856          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
857          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 1)
858          ->Check());
859}
860
861TEST_F(NetworkPortalDetectorImplTest, RequestTimeouts) {
862  ASSERT_TRUE(is_state_idle());
863  set_delay_till_next_attempt(base::TimeDelta());
864
865  SetNetworkDeviceEnabled(shill::kTypeWifi, false);
866  SetConnected(kStubCellular);
867
868  // First portal detection attempt for cellular1 uses 5sec timeout.
869  CheckRequestTimeoutAndCompleteAttempt(
870      0, 5, net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID);
871
872  // Second portal detection attempt for cellular1 uses 10sec timeout.
873  ASSERT_TRUE(is_state_portal_detection_pending());
874  base::RunLoop().RunUntilIdle();
875  CheckRequestTimeoutAndCompleteAttempt(1,
876                                        10,
877                                        net::ERR_CONNECTION_CLOSED,
878                                        net::URLFetcher::RESPONSE_CODE_INVALID);
879
880  // Third portal detection attempt for cellular1 uses 15sec timeout.
881  ASSERT_TRUE(is_state_portal_detection_pending());
882  base::RunLoop().RunUntilIdle();
883  CheckRequestTimeoutAndCompleteAttempt(2,
884                                        15,
885                                        net::ERR_CONNECTION_CLOSED,
886                                        net::URLFetcher::RESPONSE_CODE_INVALID);
887
888  ASSERT_TRUE(is_state_idle());
889
890  // Check that in lazy detection for cellular1 15sec timeout is used.
891  enable_error_screen_strategy();
892  ASSERT_TRUE(is_state_portal_detection_pending());
893  base::RunLoop().RunUntilIdle();
894  CheckRequestTimeoutAndCompleteAttempt(0,
895                                        15,
896                                        net::ERR_CONNECTION_CLOSED,
897                                        net::URLFetcher::RESPONSE_CODE_INVALID);
898  disable_error_screen_strategy();
899  ASSERT_TRUE(is_state_portal_detection_pending());
900
901  SetNetworkDeviceEnabled(shill::kTypeWifi, true);
902  SetConnected(kStubWireless1);
903
904  // First portal detection attempt for wifi1 uses 5sec timeout.
905  CheckRequestTimeoutAndCompleteAttempt(
906      0, 5, net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID);
907
908  // Second portal detection attempt for wifi1 also uses 5sec timeout.
909  ASSERT_TRUE(is_state_portal_detection_pending());
910  base::RunLoop().RunUntilIdle();
911  CheckRequestTimeoutAndCompleteAttempt(1, 10, net::OK, 204);
912  ASSERT_TRUE(is_state_idle());
913
914  // Check that in error screen strategy detection for wifi1 15sec
915  // timeout is used.
916  enable_error_screen_strategy();
917  ASSERT_TRUE(is_state_portal_detection_pending());
918  base::RunLoop().RunUntilIdle();
919  CheckRequestTimeoutAndCompleteAttempt(0, 15, net::OK, 204);
920  disable_error_screen_strategy();
921  ASSERT_TRUE(is_state_portal_detection_pending());
922
923  ASSERT_TRUE(
924      MakeResultHistogramChecker()
925          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE, 1)
926          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
927          ->Check());
928}
929
930TEST_F(NetworkPortalDetectorImplTest, StartDetectionIfIdle) {
931  ASSERT_TRUE(is_state_idle());
932  set_delay_till_next_attempt(base::TimeDelta());
933  SetConnected(kStubWireless1);
934
935  // First portal detection attempt for wifi1 uses 5sec timeout.
936  CheckRequestTimeoutAndCompleteAttempt(
937      0, 5, net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID);
938  ASSERT_TRUE(is_state_portal_detection_pending());
939  base::RunLoop().RunUntilIdle();
940
941  // Second portal detection attempt for wifi1 uses 10sec timeout.
942  CheckRequestTimeoutAndCompleteAttempt(1,
943                                        10,
944                                        net::ERR_CONNECTION_CLOSED,
945                                        net::URLFetcher::RESPONSE_CODE_INVALID);
946  ASSERT_TRUE(is_state_portal_detection_pending());
947  base::RunLoop().RunUntilIdle();
948
949  // Second portal detection attempt for wifi1 uses 15sec timeout.
950  CheckRequestTimeoutAndCompleteAttempt(2,
951                                        15,
952                                        net::ERR_CONNECTION_CLOSED,
953                                        net::URLFetcher::RESPONSE_CODE_INVALID);
954  ASSERT_TRUE(is_state_idle());
955  start_detection_if_idle();
956
957  ASSERT_TRUE(is_state_portal_detection_pending());
958
959  // First portal detection attempt for wifi1 uses 5sec timeout.
960  base::RunLoop().RunUntilIdle();
961  CheckRequestTimeoutAndCompleteAttempt(0, 5, net::OK, 204);
962  ASSERT_TRUE(is_state_idle());
963
964  ASSERT_TRUE(
965      MakeResultHistogramChecker()
966          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE, 1)
967          ->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
968          ->Check());
969}
970
971}  // namespace chromeos
972