Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(631)

Side by Side Diff: mojo/services/network/http_server_unittest.cc

Issue 1873463003: Remove mojo network service. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « mojo/services/network/http_server_impl.cc ('k') | mojo/services/network/main.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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.
4
5 #include <stddef.h>
6 #include <stdint.h>
7
8 #include <utility>
9
10 #include "base/logging.h"
11 #include "base/macros.h"
12 #include "base/memory/linked_ptr.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string_util.h"
17 #include "base/strings/stringprintf.h"
18 #include "mojo/common/data_pipe_utils.h"
19 #include "mojo/services/network/net_address_type_converters.h"
20 #include "mojo/services/network/public/cpp/web_socket_read_queue.h"
21 #include "mojo/services/network/public/cpp/web_socket_write_queue.h"
22 #include "mojo/services/network/public/interfaces/http_connection.mojom.h"
23 #include "mojo/services/network/public/interfaces/http_message.mojom.h"
24 #include "mojo/services/network/public/interfaces/http_server.mojom.h"
25 #include "mojo/services/network/public/interfaces/net_address.mojom.h"
26 #include "mojo/services/network/public/interfaces/network_service.mojom.h"
27 #include "mojo/services/network/public/interfaces/web_socket.mojom.h"
28 #include "mojo/services/network/public/interfaces/web_socket_factory.mojom.h"
29 #include "mojo/shell/public/cpp/shell_test.h"
30 #include "net/base/io_buffer.h"
31 #include "net/base/net_errors.h"
32 #include "net/base/test_completion_callback.h"
33 #include "net/http/http_response_headers.h"
34 #include "net/http/http_util.h"
35 #include "net/socket/tcp_client_socket.h"
36 #include "testing/gtest/include/gtest/gtest.h"
37
38 namespace mojo {
39 namespace {
40
41 const int kMaxExpectedResponseLength = 2048;
42
43 NetAddressPtr GetLocalHostWithAnyPort() {
44 NetAddressPtr addr(NetAddress::New());
45 addr->family = NetAddressFamily::IPV4;
46 addr->ipv4 = NetAddressIPv4::New();
47 addr->ipv4->port = 0;
48 addr->ipv4->addr.resize(4);
49 addr->ipv4->addr[0] = 127;
50 addr->ipv4->addr[1] = 0;
51 addr->ipv4->addr[2] = 0;
52 addr->ipv4->addr[3] = 1;
53
54 return addr;
55 }
56
57 using TestHeaders = std::vector<std::pair<std::string, std::string>>;
58
59 struct TestRequest {
60 std::string method;
61 std::string url;
62 TestHeaders headers;
63 scoped_ptr<std::string> body;
64 };
65
66 struct TestResponse {
67 uint32_t status_code;
68 TestHeaders headers;
69 scoped_ptr<std::string> body;
70 };
71
72 std::string MakeRequestMessage(const TestRequest& data) {
73 std::string message = data.method + " " + data.url + " HTTP/1.1\r\n";
74 for (const auto& item : data.headers)
75 message += item.first + ": " + item.second + "\r\n";
76 message += "\r\n";
77 if (data.body)
78 message += *data.body;
79
80 return message;
81 }
82
83 HttpResponsePtr MakeResponseStruct(const TestResponse& data) {
84 HttpResponsePtr response(HttpResponse::New());
85 response->status_code = data.status_code;
86 response->headers.resize(data.headers.size());
87 size_t index = 0;
88 for (const auto& item : data.headers) {
89 HttpHeaderPtr header(HttpHeader::New());
90 header->name = item.first;
91 header->value = item.second;
92 response->headers[index++] = std::move(header);
93 }
94
95 if (data.body) {
96 uint32_t num_bytes = static_cast<uint32_t>(data.body->size());
97 MojoCreateDataPipeOptions options;
98 options.struct_size = sizeof(MojoCreateDataPipeOptions);
99 options.flags = MOJO_CREATE_DATA_PIPE_OPTIONS_FLAG_NONE;
100 options.element_num_bytes = 1;
101 options.capacity_num_bytes = num_bytes;
102 DataPipe data_pipe(options);
103 response->body = std::move(data_pipe.consumer_handle);
104 MojoResult result =
105 WriteDataRaw(data_pipe.producer_handle.get(), data.body->data(),
106 &num_bytes, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE);
107 EXPECT_EQ(MOJO_RESULT_OK, result);
108 }
109
110 return response;
111 }
112
113 void CheckHeaders(const TestHeaders& expected,
114 const Array<HttpHeaderPtr>& headers) {
115 // The server impl fiddles with Content-Length and Content-Type. So we don't
116 // do a strict check here.
117 std::map<std::string, std::string> header_map;
118 for (size_t i = 0; i < headers.size(); ++i) {
119 std::string lower_name =
120 base::ToLowerASCII(headers[i]->name.To<std::string>());
121 header_map[lower_name] = headers[i]->value;
122 }
123
124 for (const auto& item : expected) {
125 std::string lower_name = base::ToLowerASCII(item.first);
126 EXPECT_NE(header_map.end(), header_map.find(lower_name));
127 EXPECT_EQ(item.second, header_map[lower_name]);
128 }
129 }
130
131 void CheckRequest(const TestRequest& expected, HttpRequestPtr request) {
132 EXPECT_EQ(expected.method, request->method);
133 EXPECT_EQ(expected.url, request->url);
134 CheckHeaders(expected.headers, request->headers);
135 if (expected.body) {
136 EXPECT_TRUE(request->body.is_valid());
137 std::string body;
138 common::BlockingCopyToString(std::move(request->body), &body);
139 EXPECT_EQ(*expected.body, body);
140 } else {
141 EXPECT_FALSE(request->body.is_valid());
142 }
143 }
144
145 void CheckResponse(const TestResponse& expected, const std::string& response) {
146 int header_end =
147 net::HttpUtil::LocateEndOfHeaders(response.c_str(), response.size());
148 std::string assembled_headers =
149 net::HttpUtil::AssembleRawHeaders(response.c_str(), header_end);
150 scoped_refptr<net::HttpResponseHeaders> parsed_headers(
151 new net::HttpResponseHeaders(assembled_headers));
152 EXPECT_EQ(expected.status_code,
153 static_cast<uint32_t>(parsed_headers->response_code()));
154 for (const auto& item : expected.headers)
155 EXPECT_TRUE(parsed_headers->HasHeaderValue(item.first, item.second));
156
157 if (expected.body) {
158 EXPECT_NE(-1, header_end);
159 std::string body(response, static_cast<size_t>(header_end));
160 EXPECT_EQ(*expected.body, body);
161 } else {
162 EXPECT_EQ(response.size(), static_cast<size_t>(header_end));
163 }
164 }
165
166 class TestHttpClient {
167 public:
168 TestHttpClient() : connect_result_(net::OK) {}
169
170 void Connect(const net::IPEndPoint& address) {
171 net::AddressList addresses(address);
172 net::NetLog::Source source;
173 socket_.reset(new net::TCPClientSocket(addresses, NULL, source));
174
175 base::RunLoop run_loop;
176 connect_result_ = socket_->Connect(base::Bind(&TestHttpClient::OnConnect,
177 base::Unretained(this),
178 run_loop.QuitClosure()));
179 if (connect_result_ == net::ERR_IO_PENDING)
180 run_loop.Run();
181
182 ASSERT_EQ(net::OK, connect_result_);
183 }
184
185 void Send(const std::string& data) {
186 write_buffer_ = new net::DrainableIOBuffer(new net::StringIOBuffer(data),
187 data.length());
188 Write();
189 }
190
191 // Note: This method determines the end of the response only by Content-Length
192 // and connection termination. Besides, it doesn't truncate at the end of the
193 // response, so |message| may return more data (e.g., part of the next
194 // response).
195 void ReadResponse(std::string* message) {
196 if (!Read(message, 1))
197 return;
198 while (!IsCompleteResponse(*message)) {
199 std::string chunk;
200 if (!Read(&chunk, 1))
201 return;
202 message->append(chunk);
203 }
204 return;
205 }
206
207 private:
208 void OnConnect(const base::Closure& quit_loop, int result) {
209 connect_result_ = result;
210 quit_loop.Run();
211 }
212
213 void Write() {
214 int result = socket_->Write(
215 write_buffer_.get(), write_buffer_->BytesRemaining(),
216 base::Bind(&TestHttpClient::OnWrite, base::Unretained(this)));
217 if (result != net::ERR_IO_PENDING)
218 OnWrite(result);
219 }
220
221 void OnWrite(int result) {
222 ASSERT_GT(result, 0);
223 write_buffer_->DidConsume(result);
224 if (write_buffer_->BytesRemaining())
225 Write();
226 }
227
228 bool Read(std::string* message, int expected_bytes) {
229 int total_bytes_received = 0;
230 message->clear();
231 while (total_bytes_received < expected_bytes) {
232 net::TestCompletionCallback callback;
233 ReadInternal(callback.callback());
234 int bytes_received = callback.WaitForResult();
235 if (bytes_received <= 0)
236 return false;
237
238 total_bytes_received += bytes_received;
239 message->append(read_buffer_->data(), bytes_received);
240 }
241 return true;
242 }
243
244 void ReadInternal(const net::CompletionCallback& callback) {
245 read_buffer_ = new net::IOBufferWithSize(kMaxExpectedResponseLength);
246 int result =
247 socket_->Read(read_buffer_.get(), kMaxExpectedResponseLength, callback);
248 if (result != net::ERR_IO_PENDING)
249 callback.Run(result);
250 }
251
252 bool IsCompleteResponse(const std::string& response) {
253 // Check end of headers first.
254 int end_of_headers =
255 net::HttpUtil::LocateEndOfHeaders(response.data(), response.size());
256 if (end_of_headers < 0)
257 return false;
258
259 // Return true if response has data equal to or more than content length.
260 int64_t body_size = static_cast<int64_t>(response.size()) - end_of_headers;
261 DCHECK_LE(0, body_size);
262 scoped_refptr<net::HttpResponseHeaders> headers(
263 new net::HttpResponseHeaders(net::HttpUtil::AssembleRawHeaders(
264 response.data(), end_of_headers)));
265 return body_size >= headers->GetContentLength();
266 }
267
268 scoped_refptr<net::IOBufferWithSize> read_buffer_;
269 scoped_refptr<net::DrainableIOBuffer> write_buffer_;
270 scoped_ptr<net::TCPClientSocket> socket_;
271 int connect_result_;
272
273 DISALLOW_COPY_AND_ASSIGN(TestHttpClient);
274 };
275
276 class WebSocketClientImpl : public WebSocketClient {
277 public:
278 explicit WebSocketClientImpl()
279 : binding_(this, &client_ptr_),
280 wait_for_message_count_(0),
281 run_loop_(nullptr) {}
282 ~WebSocketClientImpl() override {}
283
284 // Establishes a connection from the client side.
285 void Connect(WebSocketPtr web_socket, const std::string& url) {
286 web_socket_ = std::move(web_socket);
287
288 DataPipe data_pipe;
289 send_stream_ = std::move(data_pipe.producer_handle);
290 write_send_stream_.reset(new WebSocketWriteQueue(send_stream_.get()));
291
292 web_socket_->Connect(url, Array<String>(), "http://example.com",
293 std::move(data_pipe.consumer_handle),
294 std::move(client_ptr_));
295 }
296
297 // Establishes a connection from the server side.
298 void AcceptConnectRequest(
299 const HttpConnectionDelegate::OnReceivedWebSocketRequestCallback&
300 callback) {
301 InterfaceRequest<WebSocket> web_socket_request = GetProxy(&web_socket_);
302
303 DataPipe data_pipe;
304 send_stream_ = std::move(data_pipe.producer_handle);
305 write_send_stream_.reset(new WebSocketWriteQueue(send_stream_.get()));
306
307 callback.Run(std::move(web_socket_request),
308 std::move(data_pipe.consumer_handle), std::move(client_ptr_));
309 }
310
311 void WaitForConnectCompletion() {
312 DCHECK(!run_loop_);
313
314 if (receive_stream_.is_valid())
315 return;
316
317 base::RunLoop run_loop;
318 run_loop_ = &run_loop;
319 run_loop.Run();
320 run_loop_ = nullptr;
321 }
322
323 void Send(const std::string& message) {
324 DCHECK(!message.empty());
325
326 uint32_t size = static_cast<uint32_t>(message.size());
327 write_send_stream_->Write(
328 &message[0], size,
329 base::Bind(&WebSocketClientImpl::OnFinishedWritingSendStream,
330 base::Unretained(this), size));
331 }
332
333 void WaitForMessage(size_t count) {
334 DCHECK(!run_loop_);
335
336 if (received_messages_.size() >= count)
337 return;
338 wait_for_message_count_ = count;
339 base::RunLoop run_loop;
340 run_loop_ = &run_loop;
341 run_loop.Run();
342 run_loop_ = nullptr;
343 }
344
345 std::vector<std::string>& received_messages() { return received_messages_; }
346
347 private:
348 // WebSocketClient implementation.
349 void DidConnect(const String& selected_subprotocol,
350 const String& extensions,
351 ScopedDataPipeConsumerHandle receive_stream) override {
352 receive_stream_ = std::move(receive_stream);
353 read_receive_stream_.reset(new WebSocketReadQueue(receive_stream_.get()));
354
355 web_socket_->FlowControl(2048);
356 if (run_loop_)
357 run_loop_->Quit();
358 }
359
360 void DidReceiveData(bool fin,
361 WebSocket::MessageType type,
362 uint32_t num_bytes) override {
363 DCHECK(num_bytes > 0);
364
365 read_receive_stream_->Read(
366 num_bytes,
367 base::Bind(&WebSocketClientImpl::OnFinishedReadingReceiveStream,
368 base::Unretained(this), num_bytes));
369 }
370
371 void DidReceiveFlowControl(int64_t quota) override {}
372
373 void DidFail(const String& message) override {}
374
375 void DidClose(bool was_clean, uint16_t code, const String& reason) override {}
376
377 void OnFinishedWritingSendStream(uint32_t num_bytes, const char* buffer) {
378 EXPECT_TRUE(buffer);
379
380 web_socket_->Send(true, WebSocket::MessageType::TEXT, num_bytes);
381 }
382
383 void OnFinishedReadingReceiveStream(uint32_t num_bytes, const char* data) {
384 EXPECT_TRUE(data);
385
386 received_messages_.push_back(std::string(data, num_bytes));
387 if (run_loop_ && received_messages_.size() >= wait_for_message_count_) {
388 wait_for_message_count_ = 0;
389 run_loop_->Quit();
390 }
391 }
392
393 WebSocketClientPtr client_ptr_;
394 Binding<WebSocketClient> binding_;
395 WebSocketPtr web_socket_;
396
397 ScopedDataPipeProducerHandle send_stream_;
398 scoped_ptr<WebSocketWriteQueue> write_send_stream_;
399
400 ScopedDataPipeConsumerHandle receive_stream_;
401 scoped_ptr<WebSocketReadQueue> read_receive_stream_;
402
403 std::vector<std::string> received_messages_;
404 size_t wait_for_message_count_;
405
406 // Pointing to a stack-allocated RunLoop instance.
407 base::RunLoop* run_loop_;
408
409 DISALLOW_COPY_AND_ASSIGN(WebSocketClientImpl);
410 };
411
412 class HttpConnectionDelegateImpl : public HttpConnectionDelegate {
413 public:
414 struct PendingRequest {
415 HttpRequestPtr request;
416 OnReceivedRequestCallback callback;
417 };
418
419 HttpConnectionDelegateImpl(HttpConnectionPtr connection,
420 InterfaceRequest<HttpConnectionDelegate> request)
421 : connection_(std::move(connection)),
422 binding_(this, std::move(request)),
423 wait_for_request_count_(0),
424 run_loop_(nullptr) {}
425 ~HttpConnectionDelegateImpl() override {}
426
427 // HttpConnectionDelegate implementation:
428 void OnReceivedRequest(HttpRequestPtr request,
429 const OnReceivedRequestCallback& callback) override {
430 linked_ptr<PendingRequest> pending_request(new PendingRequest);
431 pending_request->request = std::move(request);
432 pending_request->callback = callback;
433 pending_requests_.push_back(pending_request);
434 if (run_loop_ && pending_requests_.size() >= wait_for_request_count_) {
435 wait_for_request_count_ = 0;
436 run_loop_->Quit();
437 }
438 }
439
440 void OnReceivedWebSocketRequest(
441 HttpRequestPtr request,
442 const OnReceivedWebSocketRequestCallback& callback) override {
443 web_socket_.reset(new WebSocketClientImpl());
444
445 web_socket_->AcceptConnectRequest(callback);
446
447 if (run_loop_)
448 run_loop_->Quit();
449 }
450
451 void SendResponse(HttpResponsePtr response) {
452 ASSERT_FALSE(pending_requests_.empty());
453 linked_ptr<PendingRequest> request = pending_requests_[0];
454 pending_requests_.erase(pending_requests_.begin());
455 request->callback.Run(std::move(response));
456 }
457
458 void WaitForRequest(size_t count) {
459 DCHECK(!run_loop_);
460
461 if (pending_requests_.size() >= count)
462 return;
463
464 wait_for_request_count_ = count;
465 base::RunLoop run_loop;
466 run_loop_ = &run_loop;
467 run_loop.Run();
468 run_loop_ = nullptr;
469 }
470
471 void WaitForWebSocketRequest() {
472 DCHECK(!run_loop_);
473
474 if (web_socket_)
475 return;
476
477 base::RunLoop run_loop;
478 run_loop_ = &run_loop;
479 run_loop.Run();
480 run_loop_ = nullptr;
481 }
482
483 std::vector<linked_ptr<PendingRequest>>& pending_requests() {
484 return pending_requests_;
485 }
486
487 WebSocketClientImpl* web_socket() { return web_socket_.get(); }
488
489 private:
490 HttpConnectionPtr connection_;
491 Binding<HttpConnectionDelegate> binding_;
492 std::vector<linked_ptr<PendingRequest>> pending_requests_;
493 size_t wait_for_request_count_;
494 scoped_ptr<WebSocketClientImpl> web_socket_;
495
496 // Pointing to a stack-allocated RunLoop instance.
497 base::RunLoop* run_loop_;
498
499 DISALLOW_COPY_AND_ASSIGN(HttpConnectionDelegateImpl);
500 };
501
502 class HttpServerDelegateImpl : public HttpServerDelegate {
503 public:
504 explicit HttpServerDelegateImpl(HttpServerDelegatePtr* delegate_ptr)
505 : binding_(this, delegate_ptr),
506 wait_for_connection_count_(0),
507 run_loop_(nullptr) {}
508 ~HttpServerDelegateImpl() override {}
509
510 // HttpServerDelegate implementation.
511 void OnConnected(HttpConnectionPtr connection,
512 InterfaceRequest<HttpConnectionDelegate> delegate) override {
513 connections_.push_back(make_linked_ptr(new HttpConnectionDelegateImpl(
514 std::move(connection), std::move(delegate))));
515 if (run_loop_ && connections_.size() >= wait_for_connection_count_) {
516 wait_for_connection_count_ = 0;
517 run_loop_->Quit();
518 }
519 }
520
521 void WaitForConnection(size_t count) {
522 DCHECK(!run_loop_);
523
524 if (connections_.size() >= count)
525 return;
526
527 wait_for_connection_count_ = count;
528 base::RunLoop run_loop;
529 run_loop_ = &run_loop;
530 run_loop.Run();
531 run_loop_ = nullptr;
532 }
533
534 std::vector<linked_ptr<HttpConnectionDelegateImpl>>& connections() {
535 return connections_;
536 }
537
538 private:
539 Binding<HttpServerDelegate> binding_;
540 std::vector<linked_ptr<HttpConnectionDelegateImpl>> connections_;
541 size_t wait_for_connection_count_;
542 // Pointing to a stack-allocated RunLoop instance.
543 base::RunLoop* run_loop_;
544
545 DISALLOW_COPY_AND_ASSIGN(HttpServerDelegateImpl);
546 };
547
548 class HttpServerTest : public test::ShellTest {
549 public:
550 HttpServerTest()
551 : ShellTest("exe:network_service_unittests") {}
552 ~HttpServerTest() override {}
553
554 protected:
555 void SetUp() override {
556 ShellTest::SetUp();
557
558 scoped_ptr<Connection> connection =
559 connector()->Connect("mojo:network_service");
560 connection->GetInterface(&network_service_);
561 connection->GetInterface(&web_socket_factory_);
562 }
563
564 scoped_ptr<base::MessageLoop> CreateMessageLoop() override {
565 return make_scoped_ptr(new base::MessageLoop(base::MessageLoop::TYPE_IO));
566 }
567
568 void CreateHttpServer(HttpServerDelegatePtr delegate,
569 NetAddressPtr* out_bound_to) {
570 base::RunLoop loop;
571 network_service_->CreateHttpServer(
572 GetLocalHostWithAnyPort(), std::move(delegate),
573 [out_bound_to, &loop](NetworkErrorPtr result, NetAddressPtr bound_to) {
574 ASSERT_EQ(net::OK, result->code);
575 EXPECT_NE(0u, bound_to->ipv4->port);
576 *out_bound_to = std::move(bound_to);
577 loop.Quit();
578 });
579 loop.Run();
580 }
581
582 NetworkServicePtr network_service_;
583 WebSocketFactoryPtr web_socket_factory_;
584
585 private:
586 DISALLOW_COPY_AND_ASSIGN(HttpServerTest);
587 };
588
589 } // namespace
590
591 TEST_F(HttpServerTest, BasicHttpRequestResponse) {
592 NetAddressPtr bound_to;
593 HttpServerDelegatePtr server_delegate_ptr;
594 HttpServerDelegateImpl server_delegate_impl(&server_delegate_ptr);
595 CreateHttpServer(std::move(server_delegate_ptr), &bound_to);
596
597 TestHttpClient client;
598 client.Connect(bound_to.To<net::IPEndPoint>());
599
600 server_delegate_impl.WaitForConnection(1);
601 HttpConnectionDelegateImpl& connection =
602 *server_delegate_impl.connections()[0];
603
604 TestRequest request_data = {"HEAD", "/test", {{"Hello", "World"}}, nullptr};
605 client.Send(MakeRequestMessage(request_data));
606
607 connection.WaitForRequest(1);
608
609 CheckRequest(request_data,
610 std::move(connection.pending_requests()[0]->request));
611
612 TestResponse response_data = {200, {{"Content-Length", "4"}}, nullptr};
613 connection.SendResponse(MakeResponseStruct(response_data));
614 // This causes the underlying TCP connection to be closed. The client can
615 // determine the end of the response based on that.
616 server_delegate_impl.connections().clear();
617
618 std::string response_message;
619 client.ReadResponse(&response_message);
620
621 CheckResponse(response_data, response_message);
622 }
623
624 TEST_F(HttpServerTest, HttpRequestResponseWithBody) {
625 NetAddressPtr bound_to;
626 HttpServerDelegatePtr server_delegate_ptr;
627 HttpServerDelegateImpl server_delegate_impl(&server_delegate_ptr);
628 CreateHttpServer(std::move(server_delegate_ptr), &bound_to);
629
630 TestHttpClient client;
631 client.Connect(bound_to.To<net::IPEndPoint>());
632
633 server_delegate_impl.WaitForConnection(1);
634 HttpConnectionDelegateImpl& connection =
635 *server_delegate_impl.connections()[0];
636
637 TestRequest request_data = {
638 "Post",
639 "/test",
640 {{"Hello", "World"},
641 {"Content-Length", "23"},
642 {"Content-Type", "text/plain"}},
643 make_scoped_ptr(new std::string("This is a test request!"))};
644 client.Send(MakeRequestMessage(request_data));
645
646 connection.WaitForRequest(1);
647
648 CheckRequest(request_data,
649 std::move(connection.pending_requests()[0]->request));
650
651 TestResponse response_data = {
652 200,
653 {{"Content-Length", "26"}},
654 make_scoped_ptr(new std::string("This is a test response..."))};
655 connection.SendResponse(MakeResponseStruct(response_data));
656
657 std::string response_message;
658 client.ReadResponse(&response_message);
659
660 CheckResponse(response_data, response_message);
661 }
662
663 TEST_F(HttpServerTest, WebSocket) {
664 NetAddressPtr bound_to;
665 HttpServerDelegatePtr server_delegate_ptr;
666 HttpServerDelegateImpl server_delegate_impl(&server_delegate_ptr);
667 CreateHttpServer(std::move(server_delegate_ptr), &bound_to);
668
669 WebSocketPtr web_socket_ptr;
670 web_socket_factory_->CreateWebSocket(GetProxy(&web_socket_ptr));
671 WebSocketClientImpl socket_0;
672 socket_0.Connect(
673 std::move(web_socket_ptr),
674 base::StringPrintf("ws://127.0.0.1:%d/hello", bound_to->ipv4->port));
675
676 server_delegate_impl.WaitForConnection(1);
677 HttpConnectionDelegateImpl& connection =
678 *server_delegate_impl.connections()[0];
679
680 connection.WaitForWebSocketRequest();
681 WebSocketClientImpl& socket_1 = *connection.web_socket();
682
683 socket_1.WaitForConnectCompletion();
684 socket_0.WaitForConnectCompletion();
685
686 socket_0.Send("Hello");
687 socket_0.Send("world!");
688
689 socket_1.WaitForMessage(2);
690 EXPECT_EQ("Hello", socket_1.received_messages()[0]);
691 EXPECT_EQ("world!", socket_1.received_messages()[1]);
692
693 socket_1.Send("How do");
694 socket_1.Send("you do?");
695
696 socket_0.WaitForMessage(2);
697 EXPECT_EQ("How do", socket_0.received_messages()[0]);
698 EXPECT_EQ("you do?", socket_0.received_messages()[1]);
699 }
700
701 } // namespace mojo
OLDNEW
« no previous file with comments | « mojo/services/network/http_server_impl.cc ('k') | mojo/services/network/main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698