Home | History | Annotate | Download | only in websockets
      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 <string.h>  // for memcpy() and memset().
     12 
     13 #include <string>
     14 
     15 #include "base/basictypes.h"
     16 #include "base/port.h"
     17 #include "net/base/big_endian.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"
     22 
     23 namespace net {
     24 namespace {
     25 
     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;
     29 
     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 const WebSocketMaskingKey kNulMaskingKey = {{'\0', '\0', '\0', '\0'}};
     61 const WebSocketMaskingKey kNonNulMaskingKey = {
     62     {'\x0d', '\x1b', '\x06', '\x17'}};
     63 
     64 // A masking key generator function which generates the identity mask,
     65 // ie. "\0\0\0\0".
     66 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; }
     67 
     68 // A masking key generation function which generates a fixed masking key with no
     69 // nul characters.
     70 WebSocketMaskingKey GenerateNonNulMaskingKey() { return kNonNulMaskingKey; }
     71 
     72 // Base class for WebSocketBasicStream test fixtures.
     73 class WebSocketBasicStreamTest : public ::testing::Test {
     74  protected:
     75   scoped_ptr<WebSocketBasicStream> stream_;
     76   CapturingNetLog net_log_;
     77 };
     78 
     79 // A subclass of StaticSocketDataProvider modified to require that all data
     80 // expected to be read or written actually is.
     81 class StrictStaticSocketDataProvider : public StaticSocketDataProvider {
     82  public:
     83   StrictStaticSocketDataProvider(MockRead* reads,
     84                                  size_t reads_count,
     85                                  MockWrite* writes,
     86                                  size_t writes_count,
     87                                  bool strict_mode)
     88       : StaticSocketDataProvider(reads, reads_count, writes, writes_count),
     89         strict_mode_(strict_mode) {}
     90 
     91   virtual ~StrictStaticSocketDataProvider() {
     92     if (strict_mode_) {
     93       EXPECT_EQ(read_count(), read_index());
     94       EXPECT_EQ(write_count(), write_index());
     95     }
     96   }
     97 
     98  private:
     99   const bool strict_mode_;
    100 };
    101 
    102 // A fixture for tests which only perform normal socket operations.
    103 class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest {
    104  protected:
    105   WebSocketBasicStreamSocketTest()
    106       : histograms_("a"),
    107         pool_(1, 1, &histograms_, &factory_),
    108         generator_(&GenerateNulMaskingKey),
    109         expect_all_io_to_complete_(true) {}
    110 
    111   virtual ~WebSocketBasicStreamSocketTest() {
    112     // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so
    113     // should be destroyed first.
    114     stream_.reset();
    115   }
    116 
    117   scoped_ptr<ClientSocketHandle> MakeTransportSocket(MockRead reads[],
    118                                                      size_t reads_count,
    119                                                      MockWrite writes[],
    120                                                      size_t writes_count) {
    121     socket_data_.reset(new StrictStaticSocketDataProvider(
    122         reads, reads_count, writes, writes_count, expect_all_io_to_complete_));
    123     socket_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
    124     factory_.AddSocketDataProvider(socket_data_.get());
    125 
    126     scoped_ptr<ClientSocketHandle> transport_socket(new ClientSocketHandle);
    127     scoped_refptr<MockTransportSocketParams> params;
    128     transport_socket->Init("a",
    129                            params,
    130                            MEDIUM,
    131                            CompletionCallback(),
    132                            &pool_,
    133                            bound_net_log_.bound());
    134     return transport_socket.Pass();
    135   }
    136 
    137   void SetHttpReadBuffer(const char* data, size_t size) {
    138     http_read_buffer_ = new GrowableIOBuffer;
    139     http_read_buffer_->SetCapacity(size);
    140     memcpy(http_read_buffer_->data(), data, size);
    141     http_read_buffer_->set_offset(size);
    142   }
    143 
    144   void CreateStream(MockRead reads[],
    145                     size_t reads_count,
    146                     MockWrite writes[],
    147                     size_t writes_count) {
    148     stream_ = WebSocketBasicStream::CreateWebSocketBasicStreamForTesting(
    149         MakeTransportSocket(reads, reads_count, writes, writes_count),
    150         http_read_buffer_,
    151         sub_protocol_,
    152         extensions_,
    153         generator_);
    154   }
    155 
    156   template <size_t N>
    157   void CreateReadOnly(MockRead (&reads)[N]) {
    158     CreateStream(reads, N, NULL, 0);
    159   }
    160 
    161   void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); }
    162 
    163   scoped_ptr<SocketDataProvider> socket_data_;
    164   MockClientSocketFactory factory_;
    165   ClientSocketPoolHistograms histograms_;
    166   MockTransportClientSocketPool pool_;
    167   CapturingBoundNetLog(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_;
    175 };
    176 
    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);
    184   }
    185 
    186   MockRead reads_[1];
    187 };
    188 
    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
    201   };
    202 
    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);
    222       }
    223       reads_[i] = MockRead(mode, start, len);
    224       start += len;
    225     }
    226     CreateStream(reads_.get(), number_of_chunks, NULL, 0);
    227   }
    228 
    229   scoped_ptr<MockRead[]> reads_;
    230 };
    231 
    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   virtual void SetUp() OVERRIDE { PrepareWriteFrame(); }
    239 
    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.release());
    257   }
    258 
    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);
    263   }
    264 };
    265 
    266 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
    267   CreateNullStream();
    268 }
    269 
    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(GG_UINT64_C(6), frames_[0]->header.payload_length);
    276   EXPECT_TRUE(frames_[0]->header.final);
    277 }
    278 
    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(GG_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.
    288 }
    289 
    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(GG_UINT64_C(6), frames_[0]->header.payload_length);
    298 }
    299 
    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(GG_UINT64_C(6), frames_[0]->header.payload_length);
    309 }
    310 
    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(GG_UINT64_C(6), frames_[0]->header.payload_length);
    322 }
    323 
    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()));
    332 }
    333 
    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));
    343 }
    344 
    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));
    349 
    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);
    355 }
    356 
    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);
    378 }
    379 
    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,
    387                     2,
    388                     LAST_FRAME_NOT_BIG);
    389   TestCompletionCallback cb[2];
    390 
    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);
    396 
    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);
    402 }
    403 
    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,
    411                     2,
    412                     LAST_FRAME_BIG);
    413   TestCompletionCallback cb[2];
    414 
    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);
    419 
    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);
    425 }
    426 
    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];
    440 
    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);
    445 
    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);
    455   }
    456 }
    457 
    458 // Multiple frames that arrive together should be parsed correctly.
    459 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ThreeFramesTogether) {
    460   CreateRead(MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize));
    461 
    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);
    467 }
    468 
    469 // ERR_CONNECTION_CLOSED must be returned on close.
    470 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncClose) {
    471   CreateRead(MockRead(SYNCHRONOUS, "", 0));
    472 
    473   EXPECT_EQ(ERR_CONNECTION_CLOSED,
    474             stream_->ReadFrames(&frames_, cb_.callback()));
    475 }
    476 
    477 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncClose) {
    478   CreateRead(MockRead(ASYNC, "", 0));
    479 
    480   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    481   EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
    482 }
    483 
    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));
    490 
    491   EXPECT_EQ(ERR_CONNECTION_CLOSED,
    492             stream_->ReadFrames(&frames_, cb_.callback()));
    493 }
    494 
    495 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncCloseWithErr) {
    496   CreateRead(MockRead(ASYNC, ERR_CONNECTION_CLOSED));
    497 
    498   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    499   EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
    500 }
    501 
    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));
    506 
    507   EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES,
    508             stream_->ReadFrames(&frames_, cb_.callback()));
    509 }
    510 
    511 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncErrorsPassedThrough) {
    512   CreateRead(MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES));
    513 
    514   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    515   EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, cb_.WaitForResult());
    516 }
    517 
    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,
    526                     2,
    527                     LAST_FRAME_NOT_BIG);
    528 
    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()));
    534 }
    535 
    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);
    542 
    543   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    544   EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
    545 }
    546 
    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);
    553 
    554   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    555   EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
    556 }
    557 
    558 // An empty first frame is not ignored.
    559 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFirstFrame) {
    560   CreateRead(MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize));
    561 
    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);
    566 }
    567 
    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);
    575 
    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()));
    580 }
    581 
    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);
    592 
    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);
    600 }
    601 
    602 // An empty final frame is not ignored.
    603 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFinalFrame) {
    604   CreateRead(
    605       MockRead(SYNCHRONOUS, kEmptyFinalTextFrame, kEmptyFinalTextFrameSize));
    606 
    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);
    611 }
    612 
    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);
    622 
    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);
    630 }
    631 
    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();
    637 
    638   EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
    639   ASSERT_EQ(1U, frames_.size());
    640   ASSERT_TRUE(frames_[0]->data);
    641   EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
    642 }
    643 
    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));
    650 
    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);
    655   EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
    656   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
    657 }
    658 
    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));
    668 
    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(
    675       0,
    676       memcmp(frames_[0]->data->data(), kCloseFrame + 2, kCloseFrameSize - 2));
    677 }
    678 
    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));
    688 
    689   EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
    690   ASSERT_EQ(1U, frames_.size());
    691   EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
    692 }
    693 
    694 // Check that an invalid frame results in an error.
    695 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncInvalidFrame) {
    696   CreateRead(MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize));
    697 
    698   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
    699             stream_->ReadFrames(&frames_, cb_.callback()));
    700 }
    701 
    702 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncInvalidFrame) {
    703   CreateRead(MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize));
    704 
    705   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    706   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
    707 }
    708 
    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));
    715 
    716   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
    717             stream_->ReadFrames(&frames_, cb_.callback()));
    718   EXPECT_TRUE(frames_.empty());
    719 }
    720 
    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));
    727 
    728   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
    729             stream_->ReadFrames(&frames_, cb_.callback()));
    730   EXPECT_TRUE(frames_.empty());
    731 }
    732 
    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,
    742                     2,
    743                     LAST_FRAME_BIG);
    744 
    745   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
    746             stream_->ReadFrames(&frames_, cb_.callback()));
    747   EXPECT_TRUE(frames_.empty());
    748 }
    749 
    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,
    758                     2,
    759                     LAST_FRAME_BIG);
    760 
    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());
    766 }
    767 
    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);
    774 
    775   EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
    776   ASSERT_EQ(1U, frames_.size());
    777   EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
    778 }
    779 
    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);
    786 
    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);
    791 }
    792 
    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   WriteBigEndian(big_frame.get() + 2, kPayloadSize);
    805   memset(big_frame.get() + kLargeFrameHeaderSize, 'A', kPayloadSize);
    806 
    807   CreateChunkedRead(ASYNC,
    808                     big_frame.get(),
    809                     kWireSize,
    810                     kReadBufferSize,
    811                     kExpectedFrameCount,
    812                     LAST_FRAME_BIG);
    813 
    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;
    824     }
    825     EXPECT_EQ(expected_payload_size, frames_[0]->header.payload_length);
    826   }
    827 }
    828 
    829 // Check that writing a frame all at once works.
    830 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteAtOnce) {
    831   MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
    832   CreateWriteOnly(writes);
    833 
    834   EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
    835 }
    836 
    837 // Check that completely async writing works.
    838 TEST_F(WebSocketBasicStreamSocketWriteTest, AsyncWriteAtOnce) {
    839   MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
    840   CreateWriteOnly(writes);
    841 
    842   ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
    843   EXPECT_EQ(OK, cb_.WaitForResult());
    844 }
    845 
    846 // Check that writing a frame to an extremely full kernel buffer (so that it
    847 // ends up being sent in bits) works. The WriteFrames() callback should not be
    848 // called until all parts have been written.
    849 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteInBits) {
    850   MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
    851                         MockWrite(ASYNC, kWriteFrame + 4, 4),
    852                         MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
    853   CreateWriteOnly(writes);
    854 
    855   ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
    856   EXPECT_EQ(OK, cb_.WaitForResult());
    857 }
    858 
    859 // Check that writing with a non-NULL mask works correctly.
    860 TEST_F(WebSocketBasicStreamSocketTest, WriteNonNulMask) {
    861   std::string masked_frame = std::string("\x81\x88");
    862   masked_frame += std::string(kNonNulMaskingKey.key, 4);
    863   masked_frame += "jiggered";
    864   MockWrite writes[] = {
    865       MockWrite(SYNCHRONOUS, masked_frame.data(), masked_frame.size())};
    866   generator_ = &GenerateNonNulMaskingKey;
    867   CreateStream(NULL, 0, writes, arraysize(writes));
    868 
    869   scoped_ptr<WebSocketFrame> frame(
    870       new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
    871   const std::string unmasked_payload = "graphics";
    872   const size_t payload_size = unmasked_payload.size();
    873   frame->data = new IOBuffer(payload_size);
    874   memcpy(frame->data->data(), unmasked_payload.data(), payload_size);
    875   WebSocketFrameHeader& header = frame->header;
    876   header.final = true;
    877   header.masked = true;
    878   header.payload_length = payload_size;
    879   frames_.push_back(frame.release());
    880 
    881   EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
    882 }
    883 
    884 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
    885   extensions_ = "inflate-uuencode";
    886   CreateNullStream();
    887 
    888   EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
    889 }
    890 
    891 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
    892   sub_protocol_ = "cyberchat";
    893   CreateNullStream();
    894 
    895   EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
    896 }
    897 
    898 }  // namespace
    899 }  // namespace net
    900