cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / mojo / services / network / http_server_apptest.cc
blobce93f047d1465daa9b4bf5ef66c744d47d5a864a
1 // Copyright 2015 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 "base/logging.h"
6 #include "base/macros.h"
7 #include "base/memory/linked_ptr.h"
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/run_loop.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "mojo/application/public/cpp/application_connection.h"
14 #include "mojo/application/public/cpp/application_impl.h"
15 #include "mojo/application/public/cpp/application_test_base.h"
16 #include "mojo/common/data_pipe_utils.h"
17 #include "mojo/services/network/net_address_type_converters.h"
18 #include "mojo/services/network/public/cpp/web_socket_read_queue.h"
19 #include "mojo/services/network/public/cpp/web_socket_write_queue.h"
20 #include "mojo/services/network/public/interfaces/http_connection.mojom.h"
21 #include "mojo/services/network/public/interfaces/http_message.mojom.h"
22 #include "mojo/services/network/public/interfaces/http_server.mojom.h"
23 #include "mojo/services/network/public/interfaces/net_address.mojom.h"
24 #include "mojo/services/network/public/interfaces/network_service.mojom.h"
25 #include "mojo/services/network/public/interfaces/web_socket.mojom.h"
26 #include "mojo/services/network/public/interfaces/web_socket_factory.mojom.h"
27 #include "net/base/io_buffer.h"
28 #include "net/base/net_errors.h"
29 #include "net/base/test_completion_callback.h"
30 #include "net/http/http_response_headers.h"
31 #include "net/http/http_util.h"
32 #include "net/socket/tcp_client_socket.h"
33 #include "testing/gtest/include/gtest/gtest.h"
35 namespace mojo {
36 namespace {
38 const int kMaxExpectedResponseLength = 2048;
40 NetAddressPtr GetLocalHostWithAnyPort() {
41 NetAddressPtr addr(NetAddress::New());
42 addr->family = NET_ADDRESS_FAMILY_IPV4;
43 addr->ipv4 = NetAddressIPv4::New();
44 addr->ipv4->port = 0;
45 addr->ipv4->addr.resize(4);
46 addr->ipv4->addr[0] = 127;
47 addr->ipv4->addr[1] = 0;
48 addr->ipv4->addr[2] = 0;
49 addr->ipv4->addr[3] = 1;
51 return addr.Pass();
54 using TestHeaders = std::vector<std::pair<std::string, std::string>>;
56 struct TestRequest {
57 std::string method;
58 std::string url;
59 TestHeaders headers;
60 scoped_ptr<std::string> body;
63 struct TestResponse {
64 uint32_t status_code;
65 TestHeaders headers;
66 scoped_ptr<std::string> body;
69 std::string MakeRequestMessage(const TestRequest& data) {
70 std::string message = data.method + " " + data.url + " HTTP/1.1\r\n";
71 for (const auto& item : data.headers)
72 message += item.first + ": " + item.second + "\r\n";
73 message += "\r\n";
74 if (data.body)
75 message += *data.body;
77 return message;
80 HttpResponsePtr MakeResponseStruct(const TestResponse& data) {
81 HttpResponsePtr response(HttpResponse::New());
82 response->status_code = data.status_code;
83 response->headers.resize(data.headers.size());
84 size_t index = 0;
85 for (const auto& item : data.headers) {
86 HttpHeaderPtr header(HttpHeader::New());
87 header->name = item.first;
88 header->value = item.second;
89 response->headers[index++] = header.Pass();
92 if (data.body) {
93 uint32_t num_bytes = static_cast<uint32_t>(data.body->size());
94 MojoCreateDataPipeOptions options;
95 options.struct_size = sizeof(MojoCreateDataPipeOptions);
96 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
97 options.element_num_bytes = 1;
98 options.capacity_num_bytes = num_bytes;
99 DataPipe data_pipe(options);
100 response->body = data_pipe.consumer_handle.Pass();
101 MojoResult result =
102 WriteDataRaw(data_pipe.producer_handle.get(), data.body->data(),
103 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
104 EXPECT_EQ(MOJO_RESULT_OK, result);
107 return response.Pass();
110 void CheckHeaders(const TestHeaders& expected,
111 const Array<HttpHeaderPtr>& headers) {
112 // The server impl fiddles with Content-Length and Content-Type. So we don't
113 // do a strict check here.
114 std::map<std::string, std::string> header_map;
115 for (size_t i = 0; i < headers.size(); ++i) {
116 std::string lower_name =
117 base::ToLowerASCII(headers[i]->name.To<std::string>());
118 header_map[lower_name] = headers[i]->value;
121 for (const auto& item : expected) {
122 std::string lower_name = base::ToLowerASCII(item.first);
123 EXPECT_NE(header_map.end(), header_map.find(lower_name));
124 EXPECT_EQ(item.second, header_map[lower_name]);
128 void CheckRequest(const TestRequest& expected, HttpRequestPtr request) {
129 EXPECT_EQ(expected.method, request->method);
130 EXPECT_EQ(expected.url, request->url);
131 CheckHeaders(expected.headers, request->headers);
132 if (expected.body) {
133 EXPECT_TRUE(request->body.is_valid());
134 std::string body;
135 common::BlockingCopyToString(request->body.Pass(), &body);
136 EXPECT_EQ(*expected.body, body);
137 } else {
138 EXPECT_FALSE(request->body.is_valid());
142 void CheckResponse(const TestResponse& expected, const std::string& response) {
143 int header_end =
144 net::HttpUtil::LocateEndOfHeaders(response.c_str(), response.size());
145 std::string assembled_headers =
146 net::HttpUtil::AssembleRawHeaders(response.c_str(), header_end);
147 scoped_refptr<net::HttpResponseHeaders> parsed_headers(
148 new net::HttpResponseHeaders(assembled_headers));
149 EXPECT_EQ(expected.status_code,
150 static_cast<uint32_t>(parsed_headers->response_code()));
151 for (const auto& item : expected.headers)
152 EXPECT_TRUE(parsed_headers->HasHeaderValue(item.first, item.second));
154 if (expected.body) {
155 EXPECT_NE(-1, header_end);
156 std::string body(response, static_cast<size_t>(header_end));
157 EXPECT_EQ(*expected.body, body);
158 } else {
159 EXPECT_EQ(response.size(), static_cast<size_t>(header_end));
163 class TestHttpClient {
164 public:
165 TestHttpClient() : connect_result_(net::OK) {}
167 void Connect(const net::IPEndPoint& address) {
168 net::AddressList addresses(address);
169 net::NetLog::Source source;
170 socket_.reset(new net::TCPClientSocket(addresses, NULL, source));
172 base::RunLoop run_loop;
173 connect_result_ = socket_->Connect(base::Bind(&TestHttpClient::OnConnect,
174 base::Unretained(this),
175 run_loop.QuitClosure()));
176 if (connect_result_ == net::ERR_IO_PENDING)
177 run_loop.Run();
179 ASSERT_EQ(net::OK, connect_result_);
182 void Send(const std::string& data) {
183 write_buffer_ = new net::DrainableIOBuffer(new net::StringIOBuffer(data),
184 data.length());
185 Write();
188 // Note: This method determines the end of the response only by Content-Length
189 // and connection termination. Besides, it doesn't truncate at the end of the
190 // response, so |message| may return more data (e.g., part of the next
191 // response).
192 void ReadResponse(std::string* message) {
193 if (!Read(message, 1))
194 return;
195 while (!IsCompleteResponse(*message)) {
196 std::string chunk;
197 if (!Read(&chunk, 1))
198 return;
199 message->append(chunk);
201 return;
204 private:
205 void OnConnect(const base::Closure& quit_loop, int result) {
206 connect_result_ = result;
207 quit_loop.Run();
210 void Write() {
211 int result = socket_->Write(
212 write_buffer_.get(), write_buffer_->BytesRemaining(),
213 base::Bind(&TestHttpClient::OnWrite, base::Unretained(this)));
214 if (result != net::ERR_IO_PENDING)
215 OnWrite(result);
218 void OnWrite(int result) {
219 ASSERT_GT(result, 0);
220 write_buffer_->DidConsume(result);
221 if (write_buffer_->BytesRemaining())
222 Write();
225 bool Read(std::string* message, int expected_bytes) {
226 int total_bytes_received = 0;
227 message->clear();
228 while (total_bytes_received < expected_bytes) {
229 net::TestCompletionCallback callback;
230 ReadInternal(callback.callback());
231 int bytes_received = callback.WaitForResult();
232 if (bytes_received <= 0)
233 return false;
235 total_bytes_received += bytes_received;
236 message->append(read_buffer_->data(), bytes_received);
238 return true;
241 void ReadInternal(const net::CompletionCallback& callback) {
242 read_buffer_ = new net::IOBufferWithSize(kMaxExpectedResponseLength);
243 int result =
244 socket_->Read(read_buffer_.get(), kMaxExpectedResponseLength, callback);
245 if (result != net::ERR_IO_PENDING)
246 callback.Run(result);
249 bool IsCompleteResponse(const std::string& response) {
250 // Check end of headers first.
251 int end_of_headers =
252 net::HttpUtil::LocateEndOfHeaders(response.data(), response.size());
253 if (end_of_headers < 0)
254 return false;
256 // Return true if response has data equal to or more than content length.
257 int64 body_size = static_cast<int64>(response.size()) - end_of_headers;
258 DCHECK_LE(0, body_size);
259 scoped_refptr<net::HttpResponseHeaders> headers(
260 new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
261 response.data(), end_of_headers)));
262 return body_size >= headers->GetContentLength();
265 scoped_refptr<net::IOBufferWithSize> read_buffer_;
266 scoped_refptr<net::DrainableIOBuffer> write_buffer_;
267 scoped_ptr<net::TCPClientSocket> socket_;
268 int connect_result_;
270 DISALLOW_COPY_AND_ASSIGN(TestHttpClient);
273 class WebSocketClientImpl : public WebSocketClient {
274 public:
275 explicit WebSocketClientImpl()
276 : binding_(this, &client_ptr_),
277 wait_for_message_count_(0),
278 run_loop_(nullptr) {}
279 ~WebSocketClientImpl() override {}
281 // Establishes a connection from the client side.
282 void Connect(WebSocketPtr web_socket, const std::string& url) {
283 web_socket_ = web_socket.Pass();
285 DataPipe data_pipe;
286 send_stream_ = data_pipe.producer_handle.Pass();
287 write_send_stream_.reset(new WebSocketWriteQueue(send_stream_.get()));
289 web_socket_->Connect(url, Array<String>(0), "http://example.com",
290 data_pipe.consumer_handle.Pass(), client_ptr_.Pass());
293 // Establishes a connection from the server side.
294 void AcceptConnectRequest(
295 const HttpConnectionDelegate::OnReceivedWebSocketRequestCallback&
296 callback) {
297 InterfaceRequest<WebSocket> web_socket_request = GetProxy(&web_socket_);
299 DataPipe data_pipe;
300 send_stream_ = data_pipe.producer_handle.Pass();
301 write_send_stream_.reset(new WebSocketWriteQueue(send_stream_.get()));
303 callback.Run(web_socket_request.Pass(), data_pipe.consumer_handle.Pass(),
304 client_ptr_.Pass());
307 void WaitForConnectCompletion() {
308 DCHECK(!run_loop_);
310 if (receive_stream_.is_valid())
311 return;
313 base::RunLoop run_loop;
314 run_loop_ = &run_loop;
315 run_loop.Run();
316 run_loop_ = nullptr;
319 void Send(const std::string& message) {
320 DCHECK(!message.empty());
322 uint32_t size = static_cast<uint32_t>(message.size());
323 write_send_stream_->Write(
324 &message[0], size,
325 base::Bind(&WebSocketClientImpl::OnFinishedWritingSendStream,
326 base::Unretained(this), size));
329 void WaitForMessage(size_t count) {
330 DCHECK(!run_loop_);
332 if (received_messages_.size() >= count)
333 return;
334 wait_for_message_count_ = count;
335 base::RunLoop run_loop;
336 run_loop_ = &run_loop;
337 run_loop.Run();
338 run_loop_ = nullptr;
341 std::vector<std::string>& received_messages() { return received_messages_; }
343 private:
344 // WebSocketClient implementation.
345 void DidConnect(const String& selected_subprotocol,
346 const String& extensions,
347 ScopedDataPipeConsumerHandle receive_stream) override {
348 receive_stream_ = receive_stream.Pass();
349 read_receive_stream_.reset(new WebSocketReadQueue(receive_stream_.get()));
351 web_socket_->FlowControl(2048);
352 if (run_loop_)
353 run_loop_->Quit();
356 void DidReceiveData(bool fin,
357 WebSocket::MessageType type,
358 uint32_t num_bytes) override {
359 DCHECK(num_bytes > 0);
361 read_receive_stream_->Read(
362 num_bytes,
363 base::Bind(&WebSocketClientImpl::OnFinishedReadingReceiveStream,
364 base::Unretained(this), num_bytes));
367 void DidReceiveFlowControl(int64_t quota) override {}
369 void DidFail(const String& message) override {}
371 void DidClose(bool was_clean, uint16_t code, const String& reason) override {}
373 void OnFinishedWritingSendStream(uint32_t num_bytes, const char* buffer) {
374 EXPECT_TRUE(buffer);
376 web_socket_->Send(true, WebSocket::MESSAGE_TYPE_TEXT, num_bytes);
379 void OnFinishedReadingReceiveStream(uint32_t num_bytes, const char* data) {
380 EXPECT_TRUE(data);
382 received_messages_.push_back(std::string(data, num_bytes));
383 if (run_loop_ && received_messages_.size() >= wait_for_message_count_) {
384 wait_for_message_count_ = 0;
385 run_loop_->Quit();
389 WebSocketClientPtr client_ptr_;
390 Binding<WebSocketClient> binding_;
391 WebSocketPtr web_socket_;
393 ScopedDataPipeProducerHandle send_stream_;
394 scoped_ptr<WebSocketWriteQueue> write_send_stream_;
396 ScopedDataPipeConsumerHandle receive_stream_;
397 scoped_ptr<WebSocketReadQueue> read_receive_stream_;
399 std::vector<std::string> received_messages_;
400 size_t wait_for_message_count_;
402 // Pointing to a stack-allocated RunLoop instance.
403 base::RunLoop* run_loop_;
405 DISALLOW_COPY_AND_ASSIGN(WebSocketClientImpl);
408 class HttpConnectionDelegateImpl : public HttpConnectionDelegate {
409 public:
410 struct PendingRequest {
411 HttpRequestPtr request;
412 OnReceivedRequestCallback callback;
415 HttpConnectionDelegateImpl(HttpConnectionPtr connection,
416 InterfaceRequest<HttpConnectionDelegate> request)
417 : connection_(connection.Pass()),
418 binding_(this, request.Pass()),
419 wait_for_request_count_(0),
420 run_loop_(nullptr) {}
421 ~HttpConnectionDelegateImpl() override {}
423 // HttpConnectionDelegate implementation:
424 void OnReceivedRequest(HttpRequestPtr request,
425 const OnReceivedRequestCallback& callback) override {
426 linked_ptr<PendingRequest> pending_request(new PendingRequest);
427 pending_request->request = request.Pass();
428 pending_request->callback = callback;
429 pending_requests_.push_back(pending_request);
430 if (run_loop_ && pending_requests_.size() >= wait_for_request_count_) {
431 wait_for_request_count_ = 0;
432 run_loop_->Quit();
436 void OnReceivedWebSocketRequest(
437 HttpRequestPtr request,
438 const OnReceivedWebSocketRequestCallback& callback) override {
439 web_socket_.reset(new WebSocketClientImpl());
441 web_socket_->AcceptConnectRequest(callback);
443 if (run_loop_)
444 run_loop_->Quit();
447 void SendResponse(HttpResponsePtr response) {
448 ASSERT_FALSE(pending_requests_.empty());
449 linked_ptr<PendingRequest> request = pending_requests_[0];
450 pending_requests_.erase(pending_requests_.begin());
451 request->callback.Run(response.Pass());
454 void WaitForRequest(size_t count) {
455 DCHECK(!run_loop_);
457 if (pending_requests_.size() >= count)
458 return;
460 wait_for_request_count_ = count;
461 base::RunLoop run_loop;
462 run_loop_ = &run_loop;
463 run_loop.Run();
464 run_loop_ = nullptr;
467 void WaitForWebSocketRequest() {
468 DCHECK(!run_loop_);
470 if (web_socket_)
471 return;
473 base::RunLoop run_loop;
474 run_loop_ = &run_loop;
475 run_loop.Run();
476 run_loop_ = nullptr;
479 std::vector<linked_ptr<PendingRequest>>& pending_requests() {
480 return pending_requests_;
483 WebSocketClientImpl* web_socket() { return web_socket_.get(); }
485 private:
486 HttpConnectionPtr connection_;
487 Binding<HttpConnectionDelegate> binding_;
488 std::vector<linked_ptr<PendingRequest>> pending_requests_;
489 size_t wait_for_request_count_;
490 scoped_ptr<WebSocketClientImpl> web_socket_;
492 // Pointing to a stack-allocated RunLoop instance.
493 base::RunLoop* run_loop_;
495 DISALLOW_COPY_AND_ASSIGN(HttpConnectionDelegateImpl);
498 class HttpServerDelegateImpl : public HttpServerDelegate {
499 public:
500 explicit HttpServerDelegateImpl(HttpServerDelegatePtr* delegate_ptr)
501 : binding_(this, delegate_ptr),
502 wait_for_connection_count_(0),
503 run_loop_(nullptr) {}
504 ~HttpServerDelegateImpl() override {}
506 // HttpServerDelegate implementation.
507 void OnConnected(HttpConnectionPtr connection,
508 InterfaceRequest<HttpConnectionDelegate> delegate) override {
509 connections_.push_back(make_linked_ptr(
510 new HttpConnectionDelegateImpl(connection.Pass(), delegate.Pass())));
511 if (run_loop_ && connections_.size() >= wait_for_connection_count_) {
512 wait_for_connection_count_ = 0;
513 run_loop_->Quit();
517 void WaitForConnection(size_t count) {
518 DCHECK(!run_loop_);
520 if (connections_.size() >= count)
521 return;
523 wait_for_connection_count_ = count;
524 base::RunLoop run_loop;
525 run_loop_ = &run_loop;
526 run_loop.Run();
527 run_loop_ = nullptr;
530 std::vector<linked_ptr<HttpConnectionDelegateImpl>>& connections() {
531 return connections_;
534 private:
535 Binding<HttpServerDelegate> binding_;
536 std::vector<linked_ptr<HttpConnectionDelegateImpl>> connections_;
537 size_t wait_for_connection_count_;
538 // Pointing to a stack-allocated RunLoop instance.
539 base::RunLoop* run_loop_;
541 DISALLOW_COPY_AND_ASSIGN(HttpServerDelegateImpl);
544 class HttpServerAppTest : public test::ApplicationTestBase {
545 public:
546 HttpServerAppTest() : message_loop_(base::MessageLoop::TYPE_IO) {}
547 ~HttpServerAppTest() override {}
549 protected:
550 bool ShouldCreateDefaultRunLoop() override { return false; }
552 void SetUp() override {
553 ApplicationTestBase::SetUp();
555 mojo::URLRequestPtr request(mojo::URLRequest::New());
556 request->url = mojo::String::From("mojo:network_service");
557 scoped_ptr<ApplicationConnection> connection =
558 application_impl()->ConnectToApplication(request.Pass());
559 connection->ConnectToService(&network_service_);
560 connection->ConnectToService(&web_socket_factory_);
563 void CreateHttpServer(HttpServerDelegatePtr delegate,
564 NetAddressPtr* out_bound_to) {
565 network_service_->CreateHttpServer(
566 GetLocalHostWithAnyPort(), delegate.Pass(),
567 [out_bound_to](NetworkErrorPtr result, NetAddressPtr bound_to) {
568 ASSERT_EQ(net::OK, result->code);
569 EXPECT_NE(0u, bound_to->ipv4->port);
570 *out_bound_to = bound_to.Pass();
572 network_service_.WaitForIncomingResponse();
575 NetworkServicePtr network_service_;
576 WebSocketFactoryPtr web_socket_factory_;
578 private:
579 base::MessageLoop message_loop_;
581 DISALLOW_COPY_AND_ASSIGN(HttpServerAppTest);
584 } // namespace
586 TEST_F(HttpServerAppTest, BasicHttpRequestResponse) {
587 NetAddressPtr bound_to;
588 HttpServerDelegatePtr server_delegate_ptr;
589 HttpServerDelegateImpl server_delegate_impl(&server_delegate_ptr);
590 CreateHttpServer(server_delegate_ptr.Pass(), &bound_to);
592 TestHttpClient client;
593 client.Connect(bound_to.To<net::IPEndPoint>());
595 server_delegate_impl.WaitForConnection(1);
596 HttpConnectionDelegateImpl& connection =
597 *server_delegate_impl.connections()[0];
599 TestRequest request_data = {"HEAD", "/test", {{"Hello", "World"}}, nullptr};
600 client.Send(MakeRequestMessage(request_data));
602 connection.WaitForRequest(1);
604 CheckRequest(request_data, connection.pending_requests()[0]->request.Pass());
606 TestResponse response_data = {200, {{"Content-Length", "4"}}, nullptr};
607 connection.SendResponse(MakeResponseStruct(response_data));
608 // This causes the underlying TCP connection to be closed. The client can
609 // determine the end of the response based on that.
610 server_delegate_impl.connections().clear();
612 std::string response_message;
613 client.ReadResponse(&response_message);
615 CheckResponse(response_data, response_message);
618 TEST_F(HttpServerAppTest, HttpRequestResponseWithBody) {
619 NetAddressPtr bound_to;
620 HttpServerDelegatePtr server_delegate_ptr;
621 HttpServerDelegateImpl server_delegate_impl(&server_delegate_ptr);
622 CreateHttpServer(server_delegate_ptr.Pass(), &bound_to);
624 TestHttpClient client;
625 client.Connect(bound_to.To<net::IPEndPoint>());
627 server_delegate_impl.WaitForConnection(1);
628 HttpConnectionDelegateImpl& connection =
629 *server_delegate_impl.connections()[0];
631 TestRequest request_data = {
632 "Post",
633 "/test",
634 {{"Hello", "World"},
635 {"Content-Length", "23"},
636 {"Content-Type", "text/plain"}},
637 make_scoped_ptr(new std::string("This is a test request!"))};
638 client.Send(MakeRequestMessage(request_data));
640 connection.WaitForRequest(1);
642 CheckRequest(request_data, connection.pending_requests()[0]->request.Pass());
644 TestResponse response_data = {
645 200,
646 {{"Content-Length", "26"}},
647 make_scoped_ptr(new std::string("This is a test response..."))};
648 connection.SendResponse(MakeResponseStruct(response_data));
650 std::string response_message;
651 client.ReadResponse(&response_message);
653 CheckResponse(response_data, response_message);
656 TEST_F(HttpServerAppTest, WebSocket) {
657 NetAddressPtr bound_to;
658 HttpServerDelegatePtr server_delegate_ptr;
659 HttpServerDelegateImpl server_delegate_impl(&server_delegate_ptr);
660 CreateHttpServer(server_delegate_ptr.Pass(), &bound_to);
662 WebSocketPtr web_socket_ptr;
663 web_socket_factory_->CreateWebSocket(GetProxy(&web_socket_ptr));
664 WebSocketClientImpl socket_0;
665 socket_0.Connect(
666 web_socket_ptr.Pass(),
667 base::StringPrintf("ws://127.0.0.1:%d/hello", bound_to->ipv4->port));
669 server_delegate_impl.WaitForConnection(1);
670 HttpConnectionDelegateImpl& connection =
671 *server_delegate_impl.connections()[0];
673 connection.WaitForWebSocketRequest();
674 WebSocketClientImpl& socket_1 = *connection.web_socket();
676 socket_1.WaitForConnectCompletion();
677 socket_0.WaitForConnectCompletion();
679 socket_0.Send("Hello");
680 socket_0.Send("world!");
682 socket_1.WaitForMessage(2);
683 EXPECT_EQ("Hello", socket_1.received_messages()[0]);
684 EXPECT_EQ("world!", socket_1.received_messages()[1]);
686 socket_1.Send("How do");
687 socket_1.Send("you do?");
689 socket_0.WaitForMessage(2);
690 EXPECT_EQ("How do", socket_0.received_messages()[0]);
691 EXPECT_EQ("you do?", socket_0.received_messages()[1]);
694 } // namespace mojo