blob: b0c800762356c0eaaf8f27b0971d8f3d7eb03600 [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,
37 ConnectJob::Delegate* delegate,
38 NetLog* net_log)
39 : ConnectJob(
Matt Menke977e61b2019-01-10 19:36:0240 DEFAULT_PRIORITY,
Matt Menkeab90584b02019-01-18 08:22:3441 timeout_duration,
42 CommonConnectJobParams(
43 "group_name",
44 SocketTag(),
45 true /* respect_limits */,
46 nullptr /* client_socket_factory */,
47 nullptr /* socket_performance_watcher_factory */,
48 nullptr /* host_resolver */,
49 nullptr /* net_log */,
50 nullptr /* websocket_endpoint_lock_manager */),
Matt Menke977e61b2019-01-10 19:36:0251 delegate,
52 NetLogWithSource::Make(net_log,
53 NetLogSourceType::TRANSPORT_CONNECT_JOB)),
54 job_type_(job_type),
55 last_seen_priority_(DEFAULT_PRIORITY) {
56 switch (job_type_) {
57 case JobType::kSyncSuccess:
58 socket_data_provider_.set_connect_data(MockConnect(SYNCHRONOUS, OK));
59 return;
60 case JobType::kAsyncSuccess:
61 socket_data_provider_.set_connect_data(MockConnect(ASYNC, OK));
62 return;
63 case JobType::kHung:
64 socket_data_provider_.set_connect_data(
65 MockConnect(SYNCHRONOUS, ERR_IO_PENDING));
66 return;
67 }
68 }
69
70 // From ConnectJob:
71 LoadState GetLoadState() const override { return LOAD_STATE_IDLE; }
72 int ConnectInternal() override {
73 SetSocket(std::unique_ptr<StreamSocket>(new MockTCPClientSocket(
74 AddressList(), net_log().net_log(), &socket_data_provider_)));
75 return socket()->Connect(base::BindOnce(
76 &TestConnectJob::NotifyDelegateOfCompletion, base::Unretained(this)));
77 }
78 void ChangePriorityInternal(RequestPriority priority) override {
79 last_seen_priority_ = priority;
80 }
81
82 using ConnectJob::ResetTimer;
83
84 // The priority seen during the most recent call to ChangePriorityInternal().
85 RequestPriority last_seen_priority() const { return last_seen_priority_; }
86
87 private:
88 const JobType job_type_;
89 StaticSocketDataProvider socket_data_provider_;
90 RequestPriority last_seen_priority_;
91
92 DISALLOW_COPY_AND_ASSIGN(TestConnectJob);
93};
94
95class ConnectJobTest : public testing::Test {
96 public:
97 ConnectJobTest()
98 : scoped_task_environment_(
99 base::test::ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {}
100 ~ConnectJobTest() override = default;
101
102 protected:
103 base::test::ScopedTaskEnvironment scoped_task_environment_;
104 TestConnectJobDelegate delegate_;
105};
106
107// Even though a timeout is specified, it doesn't time out on a synchronous
108// completion.
109TEST_F(ConnectJobTest, NoTimeoutOnSyncCompletion) {
110 TestConnectJob job(TestConnectJob::JobType::kSyncSuccess,
111 base::TimeDelta::FromMicroseconds(1), &delegate_,
112 nullptr /* net_log */);
113 EXPECT_THAT(job.Connect(), test::IsOk());
114}
115
116// Even though a timeout is specified, it doesn't time out on an asynchronous
117// completion.
118TEST_F(ConnectJobTest, NoTimeoutOnAsyncCompletion) {
119 TestConnectJob job(TestConnectJob::JobType::kAsyncSuccess,
120 base::TimeDelta::FromMinutes(1), &delegate_,
121 nullptr /* net_log */);
122 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
123 EXPECT_THAT(delegate_.WaitForResult(), test::IsOk());
124}
125
126// Job shouldn't timeout when passed a TimeDelta of zero.
127TEST_F(ConnectJobTest, NoTimeoutWithNoTimeDelta) {
128 TestConnectJob job(TestConnectJob::JobType::kHung, base::TimeDelta(),
129 &delegate_, nullptr /* net_log */);
130 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
131 scoped_task_environment_.RunUntilIdle();
132 EXPECT_FALSE(delegate_.has_result());
133}
134
135// Make sure that ChangePriority() works, and new priority is visible to
136// subclasses during the SetPriorityInternal call.
137TEST_F(ConnectJobTest, SetPriority) {
138 TestConnectJob job(TestConnectJob::JobType::kAsyncSuccess,
139 base::TimeDelta::FromMicroseconds(1), &delegate_,
140 nullptr /* net_log */);
141 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
142
143 job.ChangePriority(HIGHEST);
144 EXPECT_EQ(HIGHEST, job.priority());
145 EXPECT_EQ(HIGHEST, job.last_seen_priority());
146
147 job.ChangePriority(MEDIUM);
148 EXPECT_EQ(MEDIUM, job.priority());
149 EXPECT_EQ(MEDIUM, job.last_seen_priority());
150
151 EXPECT_THAT(delegate_.WaitForResult(), test::IsOk());
152}
153
154TEST_F(ConnectJobTest, TimedOut) {
155 const base::TimeDelta kTimeout = base::TimeDelta::FromHours(1);
156 TestNetLog log;
157
158 std::unique_ptr<TestConnectJob> job = std::make_unique<TestConnectJob>(
159 TestConnectJob::JobType::kHung, kTimeout, &delegate_, &log);
160 ASSERT_THAT(job->Connect(), test::IsError(ERR_IO_PENDING));
161
162 // Nothing should happen before the specified time.
163 scoped_task_environment_.FastForwardBy(kTimeout -
164 base::TimeDelta::FromMilliseconds(1));
165 base::RunLoop().RunUntilIdle();
166 EXPECT_FALSE(delegate_.has_result());
167
168 // At which point the job should time out.
169 scoped_task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
170 EXPECT_THAT(delegate_.WaitForResult(), test::IsError(ERR_TIMED_OUT));
171
172 // Have to delete the job for it to log the end event.
173 job.reset();
174
175 TestNetLogEntry::List entries;
176 log.GetEntries(&entries);
177
178 EXPECT_EQ(6u, entries.size());
179 EXPECT_TRUE(LogContainsBeginEvent(entries, 0,
180 NetLogEventType::SOCKET_POOL_CONNECT_JOB));
181 EXPECT_TRUE(LogContainsBeginEvent(
182 entries, 1, NetLogEventType::SOCKET_POOL_CONNECT_JOB_CONNECT));
183 EXPECT_TRUE(LogContainsEvent(entries, 2,
184 NetLogEventType::CONNECT_JOB_SET_SOCKET,
185 NetLogEventPhase::NONE));
186 EXPECT_TRUE(LogContainsEvent(
187 entries, 3, NetLogEventType::SOCKET_POOL_CONNECT_JOB_TIMED_OUT,
188 NetLogEventPhase::NONE));
189 EXPECT_TRUE(LogContainsEndEvent(
190 entries, 4, NetLogEventType::SOCKET_POOL_CONNECT_JOB_CONNECT));
191 EXPECT_TRUE(LogContainsEndEvent(entries, 5,
192 NetLogEventType::SOCKET_POOL_CONNECT_JOB));
193}
194
195TEST_F(ConnectJobTest, TimedOutWithRestartedTimer) {
196 const base::TimeDelta kTimeout = base::TimeDelta::FromHours(1);
197
198 TestConnectJob job(TestConnectJob::JobType::kHung, kTimeout, &delegate_,
199 nullptr /* net_log */);
200 ASSERT_THAT(job.Connect(), test::IsError(ERR_IO_PENDING));
201
202 // Nothing should happen before the specified time.
203 scoped_task_environment_.FastForwardBy(kTimeout -
204 base::TimeDelta::FromMilliseconds(1));
205 base::RunLoop().RunUntilIdle();
206 EXPECT_FALSE(delegate_.has_result());
207
208 // Make sure restarting the timer is respected.
209 job.ResetTimer(kTimeout);
210 scoped_task_environment_.FastForwardBy(kTimeout -
211 base::TimeDelta::FromMilliseconds(1));
212 base::RunLoop().RunUntilIdle();
213 EXPECT_FALSE(delegate_.has_result());
214
215 scoped_task_environment_.FastForwardBy(base::TimeDelta::FromMilliseconds(1));
216 EXPECT_THAT(delegate_.WaitForResult(), test::IsError(ERR_TIMED_OUT));
217}
218
219} // namespace
220} // namespace net