Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1440)

Side by Side Diff: net/websockets/websocket_basic_stream_test.cc

Issue 23604044: Replace WebSocketFrameChunk with WebSocketFrame (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Add CreateFrame() method. Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // Tests for WebSocketBasicStream. Note that we do not attempt to verify that 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 6 // frame parsing itself functions correctly, as that is covered by the
7 // WebSocketFrameParser tests. 7 // WebSocketFrameParser tests.
8 8
9 #include "net/websockets/websocket_basic_stream.h" 9 #include "net/websockets/websocket_basic_stream.h"
10 10
(...skipping 19 matching lines...) Expand all
30 "chromiunum ad pasco per loca insanis pullum manducat frumenti"; 30 "chromiunum ad pasco per loca insanis pullum manducat frumenti";
31 const size_t kPartialLargeFrameSize = arraysize(kPartialLargeFrame) - 1; 31 const size_t kPartialLargeFrameSize = arraysize(kPartialLargeFrame) - 1;
32 const size_t kLargeFrameHeaderSize = 10; 32 const size_t kLargeFrameHeaderSize = 10;
33 const size_t kLargeFrameDeclaredPayloadSize = 0x7FFFFFFF; 33 const size_t kLargeFrameDeclaredPayloadSize = 0x7FFFFFFF;
34 const char kMultipleFrames[] = "\x81\x01X\x81\x01Y\x81\x01Z"; 34 const char kMultipleFrames[] = "\x81\x01X\x81\x01Y\x81\x01Z";
35 const size_t kMultipleFramesSize = arraysize(kMultipleFrames) - 1; 35 const size_t kMultipleFramesSize = arraysize(kMultipleFrames) - 1;
36 // This frame encodes a payload length of 7 in two bytes, which is always 36 // This frame encodes a payload length of 7 in two bytes, which is always
37 // invalid. 37 // invalid.
38 const char kInvalidFrame[] = "\x81\x7E\x00\x07Invalid"; 38 const char kInvalidFrame[] = "\x81\x7E\x00\x07Invalid";
39 const size_t kInvalidFrameSize = arraysize(kInvalidFrame) - 1; 39 const size_t kInvalidFrameSize = arraysize(kInvalidFrame) - 1;
40 // Control frames must have the FIN bit set. This one does not.
41 const char kPingFrameWithoutFin[] = "\x0A\x00";
42 const size_t kPingFrameWithoutFinSize = arraysize(kPingFrameWithoutFin) - 1;
43 // Control frames must have a payload of 125 bytes or less. This one has
44 // a payload of 126 bytes.
45 const char k126BytePong[] =
46 "\x89\x7e\x00\x7eZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ"
47 "ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
48 const size_t k126BytePongSize = arraysize(k126BytePong) - 1;
49 const char kCloseFrame[] = "\x88\x09\x03\xe8occludo";
50 const size_t kCloseFrameSize = arraysize(kCloseFrame) - 1;
40 const char kWriteFrame[] = "\x81\x85\x00\x00\x00\x00Write"; 51 const char kWriteFrame[] = "\x81\x85\x00\x00\x00\x00Write";
41 const size_t kWriteFrameSize = arraysize(kWriteFrame) - 1; 52 const size_t kWriteFrameSize = arraysize(kWriteFrame) - 1;
42 const WebSocketMaskingKey kNulMaskingKey = {{'\0', '\0', '\0', '\0'}}; 53 const WebSocketMaskingKey kNulMaskingKey = {{'\0', '\0', '\0', '\0'}};
43 54
44 // Generates a ScopedVector<WebSocketFrameChunk> which will have a wire format
45 // matching kWriteFrame.
46 ScopedVector<WebSocketFrameChunk> GenerateWriteFrame() {
47 scoped_ptr<WebSocketFrameChunk> chunk(new WebSocketFrameChunk);
48 const size_t payload_size =
49 kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize +
50 WebSocketFrameHeader::kMaskingKeyLength);
51 chunk->data = new IOBufferWithSize(payload_size);
52 memcpy(chunk->data->data(),
53 kWriteFrame + kWriteFrameSize - payload_size,
54 payload_size);
55 chunk->final_chunk = true;
56 scoped_ptr<WebSocketFrameHeader> header(
57 new WebSocketFrameHeader(WebSocketFrameHeader::kOpCodeText));
58 header->final = true;
59 header->masked = true;
60 header->payload_length = payload_size;
61 chunk->header = header.Pass();
62 ScopedVector<WebSocketFrameChunk> chunks;
63 chunks.push_back(chunk.release());
64 return chunks.Pass();
65 }
66
67 // A masking key generator function which generates the identity mask, 55 // A masking key generator function which generates the identity mask,
68 // ie. "\0\0\0\0". 56 // ie. "\0\0\0\0".
69 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; } 57 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; }
70 58
71 // Base class for WebSocketBasicStream test fixtures. 59 // Base class for WebSocketBasicStream test fixtures.
72 class WebSocketBasicStreamTest : public ::testing::Test { 60 class WebSocketBasicStreamTest : public ::testing::Test {
73 protected: 61 protected:
74 scoped_ptr<WebSocketBasicStream> stream_; 62 scoped_ptr<WebSocketBasicStream> stream_;
75 CapturingNetLog net_log_; 63 CapturingNetLog net_log_;
76 }; 64 };
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 sub_protocol_, 112 sub_protocol_,
125 extensions_, 113 extensions_,
126 &GenerateNulMaskingKey); 114 &GenerateNulMaskingKey);
127 } 115 }
128 116
129 template <size_t N> 117 template <size_t N>
130 void CreateReadOnly(MockRead (&reads)[N]) { 118 void CreateReadOnly(MockRead (&reads)[N]) {
131 CreateStream(reads, N, NULL, 0); 119 CreateStream(reads, N, NULL, 0);
132 } 120 }
133 121
134 template <size_t N>
135 void CreateWriteOnly(MockWrite (&writes)[N]) {
136 CreateStream(NULL, 0, writes, N);
137 }
138
139 void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); } 122 void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); }
140 123
141 scoped_ptr<SocketDataProvider> socket_data_; 124 scoped_ptr<SocketDataProvider> socket_data_;
142 MockClientSocketFactory factory_; 125 MockClientSocketFactory factory_;
143 ClientSocketPoolHistograms histograms_; 126 ClientSocketPoolHistograms histograms_;
144 MockTransportClientSocketPool pool_; 127 MockTransportClientSocketPool pool_;
145 CapturingBoundNetLog(bound_net_log_); 128 CapturingBoundNetLog(bound_net_log_);
146 ScopedVector<WebSocketFrameChunk> frame_chunks_; 129 ScopedVector<WebSocketFrame> frames_;
147 TestCompletionCallback cb_; 130 TestCompletionCallback cb_;
148 scoped_refptr<GrowableIOBuffer> http_read_buffer_; 131 scoped_refptr<GrowableIOBuffer> http_read_buffer_;
149 std::string sub_protocol_; 132 std::string sub_protocol_;
150 std::string extensions_; 133 std::string extensions_;
151 }; 134 };
152 135
136 // A test fixture for the common case of tests that only perform a single read.
137 class WebSocketBasicStreamSocketSingleReadTest
138 : public WebSocketBasicStreamSocketTest {
139 protected:
140 void CreateRead(const MockRead& read) {
141 reads_[0] = read;
142 CreateStream(reads_, 1U, NULL, 0);
143 }
144
145 MockRead reads_[1];
146 };
147
148 // A test fixture for tests that perform chunked reads.
149 class WebSocketBasicStreamSocketChunkedReadTest
150 : public WebSocketBasicStreamSocketTest {
151 protected:
152 // Specify the behaviour if there aren't enough chunks to use all the data. If
153 // LAST_FRAME_BIG is specified, the the rest of the data will be
154 // put in the last chunk. If LAST_FRAME_NOT_BIG is specified, then the last
155 // frame will be no bigger than the rest of the frames (but it can be smaller,
156 // if not enough data remains).
157 enum LastFrameBehaviour {
158 LAST_FRAME_BIG,
159 LAST_FRAME_NOT_BIG
160 };
161
162 // Prepares a read from |data| of |data_size|, split into |number_of_chunks|,
163 // each of |chunk_size| (except that the last chunk may be larger or
164 // smaller). All reads must be either SYNCHRONOUS or ASYNC (not a mixture),
165 // and errors cannot be simulated. Once data is exhausted, further reads will
166 // return 0 (ie. connection closed).
167 void CreateChunkedRead(IoMode mode,
168 const char data[],
169 size_t data_size,
170 int chunk_size,
171 int number_of_chunks,
172 LastFrameBehaviour last_frame_behaviour) {
173 reads_.reset(new MockRead[number_of_chunks]);
174 const char* start = data;
175 for (int i = 0; i < number_of_chunks; ++i) {
176 int len = chunk_size;
177 const bool is_last_chunk = (i == number_of_chunks - 1);
178 if ((last_frame_behaviour == LAST_FRAME_BIG && is_last_chunk) ||
179 static_cast<int>(data + data_size - start) < len) {
180 len = static_cast<int>(data + data_size - start);
181 }
182 reads_[i] = MockRead(mode, start, len);
183 start += len;
184 }
185 CreateStream(reads_.get(), number_of_chunks, NULL, 0);
186 }
187
188 scoped_ptr<MockRead[]> reads_;
189 };
190
191 // Test fixture for write tests.
192 class WebSocketBasicStreamSocketWriteTest
193 : public WebSocketBasicStreamSocketTest {
194 protected:
195 // All write tests use the same frame, so it is easiest to create it during
196 // test creation.
197 virtual void SetUp() OVERRIDE { PrepareWriteFrame(); }
198
199 // Create a WebSocketFrame with a wire format matching kWriteFrame and add it
200 // to frames_.
201 void PrepareWriteFrame() {
202 scoped_ptr<WebSocketFrame> frame(
203 new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
204 const size_t payload_size =
205 kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize +
206 WebSocketFrameHeader::kMaskingKeyLength);
207 frame->data = new IOBuffer(payload_size);
208 memcpy(frame->data->data(),
209 kWriteFrame + kWriteFrameSize - payload_size,
210 payload_size);
211 WebSocketFrameHeader& header = frame->header;
212 header.final = true;
213 header.masked = true;
214 header.payload_length = payload_size;
215 frames_.push_back(frame.release());
216 }
217
218 // Create a stream that expects the listed writes.
219 template <size_t N>
220 void CreateWriteOnly(MockWrite (&writes)[N]) {
221 CreateStream(NULL, 0, writes, N);
222 }
223 };
224
153 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) { 225 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
154 CreateNullStream(); 226 CreateNullStream();
155 } 227 }
156 228
157 TEST_F(WebSocketBasicStreamSocketTest, SyncReadWorks) { 229 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncReadWorks) {
158 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize)}; 230 CreateRead(MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize));
159 CreateReadOnly(reads); 231 int result = stream_->ReadFrames(&frames_, cb_.callback());
160 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
161 EXPECT_EQ(OK, result); 232 EXPECT_EQ(OK, result);
162 ASSERT_EQ(1U, frame_chunks_.size()); 233 ASSERT_EQ(1U, frames_.size());
163 ASSERT_TRUE(frame_chunks_[0]->header); 234 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
164 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length); 235 EXPECT_TRUE(frames_[0]->header.final);
165 EXPECT_TRUE(frame_chunks_[0]->header->final);
166 EXPECT_TRUE(frame_chunks_[0]->final_chunk);
167 } 236 }
168 237
169 TEST_F(WebSocketBasicStreamSocketTest, AsyncReadWorks) { 238 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncReadWorks) {
170 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kSampleFrameSize)}; 239 CreateRead(MockRead(ASYNC, kSampleFrame, kSampleFrameSize));
171 CreateReadOnly(reads); 240 int result = stream_->ReadFrames(&frames_, cb_.callback());
172 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
173 ASSERT_EQ(ERR_IO_PENDING, result); 241 ASSERT_EQ(ERR_IO_PENDING, result);
174 EXPECT_EQ(OK, cb_.WaitForResult()); 242 EXPECT_EQ(OK, cb_.WaitForResult());
175 ASSERT_EQ(1U, frame_chunks_.size()); 243 ASSERT_EQ(1U, frames_.size());
176 ASSERT_TRUE(frame_chunks_[0]->header); 244 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
177 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
178 // Don't repeat all the tests from SyncReadWorks; just enough to be sure the 245 // Don't repeat all the tests from SyncReadWorks; just enough to be sure the
179 // frame was really read. 246 // frame was really read.
180 } 247 }
181 248
182 // ReadFrames will not return a frame whose header has not been wholly received. 249 // ReadFrames will not return a frame whose header has not been wholly received.
183 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSync) { 250 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedSync) {
184 MockRead reads[] = { 251 CreateChunkedRead(
185 MockRead(SYNCHRONOUS, kSampleFrame, 1), 252 SYNCHRONOUS, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
186 MockRead(SYNCHRONOUS, kSampleFrame + 1, kSampleFrameSize - 1)}; 253 int result = stream_->ReadFrames(&frames_, cb_.callback());
187 CreateReadOnly(reads);
188 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
189 ASSERT_EQ(OK, result); 254 ASSERT_EQ(OK, result);
190 ASSERT_EQ(1U, frame_chunks_.size()); 255 ASSERT_EQ(1U, frames_.size());
191 ASSERT_TRUE(frame_chunks_[0]->header); 256 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
192 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
193 } 257 }
194 258
195 // The same behaviour applies to asynchronous reads. 259 // The same behaviour applies to asynchronous reads.
196 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedAsync) { 260 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedAsync) {
197 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1), 261 CreateChunkedRead(
198 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)}; 262 ASYNC, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
199 CreateReadOnly(reads); 263 int result = stream_->ReadFrames(&frames_, cb_.callback());
200 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
201 ASSERT_EQ(ERR_IO_PENDING, result); 264 ASSERT_EQ(ERR_IO_PENDING, result);
202 EXPECT_EQ(OK, cb_.WaitForResult()); 265 EXPECT_EQ(OK, cb_.WaitForResult());
203 ASSERT_EQ(1U, frame_chunks_.size()); 266 ASSERT_EQ(1U, frames_.size());
204 ASSERT_TRUE(frame_chunks_[0]->header); 267 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
205 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
206 } 268 }
207 269
208 // If it receives an incomplete header in a synchronous call, then has to wait 270 // If it receives an incomplete header in a synchronous call, then has to wait
209 // for the rest of the frame, ReadFrames will return ERR_IO_PENDING. 271 // for the rest of the frame, ReadFrames will return ERR_IO_PENDING.
210 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) { 272 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) {
211 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1), 273 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1),
212 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)}; 274 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
213 CreateReadOnly(reads); 275 CreateReadOnly(reads);
214 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback()); 276 int result = stream_->ReadFrames(&frames_, cb_.callback());
215 ASSERT_EQ(ERR_IO_PENDING, result); 277 ASSERT_EQ(ERR_IO_PENDING, result);
216 EXPECT_EQ(OK, cb_.WaitForResult()); 278 EXPECT_EQ(OK, cb_.WaitForResult());
217 ASSERT_EQ(1U, frame_chunks_.size()); 279 ASSERT_EQ(1U, frames_.size());
218 ASSERT_TRUE(frame_chunks_[0]->header); 280 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
219 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
220 } 281 }
221 282
222 // An extended header should also return ERR_IO_PENDING if it is not completely 283 // An extended header should also return ERR_IO_PENDING if it is not completely
223 // received. 284 // received.
224 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) { 285 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) {
225 MockRead reads[] = { 286 MockRead reads[] = {
226 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1), 287 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1),
227 MockRead(SYNCHRONOUS, ERR_IO_PENDING)}; 288 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
228 CreateReadOnly(reads); 289 CreateReadOnly(reads);
229 EXPECT_EQ(ERR_IO_PENDING, 290 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
230 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
231 } 291 }
232 292
233 // A frame that does not arrive in a single read should arrive in chunks. 293 // A frame that does not arrive in a single read should be broken into separate
234 TEST_F(WebSocketBasicStreamSocketTest, LargeFrameFirstChunk) { 294 // frames.
235 MockRead reads[] = { 295 TEST_F(WebSocketBasicStreamSocketSingleReadTest, LargeFrameFirstChunk) {
236 MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize)}; 296 CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize));
237 CreateReadOnly(reads); 297 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
238 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); 298 ASSERT_EQ(1U, frames_.size());
239 ASSERT_EQ(1U, frame_chunks_.size()); 299 EXPECT_FALSE(frames_[0]->header.final);
240 ASSERT_TRUE(frame_chunks_[0]->header);
241 EXPECT_EQ(kLargeFrameDeclaredPayloadSize,
242 frame_chunks_[0]->header->payload_length);
243 EXPECT_TRUE(frame_chunks_[0]->header->final);
244 EXPECT_FALSE(frame_chunks_[0]->final_chunk);
245 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize, 300 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
246 static_cast<size_t>(frame_chunks_[0]->data->size())); 301 static_cast<size_t>(frames_[0]->header.payload_length));
247 } 302 }
248 303
249 // If only the header arrives, we should get a zero-byte chunk. 304 // If only the header of a data frame arrives, we should not receive a frame and
305 // be told to wait. WebSocketBasicStream does two reads in this case, as after
306 // the first read it has no frames to return.
250 TEST_F(WebSocketBasicStreamSocketTest, HeaderOnlyChunk) { 307 TEST_F(WebSocketBasicStreamSocketTest, HeaderOnlyChunk) {
251 MockRead reads[] = { 308 MockRead reads[] = {
252 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize)}; 309 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize),
310 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
253 CreateReadOnly(reads); 311 CreateReadOnly(reads);
254 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); 312 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
255 ASSERT_EQ(1U, frame_chunks_.size()); 313 ASSERT_EQ(0U, frames_.size());
256 EXPECT_FALSE(frame_chunks_[0]->final_chunk);
257 EXPECT_TRUE(frame_chunks_[0]->data.get() == NULL);
258 } 314 }
259 315
260 // The second and subsequent chunks of a frame have no header. 316 // If the header and the body of a data frame arrive seperately, we should only
261 TEST_F(WebSocketBasicStreamSocketTest, LargeFrameTwoChunks) { 317 // see one frame.
262 static const size_t kChunkSize = 16; 318 TEST_F(WebSocketBasicStreamSocketTest, HeaderBodySeparated) {
263 MockRead reads[] = { 319 MockRead reads[] = {
264 MockRead(ASYNC, kPartialLargeFrame, kChunkSize), 320 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize),
265 MockRead(ASYNC, kPartialLargeFrame + kChunkSize, kChunkSize)}; 321 MockRead(ASYNC,
322 kPartialLargeFrame + kLargeFrameHeaderSize,
323 kPartialLargeFrameSize - kLargeFrameHeaderSize)};
266 CreateReadOnly(reads); 324 CreateReadOnly(reads);
325 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
326 EXPECT_EQ(OK, cb_.WaitForResult());
327 ASSERT_EQ(1U, frames_.size());
328 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
329 frames_[0]->header.payload_length);
330 }
331
332 // If the header and body of a data frame arrive separately, the frame we see
333 // should have the opcode from the header (not Continuation).
334 TEST_F(WebSocketBasicStreamSocketTest, HeaderBodySeparatedOpCodeNotLost) {
335 MockRead reads[] = {
336 MockRead(ASYNC, kPartialLargeFrame, kLargeFrameHeaderSize),
337 MockRead(ASYNC,
338 kPartialLargeFrame + kLargeFrameHeaderSize,
339 kPartialLargeFrameSize - kLargeFrameHeaderSize)};
340 CreateReadOnly(reads);
341 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
342 EXPECT_EQ(OK, cb_.WaitForResult());
343 ASSERT_EQ(1U, frames_.size());
344 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
345 }
346
347 // Every frame has a header with a correct payload_length field.
348 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, LargeFrameTwoChunks) {
349 const size_t kChunkSize = 16;
350 CreateChunkedRead(ASYNC,
351 kPartialLargeFrame,
352 kPartialLargeFrameSize,
353 kChunkSize,
354 2,
355 LAST_FRAME_NOT_BIG);
267 TestCompletionCallback cb[2]; 356 TestCompletionCallback cb[2];
268 357
269 ASSERT_EQ(ERR_IO_PENDING, 358 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
270 stream_->ReadFrames(&frame_chunks_, cb[0].callback()));
271 EXPECT_EQ(OK, cb[0].WaitForResult()); 359 EXPECT_EQ(OK, cb[0].WaitForResult());
272 ASSERT_EQ(1U, frame_chunks_.size()); 360 ASSERT_EQ(1U, frames_.size());
273 ASSERT_TRUE(frame_chunks_[0]->header); 361 EXPECT_EQ(kChunkSize - kLargeFrameHeaderSize,
362 frames_[0]->header.payload_length);
274 363
275 frame_chunks_.clear(); 364 frames_.clear();
276 ASSERT_EQ(ERR_IO_PENDING, 365 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback()));
277 stream_->ReadFrames(&frame_chunks_, cb[1].callback()));
278 EXPECT_EQ(OK, cb[1].WaitForResult()); 366 EXPECT_EQ(OK, cb[1].WaitForResult());
279 ASSERT_EQ(1U, frame_chunks_.size()); 367 ASSERT_EQ(1U, frames_.size());
280 ASSERT_FALSE(frame_chunks_[0]->header); 368 EXPECT_EQ(kChunkSize, frames_[0]->header.payload_length);
281 } 369 }
282 370
283 // Only the final chunk of a frame has final_chunk set. 371 // Only the final frame of a fragmented message has |final| bit set.
284 TEST_F(WebSocketBasicStreamSocketTest, OnlyFinalChunkIsFinal) { 372 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OnlyFinalChunkIsFinal) {
285 static const size_t kFirstChunkSize = 4; 373 static const size_t kFirstChunkSize = 4;
286 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kFirstChunkSize), 374 CreateChunkedRead(ASYNC,
287 MockRead(ASYNC, 375 kSampleFrame,
288 kSampleFrame + kFirstChunkSize, 376 kSampleFrameSize,
289 kSampleFrameSize - kFirstChunkSize)}; 377 kFirstChunkSize,
290 CreateReadOnly(reads); 378 2,
379 LAST_FRAME_BIG);
291 TestCompletionCallback cb[2]; 380 TestCompletionCallback cb[2];
292 381
293 ASSERT_EQ(ERR_IO_PENDING, 382 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
294 stream_->ReadFrames(&frame_chunks_, cb[0].callback()));
295 EXPECT_EQ(OK, cb[0].WaitForResult()); 383 EXPECT_EQ(OK, cb[0].WaitForResult());
296 ASSERT_EQ(1U, frame_chunks_.size()); 384 ASSERT_EQ(1U, frames_.size());
297 ASSERT_FALSE(frame_chunks_[0]->final_chunk); 385 ASSERT_FALSE(frames_[0]->header.final);
298 386
299 frame_chunks_.clear(); 387 frames_.clear();
300 ASSERT_EQ(ERR_IO_PENDING, 388 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[1].callback()));
301 stream_->ReadFrames(&frame_chunks_, cb[1].callback()));
302 EXPECT_EQ(OK, cb[1].WaitForResult()); 389 EXPECT_EQ(OK, cb[1].WaitForResult());
303 ASSERT_EQ(1U, frame_chunks_.size()); 390 ASSERT_EQ(1U, frames_.size());
304 ASSERT_TRUE(frame_chunks_[0]->final_chunk); 391 ASSERT_TRUE(frames_[0]->header.final);
392 }
393
394 // All frames after the first have their opcode changed to Continuation.
395 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, ContinuationOpCodeUsed) {
396 const size_t kFirstChunkSize = 3;
397 const int kChunkCount = 3;
398 // The input data is one frame with opcode Text, which arrives in three
399 // separate chunks.
400 CreateChunkedRead(ASYNC,
401 kSampleFrame,
402 kSampleFrameSize,
403 kFirstChunkSize,
404 kChunkCount,
405 LAST_FRAME_BIG);
406 TestCompletionCallback cb[kChunkCount];
407
408 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[0].callback()));
409 EXPECT_EQ(OK, cb[0].WaitForResult());
410 ASSERT_EQ(1U, frames_.size());
411 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
412
413 // This test uses a loop to verify that the opcode for every frames generated
414 // after the first is converted to Continuation.
415 for (int i = 1; i < kChunkCount; ++i) {
416 frames_.clear();
417 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb[i].callback()));
418 EXPECT_EQ(OK, cb[i].WaitForResult());
419 ASSERT_EQ(1U, frames_.size());
420 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation,
421 frames_[0]->header.opcode);
422 }
305 } 423 }
306 424
307 // Multiple frames that arrive together should be parsed correctly. 425 // Multiple frames that arrive together should be parsed correctly.
308 TEST_F(WebSocketBasicStreamSocketTest, ThreeFramesTogether) { 426 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ThreeFramesTogether) {
309 MockRead reads[] = { 427 CreateRead(MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize));
310 MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize)};
311 CreateReadOnly(reads);
312 428
313 ASSERT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); 429 ASSERT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
314 ASSERT_EQ(3U, frame_chunks_.size()); 430 ASSERT_EQ(3U, frames_.size());
315 EXPECT_TRUE(frame_chunks_[0]->final_chunk); 431 EXPECT_TRUE(frames_[0]->header.final);
316 EXPECT_TRUE(frame_chunks_[1]->final_chunk); 432 EXPECT_TRUE(frames_[1]->header.final);
317 EXPECT_TRUE(frame_chunks_[2]->final_chunk); 433 EXPECT_TRUE(frames_[2]->header.final);
318 } 434 }
319 435
320 // ERR_CONNECTION_CLOSED must be returned on close. 436 // ERR_CONNECTION_CLOSED must be returned on close.
321 TEST_F(WebSocketBasicStreamSocketTest, SyncClose) { 437 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncClose) {
322 MockRead reads[] = {MockRead(SYNCHRONOUS, "", 0)}; 438 CreateRead(MockRead(SYNCHRONOUS, "", 0));
323 CreateReadOnly(reads);
324 439
325 EXPECT_EQ(ERR_CONNECTION_CLOSED, 440 EXPECT_EQ(ERR_CONNECTION_CLOSED,
326 stream_->ReadFrames(&frame_chunks_, cb_.callback())); 441 stream_->ReadFrames(&frames_, cb_.callback()));
327 } 442 }
328 443
329 TEST_F(WebSocketBasicStreamSocketTest, AsyncClose) { 444 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncClose) {
330 MockRead reads[] = {MockRead(ASYNC, "", 0)}; 445 CreateRead(MockRead(ASYNC, "", 0));
331 CreateReadOnly(reads);
332 446
333 ASSERT_EQ(ERR_IO_PENDING, 447 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
334 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
335 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); 448 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
336 } 449 }
337 450
338 // The result should be the same if the socket returns 451 // The result should be the same if the socket returns
339 // ERR_CONNECTION_CLOSED. This is not expected to happen on an established 452 // ERR_CONNECTION_CLOSED. This is not expected to happen on an established
340 // connection; a Read of size 0 is the expected behaviour. The key point of this 453 // connection; a Read of size 0 is the expected behaviour. The key point of this
341 // test is to confirm that ReadFrames() behaviour is identical in both cases. 454 // test is to confirm that ReadFrames() behaviour is identical in both cases.
342 TEST_F(WebSocketBasicStreamSocketTest, SyncCloseWithErr) { 455 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncCloseWithErr) {
343 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)}; 456 CreateRead(MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED));
344 CreateReadOnly(reads);
345 457
346 EXPECT_EQ(ERR_CONNECTION_CLOSED, 458 EXPECT_EQ(ERR_CONNECTION_CLOSED,
347 stream_->ReadFrames(&frame_chunks_, cb_.callback())); 459 stream_->ReadFrames(&frames_, cb_.callback()));
348 } 460 }
349 461
350 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseWithErr) { 462 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncCloseWithErr) {
351 MockRead reads[] = {MockRead(ASYNC, ERR_CONNECTION_CLOSED)}; 463 CreateRead(MockRead(ASYNC, ERR_CONNECTION_CLOSED));
352 CreateReadOnly(reads);
353 464
354 ASSERT_EQ(ERR_IO_PENDING, 465 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
355 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
356 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); 466 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
357 } 467 }
358 468
359 TEST_F(WebSocketBasicStreamSocketTest, SyncErrorsPassedThrough) { 469 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncErrorsPassedThrough) {
360 // ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that 470 // ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that
361 // WebSocketBasicStream gives no special handling to. 471 // WebSocketBasicStream gives no special handling to.
362 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES)}; 472 CreateRead(MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES));
363 CreateReadOnly(reads);
364 473
365 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, 474 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES,
366 stream_->ReadFrames(&frame_chunks_, cb_.callback())); 475 stream_->ReadFrames(&frames_, cb_.callback()));
367 } 476 }
368 477
369 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrorsPassedThrough) { 478 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncErrorsPassedThrough) {
370 MockRead reads[] = {MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES)}; 479 CreateRead(MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES));
371 CreateReadOnly(reads);
372 480
373 ASSERT_EQ(ERR_IO_PENDING, 481 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
374 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
375 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, cb_.WaitForResult()); 482 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, cb_.WaitForResult());
376 } 483 }
377 484
378 // If we get a frame followed by a close, we should receive them separately. 485 // If we get a frame followed by a close, we should receive them separately.
379 TEST_F(WebSocketBasicStreamSocketTest, CloseAfterFrame) { 486 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, CloseAfterFrame) {
380 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize), 487 // The chunk size equals the data size, so the second chunk is 0 size, closing
381 MockRead(SYNCHRONOUS, "", 0)}; 488 // the connection.
382 CreateReadOnly(reads); 489 CreateChunkedRead(SYNCHRONOUS,
490 kSampleFrame,
491 kSampleFrameSize,
492 kSampleFrameSize,
493 2,
494 LAST_FRAME_NOT_BIG);
383 495
384 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); 496 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
385 EXPECT_EQ(1U, frame_chunks_.size()); 497 EXPECT_EQ(1U, frames_.size());
386 frame_chunks_.clear(); 498 frames_.clear();
387 EXPECT_EQ(ERR_CONNECTION_CLOSED, 499 EXPECT_EQ(ERR_CONNECTION_CLOSED,
388 stream_->ReadFrames(&frame_chunks_, cb_.callback())); 500 stream_->ReadFrames(&frames_, cb_.callback()));
389 } 501 }
390 502
391 // Synchronous close after an async frame header is handled by a different code 503 // Synchronous close after an async frame header is handled by a different code
392 // path. 504 // path.
393 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) { 505 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) {
394 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U), 506 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
395 MockRead(SYNCHRONOUS, "", 0)}; 507 MockRead(SYNCHRONOUS, "", 0)};
396 CreateReadOnly(reads); 508 CreateReadOnly(reads);
397 509
398 ASSERT_EQ(ERR_IO_PENDING, 510 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
399 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
400 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); 511 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
401 } 512 }
402 513
403 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a 514 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a
404 // slightly different code path. 515 // slightly different code path.
405 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) { 516 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) {
406 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U), 517 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
407 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)}; 518 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
408 CreateReadOnly(reads); 519 CreateReadOnly(reads);
409 520
410 ASSERT_EQ(ERR_IO_PENDING, 521 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
411 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
412 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult()); 522 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
413 } 523 }
414 524
415 // If there was a frame read at the same time as the response headers (and the 525 // If there was a frame read at the same time as the response headers (and the
416 // handshake succeeded), then we should parse it. 526 // handshake succeeded), then we should parse it.
417 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) { 527 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) {
418 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize); 528 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize);
419 CreateNullStream(); 529 CreateNullStream();
420 530
421 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); 531 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
422 ASSERT_EQ(1U, frame_chunks_.size()); 532 ASSERT_EQ(1U, frames_.size());
423 ASSERT_TRUE(frame_chunks_[0]->data); 533 ASSERT_TRUE(frames_[0]->data);
424 EXPECT_EQ(6, frame_chunks_[0]->data->size()); 534 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
425 } 535 }
426 536
427 // Check that a frame whose header partially arrived at the end of the response 537 // Check that a frame whose header partially arrived at the end of the response
428 // headers works correctly. 538 // headers works correctly.
429 TEST_F(WebSocketBasicStreamSocketTest, PartialFrameHeaderInHttpResponse) { 539 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
540 PartialFrameHeaderInHttpResponse) {
430 SetHttpReadBuffer(kSampleFrame, 1); 541 SetHttpReadBuffer(kSampleFrame, 1);
431 MockRead reads[] = {MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)}; 542 CreateRead(MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1));
432 CreateReadOnly(reads);
433 543
434 ASSERT_EQ(ERR_IO_PENDING, 544 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
435 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
436 EXPECT_EQ(OK, cb_.WaitForResult()); 545 EXPECT_EQ(OK, cb_.WaitForResult());
437 ASSERT_EQ(1U, frame_chunks_.size()); 546 ASSERT_EQ(1U, frames_.size());
438 ASSERT_TRUE(frame_chunks_[0]->data); 547 ASSERT_TRUE(frames_[0]->data);
439 EXPECT_EQ(6, frame_chunks_[0]->data->size()); 548 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
440 ASSERT_TRUE(frame_chunks_[0]->header); 549 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
441 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText,
442 frame_chunks_[0]->header->opcode);
443 } 550 }
444 551
445 // Check that an invalid frame results in an error. 552 // Check that an invalid frame results in an error.
446 TEST_F(WebSocketBasicStreamSocketTest, SyncInvalidFrame) { 553 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncInvalidFrame) {
447 MockRead reads[] = {MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize)}; 554 CreateRead(MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize));
448 CreateReadOnly(reads);
449 555
450 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, 556 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
451 stream_->ReadFrames(&frame_chunks_, cb_.callback())); 557 stream_->ReadFrames(&frames_, cb_.callback()));
452 } 558 }
453 559
454 TEST_F(WebSocketBasicStreamSocketTest, AsyncInvalidFrame) { 560 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncInvalidFrame) {
455 MockRead reads[] = {MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize)}; 561 CreateRead(MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize));
456 CreateReadOnly(reads);
457 562
458 ASSERT_EQ(ERR_IO_PENDING, 563 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
459 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
460 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult()); 564 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
461 } 565 }
462 566
567 // A control frame without a FIN flag is invalid and should not be passed
568 // through to higher layers. RFC6455 5.5 "All control frames ... MUST NOT be
569 // fragmented."
570 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ControlFrameWithoutFin) {
571 CreateRead(
572 MockRead(SYNCHRONOUS, kPingFrameWithoutFin, kPingFrameWithoutFinSize));
573
574 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
575 stream_->ReadFrames(&frames_, cb_.callback()));
576 EXPECT_TRUE(frames_.empty());
577 }
578
579 // A control frame over 125 characters is invalid. RFC6455 5.5 "All control
580 // frames MUST have a payload length of 125 bytes or less". Since we use a
581 // 125-byte buffer to assemble fragmented control frames, we need to detect this
582 // error before attempting to assemble the fragments.
583 TEST_F(WebSocketBasicStreamSocketSingleReadTest, OverlongControlFrame) {
584 CreateRead(MockRead(SYNCHRONOUS, k126BytePong, k126BytePongSize));
585
586 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
587 stream_->ReadFrames(&frames_, cb_.callback()));
588 EXPECT_TRUE(frames_.empty());
589 }
590
591 // A control frame over 125 characters should still be rejected if it is split
592 // into multiple chunks.
593 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SplitOverlongControlFrame) {
594 const size_t kFirstChunkSize = 16;
595 CreateChunkedRead(SYNCHRONOUS,
596 k126BytePong,
597 k126BytePongSize,
598 kFirstChunkSize,
599 2,
600 LAST_FRAME_BIG);
601
602 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
603 stream_->ReadFrames(&frames_, cb_.callback()));
604 EXPECT_TRUE(frames_.empty());
605 }
606
607 TEST_F(WebSocketBasicStreamSocketChunkedReadTest,
608 AsyncSplitOverlongControlFrame) {
609 const size_t kFirstChunkSize = 16;
610 CreateChunkedRead(ASYNC,
611 k126BytePong,
612 k126BytePongSize,
613 kFirstChunkSize,
614 2,
615 LAST_FRAME_BIG);
616
617 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
618 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
619 // The caller should not call ReadFrames() again after receiving an error
620 // other than ERR_IO_PENDING.
621 EXPECT_TRUE(frames_.empty());
622 }
623
624 // In the synchronous case, ReadFrames assembles the whole control frame before
625 // returning.
626 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SyncControlFrameAssembly) {
627 const size_t kChunkSize = 3;
628 CreateChunkedRead(
629 SYNCHRONOUS, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
630
631 ASSERT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
632 ASSERT_EQ(1U, frames_.size());
633 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
634 }
635
636 // In the asynchronous case, the callback is not called until the control frame
637 // has been completely assembled.
638 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, AsyncControlFrameAssembly) {
639 const size_t kChunkSize = 3;
640 CreateChunkedRead(
641 ASYNC, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
642
643 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
644 ASSERT_EQ(OK, cb_.WaitForResult());
645 ASSERT_EQ(1U, frames_.size());
646 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
647 }
648
463 // Check that writing a frame all at once works. 649 // Check that writing a frame all at once works.
464 TEST_F(WebSocketBasicStreamSocketTest, WriteAtOnce) { 650 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteAtOnce) {
465 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)}; 651 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
466 CreateWriteOnly(writes); 652 CreateWriteOnly(writes);
467 frame_chunks_ = GenerateWriteFrame();
468 653
469 EXPECT_EQ(OK, stream_->WriteFrames(&frame_chunks_, cb_.callback())); 654 EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
470 } 655 }
471 656
472 // Check that completely async writing works. 657 // Check that completely async writing works.
473 TEST_F(WebSocketBasicStreamSocketTest, AsyncWriteAtOnce) { 658 TEST_F(WebSocketBasicStreamSocketWriteTest, AsyncWriteAtOnce) {
474 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)}; 659 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
475 CreateWriteOnly(writes); 660 CreateWriteOnly(writes);
476 frame_chunks_ = GenerateWriteFrame();
477 661
478 ASSERT_EQ(ERR_IO_PENDING, 662 ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
479 stream_->WriteFrames(&frame_chunks_, cb_.callback()));
480 EXPECT_EQ(OK, cb_.WaitForResult()); 663 EXPECT_EQ(OK, cb_.WaitForResult());
481 } 664 }
482 665
483 // Check that writing a frame to an extremely full kernel buffer (so that it 666 // Check that writing a frame to an extremely full kernel buffer (so that it
484 // ends up being sent in bits) works. The WriteFrames() callback should not be 667 // ends up being sent in bits) works. The WriteFrames() callback should not be
485 // called until all parts have been written. 668 // called until all parts have been written.
486 TEST_F(WebSocketBasicStreamSocketTest, WriteInBits) { 669 TEST_F(WebSocketBasicStreamSocketWriteTest, WriteInBits) {
487 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4), 670 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
488 MockWrite(ASYNC, kWriteFrame + 4, 4), 671 MockWrite(ASYNC, kWriteFrame + 4, 4),
489 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)}; 672 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
490 CreateWriteOnly(writes); 673 CreateWriteOnly(writes);
491 frame_chunks_ = GenerateWriteFrame();
492 674
493 ASSERT_EQ(ERR_IO_PENDING, 675 ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
494 stream_->WriteFrames(&frame_chunks_, cb_.callback()));
495 EXPECT_EQ(OK, cb_.WaitForResult()); 676 EXPECT_EQ(OK, cb_.WaitForResult());
496 } 677 }
497 678
498 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) { 679 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
499 extensions_ = "inflate-uuencode"; 680 extensions_ = "inflate-uuencode";
500 CreateNullStream(); 681 CreateNullStream();
501 682
502 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions()); 683 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
503 } 684 }
504 685
505 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) { 686 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
506 sub_protocol_ = "cyberchat"; 687 sub_protocol_ = "cyberchat";
507 CreateNullStream(); 688 CreateNullStream();
508 689
509 EXPECT_EQ("cyberchat", stream_->GetSubProtocol()); 690 EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
510 } 691 }
511 692
512 } // namespace 693 } // namespace
513 } // namespace net 694 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698