1*6777b538SAndroid Build Coastguard Worker // Copyright 2018 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "net/socket/connect_job.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
8*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
9*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
10*6777b538SAndroid Build Coastguard Worker #include "base/test/task_environment.h"
11*6777b538SAndroid Build Coastguard Worker #include "net/base/address_list.h"
12*6777b538SAndroid Build Coastguard Worker #include "net/base/net_errors.h"
13*6777b538SAndroid Build Coastguard Worker #include "net/base/request_priority.h"
14*6777b538SAndroid Build Coastguard Worker #include "net/dns/public/resolve_error_info.h"
15*6777b538SAndroid Build Coastguard Worker #include "net/log/test_net_log.h"
16*6777b538SAndroid Build Coastguard Worker #include "net/log/test_net_log_util.h"
17*6777b538SAndroid Build Coastguard Worker #include "net/socket/connect_job_test_util.h"
18*6777b538SAndroid Build Coastguard Worker #include "net/socket/socket_tag.h"
19*6777b538SAndroid Build Coastguard Worker #include "net/socket/socket_test_util.h"
20*6777b538SAndroid Build Coastguard Worker #include "net/test/gtest_util.h"
21*6777b538SAndroid Build Coastguard Worker #include "testing/gtest/include/gtest/gtest.h"
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker namespace net {
24*6777b538SAndroid Build Coastguard Worker namespace {
25*6777b538SAndroid Build Coastguard Worker
26*6777b538SAndroid Build Coastguard Worker class TestConnectJob : public ConnectJob {
27*6777b538SAndroid Build Coastguard Worker public:
28*6777b538SAndroid Build Coastguard Worker enum class JobType {
29*6777b538SAndroid Build Coastguard Worker kSyncSuccess,
30*6777b538SAndroid Build Coastguard Worker kAsyncSuccess,
31*6777b538SAndroid Build Coastguard Worker kHung,
32*6777b538SAndroid Build Coastguard Worker };
33*6777b538SAndroid Build Coastguard Worker
TestConnectJob(JobType job_type,base::TimeDelta timeout_duration,const CommonConnectJobParams * common_connect_job_params,ConnectJob::Delegate * delegate)34*6777b538SAndroid Build Coastguard Worker TestConnectJob(JobType job_type,
35*6777b538SAndroid Build Coastguard Worker base::TimeDelta timeout_duration,
36*6777b538SAndroid Build Coastguard Worker const CommonConnectJobParams* common_connect_job_params,
37*6777b538SAndroid Build Coastguard Worker ConnectJob::Delegate* delegate)
38*6777b538SAndroid Build Coastguard Worker : ConnectJob(DEFAULT_PRIORITY,
39*6777b538SAndroid Build Coastguard Worker SocketTag(),
40*6777b538SAndroid Build Coastguard Worker timeout_duration,
41*6777b538SAndroid Build Coastguard Worker common_connect_job_params,
42*6777b538SAndroid Build Coastguard Worker delegate,
43*6777b538SAndroid Build Coastguard Worker nullptr /* net_log */,
44*6777b538SAndroid Build Coastguard Worker NetLogSourceType::TRANSPORT_CONNECT_JOB,
45*6777b538SAndroid Build Coastguard Worker NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT),
46*6777b538SAndroid Build Coastguard Worker job_type_(job_type) {
47*6777b538SAndroid Build Coastguard Worker switch (job_type_) {
48*6777b538SAndroid Build Coastguard Worker case JobType::kSyncSuccess:
49*6777b538SAndroid Build Coastguard Worker socket_data_provider_.set_connect_data(MockConnect(SYNCHRONOUS, OK));
50*6777b538SAndroid Build Coastguard Worker return;
51*6777b538SAndroid Build Coastguard Worker case JobType::kAsyncSuccess:
52*6777b538SAndroid Build Coastguard Worker socket_data_provider_.set_connect_data(MockConnect(ASYNC, OK));
53*6777b538SAndroid Build Coastguard Worker return;
54*6777b538SAndroid Build Coastguard Worker case JobType::kHung:
55*6777b538SAndroid Build Coastguard Worker socket_data_provider_.set_connect_data(
56*6777b538SAndroid Build Coastguard Worker MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
57*6777b538SAndroid Build Coastguard Worker return;
58*6777b538SAndroid Build Coastguard Worker }
59*6777b538SAndroid Build Coastguard Worker }
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker TestConnectJob(const TestConnectJob&) = delete;
62*6777b538SAndroid Build Coastguard Worker TestConnectJob& operator=(const TestConnectJob&) = delete;
63*6777b538SAndroid Build Coastguard Worker
64*6777b538SAndroid Build Coastguard Worker // From ConnectJob:
GetLoadState() const65*6777b538SAndroid Build Coastguard Worker LoadState GetLoadState() const override { return LOAD_STATE_IDLE; }
HasEstablishedConnection() const66*6777b538SAndroid Build Coastguard Worker bool HasEstablishedConnection() const override { return false; }
GetResolveErrorInfo() const67*6777b538SAndroid Build Coastguard Worker ResolveErrorInfo GetResolveErrorInfo() const override {
68*6777b538SAndroid Build Coastguard Worker return ResolveErrorInfo(net::OK);
69*6777b538SAndroid Build Coastguard Worker }
ConnectInternal()70*6777b538SAndroid Build Coastguard Worker int ConnectInternal() override {
71*6777b538SAndroid Build Coastguard Worker SetSocket(std::make_unique<MockTCPClientSocket>(
72*6777b538SAndroid Build Coastguard Worker AddressList(), net_log().net_log(), &socket_data_provider_),
73*6777b538SAndroid Build Coastguard Worker std::nullopt /* dns_aliases */);
74*6777b538SAndroid Build Coastguard Worker return socket()->Connect(base::BindOnce(
75*6777b538SAndroid Build Coastguard Worker &TestConnectJob::NotifyDelegateOfCompletion, base::Unretained(this)));
76*6777b538SAndroid Build Coastguard Worker }
ChangePriorityInternal(RequestPriority priority)77*6777b538SAndroid Build Coastguard Worker void ChangePriorityInternal(RequestPriority priority) override {
78*6777b538SAndroid Build Coastguard Worker last_seen_priority_ = priority;
79*6777b538SAndroid Build Coastguard Worker }
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker using ConnectJob::ResetTimer;
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Worker // The priority seen during the most recent call to ChangePriorityInternal().
last_seen_priority() const84*6777b538SAndroid Build Coastguard Worker RequestPriority last_seen_priority() const { return last_seen_priority_; }
85*6777b538SAndroid Build Coastguard Worker
86*6777b538SAndroid Build Coastguard Worker protected:
87*6777b538SAndroid Build Coastguard Worker const JobType job_type_;
88*6777b538SAndroid Build Coastguard Worker StaticSocketDataProvider socket_data_provider_;
89*6777b538SAndroid Build Coastguard Worker RequestPriority last_seen_priority_ = DEFAULT_PRIORITY;
90*6777b538SAndroid Build Coastguard Worker };
91*6777b538SAndroid Build Coastguard Worker
92*6777b538SAndroid Build Coastguard Worker class ConnectJobTest : public testing::Test {
93*6777b538SAndroid Build Coastguard Worker public:
ConnectJobTest()94*6777b538SAndroid Build Coastguard Worker ConnectJobTest()
95*6777b538SAndroid Build Coastguard Worker : task_environment_(base::test::TaskEnvironment::TimeSource::MOCK_TIME),
96*6777b538SAndroid Build Coastguard Worker common_connect_job_params_(
97*6777b538SAndroid Build Coastguard Worker /*client_socket_factory=*/nullptr,
98*6777b538SAndroid Build Coastguard Worker /*host_resolver=*/nullptr,
99*6777b538SAndroid Build Coastguard Worker /*http_auth_cache=*/nullptr,
100*6777b538SAndroid Build Coastguard Worker /*http_auth_handler_factory=*/nullptr,
101*6777b538SAndroid Build Coastguard Worker /*spdy_session_pool=*/nullptr,
102*6777b538SAndroid Build Coastguard Worker /*quic_supported_versions=*/nullptr,
103*6777b538SAndroid Build Coastguard Worker /*quic_session_pool=*/nullptr,
104*6777b538SAndroid Build Coastguard Worker /*proxy_delegate=*/nullptr,
105*6777b538SAndroid Build Coastguard Worker /*http_user_agent_settings=*/nullptr,
106*6777b538SAndroid Build Coastguard Worker /*ssl_client_context=*/nullptr,
107*6777b538SAndroid Build Coastguard Worker /*socket_performance_watcher_factory=*/nullptr,
108*6777b538SAndroid Build Coastguard Worker /*network_quality_estimator=*/nullptr,
109*6777b538SAndroid Build Coastguard Worker NetLog::Get(),
110*6777b538SAndroid Build Coastguard Worker /*websocket_endpoint_lock_manager=*/nullptr,
111*6777b538SAndroid Build Coastguard Worker /*http_server_properties*/ nullptr,
112*6777b538SAndroid Build Coastguard Worker /*alpn_protos=*/nullptr,
113*6777b538SAndroid Build Coastguard Worker /*application_settings=*/nullptr,
114*6777b538SAndroid Build Coastguard Worker /*ignore_certificate_errors=*/nullptr,
115*6777b538SAndroid Build Coastguard Worker /*early_data_enabled=*/nullptr) {}
116*6777b538SAndroid Build Coastguard Worker ~ConnectJobTest() override = default;
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker protected:
119*6777b538SAndroid Build Coastguard Worker base::test::TaskEnvironment task_environment_;
120*6777b538SAndroid Build Coastguard Worker RecordingNetLogObserver net_log_observer_;
121*6777b538SAndroid Build Coastguard Worker const CommonConnectJobParams common_connect_job_params_;
122*6777b538SAndroid Build Coastguard Worker TestConnectJobDelegate delegate_;
123*6777b538SAndroid Build Coastguard Worker };
124*6777b538SAndroid Build Coastguard Worker
125*6777b538SAndroid Build Coastguard Worker // Even though a timeout is specified, it doesn't time out on a synchronous
126*6777b538SAndroid Build Coastguard Worker // completion.
TEST_F(ConnectJobTest,NoTimeoutOnSyncCompletion)127*6777b538SAndroid Build Coastguard Worker TEST_F(ConnectJobTest, NoTimeoutOnSyncCompletion) {
128*6777b538SAndroid Build Coastguard Worker TestConnectJob job(TestConnectJob::JobType::kSyncSuccess,
129*6777b538SAndroid Build Coastguard Worker base::Microseconds(1), &common_connect_job_params_,
130*6777b538SAndroid Build Coastguard Worker &delegate_);
131*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(job.Connect(), test::IsOk());
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker // Even though a timeout is specified, it doesn't time out on an asynchronous
135*6777b538SAndroid Build Coastguard Worker // completion.
TEST_F(ConnectJobTest,NoTimeoutOnAsyncCompletion)136*6777b538SAndroid Build Coastguard Worker TEST_F(ConnectJobTest, NoTimeoutOnAsyncCompletion) {
137*6777b538SAndroid Build Coastguard Worker TestConnectJob job(TestConnectJob::JobType::kAsyncSuccess, base::Minutes(1),
138*6777b538SAndroid Build Coastguard Worker &common_connect_job_params_, &delegate_);
139*6777b538SAndroid Build Coastguard Worker ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
140*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(delegate_.WaitForResult(), test::IsOk());
141*6777b538SAndroid Build Coastguard Worker }
142*6777b538SAndroid Build Coastguard Worker
143*6777b538SAndroid Build Coastguard Worker // Job shouldn't timeout when passed a TimeDelta of zero.
TEST_F(ConnectJobTest,NoTimeoutWithNoTimeDelta)144*6777b538SAndroid Build Coastguard Worker TEST_F(ConnectJobTest, NoTimeoutWithNoTimeDelta) {
145*6777b538SAndroid Build Coastguard Worker TestConnectJob job(TestConnectJob::JobType::kHung, base::TimeDelta(),
146*6777b538SAndroid Build Coastguard Worker &common_connect_job_params_, &delegate_);
147*6777b538SAndroid Build Coastguard Worker ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
148*6777b538SAndroid Build Coastguard Worker task_environment_.RunUntilIdle();
149*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(delegate_.has_result());
150*6777b538SAndroid Build Coastguard Worker }
151*6777b538SAndroid Build Coastguard Worker
152*6777b538SAndroid Build Coastguard Worker // Make sure that ChangePriority() works, and new priority is visible to
153*6777b538SAndroid Build Coastguard Worker // subclasses during the SetPriorityInternal call.
TEST_F(ConnectJobTest,SetPriority)154*6777b538SAndroid Build Coastguard Worker TEST_F(ConnectJobTest, SetPriority) {
155*6777b538SAndroid Build Coastguard Worker TestConnectJob job(TestConnectJob::JobType::kAsyncSuccess,
156*6777b538SAndroid Build Coastguard Worker base::Microseconds(1), &common_connect_job_params_,
157*6777b538SAndroid Build Coastguard Worker &delegate_);
158*6777b538SAndroid Build Coastguard Worker ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
159*6777b538SAndroid Build Coastguard Worker
160*6777b538SAndroid Build Coastguard Worker job.ChangePriority(HIGHEST);
161*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HIGHEST, job.priority());
162*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(HIGHEST, job.last_seen_priority());
163*6777b538SAndroid Build Coastguard Worker
164*6777b538SAndroid Build Coastguard Worker job.ChangePriority(MEDIUM);
165*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(MEDIUM, job.priority());
166*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(MEDIUM, job.last_seen_priority());
167*6777b538SAndroid Build Coastguard Worker
168*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(delegate_.WaitForResult(), test::IsOk());
169*6777b538SAndroid Build Coastguard Worker }
170*6777b538SAndroid Build Coastguard Worker
TEST_F(ConnectJobTest,TimedOut)171*6777b538SAndroid Build Coastguard Worker TEST_F(ConnectJobTest, TimedOut) {
172*6777b538SAndroid Build Coastguard Worker const base::TimeDelta kTimeout = base::Hours(1);
173*6777b538SAndroid Build Coastguard Worker
174*6777b538SAndroid Build Coastguard Worker std::unique_ptr<TestConnectJob> job =
175*6777b538SAndroid Build Coastguard Worker std::make_unique<TestConnectJob>(TestConnectJob::JobType::kHung, kTimeout,
176*6777b538SAndroid Build Coastguard Worker &common_connect_job_params_, &delegate_);
177*6777b538SAndroid Build Coastguard Worker ASSERT_THAT(job->Connect(), test::IsError(ERR_IO_PENDING));
178*6777b538SAndroid Build Coastguard Worker
179*6777b538SAndroid Build Coastguard Worker // Nothing should happen before the specified time.
180*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kTimeout - base::Milliseconds(1));
181*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
182*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(delegate_.has_result());
183*6777b538SAndroid Build Coastguard Worker
184*6777b538SAndroid Build Coastguard Worker // At which point the job should time out.
185*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(base::Milliseconds(1));
186*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(delegate_.WaitForResult(), test::IsError(ERR_TIMED_OUT));
187*6777b538SAndroid Build Coastguard Worker
188*6777b538SAndroid Build Coastguard Worker // Have to delete the job for it to log the end event.
189*6777b538SAndroid Build Coastguard Worker job.reset();
190*6777b538SAndroid Build Coastguard Worker
191*6777b538SAndroid Build Coastguard Worker auto entries = net_log_observer_.GetEntries();
192*6777b538SAndroid Build Coastguard Worker
193*6777b538SAndroid Build Coastguard Worker EXPECT_EQ(6u, entries.size());
194*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(LogContainsBeginEvent(entries, 0, NetLogEventType::CONNECT_JOB));
195*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(LogContainsBeginEvent(
196*6777b538SAndroid Build Coastguard Worker entries, 1, NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT));
197*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(LogContainsEvent(entries, 2,
198*6777b538SAndroid Build Coastguard Worker NetLogEventType::CONNECT_JOB_SET_SOCKET,
199*6777b538SAndroid Build Coastguard Worker NetLogEventPhase::NONE));
200*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(LogContainsEvent(entries, 3,
201*6777b538SAndroid Build Coastguard Worker NetLogEventType::CONNECT_JOB_TIMED_OUT,
202*6777b538SAndroid Build Coastguard Worker NetLogEventPhase::NONE));
203*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(LogContainsEndEvent(
204*6777b538SAndroid Build Coastguard Worker entries, 4, NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT));
205*6777b538SAndroid Build Coastguard Worker EXPECT_TRUE(LogContainsEndEvent(entries, 5, NetLogEventType::CONNECT_JOB));
206*6777b538SAndroid Build Coastguard Worker }
207*6777b538SAndroid Build Coastguard Worker
TEST_F(ConnectJobTest,TimedOutWithRestartedTimer)208*6777b538SAndroid Build Coastguard Worker TEST_F(ConnectJobTest, TimedOutWithRestartedTimer) {
209*6777b538SAndroid Build Coastguard Worker const base::TimeDelta kTimeout = base::Hours(1);
210*6777b538SAndroid Build Coastguard Worker
211*6777b538SAndroid Build Coastguard Worker TestConnectJob job(TestConnectJob::JobType::kHung, kTimeout,
212*6777b538SAndroid Build Coastguard Worker &common_connect_job_params_, &delegate_);
213*6777b538SAndroid Build Coastguard Worker ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
214*6777b538SAndroid Build Coastguard Worker
215*6777b538SAndroid Build Coastguard Worker // Nothing should happen before the specified time.
216*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kTimeout - base::Milliseconds(1));
217*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
218*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(delegate_.has_result());
219*6777b538SAndroid Build Coastguard Worker
220*6777b538SAndroid Build Coastguard Worker // Make sure restarting the timer is respected.
221*6777b538SAndroid Build Coastguard Worker job.ResetTimer(kTimeout);
222*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(kTimeout - base::Milliseconds(1));
223*6777b538SAndroid Build Coastguard Worker base::RunLoop().RunUntilIdle();
224*6777b538SAndroid Build Coastguard Worker EXPECT_FALSE(delegate_.has_result());
225*6777b538SAndroid Build Coastguard Worker
226*6777b538SAndroid Build Coastguard Worker task_environment_.FastForwardBy(base::Milliseconds(1));
227*6777b538SAndroid Build Coastguard Worker EXPECT_THAT(delegate_.WaitForResult(), test::IsError(ERR_TIMED_OUT));
228*6777b538SAndroid Build Coastguard Worker }
229*6777b538SAndroid Build Coastguard Worker
230*6777b538SAndroid Build Coastguard Worker } // namespace
231*6777b538SAndroid Build Coastguard Worker } // namespace net
232