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