blob: 616c1827c35c945ed16d726172db3d459fd42495 [file] [log] [blame]
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <algorithm>
#include <vector>
#include "base/command_line.h"
#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram_base.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/statistics_recorder.h"
#include "base/run_loop.h"
#include "chrome/browser/chromeos/net/network_portal_detector_impl.h"
#include "chrome/browser/chromeos/net/network_portal_detector_test_utils.h"
#include "chrome/test/base/testing_profile.h"
#include "chromeos/chromeos_switches.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_device_client.h"
#include "chromeos/dbus/shill_service_client.h"
#include "chromeos/network/network_state.h"
#include "chromeos/network/network_state_handler.h"
#include "chromeos/network/portal_detector/network_portal_detector_strategy.h"
#include "components/captive_portal/captive_portal_detector.h"
#include "components/captive_portal/captive_portal_testing_utils.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "dbus/object_path.h"
#include "net/base/net_errors.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/cros_system_api/dbus/service_constants.h"
using testing::AnyNumber;
using testing::Mock;
using testing::_;
namespace chromeos {
namespace {
// Service path / guid for stub networks.
const char kStubEthernet[] = "stub_ethernet";
const char kStubWireless1[] = "stub_wifi1";
const char kStubWireless2[] = "stub_wifi2";
const char kStubCellular[] = "stub_cellular";
void ErrorCallbackFunction(const std::string& error_name,
const std::string& error_message) {
LOG(ERROR) << "Shill Error: " << error_name << " : " << error_message;
}
class MockObserver : public NetworkPortalDetector::Observer {
public:
virtual ~MockObserver() {}
MOCK_METHOD2(OnPortalDetectionCompleted,
void(const NetworkState* network,
const NetworkPortalDetector::CaptivePortalState& state));
};
} // namespace
class NetworkPortalDetectorImplTest
: public testing::Test,
public captive_portal::CaptivePortalDetectorTestBase {
protected:
virtual void SetUp() {
CommandLine* cl = CommandLine::ForCurrentProcess();
cl->AppendSwitch(switches::kDisableNetworkPortalNotification);
DBusThreadManager::InitializeWithStub();
base::StatisticsRecorder::Initialize();
SetupNetworkHandler();
profile_.reset(new TestingProfile());
network_portal_detector_.reset(
new NetworkPortalDetectorImpl(profile_->GetRequestContext()));
network_portal_detector_->Enable(false);
set_detector(network_portal_detector_->captive_portal_detector_.get());
// Prevents flakiness due to message loop delays.
set_time_ticks(base::TimeTicks::Now());
if (base::HistogramBase* histogram =
base::StatisticsRecorder::FindHistogram(
"CaptivePortal.OOBE.DetectionResult")) {
original_samples_.reset(histogram->SnapshotSamples().release());
}
}
virtual void TearDown() {
network_portal_detector_.reset();
profile_.reset();
NetworkHandler::Shutdown();
DBusThreadManager::Shutdown();
PortalDetectorStrategy::reset_fields_for_testing();
}
void CheckPortalState(NetworkPortalDetector::CaptivePortalStatus status,
int response_code,
const std::string& guid) {
NetworkPortalDetector::CaptivePortalState state =
network_portal_detector()->GetCaptivePortalState(guid);
ASSERT_EQ(status, state.status);
ASSERT_EQ(response_code, state.response_code);
}
void CheckRequestTimeoutAndCompleteAttempt(int expected_attempt_count,
int expected_request_timeout_sec,
int net_error,
int status_code) {
ASSERT_TRUE(is_state_checking_for_portal());
ASSERT_EQ(expected_attempt_count, attempt_count());
ASSERT_EQ(base::TimeDelta::FromSeconds(expected_request_timeout_sec),
get_next_attempt_timeout());
CompleteURLFetch(net_error, status_code, NULL);
}
Profile* profile() { return profile_.get(); }
NetworkPortalDetectorImpl* network_portal_detector() {
return network_portal_detector_.get();
}
NetworkPortalDetectorImpl::State state() {
return network_portal_detector()->state();
}
bool start_detection_if_idle() {
return network_portal_detector()->StartDetectionIfIdle();
}
void enable_error_screen_strategy() {
network_portal_detector()->SetStrategy(
PortalDetectorStrategy::STRATEGY_ID_ERROR_SCREEN);
}
void disable_error_screen_strategy() {
network_portal_detector()->SetStrategy(
PortalDetectorStrategy::STRATEGY_ID_LOGIN_SCREEN);
}
void stop_detection() { network_portal_detector()->StopDetection(); }
bool attempt_timeout_is_cancelled() {
return network_portal_detector()->AttemptTimeoutIsCancelledForTesting();
}
base::TimeDelta get_next_attempt_timeout() {
return network_portal_detector()->strategy_->GetNextAttemptTimeout();
}
void set_next_attempt_timeout(const base::TimeDelta& timeout) {
PortalDetectorStrategy::set_next_attempt_timeout_for_testing(timeout);
}
bool is_state_idle() {
return (NetworkPortalDetectorImpl::STATE_IDLE == state());
}
bool is_state_portal_detection_pending() {
return (NetworkPortalDetectorImpl::STATE_PORTAL_CHECK_PENDING == state());
}
bool is_state_checking_for_portal() {
return (NetworkPortalDetectorImpl::STATE_CHECKING_FOR_PORTAL == state());
}
const base::TimeDelta& next_attempt_delay() {
return network_portal_detector()->next_attempt_delay_for_testing();
}
int attempt_count() {
return network_portal_detector()->attempt_count_for_testing();
}
void set_attempt_count(int ac) {
network_portal_detector()->set_attempt_count_for_testing(ac);
}
void set_delay_till_next_attempt(const base::TimeDelta& delta) {
PortalDetectorStrategy::set_delay_till_next_attempt_for_testing(delta);
}
void set_time_ticks(const base::TimeTicks& time_ticks) {
network_portal_detector()->set_time_ticks_for_testing(time_ticks);
}
void SetBehindPortal(const std::string& service_path) {
DBusThreadManager::Get()->GetShillServiceClient()->SetProperty(
dbus::ObjectPath(service_path),
shill::kStateProperty,
base::StringValue(shill::kStatePortal),
base::Bind(&base::DoNothing),
base::Bind(&ErrorCallbackFunction));
base::RunLoop().RunUntilIdle();
}
void SetNetworkDeviceEnabled(const std::string& type, bool enabled) {
NetworkHandler::Get()->network_state_handler()->SetTechnologyEnabled(
NetworkTypePattern::Primitive(type),
enabled,
network_handler::ErrorCallback());
base::RunLoop().RunUntilIdle();
}
void SetConnected(const std::string& service_path) {
DBusThreadManager::Get()->GetShillServiceClient()->Connect(
dbus::ObjectPath(service_path),
base::Bind(&base::DoNothing),
base::Bind(&ErrorCallbackFunction));
base::RunLoop().RunUntilIdle();
}
void SetDisconnected(const std::string& service_path) {
DBusThreadManager::Get()->GetShillServiceClient()->Disconnect(
dbus::ObjectPath(service_path),
base::Bind(&*base::DoNothing),
base::Bind(&ErrorCallbackFunction));
base::RunLoop().RunUntilIdle();
}
scoped_ptr<EnumHistogramChecker> MakeResultHistogramChecker() {
return scoped_ptr<EnumHistogramChecker>(
new EnumHistogramChecker(
"CaptivePortal.OOBE.DetectionResult",
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_COUNT,
original_samples_.get()));
}
private:
void AddService(const std::string& network_id,
const std::string& type) {
DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
AddService(network_id /* service_path */,
network_id /* guid */,
network_id /* name */,
type,
shill::kStateIdle,
true /* add_to_visible */);
}
void SetupDefaultShillState() {
base::RunLoop().RunUntilIdle();
DBusThreadManager::Get()->GetShillServiceClient()->GetTestInterface()->
ClearServices();
AddService(kStubEthernet, shill::kTypeEthernet);
AddService(kStubWireless1, shill::kTypeWifi);
AddService(kStubWireless2, shill::kTypeWifi);
AddService(kStubCellular, shill::kTypeCellular);
}
void SetupNetworkHandler() {
SetupDefaultShillState();
NetworkHandler::Initialize();
}
content::TestBrowserThreadBundle thread_bundle_;
scoped_ptr<TestingProfile> profile_;
scoped_ptr<NetworkPortalDetectorImpl> network_portal_detector_;
scoped_ptr<base::HistogramSamples> original_samples_;
};
TEST_F(NetworkPortalDetectorImplTest, NoPortal) {
ASSERT_TRUE(is_state_idle());
SetConnected(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
CompleteURLFetch(net::OK, 204, NULL);
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, Portal) {
ASSERT_TRUE(is_state_idle());
// Check HTTP 200 response code.
SetConnected(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 200, NULL);
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
// Check HTTP 301 response code.
SetConnected(kStubWireless2);
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 301, NULL);
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 301, kStubWireless2);
// Check HTTP 302 response code.
SetConnected(kStubEthernet);
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 302, NULL);
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 302, kStubEthernet);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 3)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, Online2Offline) {
ASSERT_TRUE(is_state_idle());
MockObserver observer;
network_portal_detector()->AddObserver(&observer);
NetworkPortalDetector::CaptivePortalState offline_state;
offline_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE;
// WiFi is in online state.
{
// When transitioning to a connected state, the network will transition to
// connecting states which will set the default network to NULL. This may
// get triggered multiple times.
EXPECT_CALL(observer, OnPortalDetectionCompleted(_, offline_state))
.Times(AnyNumber());
// Expect a single transition to an online state.
NetworkPortalDetector::CaptivePortalState online_state;
online_state.status = NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE;
online_state.response_code = 204;
EXPECT_CALL(observer, OnPortalDetectionCompleted(_, online_state)).Times(1);
SetConnected(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 204, NULL);
ASSERT_TRUE(is_state_idle());
// Check that observer was notified about online state.
Mock::VerifyAndClearExpectations(&observer);
}
// WiFi is turned off.
{
EXPECT_CALL(observer, OnPortalDetectionCompleted(NULL, offline_state))
.Times(1);
SetDisconnected(kStubWireless1);
ASSERT_TRUE(is_state_idle());
// Check that observer was notified about offline state.
Mock::VerifyAndClearExpectations(&observer);
}
network_portal_detector()->RemoveObserver(&observer);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, TwoNetworks) {
ASSERT_TRUE(is_state_idle());
SetConnected(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
// WiFi is in portal state.
CompleteURLFetch(net::OK, 200, NULL);
ASSERT_TRUE(is_state_idle());
SetConnected(kStubEthernet);
ASSERT_TRUE(is_state_checking_for_portal());
// ethernet is in online state.
CompleteURLFetch(net::OK, 204, NULL);
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubEthernet);
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, NetworkChanged) {
ASSERT_TRUE(is_state_idle());
SetConnected(kStubWireless1);
// WiFi is in portal state.
fetcher()->set_response_code(200);
ASSERT_TRUE(is_state_checking_for_portal());
// Active network is changed during portal detection for WiFi.
SetConnected(kStubEthernet);
// Portal detection for WiFi is cancelled, portal detection for
// ethernet is initiated.
ASSERT_TRUE(is_state_checking_for_portal());
// ethernet is in online state.
CompleteURLFetch(net::OK, 204, NULL);
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubEthernet);
// As active network was changed during portal detection for wifi
// network, it's state must be unknown.
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, NetworkStateNotChanged) {
ASSERT_TRUE(is_state_idle());
SetConnected(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 204, NULL);
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
SetConnected(kStubWireless1);
ASSERT_TRUE(is_state_idle());
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, NetworkStateChanged) {
// Test for Portal -> Online -> Portal network state transitions.
ASSERT_TRUE(is_state_idle());
SetBehindPortal(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 200, NULL);
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
SetConnected(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 204, NULL);
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
SetBehindPortal(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 200, NULL);
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 2)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, PortalDetectionTimeout) {
ASSERT_TRUE(is_state_idle());
// For instantaneous timeout.
set_next_attempt_timeout(base::TimeDelta::FromSeconds(0));
ASSERT_TRUE(is_state_idle());
ASSERT_EQ(0, attempt_count());
SetConnected(kStubWireless1);
base::RunLoop().RunUntilIdle();
// First portal detection timeouts, next portal detection is
// scheduled.
ASSERT_TRUE(is_state_portal_detection_pending());
ASSERT_EQ(1, attempt_count());
ASSERT_EQ(base::TimeDelta::FromSeconds(3), next_attempt_delay());
ASSERT_TRUE(MakeResultHistogramChecker()->Check());
}
TEST_F(NetworkPortalDetectorImplTest, PortalDetectionRetryAfter) {
ASSERT_TRUE(is_state_idle());
const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 101\n\n";
ASSERT_TRUE(is_state_idle());
ASSERT_EQ(0, attempt_count());
SetConnected(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 503, retry_after);
// First portal detection completed, next portal detection is
// scheduled after 101 seconds.
ASSERT_TRUE(is_state_portal_detection_pending());
ASSERT_EQ(1, attempt_count());
ASSERT_EQ(base::TimeDelta::FromSeconds(101), next_attempt_delay());
ASSERT_TRUE(MakeResultHistogramChecker()->Check());
}
TEST_F(NetworkPortalDetectorImplTest, PortalDetectorRetryAfterIsSmall) {
ASSERT_TRUE(is_state_idle());
const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 1\n\n";
ASSERT_TRUE(is_state_idle());
ASSERT_EQ(0, attempt_count());
SetConnected(kStubWireless1);
CompleteURLFetch(net::OK, 503, retry_after);
// First portal detection completed, next portal detection is
// scheduled after 3 seconds (due to minimum time between detection
// attemps).
ASSERT_TRUE(is_state_portal_detection_pending());
ASSERT_EQ(1, attempt_count());
ASSERT_EQ(base::TimeDelta::FromSeconds(3), next_attempt_delay());
ASSERT_TRUE(MakeResultHistogramChecker()->Check());
}
TEST_F(NetworkPortalDetectorImplTest, FirstAttemptFailed) {
ASSERT_TRUE(is_state_idle());
set_delay_till_next_attempt(base::TimeDelta());
const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 0\n\n";
ASSERT_TRUE(is_state_idle());
ASSERT_EQ(0, attempt_count());
SetConnected(kStubWireless1);
CompleteURLFetch(net::OK, 503, retry_after);
ASSERT_TRUE(is_state_portal_detection_pending());
ASSERT_EQ(1, attempt_count());
ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
CompleteURLFetch(net::OK, 204, NULL);
ASSERT_TRUE(is_state_idle());
ASSERT_EQ(2, attempt_count());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, AllAttemptsFailed) {
ASSERT_TRUE(is_state_idle());
set_delay_till_next_attempt(base::TimeDelta());
const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 0\n\n";
ASSERT_TRUE(is_state_idle());
ASSERT_EQ(0, attempt_count());
SetConnected(kStubWireless1);
CompleteURLFetch(net::OK, 503, retry_after);
ASSERT_TRUE(is_state_portal_detection_pending());
ASSERT_EQ(1, attempt_count());
ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
CompleteURLFetch(net::OK, 503, retry_after);
ASSERT_TRUE(is_state_portal_detection_pending());
ASSERT_EQ(2, attempt_count());
ASSERT_EQ(base::TimeDelta::FromSeconds(0), next_attempt_delay());
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
CompleteURLFetch(net::OK, 503, retry_after);
ASSERT_TRUE(is_state_idle());
ASSERT_EQ(3, attempt_count());
CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE,
503,
kStubWireless1);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, ProxyAuthRequired) {
ASSERT_TRUE(is_state_idle());
set_delay_till_next_attempt(base::TimeDelta());
SetConnected(kStubWireless1);
CompleteURLFetch(net::OK, 407, NULL);
ASSERT_EQ(1, attempt_count());
ASSERT_TRUE(is_state_portal_detection_pending());
base::RunLoop().RunUntilIdle();
CompleteURLFetch(net::OK, 407, NULL);
ASSERT_EQ(2, attempt_count());
ASSERT_TRUE(is_state_portal_detection_pending());
base::RunLoop().RunUntilIdle();
CompleteURLFetch(net::OK, 407, NULL);
ASSERT_EQ(3, attempt_count());
ASSERT_TRUE(is_state_idle());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED,
407,
kStubWireless1);
ASSERT_TRUE(MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::
CAPTIVE_PORTAL_STATUS_PROXY_AUTH_REQUIRED,
1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, NoResponseButBehindPortal) {
ASSERT_TRUE(is_state_idle());
set_delay_till_next_attempt(base::TimeDelta());
SetBehindPortal(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(
net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID, NULL);
ASSERT_EQ(1, attempt_count());
ASSERT_TRUE(is_state_portal_detection_pending());
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
CompleteURLFetch(
net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID, NULL);
ASSERT_EQ(2, attempt_count());
ASSERT_TRUE(is_state_portal_detection_pending());
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
CompleteURLFetch(
net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID, NULL);
ASSERT_EQ(3, attempt_count());
ASSERT_TRUE(is_state_idle());
CheckPortalState(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL,
net::URLFetcher::RESPONSE_CODE_INVALID,
kStubWireless1);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest,
DisableErrorScreenStrategyWhilePendingRequest) {
ASSERT_TRUE(is_state_idle());
set_attempt_count(3);
enable_error_screen_strategy();
ASSERT_TRUE(is_state_portal_detection_pending());
disable_error_screen_strategy();
// To run CaptivePortalDetector::DetectCaptivePortal().
base::MessageLoop::current()->RunUntilIdle();
ASSERT_TRUE(MakeResultHistogramChecker()->Check());
}
TEST_F(NetworkPortalDetectorImplTest, ErrorScreenStrategyForOnlineNetwork) {
ASSERT_TRUE(is_state_idle());
set_delay_till_next_attempt(base::TimeDelta());
SetConnected(kStubWireless1);
enable_error_screen_strategy();
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
CompleteURLFetch(net::OK, 204, NULL);
ASSERT_TRUE(is_state_portal_detection_pending());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
CompleteURLFetch(net::OK, 204, NULL);
ASSERT_TRUE(is_state_portal_detection_pending());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
disable_error_screen_strategy();
ASSERT_TRUE(is_state_portal_detection_pending());
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 204, NULL);
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, ErrorScreenStrategyForPortalNetwork) {
ASSERT_TRUE(is_state_idle());
set_delay_till_next_attempt(base::TimeDelta());
enable_error_screen_strategy();
SetConnected(kStubWireless1);
CompleteURLFetch(
net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID, NULL);
ASSERT_EQ(1, attempt_count());
ASSERT_TRUE(is_state_portal_detection_pending());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
CompleteURLFetch(
net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID, NULL);
ASSERT_EQ(2, attempt_count());
ASSERT_TRUE(is_state_portal_detection_pending());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
CompleteURLFetch(net::OK, 200, NULL);
ASSERT_EQ(3, attempt_count());
ASSERT_TRUE(is_state_portal_detection_pending());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
// To run CaptivePortalDetector::DetectCaptivePortal().
base::RunLoop().RunUntilIdle();
disable_error_screen_strategy();
ASSERT_TRUE(is_state_portal_detection_pending());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, DetectionTimeoutIsCancelled) {
ASSERT_TRUE(is_state_idle());
set_delay_till_next_attempt(base::TimeDelta());
SetConnected(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
stop_detection();
ASSERT_TRUE(is_state_idle());
ASSERT_TRUE(attempt_timeout_is_cancelled());
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_UNKNOWN, -1, kStubWireless1);
ASSERT_TRUE(MakeResultHistogramChecker()->Check());
}
TEST_F(NetworkPortalDetectorImplTest, TestDetectionRestart) {
ASSERT_TRUE(is_state_idle());
set_delay_till_next_attempt(base::TimeDelta());
// First portal detection attempts determines ONLINE state.
SetConnected(kStubWireless1);
ASSERT_TRUE(is_state_checking_for_portal());
ASSERT_FALSE(start_detection_if_idle());
CompleteURLFetch(net::OK, 204, NULL);
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 204, kStubWireless1);
ASSERT_TRUE(is_state_idle());
// First portal detection attempts determines PORTAL state.
ASSERT_TRUE(start_detection_if_idle());
ASSERT_TRUE(is_state_portal_detection_pending());
ASSERT_FALSE(start_detection_if_idle());
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(is_state_checking_for_portal());
CompleteURLFetch(net::OK, 200, NULL);
CheckPortalState(
NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 200, kStubWireless1);
ASSERT_TRUE(is_state_idle());
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_PORTAL, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, RequestTimeouts) {
ASSERT_TRUE(is_state_idle());
set_delay_till_next_attempt(base::TimeDelta());
SetNetworkDeviceEnabled(shill::kTypeWifi, false);
SetConnected(kStubCellular);
// First portal detection attempt for cellular1 uses 5sec timeout.
CheckRequestTimeoutAndCompleteAttempt(
0, 5, net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID);
// Second portal detection attempt for cellular1 uses 10sec timeout.
ASSERT_TRUE(is_state_portal_detection_pending());
base::RunLoop().RunUntilIdle();
CheckRequestTimeoutAndCompleteAttempt(1,
10,
net::ERR_CONNECTION_CLOSED,
net::URLFetcher::RESPONSE_CODE_INVALID);
// Third portal detection attempt for cellular1 uses 15sec timeout.
ASSERT_TRUE(is_state_portal_detection_pending());
base::RunLoop().RunUntilIdle();
CheckRequestTimeoutAndCompleteAttempt(2,
15,
net::ERR_CONNECTION_CLOSED,
net::URLFetcher::RESPONSE_CODE_INVALID);
ASSERT_TRUE(is_state_idle());
// Check that in lazy detection for cellular1 15sec timeout is used.
enable_error_screen_strategy();
ASSERT_TRUE(is_state_portal_detection_pending());
base::RunLoop().RunUntilIdle();
CheckRequestTimeoutAndCompleteAttempt(0,
15,
net::ERR_CONNECTION_CLOSED,
net::URLFetcher::RESPONSE_CODE_INVALID);
disable_error_screen_strategy();
ASSERT_TRUE(is_state_portal_detection_pending());
SetNetworkDeviceEnabled(shill::kTypeWifi, true);
SetConnected(kStubWireless1);
// First portal detection attempt for wifi1 uses 5sec timeout.
CheckRequestTimeoutAndCompleteAttempt(
0, 5, net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID);
// Second portal detection attempt for wifi1 also uses 5sec timeout.
ASSERT_TRUE(is_state_portal_detection_pending());
base::RunLoop().RunUntilIdle();
CheckRequestTimeoutAndCompleteAttempt(1, 10, net::OK, 204);
ASSERT_TRUE(is_state_idle());
// Check that in error screen strategy detection for wifi1 15sec
// timeout is used.
enable_error_screen_strategy();
ASSERT_TRUE(is_state_portal_detection_pending());
base::RunLoop().RunUntilIdle();
CheckRequestTimeoutAndCompleteAttempt(0, 15, net::OK, 204);
disable_error_screen_strategy();
ASSERT_TRUE(is_state_portal_detection_pending());
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE, 1)
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Check());
}
TEST_F(NetworkPortalDetectorImplTest, StartDetectionIfIdle) {
ASSERT_TRUE(is_state_idle());
set_delay_till_next_attempt(base::TimeDelta());
SetConnected(kStubWireless1);
// First portal detection attempt for wifi1 uses 5sec timeout.
CheckRequestTimeoutAndCompleteAttempt(
0, 5, net::ERR_CONNECTION_CLOSED, net::URLFetcher::RESPONSE_CODE_INVALID);
ASSERT_TRUE(is_state_portal_detection_pending());
base::RunLoop().RunUntilIdle();
// Second portal detection attempt for wifi1 uses 10sec timeout.
CheckRequestTimeoutAndCompleteAttempt(1,
10,
net::ERR_CONNECTION_CLOSED,
net::URLFetcher::RESPONSE_CODE_INVALID);
ASSERT_TRUE(is_state_portal_detection_pending());
base::RunLoop().RunUntilIdle();
// Second portal detection attempt for wifi1 uses 15sec timeout.
CheckRequestTimeoutAndCompleteAttempt(2,
15,
net::ERR_CONNECTION_CLOSED,
net::URLFetcher::RESPONSE_CODE_INVALID);
ASSERT_TRUE(is_state_idle());
start_detection_if_idle();
ASSERT_TRUE(is_state_portal_detection_pending());
// First portal detection attempt for wifi1 uses 5sec timeout.
base::RunLoop().RunUntilIdle();
CheckRequestTimeoutAndCompleteAttempt(0, 5, net::OK, 204);
ASSERT_TRUE(is_state_idle());
ASSERT_TRUE(
MakeResultHistogramChecker()
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_OFFLINE, 1)
->Expect(NetworkPortalDetector::CAPTIVE_PORTAL_STATUS_ONLINE, 1)
->Check());
}
} // namespace chromeos