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