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

Side by Side Diff: net/websockets/websocket_basic_stream_test.cc

Issue 18792002: WebSocketBasicStream framing logic (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Remove "We" from comment. Created 7 years, 3 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 | « net/websockets/websocket_basic_stream.cc ('k') | no next file » | 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 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
339 // ERR_CONNECTION_CLOSED. This is not expected to happen on an established
340 // connection; a Read of size 0 is the expected behaviour. The key point of this
341 // test is to confirm that ReadFrames() behaviour is identical in both cases.
342 TEST_F(WebSocketBasicStreamSocketTest, SyncCloseWithErr) {
343 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
344 CreateReadOnly(reads);
345
346 EXPECT_EQ(ERR_CONNECTION_CLOSED,
347 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
348 }
349
350 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseWithErr) {
351 MockRead reads[] = {MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
352 CreateReadOnly(reads);
353
354 ASSERT_EQ(ERR_IO_PENDING,
355 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
356 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
357 }
358
359 TEST_F(WebSocketBasicStreamSocketTest, SyncErrorsPassedThrough) {
360 // ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that
361 // WebSocketBasicStream gives no special handling to.
362 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES)};
363 CreateReadOnly(reads);
364
365 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES,
366 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
367 }
368
369 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrorsPassedThrough) {
370 MockRead reads[] = {MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES)};
371 CreateReadOnly(reads);
372
373 ASSERT_EQ(ERR_IO_PENDING,
374 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
375 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, cb_.WaitForResult());
376 }
377
378 // If we get a frame followed by a close, we should receive them separately.
379 TEST_F(WebSocketBasicStreamSocketTest, CloseAfterFrame) {
380 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize),
381 MockRead(SYNCHRONOUS, "", 0)};
382 CreateReadOnly(reads);
383
384 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
385 EXPECT_EQ(1U, frame_chunks_.size());
386 frame_chunks_.clear();
387 EXPECT_EQ(ERR_CONNECTION_CLOSED,
388 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
389 }
390
391 // Synchronous close after an async frame header is handled by a different code
392 // path.
393 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) {
394 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
395 MockRead(SYNCHRONOUS, "", 0)};
396 CreateReadOnly(reads);
397
398 ASSERT_EQ(ERR_IO_PENDING,
399 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
400 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
401 }
402
403 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a
404 // slightly different code path.
405 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) {
406 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
407 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
408 CreateReadOnly(reads);
409
410 ASSERT_EQ(ERR_IO_PENDING,
411 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
412 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
413 }
414
415 // If there was a frame read at the same time as the response headers (and the
416 // handshake succeeded), then we should parse it.
417 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) {
418 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize);
419 CreateNullStream();
420
421 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
422 ASSERT_EQ(1U, frame_chunks_.size());
423 ASSERT_TRUE(frame_chunks_[0]->data);
424 EXPECT_EQ(6, frame_chunks_[0]->data->size());
425 }
426
427 // Check that a frame whose header partially arrived at the end of the response
428 // headers works correctly.
429 TEST_F(WebSocketBasicStreamSocketTest, PartialFrameHeaderInHttpResponse) {
430 SetHttpReadBuffer(kSampleFrame, 1);
431 MockRead reads[] = {MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
432 CreateReadOnly(reads);
433
434 ASSERT_EQ(ERR_IO_PENDING,
435 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
436 EXPECT_EQ(OK, cb_.WaitForResult());
437 ASSERT_EQ(1U, frame_chunks_.size());
438 ASSERT_TRUE(frame_chunks_[0]->data);
439 EXPECT_EQ(6, frame_chunks_[0]->data->size());
440 ASSERT_TRUE(frame_chunks_[0]->header);
441 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText,
442 frame_chunks_[0]->header->opcode);
443 }
444
445 // Check that an invalid frame results in an error.
446 TEST_F(WebSocketBasicStreamSocketTest, SyncInvalidFrame) {
447 MockRead reads[] = {MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize)};
448 CreateReadOnly(reads);
449
450 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
451 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
452 }
453
454 TEST_F(WebSocketBasicStreamSocketTest, AsyncInvalidFrame) {
455 MockRead reads[] = {MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize)};
456 CreateReadOnly(reads);
457
458 ASSERT_EQ(ERR_IO_PENDING,
459 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
460 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
461 }
462
463 // Check that writing a frame all at once works.
464 TEST_F(WebSocketBasicStreamSocketTest, WriteAtOnce) {
465 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
466 CreateWriteOnly(writes);
467 frame_chunks_ = GenerateWriteFrame();
468
469 EXPECT_EQ(OK, stream_->WriteFrames(&frame_chunks_, cb_.callback()));
470 }
471
472 // Check that completely async writing works.
473 TEST_F(WebSocketBasicStreamSocketTest, AsyncWriteAtOnce) {
474 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
475 CreateWriteOnly(writes);
476 frame_chunks_ = GenerateWriteFrame();
477
478 ASSERT_EQ(ERR_IO_PENDING,
479 stream_->WriteFrames(&frame_chunks_, cb_.callback()));
480 EXPECT_EQ(OK, cb_.WaitForResult());
481 }
482
483 // Check that writing a frame to an extremely full kernel buffer (so that it
484 // ends up being sent in bits) works. The WriteFrames() callback should not be
485 // called until all parts have been written.
486 TEST_F(WebSocketBasicStreamSocketTest, WriteInBits) {
487 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
488 MockWrite(ASYNC, kWriteFrame + 4, 4),
489 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
490 CreateWriteOnly(writes);
491 frame_chunks_ = GenerateWriteFrame();
492
493 ASSERT_EQ(ERR_IO_PENDING,
494 stream_->WriteFrames(&frame_chunks_, cb_.callback()));
495 EXPECT_EQ(OK, cb_.WaitForResult());
496 }
497
498 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
499 extensions_ = "inflate-uuencode";
500 CreateNullStream();
501
502 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
503 }
504
505 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
506 sub_protocol_ = "cyberchat";
507 CreateNullStream();
508
509 EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
510 }
511
512 } // namespace
513 } // namespace net
OLDNEW
« no previous file with comments | « net/websockets/websocket_basic_stream.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698