This source file includes following definitions.
- captive_portal_service_
- captive_portal_result
- num_results_received
- Observe
- Initialize
- EnableCaptivePortalDetectionPreference
- RunTest
- RunDisabledTest
- RunBackoffTest
- AdvanceTime
- TimerRunning
- GetTimeUntilNextRequest
- set_initial_backoff_no_portal
- set_initial_backoff_portal
- set_maximum_backoff
- set_num_errors_to_ignore
- set_multiply_factor
- set_jitter_factor
- profile
- service
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
- TEST_F
#include "chrome/browser/captive_portal/captive_portal_service.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/command_line.h"
#include "base/prefs/pref_service.h"
#include "base/run_loop.h"
#include "base/test/test_timeouts.h"
#include "chrome/browser/captive_portal/testing_utils.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/test/base/testing_profile.h"
#include "chrome/test/base/ui_test_utils.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_source.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace captive_portal {
namespace {
class CaptivePortalObserver : public content::NotificationObserver {
public:
CaptivePortalObserver(Profile* profile,
CaptivePortalService* captive_portal_service)
: captive_portal_result_(
captive_portal_service->last_detection_result()),
num_results_received_(0),
profile_(profile),
captive_portal_service_(captive_portal_service) {
registrar_.Add(this,
chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT,
content::Source<Profile>(profile_));
}
Result captive_portal_result() const { return captive_portal_result_; }
int num_results_received() const { return num_results_received_; }
private:
virtual void Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) OVERRIDE {
ASSERT_EQ(type, chrome::NOTIFICATION_CAPTIVE_PORTAL_CHECK_RESULT);
ASSERT_EQ(profile_, content::Source<Profile>(source).ptr());
CaptivePortalService::Results *results =
content::Details<CaptivePortalService::Results>(details).ptr();
EXPECT_EQ(captive_portal_result_, results->previous_result);
EXPECT_EQ(captive_portal_service_->last_detection_result(),
results->result);
captive_portal_result_ = results->result;
++num_results_received_;
}
Result captive_portal_result_;
int num_results_received_;
Profile* profile_;
CaptivePortalService* captive_portal_service_;
content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(CaptivePortalObserver);
};
}
class CaptivePortalServiceTest : public testing::Test,
public CaptivePortalDetectorTestBase {
public:
CaptivePortalServiceTest()
: old_captive_portal_testing_state_(
CaptivePortalService::get_state_for_testing()) {
}
virtual ~CaptivePortalServiceTest() {
CaptivePortalService::set_state_for_testing(
old_captive_portal_testing_state_);
}
void Initialize(CaptivePortalService::TestingState testing_state) {
CaptivePortalService::set_state_for_testing(testing_state);
profile_.reset(new TestingProfile());
service_.reset(new CaptivePortalService(profile_.get()));
service_->set_time_ticks_for_testing(base::TimeTicks::Now());
set_initial_backoff_no_portal(base::TimeDelta());
set_initial_backoff_portal(base::TimeDelta());
set_detector(&service_->captive_portal_detector_);
SetTime(base::Time::Now());
set_jitter_factor(0.0);
set_multiply_factor(2.0);
set_maximum_backoff(base::TimeDelta::FromSeconds(1600));
set_num_errors_to_ignore(1);
EnableCaptivePortalDetectionPreference(true);
}
void EnableCaptivePortalDetectionPreference(bool enabled) {
profile()->GetPrefs()->SetBoolean(prefs::kAlternateErrorPagesEnabled,
enabled);
}
void RunTest(Result expected_result,
int net_error,
int status_code,
int expected_delay_secs,
const char* response_headers) {
base::TimeDelta expected_delay =
base::TimeDelta::FromSeconds(expected_delay_secs);
ASSERT_EQ(CaptivePortalService::STATE_IDLE, service()->state());
ASSERT_EQ(expected_delay, GetTimeUntilNextRequest());
AdvanceTime(expected_delay);
ASSERT_EQ(base::TimeDelta(), GetTimeUntilNextRequest());
CaptivePortalObserver observer(profile(), service());
service()->DetectCaptivePortal();
EXPECT_EQ(CaptivePortalService::STATE_TIMER_RUNNING, service()->state());
EXPECT_FALSE(FetchingURL());
ASSERT_TRUE(TimerRunning());
base::RunLoop().RunUntilIdle();
EXPECT_EQ(CaptivePortalService::STATE_CHECKING_FOR_PORTAL,
service()->state());
ASSERT_TRUE(FetchingURL());
EXPECT_FALSE(TimerRunning());
CompleteURLFetch(net_error, status_code, response_headers);
EXPECT_FALSE(FetchingURL());
EXPECT_FALSE(TimerRunning());
EXPECT_EQ(1, observer.num_results_received());
EXPECT_EQ(expected_result, observer.captive_portal_result());
}
void RunDisabledTest(int expected_delay_secs) {
base::TimeDelta expected_delay =
base::TimeDelta::FromSeconds(expected_delay_secs);
ASSERT_EQ(CaptivePortalService::STATE_IDLE, service()->state());
ASSERT_EQ(expected_delay, GetTimeUntilNextRequest());
AdvanceTime(expected_delay);
ASSERT_EQ(base::TimeDelta(), GetTimeUntilNextRequest());
CaptivePortalObserver observer(profile(), service());
service()->DetectCaptivePortal();
EXPECT_EQ(CaptivePortalService::STATE_TIMER_RUNNING, service()->state());
EXPECT_FALSE(FetchingURL());
ASSERT_TRUE(TimerRunning());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(FetchingURL());
EXPECT_FALSE(TimerRunning());
EXPECT_EQ(1, observer.num_results_received());
EXPECT_EQ(RESULT_INTERNET_CONNECTED, observer.captive_portal_result());
}
void RunBackoffTest(Result expected_result, int net_error, int status_code) {
RunTest(expected_result, net_error, status_code, 0, NULL);
RunTest(expected_result, net_error, status_code, 0, NULL);
RunTest(expected_result, net_error, status_code, 100, NULL);
RunTest(expected_result, net_error, status_code, 200, NULL);
RunTest(expected_result, net_error, status_code, 400, NULL);
RunTest(expected_result, net_error, status_code, 800, NULL);
RunTest(expected_result, net_error, status_code, 1600, NULL);
RunTest(expected_result, net_error, status_code, 1600, NULL);
}
void AdvanceTime(const base::TimeDelta& delta) {
service()->advance_time_ticks_for_testing(delta);
CaptivePortalDetectorTestBase::AdvanceTime(delta);
}
bool TimerRunning() {
return service()->TimerRunning();
}
base::TimeDelta GetTimeUntilNextRequest() {
return service()->backoff_entry_->GetTimeUntilRelease();
}
void set_initial_backoff_no_portal(
base::TimeDelta initial_backoff_no_portal) {
service()->recheck_policy().initial_backoff_no_portal_ms =
initial_backoff_no_portal.InMilliseconds();
}
void set_initial_backoff_portal(base::TimeDelta initial_backoff_portal) {
service()->recheck_policy().initial_backoff_portal_ms =
initial_backoff_portal.InMilliseconds();
}
void set_maximum_backoff(base::TimeDelta maximum_backoff) {
service()->recheck_policy().backoff_policy.maximum_backoff_ms =
maximum_backoff.InMilliseconds();
}
void set_num_errors_to_ignore(int num_errors_to_ignore) {
service()->recheck_policy().backoff_policy.num_errors_to_ignore =
num_errors_to_ignore;
}
void set_multiply_factor(double multiply_factor) {
service()->recheck_policy().backoff_policy.multiply_factor =
multiply_factor;
}
void set_jitter_factor(double jitter_factor) {
service()->recheck_policy().backoff_policy.jitter_factor = jitter_factor;
}
TestingProfile* profile() { return profile_.get(); }
CaptivePortalService* service() { return service_.get(); }
private:
const CaptivePortalService::TestingState old_captive_portal_testing_state_;
content::TestBrowserThreadBundle thread_bundle_;
scoped_ptr<TestingProfile> profile_;
scoped_ptr<CaptivePortalService> service_;
};
TEST_F(CaptivePortalServiceTest, CaptivePortalTwoProfiles) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
TestingProfile profile2;
scoped_ptr<CaptivePortalService> service2(
new CaptivePortalService(&profile2));
CaptivePortalObserver observer2(&profile2, service2.get());
RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
EXPECT_EQ(0, observer2.num_results_received());
}
TEST_F(CaptivePortalServiceTest, CaptivePortalRecheckInternetConnected) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
set_initial_backoff_portal(base::TimeDelta::FromSeconds(1));
set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
RunBackoffTest(RESULT_INTERNET_CONNECTED, net::OK, 204);
RunTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 1600, NULL);
RunTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 0, NULL);
RunTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 1, NULL);
RunTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 2, NULL);
}
TEST_F(CaptivePortalServiceTest, CaptivePortalRecheckError) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
set_initial_backoff_portal(base::TimeDelta::FromDays(1));
set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
RunBackoffTest(RESULT_NO_RESPONSE, net::OK, 500);
RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 1600, NULL);
RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 100, NULL);
}
TEST_F(CaptivePortalServiceTest, CaptivePortalRecheckBehindPortal) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(250));
set_initial_backoff_portal(base::TimeDelta::FromSeconds(100));
RunBackoffTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200);
RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 1600, NULL);
RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 250, NULL);
}
TEST_F(CaptivePortalServiceTest, CaptivePortalPrefDisabled) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
set_initial_backoff_no_portal(base::TimeDelta::FromDays(1));
set_initial_backoff_portal(base::TimeDelta::FromSeconds(100));
EnableCaptivePortalDetectionPreference(false);
RunDisabledTest(0);
for (int i = 0; i < 6; ++i)
RunDisabledTest(100);
EnableCaptivePortalDetectionPreference(true);
RunTest(RESULT_BEHIND_CAPTIVE_PORTAL, net::OK, 200, 0, NULL);
}
TEST_F(CaptivePortalServiceTest, CaptivePortalPrefDisabledWhileRunning) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
CaptivePortalObserver observer(profile(), service());
service()->DetectCaptivePortal();
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(FetchingURL());
EXPECT_FALSE(TimerRunning());
EnableCaptivePortalDetectionPreference(false);
EXPECT_FALSE(FetchingURL());
EXPECT_TRUE(TimerRunning());
EXPECT_EQ(0, observer.num_results_received());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(FetchingURL());
EXPECT_FALSE(TimerRunning());
EXPECT_EQ(1, observer.num_results_received());
EXPECT_EQ(RESULT_INTERNET_CONNECTED, observer.captive_portal_result());
}
TEST_F(CaptivePortalServiceTest, CaptivePortalPrefDisabledWhilePending) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
set_initial_backoff_no_portal(base::TimeDelta::FromDays(1));
CaptivePortalObserver observer(profile(), service());
service()->DetectCaptivePortal();
EXPECT_FALSE(FetchingURL());
EXPECT_TRUE(TimerRunning());
EnableCaptivePortalDetectionPreference(false);
EXPECT_FALSE(FetchingURL());
EXPECT_TRUE(TimerRunning());
EXPECT_EQ(0, observer.num_results_received());
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(FetchingURL());
EXPECT_FALSE(TimerRunning());
EXPECT_EQ(1, observer.num_results_received());
EXPECT_EQ(RESULT_INTERNET_CONNECTED, observer.captive_portal_result());
}
TEST_F(CaptivePortalServiceTest, CaptivePortalPrefEnabledWhilePending) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
EnableCaptivePortalDetectionPreference(false);
RunDisabledTest(0);
CaptivePortalObserver observer(profile(), service());
service()->DetectCaptivePortal();
EXPECT_FALSE(FetchingURL());
EXPECT_TRUE(TimerRunning());
EnableCaptivePortalDetectionPreference(true);
EXPECT_FALSE(FetchingURL());
EXPECT_TRUE(TimerRunning());
base::RunLoop().RunUntilIdle();
ASSERT_TRUE(FetchingURL());
EXPECT_FALSE(TimerRunning());
CompleteURLFetch(net::OK, 200, NULL);
EXPECT_FALSE(FetchingURL());
EXPECT_FALSE(TimerRunning());
EXPECT_EQ(1, observer.num_results_received());
EXPECT_EQ(RESULT_BEHIND_CAPTIVE_PORTAL, observer.captive_portal_result());
}
TEST_F(CaptivePortalServiceTest, CaptivePortalDisableForTests) {
Initialize(CaptivePortalService::DISABLED_FOR_TESTING);
RunDisabledTest(0);
}
TEST_F(CaptivePortalServiceTest, CaptivePortalJitter) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
set_jitter_factor(0.3);
set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 0, NULL);
for (int i = 0; i < 50; ++i) {
int interval_sec = GetTimeUntilNextRequest().InSeconds();
EXPECT_LE(69, interval_sec);
EXPECT_LE(interval_sec, 101);
}
}
TEST_F(CaptivePortalServiceTest, CaptivePortalRetryAfterSeconds) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 101\n\n";
RunTest(RESULT_NO_RESPONSE, net::OK, 503, 0, retry_after);
RunTest(RESULT_NO_RESPONSE, net::OK, 503, 101, retry_after);
RunTest(RESULT_INTERNET_CONNECTED, net::OK, 204, 101, NULL);
EXPECT_EQ(base::TimeDelta::FromSeconds(0), GetTimeUntilNextRequest());
}
TEST_F(CaptivePortalServiceTest, CaptivePortalRetryAfterSecondsTooShort) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(100));
const char* retry_after = "HTTP/1.1 503 OK\nRetry-After: 99\n\n";
RunTest(RESULT_NO_RESPONSE, net::OK, 503, 0, retry_after);
RunTest(RESULT_NO_RESPONSE, net::OK, 503, 99, retry_after);
EXPECT_EQ(base::TimeDelta::FromSeconds(100), GetTimeUntilNextRequest());
}
TEST_F(CaptivePortalServiceTest, CaptivePortalRetryAfterDate) {
Initialize(CaptivePortalService::SKIP_OS_CHECK_FOR_TESTING);
set_initial_backoff_no_portal(base::TimeDelta::FromSeconds(50));
base::Time start_time;
ASSERT_TRUE(
base::Time::FromString("Tue, 17 Apr 2012 18:02:00 GMT", &start_time));
SetTime(start_time);
RunTest(RESULT_NO_RESPONSE,
net::OK,
503,
0,
"HTTP/1.1 503 OK\nRetry-After: Tue, 17 Apr 2012 18:02:51 GMT\n\n");
EXPECT_EQ(base::TimeDelta::FromSeconds(51), GetTimeUntilNextRequest());
}
}