Update SplitString calls to new form
[chromium-blink-merge.git] / net / server / http_server_unittest.cc
blob8830e3f48f40ae55330ac648884761ec5c5da70d
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.
5 #include <algorithm>
6 #include <utility>
7 #include <vector>
9 #include "base/bind.h"
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"
45 namespace net {
47 namespace {
49 const int kMaxExpectedResponseLength = 2048;
51 void SetTimedOutAndQuitLoop(const base::WeakPtr<bool> timed_out,
52 const base::Closure& quit_loop_func) {
53 if (timed_out) {
54 *timed_out = true;
55 quit_loop_func.Run();
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(
63 FROM_HERE,
64 base::Bind(&SetTimedOutAndQuitLoop, timed_out_weak_factory.GetWeakPtr(),
65 run_loop->QuitClosure()),
66 base::TimeDelta::FromSeconds(1));
67 run_loop->Run();
68 return !timed_out;
71 class TestHttpClient {
72 public:
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))
88 return ERR_TIMED_OUT;
89 return connect_result_;
92 void Send(const std::string& data) {
93 write_buffer_ =
94 new DrainableIOBuffer(new StringIOBuffer(data), data.length());
95 Write();
98 bool Read(std::string* message, int expected_bytes) {
99 int total_bytes_received = 0;
100 message->clear();
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)
106 return false;
108 total_bytes_received += bytes_received;
109 message->append(read_buffer_->data(), bytes_received);
111 return true;
114 bool ReadResponse(std::string* message) {
115 if (!Read(message, 1))
116 return false;
117 while (!IsCompleteResponse(*message)) {
118 std::string chunk;
119 if (!Read(&chunk, 1))
120 return false;
121 message->append(chunk);
123 return true;
126 private:
127 void OnConnect(const base::Closure& quit_loop, int result) {
128 connect_result_ = result;
129 quit_loop.Run();
132 void Write() {
133 int result = socket_->Write(
134 write_buffer_.get(),
135 write_buffer_->BytesRemaining(),
136 base::Bind(&TestHttpClient::OnWrite, base::Unretained(this)));
137 if (result != ERR_IO_PENDING)
138 OnWrite(result);
141 void OnWrite(int result) {
142 ASSERT_GT(result, 0);
143 write_buffer_->DidConsume(result);
144 if (write_buffer_->BytesRemaining())
145 Write();
148 void ReadInternal(const CompletionCallback& callback) {
149 read_buffer_ = new IOBufferWithSize(kMaxExpectedResponseLength);
150 int result =
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(),
159 response.size());
160 if (end_of_headers < 0)
161 return false;
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_;
174 int connect_result_;
177 } // namespace
179 class HttpServerTest : public testing::Test,
180 public HttpServer::Delegate {
181 public:
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 {
203 NOTREACHED();
206 void OnWebSocketMessage(int connection_id, const std::string& data) override {
207 NOTREACHED();
210 void OnClose(int connection_id) override {}
212 bool RunUntilRequestsReceived(size_t count) {
213 quit_after_request_count_ = count;
214 if (requests_.size() == count)
215 return true;
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();
221 return success;
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);
237 protected:
238 scoped_ptr<HttpServer> server_;
239 IPEndPoint server_address_;
240 base::Closure run_loop_quit_func_;
241 std::vector<std::pair<HttpServerRequestInfo, int> > requests_;
243 private:
244 size_t quit_after_request_count_;
247 namespace {
249 class WebSocketTest : public HttpServerTest {
250 void OnHttpRequest(int connection_id,
251 const HttpServerRequestInfo& info) override {
252 NOTREACHED();
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"},
289 std::string headers;
290 for (size_t i = 0; i < arraysize(kHeaders); ++i) {
291 headers +=
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::StringToLowerASCII(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"},
317 std::string headers;
318 for (size_t i = 0; i < arraysize(kHeaders); ++i) {
319 headers +=
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::StringToLowerASCII(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[] = {
339 "Header: Abcd",
340 "HeaderWithNoWhitespace:E",
341 "HeaderWithWhitespace : \t f \t ",
342 "DuplicateHeader: g",
343 "HeaderWithComma: h, i ,j",
344 "DuplicateHeader: k",
345 "EmptyHeader:",
346 "EmptyHeaderWithWhitespace: \t ",
347 "HeaderWithNonASCII: \xf7",
349 std::string headers;
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"
378 "SomeHeader: 1\r\n"
379 "Content-Length: %" PRIuS "\r\n\r\n%s",
380 body.length(),
381 body.c_str()));
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_));
392 client.Send(
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"
398 "\r\n");
399 ASSERT_TRUE(RunUntilRequestsReceived(1));
402 TEST_F(HttpServerTest, RequestWithTooLargeBody) {
403 class TestURLFetcherDelegate : public URLFetcherDelegate {
404 public:
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();
414 private:
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));
430 fetcher->Start();
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));
447 ASSERT_TRUE(
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 {
467 public:
468 MockStreamSocket()
469 : connected_(true),
470 read_buf_(NULL),
471 read_buf_len_(0) {}
473 // StreamSocket
474 int Connect(const CompletionCallback& callback) override {
475 return ERR_NOT_IMPLEMENTED;
477 void Disconnect() override {
478 connected_ = false;
479 if (!read_callback_.is_null()) {
480 read_buf_ = NULL;
481 read_buf_len_ = 0;
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 {
502 out->clear();
504 void ClearConnectionAttempts() override {}
505 void AddConnectionAttempts(const ConnectionAttempts& attempts) override {}
507 // Socket
508 int Read(IOBuffer* buf,
509 int buf_len,
510 const CompletionCallback& callback) override {
511 if (!connected_) {
512 return ERR_SOCKET_NOT_CONNECTED;
514 if (pending_read_data_.empty()) {
515 read_buf_ = buf;
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()),
522 buf_len);
523 memcpy(buf->data(), pending_read_data_.data(), read_len);
524 pending_read_data_.erase(0, read_len);
525 return read_len;
527 int Write(IOBuffer* buf,
528 int buf_len,
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);
538 return;
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);
543 read_buf_ = NULL;
544 read_buf_len_ = 0;
545 base::ResetAndReturn(&read_callback_).Run(read_len);
548 private:
549 ~MockStreamSocket() override {}
551 bool connected_;
552 scoped_refptr<IOBuffer> read_buf_;
553 int read_buf_len_;
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"
567 "SomeHeader: 1\r\n"
568 "Content-Length: %" PRIuS "\r\n\r\n%s",
569 body.length(),
570 body.c_str());
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",
587 body.length(),
588 body.c_str()));
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 {
627 public:
628 void OnConnect(int connection_id) override {
629 connection_ids_.push_back(connection_id);
630 server_->Close(connection_id);
633 protected:
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());
646 } // namespace
648 } // namespace net