| Index: net/server/http_server_unittest.cc
|
| diff --git a/net/server/http_server_unittest.cc b/net/server/http_server_unittest.cc
|
| deleted file mode 100644
|
| index aaad7b85816fa4b6ef53fbd6c8a8df841115a086..0000000000000000000000000000000000000000
|
| --- a/net/server/http_server_unittest.cc
|
| +++ /dev/null
|
| @@ -1,638 +0,0 @@
|
| -// Copyright 2013 The Chromium Authors. All rights reserved.
|
| -// Use of this source code is governed by a BSD-style license that can be
|
| -// found in the LICENSE file.
|
| -
|
| -#include <algorithm>
|
| -#include <utility>
|
| -#include <vector>
|
| -
|
| -#include "base/bind.h"
|
| -#include "base/bind_helpers.h"
|
| -#include "base/callback_helpers.h"
|
| -#include "base/compiler_specific.h"
|
| -#include "base/format_macros.h"
|
| -#include "base/memory/ref_counted.h"
|
| -#include "base/memory/scoped_ptr.h"
|
| -#include "base/memory/weak_ptr.h"
|
| -#include "base/message_loop/message_loop.h"
|
| -#include "base/message_loop/message_loop_proxy.h"
|
| -#include "base/run_loop.h"
|
| -#include "base/strings/string_split.h"
|
| -#include "base/strings/string_util.h"
|
| -#include "base/strings/stringprintf.h"
|
| -#include "base/time/time.h"
|
| -#include "net/base/address_list.h"
|
| -#include "net/base/io_buffer.h"
|
| -#include "net/base/ip_endpoint.h"
|
| -#include "net/base/net_errors.h"
|
| -#include "net/base/net_log.h"
|
| -#include "net/base/net_util.h"
|
| -#include "net/base/test_completion_callback.h"
|
| -#include "net/http/http_response_headers.h"
|
| -#include "net/http/http_util.h"
|
| -#include "net/server/http_server.h"
|
| -#include "net/server/http_server_request_info.h"
|
| -#include "net/socket/tcp_client_socket.h"
|
| -#include "net/socket/tcp_server_socket.h"
|
| -#include "net/url_request/url_fetcher.h"
|
| -#include "net/url_request/url_fetcher_delegate.h"
|
| -#include "net/url_request/url_request_context.h"
|
| -#include "net/url_request/url_request_context_getter.h"
|
| -#include "net/url_request/url_request_test_util.h"
|
| -#include "testing/gtest/include/gtest/gtest.h"
|
| -
|
| -namespace net {
|
| -
|
| -namespace {
|
| -
|
| -const int kMaxExpectedResponseLength = 2048;
|
| -
|
| -void SetTimedOutAndQuitLoop(const base::WeakPtr<bool> timed_out,
|
| - const base::Closure& quit_loop_func) {
|
| - if (timed_out) {
|
| - *timed_out = true;
|
| - quit_loop_func.Run();
|
| - }
|
| -}
|
| -
|
| -bool RunLoopWithTimeout(base::RunLoop* run_loop) {
|
| - bool timed_out = false;
|
| - base::WeakPtrFactory<bool> timed_out_weak_factory(&timed_out);
|
| - base::MessageLoop::current()->PostDelayedTask(
|
| - FROM_HERE,
|
| - base::Bind(&SetTimedOutAndQuitLoop,
|
| - timed_out_weak_factory.GetWeakPtr(),
|
| - run_loop->QuitClosure()),
|
| - base::TimeDelta::FromSeconds(1));
|
| - run_loop->Run();
|
| - return !timed_out;
|
| -}
|
| -
|
| -class TestHttpClient {
|
| - public:
|
| - TestHttpClient() : connect_result_(OK) {}
|
| -
|
| - int ConnectAndWait(const IPEndPoint& address) {
|
| - AddressList addresses(address);
|
| - NetLog::Source source;
|
| - socket_.reset(new TCPClientSocket(addresses, NULL, source));
|
| -
|
| - base::RunLoop run_loop;
|
| - connect_result_ = socket_->Connect(base::Bind(&TestHttpClient::OnConnect,
|
| - base::Unretained(this),
|
| - run_loop.QuitClosure()));
|
| - if (connect_result_ != OK && connect_result_ != ERR_IO_PENDING)
|
| - return connect_result_;
|
| -
|
| - if (!RunLoopWithTimeout(&run_loop))
|
| - return ERR_TIMED_OUT;
|
| - return connect_result_;
|
| - }
|
| -
|
| - void Send(const std::string& data) {
|
| - write_buffer_ =
|
| - new DrainableIOBuffer(new StringIOBuffer(data), data.length());
|
| - Write();
|
| - }
|
| -
|
| - bool Read(std::string* message, int expected_bytes) {
|
| - int total_bytes_received = 0;
|
| - message->clear();
|
| - while (total_bytes_received < expected_bytes) {
|
| - net::TestCompletionCallback callback;
|
| - ReadInternal(callback.callback());
|
| - int bytes_received = callback.WaitForResult();
|
| - if (bytes_received <= 0)
|
| - return false;
|
| -
|
| - total_bytes_received += bytes_received;
|
| - message->append(read_buffer_->data(), bytes_received);
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - bool ReadResponse(std::string* message) {
|
| - if (!Read(message, 1))
|
| - return false;
|
| - while (!IsCompleteResponse(*message)) {
|
| - std::string chunk;
|
| - if (!Read(&chunk, 1))
|
| - return false;
|
| - message->append(chunk);
|
| - }
|
| - return true;
|
| - }
|
| -
|
| - private:
|
| - void OnConnect(const base::Closure& quit_loop, int result) {
|
| - connect_result_ = result;
|
| - quit_loop.Run();
|
| - }
|
| -
|
| - void Write() {
|
| - int result = socket_->Write(
|
| - write_buffer_.get(),
|
| - write_buffer_->BytesRemaining(),
|
| - base::Bind(&TestHttpClient::OnWrite, base::Unretained(this)));
|
| - if (result != ERR_IO_PENDING)
|
| - OnWrite(result);
|
| - }
|
| -
|
| - void OnWrite(int result) {
|
| - ASSERT_GT(result, 0);
|
| - write_buffer_->DidConsume(result);
|
| - if (write_buffer_->BytesRemaining())
|
| - Write();
|
| - }
|
| -
|
| - void ReadInternal(const net::CompletionCallback& callback) {
|
| - read_buffer_ = new IOBufferWithSize(kMaxExpectedResponseLength);
|
| - int result =
|
| - socket_->Read(read_buffer_.get(), kMaxExpectedResponseLength, callback);
|
| - if (result != ERR_IO_PENDING)
|
| - callback.Run(result);
|
| - }
|
| -
|
| - bool IsCompleteResponse(const std::string& response) {
|
| - // Check end of headers first.
|
| - int end_of_headers = HttpUtil::LocateEndOfHeaders(response.data(),
|
| - response.size());
|
| - if (end_of_headers < 0)
|
| - return false;
|
| -
|
| - // Return true if response has data equal to or more than content length.
|
| - int64 body_size = static_cast<int64>(response.size()) - end_of_headers;
|
| - DCHECK_LE(0, body_size);
|
| - scoped_refptr<HttpResponseHeaders> headers(new HttpResponseHeaders(
|
| - HttpUtil::AssembleRawHeaders(response.data(), end_of_headers)));
|
| - return body_size >= headers->GetContentLength();
|
| - }
|
| -
|
| - scoped_refptr<IOBufferWithSize> read_buffer_;
|
| - scoped_refptr<DrainableIOBuffer> write_buffer_;
|
| - scoped_ptr<TCPClientSocket> socket_;
|
| - int connect_result_;
|
| -};
|
| -
|
| -} // namespace
|
| -
|
| -class HttpServerTest : public testing::Test,
|
| - public HttpServer::Delegate {
|
| - public:
|
| - HttpServerTest() : quit_after_request_count_(0) {}
|
| -
|
| - void SetUp() override {
|
| - scoped_ptr<ServerSocket> server_socket(
|
| - new TCPServerSocket(NULL, net::NetLog::Source()));
|
| - server_socket->ListenWithAddressAndPort("127.0.0.1", 0, 1);
|
| - server_.reset(new HttpServer(server_socket.Pass(), this));
|
| - ASSERT_EQ(OK, server_->GetLocalAddress(&server_address_));
|
| - }
|
| -
|
| - void OnConnect(int connection_id) override {}
|
| -
|
| - void OnHttpRequest(int connection_id,
|
| - const HttpServerRequestInfo& info) override {
|
| - requests_.push_back(std::make_pair(info, connection_id));
|
| - if (requests_.size() == quit_after_request_count_)
|
| - run_loop_quit_func_.Run();
|
| - }
|
| -
|
| - void OnWebSocketRequest(int connection_id,
|
| - const HttpServerRequestInfo& info) override {
|
| - NOTREACHED();
|
| - }
|
| -
|
| - void OnWebSocketMessage(int connection_id, const std::string& data) override {
|
| - NOTREACHED();
|
| - }
|
| -
|
| - void OnClose(int connection_id) override {}
|
| -
|
| - bool RunUntilRequestsReceived(size_t count) {
|
| - quit_after_request_count_ = count;
|
| - if (requests_.size() == count)
|
| - return true;
|
| -
|
| - base::RunLoop run_loop;
|
| - run_loop_quit_func_ = run_loop.QuitClosure();
|
| - bool success = RunLoopWithTimeout(&run_loop);
|
| - run_loop_quit_func_.Reset();
|
| - return success;
|
| - }
|
| -
|
| - HttpServerRequestInfo GetRequest(size_t request_index) {
|
| - return requests_[request_index].first;
|
| - }
|
| -
|
| - int GetConnectionId(size_t request_index) {
|
| - return requests_[request_index].second;
|
| - }
|
| -
|
| - void HandleAcceptResult(scoped_ptr<StreamSocket> socket) {
|
| - server_->accepted_socket_.reset(socket.release());
|
| - server_->HandleAcceptResult(OK);
|
| - }
|
| -
|
| - protected:
|
| - scoped_ptr<HttpServer> server_;
|
| - IPEndPoint server_address_;
|
| - base::Closure run_loop_quit_func_;
|
| - std::vector<std::pair<HttpServerRequestInfo, int> > requests_;
|
| -
|
| - private:
|
| - size_t quit_after_request_count_;
|
| -};
|
| -
|
| -namespace {
|
| -
|
| -class WebSocketTest : public HttpServerTest {
|
| - void OnHttpRequest(int connection_id,
|
| - const HttpServerRequestInfo& info) override {
|
| - NOTREACHED();
|
| - }
|
| -
|
| - void OnWebSocketRequest(int connection_id,
|
| - const HttpServerRequestInfo& info) override {
|
| - HttpServerTest::OnHttpRequest(connection_id, info);
|
| - }
|
| -
|
| - void OnWebSocketMessage(int connection_id, const std::string& data) override {
|
| - }
|
| -};
|
| -
|
| -TEST_F(HttpServerTest, Request) {
|
| - TestHttpClient client;
|
| - ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
|
| - client.Send("GET /test HTTP/1.1\r\n\r\n");
|
| - ASSERT_TRUE(RunUntilRequestsReceived(1));
|
| - ASSERT_EQ("GET", GetRequest(0).method);
|
| - ASSERT_EQ("/test", GetRequest(0).path);
|
| - ASSERT_EQ("", GetRequest(0).data);
|
| - ASSERT_EQ(0u, GetRequest(0).headers.size());
|
| - ASSERT_TRUE(StartsWithASCII(GetRequest(0).peer.ToString(),
|
| - "127.0.0.1",
|
| - true));
|
| -}
|
| -
|
| -TEST_F(HttpServerTest, RequestWithHeaders) {
|
| - TestHttpClient client;
|
| - ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
|
| - const char* const kHeaders[][3] = {
|
| - {"Header", ": ", "1"},
|
| - {"HeaderWithNoWhitespace", ":", "1"},
|
| - {"HeaderWithWhitespace", " : \t ", "1 1 1 \t "},
|
| - {"HeaderWithColon", ": ", "1:1"},
|
| - {"EmptyHeader", ":", ""},
|
| - {"EmptyHeaderWithWhitespace", ": \t ", ""},
|
| - {"HeaderWithNonASCII", ": ", "\xf7"},
|
| - };
|
| - std::string headers;
|
| - for (size_t i = 0; i < arraysize(kHeaders); ++i) {
|
| - headers +=
|
| - std::string(kHeaders[i][0]) + kHeaders[i][1] + kHeaders[i][2] + "\r\n";
|
| - }
|
| -
|
| - client.Send("GET /test HTTP/1.1\r\n" + headers + "\r\n");
|
| - ASSERT_TRUE(RunUntilRequestsReceived(1));
|
| - ASSERT_EQ("", GetRequest(0).data);
|
| -
|
| - for (size_t i = 0; i < arraysize(kHeaders); ++i) {
|
| - std::string field = base::StringToLowerASCII(std::string(kHeaders[i][0]));
|
| - std::string value = kHeaders[i][2];
|
| - ASSERT_EQ(1u, GetRequest(0).headers.count(field)) << field;
|
| - ASSERT_EQ(value, GetRequest(0).headers[field]) << kHeaders[i][0];
|
| - }
|
| -}
|
| -
|
| -TEST_F(HttpServerTest, RequestWithDuplicateHeaders) {
|
| - TestHttpClient client;
|
| - ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
|
| - const char* const kHeaders[][3] = {
|
| - {"FirstHeader", ": ", "1"},
|
| - {"DuplicateHeader", ": ", "2"},
|
| - {"MiddleHeader", ": ", "3"},
|
| - {"DuplicateHeader", ": ", "4"},
|
| - {"LastHeader", ": ", "5"},
|
| - };
|
| - std::string headers;
|
| - for (size_t i = 0; i < arraysize(kHeaders); ++i) {
|
| - headers +=
|
| - std::string(kHeaders[i][0]) + kHeaders[i][1] + kHeaders[i][2] + "\r\n";
|
| - }
|
| -
|
| - client.Send("GET /test HTTP/1.1\r\n" + headers + "\r\n");
|
| - ASSERT_TRUE(RunUntilRequestsReceived(1));
|
| - ASSERT_EQ("", GetRequest(0).data);
|
| -
|
| - for (size_t i = 0; i < arraysize(kHeaders); ++i) {
|
| - std::string field = base::StringToLowerASCII(std::string(kHeaders[i][0]));
|
| - std::string value = (field == "duplicateheader") ? "2,4" : kHeaders[i][2];
|
| - ASSERT_EQ(1u, GetRequest(0).headers.count(field)) << field;
|
| - ASSERT_EQ(value, GetRequest(0).headers[field]) << kHeaders[i][0];
|
| - }
|
| -}
|
| -
|
| -TEST_F(HttpServerTest, HasHeaderValueTest) {
|
| - TestHttpClient client;
|
| - ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
|
| - const char* const kHeaders[] = {
|
| - "Header: Abcd",
|
| - "HeaderWithNoWhitespace:E",
|
| - "HeaderWithWhitespace : \t f \t ",
|
| - "DuplicateHeader: g",
|
| - "HeaderWithComma: h, i ,j",
|
| - "DuplicateHeader: k",
|
| - "EmptyHeader:",
|
| - "EmptyHeaderWithWhitespace: \t ",
|
| - "HeaderWithNonASCII: \xf7",
|
| - };
|
| - std::string headers;
|
| - for (size_t i = 0; i < arraysize(kHeaders); ++i) {
|
| - headers += std::string(kHeaders[i]) + "\r\n";
|
| - }
|
| -
|
| - client.Send("GET /test HTTP/1.1\r\n" + headers + "\r\n");
|
| - ASSERT_TRUE(RunUntilRequestsReceived(1));
|
| - ASSERT_EQ("", GetRequest(0).data);
|
| -
|
| - ASSERT_TRUE(GetRequest(0).HasHeaderValue("header", "abcd"));
|
| - ASSERT_FALSE(GetRequest(0).HasHeaderValue("header", "bc"));
|
| - ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithnowhitespace", "e"));
|
| - ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithwhitespace", "f"));
|
| - ASSERT_TRUE(GetRequest(0).HasHeaderValue("duplicateheader", "g"));
|
| - ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithcomma", "h"));
|
| - ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithcomma", "i"));
|
| - ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithcomma", "j"));
|
| - ASSERT_TRUE(GetRequest(0).HasHeaderValue("duplicateheader", "k"));
|
| - ASSERT_FALSE(GetRequest(0).HasHeaderValue("emptyheader", "x"));
|
| - ASSERT_FALSE(GetRequest(0).HasHeaderValue("emptyheaderwithwhitespace", "x"));
|
| - ASSERT_TRUE(GetRequest(0).HasHeaderValue("headerwithnonascii", "\xf7"));
|
| -}
|
| -
|
| -TEST_F(HttpServerTest, RequestWithBody) {
|
| - TestHttpClient client;
|
| - ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
|
| - std::string body = "a" + std::string(1 << 10, 'b') + "c";
|
| - client.Send(base::StringPrintf(
|
| - "GET /test HTTP/1.1\r\n"
|
| - "SomeHeader: 1\r\n"
|
| - "Content-Length: %" PRIuS "\r\n\r\n%s",
|
| - body.length(),
|
| - body.c_str()));
|
| - ASSERT_TRUE(RunUntilRequestsReceived(1));
|
| - ASSERT_EQ(2u, GetRequest(0).headers.size());
|
| - ASSERT_EQ(body.length(), GetRequest(0).data.length());
|
| - ASSERT_EQ('a', body[0]);
|
| - ASSERT_EQ('c', *body.rbegin());
|
| -}
|
| -
|
| -TEST_F(WebSocketTest, RequestWebSocket) {
|
| - TestHttpClient client;
|
| - ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
|
| - client.Send(
|
| - "GET /test HTTP/1.1\r\n"
|
| - "Upgrade: WebSocket\r\n"
|
| - "Connection: SomethingElse, Upgrade\r\n"
|
| - "Sec-WebSocket-Version: 8\r\n"
|
| - "Sec-WebSocket-Key: key\r\n"
|
| - "\r\n");
|
| - ASSERT_TRUE(RunUntilRequestsReceived(1));
|
| -}
|
| -
|
| -TEST_F(HttpServerTest, RequestWithTooLargeBody) {
|
| - class TestURLFetcherDelegate : public URLFetcherDelegate {
|
| - public:
|
| - TestURLFetcherDelegate(const base::Closure& quit_loop_func)
|
| - : quit_loop_func_(quit_loop_func) {}
|
| - ~TestURLFetcherDelegate() override {}
|
| -
|
| - void OnURLFetchComplete(const URLFetcher* source) override {
|
| - EXPECT_EQ(HTTP_INTERNAL_SERVER_ERROR, source->GetResponseCode());
|
| - quit_loop_func_.Run();
|
| - }
|
| -
|
| - private:
|
| - base::Closure quit_loop_func_;
|
| - };
|
| -
|
| - base::RunLoop run_loop;
|
| - TestURLFetcherDelegate delegate(run_loop.QuitClosure());
|
| -
|
| - scoped_refptr<URLRequestContextGetter> request_context_getter(
|
| - new TestURLRequestContextGetter(base::MessageLoopProxy::current()));
|
| - scoped_ptr<URLFetcher> fetcher(
|
| - URLFetcher::Create(GURL(base::StringPrintf("http://127.0.0.1:%d/test",
|
| - server_address_.port())),
|
| - URLFetcher::GET,
|
| - &delegate));
|
| - fetcher->SetRequestContext(request_context_getter.get());
|
| - fetcher->AddExtraRequestHeader(
|
| - base::StringPrintf("content-length:%d", 1 << 30));
|
| - fetcher->Start();
|
| -
|
| - ASSERT_TRUE(RunLoopWithTimeout(&run_loop));
|
| - ASSERT_EQ(0u, requests_.size());
|
| -}
|
| -
|
| -TEST_F(HttpServerTest, Send200) {
|
| - TestHttpClient client;
|
| - ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
|
| - client.Send("GET /test HTTP/1.1\r\n\r\n");
|
| - ASSERT_TRUE(RunUntilRequestsReceived(1));
|
| - server_->Send200(GetConnectionId(0), "Response!", "text/plain");
|
| -
|
| - std::string response;
|
| - ASSERT_TRUE(client.ReadResponse(&response));
|
| - ASSERT_TRUE(StartsWithASCII(response, "HTTP/1.1 200 OK", true));
|
| - ASSERT_TRUE(EndsWith(response, "Response!", true));
|
| -}
|
| -
|
| -TEST_F(HttpServerTest, SendRaw) {
|
| - TestHttpClient client;
|
| - ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
|
| - client.Send("GET /test HTTP/1.1\r\n\r\n");
|
| - ASSERT_TRUE(RunUntilRequestsReceived(1));
|
| - server_->SendRaw(GetConnectionId(0), "Raw Data ");
|
| - server_->SendRaw(GetConnectionId(0), "More Data");
|
| - server_->SendRaw(GetConnectionId(0), "Third Piece of Data");
|
| -
|
| - const std::string expected_response("Raw Data More DataThird Piece of Data");
|
| - std::string response;
|
| - ASSERT_TRUE(client.Read(&response, expected_response.length()));
|
| - ASSERT_EQ(expected_response, response);
|
| -}
|
| -
|
| -class MockStreamSocket : public StreamSocket {
|
| - public:
|
| - MockStreamSocket()
|
| - : connected_(true),
|
| - read_buf_(NULL),
|
| - read_buf_len_(0) {}
|
| -
|
| - // StreamSocket
|
| - int Connect(const CompletionCallback& callback) override {
|
| - return ERR_NOT_IMPLEMENTED;
|
| - }
|
| - void Disconnect() override {
|
| - connected_ = false;
|
| - if (!read_callback_.is_null()) {
|
| - read_buf_ = NULL;
|
| - read_buf_len_ = 0;
|
| - base::ResetAndReturn(&read_callback_).Run(ERR_CONNECTION_CLOSED);
|
| - }
|
| - }
|
| - bool IsConnected() const override { return connected_; }
|
| - bool IsConnectedAndIdle() const override { return IsConnected(); }
|
| - int GetPeerAddress(IPEndPoint* address) const override {
|
| - return ERR_NOT_IMPLEMENTED;
|
| - }
|
| - int GetLocalAddress(IPEndPoint* address) const override {
|
| - return ERR_NOT_IMPLEMENTED;
|
| - }
|
| - const BoundNetLog& NetLog() const override { return net_log_; }
|
| - void SetSubresourceSpeculation() override {}
|
| - void SetOmniboxSpeculation() override {}
|
| - bool WasEverUsed() const override { return true; }
|
| - bool UsingTCPFastOpen() const override { return false; }
|
| - bool WasNpnNegotiated() const override { return false; }
|
| - NextProto GetNegotiatedProtocol() const override { return kProtoUnknown; }
|
| - bool GetSSLInfo(SSLInfo* ssl_info) override { return false; }
|
| -
|
| - // Socket
|
| - int Read(IOBuffer* buf,
|
| - int buf_len,
|
| - const CompletionCallback& callback) override {
|
| - if (!connected_) {
|
| - return ERR_SOCKET_NOT_CONNECTED;
|
| - }
|
| - if (pending_read_data_.empty()) {
|
| - read_buf_ = buf;
|
| - read_buf_len_ = buf_len;
|
| - read_callback_ = callback;
|
| - return ERR_IO_PENDING;
|
| - }
|
| - DCHECK_GT(buf_len, 0);
|
| - int read_len = std::min(static_cast<int>(pending_read_data_.size()),
|
| - buf_len);
|
| - memcpy(buf->data(), pending_read_data_.data(), read_len);
|
| - pending_read_data_.erase(0, read_len);
|
| - return read_len;
|
| - }
|
| - int Write(IOBuffer* buf,
|
| - int buf_len,
|
| - const CompletionCallback& callback) override {
|
| - return ERR_NOT_IMPLEMENTED;
|
| - }
|
| - int SetReceiveBufferSize(int32 size) override { return ERR_NOT_IMPLEMENTED; }
|
| - int SetSendBufferSize(int32 size) override { return ERR_NOT_IMPLEMENTED; }
|
| -
|
| - void DidRead(const char* data, int data_len) {
|
| - if (!read_buf_.get()) {
|
| - pending_read_data_.append(data, data_len);
|
| - return;
|
| - }
|
| - int read_len = std::min(data_len, read_buf_len_);
|
| - memcpy(read_buf_->data(), data, read_len);
|
| - pending_read_data_.assign(data + read_len, data_len - read_len);
|
| - read_buf_ = NULL;
|
| - read_buf_len_ = 0;
|
| - base::ResetAndReturn(&read_callback_).Run(read_len);
|
| - }
|
| -
|
| - private:
|
| - ~MockStreamSocket() override {}
|
| -
|
| - bool connected_;
|
| - scoped_refptr<IOBuffer> read_buf_;
|
| - int read_buf_len_;
|
| - CompletionCallback read_callback_;
|
| - std::string pending_read_data_;
|
| - BoundNetLog net_log_;
|
| -
|
| - DISALLOW_COPY_AND_ASSIGN(MockStreamSocket);
|
| -};
|
| -
|
| -TEST_F(HttpServerTest, RequestWithBodySplitAcrossPackets) {
|
| - MockStreamSocket* socket = new MockStreamSocket();
|
| - HandleAcceptResult(make_scoped_ptr<StreamSocket>(socket));
|
| - std::string body("body");
|
| - std::string request_text = base::StringPrintf(
|
| - "GET /test HTTP/1.1\r\n"
|
| - "SomeHeader: 1\r\n"
|
| - "Content-Length: %" PRIuS "\r\n\r\n%s",
|
| - body.length(),
|
| - body.c_str());
|
| - socket->DidRead(request_text.c_str(), request_text.length() - 2);
|
| - ASSERT_EQ(0u, requests_.size());
|
| - socket->DidRead(request_text.c_str() + request_text.length() - 2, 2);
|
| - ASSERT_EQ(1u, requests_.size());
|
| - ASSERT_EQ(body, GetRequest(0).data);
|
| -}
|
| -
|
| -TEST_F(HttpServerTest, MultipleRequestsOnSameConnection) {
|
| - // The idea behind this test is that requests with or without bodies should
|
| - // not break parsing of the next request.
|
| - TestHttpClient client;
|
| - ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
|
| - std::string body = "body";
|
| - client.Send(base::StringPrintf(
|
| - "GET /test HTTP/1.1\r\n"
|
| - "Content-Length: %" PRIuS "\r\n\r\n%s",
|
| - body.length(),
|
| - body.c_str()));
|
| - ASSERT_TRUE(RunUntilRequestsReceived(1));
|
| - ASSERT_EQ(body, GetRequest(0).data);
|
| -
|
| - int client_connection_id = GetConnectionId(0);
|
| - server_->Send200(client_connection_id, "Content for /test", "text/plain");
|
| - std::string response1;
|
| - ASSERT_TRUE(client.ReadResponse(&response1));
|
| - ASSERT_TRUE(StartsWithASCII(response1, "HTTP/1.1 200 OK", true));
|
| - ASSERT_TRUE(EndsWith(response1, "Content for /test", true));
|
| -
|
| - client.Send("GET /test2 HTTP/1.1\r\n\r\n");
|
| - ASSERT_TRUE(RunUntilRequestsReceived(2));
|
| - ASSERT_EQ("/test2", GetRequest(1).path);
|
| -
|
| - ASSERT_EQ(client_connection_id, GetConnectionId(1));
|
| - server_->Send404(client_connection_id);
|
| - std::string response2;
|
| - ASSERT_TRUE(client.ReadResponse(&response2));
|
| - ASSERT_TRUE(StartsWithASCII(response2, "HTTP/1.1 404 Not Found", true));
|
| -
|
| - client.Send("GET /test3 HTTP/1.1\r\n\r\n");
|
| - ASSERT_TRUE(RunUntilRequestsReceived(3));
|
| - ASSERT_EQ("/test3", GetRequest(2).path);
|
| -
|
| - ASSERT_EQ(client_connection_id, GetConnectionId(2));
|
| - server_->Send200(client_connection_id, "Content for /test3", "text/plain");
|
| - std::string response3;
|
| - ASSERT_TRUE(client.ReadResponse(&response3));
|
| - ASSERT_TRUE(StartsWithASCII(response3, "HTTP/1.1 200 OK", true));
|
| - ASSERT_TRUE(EndsWith(response3, "Content for /test3", true));
|
| -}
|
| -
|
| -class CloseOnConnectHttpServerTest : public HttpServerTest {
|
| - public:
|
| - void OnConnect(int connection_id) override {
|
| - connection_ids_.push_back(connection_id);
|
| - server_->Close(connection_id);
|
| - }
|
| -
|
| - protected:
|
| - std::vector<int> connection_ids_;
|
| -};
|
| -
|
| -TEST_F(CloseOnConnectHttpServerTest, ServerImmediatelyClosesConnection) {
|
| - TestHttpClient client;
|
| - ASSERT_EQ(OK, client.ConnectAndWait(server_address_));
|
| - client.Send("GET / HTTP/1.1\r\n\r\n");
|
| - ASSERT_FALSE(RunUntilRequestsReceived(1));
|
| - ASSERT_EQ(1ul, connection_ids_.size());
|
| - ASSERT_EQ(0ul, requests_.size());
|
| -}
|
| -
|
| -} // namespace
|
| -
|
| -} // namespace net
|
|
|