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

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

Issue 18792002: WebSocketBasicStream framing logic (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Add includes and rename "data" variable Created 7 years, 4 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
(Empty)
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 "base/basictypes.h"
12 #include "base/port.h"
13 #include "net/base/capturing_net_log.h"
14 #include "net/base/test_completion_callback.h"
15 #include "net/socket/socket_test_util.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace net {
19 namespace {
20
21 // TODO(ricea): Add tests for
22 // - Empty frames (data & control)
23 // - Non-NULL masking key
24 // - A frame larger than kReadAtTime
25
26 const char kSampleFrame[] = "\x81\x06Sample";
27 const size_t kSampleFrameSize = arraysize(kSampleFrame) - 1;
28 const char kPartialLargeFrame[] =
29 "\x81\x7F\x00\x00\x00\x00\x7F\xFF\xFF\xFF"
30 "chromiunum ad pasco per loca insanis pullum manducat frumenti";
31 const size_t kPartialLargeFrameSize = arraysize(kPartialLargeFrame) - 1;
32 const size_t kLargeFrameHeaderSize = 10;
33 const size_t kLargeFrameDeclaredPayloadSize = 0x7FFFFFFF;
34 const char kMultipleFrames[] = "\x81\x01X\x81\x01Y\x81\x01Z";
35 const size_t kMultipleFramesSize = arraysize(kMultipleFrames) - 1;
36 // This frame encodes a payload length of 7 in two bytes, which is always
37 // invalid.
38 const char kInvalidFrame[] = "\x81\x7E\x00\x07Invalid";
39 const size_t kInvalidFrameSize = arraysize(kInvalidFrame) - 1;
40 const char kWriteFrame[] = "\x81\x85\x00\x00\x00\x00Write";
41 const size_t kWriteFrameSize = arraysize(kWriteFrame) - 1;
42 const WebSocketMaskingKey kNulMaskingKey = {{'\0', '\0', '\0', '\0'}};
43
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,
68 // ie. "\0\0\0\0".
69 WebSocketMaskingKey GenerateNulMaskingKey() { return kNulMaskingKey; }
70
71 // Base class for WebSocketBasicStream test fixtures.
72 class WebSocketBasicStreamTest : public ::testing::Test {
73 protected:
74 scoped_ptr<WebSocketBasicStream> stream_;
75 CapturingNetLog net_log_;
76 };
77
78 // A fixture for tests which only perform normal socket operations.
79 class WebSocketBasicStreamSocketTest : public WebSocketBasicStreamTest {
80 protected:
81 virtual ~WebSocketBasicStreamSocketTest() {
82 // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so
83 // should be destroyed first.
84 stream_.reset();
85 }
86
87 scoped_ptr<StreamSocket> MakeMockTCPClientSocket(MockRead reads[],
88 size_t reads_count,
89 MockWrite writes[],
90 size_t writes_count) {
91 // Nothing in WebSocketBasicStream should be caring about what the address
92 // is. Set it to 8.8.8.8:80.
93 AddressList address_list(IPEndPoint(IPAddressNumber(4, 8), 80));
94 socket_data_.reset(
95 new StaticSocketDataProvider(reads, reads_count, writes, writes_count));
96 socket_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
97 scoped_ptr<MockTCPClientSocket> socket(
98 new MockTCPClientSocket(address_list, &net_log_, socket_data_.get()));
99 CHECK_EQ(OK, socket->Connect(cb_.callback()));
100 return socket.PassAs<StreamSocket>();
101 }
102
103 scoped_ptr<ClientSocketHandle> MakeTransportSocket(
104 scoped_ptr<StreamSocket> socket) {
105 scoped_ptr<ClientSocketHandle> transport_socket(new ClientSocketHandle);
106 transport_socket->SetSocket(socket.Pass());
107 return transport_socket.Pass();
108 }
109
110 void SetHttpReadBuffer(const char* data, size_t size) {
111 http_read_buffer_ = new GrowableIOBuffer;
112 http_read_buffer_->SetCapacity(size);
113 memcpy(http_read_buffer_->data(), data, size);
114 http_read_buffer_->set_offset(size);
115 }
116
117 void CreateStream(MockRead reads[],
118 size_t reads_count,
119 MockWrite writes[],
120 size_t writes_count) {
121 stream_ = WebSocketBasicStream::CreateWebSocketBasicStreamForTesting(
122 MakeTransportSocket(
123 MakeMockTCPClientSocket(reads, reads_count, writes, writes_count)),
124 http_read_buffer_,
125 sub_protocol_,
126 extensions_,
127 &GenerateNulMaskingKey);
128 }
129
130 template <size_t N>
131 void CreateReadOnly(MockRead (&reads)[N]) {
132 CreateStream(reads, N, NULL, 0);
133 }
134
135 template <size_t N>
136 void CreateWriteOnly(MockWrite (&writes)[N]) {
137 CreateStream(NULL, 0, writes, N);
138 }
139
140 void CreateNullStream() { CreateStream(NULL, 0, NULL, 0); }
141
142 scoped_ptr<SocketDataProvider> socket_data_;
143 ScopedVector<WebSocketFrameChunk> frame_chunks_;
144 TestCompletionCallback cb_;
145 scoped_refptr<GrowableIOBuffer> http_read_buffer_;
146 std::string sub_protocol_;
147 std::string extensions_;
148 };
149
150 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
151 CreateNullStream();
152 }
153
154 TEST_F(WebSocketBasicStreamSocketTest, SyncReadWorks) {
155 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize)};
156 CreateReadOnly(reads);
157 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
158 EXPECT_EQ(OK, result);
159 ASSERT_EQ(1U, frame_chunks_.size());
160 ASSERT_TRUE(frame_chunks_[0]->header);
161 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
162 EXPECT_TRUE(frame_chunks_[0]->header->final);
163 EXPECT_TRUE(frame_chunks_[0]->final_chunk);
164 }
165
166 TEST_F(WebSocketBasicStreamSocketTest, AsyncReadWorks) {
167 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kSampleFrameSize)};
168 CreateReadOnly(reads);
169 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
170 ASSERT_EQ(ERR_IO_PENDING, result);
171 EXPECT_EQ(OK, cb_.WaitForResult());
172 ASSERT_EQ(1U, frame_chunks_.size());
173 ASSERT_TRUE(frame_chunks_[0]->header);
174 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
175 // Don't repeat all the tests from SyncReadWorks; just enough to be sure the
176 // frame was really read.
177 }
178
179 // ReadFrames will not return a frame whose header has not been wholly received.
180 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSync) {
181 MockRead reads[] = {
182 MockRead(SYNCHRONOUS, kSampleFrame, 1),
183 MockRead(SYNCHRONOUS, kSampleFrame + 1, kSampleFrameSize - 1)};
184 CreateReadOnly(reads);
185 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
186 ASSERT_EQ(OK, result);
187 ASSERT_EQ(1U, frame_chunks_.size());
188 ASSERT_TRUE(frame_chunks_[0]->header);
189 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
190 }
191
192 // The same behaviour applies to asynchronous reads.
193 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedAsync) {
194 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1),
195 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
196 CreateReadOnly(reads);
197 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
198 ASSERT_EQ(ERR_IO_PENDING, result);
199 EXPECT_EQ(OK, cb_.WaitForResult());
200 ASSERT_EQ(1U, frame_chunks_.size());
201 ASSERT_TRUE(frame_chunks_[0]->header);
202 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
203 }
204
205 // If it receives an incomplete header in a synchronous call, then has to wait
206 // for the rest of the frame, ReadFrames will return ERR_IO_PENDING.
207 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) {
208 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1),
209 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
210 CreateReadOnly(reads);
211 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
212 ASSERT_EQ(ERR_IO_PENDING, result);
213 EXPECT_EQ(OK, cb_.WaitForResult());
214 ASSERT_EQ(1U, frame_chunks_.size());
215 ASSERT_TRUE(frame_chunks_[0]->header);
216 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
217 }
218
219 // An extended header should also return ERR_IO_PENDING if it is not completely
220 // received.
221 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) {
222 MockRead reads[] = {
223 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1),
224 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
225 CreateReadOnly(reads);
226 EXPECT_EQ(ERR_IO_PENDING,
227 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
228 }
229
230 // A frame that does not arrive in a single read should arrive in chunks.
231 TEST_F(WebSocketBasicStreamSocketTest, LargeFrameFirstChunk) {
232 MockRead reads[] = {
233 MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize)};
234 CreateReadOnly(reads);
235 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
236 ASSERT_EQ(1U, frame_chunks_.size());
237 ASSERT_TRUE(frame_chunks_[0]->header);
238 EXPECT_EQ(kLargeFrameDeclaredPayloadSize,
239 frame_chunks_[0]->header->payload_length);
240 EXPECT_TRUE(frame_chunks_[0]->header->final);
241 EXPECT_FALSE(frame_chunks_[0]->final_chunk);
242 EXPECT_EQ(kPartialLargeFrameSize - kLargeFrameHeaderSize,
243 static_cast<size_t>(frame_chunks_[0]->data->size()));
244 }
245
246 // If only the header arrives, we should get a zero-byte chunk.
247 TEST_F(WebSocketBasicStreamSocketTest, HeaderOnlyChunk) {
248 MockRead reads[] = {
249 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize)};
250 CreateReadOnly(reads);
251 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
252 ASSERT_EQ(1U, frame_chunks_.size());
253 EXPECT_FALSE(frame_chunks_[0]->final_chunk);
254 EXPECT_TRUE(frame_chunks_[0]->data.get() == NULL);
255 }
256
257 // The second and subsequent chunks of a frame have no header.
258 TEST_F(WebSocketBasicStreamSocketTest, LargeFrameTwoChunks) {
259 static const size_t kChunkSize = 16;
260 MockRead reads[] = {
261 MockRead(ASYNC, kPartialLargeFrame, kChunkSize),
262 MockRead(ASYNC, kPartialLargeFrame + kChunkSize, kChunkSize)};
263 CreateReadOnly(reads);
264 TestCompletionCallback cb[2];
265
266 ASSERT_EQ(ERR_IO_PENDING,
267 stream_->ReadFrames(&frame_chunks_, cb[0].callback()));
268 EXPECT_EQ(OK, cb[0].WaitForResult());
269 ASSERT_EQ(1U, frame_chunks_.size());
270 ASSERT_TRUE(frame_chunks_[0]->header);
271
272 frame_chunks_.clear();
273 ASSERT_EQ(ERR_IO_PENDING,
274 stream_->ReadFrames(&frame_chunks_, cb[1].callback()));
275 EXPECT_EQ(OK, cb[1].WaitForResult());
276 ASSERT_EQ(1U, frame_chunks_.size());
277 ASSERT_FALSE(frame_chunks_[0]->header);
278 }
279
280 // Only the final chunk of a frame has final_chunk set.
281 TEST_F(WebSocketBasicStreamSocketTest, OnlyFinalChunkIsFinal) {
282 static const size_t kFirstChunkSize = 4;
283 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kFirstChunkSize),
284 MockRead(ASYNC,
285 kSampleFrame + kFirstChunkSize,
286 kSampleFrameSize - kFirstChunkSize)};
287 CreateReadOnly(reads);
288 TestCompletionCallback cb[2];
289
290 ASSERT_EQ(ERR_IO_PENDING,
291 stream_->ReadFrames(&frame_chunks_, cb[0].callback()));
292 EXPECT_EQ(OK, cb[0].WaitForResult());
293 ASSERT_EQ(1U, frame_chunks_.size());
294 ASSERT_FALSE(frame_chunks_[0]->final_chunk);
295
296 frame_chunks_.clear();
297 ASSERT_EQ(ERR_IO_PENDING,
298 stream_->ReadFrames(&frame_chunks_, cb[1].callback()));
299 EXPECT_EQ(OK, cb[1].WaitForResult());
300 ASSERT_EQ(1U, frame_chunks_.size());
301 ASSERT_TRUE(frame_chunks_[0]->final_chunk);
302 }
303
304 // Multiple frames that arrive together should be parsed correctly.
305 TEST_F(WebSocketBasicStreamSocketTest, ThreeFramesTogether) {
306 MockRead reads[] = {
307 MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize)};
308 CreateReadOnly(reads);
309
310 ASSERT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
311 ASSERT_EQ(3U, frame_chunks_.size());
312 EXPECT_TRUE(frame_chunks_[0]->final_chunk);
313 EXPECT_TRUE(frame_chunks_[1]->final_chunk);
314 EXPECT_TRUE(frame_chunks_[2]->final_chunk);
315 }
316
317 // ERR_CONNECTION_CLOSED must be returned on close.
318 TEST_F(WebSocketBasicStreamSocketTest, SyncClose) {
319 MockRead reads[] = {MockRead(SYNCHRONOUS, "", 0)};
320 CreateReadOnly(reads);
321
322 EXPECT_EQ(ERR_CONNECTION_CLOSED,
323 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
324 }
325
326 TEST_F(WebSocketBasicStreamSocketTest, AsyncClose) {
327 MockRead reads[] = {MockRead(ASYNC, "", 0)};
328 CreateReadOnly(reads);
329
330 ASSERT_EQ(ERR_IO_PENDING,
331 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
332 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
333 }
334
335 // The result should be the same if the socket returns ERR_CONNECTION_CLOSED
336 TEST_F(WebSocketBasicStreamSocketTest, SyncCloseWithErr) {
337 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
338 CreateReadOnly(reads);
339
340 EXPECT_EQ(ERR_CONNECTION_CLOSED,
341 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
342 }
343
344 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseWithErr) {
345 MockRead reads[] = {MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
346 CreateReadOnly(reads);
347
348 ASSERT_EQ(ERR_IO_PENDING,
349 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
350 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
351 }
352
353 // If we get a frame followed by a close, we should receive them separately.
354 TEST_F(WebSocketBasicStreamSocketTest, CloseAfterFrame) {
355 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize),
356 MockRead(SYNCHRONOUS, "", 0)};
357 CreateReadOnly(reads);
358
359 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
360 EXPECT_EQ(1U, frame_chunks_.size());
361 frame_chunks_.clear();
362 EXPECT_EQ(ERR_CONNECTION_CLOSED,
363 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
364 }
365
366 // Synchronous close after an async frame header is handled by a different code
367 // path.
368 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) {
369 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
370 MockRead(SYNCHRONOUS, "", 0)};
371 CreateReadOnly(reads);
372
373 ASSERT_EQ(ERR_IO_PENDING,
374 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
375 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
376 }
377
378 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a
379 // slightly different code path.
380 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) {
381 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
382 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
383 CreateReadOnly(reads);
384
385 ASSERT_EQ(ERR_IO_PENDING,
386 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
387 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
388 }
389
390 // If there was a frame read at the same time as the response headers (and the
391 // handshake succeeded), then we should parse it.
392 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) {
393 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize);
394 CreateNullStream();
395
396 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
397 ASSERT_EQ(1U, frame_chunks_.size());
398 ASSERT_TRUE(frame_chunks_[0]->data);
399 EXPECT_EQ(6, frame_chunks_[0]->data->size());
400 }
401
402 // Check that a frame whose header partially arrived at the end of the response
403 // headers works correctly.
404 TEST_F(WebSocketBasicStreamSocketTest, PartialFrameHeaderInHttpResponse) {
405 SetHttpReadBuffer(kSampleFrame, 1);
406 MockRead reads[] = {MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
407 CreateReadOnly(reads);
408
409 ASSERT_EQ(ERR_IO_PENDING,
410 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
411 EXPECT_EQ(OK, cb_.WaitForResult());
412 ASSERT_EQ(1U, frame_chunks_.size());
413 ASSERT_TRUE(frame_chunks_[0]->data);
414 EXPECT_EQ(6, frame_chunks_[0]->data->size());
415 ASSERT_TRUE(frame_chunks_[0]->header);
416 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText,
417 frame_chunks_[0]->header->opcode);
418 }
419
420 // Check that an invalid frame results in an error.
421 TEST_F(WebSocketBasicStreamSocketTest, SyncInvalidFrame) {
422 MockRead reads[] = {MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize)};
423 CreateReadOnly(reads);
424
425 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
426 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
427 }
428
429 TEST_F(WebSocketBasicStreamSocketTest, AsyncInvalidFrame) {
430 MockRead reads[] = {MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize)};
431 CreateReadOnly(reads);
432
433 ASSERT_EQ(ERR_IO_PENDING,
434 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
435 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
436 }
437
438 // Check that writing a frame all at once works.
439 TEST_F(WebSocketBasicStreamSocketTest, WriteAtOnce) {
440 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
441 CreateWriteOnly(writes);
442 frame_chunks_ = GenerateWriteFrame();
443
444 EXPECT_EQ(OK, stream_->WriteFrames(&frame_chunks_, cb_.callback()));
445 }
446
447 // Check that completely async writing works.
448 TEST_F(WebSocketBasicStreamSocketTest, AsyncWriteAtOnce) {
449 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
450 CreateWriteOnly(writes);
451 frame_chunks_ = GenerateWriteFrame();
452
453 ASSERT_EQ(ERR_IO_PENDING,
454 stream_->WriteFrames(&frame_chunks_, cb_.callback()));
455 EXPECT_EQ(OK, cb_.WaitForResult());
456 }
457
458 // Check that writing a frame to an extremely full kernel buffer (so that it
459 // ends up being sent in bits) works. The WriteFrames() callback should not be
460 // called until all parts have been written.
461 TEST_F(WebSocketBasicStreamSocketTest, WriteInBits) {
462 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
463 MockWrite(ASYNC, kWriteFrame + 4, 4),
464 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
465 CreateWriteOnly(writes);
466 frame_chunks_ = GenerateWriteFrame();
467
468 ASSERT_EQ(ERR_IO_PENDING,
469 stream_->WriteFrames(&frame_chunks_, cb_.callback()));
470 EXPECT_EQ(OK, cb_.WaitForResult());
471 }
472
473 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
474 extensions_ = "inflate-uuencode";
475 CreateNullStream();
476
477 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
478 }
479
480 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
481 sub_protocol_ = "cyberchat";
482 CreateNullStream();
483
484 EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
485 }
486
487 } // namespace
488 } // namespace net
OLDNEW
« net/websockets/websocket_basic_stream.cc ('K') | « net/websockets/websocket_basic_stream.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698