blob: 828c34e59ded50a4675fd08ffe02470316302e63 [file] [log] [blame]
// Copyright 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 "chrome/renderer/net/net_error_helper.h"
#include "base/logging.h"
#include "chrome/common/net/net_error_info.h"
#include "testing/gtest/include/gtest/gtest.h"
using chrome_common_net::DnsProbeStatus;
using chrome_common_net::DnsProbeStatusToString;
// NetErrorHelperTest cases consist of a string of these steps.
enum TestStep {
// Simulate a provisional load start, fail, commit or a finish-load event.
// (Start and fail differentiate between normal and error pages.)
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START,
LOAD_COMMIT, LOAD_FINISH,
// Simulate an IPC from the browser with DNS_PROBE_STARTED, _NOT_RUN, or
// _FINISHED_NXDOMAIN.
STATUS_STARTED, STATUS_NOT_RUN, STATUS_FINISHED,
// Expect that the *next* step will cause an update. (Any step that is not
// prefixed by this pseudo-step is expected *not* to cause an update.)
EXPECT_UPDATE
};
class TestNetErrorHelper : public NetErrorHelper {
public:
TestNetErrorHelper()
: NetErrorHelper(NULL),
mock_page_update_count_(0),
mock_displayed_probe_status_(chrome_common_net::DNS_PROBE_MAX) {}
virtual ~TestNetErrorHelper() {}
void StartLoad(bool is_main_frame, bool is_error_page) {
OnStartLoad(is_main_frame, is_error_page);
}
void FailLoad(bool is_main_frame, bool is_dns_error) {
OnFailLoad(is_main_frame, is_dns_error);
}
void CommitLoad(bool is_main_frame) {
OnCommitLoad(is_main_frame);
}
void FinishLoad(bool is_main_frame) {
OnFinishLoad(is_main_frame);
}
void ReceiveProbeStatus(DnsProbeStatus status) {
OnNetErrorInfo(static_cast<int>(status));
}
int mock_page_update_count() const { return mock_page_update_count_; }
DnsProbeStatus mock_displayed_probe_status() const {
return mock_displayed_probe_status_;
}
protected:
virtual void UpdateErrorPage() OVERRIDE {
DVLOG(1) << "Updating error page with status "
<< DnsProbeStatusToString(last_probe_status_);
mock_page_update_count_++;
mock_displayed_probe_status_ = last_probe_status_;
}
private:
int mock_page_update_count_;
DnsProbeStatus mock_displayed_probe_status_;
};
class NetErrorHelperTest : public testing::Test {
protected:
enum MainFrame { SUB_FRAME, MAIN_FRAME };
enum ErrorPage { NORMAL_PAGE, ERROR_PAGE };
enum ErrorType { OTHER_ERROR, DNS_ERROR };
void StartLoad(MainFrame main_frame, ErrorPage error_page) {
helper_.StartLoad(main_frame == MAIN_FRAME, error_page == ERROR_PAGE);
}
void FailLoad(MainFrame main_frame, ErrorType error_type) {
helper_.FailLoad(main_frame == MAIN_FRAME, error_type == DNS_ERROR);
}
void CommitLoad(MainFrame main_frame) {
helper_.CommitLoad(main_frame == MAIN_FRAME);
}
void FinishLoad(MainFrame main_frame) {
helper_.FinishLoad(main_frame == MAIN_FRAME);
}
void ReceiveProbeStatus(DnsProbeStatus status) {
helper_.ReceiveProbeStatus(status);
}
void RunTest(const TestStep steps[], int step_count);
int page_update_count() const { return helper_.mock_page_update_count(); }
DnsProbeStatus displayed_probe_status() const {
return helper_.mock_displayed_probe_status();
}
private:
TestNetErrorHelper helper_;
};
void NetErrorHelperTest::RunTest(const TestStep steps[], int step_count) {
// Whether the next instruction is expected to cause an update (since the
// step right before it was EXPECT_UPDATE) or not.
bool update_expected = false;
int expected_update_count = page_update_count();
// The last status that the test simulated receiving from the browser.
// When an update is expected, the status is expected to match this.
chrome_common_net::DnsProbeStatus last_status_received =
chrome_common_net::DNS_PROBE_POSSIBLE;
for (int i = 0; i < step_count; i++) {
switch (steps[i]) {
case LOAD_NORMAL_START:
StartLoad(MAIN_FRAME, NORMAL_PAGE);
break;
case LOAD_NORMAL_FAIL:
FailLoad(MAIN_FRAME, DNS_ERROR);
break;
case LOAD_ERROR_START:
StartLoad(MAIN_FRAME, ERROR_PAGE);
break;
case LOAD_COMMIT:
CommitLoad(MAIN_FRAME);
break;
case LOAD_FINISH:
FinishLoad(MAIN_FRAME);
break;
case STATUS_STARTED:
ReceiveProbeStatus(chrome_common_net::DNS_PROBE_STARTED);
last_status_received = chrome_common_net::DNS_PROBE_STARTED;
break;
case STATUS_NOT_RUN:
ReceiveProbeStatus(chrome_common_net::DNS_PROBE_NOT_RUN);
last_status_received = chrome_common_net::DNS_PROBE_NOT_RUN;
break;
case STATUS_FINISHED:
ReceiveProbeStatus(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
last_status_received = chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN;
break;
case EXPECT_UPDATE:
ASSERT_FALSE(update_expected);
update_expected = true;
// Skip to next step to see if it updates the status, instead of
// checking whether EXPECT_UPDATE itself caused an update.
continue;
}
if (update_expected) {
DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, last_status_received);
++expected_update_count;
EXPECT_EQ(last_status_received, displayed_probe_status());
if (displayed_probe_status() != last_status_received) {
LOG(ERROR) << "Unexpected status at step " << i << ".";
return;
}
}
EXPECT_EQ(expected_update_count, page_update_count());
if (page_update_count() != expected_update_count) {
LOG(ERROR) << (update_expected ? "Missing" : "Spurious")
<< " update at step " << i << ".";
return;
}
update_expected = false;
}
DCHECK(!update_expected);
}
TEST_F(NetErrorHelperTest, Null) {
// Test that we can simply create and destroy a NetErrorHelper.
}
TEST_F(NetErrorHelperTest, SuccessfulPageLoad) {
StartLoad(MAIN_FRAME, NORMAL_PAGE);
CommitLoad(MAIN_FRAME);
FinishLoad(MAIN_FRAME);
// Ignore spurious status.
ReceiveProbeStatus(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
EXPECT_EQ(0, page_update_count());
}
TEST_F(NetErrorHelperTest, MainFrameNonDnsError) {
StartLoad(MAIN_FRAME, NORMAL_PAGE);
FailLoad(MAIN_FRAME, OTHER_ERROR);
StartLoad(MAIN_FRAME, ERROR_PAGE);
CommitLoad(MAIN_FRAME);
FinishLoad(MAIN_FRAME);
// Ignore spurious status.
ReceiveProbeStatus(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
EXPECT_EQ(0, page_update_count());
}
TEST_F(NetErrorHelperTest, SubFrameDnsError) {
StartLoad(SUB_FRAME, NORMAL_PAGE);
FailLoad(SUB_FRAME, DNS_ERROR);
StartLoad(SUB_FRAME, ERROR_PAGE);
CommitLoad(SUB_FRAME);
FinishLoad(SUB_FRAME);
// Ignore spurious status.
ReceiveProbeStatus(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
EXPECT_EQ(0, page_update_count());
}
TEST_F(NetErrorHelperTest, FinishedAfterFail) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_FINISHED, LOAD_ERROR_START,
LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterFail_StartedAfterFail) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, STATUS_FINISHED,
LOAD_ERROR_START, LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterStart) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, STATUS_FINISHED,
LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterStart_StartedAfterFail) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
STATUS_FINISHED, LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterStart_StartedAfterStart) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
STATUS_FINISHED, LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterCommit) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
STATUS_FINISHED, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterCommit_StartedAfterFail) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
LOAD_COMMIT, STATUS_FINISHED, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterCommit_StartedAfterStart) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, STATUS_STARTED,
LOAD_ERROR_START, LOAD_COMMIT, STATUS_FINISHED, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterCommit_StartedAfterCommit) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
STATUS_STARTED, STATUS_FINISHED, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterFinish) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterFinish_StartAfterFail) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterFinish_StartAfterStart) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, STATUS_STARTED,
LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterFinish_StartAfterCommit) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
STATUS_STARTED, EXPECT_UPDATE, LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterFinish_StartAfterFinish) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
LOAD_FINISH, EXPECT_UPDATE, STATUS_STARTED, EXPECT_UPDATE, STATUS_FINISHED
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterNewStart) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
LOAD_FINISH, LOAD_NORMAL_START, EXPECT_UPDATE, STATUS_FINISHED,
LOAD_COMMIT, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, NotRunAfterFail) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_NOT_RUN, LOAD_ERROR_START,
LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, NotRunAfterStart) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, STATUS_NOT_RUN,
LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, NotRunAfterCommit) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
STATUS_NOT_RUN, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, NotRunAfterFinish) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
LOAD_FINISH, EXPECT_UPDATE, STATUS_NOT_RUN
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterNewCommit) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
LOAD_FINISH, LOAD_NORMAL_START, LOAD_COMMIT, STATUS_FINISHED, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
TEST_F(NetErrorHelperTest, FinishedAfterNewFinish) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
LOAD_FINISH, LOAD_NORMAL_START, LOAD_COMMIT, LOAD_FINISH, STATUS_FINISHED
};
RunTest(steps, arraysize(steps));
}
// Two iterations of FinishedAfterStart_StartAfterFail
TEST_F(NetErrorHelperTest, TwoProbes_FinishedAfterStart_StartAfterFail) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
STATUS_FINISHED, LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH,
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
STATUS_FINISHED, LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
};
RunTest(steps, arraysize(steps));
}
// Two iterations of FinishedAfterFinish
TEST_F(NetErrorHelperTest, TwoProbes_FinishedAfterFinish) {
const TestStep steps[] = {
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED,
LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED
};
RunTest(steps, arraysize(steps));
}