OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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 "net/socket_stream/socket_stream.h" | |
6 | |
7 #include <string> | |
8 #include <vector> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/bind_helpers.h" | |
12 #include "base/callback.h" | |
13 #include "base/strings/utf_string_conversions.h" | |
14 #include "net/base/auth.h" | |
15 #include "net/base/net_log.h" | |
16 #include "net/base/net_log_unittest.h" | |
17 #include "net/base/test_completion_callback.h" | |
18 #include "net/dns/mock_host_resolver.h" | |
19 #include "net/http/http_network_session.h" | |
20 #include "net/proxy/proxy_service.h" | |
21 #include "net/socket/socket_test_util.h" | |
22 #include "net/url_request/url_request_test_util.h" | |
23 #include "testing/gtest/include/gtest/gtest.h" | |
24 #include "testing/platform_test.h" | |
25 | |
26 using base::ASCIIToUTF16; | |
27 | |
28 namespace net { | |
29 | |
30 namespace { | |
31 | |
32 struct SocketStreamEvent { | |
33 enum EventType { | |
34 EVENT_START_OPEN_CONNECTION, EVENT_CONNECTED, EVENT_SENT_DATA, | |
35 EVENT_RECEIVED_DATA, EVENT_CLOSE, EVENT_AUTH_REQUIRED, EVENT_ERROR, | |
36 }; | |
37 | |
38 SocketStreamEvent(EventType type, | |
39 SocketStream* socket_stream, | |
40 int num, | |
41 const std::string& str, | |
42 AuthChallengeInfo* auth_challenge_info, | |
43 int error) | |
44 : event_type(type), socket(socket_stream), number(num), data(str), | |
45 auth_info(auth_challenge_info), error_code(error) {} | |
46 | |
47 EventType event_type; | |
48 SocketStream* socket; | |
49 int number; | |
50 std::string data; | |
51 scoped_refptr<AuthChallengeInfo> auth_info; | |
52 int error_code; | |
53 }; | |
54 | |
55 class SocketStreamEventRecorder : public SocketStream::Delegate { | |
56 public: | |
57 // |callback| will be run when the OnClose() or OnError() method is called. | |
58 // For OnClose(), |callback| is called with OK. For OnError(), it's called | |
59 // with the error code. | |
60 explicit SocketStreamEventRecorder(const CompletionCallback& callback) | |
61 : callback_(callback) {} | |
62 ~SocketStreamEventRecorder() override {} | |
63 | |
64 void SetOnStartOpenConnection( | |
65 const base::Callback<int(SocketStreamEvent*)>& callback) { | |
66 on_start_open_connection_ = callback; | |
67 } | |
68 void SetOnConnected( | |
69 const base::Callback<void(SocketStreamEvent*)>& callback) { | |
70 on_connected_ = callback; | |
71 } | |
72 void SetOnSentData( | |
73 const base::Callback<void(SocketStreamEvent*)>& callback) { | |
74 on_sent_data_ = callback; | |
75 } | |
76 void SetOnReceivedData( | |
77 const base::Callback<void(SocketStreamEvent*)>& callback) { | |
78 on_received_data_ = callback; | |
79 } | |
80 void SetOnClose(const base::Callback<void(SocketStreamEvent*)>& callback) { | |
81 on_close_ = callback; | |
82 } | |
83 void SetOnAuthRequired( | |
84 const base::Callback<void(SocketStreamEvent*)>& callback) { | |
85 on_auth_required_ = callback; | |
86 } | |
87 void SetOnError(const base::Callback<void(SocketStreamEvent*)>& callback) { | |
88 on_error_ = callback; | |
89 } | |
90 | |
91 int OnStartOpenConnection(SocketStream* socket, | |
92 const CompletionCallback& callback) override { | |
93 connection_callback_ = callback; | |
94 events_.push_back( | |
95 SocketStreamEvent(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
96 socket, 0, std::string(), NULL, OK)); | |
97 if (!on_start_open_connection_.is_null()) | |
98 return on_start_open_connection_.Run(&events_.back()); | |
99 return OK; | |
100 } | |
101 void OnConnected(SocketStream* socket, | |
102 int num_pending_send_allowed) override { | |
103 events_.push_back( | |
104 SocketStreamEvent(SocketStreamEvent::EVENT_CONNECTED, | |
105 socket, num_pending_send_allowed, std::string(), | |
106 NULL, OK)); | |
107 if (!on_connected_.is_null()) | |
108 on_connected_.Run(&events_.back()); | |
109 } | |
110 void OnSentData(SocketStream* socket, int amount_sent) override { | |
111 events_.push_back( | |
112 SocketStreamEvent(SocketStreamEvent::EVENT_SENT_DATA, socket, | |
113 amount_sent, std::string(), NULL, OK)); | |
114 if (!on_sent_data_.is_null()) | |
115 on_sent_data_.Run(&events_.back()); | |
116 } | |
117 void OnReceivedData(SocketStream* socket, | |
118 const char* data, | |
119 int len) override { | |
120 events_.push_back( | |
121 SocketStreamEvent(SocketStreamEvent::EVENT_RECEIVED_DATA, socket, len, | |
122 std::string(data, len), NULL, OK)); | |
123 if (!on_received_data_.is_null()) | |
124 on_received_data_.Run(&events_.back()); | |
125 } | |
126 void OnClose(SocketStream* socket) override { | |
127 events_.push_back( | |
128 SocketStreamEvent(SocketStreamEvent::EVENT_CLOSE, socket, 0, | |
129 std::string(), NULL, OK)); | |
130 if (!on_close_.is_null()) | |
131 on_close_.Run(&events_.back()); | |
132 if (!callback_.is_null()) | |
133 callback_.Run(OK); | |
134 } | |
135 void OnAuthRequired(SocketStream* socket, | |
136 AuthChallengeInfo* auth_info) override { | |
137 events_.push_back( | |
138 SocketStreamEvent(SocketStreamEvent::EVENT_AUTH_REQUIRED, socket, 0, | |
139 std::string(), auth_info, OK)); | |
140 if (!on_auth_required_.is_null()) | |
141 on_auth_required_.Run(&events_.back()); | |
142 } | |
143 void OnError(const SocketStream* socket, int error) override { | |
144 events_.push_back( | |
145 SocketStreamEvent(SocketStreamEvent::EVENT_ERROR, NULL, 0, | |
146 std::string(), NULL, error)); | |
147 if (!on_error_.is_null()) | |
148 on_error_.Run(&events_.back()); | |
149 if (!callback_.is_null()) | |
150 callback_.Run(error); | |
151 } | |
152 | |
153 void DoClose(SocketStreamEvent* event) { | |
154 event->socket->Close(); | |
155 } | |
156 void DoRestartWithAuth(SocketStreamEvent* event) { | |
157 VLOG(1) << "RestartWithAuth username=" << credentials_.username() | |
158 << " password=" << credentials_.password(); | |
159 event->socket->RestartWithAuth(credentials_); | |
160 } | |
161 void SetAuthInfo(const AuthCredentials& credentials) { | |
162 credentials_ = credentials; | |
163 } | |
164 // Wakes up the SocketStream waiting for completion of OnStartOpenConnection() | |
165 // of its delegate. | |
166 void CompleteConnection(int result) { | |
167 connection_callback_.Run(result); | |
168 } | |
169 | |
170 const std::vector<SocketStreamEvent>& GetSeenEvents() const { | |
171 return events_; | |
172 } | |
173 | |
174 private: | |
175 std::vector<SocketStreamEvent> events_; | |
176 base::Callback<int(SocketStreamEvent*)> on_start_open_connection_; | |
177 base::Callback<void(SocketStreamEvent*)> on_connected_; | |
178 base::Callback<void(SocketStreamEvent*)> on_sent_data_; | |
179 base::Callback<void(SocketStreamEvent*)> on_received_data_; | |
180 base::Callback<void(SocketStreamEvent*)> on_close_; | |
181 base::Callback<void(SocketStreamEvent*)> on_auth_required_; | |
182 base::Callback<void(SocketStreamEvent*)> on_error_; | |
183 const CompletionCallback callback_; | |
184 CompletionCallback connection_callback_; | |
185 AuthCredentials credentials_; | |
186 | |
187 DISALLOW_COPY_AND_ASSIGN(SocketStreamEventRecorder); | |
188 }; | |
189 | |
190 // This is used for the test OnErrorDetachDelegate. | |
191 class SelfDeletingDelegate : public SocketStream::Delegate { | |
192 public: | |
193 // |callback| must cause the test message loop to exit when called. | |
194 explicit SelfDeletingDelegate(const CompletionCallback& callback) | |
195 : socket_stream_(), callback_(callback) {} | |
196 | |
197 ~SelfDeletingDelegate() override {} | |
198 | |
199 // Call DetachDelegate(), delete |this|, then run the callback. | |
200 void OnError(const SocketStream* socket, int error) override { | |
201 // callback_ will be deleted when we delete |this|, so copy it to call it | |
202 // afterwards. | |
203 CompletionCallback callback = callback_; | |
204 socket_stream_->DetachDelegate(); | |
205 delete this; | |
206 callback.Run(OK); | |
207 } | |
208 | |
209 // This can't be passed in the constructor because this object needs to be | |
210 // created before SocketStream. | |
211 void set_socket_stream(const scoped_refptr<SocketStream>& socket_stream) { | |
212 socket_stream_ = socket_stream; | |
213 EXPECT_EQ(socket_stream_->delegate(), this); | |
214 } | |
215 | |
216 void OnConnected(SocketStream* socket, | |
217 int max_pending_send_allowed) override { | |
218 ADD_FAILURE() << "OnConnected() should not be called"; | |
219 } | |
220 void OnSentData(SocketStream* socket, int amount_sent) override { | |
221 ADD_FAILURE() << "OnSentData() should not be called"; | |
222 } | |
223 void OnReceivedData(SocketStream* socket, | |
224 const char* data, | |
225 int len) override { | |
226 ADD_FAILURE() << "OnReceivedData() should not be called"; | |
227 } | |
228 void OnClose(SocketStream* socket) override { | |
229 ADD_FAILURE() << "OnClose() should not be called"; | |
230 } | |
231 | |
232 private: | |
233 scoped_refptr<SocketStream> socket_stream_; | |
234 const CompletionCallback callback_; | |
235 | |
236 DISALLOW_COPY_AND_ASSIGN(SelfDeletingDelegate); | |
237 }; | |
238 | |
239 class TestURLRequestContextWithProxy : public TestURLRequestContext { | |
240 public: | |
241 explicit TestURLRequestContextWithProxy(const std::string& proxy) | |
242 : TestURLRequestContext(true) { | |
243 context_storage_.set_proxy_service(ProxyService::CreateFixed(proxy)); | |
244 Init(); | |
245 } | |
246 ~TestURLRequestContextWithProxy() override {} | |
247 }; | |
248 | |
249 class TestSocketStreamNetworkDelegate : public TestNetworkDelegate { | |
250 public: | |
251 TestSocketStreamNetworkDelegate() | |
252 : before_connect_result_(OK) {} | |
253 ~TestSocketStreamNetworkDelegate() override {} | |
254 | |
255 int OnBeforeSocketStreamConnect(SocketStream* stream, | |
256 const CompletionCallback& callback) override { | |
257 return before_connect_result_; | |
258 } | |
259 | |
260 void SetBeforeConnectResult(int result) { | |
261 before_connect_result_ = result; | |
262 } | |
263 | |
264 private: | |
265 int before_connect_result_; | |
266 }; | |
267 | |
268 } // namespace | |
269 | |
270 class SocketStreamTest : public PlatformTest { | |
271 public: | |
272 ~SocketStreamTest() override {} | |
273 void SetUp() override { | |
274 mock_socket_factory_.reset(); | |
275 handshake_request_ = kWebSocketHandshakeRequest; | |
276 handshake_response_ = kWebSocketHandshakeResponse; | |
277 } | |
278 void TearDown() override { mock_socket_factory_.reset(); } | |
279 | |
280 virtual void SetWebSocketHandshakeMessage( | |
281 const char* request, const char* response) { | |
282 handshake_request_ = request; | |
283 handshake_response_ = response; | |
284 } | |
285 virtual void AddWebSocketMessage(const std::string& message) { | |
286 messages_.push_back(message); | |
287 } | |
288 | |
289 virtual MockClientSocketFactory* GetMockClientSocketFactory() { | |
290 mock_socket_factory_.reset(new MockClientSocketFactory); | |
291 return mock_socket_factory_.get(); | |
292 } | |
293 | |
294 // Functions for SocketStreamEventRecorder to handle calls to the | |
295 // SocketStream::Delegate methods from the SocketStream. | |
296 | |
297 virtual void DoSendWebSocketHandshake(SocketStreamEvent* event) { | |
298 event->socket->SendData( | |
299 handshake_request_.data(), handshake_request_.size()); | |
300 } | |
301 | |
302 virtual void DoCloseFlushPendingWriteTest(SocketStreamEvent* event) { | |
303 // handshake response received. | |
304 for (size_t i = 0; i < messages_.size(); i++) { | |
305 std::vector<char> frame; | |
306 frame.push_back('\0'); | |
307 frame.insert(frame.end(), messages_[i].begin(), messages_[i].end()); | |
308 frame.push_back('\xff'); | |
309 EXPECT_TRUE(event->socket->SendData(&frame[0], frame.size())); | |
310 } | |
311 // Actual StreamSocket close must happen after all frames queued by | |
312 // SendData above are sent out. | |
313 event->socket->Close(); | |
314 } | |
315 | |
316 virtual void DoCloseFlushPendingWriteTestWithSetContextNull( | |
317 SocketStreamEvent* event) { | |
318 event->socket->DetachContext(); | |
319 // handshake response received. | |
320 for (size_t i = 0; i < messages_.size(); i++) { | |
321 std::vector<char> frame; | |
322 frame.push_back('\0'); | |
323 frame.insert(frame.end(), messages_[i].begin(), messages_[i].end()); | |
324 frame.push_back('\xff'); | |
325 EXPECT_TRUE(event->socket->SendData(&frame[0], frame.size())); | |
326 } | |
327 // Actual StreamSocket close must happen after all frames queued by | |
328 // SendData above are sent out. | |
329 event->socket->Close(); | |
330 } | |
331 | |
332 virtual void DoFailByTooBigDataAndClose(SocketStreamEvent* event) { | |
333 std::string frame(event->number + 1, 0x00); | |
334 VLOG(1) << event->number; | |
335 EXPECT_FALSE(event->socket->SendData(&frame[0], frame.size())); | |
336 event->socket->Close(); | |
337 } | |
338 | |
339 virtual int DoSwitchToSpdyTest(SocketStreamEvent* event) { | |
340 return ERR_PROTOCOL_SWITCHED; | |
341 } | |
342 | |
343 // Notifies |io_test_callback_| of that this method is called, and keeps the | |
344 // SocketStream waiting. | |
345 virtual int DoIOPending(SocketStreamEvent* event) { | |
346 io_test_callback_.callback().Run(OK); | |
347 return ERR_IO_PENDING; | |
348 } | |
349 | |
350 static const char kWebSocketHandshakeRequest[]; | |
351 static const char kWebSocketHandshakeResponse[]; | |
352 | |
353 protected: | |
354 TestCompletionCallback io_test_callback_; | |
355 | |
356 private: | |
357 std::string handshake_request_; | |
358 std::string handshake_response_; | |
359 std::vector<std::string> messages_; | |
360 | |
361 scoped_ptr<MockClientSocketFactory> mock_socket_factory_; | |
362 }; | |
363 | |
364 const char SocketStreamTest::kWebSocketHandshakeRequest[] = | |
365 "GET /demo HTTP/1.1\r\n" | |
366 "Host: example.com\r\n" | |
367 "Connection: Upgrade\r\n" | |
368 "Sec-WebSocket-Key2: 12998 5 Y3 1 .P00\r\n" | |
369 "Sec-WebSocket-Protocol: sample\r\n" | |
370 "Upgrade: WebSocket\r\n" | |
371 "Sec-WebSocket-Key1: 4 @1 46546xW%0l 1 5\r\n" | |
372 "Origin: http://example.com\r\n" | |
373 "\r\n" | |
374 "^n:ds[4U"; | |
375 | |
376 const char SocketStreamTest::kWebSocketHandshakeResponse[] = | |
377 "HTTP/1.1 101 WebSocket Protocol Handshake\r\n" | |
378 "Upgrade: WebSocket\r\n" | |
379 "Connection: Upgrade\r\n" | |
380 "Sec-WebSocket-Origin: http://example.com\r\n" | |
381 "Sec-WebSocket-Location: ws://example.com/demo\r\n" | |
382 "Sec-WebSocket-Protocol: sample\r\n" | |
383 "\r\n" | |
384 "8jKS'y:G*Co,Wxa-"; | |
385 | |
386 TEST_F(SocketStreamTest, CloseFlushPendingWrite) { | |
387 TestCompletionCallback test_callback; | |
388 | |
389 scoped_ptr<SocketStreamEventRecorder> delegate( | |
390 new SocketStreamEventRecorder(test_callback.callback())); | |
391 delegate->SetOnConnected(base::Bind( | |
392 &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this))); | |
393 delegate->SetOnReceivedData(base::Bind( | |
394 &SocketStreamTest::DoCloseFlushPendingWriteTest, | |
395 base::Unretained(this))); | |
396 | |
397 TestURLRequestContext context; | |
398 | |
399 scoped_refptr<SocketStream> socket_stream( | |
400 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
401 &context, NULL)); | |
402 | |
403 MockWrite data_writes[] = { | |
404 MockWrite(SocketStreamTest::kWebSocketHandshakeRequest), | |
405 MockWrite(ASYNC, "\0message1\xff", 10), | |
406 MockWrite(ASYNC, "\0message2\xff", 10) | |
407 }; | |
408 MockRead data_reads[] = { | |
409 MockRead(SocketStreamTest::kWebSocketHandshakeResponse), | |
410 // Server doesn't close the connection after handshake. | |
411 MockRead(ASYNC, ERR_IO_PENDING) | |
412 }; | |
413 AddWebSocketMessage("message1"); | |
414 AddWebSocketMessage("message2"); | |
415 | |
416 DelayedSocketData data_provider( | |
417 1, data_reads, arraysize(data_reads), | |
418 data_writes, arraysize(data_writes)); | |
419 | |
420 MockClientSocketFactory* mock_socket_factory = | |
421 GetMockClientSocketFactory(); | |
422 mock_socket_factory->AddSocketDataProvider(&data_provider); | |
423 | |
424 socket_stream->SetClientSocketFactory(mock_socket_factory); | |
425 | |
426 socket_stream->Connect(); | |
427 | |
428 test_callback.WaitForResult(); | |
429 | |
430 EXPECT_TRUE(data_provider.at_read_eof()); | |
431 EXPECT_TRUE(data_provider.at_write_eof()); | |
432 | |
433 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
434 ASSERT_EQ(7U, events.size()); | |
435 | |
436 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
437 events[0].event_type); | |
438 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
439 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type); | |
440 EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type); | |
441 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type); | |
442 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type); | |
443 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type); | |
444 } | |
445 | |
446 TEST_F(SocketStreamTest, ResolveFailure) { | |
447 TestCompletionCallback test_callback; | |
448 | |
449 scoped_ptr<SocketStreamEventRecorder> delegate( | |
450 new SocketStreamEventRecorder(test_callback.callback())); | |
451 | |
452 // Make resolver fail. | |
453 TestURLRequestContext context; | |
454 scoped_ptr<MockHostResolver> mock_host_resolver( | |
455 new MockHostResolver()); | |
456 mock_host_resolver->rules()->AddSimulatedFailure("example.com"); | |
457 context.set_host_resolver(mock_host_resolver.get()); | |
458 | |
459 scoped_refptr<SocketStream> socket_stream( | |
460 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
461 &context, NULL)); | |
462 | |
463 // No read/write on socket is expected. | |
464 StaticSocketDataProvider data_provider(NULL, 0, NULL, 0); | |
465 MockClientSocketFactory* mock_socket_factory = | |
466 GetMockClientSocketFactory(); | |
467 mock_socket_factory->AddSocketDataProvider(&data_provider); | |
468 socket_stream->SetClientSocketFactory(mock_socket_factory); | |
469 | |
470 socket_stream->Connect(); | |
471 | |
472 test_callback.WaitForResult(); | |
473 | |
474 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
475 ASSERT_EQ(2U, events.size()); | |
476 | |
477 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[0].event_type); | |
478 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[1].event_type); | |
479 } | |
480 | |
481 TEST_F(SocketStreamTest, ExceedMaxPendingSendAllowed) { | |
482 TestCompletionCallback test_callback; | |
483 | |
484 scoped_ptr<SocketStreamEventRecorder> delegate( | |
485 new SocketStreamEventRecorder(test_callback.callback())); | |
486 delegate->SetOnConnected(base::Bind( | |
487 &SocketStreamTest::DoFailByTooBigDataAndClose, base::Unretained(this))); | |
488 | |
489 TestURLRequestContext context; | |
490 | |
491 scoped_refptr<SocketStream> socket_stream( | |
492 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
493 &context, NULL)); | |
494 | |
495 DelayedSocketData data_provider(1, NULL, 0, NULL, 0); | |
496 | |
497 MockClientSocketFactory* mock_socket_factory = | |
498 GetMockClientSocketFactory(); | |
499 mock_socket_factory->AddSocketDataProvider(&data_provider); | |
500 | |
501 socket_stream->SetClientSocketFactory(mock_socket_factory); | |
502 | |
503 socket_stream->Connect(); | |
504 | |
505 test_callback.WaitForResult(); | |
506 | |
507 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
508 ASSERT_EQ(4U, events.size()); | |
509 | |
510 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
511 events[0].event_type); | |
512 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
513 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[2].event_type); | |
514 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type); | |
515 } | |
516 | |
517 TEST_F(SocketStreamTest, BasicAuthProxy) { | |
518 MockClientSocketFactory mock_socket_factory; | |
519 MockWrite data_writes1[] = { | |
520 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" | |
521 "Host: example.com\r\n" | |
522 "Proxy-Connection: keep-alive\r\n\r\n"), | |
523 }; | |
524 MockRead data_reads1[] = { | |
525 MockRead("HTTP/1.1 407 Proxy Authentication Required\r\n"), | |
526 MockRead("Proxy-Authenticate: Basic realm=\"MyRealm1\"\r\n"), | |
527 MockRead("\r\n"), | |
528 }; | |
529 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), | |
530 data_writes1, arraysize(data_writes1)); | |
531 mock_socket_factory.AddSocketDataProvider(&data1); | |
532 | |
533 MockWrite data_writes2[] = { | |
534 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" | |
535 "Host: example.com\r\n" | |
536 "Proxy-Connection: keep-alive\r\n" | |
537 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), | |
538 }; | |
539 MockRead data_reads2[] = { | |
540 MockRead("HTTP/1.1 200 Connection Established\r\n"), | |
541 MockRead("Proxy-agent: Apache/2.2.8\r\n"), | |
542 MockRead("\r\n"), | |
543 // SocketStream::DoClose is run asynchronously. Socket can be read after | |
544 // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate | |
545 // server doesn't close the connection. | |
546 MockRead(ASYNC, ERR_IO_PENDING) | |
547 }; | |
548 StaticSocketDataProvider data2(data_reads2, arraysize(data_reads2), | |
549 data_writes2, arraysize(data_writes2)); | |
550 mock_socket_factory.AddSocketDataProvider(&data2); | |
551 | |
552 TestCompletionCallback test_callback; | |
553 | |
554 scoped_ptr<SocketStreamEventRecorder> delegate( | |
555 new SocketStreamEventRecorder(test_callback.callback())); | |
556 delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose, | |
557 base::Unretained(delegate.get()))); | |
558 delegate->SetAuthInfo(AuthCredentials(ASCIIToUTF16("foo"), | |
559 ASCIIToUTF16("bar"))); | |
560 delegate->SetOnAuthRequired(base::Bind( | |
561 &SocketStreamEventRecorder::DoRestartWithAuth, | |
562 base::Unretained(delegate.get()))); | |
563 | |
564 TestURLRequestContextWithProxy context("myproxy:70"); | |
565 | |
566 scoped_refptr<SocketStream> socket_stream( | |
567 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
568 &context, NULL)); | |
569 | |
570 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
571 | |
572 socket_stream->Connect(); | |
573 | |
574 test_callback.WaitForResult(); | |
575 | |
576 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
577 ASSERT_EQ(5U, events.size()); | |
578 | |
579 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
580 events[0].event_type); | |
581 EXPECT_EQ(SocketStreamEvent::EVENT_AUTH_REQUIRED, events[1].event_type); | |
582 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[2].event_type); | |
583 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[3].event_type); | |
584 EXPECT_EQ(ERR_ABORTED, events[3].error_code); | |
585 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[4].event_type); | |
586 | |
587 // TODO(eroman): Add back NetLogTest here... | |
588 } | |
589 | |
590 TEST_F(SocketStreamTest, BasicAuthProxyWithAuthCache) { | |
591 MockClientSocketFactory mock_socket_factory; | |
592 MockWrite data_writes[] = { | |
593 // WebSocket(SocketStream) always uses CONNECT when it is configured to use | |
594 // proxy so the port may not be 443. | |
595 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" | |
596 "Host: example.com\r\n" | |
597 "Proxy-Connection: keep-alive\r\n" | |
598 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), | |
599 }; | |
600 MockRead data_reads[] = { | |
601 MockRead("HTTP/1.1 200 Connection Established\r\n"), | |
602 MockRead("Proxy-agent: Apache/2.2.8\r\n"), | |
603 MockRead("\r\n"), | |
604 MockRead(ASYNC, ERR_IO_PENDING) | |
605 }; | |
606 StaticSocketDataProvider data(data_reads, arraysize(data_reads), | |
607 data_writes, arraysize(data_writes)); | |
608 mock_socket_factory.AddSocketDataProvider(&data); | |
609 | |
610 TestCompletionCallback test_callback; | |
611 scoped_ptr<SocketStreamEventRecorder> delegate( | |
612 new SocketStreamEventRecorder(test_callback.callback())); | |
613 delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose, | |
614 base::Unretained(delegate.get()))); | |
615 | |
616 TestURLRequestContextWithProxy context("myproxy:70"); | |
617 HttpAuthCache* auth_cache = | |
618 context.http_transaction_factory()->GetSession()->http_auth_cache(); | |
619 auth_cache->Add(GURL("http://myproxy:70"), | |
620 "MyRealm1", | |
621 HttpAuth::AUTH_SCHEME_BASIC, | |
622 "Basic realm=MyRealm1", | |
623 AuthCredentials(ASCIIToUTF16("foo"), | |
624 ASCIIToUTF16("bar")), | |
625 "/"); | |
626 | |
627 scoped_refptr<SocketStream> socket_stream( | |
628 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
629 &context, NULL)); | |
630 | |
631 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
632 | |
633 socket_stream->Connect(); | |
634 | |
635 test_callback.WaitForResult(); | |
636 | |
637 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
638 ASSERT_EQ(4U, events.size()); | |
639 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
640 events[0].event_type); | |
641 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
642 EXPECT_EQ(ERR_ABORTED, events[2].error_code); | |
643 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type); | |
644 } | |
645 | |
646 TEST_F(SocketStreamTest, WSSBasicAuthProxyWithAuthCache) { | |
647 MockClientSocketFactory mock_socket_factory; | |
648 MockWrite data_writes1[] = { | |
649 MockWrite("CONNECT example.com:443 HTTP/1.1\r\n" | |
650 "Host: example.com\r\n" | |
651 "Proxy-Connection: keep-alive\r\n" | |
652 "Proxy-Authorization: Basic Zm9vOmJhcg==\r\n\r\n"), | |
653 }; | |
654 MockRead data_reads1[] = { | |
655 MockRead("HTTP/1.1 200 Connection Established\r\n"), | |
656 MockRead("Proxy-agent: Apache/2.2.8\r\n"), | |
657 MockRead("\r\n"), | |
658 MockRead(ASYNC, ERR_IO_PENDING) | |
659 }; | |
660 StaticSocketDataProvider data1(data_reads1, arraysize(data_reads1), | |
661 data_writes1, arraysize(data_writes1)); | |
662 mock_socket_factory.AddSocketDataProvider(&data1); | |
663 | |
664 SSLSocketDataProvider data2(ASYNC, OK); | |
665 mock_socket_factory.AddSSLSocketDataProvider(&data2); | |
666 | |
667 TestCompletionCallback test_callback; | |
668 scoped_ptr<SocketStreamEventRecorder> delegate( | |
669 new SocketStreamEventRecorder(test_callback.callback())); | |
670 delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose, | |
671 base::Unretained(delegate.get()))); | |
672 | |
673 TestURLRequestContextWithProxy context("myproxy:70"); | |
674 HttpAuthCache* auth_cache = | |
675 context.http_transaction_factory()->GetSession()->http_auth_cache(); | |
676 auth_cache->Add(GURL("http://myproxy:70"), | |
677 "MyRealm1", | |
678 HttpAuth::AUTH_SCHEME_BASIC, | |
679 "Basic realm=MyRealm1", | |
680 AuthCredentials(ASCIIToUTF16("foo"), | |
681 ASCIIToUTF16("bar")), | |
682 "/"); | |
683 | |
684 scoped_refptr<SocketStream> socket_stream( | |
685 new SocketStream(GURL("wss://example.com/demo"), delegate.get(), | |
686 &context, NULL)); | |
687 | |
688 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
689 | |
690 socket_stream->Connect(); | |
691 | |
692 test_callback.WaitForResult(); | |
693 | |
694 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
695 ASSERT_EQ(4U, events.size()); | |
696 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
697 events[0].event_type); | |
698 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
699 EXPECT_EQ(ERR_ABORTED, events[2].error_code); | |
700 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type); | |
701 } | |
702 | |
703 TEST_F(SocketStreamTest, IOPending) { | |
704 TestCompletionCallback test_callback; | |
705 | |
706 scoped_ptr<SocketStreamEventRecorder> delegate( | |
707 new SocketStreamEventRecorder(test_callback.callback())); | |
708 delegate->SetOnStartOpenConnection(base::Bind( | |
709 &SocketStreamTest::DoIOPending, base::Unretained(this))); | |
710 delegate->SetOnConnected(base::Bind( | |
711 &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this))); | |
712 delegate->SetOnReceivedData(base::Bind( | |
713 &SocketStreamTest::DoCloseFlushPendingWriteTest, | |
714 base::Unretained(this))); | |
715 | |
716 TestURLRequestContext context; | |
717 | |
718 scoped_refptr<SocketStream> socket_stream( | |
719 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
720 &context, NULL)); | |
721 | |
722 MockWrite data_writes[] = { | |
723 MockWrite(SocketStreamTest::kWebSocketHandshakeRequest), | |
724 MockWrite(ASYNC, "\0message1\xff", 10), | |
725 MockWrite(ASYNC, "\0message2\xff", 10) | |
726 }; | |
727 MockRead data_reads[] = { | |
728 MockRead(SocketStreamTest::kWebSocketHandshakeResponse), | |
729 // Server doesn't close the connection after handshake. | |
730 MockRead(ASYNC, ERR_IO_PENDING) | |
731 }; | |
732 AddWebSocketMessage("message1"); | |
733 AddWebSocketMessage("message2"); | |
734 | |
735 DelayedSocketData data_provider( | |
736 1, data_reads, arraysize(data_reads), | |
737 data_writes, arraysize(data_writes)); | |
738 | |
739 MockClientSocketFactory* mock_socket_factory = | |
740 GetMockClientSocketFactory(); | |
741 mock_socket_factory->AddSocketDataProvider(&data_provider); | |
742 | |
743 socket_stream->SetClientSocketFactory(mock_socket_factory); | |
744 | |
745 socket_stream->Connect(); | |
746 io_test_callback_.WaitForResult(); | |
747 EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE, | |
748 socket_stream->next_state_); | |
749 delegate->CompleteConnection(OK); | |
750 | |
751 EXPECT_EQ(OK, test_callback.WaitForResult()); | |
752 | |
753 EXPECT_TRUE(data_provider.at_read_eof()); | |
754 EXPECT_TRUE(data_provider.at_write_eof()); | |
755 | |
756 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
757 ASSERT_EQ(7U, events.size()); | |
758 | |
759 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
760 events[0].event_type); | |
761 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
762 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type); | |
763 EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type); | |
764 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[4].event_type); | |
765 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[5].event_type); | |
766 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[6].event_type); | |
767 } | |
768 | |
769 TEST_F(SocketStreamTest, SwitchToSpdy) { | |
770 TestCompletionCallback test_callback; | |
771 | |
772 scoped_ptr<SocketStreamEventRecorder> delegate( | |
773 new SocketStreamEventRecorder(test_callback.callback())); | |
774 delegate->SetOnStartOpenConnection(base::Bind( | |
775 &SocketStreamTest::DoSwitchToSpdyTest, base::Unretained(this))); | |
776 | |
777 TestURLRequestContext context; | |
778 | |
779 scoped_refptr<SocketStream> socket_stream( | |
780 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
781 &context, NULL)); | |
782 | |
783 socket_stream->Connect(); | |
784 | |
785 EXPECT_EQ(ERR_PROTOCOL_SWITCHED, test_callback.WaitForResult()); | |
786 | |
787 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
788 ASSERT_EQ(2U, events.size()); | |
789 | |
790 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
791 events[0].event_type); | |
792 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type); | |
793 EXPECT_EQ(ERR_PROTOCOL_SWITCHED, events[1].error_code); | |
794 } | |
795 | |
796 TEST_F(SocketStreamTest, SwitchAfterPending) { | |
797 TestCompletionCallback test_callback; | |
798 | |
799 scoped_ptr<SocketStreamEventRecorder> delegate( | |
800 new SocketStreamEventRecorder(test_callback.callback())); | |
801 delegate->SetOnStartOpenConnection(base::Bind( | |
802 &SocketStreamTest::DoIOPending, base::Unretained(this))); | |
803 | |
804 TestURLRequestContext context; | |
805 | |
806 scoped_refptr<SocketStream> socket_stream( | |
807 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
808 &context, NULL)); | |
809 | |
810 socket_stream->Connect(); | |
811 io_test_callback_.WaitForResult(); | |
812 | |
813 EXPECT_EQ(SocketStream::STATE_RESOLVE_PROTOCOL_COMPLETE, | |
814 socket_stream->next_state_); | |
815 delegate->CompleteConnection(ERR_PROTOCOL_SWITCHED); | |
816 | |
817 EXPECT_EQ(ERR_PROTOCOL_SWITCHED, test_callback.WaitForResult()); | |
818 | |
819 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
820 ASSERT_EQ(2U, events.size()); | |
821 | |
822 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
823 events[0].event_type); | |
824 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type); | |
825 EXPECT_EQ(ERR_PROTOCOL_SWITCHED, events[1].error_code); | |
826 } | |
827 | |
828 // Test a connection though a secure proxy. | |
829 TEST_F(SocketStreamTest, SecureProxyConnectError) { | |
830 MockClientSocketFactory mock_socket_factory; | |
831 MockWrite data_writes[] = { | |
832 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" | |
833 "Host: example.com\r\n" | |
834 "Proxy-Connection: keep-alive\r\n\r\n") | |
835 }; | |
836 MockRead data_reads[] = { | |
837 MockRead("HTTP/1.1 200 Connection Established\r\n"), | |
838 MockRead("Proxy-agent: Apache/2.2.8\r\n"), | |
839 MockRead("\r\n"), | |
840 // SocketStream::DoClose is run asynchronously. Socket can be read after | |
841 // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate | |
842 // server doesn't close the connection. | |
843 MockRead(ASYNC, ERR_IO_PENDING) | |
844 }; | |
845 StaticSocketDataProvider data(data_reads, arraysize(data_reads), | |
846 data_writes, arraysize(data_writes)); | |
847 mock_socket_factory.AddSocketDataProvider(&data); | |
848 SSLSocketDataProvider ssl(SYNCHRONOUS, ERR_SSL_PROTOCOL_ERROR); | |
849 mock_socket_factory.AddSSLSocketDataProvider(&ssl); | |
850 | |
851 TestCompletionCallback test_callback; | |
852 TestURLRequestContextWithProxy context("https://myproxy:70"); | |
853 | |
854 scoped_ptr<SocketStreamEventRecorder> delegate( | |
855 new SocketStreamEventRecorder(test_callback.callback())); | |
856 delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose, | |
857 base::Unretained(delegate.get()))); | |
858 | |
859 scoped_refptr<SocketStream> socket_stream( | |
860 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
861 &context, NULL)); | |
862 | |
863 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
864 | |
865 socket_stream->Connect(); | |
866 | |
867 test_callback.WaitForResult(); | |
868 | |
869 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
870 ASSERT_EQ(3U, events.size()); | |
871 | |
872 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
873 events[0].event_type); | |
874 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[1].event_type); | |
875 EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, events[1].error_code); | |
876 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[2].event_type); | |
877 } | |
878 | |
879 // Test a connection though a secure proxy. | |
880 TEST_F(SocketStreamTest, SecureProxyConnect) { | |
881 MockClientSocketFactory mock_socket_factory; | |
882 MockWrite data_writes[] = { | |
883 MockWrite("CONNECT example.com:80 HTTP/1.1\r\n" | |
884 "Host: example.com\r\n" | |
885 "Proxy-Connection: keep-alive\r\n\r\n") | |
886 }; | |
887 MockRead data_reads[] = { | |
888 MockRead("HTTP/1.1 200 Connection Established\r\n"), | |
889 MockRead("Proxy-agent: Apache/2.2.8\r\n"), | |
890 MockRead("\r\n"), | |
891 // SocketStream::DoClose is run asynchronously. Socket can be read after | |
892 // "\r\n". We have to give ERR_IO_PENDING to SocketStream then to indicate | |
893 // server doesn't close the connection. | |
894 MockRead(ASYNC, ERR_IO_PENDING) | |
895 }; | |
896 StaticSocketDataProvider data(data_reads, arraysize(data_reads), | |
897 data_writes, arraysize(data_writes)); | |
898 mock_socket_factory.AddSocketDataProvider(&data); | |
899 SSLSocketDataProvider ssl(SYNCHRONOUS, OK); | |
900 mock_socket_factory.AddSSLSocketDataProvider(&ssl); | |
901 | |
902 TestCompletionCallback test_callback; | |
903 TestURLRequestContextWithProxy context("https://myproxy:70"); | |
904 | |
905 scoped_ptr<SocketStreamEventRecorder> delegate( | |
906 new SocketStreamEventRecorder(test_callback.callback())); | |
907 delegate->SetOnConnected(base::Bind(&SocketStreamEventRecorder::DoClose, | |
908 base::Unretained(delegate.get()))); | |
909 | |
910 scoped_refptr<SocketStream> socket_stream( | |
911 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
912 &context, NULL)); | |
913 | |
914 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
915 | |
916 socket_stream->Connect(); | |
917 | |
918 test_callback.WaitForResult(); | |
919 | |
920 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
921 ASSERT_EQ(4U, events.size()); | |
922 | |
923 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
924 events[0].event_type); | |
925 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
926 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[2].event_type); | |
927 EXPECT_EQ(ERR_ABORTED, events[2].error_code); | |
928 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[3].event_type); | |
929 } | |
930 | |
931 TEST_F(SocketStreamTest, BeforeConnectFailed) { | |
932 TestCompletionCallback test_callback; | |
933 | |
934 scoped_ptr<SocketStreamEventRecorder> delegate( | |
935 new SocketStreamEventRecorder(test_callback.callback())); | |
936 | |
937 TestURLRequestContext context; | |
938 TestSocketStreamNetworkDelegate network_delegate; | |
939 network_delegate.SetBeforeConnectResult(ERR_ACCESS_DENIED); | |
940 context.set_network_delegate(&network_delegate); | |
941 | |
942 scoped_refptr<SocketStream> socket_stream( | |
943 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
944 &context, NULL)); | |
945 | |
946 socket_stream->Connect(); | |
947 | |
948 test_callback.WaitForResult(); | |
949 | |
950 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
951 ASSERT_EQ(2U, events.size()); | |
952 | |
953 EXPECT_EQ(SocketStreamEvent::EVENT_ERROR, events[0].event_type); | |
954 EXPECT_EQ(ERR_ACCESS_DENIED, events[0].error_code); | |
955 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[1].event_type); | |
956 } | |
957 | |
958 // Check that a connect failure, followed by the delegate calling DetachDelegate | |
959 // and deleting itself in the OnError callback, is handled correctly. | |
960 TEST_F(SocketStreamTest, OnErrorDetachDelegate) { | |
961 MockClientSocketFactory mock_socket_factory; | |
962 TestCompletionCallback test_callback; | |
963 | |
964 // SelfDeletingDelegate is self-owning; we just need a pointer to it to | |
965 // connect it and the SocketStream. | |
966 SelfDeletingDelegate* delegate = | |
967 new SelfDeletingDelegate(test_callback.callback()); | |
968 MockConnect mock_connect(ASYNC, ERR_CONNECTION_REFUSED); | |
969 StaticSocketDataProvider data; | |
970 data.set_connect_data(mock_connect); | |
971 mock_socket_factory.AddSocketDataProvider(&data); | |
972 | |
973 TestURLRequestContext context; | |
974 scoped_refptr<SocketStream> socket_stream( | |
975 new SocketStream(GURL("ws://localhost:9998/echo"), delegate, | |
976 &context, NULL)); | |
977 socket_stream->SetClientSocketFactory(&mock_socket_factory); | |
978 delegate->set_socket_stream(socket_stream); | |
979 // The delegate pointer will become invalid during the test. Set it to NULL to | |
980 // avoid holding a dangling pointer. | |
981 delegate = NULL; | |
982 | |
983 socket_stream->Connect(); | |
984 | |
985 EXPECT_EQ(OK, test_callback.WaitForResult()); | |
986 } | |
987 | |
988 TEST_F(SocketStreamTest, NullContextSocketStreamShouldNotCrash) { | |
989 TestCompletionCallback test_callback; | |
990 | |
991 scoped_ptr<SocketStreamEventRecorder> delegate( | |
992 new SocketStreamEventRecorder(test_callback.callback())); | |
993 TestURLRequestContext context; | |
994 scoped_refptr<SocketStream> socket_stream( | |
995 new SocketStream(GURL("ws://example.com/demo"), delegate.get(), | |
996 &context, NULL)); | |
997 delegate->SetOnStartOpenConnection(base::Bind( | |
998 &SocketStreamTest::DoIOPending, base::Unretained(this))); | |
999 delegate->SetOnConnected(base::Bind( | |
1000 &SocketStreamTest::DoSendWebSocketHandshake, base::Unretained(this))); | |
1001 delegate->SetOnReceivedData(base::Bind( | |
1002 &SocketStreamTest::DoCloseFlushPendingWriteTestWithSetContextNull, | |
1003 base::Unretained(this))); | |
1004 | |
1005 MockWrite data_writes[] = { | |
1006 MockWrite(SocketStreamTest::kWebSocketHandshakeRequest), | |
1007 }; | |
1008 MockRead data_reads[] = { | |
1009 MockRead(SocketStreamTest::kWebSocketHandshakeResponse), | |
1010 }; | |
1011 AddWebSocketMessage("message1"); | |
1012 AddWebSocketMessage("message2"); | |
1013 | |
1014 DelayedSocketData data_provider( | |
1015 1, data_reads, arraysize(data_reads), | |
1016 data_writes, arraysize(data_writes)); | |
1017 | |
1018 MockClientSocketFactory* mock_socket_factory = GetMockClientSocketFactory(); | |
1019 mock_socket_factory->AddSocketDataProvider(&data_provider); | |
1020 socket_stream->SetClientSocketFactory(mock_socket_factory); | |
1021 | |
1022 socket_stream->Connect(); | |
1023 io_test_callback_.WaitForResult(); | |
1024 delegate->CompleteConnection(OK); | |
1025 EXPECT_EQ(OK, test_callback.WaitForResult()); | |
1026 | |
1027 EXPECT_TRUE(data_provider.at_read_eof()); | |
1028 EXPECT_TRUE(data_provider.at_write_eof()); | |
1029 | |
1030 const std::vector<SocketStreamEvent>& events = delegate->GetSeenEvents(); | |
1031 ASSERT_EQ(5U, events.size()); | |
1032 | |
1033 EXPECT_EQ(SocketStreamEvent::EVENT_START_OPEN_CONNECTION, | |
1034 events[0].event_type); | |
1035 EXPECT_EQ(SocketStreamEvent::EVENT_CONNECTED, events[1].event_type); | |
1036 EXPECT_EQ(SocketStreamEvent::EVENT_SENT_DATA, events[2].event_type); | |
1037 EXPECT_EQ(SocketStreamEvent::EVENT_RECEIVED_DATA, events[3].event_type); | |
1038 EXPECT_EQ(SocketStreamEvent::EVENT_CLOSE, events[4].event_type); | |
1039 } | |
1040 | |
1041 } // namespace net | |
OLD | NEW |