bookmarks: Move bookmark_test_helpers.h into 'bookmarks' namespace.
[chromium-blink-merge.git] / net / websockets / websocket_basic_stream_test.cc
blob92b7d3f88d45dfcf43e4abdcc13e87f6bf213d18
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 <string.h> // for memcpy() and memset().
13 #include <string>
15 #include "base/basictypes.h"
16 #include "base/big_endian.h"
17 #include "base/port.h"
18 #include "net/base/capturing_net_log.h"
19 #include "net/base/test_completion_callback.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 CapturingNetLog 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 : histograms_("a"),
109 pool_(1, 1, &histograms_, &factory_),
110 generator_(&GenerateNulMaskingKey),
111 expect_all_io_to_complete_(true) {}
113 virtual ~WebSocketBasicStreamSocketTest() {
114 // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so
115 // should be destroyed first.
116 stream_.reset();
119 scoped_ptr<ClientSocketHandle> MakeTransportSocket(MockRead reads[],
120 size_t reads_count,
121 MockWrite writes[],
122 size_t writes_count) {
123 socket_data_.reset(new StrictStaticSocketDataProvider(
124 reads, reads_count, writes, writes_count, expect_all_io_to_complete_));
125 socket_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
126 factory_.AddSocketDataProvider(socket_data_.get());
128 scoped_ptr<ClientSocketHandle> transport_socket(new ClientSocketHandle);
129 scoped_refptr<MockTransportSocketParams> params;
130 transport_socket->Init("a",
131 params,
132 MEDIUM,
133 CompletionCallback(),
134 &pool_,
135 bound_net_log_.bound());
136 return transport_socket.Pass();
139 void SetHttpReadBuffer(const char* data, size_t size) {
140 http_read_buffer_ = new GrowableIOBuffer;
141 http_read_buffer_->SetCapacity(size);
142 memcpy(http_read_buffer_->data(), data, size);
143 http_read_buffer_->set_offset(size);
146 void CreateStream(MockRead reads[],
147 size_t reads_count,
148 MockWrite writes[],
149 size_t writes_count) {
150 stream_ = WebSocketBasicStream::CreateWebSocketBasicStreamForTesting(
151 MakeTransportSocket(reads, reads_count, writes, writes_count),
152 http_read_buffer_,
153 sub_protocol_,
154 extensions_,
155 generator_);
158 template <size_t N>
159 void CreateReadOnly(MockRead (&reads)[N]) {
160 CreateStream(reads, N, NULL, 0);
163 void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); }
165 scoped_ptr<SocketDataProvider> socket_data_;
166 MockClientSocketFactory factory_;
167 ClientSocketPoolHistograms histograms_;
168 MockTransportClientSocketPool pool_;
169 CapturingBoundNetLog(bound_net_log_);
170 ScopedVector<WebSocketFrame> frames_;
171 TestCompletionCallback cb_;
172 scoped_refptr<GrowableIOBuffer> http_read_buffer_;
173 std::string sub_protocol_;
174 std::string extensions_;
175 WebSocketBasicStream::WebSocketMaskingKeyGeneratorFunction generator_;
176 bool expect_all_io_to_complete_;
179 // A test fixture for the common case of tests that only perform a single read.
180 class WebSocketBasicStreamSocketSingleReadTest
181 : public WebSocketBasicStreamSocketTest {
182 protected:
183 void CreateRead(const MockRead& read) {
184 reads_[0] = read;
185 CreateStream(reads_, 1U, NULL, 0);
188 MockRead reads_[1];
191 // A test fixture for tests that perform chunked reads.
192 class WebSocketBasicStreamSocketChunkedReadTest
193 : public WebSocketBasicStreamSocketTest {
194 protected:
195 // Specify the behaviour if there aren't enough chunks to use all the data. If
196 // LAST_FRAME_BIG is specified, then the rest of the data will be
197 // put in the last chunk. If LAST_FRAME_NOT_BIG is specified, then the last
198 // frame will be no bigger than the rest of the frames (but it can be smaller,
199 // if not enough data remains).
200 enum LastFrameBehaviour {
201 LAST_FRAME_BIG,
202 LAST_FRAME_NOT_BIG
205 // Prepares a read from |data| of |data_size|, split into |number_of_chunks|,
206 // each of |chunk_size| (except that the last chunk may be larger or
207 // smaller). All reads must be either SYNCHRONOUS or ASYNC (not a mixture),
208 // and errors cannot be simulated. Once data is exhausted, further reads will
209 // return 0 (ie. connection closed).
210 void CreateChunkedRead(IoMode mode,
211 const char data[],
212 size_t data_size,
213 int chunk_size,
214 int number_of_chunks,
215 LastFrameBehaviour last_frame_behaviour) {
216 reads_.reset(new MockRead[number_of_chunks]);
217 const char* start = data;
218 for (int i = 0; i < number_of_chunks; ++i) {
219 int len = chunk_size;
220 const bool is_last_chunk = (i == number_of_chunks - 1);
221 if ((last_frame_behaviour == LAST_FRAME_BIG && is_last_chunk) ||
222 static_cast<int>(data + data_size - start) < len) {
223 len = static_cast<int>(data + data_size - start);
225 reads_[i] = MockRead(mode, start, len);
226 start += len;
228 CreateStream(reads_.get(), number_of_chunks, NULL, 0);
231 scoped_ptr<MockRead[]> reads_;
234 // Test fixture for write tests.
235 class WebSocketBasicStreamSocketWriteTest
236 : public WebSocketBasicStreamSocketTest {
237 protected:
238 // All write tests use the same frame, so it is easiest to create it during
239 // test creation.
240 virtual void SetUp() override { PrepareWriteFrame(); }
242 // Creates a WebSocketFrame with a wire format matching kWriteFrame and adds
243 // it to |frames_|.
244 void PrepareWriteFrame() {
245 scoped_ptr<WebSocketFrame> frame(
246 new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
247 const size_t payload_size =
248 kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize +
249 WebSocketFrameHeader::kMaskingKeyLength);
250 frame->data = new IOBuffer(payload_size);
251 memcpy(frame->data->data(),
252 kWriteFrame + kWriteFrameSize - payload_size,
253 payload_size);
254 WebSocketFrameHeader& header = frame->header;
255 header.final = true;
256 header.masked = true;
257 header.payload_length = payload_size;
258 frames_.push_back(frame.release());
261 // Creates a stream that expects the listed writes.
262 template <size_t N>
263 void CreateWriteOnly(MockWrite (&writes)[N]) {
264 CreateStream(NULL, 0, writes, N);
268 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
269 CreateNullStream();
272 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncReadWorks) {
273 CreateRead(MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize));
274 int result = stream_->ReadFrames(&frames_, cb_.callback());
275 EXPECT_EQ(OK, result);
276 ASSERT_EQ(1U, frames_.size());
277 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
278 EXPECT_TRUE(frames_[0]->header.final);
281 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncReadWorks) {
282 CreateRead(MockRead(ASYNC, kSampleFrame, kSampleFrameSize));
283 int result = stream_->ReadFrames(&frames_, cb_.callback());
284 ASSERT_EQ(ERR_IO_PENDING, result);
285 EXPECT_EQ(OK, cb_.WaitForResult());
286 ASSERT_EQ(1U, frames_.size());
287 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
288 // Don't repeat all the tests from SyncReadWorks; just enough to be sure the
289 // frame was really read.
292 // ReadFrames will not return a frame whose header has not been wholly received.
293 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedSync) {
294 CreateChunkedRead(
295 SYNCHRONOUS, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
296 int result = stream_->ReadFrames(&frames_, cb_.callback());
297 EXPECT_EQ(OK, result);
298 ASSERT_EQ(1U, frames_.size());
299 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
302 // The same behaviour applies to asynchronous reads.
303 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedAsync) {
304 CreateChunkedRead(
305 ASYNC, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
306 int result = stream_->ReadFrames(&frames_, cb_.callback());
307 ASSERT_EQ(ERR_IO_PENDING, result);
308 EXPECT_EQ(OK, cb_.WaitForResult());
309 ASSERT_EQ(1U, frames_.size());
310 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
313 // If it receives an incomplete header in a synchronous call, then has to wait
314 // for the rest of the frame, ReadFrames will return ERR_IO_PENDING.
315 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) {
316 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1),
317 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
318 CreateReadOnly(reads);
319 int result = stream_->ReadFrames(&frames_, cb_.callback());
320 ASSERT_EQ(ERR_IO_PENDING, result);
321 EXPECT_EQ(OK, cb_.WaitForResult());
322 ASSERT_EQ(1U, frames_.size());
323 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
326 // An extended header should also return ERR_IO_PENDING if it is not completely
327 // received.
328 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) {
329 MockRead reads[] = {
330 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1),
331 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
332 CreateReadOnly(reads);
333 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
336 // A frame that does not arrive in a single read should be broken into separate
337 // frames.
338 TEST_F(WebSocketBasicStreamSocketSingleReadTest, LargeFrameFirstChunk) {
339 CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize));
340 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
341 ASSERT_EQ(1U, frames_.size());
342 EXPECT_FALSE(frames_[0]->header.final);
343 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
344 static_cast<size_t>(frames_[0]->header.payload_length));
347 // If only the header of a data frame arrives, we should receive a frame with a
348 // zero-size payload.
349 TEST_F(WebSocketBasicStreamSocketSingleReadTest, HeaderOnlyChunk) {
350 CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize));
352 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
353 ASSERT_EQ(1U, frames_.size());
354 EXPECT_EQ(NULL, frames_[0]->data.get());
355 EXPECT_EQ(0U, frames_[0]->header.payload_length);
356 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
359 // If the header and the body of a data frame arrive seperately, we should see
360 // them as separate frames.
361 TEST_F(WebSocketBasicStreamSocketTest, HeaderBodySeparated) {
362 MockRead reads[] = {
363 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize),
364 MockRead(ASYNC,
365 kPartialLargeFrame + kLargeFrameHeaderSize,
366 kPartialLargeFrameSize - kLargeFrameHeaderSize)};
367 CreateReadOnly(reads);
368 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
369 ASSERT_EQ(1U, frames_.size());
370 EXPECT_EQ(NULL, frames_[0]->data.get());
371 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
372 frames_.clear();
373 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
374 EXPECT_EQ(OK, cb_.WaitForResult());
375 ASSERT_EQ(1U, frames_.size());
376 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
377 frames_[0]->header.payload_length);
378 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
379 frames_[0]->header.opcode);
382 // Every frame has a header with a correct payload_length field.
383 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, LargeFrameTwoChunks) {
384 const size_t kChunkSize = 16;
385 CreateChunkedRead(ASYNC,
386 kPartialLargeFrame,
387 kPartialLargeFrameSize,
388 kChunkSize,
390 LAST_FRAME_NOT_BIG);
391 TestCompletionCallback cb[2];
393 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
394 EXPECT_EQ(OK, cb[0].WaitForResult());
395 ASSERT_EQ(1U, frames_.size());
396 EXPECT_EQ(kChunkSize - kLargeFrameHeaderSize,
397 frames_[0]->header.payload_length);
399 frames_.clear();
400 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback()));
401 EXPECT_EQ(OK, cb[1].WaitForResult());
402 ASSERT_EQ(1U, frames_.size());
403 EXPECT_EQ(kChunkSize, frames_[0]->header.payload_length);
406 // Only the final frame of a fragmented message has |final| bit set.
407 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OnlyFinalChunkIsFinal) {
408 static const size_t kFirstChunkSize = 4;
409 CreateChunkedRead(ASYNC,
410 kSampleFrame,
411 kSampleFrameSize,
412 kFirstChunkSize,
414 LAST_FRAME_BIG);
415 TestCompletionCallback cb[2];
417 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
418 EXPECT_EQ(OK, cb[0].WaitForResult());
419 ASSERT_EQ(1U, frames_.size());
420 ASSERT_FALSE(frames_[0]->header.final);
422 frames_.clear();
423 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback()));
424 EXPECT_EQ(OK, cb[1].WaitForResult());
425 ASSERT_EQ(1U, frames_.size());
426 ASSERT_TRUE(frames_[0]->header.final);
429 // All frames after the first have their opcode changed to Continuation.
430 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ContinuationOpCodeUsed) {
431 const size_t kFirstChunkSize = 3;
432 const int kChunkCount = 3;
433 // The input data is one frame with opcode Text, which arrives in three
434 // separate chunks.
435 CreateChunkedRead(ASYNC,
436 kSampleFrame,
437 kSampleFrameSize,
438 kFirstChunkSize,
439 kChunkCount,
440 LAST_FRAME_BIG);
441 TestCompletionCallback cb[kChunkCount];
443 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
444 EXPECT_EQ(OK, cb[0].WaitForResult());
445 ASSERT_EQ(1U, frames_.size());
446 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
448 // This test uses a loop to verify that the opcode for every frames generated
449 // after the first is converted to Continuation.
450 for (int i = 1; i < kChunkCount; ++i) {
451 frames_.clear();
452 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[i].callback()));
453 EXPECT_EQ(OK, cb[i].WaitForResult());
454 ASSERT_EQ(1U, frames_.size());
455 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
456 frames_[0]->header.opcode);
460 // Multiple frames that arrive together should be parsed correctly.
461 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ThreeFramesTogether) {
462 CreateRead(MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize));
464 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
465 ASSERT_EQ(3U, frames_.size());
466 EXPECT_TRUE(frames_[0]->header.final);
467 EXPECT_TRUE(frames_[1]->header.final);
468 EXPECT_TRUE(frames_[2]->header.final);
471 // ERR_CONNECTION_CLOSED must be returned on close.
472 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncClose) {
473 CreateRead(MockRead(SYNCHRONOUS, "", 0));
475 EXPECT_EQ(ERR_CONNECTION_CLOSED,
476 stream_->ReadFrames(&frames_, cb_.callback()));
479 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncClose) {
480 CreateRead(MockRead(ASYNC, "", 0));
482 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
483 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
486 // The result should be the same if the socket returns
487 // ERR_CONNECTION_CLOSED. This is not expected to happen on an established
488 // connection; a Read of size 0 is the expected behaviour. The key point of this
489 // test is to confirm that ReadFrames() behaviour is identical in both cases.
490 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncCloseWithErr) {
491 CreateRead(MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED));
493 EXPECT_EQ(ERR_CONNECTION_CLOSED,
494 stream_->ReadFrames(&frames_, cb_.callback()));
497 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncCloseWithErr) {
498 CreateRead(MockRead(ASYNC, ERR_CONNECTION_CLOSED));
500 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
501 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
504 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncErrorsPassedThrough) {
505 // ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that
506 // WebSocketBasicStream gives no special handling to.
507 CreateRead(MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES));
509 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES,
510 stream_->ReadFrames(&frames_, cb_.callback()));
513 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncErrorsPassedThrough) {
514 CreateRead(MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES));
516 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
517 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, cb_.WaitForResult());
520 // If we get a frame followed by a close, we should receive them separately.
521 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, CloseAfterFrame) {
522 // The chunk size equals the data size, so the second chunk is 0 size, closing
523 // the connection.
524 CreateChunkedRead(SYNCHRONOUS,
525 kSampleFrame,
526 kSampleFrameSize,
527 kSampleFrameSize,
529 LAST_FRAME_NOT_BIG);
531 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
532 EXPECT_EQ(1U, frames_.size());
533 frames_.clear();
534 EXPECT_EQ(ERR_CONNECTION_CLOSED,
535 stream_->ReadFrames(&frames_, cb_.callback()));
538 // Synchronous close after an async frame header is handled by a different code
539 // path.
540 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) {
541 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
542 MockRead(SYNCHRONOUS, "", 0)};
543 CreateReadOnly(reads);
545 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
546 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
549 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a
550 // slightly different code path.
551 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) {
552 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
553 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
554 CreateReadOnly(reads);
556 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
557 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
560 // An empty first frame is not ignored.
561 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFirstFrame) {
562 CreateRead(MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize));
564 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
565 ASSERT_EQ(1U, frames_.size());
566 EXPECT_EQ(NULL, frames_[0]->data.get());
567 EXPECT_EQ(0U, frames_[0]->header.payload_length);
570 // An empty frame in the middle of a message is ignored.
571 TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrame) {
572 MockRead reads[] = {
573 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
574 MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
575 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
576 CreateReadOnly(reads);
578 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
579 EXPECT_EQ(1U, frames_.size());
580 frames_.clear();
581 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
584 // An empty frame in the middle of a message that arrives separately is still
585 // ignored.
586 TEST_F(WebSocketBasicStreamSocketTest, EmptyMiddleFrameAsync) {
587 MockRead reads[] = {
588 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
589 MockRead(ASYNC, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
590 // We include a pong message to verify the middle frame was actually
591 // processed.
592 MockRead(ASYNC, kValidPong, kValidPongSize)};
593 CreateReadOnly(reads);
595 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
596 EXPECT_EQ(1U, frames_.size());
597 frames_.clear();
598 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
599 EXPECT_EQ(OK, cb_.WaitForResult());
600 ASSERT_EQ(1U, frames_.size());
601 EXPECT_EQ(WebSocketFrameHeader::kOpCodePong, frames_[0]->header.opcode);
604 // An empty final frame is not ignored.
605 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFinalFrame) {
606 CreateRead(
607 MockRead(SYNCHRONOUS, kEmptyFinalTextFrame, kEmptyFinalTextFrameSize));
609 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
610 ASSERT_EQ(1U, frames_.size());
611 EXPECT_EQ(NULL, frames_[0]->data.get());
612 EXPECT_EQ(0U, frames_[0]->header.payload_length);
615 // An empty middle frame is ignored with a final frame present.
616 TEST_F(WebSocketBasicStreamSocketTest, ThreeFrameEmptyMessage) {
617 MockRead reads[] = {
618 MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize),
619 MockRead(SYNCHRONOUS, kEmptyMiddleFrame, kEmptyMiddleFrameSize),
620 MockRead(SYNCHRONOUS,
621 kEmptyFinalContinuationFrame,
622 kEmptyFinalContinuationFrameSize)};
623 CreateReadOnly(reads);
625 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
626 ASSERT_EQ(1U, frames_.size());
627 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
628 frames_.clear();
629 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
630 ASSERT_EQ(1U, frames_.size());
631 EXPECT_TRUE(frames_[0]->header.final);
634 // If there was a frame read at the same time as the response headers (and the
635 // handshake succeeded), then we should parse it.
636 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) {
637 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize);
638 CreateNullStream();
640 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
641 ASSERT_EQ(1U, frames_.size());
642 ASSERT_TRUE(frames_[0]->data.get());
643 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
646 // Check that a frame whose header partially arrived at the end of the response
647 // headers works correctly.
648 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
649 PartialFrameHeaderInHttpResponse) {
650 SetHttpReadBuffer(kSampleFrame, 1);
651 CreateRead(MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1));
653 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
654 EXPECT_EQ(OK, cb_.WaitForResult());
655 ASSERT_EQ(1U, frames_.size());
656 ASSERT_TRUE(frames_[0]->data.get());
657 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
658 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
661 // Check that a control frame which partially arrives at the end of the response
662 // headers works correctly.
663 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
664 PartialControlFrameInHttpResponse) {
665 const size_t kPartialFrameBytes = 3;
666 SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes);
667 CreateRead(MockRead(ASYNC,
668 kCloseFrame + kPartialFrameBytes,
669 kCloseFrameSize - kPartialFrameBytes));
671 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
672 EXPECT_EQ(OK, cb_.WaitForResult());
673 ASSERT_EQ(1U, frames_.size());
674 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
675 EXPECT_EQ(kCloseFrameSize - 2, frames_[0]->header.payload_length);
676 EXPECT_EQ(
678 memcmp(frames_[0]->data->data(), kCloseFrame + 2, kCloseFrameSize - 2));
681 // Check that a control frame which partially arrives at the end of the response
682 // headers works correctly. Synchronous version (unlikely in practice).
683 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
684 PartialControlFrameInHttpResponseSync) {
685 const size_t kPartialFrameBytes = 3;
686 SetHttpReadBuffer(kCloseFrame, kPartialFrameBytes);
687 CreateRead(MockRead(SYNCHRONOUS,
688 kCloseFrame + kPartialFrameBytes,
689 kCloseFrameSize - kPartialFrameBytes));
691 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
692 ASSERT_EQ(1U, frames_.size());
693 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
696 // Check that an invalid frame results in an error.
697 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncInvalidFrame) {
698 CreateRead(MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize));
700 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
701 stream_->ReadFrames(&frames_, cb_.callback()));
704 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncInvalidFrame) {
705 CreateRead(MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize));
707 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
708 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
711 // A control frame without a FIN flag is invalid and should not be passed
712 // through to higher layers. RFC6455 5.5 "All control frames ... MUST NOT be
713 // fragmented."
714 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ControlFrameWithoutFin) {
715 CreateRead(
716 MockRead(SYNCHRONOUS, kPingFrameWithoutFin, kPingFrameWithoutFinSize));
718 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
719 stream_->ReadFrames(&frames_, cb_.callback()));
720 EXPECT_TRUE(frames_.empty());
723 // A control frame over 125 characters is invalid. RFC6455 5.5 "All control
724 // frames MUST have a payload length of 125 bytes or less". Since we use a
725 // 125-byte buffer to assemble fragmented control frames, we need to detect this
726 // error before attempting to assemble the fragments.
727 TEST_F(WebSocketBasicStreamSocketSingleReadTest, OverlongControlFrame) {
728 CreateRead(MockRead(SYNCHRONOUS, k126BytePong, k126BytePongSize));
730 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
731 stream_->ReadFrames(&frames_, cb_.callback()));
732 EXPECT_TRUE(frames_.empty());
735 // A control frame over 125 characters should still be rejected if it is split
736 // into multiple chunks.
737 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SplitOverlongControlFrame) {
738 const size_t kFirstChunkSize = 16;
739 expect_all_io_to_complete_ = false;
740 CreateChunkedRead(SYNCHRONOUS,
741 k126BytePong,
742 k126BytePongSize,
743 kFirstChunkSize,
745 LAST_FRAME_BIG);
747 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
748 stream_->ReadFrames(&frames_, cb_.callback()));
749 EXPECT_TRUE(frames_.empty());
752 TEST_F(WebSocketBasicStreamSocketChunkedReadTest,
753 AsyncSplitOverlongControlFrame) {
754 const size_t kFirstChunkSize = 16;
755 expect_all_io_to_complete_ = false;
756 CreateChunkedRead(ASYNC,
757 k126BytePong,
758 k126BytePongSize,
759 kFirstChunkSize,
761 LAST_FRAME_BIG);
763 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
764 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
765 // The caller should not call ReadFrames() again after receiving an error
766 // other than ERR_IO_PENDING.
767 EXPECT_TRUE(frames_.empty());
770 // In the synchronous case, ReadFrames assembles the whole control frame before
771 // returning.
772 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SyncControlFrameAssembly) {
773 const size_t kChunkSize = 3;
774 CreateChunkedRead(
775 SYNCHRONOUS, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
777 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
778 ASSERT_EQ(1U, frames_.size());
779 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
782 // In the asynchronous case, the callback is not called until the control frame
783 // has been completely assembled.
784 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, AsyncControlFrameAssembly) {
785 const size_t kChunkSize = 3;
786 CreateChunkedRead(
787 ASYNC, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
789 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
790 EXPECT_EQ(OK, cb_.WaitForResult());
791 ASSERT_EQ(1U, frames_.size());
792 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
795 // A frame with a 1MB payload that has to be read in chunks.
796 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OneMegFrame) {
797 // This should be equal to the definition of kReadBufferSize in
798 // websocket_basic_stream.cc.
799 const int kReadBufferSize = 32 * 1024;
800 const uint64 kPayloadSize = 1 << 20;
801 const size_t kWireSize = kPayloadSize + kLargeFrameHeaderSize;
802 const size_t kExpectedFrameCount =
803 (kWireSize + kReadBufferSize - 1) / kReadBufferSize;
804 scoped_ptr<char[]> big_frame(new char[kWireSize]);
805 memcpy(big_frame.get(), "\x81\x7F", 2);
806 base::WriteBigEndian(big_frame.get() + 2, kPayloadSize);
807 memset(big_frame.get() + kLargeFrameHeaderSize, 'A', kPayloadSize);
809 CreateChunkedRead(ASYNC,
810 big_frame.get(),
811 kWireSize,
812 kReadBufferSize,
813 kExpectedFrameCount,
814 LAST_FRAME_BIG);
816 for (size_t frame = 0; frame < kExpectedFrameCount; ++frame) {
817 frames_.clear();
818 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
819 EXPECT_EQ(OK, cb_.WaitForResult());
820 ASSERT_EQ(1U, frames_.size());
821 size_t expected_payload_size = kReadBufferSize;
822 if (frame == 0) {
823 expected_payload_size = kReadBufferSize - kLargeFrameHeaderSize;
824 } else if (frame == kExpectedFrameCount - 1) {
825 expected_payload_size = kLargeFrameHeaderSize;
827 EXPECT_EQ(expected_payload_size, frames_[0]->header.payload_length);
831 // A frame with reserved flag(s) set that arrives in chunks should only have the
832 // reserved flag(s) set on the first chunk when split.
833 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ReservedFlagCleared) {
834 static const char kReservedFlagFrame[] = "\x41\x05Hello";
835 const size_t kReservedFlagFrameSize = arraysize(kReservedFlagFrame) - 1;
836 const size_t kChunkSize = 5;
838 CreateChunkedRead(ASYNC,
839 kReservedFlagFrame,
840 kReservedFlagFrameSize,
841 kChunkSize,
843 LAST_FRAME_BIG);
845 TestCompletionCallback cb[2];
846 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
847 EXPECT_EQ(OK, cb[0].WaitForResult());
848 ASSERT_EQ(1U, frames_.size());
849 EXPECT_TRUE(frames_[0]->header.reserved1);
851 frames_.clear();
852 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback()));
853 EXPECT_EQ(OK, cb[1].WaitForResult());
854 ASSERT_EQ(1U, frames_.size());
855 EXPECT_FALSE(frames_[0]->header.reserved1);
858 // Check that writing a frame all at once works.
859 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteAtOnce) {
860 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
861 CreateWriteOnly(writes);
863 EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
866 // Check that completely async writing works.
867 TEST_F(WebSocketBasicStreamSocketWriteTest, AsyncWriteAtOnce) {
868 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
869 CreateWriteOnly(writes);
871 ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
872 EXPECT_EQ(OK, cb_.WaitForResult());
875 // Check that writing a frame to an extremely full kernel buffer (so that it
876 // ends up being sent in bits) works. The WriteFrames() callback should not be
877 // called until all parts have been written.
878 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteInBits) {
879 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
880 MockWrite(ASYNC, kWriteFrame + 4, 4),
881 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
882 CreateWriteOnly(writes);
884 ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
885 EXPECT_EQ(OK, cb_.WaitForResult());
888 // Check that writing a Pong frame with a NULL body works.
889 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteNullPong) {
890 MockWrite writes[] = {
891 MockWrite(SYNCHRONOUS, kMaskedEmptyPong, kMaskedEmptyPongSize)};
892 CreateWriteOnly(writes);
894 scoped_ptr<WebSocketFrame> frame(
895 new WebSocketFrame(WebSocketFrameHeader::kOpCodePong));
896 WebSocketFrameHeader& header = frame->header;
897 header.final = true;
898 header.masked = true;
899 header.payload_length = 0;
900 ScopedVector<WebSocketFrame> frames;
901 frames.push_back(frame.release());
902 EXPECT_EQ(OK, stream_->WriteFrames(&frames, cb_.callback()));
905 // Check that writing with a non-NULL mask works correctly.
906 TEST_F(WebSocketBasicStreamSocketTest, WriteNonNulMask) {
907 std::string masked_frame = std::string("\x81\x88");
908 masked_frame += std::string(kNonNulMaskingKey.key, 4);
909 masked_frame += "jiggered";
910 MockWrite writes[] = {
911 MockWrite(SYNCHRONOUS, masked_frame.data(), masked_frame.size())};
912 generator_ = &GenerateNonNulMaskingKey;
913 CreateStream(NULL, 0, writes, arraysize(writes));
915 scoped_ptr<WebSocketFrame> frame(
916 new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
917 const std::string unmasked_payload = "graphics";
918 const size_t payload_size = unmasked_payload.size();
919 frame->data = new IOBuffer(payload_size);
920 memcpy(frame->data->data(), unmasked_payload.data(), payload_size);
921 WebSocketFrameHeader& header = frame->header;
922 header.final = true;
923 header.masked = true;
924 header.payload_length = payload_size;
925 frames_.push_back(frame.release());
927 EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
930 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
931 extensions_ = "inflate-uuencode";
932 CreateNullStream();
934 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
937 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
938 sub_protocol_ = "cyberchat";
939 CreateNullStream();
941 EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
944 } // namespace
945 } // namespace net