blob: e7d716475193d88ac7f52dcfce371e1047098980 [file] [log] [blame]
Matt Menke977e61b2019-01-10 19:36:021// Copyright 2018 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/socket/connect_job.h"
6
Sebastien Marchand6d0558fd2019-01-25 16:49:377#include "base/bind.h"
Matt Menke977e61b2019-01-10 19:36:028#include "base/callback.h"
9#include "base/logging.h"
10#include "base/macros.h"
11#include "base/run_loop.h"
12#include "base/test/scoped_task_environment.h"
13#include "net/base/address_list.h"
14#include "net/base/net_errors.h"
15#include "net/base/request_priority.h"
16#include "net/log/test_net_log.h"
17#include "net/log/test_net_log_util.h"
Matt Menke3abc57c2019-01-10 21:48:4218#include "net/socket/connect_job_test_util.h"
Matt Menke977e61b2019-01-10 19:36:0219#include "net/socket/socket_tag.h"
20#include "net/socket/socket_test_util.h"
21#include "net/test/gtest_util.h"
22#include "testing/gtest/include/gtest/gtest.h"
23
24namespace net {
25namespace {
26
Matt Menke977e61b2019-01-10 19:36:0227class TestConnectJob : public ConnectJob {
28 public:
29 enum class JobType {
30 kSyncSuccess,
31 kAsyncSuccess,
32 kHung,
33 };
34
35 TestConnectJob(JobType job_type,
36 base::TimeDelta timeout_duration,
Matt Menkea6f99ad2019-03-08 02:26:4337 const CommonConnectJobParams* common_connect_job_params,
38 ConnectJob::Delegate* delegate)
Matt Menke1a6c92d2019-02-23 00:25:3839 : ConnectJob(DEFAULT_PRIORITY,
Matt Menkea6f99ad2019-03-08 02:26:4340 SocketTag(),
Matt Menke1a6c92d2019-02-23 00:25:3841 timeout_duration,
Matt Menkea6f99ad2019-03-08 02:26:4342 common_connect_job_params,
Matt Menke1a6c92d2019-02-23 00:25:3843 delegate,
44 nullptr /* net_log */,
45 NetLogSourceType::TRANSPORT_CONNECT_JOB,
46 NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT),
Matt Menke977e61b2019-01-10 19:36:0247 job_type_(job_type),
48 last_seen_priority_(DEFAULT_PRIORITY) {
49 switch (job_type_) {
50 case JobType::kSyncSuccess:
51 socket_data_provider_.set_connect_data(MockConnect(SYNCHRONOUS, OK));
52 return;
53 case JobType::kAsyncSuccess:
54 socket_data_provider_.set_connect_data(MockConnect(ASYNC, OK));
55 return;
56 case JobType::kHung:
57 socket_data_provider_.set_connect_data(
58 MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
59 return;
60 }
61 }
62
63 // From ConnectJob:
64 LoadState GetLoadState() const override { return LOAD_STATE_IDLE; }
Matt Menke141b87f22019-01-30 02:43:0365 bool HasEstablishedConnection() const override { return false; }
Matt Menke977e61b2019-01-10 19:36:0266 int ConnectInternal() override {
67 SetSocket(std::unique_ptr<StreamSocket>(new MockTCPClientSocket(
68 AddressList(), net_log().net_log(), &socket_data_provider_)));
69 return socket()->Connect(base::BindOnce(
70 &TestConnectJob::NotifyDelegateOfCompletion, base::Unretained(this)));
71 }
72 void ChangePriorityInternal(RequestPriority priority) override {
73 last_seen_priority_ = priority;
74 }
75
76 using ConnectJob::ResetTimer;
77
78 // The priority seen during the most recent call to ChangePriorityInternal().
79 RequestPriority last_seen_priority() const { return last_seen_priority_; }
80
Matt Menkea6f99ad2019-03-08 02:26:4381 protected:
Matt Menke977e61b2019-01-10 19:36:0282 const JobType job_type_;
83 StaticSocketDataProvider socket_data_provider_;
84 RequestPriority last_seen_priority_;
85
86 DISALLOW_COPY_AND_ASSIGN(TestConnectJob);
87};
88
89class ConnectJobTest : public testing::Test {
90 public:
91 ConnectJobTest()
92 : scoped_task_environment_(
Matt Menkea6f99ad2019-03-08 02:26:4393 base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME),
94 common_connect_job_params_(
95 nullptr /* client_socket_factory */,
96 nullptr /* host_resolver */,
Matt Menkeb88837e2019-03-20 11:50:4097 nullptr /* http_auth_cache */,
98 nullptr /* http_auth_handler_factory */,
99 nullptr /* spdy_session_pool */,
100 nullptr /* quic_stream_factory */,
Matt Menkea6f99ad2019-03-08 02:26:43101 nullptr /* proxy_delegate */,
Matt Menked732ea42019-03-08 12:05:00102 nullptr /* http_user_agent_settings */,
Matt Menkea6f99ad2019-03-08 02:26:43103 SSLClientSocketContext(),
104 SSLClientSocketContext(),
105 nullptr /* socket_performance_watcher_factory */,
106 nullptr /* network_quality_estimator */,
107 &net_log_,
108 nullptr /* websocket_endpoint_lock_manager */) {}
Matt Menke977e61b2019-01-10 19:36:02109 ~ConnectJobTest() override = default;
110
111 protected:
112 base::test::ScopedTaskEnvironment scoped_task_environment_;
Matt Menkea6f99ad2019-03-08 02:26:43113 TestNetLog net_log_;
114 const CommonConnectJobParams common_connect_job_params_;
Matt Menke977e61b2019-01-10 19:36:02115 TestConnectJobDelegate delegate_;
116};
117
118// Even though a timeout is specified, it doesn't time out on a synchronous
119// completion.
120TEST_F(ConnectJobTest, NoTimeoutOnSyncCompletion) {
121 TestConnectJob job(TestConnectJob::JobType::kSyncSuccess,
Matt Menkea6f99ad2019-03-08 02:26:43122 base::TimeDelta::FromMicroseconds(1),
123 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02124 EXPECT_THAT(job.Connect(), test::IsOk());
125}
126
127// Even though a timeout is specified, it doesn't time out on an asynchronous
128// completion.
129TEST_F(ConnectJobTest, NoTimeoutOnAsyncCompletion) {
130 TestConnectJob job(TestConnectJob::JobType::kAsyncSuccess,
Matt Menkea6f99ad2019-03-08 02:26:43131 base::TimeDelta::FromMinutes(1),
132 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02133 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
134 EXPECT_THAT(delegate_.WaitForResult(), test::IsOk());
135}
136
137// Job shouldn't timeout when passed a TimeDelta of zero.
138TEST_F(ConnectJobTest, NoTimeoutWithNoTimeDelta) {
139 TestConnectJob job(TestConnectJob::JobType::kHung, base::TimeDelta(),
Matt Menkea6f99ad2019-03-08 02:26:43140 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02141 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
142 scoped_task_environment_.RunUntilIdle();
143 EXPECT_FALSE(delegate_.has_result());
144}
145
146// Make sure that ChangePriority() works, and new priority is visible to
147// subclasses during the SetPriorityInternal call.
148TEST_F(ConnectJobTest, SetPriority) {
149 TestConnectJob job(TestConnectJob::JobType::kAsyncSuccess,
Matt Menkea6f99ad2019-03-08 02:26:43150 base::TimeDelta::FromMicroseconds(1),
151 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02152 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
153
154 job.ChangePriority(HIGHEST);
155 EXPECT_EQ(HIGHEST, job.priority());
156 EXPECT_EQ(HIGHEST, job.last_seen_priority());
157
158 job.ChangePriority(MEDIUM);
159 EXPECT_EQ(MEDIUM, job.priority());
160 EXPECT_EQ(MEDIUM, job.last_seen_priority());
161
162 EXPECT_THAT(delegate_.WaitForResult(), test::IsOk());
163}
164
165TEST_F(ConnectJobTest, TimedOut) {
166 const base::TimeDelta kTimeout = base::TimeDelta::FromHours(1);
Matt Menke977e61b2019-01-10 19:36:02167
Matt Menkea6f99ad2019-03-08 02:26:43168 std::unique_ptr<TestConnectJob> job =
169 std::make_unique<TestConnectJob>(TestConnectJob::JobType::kHung, kTimeout,
170 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02171 ASSERT_THAT(job->Connect(), test::IsError(ERR_IO_PENDING));
172
173 // Nothing should happen before the specified time.
174 scoped_task_environment_.FastForwardBy(kTimeout -
175 base::TimeDelta::FromMilliseconds(1));
176 base::RunLoop().RunUntilIdle();
177 EXPECT_FALSE(delegate_.has_result());
178
179 // At which point the job should time out.
180 scoped_task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
181 EXPECT_THAT(delegate_.WaitForResult(), test::IsError(ERR_TIMED_OUT));
182
183 // Have to delete the job for it to log the end event.
184 job.reset();
185
186 TestNetLogEntry::List entries;
Matt Menkea6f99ad2019-03-08 02:26:43187 net_log_.GetEntries(&entries);
Matt Menke977e61b2019-01-10 19:36:02188
189 EXPECT_EQ(6u, entries.size());
Matt Menke1a6c92d2019-02-23 00:25:38190 EXPECT_TRUE(LogContainsBeginEvent(entries, 0, NetLogEventType::CONNECT_JOB));
Matt Menke977e61b2019-01-10 19:36:02191 EXPECT_TRUE(LogContainsBeginEvent(
Matt Menke1a6c92d2019-02-23 00:25:38192 entries, 1, NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT));
Matt Menke977e61b2019-01-10 19:36:02193 EXPECT_TRUE(LogContainsEvent(entries, 2,
194 NetLogEventType::CONNECT_JOB_SET_SOCKET,
195 NetLogEventPhase::NONE));
Matt Menke1a6c92d2019-02-23 00:25:38196 EXPECT_TRUE(LogContainsEvent(entries, 3,
197 NetLogEventType::CONNECT_JOB_TIMED_OUT,
198 NetLogEventPhase::NONE));
Matt Menke977e61b2019-01-10 19:36:02199 EXPECT_TRUE(LogContainsEndEvent(
Matt Menke1a6c92d2019-02-23 00:25:38200 entries, 4, NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT));
201 EXPECT_TRUE(LogContainsEndEvent(entries, 5, NetLogEventType::CONNECT_JOB));
Matt Menke977e61b2019-01-10 19:36:02202}
203
204TEST_F(ConnectJobTest, TimedOutWithRestartedTimer) {
205 const base::TimeDelta kTimeout = base::TimeDelta::FromHours(1);
206
Matt Menkea6f99ad2019-03-08 02:26:43207 TestConnectJob job(TestConnectJob::JobType::kHung, kTimeout,
208 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02209 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
210
211 // Nothing should happen before the specified time.
212 scoped_task_environment_.FastForwardBy(kTimeout -
213 base::TimeDelta::FromMilliseconds(1));
214 base::RunLoop().RunUntilIdle();
215 EXPECT_FALSE(delegate_.has_result());
216
217 // Make sure restarting the timer is respected.
218 job.ResetTimer(kTimeout);
219 scoped_task_environment_.FastForwardBy(kTimeout -
220 base::TimeDelta::FromMilliseconds(1));
221 base::RunLoop().RunUntilIdle();
222 EXPECT_FALSE(delegate_.has_result());
223
224 scoped_task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
225 EXPECT_THAT(delegate_.WaitForResult(), test::IsError(ERR_TIMED_OUT));
226}
227
228} // namespace
229} // namespace net