blob: cfd1c5882cfe9bae5f0ec7d4e289b8bce18d9e8f [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 */,
97 nullptr /* proxy_delegate */,
Matt Menked732ea42019-03-08 12:05:0098 nullptr /* http_user_agent_settings */,
Matt Menkea6f99ad2019-03-08 02:26:4399 SSLClientSocketContext(),
100 SSLClientSocketContext(),
101 nullptr /* socket_performance_watcher_factory */,
102 nullptr /* network_quality_estimator */,
103 &net_log_,
104 nullptr /* websocket_endpoint_lock_manager */) {}
Matt Menke977e61b2019-01-10 19:36:02105 ~ConnectJobTest() override = default;
106
107 protected:
108 base::test::ScopedTaskEnvironment scoped_task_environment_;
Matt Menkea6f99ad2019-03-08 02:26:43109 TestNetLog net_log_;
110 const CommonConnectJobParams common_connect_job_params_;
Matt Menke977e61b2019-01-10 19:36:02111 TestConnectJobDelegate delegate_;
112};
113
114// Even though a timeout is specified, it doesn't time out on a synchronous
115// completion.
116TEST_F(ConnectJobTest, NoTimeoutOnSyncCompletion) {
117 TestConnectJob job(TestConnectJob::JobType::kSyncSuccess,
Matt Menkea6f99ad2019-03-08 02:26:43118 base::TimeDelta::FromMicroseconds(1),
119 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02120 EXPECT_THAT(job.Connect(), test::IsOk());
121}
122
123// Even though a timeout is specified, it doesn't time out on an asynchronous
124// completion.
125TEST_F(ConnectJobTest, NoTimeoutOnAsyncCompletion) {
126 TestConnectJob job(TestConnectJob::JobType::kAsyncSuccess,
Matt Menkea6f99ad2019-03-08 02:26:43127 base::TimeDelta::FromMinutes(1),
128 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02129 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
130 EXPECT_THAT(delegate_.WaitForResult(), test::IsOk());
131}
132
133// Job shouldn't timeout when passed a TimeDelta of zero.
134TEST_F(ConnectJobTest, NoTimeoutWithNoTimeDelta) {
135 TestConnectJob job(TestConnectJob::JobType::kHung, base::TimeDelta(),
Matt Menkea6f99ad2019-03-08 02:26:43136 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02137 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
138 scoped_task_environment_.RunUntilIdle();
139 EXPECT_FALSE(delegate_.has_result());
140}
141
142// Make sure that ChangePriority() works, and new priority is visible to
143// subclasses during the SetPriorityInternal call.
144TEST_F(ConnectJobTest, SetPriority) {
145 TestConnectJob job(TestConnectJob::JobType::kAsyncSuccess,
Matt Menkea6f99ad2019-03-08 02:26:43146 base::TimeDelta::FromMicroseconds(1),
147 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02148 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
149
150 job.ChangePriority(HIGHEST);
151 EXPECT_EQ(HIGHEST, job.priority());
152 EXPECT_EQ(HIGHEST, job.last_seen_priority());
153
154 job.ChangePriority(MEDIUM);
155 EXPECT_EQ(MEDIUM, job.priority());
156 EXPECT_EQ(MEDIUM, job.last_seen_priority());
157
158 EXPECT_THAT(delegate_.WaitForResult(), test::IsOk());
159}
160
161TEST_F(ConnectJobTest, TimedOut) {
162 const base::TimeDelta kTimeout = base::TimeDelta::FromHours(1);
Matt Menke977e61b2019-01-10 19:36:02163
Matt Menkea6f99ad2019-03-08 02:26:43164 std::unique_ptr<TestConnectJob> job =
165 std::make_unique<TestConnectJob>(TestConnectJob::JobType::kHung, kTimeout,
166 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02167 ASSERT_THAT(job->Connect(), test::IsError(ERR_IO_PENDING));
168
169 // Nothing should happen before the specified time.
170 scoped_task_environment_.FastForwardBy(kTimeout -
171 base::TimeDelta::FromMilliseconds(1));
172 base::RunLoop().RunUntilIdle();
173 EXPECT_FALSE(delegate_.has_result());
174
175 // At which point the job should time out.
176 scoped_task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
177 EXPECT_THAT(delegate_.WaitForResult(), test::IsError(ERR_TIMED_OUT));
178
179 // Have to delete the job for it to log the end event.
180 job.reset();
181
182 TestNetLogEntry::List entries;
Matt Menkea6f99ad2019-03-08 02:26:43183 net_log_.GetEntries(&entries);
Matt Menke977e61b2019-01-10 19:36:02184
185 EXPECT_EQ(6u, entries.size());
Matt Menke1a6c92d2019-02-23 00:25:38186 EXPECT_TRUE(LogContainsBeginEvent(entries, 0, NetLogEventType::CONNECT_JOB));
Matt Menke977e61b2019-01-10 19:36:02187 EXPECT_TRUE(LogContainsBeginEvent(
Matt Menke1a6c92d2019-02-23 00:25:38188 entries, 1, NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT));
Matt Menke977e61b2019-01-10 19:36:02189 EXPECT_TRUE(LogContainsEvent(entries, 2,
190 NetLogEventType::CONNECT_JOB_SET_SOCKET,
191 NetLogEventPhase::NONE));
Matt Menke1a6c92d2019-02-23 00:25:38192 EXPECT_TRUE(LogContainsEvent(entries, 3,
193 NetLogEventType::CONNECT_JOB_TIMED_OUT,
194 NetLogEventPhase::NONE));
Matt Menke977e61b2019-01-10 19:36:02195 EXPECT_TRUE(LogContainsEndEvent(
Matt Menke1a6c92d2019-02-23 00:25:38196 entries, 4, NetLogEventType::TRANSPORT_CONNECT_JOB_CONNECT));
197 EXPECT_TRUE(LogContainsEndEvent(entries, 5, NetLogEventType::CONNECT_JOB));
Matt Menke977e61b2019-01-10 19:36:02198}
199
200TEST_F(ConnectJobTest, TimedOutWithRestartedTimer) {
201 const base::TimeDelta kTimeout = base::TimeDelta::FromHours(1);
202
Matt Menkea6f99ad2019-03-08 02:26:43203 TestConnectJob job(TestConnectJob::JobType::kHung, kTimeout,
204 &common_connect_job_params_, &delegate_);
Matt Menke977e61b2019-01-10 19:36:02205 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
206
207 // Nothing should happen before the specified time.
208 scoped_task_environment_.FastForwardBy(kTimeout -
209 base::TimeDelta::FromMilliseconds(1));
210 base::RunLoop().RunUntilIdle();
211 EXPECT_FALSE(delegate_.has_result());
212
213 // Make sure restarting the timer is respected.
214 job.ResetTimer(kTimeout);
215 scoped_task_environment_.FastForwardBy(kTimeout -
216 base::TimeDelta::FromMilliseconds(1));
217 base::RunLoop().RunUntilIdle();
218 EXPECT_FALSE(delegate_.has_result());
219
220 scoped_task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
221 EXPECT_THAT(delegate_.WaitForResult(), test::IsError(ERR_TIMED_OUT));
222}
223
224} // namespace
225} // namespace net