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/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"
     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 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'}};
     65 
     66 // A masking key generator function which generates the identity mask,
     67 // ie. "\0\0\0\0".
     68 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; }
     69 
     70 // A masking key generation function which generates a fixed masking key with no
     71 // nul characters.
     72 WebSocketMaskingKey GenerateNonNulMaskingKey() { return kNonNulMaskingKey; }
     73 
     74 // Base class for WebSocketBasicStream test fixtures.
     75 class WebSocketBasicStreamTest : public ::testing::Test {
     76  protected:
     77   scoped_ptr<WebSocketBasicStream> stream_;
     78   CapturingNetLog net_log_;
     79 };
     80 
     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) {}
     92 
     93   virtual ~StrictStaticSocketDataProvider() {
     94     if (strict_mode_) {
     95       EXPECT_EQ(read_count(), read_index());
     96       EXPECT_EQ(write_count(), write_index());
     97     }
     98   }
     99 
    100  private:
    101   const bool strict_mode_;
    102 };
    103 
    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) {}
    112 
    113   virtual ~WebSocketBasicStreamSocketTest() {
    114     // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so
    115     // should be destroyed first.
    116     stream_.reset();
    117   }
    118 
    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());
    127 
    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();
    137   }
    138 
    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);
    144   }
    145 
    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_);
    156   }
    157 
    158   template <size_t N>
    159   void CreateReadOnly(MockRead (&reads)[N]) {
    160     CreateStream(reads, N, NULL, 0);
    161   }
    162 
    163   void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); }
    164 
    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_;
    177 };
    178 
    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);
    186   }
    187 
    188   MockRead reads_[1];
    189 };
    190 
    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
    203   };
    204 
    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);
    224       }
    225       reads_[i] = MockRead(mode, start, len);
    226       start += len;
    227     }
    228     CreateStream(reads_.get(), number_of_chunks, NULL, 0);
    229   }
    230 
    231   scoped_ptr<MockRead[]> reads_;
    232 };
    233 
    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(); }
    241 
    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());
    259   }
    260 
    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);
    265   }
    266 };
    267 
    268 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
    269   CreateNullStream();
    270 }
    271 
    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);
    279 }
    280 
    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.
    290 }
    291 
    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);
    300 }
    301 
    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);
    311 }
    312 
    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);
    324 }
    325 
    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()));
    334 }
    335 
    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));
    345 }
    346 
    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));
    351 
    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);
    357 }
    358 
    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);
    380 }
    381 
    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,
    389                     2,
    390                     LAST_FRAME_NOT_BIG);
    391   TestCompletionCallback cb[2];
    392 
    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);
    398 
    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);
    404 }
    405 
    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,
    413                     2,
    414                     LAST_FRAME_BIG);
    415   TestCompletionCallback cb[2];
    416 
    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);
    421 
    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);
    427 }
    428 
    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];
    442 
    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);
    447 
    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);
    457   }
    458 }
    459 
    460 // Multiple frames that arrive together should be parsed correctly.
    461 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ThreeFramesTogether) {
    462   CreateRead(MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize));
    463 
    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);
    469 }
    470 
    471 // ERR_CONNECTION_CLOSED must be returned on close.
    472 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncClose) {
    473   CreateRead(MockRead(SYNCHRONOUS, "", 0));
    474 
    475   EXPECT_EQ(ERR_CONNECTION_CLOSED,
    476             stream_->ReadFrames(&frames_, cb_.callback()));
    477 }
    478 
    479 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncClose) {
    480   CreateRead(MockRead(ASYNC, "", 0));
    481 
    482   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    483   EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
    484 }
    485 
    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));
    492 
    493   EXPECT_EQ(ERR_CONNECTION_CLOSED,
    494             stream_->ReadFrames(&frames_, cb_.callback()));
    495 }
    496 
    497 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncCloseWithErr) {
    498   CreateRead(MockRead(ASYNC, ERR_CONNECTION_CLOSED));
    499 
    500   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    501   EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
    502 }
    503 
    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));
    508 
    509   EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES,
    510             stream_->ReadFrames(&frames_, cb_.callback()));
    511 }
    512 
    513 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncErrorsPassedThrough) {
    514   CreateRead(MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES));
    515 
    516   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    517   EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, cb_.WaitForResult());
    518 }
    519 
    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,
    528                     2,
    529                     LAST_FRAME_NOT_BIG);
    530 
    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()));
    536 }
    537 
    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);
    544 
    545   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    546   EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
    547 }
    548 
    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);
    555 
    556   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    557   EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
    558 }
    559 
    560 // An empty first frame is not ignored.
    561 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFirstFrame) {
    562   CreateRead(MockRead(SYNCHRONOUS, kEmptyFirstFrame, kEmptyFirstFrameSize));
    563 
    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);
    568 }
    569 
    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);
    577 
    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()));
    582 }
    583 
    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);
    594 
    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);
    602 }
    603 
    604 // An empty final frame is not ignored.
    605 TEST_F(WebSocketBasicStreamSocketSingleReadTest, EmptyFinalFrame) {
    606   CreateRead(
    607       MockRead(SYNCHRONOUS, kEmptyFinalTextFrame, kEmptyFinalTextFrameSize));
    608 
    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);
    613 }
    614 
    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);
    624 
    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);
    632 }
    633 
    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();
    639 
    640   EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
    641   ASSERT_EQ(1U, frames_.size());
    642   ASSERT_TRUE(frames_[0]->data);
    643   EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
    644 }
    645 
    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));
    652 
    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);
    657   EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
    658   EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
    659 }
    660 
    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));
    670 
    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(
    677       0,
    678       memcmp(frames_[0]->data->data(), kCloseFrame + 2, kCloseFrameSize - 2));
    679 }
    680 
    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));
    690 
    691   EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
    692   ASSERT_EQ(1U, frames_.size());
    693   EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
    694 }
    695 
    696 // Check that an invalid frame results in an error.
    697 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncInvalidFrame) {
    698   CreateRead(MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize));
    699 
    700   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
    701             stream_->ReadFrames(&frames_, cb_.callback()));
    702 }
    703 
    704 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncInvalidFrame) {
    705   CreateRead(MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize));
    706 
    707   ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
    708   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
    709 }
    710 
    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));
    717 
    718   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
    719             stream_->ReadFrames(&frames_, cb_.callback()));
    720   EXPECT_TRUE(frames_.empty());
    721 }
    722 
    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));
    729 
    730   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
    731             stream_->ReadFrames(&frames_, cb_.callback()));
    732   EXPECT_TRUE(frames_.empty());
    733 }
    734 
    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,
    744                     2,
    745                     LAST_FRAME_BIG);
    746 
    747   EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
    748             stream_->ReadFrames(&frames_, cb_.callback()));
    749   EXPECT_TRUE(frames_.empty());
    750 }
    751 
    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,
    760                     2,
    761                     LAST_FRAME_BIG);
    762 
    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());
    768 }
    769 
    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);
    776 
    777   EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
    778   ASSERT_EQ(1U, frames_.size());
    779   EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
    780 }
    781 
    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);
    788 
    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);
    793 }
    794 
    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);
    808 
    809   CreateChunkedRead(ASYNC,
    810                     big_frame.get(),
    811                     kWireSize,
    812                     kReadBufferSize,
    813                     kExpectedFrameCount,
    814                     LAST_FRAME_BIG);
    815 
    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;
    826     }
    827     EXPECT_EQ(expected_payload_size, frames_[0]->header.payload_length);
    828   }
    829 }
    830 
    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;
    837 
    838   CreateChunkedRead(ASYNC,
    839                     kReservedFlagFrame,
    840                     kReservedFlagFrameSize,
    841                     kChunkSize,
    842                     2,
    843                     LAST_FRAME_BIG);
    844 
    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);
    850 
    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);
    856 }
    857 
    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);
    862 
    863   EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
    864 }
    865 
    866 // Check that completely async writing works.
    867 TEST_F(WebSocketBasicStreamSocketWriteTest, AsyncWriteAtOnce) {
    868   MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
    869   CreateWriteOnly(writes);
    870 
    871   ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
    872   EXPECT_EQ(OK, cb_.WaitForResult());
    873 }
    874 
    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);
    883 
    884   ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
    885   EXPECT_EQ(OK, cb_.WaitForResult());
    886 }
    887 
    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);
    893 
    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()));
    903 }
    904 
    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));
    914 
    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());
    926 
    927   EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
    928 }
    929 
    930 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
    931   extensions_ = "inflate-uuencode";
    932   CreateNullStream();
    933 
    934   EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
    935 }
    936 
    937 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
    938   sub_protocol_ = "cyberchat";
    939   CreateNullStream();
    940 
    941   EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
    942 }
    943 
    944 }  // namespace
    945 }  // namespace net
    946