OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2013 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 // Tests for WebSocketBasicStream. Note that we do not attempt to verify that | |
6 // frame parsing itself functions correctly, as that is covered by the | |
7 // WebSocketFrameParser tests. | |
8 | |
9 #include "net/websockets/websocket_basic_stream.h" | |
10 | |
11 #include "base/basictypes.h" | |
tyoshino (SeeGerritForStatus)
2013/08/22 21:08:43
add
base/port.h
Adam Rice
2013/08/23 06:05:18
Done.
| |
12 #include "net/base/capturing_net_log.h" | |
13 #include "net/base/test_completion_callback.h" | |
14 #include "net/socket/socket_test_util.h" | |
15 #include "testing/gtest/include/gtest/gtest.h" | |
16 | |
17 namespace net { | |
18 namespace { | |
19 | |
tyoshino (SeeGerritForStatus)
2013/08/22 21:08:43
please add
- tests for empty frame cases
- frame w
Adam Rice
2013/08/23 06:05:18
Done.
| |
20 const char kSampleFrame[] = "\x81\x06Sample"; | |
21 const size_t kSampleFrameSize = arraysize(kSampleFrame) - 1; | |
22 const char kPartialLargeFrame[] = | |
23 "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF" | |
24 "chromiunum ad pasco per loca insanis pullum manducat frumenti"; | |
25 const size_t kPartialLargeFrameSize = arraysize(kPartialLargeFrame) - 1; | |
26 const size_t kLargeFrameHeaderSize = 10; | |
27 const size_t kLargeFrameDeclaredPayloadSize = 0x7FFFFFFF; | |
28 const char kMultipleFrames[] = "\x81\x01X\x81\x01Y\x81\x01Z"; | |
29 const size_t kMultipleFramesSize = arraysize(kMultipleFrames) - 1; | |
30 // This frame encodes a payload length of 7 in two bytes, which is always | |
31 // invalid. | |
32 const char kInvalidFrame[] = "\x81\x7E\x00\x07Invalid"; | |
33 const size_t kInvalidFrameSize = arraysize(kInvalidFrame) - 1; | |
34 const char kWriteFrame[] = "\x81\x85\x00\x00\x00\x00Write"; | |
35 const size_t kWriteFrameSize = arraysize(kWriteFrame) - 1; | |
36 const WebSocketMaskingKey kNulMaskingKey = {{'\0', '\0', '\0', '\0'}}; | |
37 | |
38 // Generates a ScopedVector<WebSocketFrameChunk> which will have a wire format | |
39 // matching kWriteFrame. | |
40 ScopedVector<WebSocketFrameChunk> GenerateWriteFrame() { | |
41 scoped_ptr<WebSocketFrameChunk> chunk(new WebSocketFrameChunk); | |
42 const size_t payload_size = | |
43 kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize + | |
44 WebSocketFrameHeader::kMaskingKeyLength); | |
45 chunk->data = new IOBufferWithSize(payload_size); | |
46 memcpy(chunk->data->data(), | |
47 kWriteFrame + kWriteFrameSize - payload_size, | |
48 payload_size); | |
49 chunk->final_chunk = true; | |
50 scoped_ptr<WebSocketFrameHeader> header( | |
51 new WebSocketFrameHeader(WebSocketFrameHeader::kOpCodeText)); | |
52 header->final = true; | |
53 header->masked = true; | |
54 header->payload_length = payload_size; | |
55 chunk->header = header.Pass(); | |
56 ScopedVector<WebSocketFrameChunk> chunks; | |
57 chunks.push_back(chunk.release()); | |
58 return chunks.Pass(); | |
59 } | |
60 | |
61 // A masking key generator function which generates the identity mask, | |
62 // ie. "\0\0\0\0". | |
63 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; } | |
64 | |
65 // Base class for WebSocketBasicStream test fixtures. | |
66 class WebSocketBasicStreamTest : public ::testing::Test { | |
67 protected: | |
68 scoped_ptr<WebSocketBasicStream> stream_; | |
69 CapturingNetLog net_log_; | |
70 }; | |
71 | |
72 // A fixture for tests which only perform normal socket operations. | |
73 class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest { | |
74 protected: | |
75 virtual ~WebSocketBasicStreamSocketTest() { | |
76 // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so | |
77 // should be destroyed first. | |
78 stream_.reset(); | |
79 } | |
80 | |
81 scoped_ptr<StreamSocket> MakeMockTCPClientSocket(MockRead reads[], | |
82 size_t reads_count, | |
83 MockWrite writes[], | |
84 size_t writes_count) { | |
85 // Nothing in WebSocketBasicStream should be caring about what the address | |
86 // is. Set it to 8.8.8.8:80. | |
87 AddressList address_list(IPEndPoint(IPAddressNumber(4, 8), 80)); | |
88 socket_data_.reset( | |
89 new StaticSocketDataProvider(reads, reads_count, writes, writes_count)); | |
90 socket_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK)); | |
91 scoped_ptr<MockTCPClientSocket> socket( | |
92 new MockTCPClientSocket(address_list, &net_log_, socket_data_.get())); | |
93 CHECK_EQ(OK, socket->Connect(cb_.callback())); | |
94 return socket.PassAs<StreamSocket>(); | |
95 } | |
96 | |
97 scoped_ptr<ClientSocketHandle> MakeTransportSocket( | |
98 scoped_ptr<StreamSocket> socket) { | |
99 scoped_ptr<ClientSocketHandle> transport_socket(new ClientSocketHandle); | |
100 transport_socket->SetSocket(socket.Pass()); | |
101 return transport_socket.Pass(); | |
102 } | |
103 | |
104 void SetHttpReadBuffer(const char* data, size_t size) { | |
105 http_read_buffer_ = new GrowableIOBuffer; | |
106 http_read_buffer_->SetCapacity(size); | |
107 memcpy(http_read_buffer_->data(), data, size); | |
108 http_read_buffer_->set_offset(size); | |
109 } | |
110 | |
111 void CreateStream(MockRead reads[], | |
112 size_t reads_count, | |
113 MockWrite writes[], | |
114 size_t writes_count) { | |
115 stream_ = WebSocketBasicStream::CreateWebSocketBasicStreamForTesting( | |
116 MakeTransportSocket( | |
117 MakeMockTCPClientSocket(reads, reads_count, writes, writes_count)), | |
118 http_read_buffer_, | |
119 sub_protocol_, | |
120 extensions_, | |
121 &GenerateNulMaskingKey); | |
122 } | |
123 | |
124 template <size_t N> | |
125 void CreateReadOnly(MockRead (&reads)[N]) { | |
126 CreateStream(reads, N, NULL, 0); | |
127 } | |
128 | |
129 template <size_t N> | |
130 void CreateWriteOnly(MockWrite (&writes)[N]) { | |
131 CreateStream(NULL, 0, writes, N); | |
132 } | |
133 | |
134 void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); } | |
135 | |
136 scoped_ptr<SocketDataProvider> socket_data_; | |
137 ScopedVector<WebSocketFrameChunk> frame_chunks_; | |
138 TestCompletionCallback cb_; | |
139 scoped_refptr<GrowableIOBuffer> http_read_buffer_; | |
140 std::string sub_protocol_; | |
141 std::string extensions_; | |
142 }; | |
143 | |
144 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) { | |
145 CreateNullStream(); | |
146 } | |
147 | |
148 TEST_F(WebSocketBasicStreamSocketTest, SyncReadWorks) { | |
149 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize)}; | |
150 CreateReadOnly(reads); | |
151 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback()); | |
152 EXPECT_EQ(OK, result); | |
153 ASSERT_EQ(1U, frame_chunks_.size()); | |
154 ASSERT_TRUE(frame_chunks_[0]->header); | |
155 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length); | |
156 EXPECT_TRUE(frame_chunks_[0]->header->final); | |
157 EXPECT_TRUE(frame_chunks_[0]->final_chunk); | |
158 } | |
159 | |
160 TEST_F(WebSocketBasicStreamSocketTest, AsyncReadWorks) { | |
161 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kSampleFrameSize)}; | |
162 CreateReadOnly(reads); | |
163 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback()); | |
164 ASSERT_EQ(ERR_IO_PENDING, result); | |
165 EXPECT_EQ(OK, cb_.WaitForResult()); | |
166 ASSERT_EQ(1U, frame_chunks_.size()); | |
167 ASSERT_TRUE(frame_chunks_[0]->header); | |
168 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length); | |
169 // Don't repeat all the tests from SyncReadWorks; just enough to be sure the | |
170 // frame was really read. | |
171 } | |
172 | |
173 // ReadFrames will not return a frame whose header has not been wholly received. | |
174 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSync) { | |
175 MockRead reads[] = { | |
176 MockRead(SYNCHRONOUS, kSampleFrame, 1), | |
177 MockRead(SYNCHRONOUS, kSampleFrame + 1, kSampleFrameSize - 1)}; | |
178 CreateReadOnly(reads); | |
179 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback()); | |
180 ASSERT_EQ(OK, result); | |
181 ASSERT_EQ(1U, frame_chunks_.size()); | |
182 ASSERT_TRUE(frame_chunks_[0]->header); | |
183 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length); | |
184 } | |
185 | |
186 // The same behaviour applies to asynchronous reads. | |
187 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedAsync) { | |
188 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1), | |
189 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)}; | |
190 CreateReadOnly(reads); | |
191 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback()); | |
192 ASSERT_EQ(ERR_IO_PENDING, result); | |
193 EXPECT_EQ(OK, cb_.WaitForResult()); | |
194 ASSERT_EQ(1U, frame_chunks_.size()); | |
195 ASSERT_TRUE(frame_chunks_[0]->header); | |
196 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length); | |
197 } | |
198 | |
199 // If it receives an incomplete header in a synchronous call, then has to wait | |
200 // for the rest of the frame, ReadFrames will return ERR_IO_PENDING. | |
201 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) { | |
202 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1), | |
203 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)}; | |
204 CreateReadOnly(reads); | |
205 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback()); | |
206 ASSERT_EQ(ERR_IO_PENDING, result); | |
207 EXPECT_EQ(OK, cb_.WaitForResult()); | |
208 ASSERT_EQ(1U, frame_chunks_.size()); | |
209 ASSERT_TRUE(frame_chunks_[0]->header); | |
210 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length); | |
211 } | |
212 | |
213 // An extended header should also return ERR_IO_PENDING if it is not completely | |
214 // received. | |
215 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) { | |
216 MockRead reads[] = { | |
217 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1), | |
218 MockRead(SYNCHRONOUS, ERR_IO_PENDING)}; | |
219 CreateReadOnly(reads); | |
220 EXPECT_EQ(ERR_IO_PENDING, | |
221 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
222 } | |
223 | |
224 // A frame that does not arrive in a single read should arrive in chunks. | |
225 TEST_F(WebSocketBasicStreamSocketTest, LargeFrameFirstChunk) { | |
226 MockRead reads[] = { | |
227 MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize)}; | |
228 CreateReadOnly(reads); | |
229 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
230 ASSERT_EQ(1U, frame_chunks_.size()); | |
231 ASSERT_TRUE(frame_chunks_[0]->header); | |
232 EXPECT_EQ(kLargeFrameDeclaredPayloadSize, | |
233 frame_chunks_[0]->header->payload_length); | |
234 EXPECT_TRUE(frame_chunks_[0]->header->final); | |
235 EXPECT_FALSE(frame_chunks_[0]->final_chunk); | |
236 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize, | |
237 static_cast<size_t>(frame_chunks_[0]->data->size())); | |
238 } | |
239 | |
240 // If only the header arrives, we should get a zero-byte chunk. | |
241 TEST_F(WebSocketBasicStreamSocketTest, HeaderOnlyChunk) { | |
242 MockRead reads[] = { | |
243 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize)}; | |
244 CreateReadOnly(reads); | |
245 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
246 ASSERT_EQ(1U, frame_chunks_.size()); | |
247 EXPECT_FALSE(frame_chunks_[0]->final_chunk); | |
248 EXPECT_TRUE(frame_chunks_[0]->data.get() == NULL); | |
249 } | |
250 | |
251 // The second and subsequent chunks of a frame have no header. | |
252 TEST_F(WebSocketBasicStreamSocketTest, LargeFrameTwoChunks) { | |
253 static const size_t kChunkSize = 16; | |
254 MockRead reads[] = { | |
255 MockRead(ASYNC, kPartialLargeFrame, kChunkSize), | |
256 MockRead(ASYNC, kPartialLargeFrame + kChunkSize, kChunkSize)}; | |
257 CreateReadOnly(reads); | |
258 TestCompletionCallback cb[2]; | |
259 | |
260 ASSERT_EQ(ERR_IO_PENDING, | |
261 stream_->ReadFrames(&frame_chunks_, cb[0].callback())); | |
262 EXPECT_EQ(OK, cb[0].WaitForResult()); | |
263 ASSERT_EQ(1U, frame_chunks_.size()); | |
264 ASSERT_TRUE(frame_chunks_[0]->header); | |
265 | |
266 frame_chunks_.clear(); | |
267 ASSERT_EQ(ERR_IO_PENDING, | |
268 stream_->ReadFrames(&frame_chunks_, cb[1].callback())); | |
269 EXPECT_EQ(OK, cb[1].WaitForResult()); | |
270 ASSERT_EQ(1U, frame_chunks_.size()); | |
271 ASSERT_FALSE(frame_chunks_[0]->header); | |
272 } | |
273 | |
274 // Only the final chunk of a frame has final_chunk set. | |
275 TEST_F(WebSocketBasicStreamSocketTest, OnlyFinalChunkIsFinal) { | |
276 static const size_t kFirstChunkSize = 4; | |
277 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kFirstChunkSize), | |
278 MockRead(ASYNC, | |
279 kSampleFrame + kFirstChunkSize, | |
280 kSampleFrameSize - kFirstChunkSize)}; | |
281 CreateReadOnly(reads); | |
282 TestCompletionCallback cb[2]; | |
283 | |
284 ASSERT_EQ(ERR_IO_PENDING, | |
285 stream_->ReadFrames(&frame_chunks_, cb[0].callback())); | |
286 EXPECT_EQ(OK, cb[0].WaitForResult()); | |
287 ASSERT_EQ(1U, frame_chunks_.size()); | |
288 ASSERT_FALSE(frame_chunks_[0]->final_chunk); | |
289 | |
290 frame_chunks_.clear(); | |
291 ASSERT_EQ(ERR_IO_PENDING, | |
292 stream_->ReadFrames(&frame_chunks_, cb[1].callback())); | |
293 EXPECT_EQ(OK, cb[1].WaitForResult()); | |
294 ASSERT_EQ(1U, frame_chunks_.size()); | |
295 ASSERT_TRUE(frame_chunks_[0]->final_chunk); | |
296 } | |
297 | |
298 // Multiple frames that arrive together should be parsed correctly. | |
299 TEST_F(WebSocketBasicStreamSocketTest, ThreeFramesTogether) { | |
300 MockRead reads[] = { | |
301 MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize)}; | |
302 CreateReadOnly(reads); | |
303 | |
304 ASSERT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
305 ASSERT_EQ(3U, frame_chunks_.size()); | |
306 EXPECT_TRUE(frame_chunks_[0]->final_chunk); | |
307 EXPECT_TRUE(frame_chunks_[1]->final_chunk); | |
308 EXPECT_TRUE(frame_chunks_[2]->final_chunk); | |
309 } | |
310 | |
311 // ERR_CONNECTION_CLOSED must be returned on close. | |
312 TEST_F(WebSocketBasicStreamSocketTest, SyncClose) { | |
313 MockRead reads[] = {MockRead(SYNCHRONOUS, "", 0)}; | |
314 CreateReadOnly(reads); | |
315 | |
316 EXPECT_EQ(ERR_CONNECTION_CLOSED, | |
317 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
318 } | |
319 | |
320 TEST_F(WebSocketBasicStreamSocketTest, AsyncClose) { | |
321 MockRead reads[] = {MockRead(ASYNC, "", 0)}; | |
322 CreateReadOnly(reads); | |
323 | |
324 ASSERT_EQ(ERR_IO_PENDING, | |
325 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
326 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); | |
327 } | |
328 | |
329 // The result should be the same if the socket returns ERR_CONNECTION_CLOSED | |
330 TEST_F(WebSocketBasicStreamSocketTest, SyncCloseWithErr) { | |
331 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)}; | |
332 CreateReadOnly(reads); | |
333 | |
334 EXPECT_EQ(ERR_CONNECTION_CLOSED, | |
335 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
336 } | |
337 | |
338 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseWithErr) { | |
339 MockRead reads[] = {MockRead(ASYNC, ERR_CONNECTION_CLOSED)}; | |
340 CreateReadOnly(reads); | |
341 | |
342 ASSERT_EQ(ERR_IO_PENDING, | |
343 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
344 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); | |
345 } | |
346 | |
347 // If we get a frame followed by a close, we should receive them separately. | |
348 TEST_F(WebSocketBasicStreamSocketTest, CloseAfterFrame) { | |
349 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize), | |
350 MockRead(SYNCHRONOUS, "", 0)}; | |
351 CreateReadOnly(reads); | |
352 | |
353 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
354 EXPECT_EQ(1U, frame_chunks_.size()); | |
355 frame_chunks_.clear(); | |
356 EXPECT_EQ(ERR_CONNECTION_CLOSED, | |
357 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
358 } | |
359 | |
360 // Synchronous close after an async frame header is handled by a different code | |
361 // path. | |
362 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) { | |
363 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U), | |
364 MockRead(SYNCHRONOUS, "", 0)}; | |
365 CreateReadOnly(reads); | |
366 | |
367 ASSERT_EQ(ERR_IO_PENDING, | |
368 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
369 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); | |
370 } | |
371 | |
372 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a | |
373 // slightly different code path. | |
374 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) { | |
375 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U), | |
376 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)}; | |
377 CreateReadOnly(reads); | |
378 | |
379 ASSERT_EQ(ERR_IO_PENDING, | |
380 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
381 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); | |
382 } | |
383 | |
384 // If there was a frame read at the same time as the response headers (and the | |
385 // handshake succeeded), then we should parse it. | |
386 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) { | |
387 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize); | |
388 CreateNullStream(); | |
389 | |
390 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
391 ASSERT_EQ(1U, frame_chunks_.size()); | |
392 ASSERT_TRUE(frame_chunks_[0]->data); | |
393 EXPECT_EQ(6, frame_chunks_[0]->data->size()); | |
394 } | |
395 | |
396 // Check that a frame whose header partially arrived at the end of the response | |
397 // headers works correctly. | |
398 TEST_F(WebSocketBasicStreamSocketTest, PartialFrameHeaderInHttpResponse) { | |
399 SetHttpReadBuffer(kSampleFrame, 1); | |
400 MockRead reads[] = {MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)}; | |
401 CreateReadOnly(reads); | |
402 | |
403 ASSERT_EQ(ERR_IO_PENDING, | |
404 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
405 EXPECT_EQ(OK, cb_.WaitForResult()); | |
406 ASSERT_EQ(1U, frame_chunks_.size()); | |
407 ASSERT_TRUE(frame_chunks_[0]->data); | |
408 EXPECT_EQ(6, frame_chunks_[0]->data->size()); | |
409 ASSERT_TRUE(frame_chunks_[0]->header); | |
410 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, | |
411 frame_chunks_[0]->header->opcode); | |
412 } | |
413 | |
414 // Check that an invalid frame results in an error. | |
415 TEST_F(WebSocketBasicStreamSocketTest, SyncInvalidFrame) { | |
416 MockRead reads[] = {MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize)}; | |
417 CreateReadOnly(reads); | |
418 | |
419 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, | |
420 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
421 } | |
422 | |
423 TEST_F(WebSocketBasicStreamSocketTest, AsyncInvalidFrame) { | |
424 MockRead reads[] = {MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize)}; | |
425 CreateReadOnly(reads); | |
426 | |
427 ASSERT_EQ(ERR_IO_PENDING, | |
428 stream_->ReadFrames(&frame_chunks_, cb_.callback())); | |
429 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult()); | |
430 } | |
431 | |
432 // Check that writing a frame all at once works. | |
433 TEST_F(WebSocketBasicStreamSocketTest, WriteAtOnce) { | |
434 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)}; | |
435 CreateWriteOnly(writes); | |
436 frame_chunks_ = GenerateWriteFrame(); | |
437 | |
438 EXPECT_EQ(OK, stream_->WriteFrames(&frame_chunks_, cb_.callback())); | |
439 } | |
440 | |
441 // Check that completely async writing works. | |
442 TEST_F(WebSocketBasicStreamSocketTest, AsyncWriteAtOnce) { | |
443 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)}; | |
444 CreateWriteOnly(writes); | |
445 frame_chunks_ = GenerateWriteFrame(); | |
446 | |
447 ASSERT_EQ(ERR_IO_PENDING, | |
448 stream_->WriteFrames(&frame_chunks_, cb_.callback())); | |
449 EXPECT_EQ(OK, cb_.WaitForResult()); | |
450 } | |
451 | |
452 // Check that writing a frame to an extremely full kernel buffer (so that it | |
453 // ends up being sent in bits) works. The WriteFrames() callback should not be | |
454 // called until all parts have been written. | |
455 TEST_F(WebSocketBasicStreamSocketTest, WriteInBits) { | |
456 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4), | |
457 MockWrite(ASYNC, kWriteFrame + 4, 4), | |
458 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)}; | |
459 CreateWriteOnly(writes); | |
460 frame_chunks_ = GenerateWriteFrame(); | |
461 | |
462 ASSERT_EQ(ERR_IO_PENDING, | |
463 stream_->WriteFrames(&frame_chunks_, cb_.callback())); | |
464 EXPECT_EQ(OK, cb_.WaitForResult()); | |
465 } | |
466 | |
467 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) { | |
468 extensions_ = "inflate-uuencode"; | |
469 CreateNullStream(); | |
470 | |
471 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions()); | |
472 } | |
473 | |
474 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) { | |
475 sub_protocol_ = "cyberchat"; | |
476 CreateNullStream(); | |
477 | |
478 EXPECT_EQ("cyberchat", stream_->GetSubProtocol()); | |
479 } | |
480 | |
481 } // namespace | |
482 } // namespace net | |
OLD | NEW |