Index: mojo/services/network/http_server_unittest.cc |
diff --git a/mojo/services/network/http_server_unittest.cc b/mojo/services/network/http_server_unittest.cc |
deleted file mode 100644 |
index dc9769b727f9bf7e731de809d043baf0f783e26a..0000000000000000000000000000000000000000 |
--- a/mojo/services/network/http_server_unittest.cc |
+++ /dev/null |
@@ -1,701 +0,0 @@ |
-// Copyright 2015 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 <stddef.h> |
-#include <stdint.h> |
- |
-#include <utility> |
- |
-#include "base/logging.h" |
-#include "base/macros.h" |
-#include "base/memory/linked_ptr.h" |
-#include "base/memory/ref_counted.h" |
-#include "base/memory/scoped_ptr.h" |
-#include "base/run_loop.h" |
-#include "base/strings/string_util.h" |
-#include "base/strings/stringprintf.h" |
-#include "mojo/common/data_pipe_utils.h" |
-#include "mojo/services/network/net_address_type_converters.h" |
-#include "mojo/services/network/public/cpp/web_socket_read_queue.h" |
-#include "mojo/services/network/public/cpp/web_socket_write_queue.h" |
-#include "mojo/services/network/public/interfaces/http_connection.mojom.h" |
-#include "mojo/services/network/public/interfaces/http_message.mojom.h" |
-#include "mojo/services/network/public/interfaces/http_server.mojom.h" |
-#include "mojo/services/network/public/interfaces/net_address.mojom.h" |
-#include "mojo/services/network/public/interfaces/network_service.mojom.h" |
-#include "mojo/services/network/public/interfaces/web_socket.mojom.h" |
-#include "mojo/services/network/public/interfaces/web_socket_factory.mojom.h" |
-#include "mojo/shell/public/cpp/shell_test.h" |
-#include "net/base/io_buffer.h" |
-#include "net/base/net_errors.h" |
-#include "net/base/test_completion_callback.h" |
-#include "net/http/http_response_headers.h" |
-#include "net/http/http_util.h" |
-#include "net/socket/tcp_client_socket.h" |
-#include "testing/gtest/include/gtest/gtest.h" |
- |
-namespace mojo { |
-namespace { |
- |
-const int kMaxExpectedResponseLength = 2048; |
- |
-NetAddressPtr GetLocalHostWithAnyPort() { |
- NetAddressPtr addr(NetAddress::New()); |
- addr->family = NetAddressFamily::IPV4; |
- addr->ipv4 = NetAddressIPv4::New(); |
- addr->ipv4->port = 0; |
- addr->ipv4->addr.resize(4); |
- addr->ipv4->addr[0] = 127; |
- addr->ipv4->addr[1] = 0; |
- addr->ipv4->addr[2] = 0; |
- addr->ipv4->addr[3] = 1; |
- |
- return addr; |
-} |
- |
-using TestHeaders = std::vector<std::pair<std::string, std::string>>; |
- |
-struct TestRequest { |
- std::string method; |
- std::string url; |
- TestHeaders headers; |
- scoped_ptr<std::string> body; |
-}; |
- |
-struct TestResponse { |
- uint32_t status_code; |
- TestHeaders headers; |
- scoped_ptr<std::string> body; |
-}; |
- |
-std::string MakeRequestMessage(const TestRequest& data) { |
- std::string message = data.method + " " + data.url + " HTTP/1.1\r\n"; |
- for (const auto& item : data.headers) |
- message += item.first + ": " + item.second + "\r\n"; |
- message += "\r\n"; |
- if (data.body) |
- message += *data.body; |
- |
- return message; |
-} |
- |
-HttpResponsePtr MakeResponseStruct(const TestResponse& data) { |
- HttpResponsePtr response(HttpResponse::New()); |
- response->status_code = data.status_code; |
- response->headers.resize(data.headers.size()); |
- size_t index = 0; |
- for (const auto& item : data.headers) { |
- HttpHeaderPtr header(HttpHeader::New()); |
- header->name = item.first; |
- header->value = item.second; |
- response->headers[index++] = std::move(header); |
- } |
- |
- if (data.body) { |
- uint32_t num_bytes = static_cast<uint32_t>(data.body->size()); |
- MojoCreateDataPipeOptions options; |
- options.struct_size = sizeof(MojoCreateDataPipeOptions); |
- options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE; |
- options.element_num_bytes = 1; |
- options.capacity_num_bytes = num_bytes; |
- DataPipe data_pipe(options); |
- response->body = std::move(data_pipe.consumer_handle); |
- MojoResult result = |
- WriteDataRaw(data_pipe.producer_handle.get(), data.body->data(), |
- &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE); |
- EXPECT_EQ(MOJO_RESULT_OK, result); |
- } |
- |
- return response; |
-} |
- |
-void CheckHeaders(const TestHeaders& expected, |
- const Array<HttpHeaderPtr>& headers) { |
- // The server impl fiddles with Content-Length and Content-Type. So we don't |
- // do a strict check here. |
- std::map<std::string, std::string> header_map; |
- for (size_t i = 0; i < headers.size(); ++i) { |
- std::string lower_name = |
- base::ToLowerASCII(headers[i]->name.To<std::string>()); |
- header_map[lower_name] = headers[i]->value; |
- } |
- |
- for (const auto& item : expected) { |
- std::string lower_name = base::ToLowerASCII(item.first); |
- EXPECT_NE(header_map.end(), header_map.find(lower_name)); |
- EXPECT_EQ(item.second, header_map[lower_name]); |
- } |
-} |
- |
-void CheckRequest(const TestRequest& expected, HttpRequestPtr request) { |
- EXPECT_EQ(expected.method, request->method); |
- EXPECT_EQ(expected.url, request->url); |
- CheckHeaders(expected.headers, request->headers); |
- if (expected.body) { |
- EXPECT_TRUE(request->body.is_valid()); |
- std::string body; |
- common::BlockingCopyToString(std::move(request->body), &body); |
- EXPECT_EQ(*expected.body, body); |
- } else { |
- EXPECT_FALSE(request->body.is_valid()); |
- } |
-} |
- |
-void CheckResponse(const TestResponse& expected, const std::string& response) { |
- int header_end = |
- net::HttpUtil::LocateEndOfHeaders(response.c_str(), response.size()); |
- std::string assembled_headers = |
- net::HttpUtil::AssembleRawHeaders(response.c_str(), header_end); |
- scoped_refptr<net::HttpResponseHeaders> parsed_headers( |
- new net::HttpResponseHeaders(assembled_headers)); |
- EXPECT_EQ(expected.status_code, |
- static_cast<uint32_t>(parsed_headers->response_code())); |
- for (const auto& item : expected.headers) |
- EXPECT_TRUE(parsed_headers->HasHeaderValue(item.first, item.second)); |
- |
- if (expected.body) { |
- EXPECT_NE(-1, header_end); |
- std::string body(response, static_cast<size_t>(header_end)); |
- EXPECT_EQ(*expected.body, body); |
- } else { |
- EXPECT_EQ(response.size(), static_cast<size_t>(header_end)); |
- } |
-} |
- |
-class TestHttpClient { |
- public: |
- TestHttpClient() : connect_result_(net::OK) {} |
- |
- void Connect(const net::IPEndPoint& address) { |
- net::AddressList addresses(address); |
- net::NetLog::Source source; |
- socket_.reset(new net::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_ == net::ERR_IO_PENDING) |
- run_loop.Run(); |
- |
- ASSERT_EQ(net::OK, connect_result_); |
- } |
- |
- void Send(const std::string& data) { |
- write_buffer_ = new net::DrainableIOBuffer(new net::StringIOBuffer(data), |
- data.length()); |
- Write(); |
- } |
- |
- // Note: This method determines the end of the response only by Content-Length |
- // and connection termination. Besides, it doesn't truncate at the end of the |
- // response, so |message| may return more data (e.g., part of the next |
- // response). |
- void ReadResponse(std::string* message) { |
- if (!Read(message, 1)) |
- return; |
- while (!IsCompleteResponse(*message)) { |
- std::string chunk; |
- if (!Read(&chunk, 1)) |
- return; |
- message->append(chunk); |
- } |
- return; |
- } |
- |
- 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 != net::ERR_IO_PENDING) |
- OnWrite(result); |
- } |
- |
- void OnWrite(int result) { |
- ASSERT_GT(result, 0); |
- write_buffer_->DidConsume(result); |
- if (write_buffer_->BytesRemaining()) |
- 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; |
- } |
- |
- void ReadInternal(const net::CompletionCallback& callback) { |
- read_buffer_ = new net::IOBufferWithSize(kMaxExpectedResponseLength); |
- int result = |
- socket_->Read(read_buffer_.get(), kMaxExpectedResponseLength, callback); |
- if (result != net::ERR_IO_PENDING) |
- callback.Run(result); |
- } |
- |
- bool IsCompleteResponse(const std::string& response) { |
- // Check end of headers first. |
- int end_of_headers = |
- net::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_t body_size = static_cast<int64_t>(response.size()) - end_of_headers; |
- DCHECK_LE(0, body_size); |
- scoped_refptr<net::HttpResponseHeaders> headers( |
- new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders( |
- response.data(), end_of_headers))); |
- return body_size >= headers->GetContentLength(); |
- } |
- |
- scoped_refptr<net::IOBufferWithSize> read_buffer_; |
- scoped_refptr<net::DrainableIOBuffer> write_buffer_; |
- scoped_ptr<net::TCPClientSocket> socket_; |
- int connect_result_; |
- |
- DISALLOW_COPY_AND_ASSIGN(TestHttpClient); |
-}; |
- |
-class WebSocketClientImpl : public WebSocketClient { |
- public: |
- explicit WebSocketClientImpl() |
- : binding_(this, &client_ptr_), |
- wait_for_message_count_(0), |
- run_loop_(nullptr) {} |
- ~WebSocketClientImpl() override {} |
- |
- // Establishes a connection from the client side. |
- void Connect(WebSocketPtr web_socket, const std::string& url) { |
- web_socket_ = std::move(web_socket); |
- |
- DataPipe data_pipe; |
- send_stream_ = std::move(data_pipe.producer_handle); |
- write_send_stream_.reset(new WebSocketWriteQueue(send_stream_.get())); |
- |
- web_socket_->Connect(url, Array<String>(), "http://example.com", |
- std::move(data_pipe.consumer_handle), |
- std::move(client_ptr_)); |
- } |
- |
- // Establishes a connection from the server side. |
- void AcceptConnectRequest( |
- const HttpConnectionDelegate::OnReceivedWebSocketRequestCallback& |
- callback) { |
- InterfaceRequest<WebSocket> web_socket_request = GetProxy(&web_socket_); |
- |
- DataPipe data_pipe; |
- send_stream_ = std::move(data_pipe.producer_handle); |
- write_send_stream_.reset(new WebSocketWriteQueue(send_stream_.get())); |
- |
- callback.Run(std::move(web_socket_request), |
- std::move(data_pipe.consumer_handle), std::move(client_ptr_)); |
- } |
- |
- void WaitForConnectCompletion() { |
- DCHECK(!run_loop_); |
- |
- if (receive_stream_.is_valid()) |
- return; |
- |
- base::RunLoop run_loop; |
- run_loop_ = &run_loop; |
- run_loop.Run(); |
- run_loop_ = nullptr; |
- } |
- |
- void Send(const std::string& message) { |
- DCHECK(!message.empty()); |
- |
- uint32_t size = static_cast<uint32_t>(message.size()); |
- write_send_stream_->Write( |
- &message[0], size, |
- base::Bind(&WebSocketClientImpl::OnFinishedWritingSendStream, |
- base::Unretained(this), size)); |
- } |
- |
- void WaitForMessage(size_t count) { |
- DCHECK(!run_loop_); |
- |
- if (received_messages_.size() >= count) |
- return; |
- wait_for_message_count_ = count; |
- base::RunLoop run_loop; |
- run_loop_ = &run_loop; |
- run_loop.Run(); |
- run_loop_ = nullptr; |
- } |
- |
- std::vector<std::string>& received_messages() { return received_messages_; } |
- |
- private: |
- // WebSocketClient implementation. |
- void DidConnect(const String& selected_subprotocol, |
- const String& extensions, |
- ScopedDataPipeConsumerHandle receive_stream) override { |
- receive_stream_ = std::move(receive_stream); |
- read_receive_stream_.reset(new WebSocketReadQueue(receive_stream_.get())); |
- |
- web_socket_->FlowControl(2048); |
- if (run_loop_) |
- run_loop_->Quit(); |
- } |
- |
- void DidReceiveData(bool fin, |
- WebSocket::MessageType type, |
- uint32_t num_bytes) override { |
- DCHECK(num_bytes > 0); |
- |
- read_receive_stream_->Read( |
- num_bytes, |
- base::Bind(&WebSocketClientImpl::OnFinishedReadingReceiveStream, |
- base::Unretained(this), num_bytes)); |
- } |
- |
- void DidReceiveFlowControl(int64_t quota) override {} |
- |
- void DidFail(const String& message) override {} |
- |
- void DidClose(bool was_clean, uint16_t code, const String& reason) override {} |
- |
- void OnFinishedWritingSendStream(uint32_t num_bytes, const char* buffer) { |
- EXPECT_TRUE(buffer); |
- |
- web_socket_->Send(true, WebSocket::MessageType::TEXT, num_bytes); |
- } |
- |
- void OnFinishedReadingReceiveStream(uint32_t num_bytes, const char* data) { |
- EXPECT_TRUE(data); |
- |
- received_messages_.push_back(std::string(data, num_bytes)); |
- if (run_loop_ && received_messages_.size() >= wait_for_message_count_) { |
- wait_for_message_count_ = 0; |
- run_loop_->Quit(); |
- } |
- } |
- |
- WebSocketClientPtr client_ptr_; |
- Binding<WebSocketClient> binding_; |
- WebSocketPtr web_socket_; |
- |
- ScopedDataPipeProducerHandle send_stream_; |
- scoped_ptr<WebSocketWriteQueue> write_send_stream_; |
- |
- ScopedDataPipeConsumerHandle receive_stream_; |
- scoped_ptr<WebSocketReadQueue> read_receive_stream_; |
- |
- std::vector<std::string> received_messages_; |
- size_t wait_for_message_count_; |
- |
- // Pointing to a stack-allocated RunLoop instance. |
- base::RunLoop* run_loop_; |
- |
- DISALLOW_COPY_AND_ASSIGN(WebSocketClientImpl); |
-}; |
- |
-class HttpConnectionDelegateImpl : public HttpConnectionDelegate { |
- public: |
- struct PendingRequest { |
- HttpRequestPtr request; |
- OnReceivedRequestCallback callback; |
- }; |
- |
- HttpConnectionDelegateImpl(HttpConnectionPtr connection, |
- InterfaceRequest<HttpConnectionDelegate> request) |
- : connection_(std::move(connection)), |
- binding_(this, std::move(request)), |
- wait_for_request_count_(0), |
- run_loop_(nullptr) {} |
- ~HttpConnectionDelegateImpl() override {} |
- |
- // HttpConnectionDelegate implementation: |
- void OnReceivedRequest(HttpRequestPtr request, |
- const OnReceivedRequestCallback& callback) override { |
- linked_ptr<PendingRequest> pending_request(new PendingRequest); |
- pending_request->request = std::move(request); |
- pending_request->callback = callback; |
- pending_requests_.push_back(pending_request); |
- if (run_loop_ && pending_requests_.size() >= wait_for_request_count_) { |
- wait_for_request_count_ = 0; |
- run_loop_->Quit(); |
- } |
- } |
- |
- void OnReceivedWebSocketRequest( |
- HttpRequestPtr request, |
- const OnReceivedWebSocketRequestCallback& callback) override { |
- web_socket_.reset(new WebSocketClientImpl()); |
- |
- web_socket_->AcceptConnectRequest(callback); |
- |
- if (run_loop_) |
- run_loop_->Quit(); |
- } |
- |
- void SendResponse(HttpResponsePtr response) { |
- ASSERT_FALSE(pending_requests_.empty()); |
- linked_ptr<PendingRequest> request = pending_requests_[0]; |
- pending_requests_.erase(pending_requests_.begin()); |
- request->callback.Run(std::move(response)); |
- } |
- |
- void WaitForRequest(size_t count) { |
- DCHECK(!run_loop_); |
- |
- if (pending_requests_.size() >= count) |
- return; |
- |
- wait_for_request_count_ = count; |
- base::RunLoop run_loop; |
- run_loop_ = &run_loop; |
- run_loop.Run(); |
- run_loop_ = nullptr; |
- } |
- |
- void WaitForWebSocketRequest() { |
- DCHECK(!run_loop_); |
- |
- if (web_socket_) |
- return; |
- |
- base::RunLoop run_loop; |
- run_loop_ = &run_loop; |
- run_loop.Run(); |
- run_loop_ = nullptr; |
- } |
- |
- std::vector<linked_ptr<PendingRequest>>& pending_requests() { |
- return pending_requests_; |
- } |
- |
- WebSocketClientImpl* web_socket() { return web_socket_.get(); } |
- |
- private: |
- HttpConnectionPtr connection_; |
- Binding<HttpConnectionDelegate> binding_; |
- std::vector<linked_ptr<PendingRequest>> pending_requests_; |
- size_t wait_for_request_count_; |
- scoped_ptr<WebSocketClientImpl> web_socket_; |
- |
- // Pointing to a stack-allocated RunLoop instance. |
- base::RunLoop* run_loop_; |
- |
- DISALLOW_COPY_AND_ASSIGN(HttpConnectionDelegateImpl); |
-}; |
- |
-class HttpServerDelegateImpl : public HttpServerDelegate { |
- public: |
- explicit HttpServerDelegateImpl(HttpServerDelegatePtr* delegate_ptr) |
- : binding_(this, delegate_ptr), |
- wait_for_connection_count_(0), |
- run_loop_(nullptr) {} |
- ~HttpServerDelegateImpl() override {} |
- |
- // HttpServerDelegate implementation. |
- void OnConnected(HttpConnectionPtr connection, |
- InterfaceRequest<HttpConnectionDelegate> delegate) override { |
- connections_.push_back(make_linked_ptr(new HttpConnectionDelegateImpl( |
- std::move(connection), std::move(delegate)))); |
- if (run_loop_ && connections_.size() >= wait_for_connection_count_) { |
- wait_for_connection_count_ = 0; |
- run_loop_->Quit(); |
- } |
- } |
- |
- void WaitForConnection(size_t count) { |
- DCHECK(!run_loop_); |
- |
- if (connections_.size() >= count) |
- return; |
- |
- wait_for_connection_count_ = count; |
- base::RunLoop run_loop; |
- run_loop_ = &run_loop; |
- run_loop.Run(); |
- run_loop_ = nullptr; |
- } |
- |
- std::vector<linked_ptr<HttpConnectionDelegateImpl>>& connections() { |
- return connections_; |
- } |
- |
- private: |
- Binding<HttpServerDelegate> binding_; |
- std::vector<linked_ptr<HttpConnectionDelegateImpl>> connections_; |
- size_t wait_for_connection_count_; |
- // Pointing to a stack-allocated RunLoop instance. |
- base::RunLoop* run_loop_; |
- |
- DISALLOW_COPY_AND_ASSIGN(HttpServerDelegateImpl); |
-}; |
- |
-class HttpServerTest : public test::ShellTest { |
- public: |
- HttpServerTest() |
- : ShellTest("exe:network_service_unittests") {} |
- ~HttpServerTest() override {} |
- |
- protected: |
- void SetUp() override { |
- ShellTest::SetUp(); |
- |
- scoped_ptr<Connection> connection = |
- connector()->Connect("mojo:network_service"); |
- connection->GetInterface(&network_service_); |
- connection->GetInterface(&web_socket_factory_); |
- } |
- |
- scoped_ptr<base::MessageLoop> CreateMessageLoop() override { |
- return make_scoped_ptr(new base::MessageLoop(base::MessageLoop::TYPE_IO)); |
- } |
- |
- void CreateHttpServer(HttpServerDelegatePtr delegate, |
- NetAddressPtr* out_bound_to) { |
- base::RunLoop loop; |
- network_service_->CreateHttpServer( |
- GetLocalHostWithAnyPort(), std::move(delegate), |
- [out_bound_to, &loop](NetworkErrorPtr result, NetAddressPtr bound_to) { |
- ASSERT_EQ(net::OK, result->code); |
- EXPECT_NE(0u, bound_to->ipv4->port); |
- *out_bound_to = std::move(bound_to); |
- loop.Quit(); |
- }); |
- loop.Run(); |
- } |
- |
- NetworkServicePtr network_service_; |
- WebSocketFactoryPtr web_socket_factory_; |
- |
- private: |
- DISALLOW_COPY_AND_ASSIGN(HttpServerTest); |
-}; |
- |
-} // namespace |
- |
-TEST_F(HttpServerTest, BasicHttpRequestResponse) { |
- NetAddressPtr bound_to; |
- HttpServerDelegatePtr server_delegate_ptr; |
- HttpServerDelegateImpl server_delegate_impl(&server_delegate_ptr); |
- CreateHttpServer(std::move(server_delegate_ptr), &bound_to); |
- |
- TestHttpClient client; |
- client.Connect(bound_to.To<net::IPEndPoint>()); |
- |
- server_delegate_impl.WaitForConnection(1); |
- HttpConnectionDelegateImpl& connection = |
- *server_delegate_impl.connections()[0]; |
- |
- TestRequest request_data = {"HEAD", "/test", {{"Hello", "World"}}, nullptr}; |
- client.Send(MakeRequestMessage(request_data)); |
- |
- connection.WaitForRequest(1); |
- |
- CheckRequest(request_data, |
- std::move(connection.pending_requests()[0]->request)); |
- |
- TestResponse response_data = {200, {{"Content-Length", "4"}}, nullptr}; |
- connection.SendResponse(MakeResponseStruct(response_data)); |
- // This causes the underlying TCP connection to be closed. The client can |
- // determine the end of the response based on that. |
- server_delegate_impl.connections().clear(); |
- |
- std::string response_message; |
- client.ReadResponse(&response_message); |
- |
- CheckResponse(response_data, response_message); |
-} |
- |
-TEST_F(HttpServerTest, HttpRequestResponseWithBody) { |
- NetAddressPtr bound_to; |
- HttpServerDelegatePtr server_delegate_ptr; |
- HttpServerDelegateImpl server_delegate_impl(&server_delegate_ptr); |
- CreateHttpServer(std::move(server_delegate_ptr), &bound_to); |
- |
- TestHttpClient client; |
- client.Connect(bound_to.To<net::IPEndPoint>()); |
- |
- server_delegate_impl.WaitForConnection(1); |
- HttpConnectionDelegateImpl& connection = |
- *server_delegate_impl.connections()[0]; |
- |
- TestRequest request_data = { |
- "Post", |
- "/test", |
- {{"Hello", "World"}, |
- {"Content-Length", "23"}, |
- {"Content-Type", "text/plain"}}, |
- make_scoped_ptr(new std::string("This is a test request!"))}; |
- client.Send(MakeRequestMessage(request_data)); |
- |
- connection.WaitForRequest(1); |
- |
- CheckRequest(request_data, |
- std::move(connection.pending_requests()[0]->request)); |
- |
- TestResponse response_data = { |
- 200, |
- {{"Content-Length", "26"}}, |
- make_scoped_ptr(new std::string("This is a test response..."))}; |
- connection.SendResponse(MakeResponseStruct(response_data)); |
- |
- std::string response_message; |
- client.ReadResponse(&response_message); |
- |
- CheckResponse(response_data, response_message); |
-} |
- |
-TEST_F(HttpServerTest, WebSocket) { |
- NetAddressPtr bound_to; |
- HttpServerDelegatePtr server_delegate_ptr; |
- HttpServerDelegateImpl server_delegate_impl(&server_delegate_ptr); |
- CreateHttpServer(std::move(server_delegate_ptr), &bound_to); |
- |
- WebSocketPtr web_socket_ptr; |
- web_socket_factory_->CreateWebSocket(GetProxy(&web_socket_ptr)); |
- WebSocketClientImpl socket_0; |
- socket_0.Connect( |
- std::move(web_socket_ptr), |
- base::StringPrintf("ws://127.0.0.1:%d/hello", bound_to->ipv4->port)); |
- |
- server_delegate_impl.WaitForConnection(1); |
- HttpConnectionDelegateImpl& connection = |
- *server_delegate_impl.connections()[0]; |
- |
- connection.WaitForWebSocketRequest(); |
- WebSocketClientImpl& socket_1 = *connection.web_socket(); |
- |
- socket_1.WaitForConnectCompletion(); |
- socket_0.WaitForConnectCompletion(); |
- |
- socket_0.Send("Hello"); |
- socket_0.Send("world!"); |
- |
- socket_1.WaitForMessage(2); |
- EXPECT_EQ("Hello", socket_1.received_messages()[0]); |
- EXPECT_EQ("world!", socket_1.received_messages()[1]); |
- |
- socket_1.Send("How do"); |
- socket_1.Send("you do?"); |
- |
- socket_0.WaitForMessage(2); |
- EXPECT_EQ("How do", socket_0.received_messages()[0]); |
- EXPECT_EQ("you do?", socket_0.received_messages()[1]); |
-} |
- |
-} // namespace mojo |