connect_job_unittest.cc 8.3 KB

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