Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / net / websockets / websocket_basic_stream_test.cc
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   ~StrictStaticSocketDataProvider() override {
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   ~WebSocketBasicStreamSocketTest() override {
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   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.get());
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.get());
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