1 // Copyright 2013 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.
10 #include "base/bind_helpers.h"
11 #include "base/callback_helpers.h"
12 #include "base/compiler_specific.h"
13 #include "base/format_macros.h"
14 #include "base/location.h"
15 #include "base/memory/ref_counted.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/memory/weak_ptr.h"
18 #include "base/run_loop.h"
19 #include "base/single_thread_task_runner.h"
20 #include "base/strings/string_split.h"
21 #include "base/strings/string_util.h"
22 #include "base/strings/stringprintf.h"
23 #include "base/thread_task_runner_handle.h"
24 #include "base/time/time.h"
25 #include "net/base/address_list.h"
26 #include "net/base/io_buffer.h"
27 #include "net/base/ip_endpoint.h"
28 #include "net/base/net_errors.h"
29 #include "net/base/net_util.h"
30 #include "net/base/test_completion_callback.h"
31 #include "net/http/http_response_headers.h"
32 #include "net/http/http_util.h"
33 #include "net/log/net_log.h"
34 #include "net/server/http_server.h"
35 #include "net/server/http_server_request_info.h"
36 #include "net/socket/tcp_client_socket.h"
37 #include "net/socket/tcp_server_socket.h"
38 #include "net/url_request/url_fetcher.h"
39 #include "net/url_request/url_fetcher_delegate.h"
40 #include "net/url_request/url_request_context.h"
41 #include "net/url_request/url_request_context_getter.h"
42 #include "net/url_request/url_request_test_util.h"
43 #include "testing/gtest/include/gtest/gtest.h"
49 const int kMaxExpectedResponseLength
= 2048;
51 void SetTimedOutAndQuitLoop(const base::WeakPtr
<bool> timed_out
,
52 const base::Closure
& quit_loop_func
) {
59 bool RunLoopWithTimeout(base::RunLoop
* run_loop
) {
60 bool timed_out
= false;
61 base::WeakPtrFactory
<bool> timed_out_weak_factory(&timed_out
);
62 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
64 base::Bind(&SetTimedOutAndQuitLoop
, timed_out_weak_factory
.GetWeakPtr(),
65 run_loop
->QuitClosure()),
66 base::TimeDelta::FromSeconds(1));
71 class TestHttpClient
{
73 TestHttpClient() : connect_result_(OK
) {}
75 int ConnectAndWait(const IPEndPoint
& address
) {
76 AddressList
addresses(address
);
77 NetLog::Source source
;
78 socket_
.reset(new TCPClientSocket(addresses
, NULL
, source
));
80 base::RunLoop run_loop
;
81 connect_result_
= socket_
->Connect(base::Bind(&TestHttpClient::OnConnect
,
82 base::Unretained(this),
83 run_loop
.QuitClosure()));
84 if (connect_result_
!= OK
&& connect_result_
!= ERR_IO_PENDING
)
85 return connect_result_
;
87 if (!RunLoopWithTimeout(&run_loop
))
89 return connect_result_
;
92 void Send(const std::string
& data
) {
94 new DrainableIOBuffer(new StringIOBuffer(data
), data
.length());
98 bool Read(std::string
* message
, int expected_bytes
) {
99 int total_bytes_received
= 0;
101 while (total_bytes_received
< expected_bytes
) {
102 TestCompletionCallback callback
;
103 ReadInternal(callback
.callback());
104 int bytes_received
= callback
.WaitForResult();
105 if (bytes_received
<= 0)
108 total_bytes_received
+= bytes_received
;
109 message
->append(read_buffer_
->data(), bytes_received
);
114 bool ReadResponse(std::string
* message
) {
115 if (!Read(message
, 1))
117 while (!IsCompleteResponse(*message
)) {
119 if (!Read(&chunk
, 1))
121 message
->append(chunk
);
127 void OnConnect(const base::Closure
& quit_loop
, int result
) {
128 connect_result_
= result
;
133 int result
= socket_
->Write(
135 write_buffer_
->BytesRemaining(),
136 base::Bind(&TestHttpClient::OnWrite
, base::Unretained(this)));
137 if (result
!= ERR_IO_PENDING
)
141 void OnWrite(int result
) {
142 ASSERT_GT(result
, 0);
143 write_buffer_
->DidConsume(result
);
144 if (write_buffer_
->BytesRemaining())
148 void ReadInternal(const CompletionCallback
& callback
) {
149 read_buffer_
= new IOBufferWithSize(kMaxExpectedResponseLength
);
151 socket_
->Read(read_buffer_
.get(), kMaxExpectedResponseLength
, callback
);
152 if (result
!= ERR_IO_PENDING
)
153 callback
.Run(result
);
156 bool IsCompleteResponse(const std::string
& response
) {
157 // Check end of headers first.
158 int end_of_headers
= HttpUtil::LocateEndOfHeaders(response
.data(),
160 if (end_of_headers
< 0)
163 // Return true if response has data equal to or more than content length.
164 int64 body_size
= static_cast<int64
>(response
.size()) - end_of_headers
;
165 DCHECK_LE(0, body_size
);
166 scoped_refptr
<HttpResponseHeaders
> headers(new HttpResponseHeaders(
167 HttpUtil::AssembleRawHeaders(response
.data(), end_of_headers
)));
168 return body_size
>= headers
->GetContentLength();
171 scoped_refptr
<IOBufferWithSize
> read_buffer_
;
172 scoped_refptr
<DrainableIOBuffer
> write_buffer_
;
173 scoped_ptr
<TCPClientSocket
> socket_
;
179 class HttpServerTest
: public testing::Test
,
180 public HttpServer::Delegate
{
182 HttpServerTest() : quit_after_request_count_(0) {}
184 void SetUp() override
{
185 scoped_ptr
<ServerSocket
> server_socket(
186 new TCPServerSocket(NULL
, NetLog::Source()));
187 server_socket
->ListenWithAddressAndPort("127.0.0.1", 0, 1);
188 server_
.reset(new HttpServer(server_socket
.Pass(), this));
189 ASSERT_EQ(OK
, server_
->GetLocalAddress(&server_address_
));
192 void OnConnect(int connection_id
) override
{}
194 void OnHttpRequest(int connection_id
,
195 const HttpServerRequestInfo
& info
) override
{
196 requests_
.push_back(std::make_pair(info
, connection_id
));
197 if (requests_
.size() == quit_after_request_count_
)
198 run_loop_quit_func_
.Run();
201 void OnWebSocketRequest(int connection_id
,
202 const HttpServerRequestInfo
& info
) override
{
206 void OnWebSocketMessage(int connection_id
, const std::string
& data
) override
{
210 void OnClose(int connection_id
) override
{}
212 bool RunUntilRequestsReceived(size_t count
) {
213 quit_after_request_count_
= count
;
214 if (requests_
.size() == count
)
217 base::RunLoop run_loop
;
218 run_loop_quit_func_
= run_loop
.QuitClosure();
219 bool success
= RunLoopWithTimeout(&run_loop
);
220 run_loop_quit_func_
.Reset();
224 HttpServerRequestInfo
GetRequest(size_t request_index
) {
225 return requests_
[request_index
].first
;
228 int GetConnectionId(size_t request_index
) {
229 return requests_
[request_index
].second
;
232 void HandleAcceptResult(scoped_ptr
<StreamSocket
> socket
) {
233 server_
->accepted_socket_
.reset(socket
.release());
234 server_
->HandleAcceptResult(OK
);
238 scoped_ptr
<HttpServer
> server_
;
239 IPEndPoint server_address_
;
240 base::Closure run_loop_quit_func_
;
241 std::vector
<std::pair
<HttpServerRequestInfo
, int> > requests_
;
244 size_t quit_after_request_count_
;
249 class WebSocketTest
: public HttpServerTest
{
250 void OnHttpRequest(int connection_id
,
251 const HttpServerRequestInfo
& info
) override
{
255 void OnWebSocketRequest(int connection_id
,
256 const HttpServerRequestInfo
& info
) override
{
257 HttpServerTest::OnHttpRequest(connection_id
, info
);
260 void OnWebSocketMessage(int connection_id
, const std::string
& data
) override
{
264 TEST_F(HttpServerTest
, Request
) {
265 TestHttpClient client
;
266 ASSERT_EQ(OK
, client
.ConnectAndWait(server_address_
));
267 client
.Send("GET /test HTTP/1.1\r\n\r\n");
268 ASSERT_TRUE(RunUntilRequestsReceived(1));
269 ASSERT_EQ("GET", GetRequest(0).method
);
270 ASSERT_EQ("/test", GetRequest(0).path
);
271 ASSERT_EQ("", GetRequest(0).data
);
272 ASSERT_EQ(0u, GetRequest(0).headers
.size());
273 ASSERT_TRUE(base::StartsWith(GetRequest(0).peer
.ToString(), "127.0.0.1",
274 base::CompareCase::SENSITIVE
));
277 TEST_F(HttpServerTest
, RequestWithHeaders
) {
278 TestHttpClient client
;
279 ASSERT_EQ(OK
, client
.ConnectAndWait(server_address_
));
280 const char* const kHeaders
[][3] = {
281 {"Header", ": ", "1"},
282 {"HeaderWithNoWhitespace", ":", "1"},
283 {"HeaderWithWhitespace", " : \t ", "1 1 1 \t "},
284 {"HeaderWithColon", ": ", "1:1"},
285 {"EmptyHeader", ":", ""},
286 {"EmptyHeaderWithWhitespace", ": \t ", ""},
287 {"HeaderWithNonASCII", ": ", "\xf7"},
290 for (size_t i
= 0; i
< arraysize(kHeaders
); ++i
) {
292 std::string(kHeaders
[i
][0]) + kHeaders
[i
][1] + kHeaders
[i
][2] + "\r\n";
295 client
.Send("GET /test HTTP/1.1\r\n" + headers
+ "\r\n");
296 ASSERT_TRUE(RunUntilRequestsReceived(1));
297 ASSERT_EQ("", GetRequest(0).data
);
299 for (size_t i
= 0; i
< arraysize(kHeaders
); ++i
) {
300 std::string field
= base::ToLowerASCII(std::string(kHeaders
[i
][0]));
301 std::string value
= kHeaders
[i
][2];
302 ASSERT_EQ(1u, GetRequest(0).headers
.count(field
)) << field
;
303 ASSERT_EQ(value
, GetRequest(0).headers
[field
]) << kHeaders
[i
][0];
307 TEST_F(HttpServerTest
, RequestWithDuplicateHeaders
) {
308 TestHttpClient client
;
309 ASSERT_EQ(OK
, client
.ConnectAndWait(server_address_
));
310 const char* const kHeaders
[][3] = {
311 {"FirstHeader", ": ", "1"},
312 {"DuplicateHeader", ": ", "2"},
313 {"MiddleHeader", ": ", "3"},
314 {"DuplicateHeader", ": ", "4"},
315 {"LastHeader", ": ", "5"},
318 for (size_t i
= 0; i
< arraysize(kHeaders
); ++i
) {
320 std::string(kHeaders
[i
][0]) + kHeaders
[i
][1] + kHeaders
[i
][2] + "\r\n";
323 client
.Send("GET /test HTTP/1.1\r\n" + headers
+ "\r\n");
324 ASSERT_TRUE(RunUntilRequestsReceived(1));
325 ASSERT_EQ("", GetRequest(0).data
);
327 for (size_t i
= 0; i
< arraysize(kHeaders
); ++i
) {
328 std::string field
= base::ToLowerASCII(std::string(kHeaders
[i
][0]));
329 std::string value
= (field
== "duplicateheader") ? "2,4" : kHeaders
[i
][2];
330 ASSERT_EQ(1u, GetRequest(0).headers
.count(field
)) << field
;
331 ASSERT_EQ(value
, GetRequest(0).headers
[field
]) << kHeaders
[i
][0];
335 TEST_F(HttpServerTest
, HasHeaderValueTest
) {
336 TestHttpClient client
;
337 ASSERT_EQ(OK
, client
.ConnectAndWait(server_address_
));
338 const char* const kHeaders
[] = {
340 "HeaderWithNoWhitespace:E",
341 "HeaderWithWhitespace : \t f \t ",
342 "DuplicateHeader: g",
343 "HeaderWithComma: h, i ,j",
344 "DuplicateHeader: k",
346 "EmptyHeaderWithWhitespace: \t ",
347 "HeaderWithNonASCII: \xf7",
350 for (size_t i
= 0; i
< arraysize(kHeaders
); ++i
) {
351 headers
+= std::string(kHeaders
[i
]) + "\r\n";
354 client
.Send("GET /test HTTP/1.1\r\n" + headers
+ "\r\n");
355 ASSERT_TRUE(RunUntilRequestsReceived(1));
356 ASSERT_EQ("", GetRequest(0).data
);
358 ASSERT_TRUE(GetRequest(0).HasHeaderValue("header", "abcd"));
359 ASSERT_FALSE(GetRequest(0).HasHeaderValue("header", "bc"));
360 ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithnowhitespace", "e"));
361 ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithwhitespace", "f"));
362 ASSERT_TRUE(GetRequest(0).HasHeaderValue("duplicateheader", "g"));
363 ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithcomma", "h"));
364 ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithcomma", "i"));
365 ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithcomma", "j"));
366 ASSERT_TRUE(GetRequest(0).HasHeaderValue("duplicateheader", "k"));
367 ASSERT_FALSE(GetRequest(0).HasHeaderValue("emptyheader", "x"));
368 ASSERT_FALSE(GetRequest(0).HasHeaderValue("emptyheaderwithwhitespace", "x"));
369 ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithnonascii", "\xf7"));
372 TEST_F(HttpServerTest
, RequestWithBody
) {
373 TestHttpClient client
;
374 ASSERT_EQ(OK
, client
.ConnectAndWait(server_address_
));
375 std::string body
= "a" + std::string(1 << 10, 'b') + "c";
376 client
.Send(base::StringPrintf(
377 "GET /test HTTP/1.1\r\n"
379 "Content-Length: %" PRIuS
"\r\n\r\n%s",
382 ASSERT_TRUE(RunUntilRequestsReceived(1));
383 ASSERT_EQ(2u, GetRequest(0).headers
.size());
384 ASSERT_EQ(body
.length(), GetRequest(0).data
.length());
385 ASSERT_EQ('a', body
[0]);
386 ASSERT_EQ('c', *body
.rbegin());
389 TEST_F(WebSocketTest
, RequestWebSocket
) {
390 TestHttpClient client
;
391 ASSERT_EQ(OK
, client
.ConnectAndWait(server_address_
));
393 "GET /test HTTP/1.1\r\n"
394 "Upgrade: WebSocket\r\n"
395 "Connection: SomethingElse, Upgrade\r\n"
396 "Sec-WebSocket-Version: 8\r\n"
397 "Sec-WebSocket-Key: key\r\n"
399 ASSERT_TRUE(RunUntilRequestsReceived(1));
402 TEST_F(HttpServerTest
, RequestWithTooLargeBody
) {
403 class TestURLFetcherDelegate
: public URLFetcherDelegate
{
405 TestURLFetcherDelegate(const base::Closure
& quit_loop_func
)
406 : quit_loop_func_(quit_loop_func
) {}
407 ~TestURLFetcherDelegate() override
{}
409 void OnURLFetchComplete(const URLFetcher
* source
) override
{
410 EXPECT_EQ(HTTP_INTERNAL_SERVER_ERROR
, source
->GetResponseCode());
411 quit_loop_func_
.Run();
415 base::Closure quit_loop_func_
;
418 base::RunLoop run_loop
;
419 TestURLFetcherDelegate
delegate(run_loop
.QuitClosure());
421 scoped_refptr
<URLRequestContextGetter
> request_context_getter(
422 new TestURLRequestContextGetter(base::ThreadTaskRunnerHandle::Get()));
423 scoped_ptr
<URLFetcher
> fetcher
=
424 URLFetcher::Create(GURL(base::StringPrintf("http://127.0.0.1:%d/test",
425 server_address_
.port())),
426 URLFetcher::GET
, &delegate
);
427 fetcher
->SetRequestContext(request_context_getter
.get());
428 fetcher
->AddExtraRequestHeader(
429 base::StringPrintf("content-length:%d", 1 << 30));
432 ASSERT_TRUE(RunLoopWithTimeout(&run_loop
));
433 ASSERT_EQ(0u, requests_
.size());
436 TEST_F(HttpServerTest
, Send200
) {
437 TestHttpClient client
;
438 ASSERT_EQ(OK
, client
.ConnectAndWait(server_address_
));
439 client
.Send("GET /test HTTP/1.1\r\n\r\n");
440 ASSERT_TRUE(RunUntilRequestsReceived(1));
441 server_
->Send200(GetConnectionId(0), "Response!", "text/plain");
443 std::string response
;
444 ASSERT_TRUE(client
.ReadResponse(&response
));
445 ASSERT_TRUE(base::StartsWith(response
, "HTTP/1.1 200 OK",
446 base::CompareCase::SENSITIVE
));
448 base::EndsWith(response
, "Response!", base::CompareCase::SENSITIVE
));
451 TEST_F(HttpServerTest
, SendRaw
) {
452 TestHttpClient client
;
453 ASSERT_EQ(OK
, client
.ConnectAndWait(server_address_
));
454 client
.Send("GET /test HTTP/1.1\r\n\r\n");
455 ASSERT_TRUE(RunUntilRequestsReceived(1));
456 server_
->SendRaw(GetConnectionId(0), "Raw Data ");
457 server_
->SendRaw(GetConnectionId(0), "More Data");
458 server_
->SendRaw(GetConnectionId(0), "Third Piece of Data");
460 const std::string
expected_response("Raw Data More DataThird Piece of Data");
461 std::string response
;
462 ASSERT_TRUE(client
.Read(&response
, expected_response
.length()));
463 ASSERT_EQ(expected_response
, response
);
466 class MockStreamSocket
: public StreamSocket
{
474 int Connect(const CompletionCallback
& callback
) override
{
475 return ERR_NOT_IMPLEMENTED
;
477 void Disconnect() override
{
479 if (!read_callback_
.is_null()) {
482 base::ResetAndReturn(&read_callback_
).Run(ERR_CONNECTION_CLOSED
);
485 bool IsConnected() const override
{ return connected_
; }
486 bool IsConnectedAndIdle() const override
{ return IsConnected(); }
487 int GetPeerAddress(IPEndPoint
* address
) const override
{
488 return ERR_NOT_IMPLEMENTED
;
490 int GetLocalAddress(IPEndPoint
* address
) const override
{
491 return ERR_NOT_IMPLEMENTED
;
493 const BoundNetLog
& NetLog() const override
{ return net_log_
; }
494 void SetSubresourceSpeculation() override
{}
495 void SetOmniboxSpeculation() override
{}
496 bool WasEverUsed() const override
{ return true; }
497 bool UsingTCPFastOpen() const override
{ return false; }
498 bool WasNpnNegotiated() const override
{ return false; }
499 NextProto
GetNegotiatedProtocol() const override
{ return kProtoUnknown
; }
500 bool GetSSLInfo(SSLInfo
* ssl_info
) override
{ return false; }
501 void GetConnectionAttempts(ConnectionAttempts
* out
) const override
{
504 void ClearConnectionAttempts() override
{}
505 void AddConnectionAttempts(const ConnectionAttempts
& attempts
) override
{}
508 int Read(IOBuffer
* buf
,
510 const CompletionCallback
& callback
) override
{
512 return ERR_SOCKET_NOT_CONNECTED
;
514 if (pending_read_data_
.empty()) {
516 read_buf_len_
= buf_len
;
517 read_callback_
= callback
;
518 return ERR_IO_PENDING
;
520 DCHECK_GT(buf_len
, 0);
521 int read_len
= std::min(static_cast<int>(pending_read_data_
.size()),
523 memcpy(buf
->data(), pending_read_data_
.data(), read_len
);
524 pending_read_data_
.erase(0, read_len
);
527 int Write(IOBuffer
* buf
,
529 const CompletionCallback
& callback
) override
{
530 return ERR_NOT_IMPLEMENTED
;
532 int SetReceiveBufferSize(int32 size
) override
{ return ERR_NOT_IMPLEMENTED
; }
533 int SetSendBufferSize(int32 size
) override
{ return ERR_NOT_IMPLEMENTED
; }
535 void DidRead(const char* data
, int data_len
) {
536 if (!read_buf_
.get()) {
537 pending_read_data_
.append(data
, data_len
);
540 int read_len
= std::min(data_len
, read_buf_len_
);
541 memcpy(read_buf_
->data(), data
, read_len
);
542 pending_read_data_
.assign(data
+ read_len
, data_len
- read_len
);
545 base::ResetAndReturn(&read_callback_
).Run(read_len
);
549 ~MockStreamSocket() override
{}
552 scoped_refptr
<IOBuffer
> read_buf_
;
554 CompletionCallback read_callback_
;
555 std::string pending_read_data_
;
556 BoundNetLog net_log_
;
558 DISALLOW_COPY_AND_ASSIGN(MockStreamSocket
);
561 TEST_F(HttpServerTest
, RequestWithBodySplitAcrossPackets
) {
562 MockStreamSocket
* socket
= new MockStreamSocket();
563 HandleAcceptResult(make_scoped_ptr
<StreamSocket
>(socket
));
564 std::string
body("body");
565 std::string request_text
= base::StringPrintf(
566 "GET /test HTTP/1.1\r\n"
568 "Content-Length: %" PRIuS
"\r\n\r\n%s",
571 socket
->DidRead(request_text
.c_str(), request_text
.length() - 2);
572 ASSERT_EQ(0u, requests_
.size());
573 socket
->DidRead(request_text
.c_str() + request_text
.length() - 2, 2);
574 ASSERT_EQ(1u, requests_
.size());
575 ASSERT_EQ(body
, GetRequest(0).data
);
578 TEST_F(HttpServerTest
, MultipleRequestsOnSameConnection
) {
579 // The idea behind this test is that requests with or without bodies should
580 // not break parsing of the next request.
581 TestHttpClient client
;
582 ASSERT_EQ(OK
, client
.ConnectAndWait(server_address_
));
583 std::string body
= "body";
584 client
.Send(base::StringPrintf(
585 "GET /test HTTP/1.1\r\n"
586 "Content-Length: %" PRIuS
"\r\n\r\n%s",
589 ASSERT_TRUE(RunUntilRequestsReceived(1));
590 ASSERT_EQ(body
, GetRequest(0).data
);
592 int client_connection_id
= GetConnectionId(0);
593 server_
->Send200(client_connection_id
, "Content for /test", "text/plain");
594 std::string response1
;
595 ASSERT_TRUE(client
.ReadResponse(&response1
));
596 ASSERT_TRUE(base::StartsWith(response1
, "HTTP/1.1 200 OK",
597 base::CompareCase::SENSITIVE
));
598 ASSERT_TRUE(base::EndsWith(response1
, "Content for /test",
599 base::CompareCase::SENSITIVE
));
601 client
.Send("GET /test2 HTTP/1.1\r\n\r\n");
602 ASSERT_TRUE(RunUntilRequestsReceived(2));
603 ASSERT_EQ("/test2", GetRequest(1).path
);
605 ASSERT_EQ(client_connection_id
, GetConnectionId(1));
606 server_
->Send404(client_connection_id
);
607 std::string response2
;
608 ASSERT_TRUE(client
.ReadResponse(&response2
));
609 ASSERT_TRUE(base::StartsWith(response2
, "HTTP/1.1 404 Not Found",
610 base::CompareCase::SENSITIVE
));
612 client
.Send("GET /test3 HTTP/1.1\r\n\r\n");
613 ASSERT_TRUE(RunUntilRequestsReceived(3));
614 ASSERT_EQ("/test3", GetRequest(2).path
);
616 ASSERT_EQ(client_connection_id
, GetConnectionId(2));
617 server_
->Send200(client_connection_id
, "Content for /test3", "text/plain");
618 std::string response3
;
619 ASSERT_TRUE(client
.ReadResponse(&response3
));
620 ASSERT_TRUE(base::StartsWith(response3
, "HTTP/1.1 200 OK",
621 base::CompareCase::SENSITIVE
));
622 ASSERT_TRUE(base::EndsWith(response3
, "Content for /test3",
623 base::CompareCase::SENSITIVE
));
626 class CloseOnConnectHttpServerTest
: public HttpServerTest
{
628 void OnConnect(int connection_id
) override
{
629 connection_ids_
.push_back(connection_id
);
630 server_
->Close(connection_id
);
634 std::vector
<int> connection_ids_
;
637 TEST_F(CloseOnConnectHttpServerTest
, ServerImmediatelyClosesConnection
) {
638 TestHttpClient client
;
639 ASSERT_EQ(OK
, client
.ConnectAndWait(server_address_
));
640 client
.Send("GET / HTTP/1.1\r\n\r\n");
641 ASSERT_FALSE(RunUntilRequestsReceived(1));
642 ASSERT_EQ(1ul, connection_ids_
.size());
643 ASSERT_EQ(0ul, requests_
.size());