1 // Copyright 2023 The Chromium Authors
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/http/http_transaction_test_util.h"
6
7 #include <string>
8 #include <string_view>
9
10 #include "base/test/bind.h"
11 #include "base/test/task_environment.h"
12 #include "net/base/test_completion_callback.h"
13 #include "net/test/gtest_util.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace net {
17
18 namespace {
19
20 // Default transaction.
21 const MockTransaction kBasicTransaction = {
22 .url = "http://www.example.com/",
23 .method = "GET",
24 .request_time = base::Time(),
25 .request_headers = "",
26 .load_flags = LOAD_NORMAL,
27 .transport_info = TransportInfo(TransportType::kDirect,
28 IPEndPoint(IPAddress::IPv4Localhost(), 80),
29 /*accept_ch_frame_arg=*/"",
30 /*cert_is_issued_by_known_root=*/false,
31 kProtoUnknown),
32 .status = "HTTP/1.1 200 OK",
33 .response_headers = "Cache-Control: max-age=10000\n",
34 .response_time = base::Time(),
35 .data = "<html><body>Hello world!</body></html>",
36 .dns_aliases = {},
37 .fps_cache_filter = absl::nullopt,
38 .browser_run_id = absl::nullopt,
39 .test_mode = TEST_MODE_NORMAL,
40 .handler = MockTransactionHandler(),
41 .read_handler = MockTransactionReadHandler(),
42 .cert = nullptr,
43 .cert_status = 0,
44 .ssl_connection_status = 0,
45 .start_return_code = OK,
46 .read_return_code = OK,
47 };
48 const size_t kDefaultBufferSize = 1024;
49
50 } // namespace
51
52 class MockNetworkTransactionTest : public ::testing::Test {
53 public:
MockNetworkTransactionTest()54 MockNetworkTransactionTest()
55 : network_layer_(std::make_unique<MockNetworkLayer>()) {}
56 ~MockNetworkTransactionTest() override = default;
57
58 MockNetworkTransactionTest(const MockNetworkTransactionTest&) = delete;
59 MockNetworkTransactionTest& operator=(const MockNetworkTransactionTest&) =
60 delete;
61
62 protected:
CreateNetworkTransaction()63 std::unique_ptr<HttpTransaction> CreateNetworkTransaction() {
64 std::unique_ptr<HttpTransaction> network_transaction;
65 network_layer_->CreateTransaction(DEFAULT_PRIORITY, &network_transaction);
66 return network_transaction;
67 }
68
RunUntilIdle()69 void RunUntilIdle() { task_environment_.RunUntilIdle(); }
70
network_layer()71 MockNetworkLayer& network_layer() { return *network_layer_.get(); }
72
73 private:
74 std::unique_ptr<MockNetworkLayer> network_layer_;
75 base::test::TaskEnvironment task_environment_{
76 base::test::TaskEnvironment::TimeSource::MOCK_TIME};
77 };
78
TEST_F(MockNetworkTransactionTest,Basic)79 TEST_F(MockNetworkTransactionTest, Basic) {
80 AddMockTransaction(&kBasicTransaction);
81 HttpRequestInfo request = MockHttpRequest(kBasicTransaction);
82
83 auto transaction = CreateNetworkTransaction();
84 TestCompletionCallback start_callback;
85 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
86 NetLogWithSource()),
87 test::IsError(ERR_IO_PENDING));
88 EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
89
90 EXPECT_FALSE(transaction->GetResponseInfo()->was_cached);
91 EXPECT_TRUE(transaction->GetResponseInfo()->network_accessed);
92 EXPECT_EQ(kBasicTransaction.transport_info.endpoint,
93 transaction->GetResponseInfo()->remote_endpoint);
94 EXPECT_FALSE(transaction->GetResponseInfo()->was_fetched_via_proxy);
95
96 scoped_refptr<IOBufferWithSize> buf =
97 base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
98 TestCompletionCallback read_callback;
99 ASSERT_THAT(
100 transaction->Read(buf.get(), buf->size(), read_callback.callback()),
101 test::IsError(ERR_IO_PENDING));
102 int read_result = read_callback.WaitForResult();
103 ASSERT_THAT(read_result, std::string_view(kBasicTransaction.data).size());
104 EXPECT_EQ(std::string_view(kBasicTransaction.data),
105 std::string_view(buf->data(), read_result));
106 }
107
TEST_F(MockNetworkTransactionTest,SyncNetStart)108 TEST_F(MockNetworkTransactionTest, SyncNetStart) {
109 MockTransaction new_mock_transaction = kBasicTransaction;
110 new_mock_transaction.test_mode = TEST_MODE_SYNC_NET_START;
111 AddMockTransaction(&new_mock_transaction);
112 HttpRequestInfo request = MockHttpRequest(new_mock_transaction);
113
114 auto transaction = CreateNetworkTransaction();
115 TestCompletionCallback start_callback;
116 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
117 NetLogWithSource()),
118 test::IsError(OK));
119
120 scoped_refptr<IOBufferWithSize> buf =
121 base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
122 TestCompletionCallback read_callback;
123 ASSERT_THAT(
124 transaction->Read(buf.get(), buf->size(), read_callback.callback()),
125 test::IsError(ERR_IO_PENDING));
126 int read_result = read_callback.WaitForResult();
127 ASSERT_THAT(read_result, std::string_view(new_mock_transaction.data).size());
128 EXPECT_EQ(std::string_view(new_mock_transaction.data),
129 std::string_view(buf->data(), read_result));
130 }
131
TEST_F(MockNetworkTransactionTest,AsyncNetStartFailure)132 TEST_F(MockNetworkTransactionTest, AsyncNetStartFailure) {
133 MockTransaction new_mock_transaction = kBasicTransaction;
134 new_mock_transaction.start_return_code = ERR_NETWORK_ACCESS_DENIED;
135 AddMockTransaction(&new_mock_transaction);
136 HttpRequestInfo request = MockHttpRequest(new_mock_transaction);
137
138 auto transaction = CreateNetworkTransaction();
139 TestCompletionCallback start_callback;
140 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
141 NetLogWithSource()),
142 test::IsError(ERR_IO_PENDING));
143 EXPECT_THAT(start_callback.WaitForResult(),
144 test::IsError(ERR_NETWORK_ACCESS_DENIED));
145 }
146
TEST_F(MockNetworkTransactionTest,SyncNetStartFailure)147 TEST_F(MockNetworkTransactionTest, SyncNetStartFailure) {
148 MockTransaction new_mock_transaction = kBasicTransaction;
149 new_mock_transaction.test_mode = TEST_MODE_SYNC_NET_START;
150 new_mock_transaction.start_return_code = ERR_NETWORK_ACCESS_DENIED;
151 AddMockTransaction(&new_mock_transaction);
152 HttpRequestInfo request = MockHttpRequest(new_mock_transaction);
153
154 auto transaction = CreateNetworkTransaction();
155 TestCompletionCallback start_callback;
156 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
157 NetLogWithSource()),
158 test::IsError(ERR_NETWORK_ACCESS_DENIED));
159 }
160
TEST_F(MockNetworkTransactionTest,BeforeNetworkStartCallback)161 TEST_F(MockNetworkTransactionTest, BeforeNetworkStartCallback) {
162 AddMockTransaction(&kBasicTransaction);
163 HttpRequestInfo request = MockHttpRequest(kBasicTransaction);
164
165 auto transaction = CreateNetworkTransaction();
166 bool before_network_start_callback_called = false;
167 transaction->SetBeforeNetworkStartCallback(base::BindLambdaForTesting(
168 [&](bool* defer) { before_network_start_callback_called = true; }));
169
170 TestCompletionCallback start_callback;
171 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
172 NetLogWithSource()),
173 test::IsError(ERR_IO_PENDING));
174 EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
175 EXPECT_TRUE(before_network_start_callback_called);
176 }
177
TEST_F(MockNetworkTransactionTest,BeforeNetworkStartCallbackDeferAndResume)178 TEST_F(MockNetworkTransactionTest, BeforeNetworkStartCallbackDeferAndResume) {
179 AddMockTransaction(&kBasicTransaction);
180 HttpRequestInfo request = MockHttpRequest(kBasicTransaction);
181
182 auto transaction = CreateNetworkTransaction();
183 bool before_network_start_callback_called = false;
184 transaction->SetBeforeNetworkStartCallback(
185 base::BindLambdaForTesting([&](bool* defer) {
186 before_network_start_callback_called = true;
187 *defer = true;
188 }));
189
190 TestCompletionCallback start_callback;
191 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
192 NetLogWithSource()),
193 test::IsError(ERR_IO_PENDING));
194 EXPECT_TRUE(before_network_start_callback_called);
195 RunUntilIdle();
196 EXPECT_FALSE(start_callback.have_result());
197 transaction->ResumeNetworkStart();
198 EXPECT_FALSE(start_callback.have_result());
199 EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
200 }
201
TEST_F(MockNetworkTransactionTest,AsyncConnectedCallback)202 TEST_F(MockNetworkTransactionTest, AsyncConnectedCallback) {
203 AddMockTransaction(&kBasicTransaction);
204 HttpRequestInfo request = MockHttpRequest(kBasicTransaction);
205
206 auto transaction = CreateNetworkTransaction();
207 bool connected_callback_called = false;
208 CompletionOnceCallback callback_for_connected_callback;
209 transaction->SetConnectedCallback(base::BindLambdaForTesting(
210 [&](const TransportInfo& info, CompletionOnceCallback callback) -> int {
211 EXPECT_EQ(kBasicTransaction.transport_info, info);
212 connected_callback_called = true;
213 callback_for_connected_callback = std::move(callback);
214 return ERR_IO_PENDING;
215 }));
216
217 TestCompletionCallback start_callback;
218 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
219 NetLogWithSource()),
220 test::IsError(ERR_IO_PENDING));
221 RunUntilIdle();
222 EXPECT_TRUE(connected_callback_called);
223 EXPECT_FALSE(start_callback.have_result());
224 std::move(callback_for_connected_callback).Run(OK);
225 EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
226 }
227
TEST_F(MockNetworkTransactionTest,AsyncConnectedCallbackFailure)228 TEST_F(MockNetworkTransactionTest, AsyncConnectedCallbackFailure) {
229 AddMockTransaction(&kBasicTransaction);
230 HttpRequestInfo request = MockHttpRequest(kBasicTransaction);
231
232 auto transaction = CreateNetworkTransaction();
233 bool connected_callback_called = false;
234 CompletionOnceCallback callback_for_connected_callback;
235 transaction->SetConnectedCallback(base::BindLambdaForTesting(
236 [&](const TransportInfo& info, CompletionOnceCallback callback) -> int {
237 EXPECT_EQ(kBasicTransaction.transport_info, info);
238 connected_callback_called = true;
239 callback_for_connected_callback = std::move(callback);
240 return ERR_IO_PENDING;
241 }));
242
243 TestCompletionCallback start_callback;
244 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
245 NetLogWithSource()),
246 test::IsError(ERR_IO_PENDING));
247 RunUntilIdle();
248 EXPECT_TRUE(connected_callback_called);
249 EXPECT_FALSE(start_callback.have_result());
250 std::move(callback_for_connected_callback).Run(ERR_INSUFFICIENT_RESOURCES);
251 EXPECT_THAT(start_callback.WaitForResult(),
252 test::IsError(ERR_INSUFFICIENT_RESOURCES));
253 }
254
TEST_F(MockNetworkTransactionTest,SyncConnectedCallback)255 TEST_F(MockNetworkTransactionTest, SyncConnectedCallback) {
256 AddMockTransaction(&kBasicTransaction);
257 HttpRequestInfo request = MockHttpRequest(kBasicTransaction);
258
259 auto transaction = CreateNetworkTransaction();
260 bool connected_callback_called = false;
261 transaction->SetConnectedCallback(base::BindLambdaForTesting(
262 [&](const TransportInfo& info, CompletionOnceCallback callback) -> int {
263 EXPECT_EQ(kBasicTransaction.transport_info, info);
264 connected_callback_called = true;
265 return OK;
266 }));
267
268 TestCompletionCallback start_callback;
269 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
270 NetLogWithSource()),
271 test::IsError(ERR_IO_PENDING));
272 RunUntilIdle();
273 EXPECT_TRUE(connected_callback_called);
274 EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
275 }
276
TEST_F(MockNetworkTransactionTest,SyncConnectedCallbackFailure)277 TEST_F(MockNetworkTransactionTest, SyncConnectedCallbackFailure) {
278 AddMockTransaction(&kBasicTransaction);
279 HttpRequestInfo request = MockHttpRequest(kBasicTransaction);
280
281 auto transaction = CreateNetworkTransaction();
282 bool connected_callback_called = false;
283 transaction->SetConnectedCallback(base::BindLambdaForTesting(
284 [&](const TransportInfo& info, CompletionOnceCallback callback) -> int {
285 EXPECT_EQ(kBasicTransaction.transport_info, info);
286 connected_callback_called = true;
287 return ERR_INSUFFICIENT_RESOURCES;
288 }));
289
290 TestCompletionCallback start_callback;
291 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
292 NetLogWithSource()),
293 test::IsError(ERR_IO_PENDING));
294 RunUntilIdle();
295 EXPECT_TRUE(connected_callback_called);
296 EXPECT_THAT(start_callback.WaitForResult(),
297 test::IsError(ERR_INSUFFICIENT_RESOURCES));
298 }
299
TEST_F(MockNetworkTransactionTest,ModifyRequestHeadersCallback)300 TEST_F(MockNetworkTransactionTest, ModifyRequestHeadersCallback) {
301 const std::string kTestResponseData = "hello";
302 MockTransaction new_mock_transaction = kBasicTransaction;
303 new_mock_transaction.request_headers = "Foo: Bar\r\n";
304
305 bool transaction_handler_called = false;
306 new_mock_transaction.handler = base::BindLambdaForTesting(
307 [&](const HttpRequestInfo* request, std::string* response_status,
308 std::string* response_headers, std::string* response_data) {
309 EXPECT_EQ("Foo: Bar\r\nHoge: Piyo\r\n\r\n",
310 request->extra_headers.ToString());
311 *response_data = kTestResponseData;
312 transaction_handler_called = true;
313 });
314 AddMockTransaction(&new_mock_transaction);
315 HttpRequestInfo request = MockHttpRequest(new_mock_transaction);
316
317 auto transaction = CreateNetworkTransaction();
318 bool modify_request_headers_callback_called_ = false;
319 transaction->SetModifyRequestHeadersCallback(
320 base::BindLambdaForTesting([&](HttpRequestHeaders* request_headers) {
321 modify_request_headers_callback_called_ = true;
322 request_headers->SetHeader("Hoge", "Piyo");
323 }));
324
325 TestCompletionCallback start_callback;
326 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
327 NetLogWithSource()),
328 test::IsError(ERR_IO_PENDING));
329 EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
330 EXPECT_TRUE(modify_request_headers_callback_called_);
331 EXPECT_TRUE(transaction_handler_called);
332
333 scoped_refptr<IOBufferWithSize> buf =
334 base::MakeRefCounted<IOBufferWithSize>(kDefaultBufferSize);
335 TestCompletionCallback read_callback;
336 ASSERT_THAT(
337 transaction->Read(buf.get(), buf->size(), read_callback.callback()),
338 test::IsError(ERR_IO_PENDING));
339 int read_result = read_callback.WaitForResult();
340 ASSERT_THAT(read_result, kTestResponseData.size());
341 EXPECT_EQ(kTestResponseData, std::string_view(buf->data(), read_result));
342 }
343
TEST_F(MockNetworkTransactionTest,CallbackOrder)344 TEST_F(MockNetworkTransactionTest, CallbackOrder) {
345 const std::string kTestResponseData = "hello";
346 MockTransaction new_mock_transaction = kBasicTransaction;
347 new_mock_transaction.request_headers = "Foo: Bar\r\n";
348
349 bool before_network_start_callback_called = false;
350 bool connected_callback_called = false;
351 bool modify_request_headers_callback_called_ = false;
352 bool transaction_handler_called = false;
353
354 new_mock_transaction.handler = base::BindLambdaForTesting(
355 [&](const HttpRequestInfo* request, std::string* response_status,
356 std::string* response_headers, std::string* response_data) {
357 EXPECT_TRUE(before_network_start_callback_called);
358 EXPECT_TRUE(connected_callback_called);
359 EXPECT_TRUE(modify_request_headers_callback_called_);
360 EXPECT_FALSE(transaction_handler_called);
361
362 *response_data = kTestResponseData;
363 transaction_handler_called = true;
364 });
365
366 AddMockTransaction(&new_mock_transaction);
367 HttpRequestInfo request = MockHttpRequest(new_mock_transaction);
368
369 auto transaction = CreateNetworkTransaction();
370 transaction->SetBeforeNetworkStartCallback(
371 base::BindLambdaForTesting([&](bool* defer) {
372 EXPECT_FALSE(before_network_start_callback_called);
373 EXPECT_FALSE(connected_callback_called);
374 EXPECT_FALSE(modify_request_headers_callback_called_);
375 EXPECT_FALSE(transaction_handler_called);
376
377 before_network_start_callback_called = true;
378 *defer = true;
379 }));
380
381 CompletionOnceCallback callback_for_connected_callback;
382 transaction->SetConnectedCallback(base::BindLambdaForTesting(
383 [&](const TransportInfo& info, CompletionOnceCallback callback) -> int {
384 EXPECT_TRUE(before_network_start_callback_called);
385 EXPECT_FALSE(connected_callback_called);
386 EXPECT_FALSE(modify_request_headers_callback_called_);
387 EXPECT_FALSE(transaction_handler_called);
388
389 connected_callback_called = true;
390 callback_for_connected_callback = std::move(callback);
391 return ERR_IO_PENDING;
392 }));
393
394 transaction->SetModifyRequestHeadersCallback(
395 base::BindLambdaForTesting([&](HttpRequestHeaders* request_headers) {
396 EXPECT_TRUE(before_network_start_callback_called);
397 EXPECT_TRUE(connected_callback_called);
398 EXPECT_FALSE(modify_request_headers_callback_called_);
399 EXPECT_FALSE(transaction_handler_called);
400
401 modify_request_headers_callback_called_ = true;
402 }));
403
404 EXPECT_FALSE(before_network_start_callback_called);
405 TestCompletionCallback start_callback;
406 ASSERT_THAT(transaction->Start(&request, start_callback.callback(),
407 NetLogWithSource()),
408 test::IsError(ERR_IO_PENDING));
409
410 EXPECT_TRUE(before_network_start_callback_called);
411
412 EXPECT_FALSE(connected_callback_called);
413 transaction->ResumeNetworkStart();
414 RunUntilIdle();
415 EXPECT_TRUE(connected_callback_called);
416
417 EXPECT_FALSE(modify_request_headers_callback_called_);
418 std::move(callback_for_connected_callback).Run(OK);
419 EXPECT_TRUE(modify_request_headers_callback_called_);
420 EXPECT_TRUE(transaction_handler_called);
421
422 EXPECT_TRUE(start_callback.have_result());
423 EXPECT_THAT(start_callback.WaitForResult(), test::IsError(OK));
424 }
425
426 } // namespace net
427