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

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: Fixes to debug printing. 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 55 // Generates a ScopedVector<WebSocketFrame> which will have a wire format
45 // matching kWriteFrame. 56 // matching kWriteFrame.
46 ScopedVector<WebSocketFrameChunk> GenerateWriteFrame() { 57 ScopedVector<WebSocketFrame> GenerateWriteFrame() {
yhirano 2013/09/13 10:03:17 Why do you use ScopedVector instead of scoptr_ptr?
Adam Rice 2013/09/13 14:09:53 I realised I was always calling it in the same way
47 scoped_ptr<WebSocketFrameChunk> chunk(new WebSocketFrameChunk); 58 scoped_ptr<WebSocketFrame> frame(
59 new WebSocketFrame(WebSocketFrameHeader::kOpCodeText));
48 const size_t payload_size = 60 const size_t payload_size =
49 kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize + 61 kWriteFrameSize - (WebSocketFrameHeader::kBaseHeaderSize +
50 WebSocketFrameHeader::kMaskingKeyLength); 62 WebSocketFrameHeader::kMaskingKeyLength);
51 chunk->data = new IOBufferWithSize(payload_size); 63 frame->data = new IOBufferWithSize(payload_size);
52 memcpy(chunk->data->data(), 64 memcpy(frame->data->data(),
53 kWriteFrame + kWriteFrameSize - payload_size, 65 kWriteFrame + kWriteFrameSize - payload_size,
54 payload_size); 66 payload_size);
55 chunk->final_chunk = true; 67 WebSocketFrameHeader& header = frame->header;
56 scoped_ptr<WebSocketFrameHeader> header( 68 header.final = true;
57 new WebSocketFrameHeader(WebSocketFrameHeader::kOpCodeText)); 69 header.masked = true;
58 header->final = true; 70 header.payload_length = payload_size;
59 header->masked = true; 71 ScopedVector<WebSocketFrame> frames;
60 header->payload_length = payload_size; 72 frames.push_back(frame.release());
61 chunk->header = header.Pass(); 73 return frames.Pass();
62 ScopedVector<WebSocketFrameChunk> chunks;
63 chunks.push_back(chunk.release());
64 return chunks.Pass();
65 } 74 }
66 75
67 // A masking key generator function which generates the identity mask, 76 // A masking key generator function which generates the identity mask,
68 // ie. "\0\0\0\0". 77 // ie. "\0\0\0\0".
69 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; } 78 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; }
70 79
71 // Base class for WebSocketBasicStream test fixtures. 80 // Base class for WebSocketBasicStream test fixtures.
72 class WebSocketBasicStreamTest : public ::testing::Test { 81 class WebSocketBasicStreamTest : public ::testing::Test {
73 protected: 82 protected:
74 scoped_ptr<WebSocketBasicStream> stream_; 83 scoped_ptr<WebSocketBasicStream> stream_;
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
136 CreateStream(NULL, 0, writes, N); 145 CreateStream(NULL, 0, writes, N);
137 } 146 }
138 147
139 void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); } 148 void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); }
140 149
141 scoped_ptr<SocketDataProvider> socket_data_; 150 scoped_ptr<SocketDataProvider> socket_data_;
142 MockClientSocketFactory factory_; 151 MockClientSocketFactory factory_;
143 ClientSocketPoolHistograms histograms_; 152 ClientSocketPoolHistograms histograms_;
144 MockTransportClientSocketPool pool_; 153 MockTransportClientSocketPool pool_;
145 CapturingBoundNetLog(bound_net_log_); 154 CapturingBoundNetLog(bound_net_log_);
146 ScopedVector<WebSocketFrameChunk> frame_chunks_; 155 ScopedVector<WebSocketFrame> frames_;
147 TestCompletionCallback cb_; 156 TestCompletionCallback cb_;
148 scoped_refptr<GrowableIOBuffer> http_read_buffer_; 157 scoped_refptr<GrowableIOBuffer> http_read_buffer_;
149 std::string sub_protocol_; 158 std::string sub_protocol_;
150 std::string extensions_; 159 std::string extensions_;
151 }; 160 };
152 161
162 // A test fixture for the common case of tests that only perform a single read.
163 class WebSocketBasicStreamSocketSingleReadTest
164 : public WebSocketBasicStreamSocketTest {
165 protected:
166 void CreateRead(const MockRead& read) {
167 reads_[0] = read;
168 CreateStream(reads_, 1U, NULL, 0);
169 }
170
171 MockRead reads_[1];
172 };
173
174 // A test fixture for tests that perform chunked reads.
175 class WebSocketBasicStreamSocketChunkedReadTest
176 : public WebSocketBasicStreamSocketTest {
177 protected:
178 // Specify the behaviour if there aren't enough chunks to use all the data. If
179 // LAST_FRAME_BIG is specified, the the rest of the data will be
180 // put in the last chunk. If LAST_FRAME_NOT_BIG is specified, then the last
181 // frame will be no bigger than the rest of the frames (but it can be smaller,
182 // if not enough data remains).
183 enum LastFrameBehaviour {
184 LAST_FRAME_BIG,
185 LAST_FRAME_NOT_BIG
186 };
187
188 // Prepares a read from |data| of |data_size|, split into |number_of_chunks|,
189 // each of |chunk_size| (except that the last chunk may be larger or
190 // smaller). All reads must be either SYNCHRONOUS or ASYNC (not a mixture),
191 // and errors cannot be simulated. Once data is exhausted, further reads will
192 // return 0 (ie. connection closed).
193 void CreateChunkedRead(IoMode mode,
194 const char data[],
195 size_t data_size,
196 int chunk_size,
197 int number_of_chunks,
198 LastFrameBehaviour last_frame_behaviour) {
199 reads_.reset(new MockRead[number_of_chunks]);
200 const char* start = data;
201 for (int i = 0; i < number_of_chunks; ++i) {
202 int len = chunk_size;
203 if (last_frame_behaviour == LAST_FRAME_BIG && i == number_of_chunks - 1 &&
204 data + data_size - start > static_cast<size_t>(len)) {
yhirano 2013/09/13 10:03:17 Is the last condition necessary?
Adam Rice 2013/09/13 14:09:53 No. I have cleaned up this condition a bit.
205 len = static_cast<int>(data + data_size - start);
206 } else if (data + data_size - start < static_cast<size_t>(len)) {
207 len = static_cast<int>(data + data_size - start);
208 }
209 reads_[i] = MockRead(mode, start, len);
210 start += len;
211 }
212 CreateStream(reads_.get(), number_of_chunks, NULL, 0);
213 }
214
215 scoped_ptr<MockRead[]> reads_;
216 };
217
153 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) { 218 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
154 CreateNullStream(); 219 CreateNullStream();
155 } 220 }
156 221
157 TEST_F(WebSocketBasicStreamSocketTest, SyncReadWorks) { 222 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncReadWorks) {
158 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize)}; 223 CreateRead(MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize));
159 CreateReadOnly(reads); 224 int result = stream_->ReadFrames(&frames_, cb_.callback());
160 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
161 EXPECT_EQ(OK, result); 225 EXPECT_EQ(OK, result);
162 ASSERT_EQ(1U, frame_chunks_.size()); 226 ASSERT_EQ(1U, frames_.size());
163 ASSERT_TRUE(frame_chunks_[0]->header); 227 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
164 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length); 228 EXPECT_TRUE(frames_[0]->header.final);
165 EXPECT_TRUE(frame_chunks_[0]->header->final);
166 EXPECT_TRUE(frame_chunks_[0]->final_chunk);
167 } 229 }
168 230
169 TEST_F(WebSocketBasicStreamSocketTest, AsyncReadWorks) { 231 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncReadWorks) {
170 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kSampleFrameSize)}; 232 CreateRead(MockRead(ASYNC, kSampleFrame, kSampleFrameSize));
171 CreateReadOnly(reads); 233 int result = stream_->ReadFrames(&frames_, cb_.callback());
172 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
173 ASSERT_EQ(ERR_IO_PENDING, result); 234 ASSERT_EQ(ERR_IO_PENDING, result);
174 EXPECT_EQ(OK, cb_.WaitForResult()); 235 EXPECT_EQ(OK, cb_.WaitForResult());
175 ASSERT_EQ(1U, frame_chunks_.size()); 236 ASSERT_EQ(1U, frames_.size());
176 ASSERT_TRUE(frame_chunks_[0]->header); 237 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 238 // Don't repeat all the tests from SyncReadWorks; just enough to be sure the
179 // frame was really read. 239 // frame was really read.
180 } 240 }
181 241
182 // ReadFrames will not return a frame whose header has not been wholly received. 242 // ReadFrames will not return a frame whose header has not been wholly received.
183 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSync) { 243 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedSync) {
184 MockRead reads[] = { 244 CreateChunkedRead(
185 MockRead(SYNCHRONOUS, kSampleFrame, 1), 245 SYNCHRONOUS, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
186 MockRead(SYNCHRONOUS, kSampleFrame + 1, kSampleFrameSize - 1)}; 246 int result = stream_->ReadFrames(&frames_, cb_.callback());
187 CreateReadOnly(reads);
188 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
189 ASSERT_EQ(OK, result); 247 ASSERT_EQ(OK, result);
190 ASSERT_EQ(1U, frame_chunks_.size()); 248 ASSERT_EQ(1U, frames_.size());
191 ASSERT_TRUE(frame_chunks_[0]->header); 249 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 } 250 }
194 251
195 // The same behaviour applies to asynchronous reads. 252 // The same behaviour applies to asynchronous reads.
196 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedAsync) { 253 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, HeaderFragmentedAsync) {
197 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1), 254 CreateChunkedRead(
198 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)}; 255 ASYNC, kSampleFrame, kSampleFrameSize, 1, 2, LAST_FRAME_BIG);
199 CreateReadOnly(reads); 256 int result = stream_->ReadFrames(&frames_, cb_.callback());
200 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
201 ASSERT_EQ(ERR_IO_PENDING, result); 257 ASSERT_EQ(ERR_IO_PENDING, result);
202 EXPECT_EQ(OK, cb_.WaitForResult()); 258 EXPECT_EQ(OK, cb_.WaitForResult());
203 ASSERT_EQ(1U, frame_chunks_.size()); 259 ASSERT_EQ(1U, frames_.size());
204 ASSERT_TRUE(frame_chunks_[0]->header); 260 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 } 261 }
207 262
208 // If it receives an incomplete header in a synchronous call, then has to wait 263 // 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. 264 // for the rest of the frame, ReadFrames will return ERR_IO_PENDING.
210 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) { 265 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) {
211 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1), 266 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1),
212 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)}; 267 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
213 CreateReadOnly(reads); 268 CreateReadOnly(reads);
214 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback()); 269 int result = stream_->ReadFrames(&frames_, cb_.callback());
215 ASSERT_EQ(ERR_IO_PENDING, result); 270 ASSERT_EQ(ERR_IO_PENDING, result);
216 EXPECT_EQ(OK, cb_.WaitForResult()); 271 EXPECT_EQ(OK, cb_.WaitForResult());
217 ASSERT_EQ(1U, frame_chunks_.size()); 272 ASSERT_EQ(1U, frames_.size());
218 ASSERT_TRUE(frame_chunks_[0]->header); 273 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 } 274 }
221 275
222 // An extended header should also return ERR_IO_PENDING if it is not completely 276 // An extended header should also return ERR_IO_PENDING if it is not completely
223 // received. 277 // received.
224 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) { 278 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) {
225 MockRead reads[] = { 279 MockRead reads[] = {
226 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1), 280 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1),
227 MockRead(SYNCHRONOUS, ERR_IO_PENDING)}; 281 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
228 CreateReadOnly(reads); 282 CreateReadOnly(reads);
229 EXPECT_EQ(ERR_IO_PENDING, 283 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
230 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
231 } 284 }
232 285
233 // A frame that does not arrive in a single read should arrive in chunks. 286 // A frame that does not arrive in a single read should be broken into separate
234 TEST_F(WebSocketBasicStreamSocketTest, LargeFrameFirstChunk) { 287 // frames.
235 MockRead reads[] = { 288 TEST_F(WebSocketBasicStreamSocketSingleReadTest, LargeFrameFirstChunk) {
236 MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize)}; 289 CreateRead(MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize));
237 CreateReadOnly(reads); 290 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
238 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); 291 ASSERT_EQ(1U, frames_.size());
239 ASSERT_EQ(1U, frame_chunks_.size()); 292 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, 293 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
246 static_cast<size_t>(frame_chunks_[0]->data->size())); 294 static_cast<size_t>(frames_[0]->header.payload_length));
247 } 295 }
248 296
249 // If only the header arrives, we should get a zero-byte chunk. 297 // If only the header of a data frame arrives, we should not receive a frame and
298 // be told to wait. WebSocketBasicStream does two reads in this case, as after
299 // the first read it has no frames to return.
250 TEST_F(WebSocketBasicStreamSocketTest, HeaderOnlyChunk) { 300 TEST_F(WebSocketBasicStreamSocketTest, HeaderOnlyChunk) {
251 MockRead reads[] = { 301 MockRead reads[] = {
252 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize)}; 302 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize),
303 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
253 CreateReadOnly(reads); 304 CreateReadOnly(reads);
254 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); 305 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
255 ASSERT_EQ(1U, frame_chunks_.size()); 306 ASSERT_EQ(0U, frames_.size());
256 EXPECT_FALSE(frame_chunks_[0]->final_chunk);
257 EXPECT_TRUE(frame_chunks_[0]->data.get() == NULL);
258 } 307 }
259 308
260 // The second and subsequent chunks of a frame have no header. 309 // If the header and the body of a data frame arrive seperately, we should only
261 TEST_F(WebSocketBasicStreamSocketTest, LargeFrameTwoChunks) { 310 // see one frame.
262 static const size_t kChunkSize = 16; 311 TEST_F(WebSocketBasicStreamSocketTest, HeaderBodySeparated) {
263 MockRead reads[] = { 312 MockRead reads[] = {
264 MockRead(ASYNC, kPartialLargeFrame, kChunkSize), 313 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize),
265 MockRead(ASYNC, kPartialLargeFrame + kChunkSize, kChunkSize)}; 314 MockRead(ASYNC,
315 kPartialLargeFrame + kLargeFrameHeaderSize,
316 kPartialLargeFrameSize - kLargeFrameHeaderSize)};
266 CreateReadOnly(reads); 317 CreateReadOnly(reads);
318 EXPECT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
319 EXPECT_EQ(OK, cb_.WaitForResult());
320 ASSERT_EQ(1U, frames_.size());
321 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
322 frames_[0]->header.payload_length);
323 }
324
325 // Every frame has a header with a correct payload_length field.
326 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, LargeFrameTwoChunks) {
327 const size_t kChunkSize = 16;
328 CreateChunkedRead(ASYNC,
329 kPartialLargeFrame,
330 kPartialLargeFrameSize,
331 kChunkSize,
332 2,
333 LAST_FRAME_NOT_BIG);
267 TestCompletionCallback cb[2]; 334 TestCompletionCallback cb[2];
268 335
269 ASSERT_EQ(ERR_IO_PENDING, 336 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()); 337 EXPECT_EQ(OK, cb[0].WaitForResult());
272 ASSERT_EQ(1U, frame_chunks_.size()); 338 ASSERT_EQ(1U, frames_.size());
273 ASSERT_TRUE(frame_chunks_[0]->header); 339 EXPECT_EQ(kChunkSize - kLargeFrameHeaderSize,
340 frames_[0]->header.payload_length);
274 341
275 frame_chunks_.clear(); 342 frames_.clear();
276 ASSERT_EQ(ERR_IO_PENDING, 343 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()); 344 EXPECT_EQ(OK, cb[1].WaitForResult());
279 ASSERT_EQ(1U, frame_chunks_.size()); 345 ASSERT_EQ(1U, frames_.size());
280 ASSERT_FALSE(frame_chunks_[0]->header); 346 EXPECT_EQ(kChunkSize, frames_[0]->header.payload_length);
281 } 347 }
282 348
283 // Only the final chunk of a frame has final_chunk set. 349 // Only the final frame of a fragmented message has |final| bit set.
284 TEST_F(WebSocketBasicStreamSocketTest, OnlyFinalChunkIsFinal) { 350 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, OnlyFinalChunkIsFinal) {
285 static const size_t kFirstChunkSize = 4; 351 static const size_t kFirstChunkSize = 4;
286 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kFirstChunkSize), 352 CreateChunkedRead(ASYNC,
287 MockRead(ASYNC, 353 kSampleFrame,
288 kSampleFrame + kFirstChunkSize, 354 kSampleFrameSize,
289 kSampleFrameSize - kFirstChunkSize)}; 355 kFirstChunkSize,
290 CreateReadOnly(reads); 356 2,
357 LAST_FRAME_BIG);
291 TestCompletionCallback cb[2]; 358 TestCompletionCallback cb[2];
292 359
293 ASSERT_EQ(ERR_IO_PENDING, 360 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()); 361 EXPECT_EQ(OK, cb[0].WaitForResult());
296 ASSERT_EQ(1U, frame_chunks_.size()); 362 ASSERT_EQ(1U, frames_.size());
297 ASSERT_FALSE(frame_chunks_[0]->final_chunk); 363 ASSERT_FALSE(frames_[0]->header.final);
298 364
299 frame_chunks_.clear(); 365 frames_.clear();
300 ASSERT_EQ(ERR_IO_PENDING, 366 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()); 367 EXPECT_EQ(OK, cb[1].WaitForResult());
303 ASSERT_EQ(1U, frame_chunks_.size()); 368 ASSERT_EQ(1U, frames_.size());
304 ASSERT_TRUE(frame_chunks_[0]->final_chunk); 369 ASSERT_TRUE(frames_[0]->header.final);
305 } 370 }
306 371
307 // Multiple frames that arrive together should be parsed correctly. 372 // Multiple frames that arrive together should be parsed correctly.
308 TEST_F(WebSocketBasicStreamSocketTest, ThreeFramesTogether) { 373 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ThreeFramesTogether) {
309 MockRead reads[] = { 374 CreateRead(MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize));
310 MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize)};
311 CreateReadOnly(reads);
312 375
313 ASSERT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); 376 ASSERT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
314 ASSERT_EQ(3U, frame_chunks_.size()); 377 ASSERT_EQ(3U, frames_.size());
315 EXPECT_TRUE(frame_chunks_[0]->final_chunk); 378 EXPECT_TRUE(frames_[0]->header.final);
316 EXPECT_TRUE(frame_chunks_[1]->final_chunk); 379 EXPECT_TRUE(frames_[1]->header.final);
317 EXPECT_TRUE(frame_chunks_[2]->final_chunk); 380 EXPECT_TRUE(frames_[2]->header.final);
318 } 381 }
319 382
320 // ERR_CONNECTION_CLOSED must be returned on close. 383 // ERR_CONNECTION_CLOSED must be returned on close.
321 TEST_F(WebSocketBasicStreamSocketTest, SyncClose) { 384 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncClose) {
322 MockRead reads[] = {MockRead(SYNCHRONOUS, "", 0)}; 385 CreateRead(MockRead(SYNCHRONOUS, "", 0));
323 CreateReadOnly(reads);
324 386
325 EXPECT_EQ(ERR_CONNECTION_CLOSED, 387 EXPECT_EQ(ERR_CONNECTION_CLOSED,
326 stream_->ReadFrames(&frame_chunks_, cb_.callback())); 388 stream_->ReadFrames(&frames_, cb_.callback()));
327 } 389 }
328 390
329 TEST_F(WebSocketBasicStreamSocketTest, AsyncClose) { 391 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncClose) {
330 MockRead reads[] = {MockRead(ASYNC, "", 0)}; 392 CreateRead(MockRead(ASYNC, "", 0));
331 CreateReadOnly(reads);
332 393
333 ASSERT_EQ(ERR_IO_PENDING, 394 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()); 395 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
336 } 396 }
337 397
338 // The result should be the same if the socket returns 398 // The result should be the same if the socket returns
339 // ERR_CONNECTION_CLOSED. This is not expected to happen on an established 399 // 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 400 // 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. 401 // test is to confirm that ReadFrames() behaviour is identical in both cases.
342 TEST_F(WebSocketBasicStreamSocketTest, SyncCloseWithErr) { 402 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncCloseWithErr) {
343 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)}; 403 CreateRead(MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED));
344 CreateReadOnly(reads);
345 404
346 EXPECT_EQ(ERR_CONNECTION_CLOSED, 405 EXPECT_EQ(ERR_CONNECTION_CLOSED,
347 stream_->ReadFrames(&frame_chunks_, cb_.callback())); 406 stream_->ReadFrames(&frames_, cb_.callback()));
348 } 407 }
349 408
350 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseWithErr) { 409 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncCloseWithErr) {
351 MockRead reads[] = {MockRead(ASYNC, ERR_CONNECTION_CLOSED)}; 410 CreateRead(MockRead(ASYNC, ERR_CONNECTION_CLOSED));
352 CreateReadOnly(reads);
353 411
354 ASSERT_EQ(ERR_IO_PENDING, 412 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()); 413 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
357 } 414 }
358 415
359 TEST_F(WebSocketBasicStreamSocketTest, SyncErrorsPassedThrough) { 416 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncErrorsPassedThrough) {
360 // ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that 417 // ERR_INSUFFICIENT_RESOURCES here represents an arbitrary error that
361 // WebSocketBasicStream gives no special handling to. 418 // WebSocketBasicStream gives no special handling to.
362 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES)}; 419 CreateRead(MockRead(SYNCHRONOUS, ERR_INSUFFICIENT_RESOURCES));
363 CreateReadOnly(reads);
364 420
365 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, 421 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES,
366 stream_->ReadFrames(&frame_chunks_, cb_.callback())); 422 stream_->ReadFrames(&frames_, cb_.callback()));
367 } 423 }
368 424
369 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrorsPassedThrough) { 425 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncErrorsPassedThrough) {
370 MockRead reads[] = {MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES)}; 426 CreateRead(MockRead(ASYNC, ERR_INSUFFICIENT_RESOURCES));
371 CreateReadOnly(reads);
372 427
373 ASSERT_EQ(ERR_IO_PENDING, 428 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()); 429 EXPECT_EQ(ERR_INSUFFICIENT_RESOURCES, cb_.WaitForResult());
376 } 430 }
377 431
378 // If we get a frame followed by a close, we should receive them separately. 432 // If we get a frame followed by a close, we should receive them separately.
379 TEST_F(WebSocketBasicStreamSocketTest, CloseAfterFrame) { 433 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, CloseAfterFrame) {
380 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize), 434 // The chunk size equals the data size, so the second chunk is 0 size, closing
381 MockRead(SYNCHRONOUS, "", 0)}; 435 // the connection.
382 CreateReadOnly(reads); 436 CreateChunkedRead(SYNCHRONOUS,
437 kSampleFrame,
438 kSampleFrameSize,
439 kSampleFrameSize,
440 2,
441 LAST_FRAME_NOT_BIG);
383 442
384 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); 443 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
385 EXPECT_EQ(1U, frame_chunks_.size()); 444 EXPECT_EQ(1U, frames_.size());
386 frame_chunks_.clear(); 445 frames_.clear();
387 EXPECT_EQ(ERR_CONNECTION_CLOSED, 446 EXPECT_EQ(ERR_CONNECTION_CLOSED,
388 stream_->ReadFrames(&frame_chunks_, cb_.callback())); 447 stream_->ReadFrames(&frames_, cb_.callback()));
389 } 448 }
390 449
391 // Synchronous close after an async frame header is handled by a different code 450 // Synchronous close after an async frame header is handled by a different code
392 // path. 451 // path.
393 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) { 452 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) {
394 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U), 453 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
395 MockRead(SYNCHRONOUS, "", 0)}; 454 MockRead(SYNCHRONOUS, "", 0)};
396 CreateReadOnly(reads); 455 CreateReadOnly(reads);
397 456
398 ASSERT_EQ(ERR_IO_PENDING, 457 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()); 458 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
401 } 459 }
402 460
403 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a 461 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a
404 // slightly different code path. 462 // slightly different code path.
405 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) { 463 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) {
406 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U), 464 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
407 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)}; 465 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
408 CreateReadOnly(reads); 466 CreateReadOnly(reads);
409 467
410 ASSERT_EQ(ERR_IO_PENDING, 468 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()); 469 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
413 } 470 }
414 471
415 // If there was a frame read at the same time as the response headers (and the 472 // If there was a frame read at the same time as the response headers (and the
416 // handshake succeeded), then we should parse it. 473 // handshake succeeded), then we should parse it.
417 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) { 474 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) {
418 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize); 475 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize);
419 CreateNullStream(); 476 CreateNullStream();
420 477
421 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback())); 478 EXPECT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
422 ASSERT_EQ(1U, frame_chunks_.size()); 479 ASSERT_EQ(1U, frames_.size());
423 ASSERT_TRUE(frame_chunks_[0]->data); 480 ASSERT_TRUE(frames_[0]->data);
424 EXPECT_EQ(6, frame_chunks_[0]->data->size()); 481 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
425 } 482 }
426 483
427 // Check that a frame whose header partially arrived at the end of the response 484 // Check that a frame whose header partially arrived at the end of the response
428 // headers works correctly. 485 // headers works correctly.
429 TEST_F(WebSocketBasicStreamSocketTest, PartialFrameHeaderInHttpResponse) { 486 TEST_F(WebSocketBasicStreamSocketSingleReadTest,
487 PartialFrameHeaderInHttpResponse) {
430 SetHttpReadBuffer(kSampleFrame, 1); 488 SetHttpReadBuffer(kSampleFrame, 1);
431 MockRead reads[] = {MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)}; 489 CreateRead(MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1));
432 CreateReadOnly(reads);
433 490
434 ASSERT_EQ(ERR_IO_PENDING, 491 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
435 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
436 EXPECT_EQ(OK, cb_.WaitForResult()); 492 EXPECT_EQ(OK, cb_.WaitForResult());
437 ASSERT_EQ(1U, frame_chunks_.size()); 493 ASSERT_EQ(1U, frames_.size());
438 ASSERT_TRUE(frame_chunks_[0]->data); 494 ASSERT_TRUE(frames_[0]->data);
439 EXPECT_EQ(6, frame_chunks_[0]->data->size()); 495 EXPECT_EQ(GG_UINT64_C(6), frames_[0]->header.payload_length);
440 ASSERT_TRUE(frame_chunks_[0]->header); 496 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_[0]->header.opcode);
441 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText,
442 frame_chunks_[0]->header->opcode);
443 } 497 }
444 498
445 // Check that an invalid frame results in an error. 499 // Check that an invalid frame results in an error.
446 TEST_F(WebSocketBasicStreamSocketTest, SyncInvalidFrame) { 500 TEST_F(WebSocketBasicStreamSocketSingleReadTest, SyncInvalidFrame) {
447 MockRead reads[] = {MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize)}; 501 CreateRead(MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize));
448 CreateReadOnly(reads);
449 502
450 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, 503 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
451 stream_->ReadFrames(&frame_chunks_, cb_.callback())); 504 stream_->ReadFrames(&frames_, cb_.callback()));
452 } 505 }
453 506
454 TEST_F(WebSocketBasicStreamSocketTest, AsyncInvalidFrame) { 507 TEST_F(WebSocketBasicStreamSocketSingleReadTest, AsyncInvalidFrame) {
455 MockRead reads[] = {MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize)}; 508 CreateRead(MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize));
456 CreateReadOnly(reads);
457 509
458 ASSERT_EQ(ERR_IO_PENDING, 510 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()); 511 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
461 } 512 }
462 513
514 // A control frame without a FIN flag is invalid and should not be passed
515 // through to higher layers. RFC6455 5.5 "All control frames ... MUST NOT be
516 // fragmented."
517 TEST_F(WebSocketBasicStreamSocketSingleReadTest, ControlFrameWithoutFin) {
518 CreateRead(
519 MockRead(SYNCHRONOUS, kPingFrameWithoutFin, kPingFrameWithoutFinSize));
520
521 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR,
522 stream_->ReadFrames(&frames_, cb_.callback()));
523 EXPECT_TRUE(frames_.empty());
524 }
525
526 // A control frame over 125 characters is invalid. RFC6455 5.5 "All control
527 // frames MUST have a payload length of 125 bytes or less". Since we use a
528 // 125-byte buffer to assemble fragmented control frames, we need to detect this
529 // error before attempting to assemble the fragments.
530 TEST_F(WebSocketBasicStreamSocketSingleReadTest, OverlongControlFrame) {
531 CreateRead(MockRead(SYNCHRONOUS, k126BytePong, k126BytePongSize));
532
533 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
534 stream_->ReadFrames(&frames_, cb_.callback()));
535 EXPECT_TRUE(frames_.empty());
536 }
537
538 // A control frame over 125 characters should still be rejected if it is split
539 // into multiple chunks.
540 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SplitOverlongControlFrame) {
541 const size_t kFirstChunkSize = 16;
542 CreateChunkedRead(SYNCHRONOUS,
543 k126BytePong,
544 k126BytePongSize,
545 kFirstChunkSize,
546 2,
547 LAST_FRAME_BIG);
548
549 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
550 stream_->ReadFrames(&frames_, cb_.callback()));
551 EXPECT_TRUE(frames_.empty());
552 }
553
554 TEST_F(WebSocketBasicStreamSocketChunkedReadTest,
555 AsyncSplitOverlongControlFrame) {
556 const size_t kFirstChunkSize = 16;
557 CreateChunkedRead(ASYNC,
558 k126BytePong,
559 k126BytePongSize,
560 kFirstChunkSize,
561 2,
562 LAST_FRAME_BIG);
563
564 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
565 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
566 // The caller should not call ReadFrames() again after receiving an error
567 // other than ERR_IO_PENDING.
568 EXPECT_TRUE(frames_.empty());
569 }
570
571 // In the synchronous case, ReadFrames assembles the whole control frame before
572 // returning.
573 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, SyncControlFrameAssembly) {
574 const size_t kChunkSize = 3;
575 CreateChunkedRead(
576 SYNCHRONOUS, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
577
578 ASSERT_EQ(OK, stream_->ReadFrames(&frames_, cb_.callback()));
579 ASSERT_EQ(1U, frames_.size());
580 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
581 }
582
583 // In the asynchronous case, the callback is not called until the control frame
584 // has been completely assembled.
585 TEST_F(WebSocketBasicStreamSocketChunkedReadTest, AsyncControlFrameAssembly) {
586 const size_t kChunkSize = 3;
587 CreateChunkedRead(
588 ASYNC, kCloseFrame, kCloseFrameSize, kChunkSize, 3, LAST_FRAME_BIG);
589
590 ASSERT_EQ(ERR_IO_PENDING, stream_->ReadFrames(&frames_, cb_.callback()));
591 ASSERT_EQ(OK, cb_.WaitForResult());
592 ASSERT_EQ(1U, frames_.size());
593 EXPECT_EQ(WebSocketFrameHeader::kOpCodeClose, frames_[0]->header.opcode);
594 }
595
463 // Check that writing a frame all at once works. 596 // Check that writing a frame all at once works.
464 TEST_F(WebSocketBasicStreamSocketTest, WriteAtOnce) { 597 TEST_F(WebSocketBasicStreamSocketTest, WriteAtOnce) {
465 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)}; 598 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
466 CreateWriteOnly(writes); 599 CreateWriteOnly(writes);
467 frame_chunks_ = GenerateWriteFrame(); 600 frames_ = GenerateWriteFrame();
468 601
469 EXPECT_EQ(OK, stream_->WriteFrames(&frame_chunks_, cb_.callback())); 602 EXPECT_EQ(OK, stream_->WriteFrames(&frames_, cb_.callback()));
470 } 603 }
471 604
472 // Check that completely async writing works. 605 // Check that completely async writing works.
473 TEST_F(WebSocketBasicStreamSocketTest, AsyncWriteAtOnce) { 606 TEST_F(WebSocketBasicStreamSocketTest, AsyncWriteAtOnce) {
474 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)}; 607 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
475 CreateWriteOnly(writes); 608 CreateWriteOnly(writes);
476 frame_chunks_ = GenerateWriteFrame(); 609 frames_ = GenerateWriteFrame();
477 610
478 ASSERT_EQ(ERR_IO_PENDING, 611 ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
479 stream_->WriteFrames(&frame_chunks_, cb_.callback()));
480 EXPECT_EQ(OK, cb_.WaitForResult()); 612 EXPECT_EQ(OK, cb_.WaitForResult());
481 } 613 }
482 614
483 // Check that writing a frame to an extremely full kernel buffer (so that it 615 // 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 616 // ends up being sent in bits) works. The WriteFrames() callback should not be
485 // called until all parts have been written. 617 // called until all parts have been written.
486 TEST_F(WebSocketBasicStreamSocketTest, WriteInBits) { 618 TEST_F(WebSocketBasicStreamSocketTest, WriteInBits) {
487 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4), 619 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
488 MockWrite(ASYNC, kWriteFrame + 4, 4), 620 MockWrite(ASYNC, kWriteFrame + 4, 4),
489 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)}; 621 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
490 CreateWriteOnly(writes); 622 CreateWriteOnly(writes);
491 frame_chunks_ = GenerateWriteFrame(); 623 frames_ = GenerateWriteFrame();
492 624
493 ASSERT_EQ(ERR_IO_PENDING, 625 ASSERT_EQ(ERR_IO_PENDING, stream_->WriteFrames(&frames_, cb_.callback()));
494 stream_->WriteFrames(&frame_chunks_, cb_.callback()));
495 EXPECT_EQ(OK, cb_.WaitForResult()); 626 EXPECT_EQ(OK, cb_.WaitForResult());
496 } 627 }
497 628
498 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) { 629 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
499 extensions_ = "inflate-uuencode"; 630 extensions_ = "inflate-uuencode";
500 CreateNullStream(); 631 CreateNullStream();
501 632
502 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions()); 633 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
503 } 634 }
504 635
505 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) { 636 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
506 sub_protocol_ = "cyberchat"; 637 sub_protocol_ = "cyberchat";
507 CreateNullStream(); 638 CreateNullStream();
508 639
509 EXPECT_EQ("cyberchat", stream_->GetSubProtocol()); 640 EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
510 } 641 }
511 642
512 } // namespace 643 } // namespace
513 } // namespace net 644 } // namespace net
yhirano 2013/09/13 10:03:17 It's good to have a test that checks if the opcode
Adam Rice 2013/09/13 14:09:53 Added test "ContinuationOpCodeUsed".
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698