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

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: Amend comment to http_read_buffer_ to explain the type. 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
(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 kReadBufferSize;
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 WebSocketBasicStreamSocketTest()
82 : histograms_("a"), pool_(1, 1, &histograms_, &factory_) {}
83
84 virtual ~WebSocketBasicStreamSocketTest() {
85 // stream_ has a reference to socket_data_ (via MockTCPClientSocket) and so
86 // should be destroyed first.
87 stream_.reset();
88 }
89
90 scoped_ptr<ClientSocketHandle> MakeTransportSocket(MockRead reads[],
91 size_t reads_count,
92 MockWrite writes[],
93 size_t writes_count) {
94 socket_data_.reset(
95 new StaticSocketDataProvider(reads, reads_count, writes, writes_count));
96 socket_data_->set_connect_data(MockConnect(SYNCHRONOUS, OK));
97 factory_.AddSocketDataProvider(socket_data_.get());
98
99 scoped_ptr<ClientSocketHandle> transport_socket(new ClientSocketHandle);
100 scoped_refptr<MockTransportSocketParams> params;
101 transport_socket->Init("a",
102 params,
103 MEDIUM,
104 CompletionCallback(),
105 &pool_,
106 bound_net_log_.bound());
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(reads, reads_count, writes, writes_count),
123 http_read_buffer_,
124 sub_protocol_,
125 extensions_,
126 &GenerateNulMaskingKey);
127 }
128
129 template <size_t N>
130 void CreateReadOnly(MockRead (&reads)[N]) {
131 CreateStream(reads, N, NULL, 0);
132 }
133
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); }
140
141 scoped_ptr<SocketDataProvider> socket_data_;
142 MockClientSocketFactory factory_;
143 ClientSocketPoolHistograms histograms_;
144 MockTransportClientSocketPool pool_;
145 CapturingBoundNetLog(bound_net_log_);
146 ScopedVector<WebSocketFrameChunk> frame_chunks_;
147 TestCompletionCallback cb_;
148 scoped_refptr<GrowableIOBuffer> http_read_buffer_;
149 std::string sub_protocol_;
150 std::string extensions_;
151 };
152
153 TEST_F(WebSocketBasicStreamSocketTest, ConstructionWorks) {
154 CreateNullStream();
155 }
156
157 TEST_F(WebSocketBasicStreamSocketTest, SyncReadWorks) {
158 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize)};
159 CreateReadOnly(reads);
160 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
161 EXPECT_EQ(OK, result);
162 ASSERT_EQ(1U, frame_chunks_.size());
163 ASSERT_TRUE(frame_chunks_[0]->header);
164 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
165 EXPECT_TRUE(frame_chunks_[0]->header->final);
166 EXPECT_TRUE(frame_chunks_[0]->final_chunk);
167 }
168
169 TEST_F(WebSocketBasicStreamSocketTest, AsyncReadWorks) {
170 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kSampleFrameSize)};
171 CreateReadOnly(reads);
172 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
173 ASSERT_EQ(ERR_IO_PENDING, result);
174 EXPECT_EQ(OK, cb_.WaitForResult());
175 ASSERT_EQ(1U, frame_chunks_.size());
176 ASSERT_TRUE(frame_chunks_[0]->header);
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
179 // frame was really read.
180 }
181
182 // ReadFrames will not return a frame whose header has not been wholly received.
183 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSync) {
184 MockRead reads[] = {
185 MockRead(SYNCHRONOUS, kSampleFrame, 1),
186 MockRead(SYNCHRONOUS, kSampleFrame + 1, kSampleFrameSize - 1)};
187 CreateReadOnly(reads);
188 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
189 ASSERT_EQ(OK, result);
190 ASSERT_EQ(1U, frame_chunks_.size());
191 ASSERT_TRUE(frame_chunks_[0]->header);
192 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
193 }
194
195 // The same behaviour applies to asynchronous reads.
196 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedAsync) {
197 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1),
198 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
199 CreateReadOnly(reads);
200 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
201 ASSERT_EQ(ERR_IO_PENDING, result);
202 EXPECT_EQ(OK, cb_.WaitForResult());
203 ASSERT_EQ(1U, frame_chunks_.size());
204 ASSERT_TRUE(frame_chunks_[0]->header);
205 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
206 }
207
208 // 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.
210 TEST_F(WebSocketBasicStreamSocketTest, HeaderFragmentedSyncAsync) {
211 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, 1),
212 MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
213 CreateReadOnly(reads);
214 int result = stream_->ReadFrames(&frame_chunks_, cb_.callback());
215 ASSERT_EQ(ERR_IO_PENDING, result);
216 EXPECT_EQ(OK, cb_.WaitForResult());
217 ASSERT_EQ(1U, frame_chunks_.size());
218 ASSERT_TRUE(frame_chunks_[0]->header);
219 EXPECT_EQ(GG_UINT64_C(6), frame_chunks_[0]->header->payload_length);
220 }
221
222 // An extended header should also return ERR_IO_PENDING if it is not completely
223 // received.
224 TEST_F(WebSocketBasicStreamSocketTest, FragmentedLargeHeader) {
225 MockRead reads[] = {
226 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize - 1),
227 MockRead(SYNCHRONOUS, ERR_IO_PENDING)};
228 CreateReadOnly(reads);
229 EXPECT_EQ(ERR_IO_PENDING,
230 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
231 }
232
233 // A frame that does not arrive in a single read should arrive in chunks.
234 TEST_F(WebSocketBasicStreamSocketTest, LargeFrameFirstChunk) {
235 MockRead reads[] = {
236 MockRead(SYNCHRONOUS, kPartialLargeFrame, kPartialLargeFrameSize)};
237 CreateReadOnly(reads);
238 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
239 ASSERT_EQ(1U, frame_chunks_.size());
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,
246 static_cast<size_t>(frame_chunks_[0]->data->size()));
247 }
248
249 // If only the header arrives, we should get a zero-byte chunk.
250 TEST_F(WebSocketBasicStreamSocketTest, HeaderOnlyChunk) {
251 MockRead reads[] = {
252 MockRead(SYNCHRONOUS, kPartialLargeFrame, kLargeFrameHeaderSize)};
253 CreateReadOnly(reads);
254 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
255 ASSERT_EQ(1U, frame_chunks_.size());
256 EXPECT_FALSE(frame_chunks_[0]->final_chunk);
257 EXPECT_TRUE(frame_chunks_[0]->data.get() == NULL);
258 }
259
260 // The second and subsequent chunks of a frame have no header.
261 TEST_F(WebSocketBasicStreamSocketTest, LargeFrameTwoChunks) {
262 static const size_t kChunkSize = 16;
263 MockRead reads[] = {
264 MockRead(ASYNC, kPartialLargeFrame, kChunkSize),
265 MockRead(ASYNC, kPartialLargeFrame + kChunkSize, kChunkSize)};
266 CreateReadOnly(reads);
267 TestCompletionCallback cb[2];
268
269 ASSERT_EQ(ERR_IO_PENDING,
270 stream_->ReadFrames(&frame_chunks_, cb[0].callback()));
271 EXPECT_EQ(OK, cb[0].WaitForResult());
272 ASSERT_EQ(1U, frame_chunks_.size());
273 ASSERT_TRUE(frame_chunks_[0]->header);
274
275 frame_chunks_.clear();
276 ASSERT_EQ(ERR_IO_PENDING,
277 stream_->ReadFrames(&frame_chunks_, cb[1].callback()));
278 EXPECT_EQ(OK, cb[1].WaitForResult());
279 ASSERT_EQ(1U, frame_chunks_.size());
280 ASSERT_FALSE(frame_chunks_[0]->header);
281 }
282
283 // Only the final chunk of a frame has final_chunk set.
284 TEST_F(WebSocketBasicStreamSocketTest, OnlyFinalChunkIsFinal) {
285 static const size_t kFirstChunkSize = 4;
286 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, kFirstChunkSize),
287 MockRead(ASYNC,
288 kSampleFrame + kFirstChunkSize,
289 kSampleFrameSize - kFirstChunkSize)};
290 CreateReadOnly(reads);
291 TestCompletionCallback cb[2];
292
293 ASSERT_EQ(ERR_IO_PENDING,
294 stream_->ReadFrames(&frame_chunks_, cb[0].callback()));
295 EXPECT_EQ(OK, cb[0].WaitForResult());
296 ASSERT_EQ(1U, frame_chunks_.size());
297 ASSERT_FALSE(frame_chunks_[0]->final_chunk);
298
299 frame_chunks_.clear();
300 ASSERT_EQ(ERR_IO_PENDING,
301 stream_->ReadFrames(&frame_chunks_, cb[1].callback()));
302 EXPECT_EQ(OK, cb[1].WaitForResult());
303 ASSERT_EQ(1U, frame_chunks_.size());
304 ASSERT_TRUE(frame_chunks_[0]->final_chunk);
305 }
306
307 // Multiple frames that arrive together should be parsed correctly.
308 TEST_F(WebSocketBasicStreamSocketTest, ThreeFramesTogether) {
309 MockRead reads[] = {
310 MockRead(SYNCHRONOUS, kMultipleFrames, kMultipleFramesSize)};
311 CreateReadOnly(reads);
312
313 ASSERT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
314 ASSERT_EQ(3U, frame_chunks_.size());
315 EXPECT_TRUE(frame_chunks_[0]->final_chunk);
316 EXPECT_TRUE(frame_chunks_[1]->final_chunk);
317 EXPECT_TRUE(frame_chunks_[2]->final_chunk);
318 }
319
320 // ERR_CONNECTION_CLOSED must be returned on close.
321 TEST_F(WebSocketBasicStreamSocketTest, SyncClose) {
322 MockRead reads[] = {MockRead(SYNCHRONOUS, "", 0)};
323 CreateReadOnly(reads);
324
325 EXPECT_EQ(ERR_CONNECTION_CLOSED,
326 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
327 }
328
329 TEST_F(WebSocketBasicStreamSocketTest, AsyncClose) {
330 MockRead reads[] = {MockRead(ASYNC, "", 0)};
331 CreateReadOnly(reads);
332
333 ASSERT_EQ(ERR_IO_PENDING,
334 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
335 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
336 }
337
338 // The result should be the same if the socket returns ERR_CONNECTION_CLOSED
szym 2013/08/29 16:42:01 I think Socket implementations only return this du
Adam Rice 2013/08/30 10:05:35 I added a comment clarifying that we are not actua
339 TEST_F(WebSocketBasicStreamSocketTest, SyncCloseWithErr) {
340 MockRead reads[] = {MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
341 CreateReadOnly(reads);
342
343 EXPECT_EQ(ERR_CONNECTION_CLOSED,
344 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
345 }
346
347 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseWithErr) {
348 MockRead reads[] = {MockRead(ASYNC, ERR_CONNECTION_CLOSED)};
349 CreateReadOnly(reads);
350
351 ASSERT_EQ(ERR_IO_PENDING,
352 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
353 EXPECT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
354 }
355
356 // If we get a frame followed by a close, we should receive them separately.
357 TEST_F(WebSocketBasicStreamSocketTest, CloseAfterFrame) {
358 MockRead reads[] = {MockRead(SYNCHRONOUS, kSampleFrame, kSampleFrameSize),
359 MockRead(SYNCHRONOUS, "", 0)};
360 CreateReadOnly(reads);
361
362 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
363 EXPECT_EQ(1U, frame_chunks_.size());
364 frame_chunks_.clear();
365 EXPECT_EQ(ERR_CONNECTION_CLOSED,
366 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
367 }
368
369 // Synchronous close after an async frame header is handled by a different code
370 // path.
371 TEST_F(WebSocketBasicStreamSocketTest, AsyncCloseAfterIncompleteHeader) {
372 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
373 MockRead(SYNCHRONOUS, "", 0)};
374 CreateReadOnly(reads);
375
376 ASSERT_EQ(ERR_IO_PENDING,
377 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
378 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
379 }
380
381 // When Stream::Read returns ERR_CONNECTION_CLOSED we get the same result via a
382 // slightly different code path.
383 TEST_F(WebSocketBasicStreamSocketTest, AsyncErrCloseAfterIncompleteHeader) {
384 MockRead reads[] = {MockRead(ASYNC, kSampleFrame, 1U),
385 MockRead(SYNCHRONOUS, ERR_CONNECTION_CLOSED)};
386 CreateReadOnly(reads);
387
388 ASSERT_EQ(ERR_IO_PENDING,
389 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
390 ASSERT_EQ(ERR_CONNECTION_CLOSED, cb_.WaitForResult());
391 }
392
393 // If there was a frame read at the same time as the response headers (and the
394 // handshake succeeded), then we should parse it.
395 TEST_F(WebSocketBasicStreamSocketTest, HttpReadBufferIsUsed) {
396 SetHttpReadBuffer(kSampleFrame, kSampleFrameSize);
397 CreateNullStream();
398
399 EXPECT_EQ(OK, stream_->ReadFrames(&frame_chunks_, cb_.callback()));
400 ASSERT_EQ(1U, frame_chunks_.size());
401 ASSERT_TRUE(frame_chunks_[0]->data);
402 EXPECT_EQ(6, frame_chunks_[0]->data->size());
403 }
404
405 // Check that a frame whose header partially arrived at the end of the response
406 // headers works correctly.
407 TEST_F(WebSocketBasicStreamSocketTest, PartialFrameHeaderInHttpResponse) {
408 SetHttpReadBuffer(kSampleFrame, 1);
409 MockRead reads[] = {MockRead(ASYNC, kSampleFrame + 1, kSampleFrameSize - 1)};
410 CreateReadOnly(reads);
411
412 ASSERT_EQ(ERR_IO_PENDING,
413 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
414 EXPECT_EQ(OK, cb_.WaitForResult());
415 ASSERT_EQ(1U, frame_chunks_.size());
416 ASSERT_TRUE(frame_chunks_[0]->data);
417 EXPECT_EQ(6, frame_chunks_[0]->data->size());
418 ASSERT_TRUE(frame_chunks_[0]->header);
419 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText,
420 frame_chunks_[0]->header->opcode);
421 }
422
423 // Check that an invalid frame results in an error.
424 TEST_F(WebSocketBasicStreamSocketTest, SyncInvalidFrame) {
425 MockRead reads[] = {MockRead(SYNCHRONOUS, kInvalidFrame, kInvalidFrameSize)};
426 CreateReadOnly(reads);
427
428 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR,
429 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
430 }
431
432 TEST_F(WebSocketBasicStreamSocketTest, AsyncInvalidFrame) {
433 MockRead reads[] = {MockRead(ASYNC, kInvalidFrame, kInvalidFrameSize)};
434 CreateReadOnly(reads);
435
436 ASSERT_EQ(ERR_IO_PENDING,
437 stream_->ReadFrames(&frame_chunks_, cb_.callback()));
438 EXPECT_EQ(ERR_WS_PROTOCOL_ERROR, cb_.WaitForResult());
439 }
440
441 // Check that writing a frame all at once works.
442 TEST_F(WebSocketBasicStreamSocketTest, WriteAtOnce) {
443 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, kWriteFrameSize)};
444 CreateWriteOnly(writes);
445 frame_chunks_ = GenerateWriteFrame();
446
447 EXPECT_EQ(OK, stream_->WriteFrames(&frame_chunks_, cb_.callback()));
448 }
449
450 // Check that completely async writing works.
451 TEST_F(WebSocketBasicStreamSocketTest, AsyncWriteAtOnce) {
452 MockWrite writes[] = {MockWrite(ASYNC, kWriteFrame, kWriteFrameSize)};
453 CreateWriteOnly(writes);
454 frame_chunks_ = GenerateWriteFrame();
455
456 ASSERT_EQ(ERR_IO_PENDING,
457 stream_->WriteFrames(&frame_chunks_, cb_.callback()));
458 EXPECT_EQ(OK, cb_.WaitForResult());
459 }
460
461 // Check that writing a frame to an extremely full kernel buffer (so that it
462 // ends up being sent in bits) works. The WriteFrames() callback should not be
463 // called until all parts have been written.
464 TEST_F(WebSocketBasicStreamSocketTest, WriteInBits) {
465 MockWrite writes[] = {MockWrite(SYNCHRONOUS, kWriteFrame, 4),
466 MockWrite(ASYNC, kWriteFrame + 4, 4),
467 MockWrite(ASYNC, kWriteFrame + 8, kWriteFrameSize - 8)};
468 CreateWriteOnly(writes);
469 frame_chunks_ = GenerateWriteFrame();
470
471 ASSERT_EQ(ERR_IO_PENDING,
472 stream_->WriteFrames(&frame_chunks_, cb_.callback()));
473 EXPECT_EQ(OK, cb_.WaitForResult());
474 }
475
476 TEST_F(WebSocketBasicStreamSocketTest, GetExtensionsWorks) {
477 extensions_ = "inflate-uuencode";
478 CreateNullStream();
479
480 EXPECT_EQ("inflate-uuencode", stream_->GetExtensions());
481 }
482
483 TEST_F(WebSocketBasicStreamSocketTest, GetSubProtocolWorks) {
484 sub_protocol_ = "cyberchat";
485 CreateNullStream();
486
487 EXPECT_EQ("cyberchat", stream_->GetSubProtocol());
488 }
489
490 } // namespace
491 } // namespace net
OLDNEW
« net/websockets/websocket_basic_stream.h ('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