Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / net / websockets / websocket_basic_stream_test.cc
blob9426f59cb7ea6a97dc1afa22330e6d893af18f75
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.
9 #include "net/websockets/websocket_basic_stream.h"
11 #include <stdint.h>
12 #include <string.h> // for memcpy() and memset().
14 #include <string>
16 #include "base/basictypes.h"
17 #include "base/big_endian.h"
18 #include "net/base/test_completion_callback.h"
19 #include "net/log/test_net_log.h"
20 #include "net/socket/socket_test_util.h"
21 #include "testing/gtest/include/gtest/gtest.h"
23 namespace net {
24 namespace {
26 #define WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(name, value) \
27 const char k##name[] = value; \
28 const size_t k##name##Size = arraysize(k##name) - 1;
30 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(SampleFrame, "\x81\x06Sample");
31 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(
32 PartialLargeFrame,
33 "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF"
34 "chromiunum ad pasco per loca insanis pullum manducat frumenti");
35 const size_t kLargeFrameHeaderSize = 10;
36 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(MultipleFrames,
37 "\x81\x01X\x81\x01Y\x81\x01Z");
38 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFirstFrame, "\x01\x00");
39 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyMiddleFrame, "\x00\x00");
40 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFinalTextFrame, "\x81\x00");
41 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(EmptyFinalContinuationFrame,
42 "\x80\x00");
43 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(ValidPong, "\x8A\x00");
44 // This frame encodes a payload length of 7 in two bytes, which is always
45 // invalid.
46 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(InvalidFrame,
47 "\x81\x7E\x00\x07Invalid");
48 // Control frames must have the FIN bit set. This one does not.
49 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(PingFrameWithoutFin, "\x09\x00");
50 // Control frames must have a payload of 125 bytes or less. This one has
51 // a payload of 126 bytes.
52 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(
53 126BytePong,
54 "\x8a\x7e\x00\x7eZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
55 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ");
56 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(CloseFrame,
57 "\x88\x09\x03\xe8occludo");
58 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(WriteFrame,
59 "\x81\x85\x00\x00\x00\x00Write");
60 WEBSOCKET_BASIC_STREAM_TEST_DEFINE_CONSTANT(MaskedEmptyPong,
61 "\x8A\x80\x00\x00\x00\x00");
62 const WebSocketMaskingKey kNulMaskingKey = {{'\0', '\0', '\0', '\0'}};
63 const WebSocketMaskingKey kNonNulMaskingKey = {
64 {'\x0d', '\x1b', '\x06', '\x17'}};
66 // A masking key generator function which generates the identity mask,
67 // ie. "\0\0\0\0".
68 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; }
70 // A masking key generation function which generates a fixed masking key with no
71 // nul characters.
72 WebSocketMaskingKey GenerateNonNulMaskingKey() { return kNonNulMaskingKey; }
74 // Base class for WebSocketBasicStream test fixtures.
75 class WebSocketBasicStreamTest : public ::testing::Test {
76 protected:
77 scoped_ptr<WebSocketBasicStream> stream_;
78 TestNetLog net_log_;
81 // A subclass of StaticSocketDataProvider modified to require that all data
82 // expected to be read or written actually is.
83 class StrictStaticSocketDataProvider : public StaticSocketDataProvider {
84 public:
85 StrictStaticSocketDataProvider(MockRead* reads,
86 size_t reads_count,
87 MockWrite* writes,
88 size_t writes_count,
89 bool strict_mode)
90 : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
91 strict_mode_(strict_mode) {}
93 ~StrictStaticSocketDataProvider() override {
94 if (strict_mode_) {
95 EXPECT_EQ(read_count(), read_index());
96 EXPECT_EQ(write_count(), write_index());
100 private:
101 const bool strict_mode_;
104 // A fixture for tests which only perform normal socket operations.
105 class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest {
106 protected:
107 WebSocketBasicStreamSocketTest()
108 : pool_(1, 1, &factory_),
109 generator_(&GenerateNulMaskingKey),
110 expect_all_io_to_complete_(true) {}
112 ~WebSocketBasicStreamSocketTest() override {
113 // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so
114 // should be destroyed first.
115 stream_.reset();
118 scoped_ptr<ClientSocketHandle> MakeTransportSocket(MockRead reads[],
119 size_t reads_count,
120 MockWrite writes[],
121 size_t writes_count) {
122 socket_data_.reset(new StrictStaticSocketDataProvider(
123 reads, reads_count, writes, writes_count, expect_all_io_to_complete_));
124 socket_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
125 factory_.AddSocketDataProvider(socket_data_.get());
127 scoped_ptr<ClientSocketHandle> transport_socket(new ClientSocketHandle);
128 scoped_refptr<MockTransportSocketParams> params;
129 transport_socket->Init("a",
130 params,
131 MEDIUM,
132 CompletionCallback(),
133 &pool_,
134 bound_net_log_.bound());
135 return transport_socket.Pass();
138 void SetHttpReadBuffer(const char* data, size_t size) {
139 http_read_buffer_ = new GrowableIOBuffer;
140 http_read_buffer_->SetCapacity(size);
141 memcpy(http_read_buffer_->data(), data, size);
142 http_read_buffer_->set_offset(size);
145 void CreateStream(MockRead reads[],
146 size_t reads_count,
147 MockWrite writes[],
148 size_t writes_count) {
149 stream_ = WebSocketBasicStream::CreateWebSocketBasicStreamForTesting(
150 MakeTransportSocket(reads, reads_count, writes, writes_count),
151 http_read_buffer_,
152 sub_protocol_,
153 extensions_,
154 generator_);
157 template <size_t N>
158 void CreateReadOnly(MockRead (&reads)[N]) {
159 CreateStream(reads, N, NULL, 0);
162 void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); }
164 scoped_ptr<SocketDataProvider> socket_data_;
165 MockClientSocketFactory factory_;
166 MockTransportClientSocketPool pool_;
167 BoundTestNetLog(bound_net_log_);
168 ScopedVector<WebSocketFrame> frames_;
169 TestCompletionCallback cb_;
170 scoped_refptr<GrowableIOBuffer> http_read_buffer_;
171 std::string sub_protocol_;
172 std::string extensions_;
173 WebSocketBasicStream::WebSocketMaskingKeyGeneratorFunction generator_;
174 bool expect_all_io_to_complete_;
177 // A test fixture for the common case of tests that only perform a single read.
178 class WebSocketBasicStreamSocketSingleReadTest
179 : public WebSocketBasicStreamSocketTest {
180 protected:
181 void CreateRead(const MockRead& read) {
182 reads_[0] = read;
183 CreateStream(reads_, 1U, NULL, 0);
186 MockRead reads_[1];
189 // A test fixture for tests that perform chunked reads.
190 class WebSocketBasicStreamSocketChunkedReadTest
191 : public WebSocketBasicStreamSocketTest {
192 protected:
193 // Specify the behaviour if there aren't enough chunks to use all the data. If
194 // LAST_FRAME_BIG is specified, then the rest of the data will be
195 // put in the last chunk. If LAST_FRAME_NOT_BIG is specified, then the last
196 // frame will be no bigger than the rest of the frames (but it can be smaller,
197 // if not enough data remains).
198 enum LastFrameBehaviour {
199 LAST_FRAME_BIG,
200 LAST_FRAME_NOT_BIG
203 // Prepares a read from |data| of |data_size|, split into |number_of_chunks|,
204 // each of |chunk_size| (except that the last chunk may be larger or
205 // smaller). All reads must be either SYNCHRONOUS or ASYNC (not a mixture),
206 // and errors cannot be simulated. Once data is exhausted, further reads will
207 // return 0 (ie. connection closed).
208 void CreateChunkedRead(IoMode mode,
209 const char data[],
210 size_t data_size,
211 int chunk_size,
212 int number_of_chunks,
213 LastFrameBehaviour last_frame_behaviour) {
214 reads_.reset(new MockRead[number_of_chunks]);
215 const char* start = data;
216 for (int i = 0; i < number_of_chunks; ++i) {
217 int len = chunk_size;
218 const bool is_last_chunk = (i == number_of_chunks - 1);
219 if ((last_frame_behaviour == LAST_FRAME_BIG && is_last_chunk) ||
220 static_cast<int>(data + data_size - start) < len) {
221 len = static_cast<int>(data + data_size - start);
223 reads_[i] = MockRead(mode, start, len);
224 start += len;
226 CreateStream(reads_.get(), number_of_chunks, NULL, 0);
229 scoped_ptr<MockRead[]> reads_;
232 // Test fixture for write tests.
233 class WebSocketBasicStreamSocketWriteTest
234 : public WebSocketBasicStreamSocketTest {
235 protected:
236 // All write tests use the same frame, so it is easiest to create it during
237 // test creation.
238 void SetUp() override { PrepareWriteFrame(); }
240 // Creates a WebSocketFrame with a wire format matching kWriteFrame and adds
241 // it to |frames_|.
242 void PrepareWriteFrame() {
243 scoped_ptr<WebSocketFrame> frame(
244 new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
245 const size_t payload_size =
246 kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize +
247 WebSocketFrameHeader::kMaskingKeyLength);
248 frame->data = new IOBuffer(payload_size);
249 memcpy(frame->data->data(),
250 kWriteFrame + kWriteFrameSize - payload_size,
251 payload_size);
252 WebSocketFrameHeader& header = frame->header;
253 header.final = true;
254 header.masked = true;
255 header.payload_length = payload_size;
256 frames_.push_back(frame.Pass());
259 // Creates a stream that expects the listed writes.
260 template <size_t N>
261 void CreateWriteOnly(MockWrite (&writes)[N]) {
262 CreateStream(NULL, 0, writes, N);
266 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
267 CreateNullStream();
270 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncReadWorks) {
271 CreateRead(MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize));
272 int result = stream_->ReadFrames(&frames_, cb_.callback());
273 EXPECT_EQ(OK, result);
274 ASSERT_EQ(1U, frames_.size());
275 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
276 EXPECT_TRUE(frames_[0]->header.final);
279 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncReadWorks) {
280 CreateRead(MockRead(ASYNC, kSampleFrame, kSampleFrameSize));
281 int result = stream_->ReadFrames(&frames_, cb_.callback());
282 ASSERT_EQ(ERR_IO_PENDING, result);
283 EXPECT_EQ(OK, cb_.WaitForResult());
284 ASSERT_EQ(1U, frames_.size());
285 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
286 // Don't repeat all the tests from SyncReadWorks; just enough to be sure the
287 // frame was really read.
290 // ReadFrames will not return a frame whose header has not been wholly received.
291 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedSync) {
292 CreateChunkedRead(
293 SYNCHRONOUS, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
294 int result = stream_->ReadFrames(&frames_, cb_.callback());
295 EXPECT_EQ(OK, result);
296 ASSERT_EQ(1U, frames_.size());
297 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
300 // The same behaviour applies to asynchronous reads.
301 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedAsync) {
302 CreateChunkedRead(
303 ASYNC, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
304 int result = stream_->ReadFrames(&frames_, cb_.callback());
305 ASSERT_EQ(ERR_IO_PENDING, result);
306 EXPECT_EQ(OK, cb_.WaitForResult());
307 ASSERT_EQ(1U, frames_.size());
308 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
311 // If it receives an incomplete header in a synchronous call, then has to wait
312 // for the rest of the frame, ReadFrames will return ERR_IO_PENDING.
313 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) {
314 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1),
315 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
316 CreateReadOnly(reads);
317 int result = stream_->ReadFrames(&frames_, cb_.callback());
318 ASSERT_EQ(ERR_IO_PENDING, result);
319 EXPECT_EQ(OK, cb_.WaitForResult());
320 ASSERT_EQ(1U, frames_.size());
321 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
324 // An extended header should also return ERR_IO_PENDING if it is not completely
325 // received.
326 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) {
327 MockRead reads[] = {
328 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1),
329 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
330 CreateReadOnly(reads);
331 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
334 // A frame that does not arrive in a single read should be broken into separate
335 // frames.
336 TEST_F(WebSocketBasicStreamSocketSingleReadTest, LargeFrameFirstChunk) {
337 CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize));
338 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
339 ASSERT_EQ(1U, frames_.size());
340 EXPECT_FALSE(frames_[0]->header.final);
341 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
342 static_cast<size_t>(frames_[0]->header.payload_length));
345 // If only the header of a data frame arrives, we should receive a frame with a
346 // zero-size payload.
347 TEST_F(WebSocketBasicStreamSocketSingleReadTest, HeaderOnlyChunk) {
348 CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize));
350 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
351 ASSERT_EQ(1U, frames_.size());
352 EXPECT_EQ(NULL, frames_[0]->data.get());
353 EXPECT_EQ(0U, frames_[0]->header.payload_length);
354 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
357 // If the header and the body of a data frame arrive seperately, we should see
358 // them as separate frames.
359 TEST_F(WebSocketBasicStreamSocketTest, HeaderBodySeparated) {
360 MockRead reads[] = {
361 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize),
362 MockRead(ASYNC,
363 kPartialLargeFrame + kLargeFrameHeaderSize,
364 kPartialLargeFrameSize - kLargeFrameHeaderSize)};
365 CreateReadOnly(reads);
366 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
367 ASSERT_EQ(1U, frames_.size());
368 EXPECT_EQ(NULL, frames_[0]->data.get());
369 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
370 frames_.clear();
371 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
372 EXPECT_EQ(OK, cb_.WaitForResult());
373 ASSERT_EQ(1U, frames_.size());
374 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
375 frames_[0]->header.payload_length);
376 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
377 frames_[0]->header.opcode);
380 // Every frame has a header with a correct payload_length field.
381 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, LargeFrameTwoChunks) {
382 const size_t kChunkSize = 16;
383 CreateChunkedRead(ASYNC,
384 kPartialLargeFrame,
385 kPartialLargeFrameSize,
386 kChunkSize,
388 LAST_FRAME_NOT_BIG);
389 TestCompletionCallback cb[2];
391 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
392 EXPECT_EQ(OK, cb[0].WaitForResult());
393 ASSERT_EQ(1U, frames_.size());
394 EXPECT_EQ(kChunkSize - kLargeFrameHeaderSize,
395 frames_[0]->header.payload_length);
397 frames_.clear();
398 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback()));
399 EXPECT_EQ(OK, cb[1].WaitForResult());
400 ASSERT_EQ(1U, frames_.size());
401 EXPECT_EQ(kChunkSize, frames_[0]->header.payload_length);
404 // Only the final frame of a fragmented message has |final| bit set.
405 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OnlyFinalChunkIsFinal) {
406 static const size_t kFirstChunkSize = 4;
407 CreateChunkedRead(ASYNC,
408 kSampleFrame,
409 kSampleFrameSize,
410 kFirstChunkSize,
412 LAST_FRAME_BIG);
413 TestCompletionCallback cb[2];
415 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
416 EXPECT_EQ(OK, cb[0].WaitForResult());
417 ASSERT_EQ(1U, frames_.size());
418 ASSERT_FALSE(frames_[0]->header.final);
420 frames_.clear();
421 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback()));
422 EXPECT_EQ(OK, cb[1].WaitForResult());
423 ASSERT_EQ(1U, frames_.size());
424 ASSERT_TRUE(frames_[0]->header.final);
427 // All frames after the first have their opcode changed to Continuation.
428 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ContinuationOpCodeUsed) {
429 const size_t kFirstChunkSize = 3;
430 const int kChunkCount = 3;
431 // The input data is one frame with opcode Text, which arrives in three
432 // separate chunks.
433 CreateChunkedRead(ASYNC,
434 kSampleFrame,
435 kSampleFrameSize,
436 kFirstChunkSize,
437 kChunkCount,
438 LAST_FRAME_BIG);
439 TestCompletionCallback cb[kChunkCount];
441 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
442 EXPECT_EQ(OK, cb[0].WaitForResult());
443 ASSERT_EQ(1U, frames_.size());
444 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
446 // This test uses a loop to verify that the opcode for every frames generated
447 // after the first is converted to Continuation.
448 for (int i = 1; i < kChunkCount; ++i) {
449 frames_.clear();
450 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[i].callback()));
451 EXPECT_EQ(OK, cb[i].WaitForResult());
452 ASSERT_EQ(1U, frames_.size());
453 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
454 frames_[0]->header.opcode);
458 // Multiple frames that arrive together should be parsed correctly.
459 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ThreeFramesTogether) {
460 CreateRead(MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize));
462 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
463 ASSERT_EQ(3U, frames_.size());
464 EXPECT_TRUE(frames_[0]->header.final);
465 EXPECT_TRUE(frames_[1]->header.final);
466 EXPECT_TRUE(frames_[2]->header.final);
469 // ERR_CONNECTION_CLOSED must be returned on close.
470 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncClose) {
471 CreateRead(MockRead(SYNCHRONOUS, "", 0));
473 EXPECT_EQ(ERR_CONNECTION_CLOSED,
474 stream_->ReadFrames(&frames_, cb_.callback()));
477 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncClose) {
478 CreateRead(MockRead(ASYNC, "", 0));
480 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
481 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
484 // The result should be the same if the socket returns
485 // ERR_CONNECTION_CLOSED. This is not expected to happen on an established
486 // connection; a Read of size 0 is the expected behaviour. The key point of this
487 // test is to confirm that ReadFrames() behaviour is identical in both cases.
488 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncCloseWithErr) {
489 CreateRead(MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED));
491 EXPECT_EQ(ERR_CONNECTION_CLOSED,
492 stream_->ReadFrames(&frames_, cb_.callback()));
495 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncCloseWithErr) {
496 CreateRead(MockRead(ASYNC, ERR_CONNECTION_CLOSED));
498 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
499 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
502 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncErrorsPassedThrough) {
503 // ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that
504 // WebSocketBasicStream gives no special handling to.
505 CreateRead(MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES));
507 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES,
508 stream_->ReadFrames(&frames_, cb_.callback()));
511 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncErrorsPassedThrough) {
512 CreateRead(MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES));
514 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
515 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, cb_.WaitForResult());
518 // If we get a frame followed by a close, we should receive them separately.
519 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, CloseAfterFrame) {
520 // The chunk size equals the data size, so the second chunk is 0 size, closing
521 // the connection.
522 CreateChunkedRead(SYNCHRONOUS,
523 kSampleFrame,
524 kSampleFrameSize,
525 kSampleFrameSize,
527 LAST_FRAME_NOT_BIG);
529 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
530 EXPECT_EQ(1U, frames_.size());
531 frames_.clear();
532 EXPECT_EQ(ERR_CONNECTION_CLOSED,
533 stream_->ReadFrames(&frames_, cb_.callback()));
536 // Synchronous close after an async frame header is handled by a different code
537 // path.
538 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) {
539 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
540 MockRead(SYNCHRONOUS, "", 0)};
541 CreateReadOnly(reads);
543 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
544 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
547 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a
548 // slightly different code path.
549 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) {
550 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
551 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
552 CreateReadOnly(reads);
554 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
555 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
558 // An empty first frame is not ignored.
559 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFirstFrame) {
560 CreateRead(MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize));
562 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
563 ASSERT_EQ(1U, frames_.size());
564 EXPECT_EQ(NULL, frames_[0]->data.get());
565 EXPECT_EQ(0U, frames_[0]->header.payload_length);
568 // An empty frame in the middle of a message is ignored.
569 TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrame) {
570 MockRead reads[] = {
571 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
572 MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
573 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
574 CreateReadOnly(reads);
576 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
577 EXPECT_EQ(1U, frames_.size());
578 frames_.clear();
579 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
582 // An empty frame in the middle of a message that arrives separately is still
583 // ignored.
584 TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrameAsync) {
585 MockRead reads[] = {
586 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
587 MockRead(ASYNC, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
588 // We include a pong message to verify the middle frame was actually
589 // processed.
590 MockRead(ASYNC, kValidPong, kValidPongSize)};
591 CreateReadOnly(reads);
593 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
594 EXPECT_EQ(1U, frames_.size());
595 frames_.clear();
596 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
597 EXPECT_EQ(OK, cb_.WaitForResult());
598 ASSERT_EQ(1U, frames_.size());
599 EXPECT_EQ(WebSocketFrameHeader::kOpCodePong, frames_[0]->header.opcode);
602 // An empty final frame is not ignored.
603 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFinalFrame) {
604 CreateRead(
605 MockRead(SYNCHRONOUS, kEmptyFinalTextFrame, kEmptyFinalTextFrameSize));
607 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
608 ASSERT_EQ(1U, frames_.size());
609 EXPECT_EQ(NULL, frames_[0]->data.get());
610 EXPECT_EQ(0U, frames_[0]->header.payload_length);
613 // An empty middle frame is ignored with a final frame present.
614 TEST_F(WebSocketBasicStreamSocketTest, ThreeFrameEmptyMessage) {
615 MockRead reads[] = {
616 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
617 MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
618 MockRead(SYNCHRONOUS,
619 kEmptyFinalContinuationFrame,
620 kEmptyFinalContinuationFrameSize)};
621 CreateReadOnly(reads);
623 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
624 ASSERT_EQ(1U, frames_.size());
625 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
626 frames_.clear();
627 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
628 ASSERT_EQ(1U, frames_.size());
629 EXPECT_TRUE(frames_[0]->header.final);
632 // If there was a frame read at the same time as the response headers (and the
633 // handshake succeeded), then we should parse it.
634 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) {
635 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize);
636 CreateNullStream();
638 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
639 ASSERT_EQ(1U, frames_.size());
640 ASSERT_TRUE(frames_[0]->data.get());
641 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
644 // Check that a frame whose header partially arrived at the end of the response
645 // headers works correctly.
646 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
647 PartialFrameHeaderInHttpResponse) {
648 SetHttpReadBuffer(kSampleFrame, 1);
649 CreateRead(MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1));
651 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
652 EXPECT_EQ(OK, cb_.WaitForResult());
653 ASSERT_EQ(1U, frames_.size());
654 ASSERT_TRUE(frames_[0]->data.get());
655 EXPECT_EQ(UINT64_C(6), frames_[0]->header.payload_length);
656 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
659 // Check that a control frame which partially arrives at the end of the response
660 // headers works correctly.
661 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
662 PartialControlFrameInHttpResponse) {
663 const size_t kPartialFrameBytes = 3;
664 SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes);
665 CreateRead(MockRead(ASYNC,
666 kCloseFrame + kPartialFrameBytes,
667 kCloseFrameSize - kPartialFrameBytes));
669 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
670 EXPECT_EQ(OK, cb_.WaitForResult());
671 ASSERT_EQ(1U, frames_.size());
672 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
673 EXPECT_EQ(kCloseFrameSize - 2, frames_[0]->header.payload_length);
674 EXPECT_EQ(
676 memcmp(frames_[0]->data->data(), kCloseFrame + 2, kCloseFrameSize - 2));
679 // Check that a control frame which partially arrives at the end of the response
680 // headers works correctly. Synchronous version (unlikely in practice).
681 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
682 PartialControlFrameInHttpResponseSync) {
683 const size_t kPartialFrameBytes = 3;
684 SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes);
685 CreateRead(MockRead(SYNCHRONOUS,
686 kCloseFrame + kPartialFrameBytes,
687 kCloseFrameSize - kPartialFrameBytes));
689 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
690 ASSERT_EQ(1U, frames_.size());
691 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
694 // Check that an invalid frame results in an error.
695 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncInvalidFrame) {
696 CreateRead(MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize));
698 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
699 stream_->ReadFrames(&frames_, cb_.callback()));
702 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncInvalidFrame) {
703 CreateRead(MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize));
705 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
706 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
709 // A control frame without a FIN flag is invalid and should not be passed
710 // through to higher layers. RFC6455 5.5 "All control frames ... MUST NOT be
711 // fragmented."
712 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ControlFrameWithoutFin) {
713 CreateRead(
714 MockRead(SYNCHRONOUS, kPingFrameWithoutFin, kPingFrameWithoutFinSize));
716 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
717 stream_->ReadFrames(&frames_, cb_.callback()));
718 EXPECT_TRUE(frames_.empty());
721 // A control frame over 125 characters is invalid. RFC6455 5.5 "All control
722 // frames MUST have a payload length of 125 bytes or less". Since we use a
723 // 125-byte buffer to assemble fragmented control frames, we need to detect this
724 // error before attempting to assemble the fragments.
725 TEST_F(WebSocketBasicStreamSocketSingleReadTest, OverlongControlFrame) {
726 CreateRead(MockRead(SYNCHRONOUS, k126BytePong, k126BytePongSize));
728 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
729 stream_->ReadFrames(&frames_, cb_.callback()));
730 EXPECT_TRUE(frames_.empty());
733 // A control frame over 125 characters should still be rejected if it is split
734 // into multiple chunks.
735 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SplitOverlongControlFrame) {
736 const size_t kFirstChunkSize = 16;
737 expect_all_io_to_complete_ = false;
738 CreateChunkedRead(SYNCHRONOUS,
739 k126BytePong,
740 k126BytePongSize,
741 kFirstChunkSize,
743 LAST_FRAME_BIG);
745 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
746 stream_->ReadFrames(&frames_, cb_.callback()));
747 EXPECT_TRUE(frames_.empty());
750 TEST_F(WebSocketBasicStreamSocketChunkedReadTest,
751 AsyncSplitOverlongControlFrame) {
752 const size_t kFirstChunkSize = 16;
753 expect_all_io_to_complete_ = false;
754 CreateChunkedRead(ASYNC,
755 k126BytePong,
756 k126BytePongSize,
757 kFirstChunkSize,
759 LAST_FRAME_BIG);
761 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
762 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
763 // The caller should not call ReadFrames() again after receiving an error
764 // other than ERR_IO_PENDING.
765 EXPECT_TRUE(frames_.empty());
768 // In the synchronous case, ReadFrames assembles the whole control frame before
769 // returning.
770 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SyncControlFrameAssembly) {
771 const size_t kChunkSize = 3;
772 CreateChunkedRead(
773 SYNCHRONOUS, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
775 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
776 ASSERT_EQ(1U, frames_.size());
777 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
780 // In the asynchronous case, the callback is not called until the control frame
781 // has been completely assembled.
782 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, AsyncControlFrameAssembly) {
783 const size_t kChunkSize = 3;
784 CreateChunkedRead(
785 ASYNC, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
787 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
788 EXPECT_EQ(OK, cb_.WaitForResult());
789 ASSERT_EQ(1U, frames_.size());
790 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
793 // A frame with a 1MB payload that has to be read in chunks.
794 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OneMegFrame) {
795 // This should be equal to the definition of kReadBufferSize in
796 // websocket_basic_stream.cc.
797 const int kReadBufferSize = 32 * 1024;
798 const uint64 kPayloadSize = 1 << 20;
799 const size_t kWireSize = kPayloadSize + kLargeFrameHeaderSize;
800 const size_t kExpectedFrameCount =
801 (kWireSize + kReadBufferSize - 1) / kReadBufferSize;
802 scoped_ptr<char[]> big_frame(new char[kWireSize]);
803 memcpy(big_frame.get(), "\x81\x7F", 2);
804 base::WriteBigEndian(big_frame.get() + 2, kPayloadSize);
805 memset(big_frame.get() + kLargeFrameHeaderSize, 'A', kPayloadSize);
807 CreateChunkedRead(ASYNC,
808 big_frame.get(),
809 kWireSize,
810 kReadBufferSize,
811 kExpectedFrameCount,
812 LAST_FRAME_BIG);
814 for (size_t frame = 0; frame < kExpectedFrameCount; ++frame) {
815 frames_.clear();
816 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
817 EXPECT_EQ(OK, cb_.WaitForResult());
818 ASSERT_EQ(1U, frames_.size());
819 size_t expected_payload_size = kReadBufferSize;
820 if (frame == 0) {
821 expected_payload_size = kReadBufferSize - kLargeFrameHeaderSize;
822 } else if (frame == kExpectedFrameCount - 1) {
823 expected_payload_size = kLargeFrameHeaderSize;
825 EXPECT_EQ(expected_payload_size, frames_[0]->header.payload_length);
829 // A frame with reserved flag(s) set that arrives in chunks should only have the
830 // reserved flag(s) set on the first chunk when split.
831 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ReservedFlagCleared) {
832 static const char kReservedFlagFrame[] = "\x41\x05Hello";
833 const size_t kReservedFlagFrameSize = arraysize(kReservedFlagFrame) - 1;
834 const size_t kChunkSize = 5;
836 CreateChunkedRead(ASYNC,
837 kReservedFlagFrame,
838 kReservedFlagFrameSize,
839 kChunkSize,
841 LAST_FRAME_BIG);
843 TestCompletionCallback cb[2];
844 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
845 EXPECT_EQ(OK, cb[0].WaitForResult());
846 ASSERT_EQ(1U, frames_.size());
847 EXPECT_TRUE(frames_[0]->header.reserved1);
849 frames_.clear();
850 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback()));
851 EXPECT_EQ(OK, cb[1].WaitForResult());
852 ASSERT_EQ(1U, frames_.size());
853 EXPECT_FALSE(frames_[0]->header.reserved1);
856 // Check that writing a frame all at once works.
857 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteAtOnce) {
858 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
859 CreateWriteOnly(writes);
861 EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
864 // Check that completely async writing works.
865 TEST_F(WebSocketBasicStreamSocketWriteTest, AsyncWriteAtOnce) {
866 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
867 CreateWriteOnly(writes);
869 ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
870 EXPECT_EQ(OK, cb_.WaitForResult());
873 // Check that writing a frame to an extremely full kernel buffer (so that it
874 // ends up being sent in bits) works. The WriteFrames() callback should not be
875 // called until all parts have been written.
876 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteInBits) {
877 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
878 MockWrite(ASYNC, kWriteFrame + 4, 4),
879 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
880 CreateWriteOnly(writes);
882 ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
883 EXPECT_EQ(OK, cb_.WaitForResult());
886 // Check that writing a Pong frame with a NULL body works.
887 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteNullPong) {
888 MockWrite writes[] = {
889 MockWrite(SYNCHRONOUS, kMaskedEmptyPong, kMaskedEmptyPongSize)};
890 CreateWriteOnly(writes);
892 scoped_ptr<WebSocketFrame> frame(
893 new WebSocketFrame(WebSocketFrameHeader::kOpCodePong));
894 WebSocketFrameHeader& header = frame->header;
895 header.final = true;
896 header.masked = true;
897 header.payload_length = 0;
898 ScopedVector<WebSocketFrame> frames;
899 frames.push_back(frame.Pass());
900 EXPECT_EQ(OK, stream_->WriteFrames(&frames, cb_.callback()));
903 // Check that writing with a non-NULL mask works correctly.
904 TEST_F(WebSocketBasicStreamSocketTest, WriteNonNulMask) {
905 std::string masked_frame = std::string("\x81\x88");
906 masked_frame += std::string(kNonNulMaskingKey.key, 4);
907 masked_frame += "jiggered";
908 MockWrite writes[] = {
909 MockWrite(SYNCHRONOUS, masked_frame.data(), masked_frame.size())};
910 generator_ = &GenerateNonNulMaskingKey;
911 CreateStream(NULL, 0, writes, arraysize(writes));
913 scoped_ptr<WebSocketFrame> frame(
914 new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
915 const std::string unmasked_payload = "graphics";
916 const size_t payload_size = unmasked_payload.size();
917 frame->data = new IOBuffer(payload_size);
918 memcpy(frame->data->data(), unmasked_payload.data(), payload_size);
919 WebSocketFrameHeader& header = frame->header;
920 header.final = true;
921 header.masked = true;
922 header.payload_length = payload_size;
923 frames_.push_back(frame.Pass());
925 EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
928 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
929 extensions_ = "inflate-uuencode";
930 CreateNullStream();
932 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
935 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
936 sub_protocol_ = "cyberchat";
937 CreateNullStream();
939 EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
942 } // namespace
943 } // namespace net