OLD | NEW |
| (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 #include "net/websockets/websocket_deflate_stream.h" | |
6 | |
7 #include <stdint.h> | |
8 #include <deque> | |
9 #include <string> | |
10 | |
11 #include "base/basictypes.h" | |
12 #include "base/bind.h" | |
13 #include "base/memory/ref_counted.h" | |
14 #include "base/memory/scoped_ptr.h" | |
15 #include "base/memory/scoped_vector.h" | |
16 #include "net/base/completion_callback.h" | |
17 #include "net/base/io_buffer.h" | |
18 #include "net/base/net_errors.h" | |
19 #include "net/websockets/websocket_deflate_predictor.h" | |
20 #include "net/websockets/websocket_deflater.h" | |
21 #include "net/websockets/websocket_frame.h" | |
22 #include "net/websockets/websocket_inflater.h" | |
23 #include "net/websockets/websocket_stream.h" | |
24 #include "net/websockets/websocket_test_util.h" | |
25 #include "testing/gmock/include/gmock/gmock.h" | |
26 #include "testing/gtest/include/gtest/gtest.h" | |
27 | |
28 namespace net { | |
29 namespace { | |
30 | |
31 typedef ::testing::MockFunction<void(int)> MockCallback; // NOLINT | |
32 using ::testing::_; | |
33 using ::testing::InSequence; | |
34 using ::testing::Invoke; | |
35 using ::testing::Return; | |
36 | |
37 typedef uint32_t FrameFlag; | |
38 const FrameFlag kNoFlag = 0; | |
39 const FrameFlag kFinal = 1; | |
40 const FrameFlag kReserved1 = 2; | |
41 // We don't define values for other flags because we don't need them. | |
42 | |
43 // The value must equal to the value of the corresponding | |
44 // constant in websocket_deflate_stream.cc | |
45 const size_t kChunkSize = 4 * 1024; | |
46 const int kWindowBits = 15; | |
47 | |
48 scoped_refptr<IOBuffer> ToIOBuffer(const std::string& s) { | |
49 scoped_refptr<IOBuffer> buffer = new IOBuffer(s.size()); | |
50 memcpy(buffer->data(), s.data(), s.size()); | |
51 return buffer; | |
52 } | |
53 | |
54 std::string ToString(IOBufferWithSize* buffer) { | |
55 return std::string(buffer->data(), buffer->size()); | |
56 } | |
57 | |
58 std::string ToString(const scoped_refptr<IOBufferWithSize>& buffer) { | |
59 return ToString(buffer.get()); | |
60 } | |
61 | |
62 std::string ToString(IOBuffer* buffer, size_t size) { | |
63 return std::string(buffer->data(), size); | |
64 } | |
65 | |
66 std::string ToString(const scoped_refptr<IOBuffer>& buffer, size_t size) { | |
67 return ToString(buffer.get(), size); | |
68 } | |
69 | |
70 std::string ToString(const WebSocketFrame* frame) { | |
71 return frame->data.get() ? ToString(frame->data, frame->header.payload_length) | |
72 : ""; | |
73 } | |
74 | |
75 void AppendTo(ScopedVector<WebSocketFrame>* frames, | |
76 WebSocketFrameHeader::OpCode opcode, | |
77 FrameFlag flag, | |
78 const std::string& data) { | |
79 scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(opcode)); | |
80 frame->header.final = (flag & kFinal); | |
81 frame->header.reserved1 = (flag & kReserved1); | |
82 frame->data = ToIOBuffer(data); | |
83 frame->header.payload_length = data.size(); | |
84 frames->push_back(frame.release()); | |
85 } | |
86 | |
87 void AppendTo(ScopedVector<WebSocketFrame>* frames, | |
88 WebSocketFrameHeader::OpCode opcode, | |
89 FrameFlag flag) { | |
90 scoped_ptr<WebSocketFrame> frame(new WebSocketFrame(opcode)); | |
91 frame->header.final = (flag & kFinal); | |
92 frame->header.reserved1 = (flag & kReserved1); | |
93 frames->push_back(frame.release()); | |
94 } | |
95 | |
96 class MockWebSocketStream : public WebSocketStream { | |
97 public: | |
98 MOCK_METHOD2(ReadFrames, int(ScopedVector<WebSocketFrame>*, | |
99 const CompletionCallback&)); | |
100 MOCK_METHOD2(WriteFrames, int(ScopedVector<WebSocketFrame>*, | |
101 const CompletionCallback&)); | |
102 MOCK_METHOD0(Close, void()); | |
103 MOCK_CONST_METHOD0(GetSubProtocol, std::string()); | |
104 MOCK_CONST_METHOD0(GetExtensions, std::string()); | |
105 }; | |
106 | |
107 // This mock class relies on some assumptions. | |
108 // - RecordInputDataFrame is called after the corresponding WriteFrames | |
109 // call. | |
110 // - RecordWrittenDataFrame is called before writing the frame. | |
111 class WebSocketDeflatePredictorMock : public WebSocketDeflatePredictor { | |
112 public: | |
113 WebSocketDeflatePredictorMock() : result_(DEFLATE) {} | |
114 ~WebSocketDeflatePredictorMock() override { | |
115 // Verify whether all expectaions are consumed. | |
116 if (!frames_to_be_input_.empty()) { | |
117 ADD_FAILURE() << "There are missing frames to be input."; | |
118 return; | |
119 } | |
120 if (!frames_written_.empty()) { | |
121 ADD_FAILURE() << "There are extra written frames."; | |
122 return; | |
123 } | |
124 } | |
125 | |
126 // WebSocketDeflatePredictor functions. | |
127 Result Predict(const ScopedVector<WebSocketFrame>& frames, | |
128 size_t frame_index) override { | |
129 return result_; | |
130 } | |
131 void RecordInputDataFrame(const WebSocketFrame* frame) override { | |
132 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) { | |
133 ADD_FAILURE() << "Control frames should not be recorded."; | |
134 return; | |
135 } | |
136 if (frame->header.reserved1) { | |
137 ADD_FAILURE() << "Input frame may not be compressed."; | |
138 return; | |
139 } | |
140 if (frames_to_be_input_.empty()) { | |
141 ADD_FAILURE() << "Unexpected input data frame"; | |
142 return; | |
143 } | |
144 if (frame != frames_to_be_input_.front()) { | |
145 ADD_FAILURE() << "Input data frame does not match the expectation."; | |
146 return; | |
147 } | |
148 frames_to_be_input_.pop_front(); | |
149 } | |
150 void RecordWrittenDataFrame(const WebSocketFrame* frame) override { | |
151 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) { | |
152 ADD_FAILURE() << "Control frames should not be recorded."; | |
153 return; | |
154 } | |
155 frames_written_.push_back(frame); | |
156 } | |
157 | |
158 // Sets |result_| for the |Predict| return value. | |
159 void set_result(Result result) { result_ = result; } | |
160 | |
161 // Adds |frame| as an expectation of future |RecordInputDataFrame| call. | |
162 void AddFrameToBeInput(const WebSocketFrame* frame) { | |
163 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) | |
164 return; | |
165 frames_to_be_input_.push_back(frame); | |
166 } | |
167 // Verifies that |frame| is recorded in order. | |
168 void VerifySentFrame(const WebSocketFrame* frame) { | |
169 if (!WebSocketFrameHeader::IsKnownDataOpCode(frame->header.opcode)) | |
170 return; | |
171 if (frames_written_.empty()) { | |
172 ADD_FAILURE() << "There are missing frames to be written."; | |
173 return; | |
174 } | |
175 if (frame != frames_written_.front()) { | |
176 ADD_FAILURE() << "Written data frame does not match the expectation."; | |
177 return; | |
178 } | |
179 frames_written_.pop_front(); | |
180 } | |
181 void AddFramesToBeInput(const ScopedVector<WebSocketFrame>& frames) { | |
182 for (size_t i = 0; i < frames.size(); ++i) | |
183 AddFrameToBeInput(frames[i]); | |
184 } | |
185 void VerifySentFrames(const ScopedVector<WebSocketFrame>& frames) { | |
186 for (size_t i = 0; i < frames.size(); ++i) | |
187 VerifySentFrame(frames[i]); | |
188 } | |
189 // Call this method in order to disable checks in the destructor when | |
190 // WriteFrames fails. | |
191 void Clear() { | |
192 frames_to_be_input_.clear(); | |
193 frames_written_.clear(); | |
194 } | |
195 | |
196 private: | |
197 Result result_; | |
198 // Data frames which will be recorded by |RecordInputFrames|. | |
199 // Pushed by |AddFrameToBeInput| and popped and verified by | |
200 // |RecordInputFrames|. | |
201 std::deque<const WebSocketFrame*> frames_to_be_input_; | |
202 // Data frames recorded by |RecordWrittenFrames|. | |
203 // Pushed by |RecordWrittenFrames| and popped and verified by | |
204 // |VerifySentFrame|. | |
205 std::deque<const WebSocketFrame*> frames_written_; | |
206 | |
207 DISALLOW_COPY_AND_ASSIGN(WebSocketDeflatePredictorMock); | |
208 }; | |
209 | |
210 class WebSocketDeflateStreamTest : public ::testing::Test { | |
211 public: | |
212 WebSocketDeflateStreamTest() | |
213 : mock_stream_(NULL), | |
214 predictor_(NULL) {} | |
215 ~WebSocketDeflateStreamTest() override {} | |
216 | |
217 void SetUp() override { | |
218 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, kWindowBits); | |
219 } | |
220 | |
221 protected: | |
222 // Initialize deflate_stream_ with the given parameters. | |
223 void Initialize(WebSocketDeflater::ContextTakeOverMode mode, | |
224 int window_bits) { | |
225 mock_stream_ = new testing::StrictMock<MockWebSocketStream>; | |
226 predictor_ = new WebSocketDeflatePredictorMock; | |
227 deflate_stream_.reset(new WebSocketDeflateStream( | |
228 scoped_ptr<WebSocketStream>(mock_stream_), | |
229 mode, | |
230 window_bits, | |
231 scoped_ptr<WebSocketDeflatePredictor>(predictor_))); | |
232 } | |
233 | |
234 scoped_ptr<WebSocketDeflateStream> deflate_stream_; | |
235 // Owned by |deflate_stream_|. | |
236 MockWebSocketStream* mock_stream_; | |
237 // Owned by |deflate_stream_|. | |
238 WebSocketDeflatePredictorMock* predictor_; | |
239 }; | |
240 | |
241 // Since WebSocketDeflater with DoNotTakeOverContext is well tested at | |
242 // websocket_deflater_test.cc, we have only a few tests for this configuration | |
243 // here. | |
244 class WebSocketDeflateStreamWithDoNotTakeOverContextTest | |
245 : public WebSocketDeflateStreamTest { | |
246 public: | |
247 WebSocketDeflateStreamWithDoNotTakeOverContextTest() {} | |
248 ~WebSocketDeflateStreamWithDoNotTakeOverContextTest() override {} | |
249 | |
250 void SetUp() override { | |
251 Initialize(WebSocketDeflater::DO_NOT_TAKE_OVER_CONTEXT, kWindowBits); | |
252 } | |
253 }; | |
254 | |
255 class WebSocketDeflateStreamWithClientWindowBitsTest | |
256 : public WebSocketDeflateStreamTest { | |
257 public: | |
258 WebSocketDeflateStreamWithClientWindowBitsTest() {} | |
259 ~WebSocketDeflateStreamWithClientWindowBitsTest() override {} | |
260 | |
261 // Overridden to postpone the call to Initialize(). | |
262 void SetUp() override {} | |
263 | |
264 // This needs to be called explicitly from the tests. | |
265 void SetUpWithWindowBits(int window_bits) { | |
266 Initialize(WebSocketDeflater::TAKE_OVER_CONTEXT, window_bits); | |
267 } | |
268 | |
269 // Add a frame which will be compressed to a smaller size if the window | |
270 // size is large enough. | |
271 void AddCompressibleFrameString() { | |
272 const std::string word = "Chromium"; | |
273 const std::string payload = word + std::string(256, 'a') + word; | |
274 AppendTo(&frames_, WebSocketFrameHeader::kOpCodeText, kFinal, payload); | |
275 predictor_->AddFramesToBeInput(frames_); | |
276 } | |
277 | |
278 protected: | |
279 ScopedVector<WebSocketFrame> frames_; | |
280 }; | |
281 | |
282 // ReadFrameStub is a stub for WebSocketStream::ReadFrames. | |
283 // It returns |result_| and |frames_to_output_| to the caller and | |
284 // saves parameters to |frames_passed_| and |callback_|. | |
285 class ReadFramesStub { | |
286 public: | |
287 explicit ReadFramesStub(int result) : result_(result) {} | |
288 | |
289 ReadFramesStub(int result, ScopedVector<WebSocketFrame>* frames_to_output) | |
290 : result_(result) { | |
291 frames_to_output_.swap(*frames_to_output); | |
292 } | |
293 | |
294 int Call(ScopedVector<WebSocketFrame>* frames, | |
295 const CompletionCallback& callback) { | |
296 DCHECK(frames->empty()); | |
297 frames_passed_ = frames; | |
298 callback_ = callback; | |
299 frames->swap(frames_to_output_); | |
300 return result_; | |
301 } | |
302 | |
303 int result() const { return result_; } | |
304 const CompletionCallback callback() const { return callback_; } | |
305 ScopedVector<WebSocketFrame>* frames_passed() { | |
306 return frames_passed_; | |
307 } | |
308 | |
309 private: | |
310 int result_; | |
311 CompletionCallback callback_; | |
312 ScopedVector<WebSocketFrame> frames_to_output_; | |
313 ScopedVector<WebSocketFrame>* frames_passed_; | |
314 }; | |
315 | |
316 // WriteFramesStub is a stub for WebSocketStream::WriteFrames. | |
317 // It returns |result_| and |frames_| to the caller and | |
318 // saves |callback| parameter to |callback_|. | |
319 class WriteFramesStub { | |
320 public: | |
321 explicit WriteFramesStub(WebSocketDeflatePredictorMock* predictor, | |
322 int result) | |
323 : result_(result), predictor_(predictor) {} | |
324 | |
325 int Call(ScopedVector<WebSocketFrame>* frames, | |
326 const CompletionCallback& callback) { | |
327 frames_.insert(frames_.end(), frames->begin(), frames->end()); | |
328 frames->weak_clear(); | |
329 callback_ = callback; | |
330 predictor_->VerifySentFrames(frames_); | |
331 return result_; | |
332 } | |
333 | |
334 int result() const { return result_; } | |
335 const CompletionCallback callback() const { return callback_; } | |
336 ScopedVector<WebSocketFrame>* frames() { return &frames_; } | |
337 | |
338 private: | |
339 int result_; | |
340 CompletionCallback callback_; | |
341 ScopedVector<WebSocketFrame> frames_; | |
342 WebSocketDeflatePredictorMock* predictor_; | |
343 }; | |
344 | |
345 TEST_F(WebSocketDeflateStreamTest, ReadFailedImmediately) { | |
346 ScopedVector<WebSocketFrame> frames; | |
347 CompletionCallback callback; | |
348 { | |
349 InSequence s; | |
350 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
351 .WillOnce(Return(ERR_FAILED)); | |
352 } | |
353 EXPECT_EQ(ERR_FAILED, deflate_stream_->ReadFrames(&frames, callback)); | |
354 } | |
355 | |
356 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameImmediately) { | |
357 ScopedVector<WebSocketFrame> frames_to_output; | |
358 AppendTo(&frames_to_output, | |
359 WebSocketFrameHeader::kOpCodeText, | |
360 kFinal, | |
361 "hello"); | |
362 ReadFramesStub stub(OK, &frames_to_output); | |
363 ScopedVector<WebSocketFrame> frames; | |
364 | |
365 { | |
366 InSequence s; | |
367 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
368 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
369 } | |
370 CompletionCallback callback; | |
371 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
372 ASSERT_EQ(1u, frames.size()); | |
373 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
374 EXPECT_TRUE(frames[0]->header.final); | |
375 EXPECT_FALSE(frames[0]->header.reserved1); | |
376 EXPECT_EQ("hello", ToString(frames[0])); | |
377 } | |
378 | |
379 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedFrameAsync) { | |
380 ReadFramesStub stub(ERR_IO_PENDING); | |
381 ScopedVector<WebSocketFrame> frames; | |
382 MockCallback mock_callback, checkpoint; | |
383 CompletionCallback callback = | |
384 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); | |
385 | |
386 { | |
387 InSequence s; | |
388 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
389 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
390 EXPECT_CALL(checkpoint, Call(0)); | |
391 EXPECT_CALL(mock_callback, Call(OK)); | |
392 } | |
393 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback)); | |
394 ASSERT_EQ(0u, frames.size()); | |
395 | |
396 checkpoint.Call(0); | |
397 | |
398 AppendTo(stub.frames_passed(), | |
399 WebSocketFrameHeader::kOpCodeText, | |
400 kFinal, | |
401 "hello"); | |
402 stub.callback().Run(OK); | |
403 ASSERT_EQ(1u, frames.size()); | |
404 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
405 EXPECT_TRUE(frames[0]->header.final); | |
406 EXPECT_FALSE(frames[0]->header.reserved1); | |
407 EXPECT_EQ("hello", ToString(frames[0])); | |
408 } | |
409 | |
410 TEST_F(WebSocketDeflateStreamTest, ReadFailedAsync) { | |
411 ReadFramesStub stub(ERR_IO_PENDING); | |
412 ScopedVector<WebSocketFrame> frames; | |
413 MockCallback mock_callback, checkpoint; | |
414 CompletionCallback callback = | |
415 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); | |
416 | |
417 { | |
418 InSequence s; | |
419 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
420 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
421 EXPECT_CALL(checkpoint, Call(0)); | |
422 EXPECT_CALL(mock_callback, Call(ERR_FAILED)); | |
423 } | |
424 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback)); | |
425 ASSERT_EQ(0u, frames.size()); | |
426 | |
427 checkpoint.Call(0); | |
428 | |
429 AppendTo(stub.frames_passed(), | |
430 WebSocketFrameHeader::kOpCodeText, | |
431 kFinal, | |
432 "hello"); | |
433 stub.callback().Run(ERR_FAILED); | |
434 ASSERT_EQ(0u, frames.size()); | |
435 } | |
436 | |
437 TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameImmediately) { | |
438 ScopedVector<WebSocketFrame> frames_to_output; | |
439 AppendTo(&frames_to_output, | |
440 WebSocketFrameHeader::kOpCodeText, | |
441 kFinal | kReserved1, | |
442 std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); | |
443 ReadFramesStub stub(OK, &frames_to_output); | |
444 CompletionCallback callback; | |
445 ScopedVector<WebSocketFrame> frames; | |
446 { | |
447 InSequence s; | |
448 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
449 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
450 } | |
451 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
452 ASSERT_EQ(1u, frames.size()); | |
453 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
454 EXPECT_TRUE(frames[0]->header.final); | |
455 EXPECT_FALSE(frames[0]->header.reserved1); | |
456 EXPECT_EQ("Hello", ToString(frames[0])); | |
457 } | |
458 | |
459 TEST_F(WebSocketDeflateStreamTest, ReadCompressedFrameAsync) { | |
460 ReadFramesStub stub(ERR_IO_PENDING); | |
461 MockCallback mock_callback, checkpoint; | |
462 CompletionCallback callback = | |
463 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); | |
464 ScopedVector<WebSocketFrame> frames; | |
465 { | |
466 InSequence s; | |
467 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
468 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
469 EXPECT_CALL(checkpoint, Call(0)); | |
470 EXPECT_CALL(mock_callback, Call(OK)); | |
471 } | |
472 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback)); | |
473 | |
474 checkpoint.Call(0); | |
475 | |
476 AppendTo(stub.frames_passed(), | |
477 WebSocketFrameHeader::kOpCodeText, | |
478 kFinal | kReserved1, | |
479 std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7)); | |
480 stub.callback().Run(OK); | |
481 | |
482 ASSERT_EQ(1u, frames.size()); | |
483 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
484 EXPECT_TRUE(frames[0]->header.final); | |
485 EXPECT_FALSE(frames[0]->header.reserved1); | |
486 EXPECT_EQ("Hello", ToString(frames[0])); | |
487 } | |
488 | |
489 TEST_F(WebSocketDeflateStreamTest, | |
490 ReadCompressedFrameFragmentImmediatelyButInflaterReturnsPending) { | |
491 ScopedVector<WebSocketFrame> frames_to_output; | |
492 const std::string data1("\xf2", 1); | |
493 const std::string data2("\x48\xcd\xc9\xc9\x07\x00", 6); | |
494 AppendTo(&frames_to_output, | |
495 WebSocketFrameHeader::kOpCodeText, | |
496 kReserved1, | |
497 data1); | |
498 ReadFramesStub stub1(OK, &frames_to_output), stub2(ERR_IO_PENDING); | |
499 MockCallback mock_callback, checkpoint; | |
500 CompletionCallback callback = | |
501 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); | |
502 ScopedVector<WebSocketFrame> frames; | |
503 | |
504 { | |
505 InSequence s; | |
506 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
507 .WillOnce(Invoke(&stub1, &ReadFramesStub::Call)) | |
508 .WillOnce(Invoke(&stub2, &ReadFramesStub::Call)); | |
509 EXPECT_CALL(checkpoint, Call(0)); | |
510 EXPECT_CALL(mock_callback, Call(OK)); | |
511 } | |
512 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback)); | |
513 ASSERT_EQ(0u, frames.size()); | |
514 | |
515 AppendTo(stub2.frames_passed(), | |
516 WebSocketFrameHeader::kOpCodeText, | |
517 kFinal, | |
518 data2); | |
519 | |
520 checkpoint.Call(0); | |
521 stub2.callback().Run(OK); | |
522 | |
523 ASSERT_EQ(1u, frames.size()); | |
524 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
525 EXPECT_TRUE(frames[0]->header.final); | |
526 EXPECT_FALSE(frames[0]->header.reserved1); | |
527 EXPECT_EQ("Hello", ToString(frames[0])); | |
528 } | |
529 | |
530 TEST_F(WebSocketDeflateStreamTest, ReadInvalidCompressedPayload) { | |
531 const std::string data("\xf2\x48\xcdINVALID", 10); | |
532 ScopedVector<WebSocketFrame> frames_to_output; | |
533 AppendTo(&frames_to_output, | |
534 WebSocketFrameHeader::kOpCodeText, | |
535 kFinal | kReserved1, | |
536 data); | |
537 ReadFramesStub stub(OK, &frames_to_output); | |
538 CompletionCallback callback; | |
539 ScopedVector<WebSocketFrame> frames; | |
540 | |
541 { | |
542 InSequence s; | |
543 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
544 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
545 } | |
546 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR, | |
547 deflate_stream_->ReadFrames(&frames, callback)); | |
548 ASSERT_EQ(0u, frames.size()); | |
549 } | |
550 | |
551 TEST_F(WebSocketDeflateStreamTest, MergeMultipleFramesInReadFrames) { | |
552 const std::string data1("\xf2\x48\xcd", 3); | |
553 const std::string data2("\xc9\xc9\x07\x00", 4); | |
554 ScopedVector<WebSocketFrame> frames_to_output; | |
555 AppendTo(&frames_to_output, | |
556 WebSocketFrameHeader::kOpCodeText, | |
557 kReserved1, | |
558 data1); | |
559 AppendTo(&frames_to_output, | |
560 WebSocketFrameHeader::kOpCodeContinuation, | |
561 kFinal, | |
562 data2); | |
563 ReadFramesStub stub(OK, &frames_to_output); | |
564 CompletionCallback callback; | |
565 ScopedVector<WebSocketFrame> frames; | |
566 | |
567 { | |
568 InSequence s; | |
569 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
570 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
571 } | |
572 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
573 ASSERT_EQ(1u, frames.size()); | |
574 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
575 EXPECT_TRUE(frames[0]->header.final); | |
576 EXPECT_FALSE(frames[0]->header.reserved1); | |
577 EXPECT_EQ("Hello", ToString(frames[0])); | |
578 } | |
579 | |
580 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedEmptyFrames) { | |
581 ScopedVector<WebSocketFrame> frames_to_output; | |
582 AppendTo(&frames_to_output, | |
583 WebSocketFrameHeader::kOpCodeText, | |
584 kNoFlag); | |
585 AppendTo(&frames_to_output, | |
586 WebSocketFrameHeader::kOpCodeContinuation, | |
587 kFinal); | |
588 ReadFramesStub stub(OK, &frames_to_output); | |
589 CompletionCallback callback; | |
590 ScopedVector<WebSocketFrame> frames; | |
591 | |
592 { | |
593 InSequence s; | |
594 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
595 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
596 } | |
597 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
598 ASSERT_EQ(2u, frames.size()); | |
599 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
600 EXPECT_FALSE(frames[0]->header.final); | |
601 EXPECT_FALSE(frames[0]->header.reserved1); | |
602 EXPECT_EQ("", ToString(frames[0])); | |
603 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, | |
604 frames[1]->header.opcode); | |
605 EXPECT_TRUE(frames[1]->header.final); | |
606 EXPECT_FALSE(frames[1]->header.reserved1); | |
607 EXPECT_EQ("", ToString(frames[1])); | |
608 } | |
609 | |
610 TEST_F(WebSocketDeflateStreamTest, ReadCompressedEmptyFrames) { | |
611 ScopedVector<WebSocketFrame> frames_to_output; | |
612 AppendTo(&frames_to_output, | |
613 WebSocketFrameHeader::kOpCodeText, | |
614 kReserved1, | |
615 std::string("\x02\x00", 1)); | |
616 AppendTo(&frames_to_output, | |
617 WebSocketFrameHeader::kOpCodeContinuation, | |
618 kFinal); | |
619 ReadFramesStub stub(OK, &frames_to_output); | |
620 CompletionCallback callback; | |
621 ScopedVector<WebSocketFrame> frames; | |
622 | |
623 { | |
624 InSequence s; | |
625 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
626 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
627 } | |
628 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
629 ASSERT_EQ(1u, frames.size()); | |
630 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
631 EXPECT_TRUE(frames[0]->header.final); | |
632 EXPECT_FALSE(frames[0]->header.reserved1); | |
633 EXPECT_EQ("", ToString(frames[0])); | |
634 } | |
635 | |
636 TEST_F(WebSocketDeflateStreamTest, | |
637 ReadCompressedFrameFollowedByEmptyFrame) { | |
638 const std::string data("\xf2\x48\xcd\xc9\xc9\x07\x00", 7); | |
639 ScopedVector<WebSocketFrame> frames_to_output; | |
640 AppendTo(&frames_to_output, | |
641 WebSocketFrameHeader::kOpCodeText, | |
642 kReserved1, | |
643 data); | |
644 AppendTo(&frames_to_output, | |
645 WebSocketFrameHeader::kOpCodeContinuation, | |
646 kFinal); | |
647 ReadFramesStub stub(OK, &frames_to_output); | |
648 CompletionCallback callback; | |
649 ScopedVector<WebSocketFrame> frames; | |
650 | |
651 { | |
652 InSequence s; | |
653 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
654 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
655 } | |
656 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
657 ASSERT_EQ(1u, frames.size()); | |
658 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
659 EXPECT_TRUE(frames[0]->header.final); | |
660 EXPECT_FALSE(frames[0]->header.reserved1); | |
661 EXPECT_EQ("Hello", ToString(frames[0])); | |
662 } | |
663 | |
664 TEST_F(WebSocketDeflateStreamTest, ReadControlFrameBetweenDataFrames) { | |
665 const std::string data1("\xf2\x48\xcd", 3); | |
666 const std::string data2("\xc9\xc9\x07\x00", 4); | |
667 ScopedVector<WebSocketFrame> frames_to_output; | |
668 AppendTo(&frames_to_output, | |
669 WebSocketFrameHeader::kOpCodeText, | |
670 kReserved1, | |
671 data1); | |
672 AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodePing, kFinal); | |
673 AppendTo(&frames_to_output, WebSocketFrameHeader::kOpCodeText, kFinal, data2); | |
674 ReadFramesStub stub(OK, &frames_to_output); | |
675 CompletionCallback callback; | |
676 ScopedVector<WebSocketFrame> frames; | |
677 | |
678 { | |
679 InSequence s; | |
680 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
681 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
682 } | |
683 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
684 ASSERT_EQ(2u, frames.size()); | |
685 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames[0]->header.opcode); | |
686 EXPECT_TRUE(frames[0]->header.final); | |
687 EXPECT_FALSE(frames[0]->header.reserved1); | |
688 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode); | |
689 EXPECT_TRUE(frames[1]->header.final); | |
690 EXPECT_FALSE(frames[1]->header.reserved1); | |
691 EXPECT_EQ("Hello", ToString(frames[1])); | |
692 } | |
693 | |
694 TEST_F(WebSocketDeflateStreamTest, SplitToMultipleFramesInReadFrames) { | |
695 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT); | |
696 deflater.Initialize(kWindowBits); | |
697 const size_t kSize = kChunkSize * 3; | |
698 const std::string original_data(kSize, 'a'); | |
699 deflater.AddBytes(original_data.data(), original_data.size()); | |
700 deflater.Finish(); | |
701 | |
702 ScopedVector<WebSocketFrame> frames_to_output; | |
703 AppendTo(&frames_to_output, | |
704 WebSocketFrameHeader::kOpCodeBinary, | |
705 kFinal | kReserved1, | |
706 ToString(deflater.GetOutput(deflater.CurrentOutputSize()))); | |
707 | |
708 ReadFramesStub stub(OK, &frames_to_output); | |
709 CompletionCallback callback; | |
710 ScopedVector<WebSocketFrame> frames; | |
711 { | |
712 InSequence s; | |
713 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
714 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
715 } | |
716 | |
717 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
718 ASSERT_EQ(3u, frames.size()); | |
719 EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode); | |
720 EXPECT_FALSE(frames[0]->header.final); | |
721 EXPECT_FALSE(frames[0]->header.reserved1); | |
722 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[0]->header.payload_length)); | |
723 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, | |
724 frames[1]->header.opcode); | |
725 EXPECT_FALSE(frames[1]->header.final); | |
726 EXPECT_FALSE(frames[1]->header.reserved1); | |
727 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[1]->header.payload_length)); | |
728 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, | |
729 frames[2]->header.opcode); | |
730 EXPECT_TRUE(frames[2]->header.final); | |
731 EXPECT_FALSE(frames[2]->header.reserved1); | |
732 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[2]->header.payload_length)); | |
733 EXPECT_EQ(original_data, | |
734 ToString(frames[0]) + ToString(frames[1]) + ToString(frames[2])); | |
735 } | |
736 | |
737 TEST_F(WebSocketDeflateStreamTest, InflaterInternalDataCanBeEmpty) { | |
738 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT); | |
739 deflater.Initialize(kWindowBits); | |
740 const std::string original_data(kChunkSize, 'a'); | |
741 deflater.AddBytes(original_data.data(), original_data.size()); | |
742 deflater.Finish(); | |
743 | |
744 ScopedVector<WebSocketFrame> frames_to_output; | |
745 AppendTo(&frames_to_output, | |
746 WebSocketFrameHeader::kOpCodeBinary, | |
747 kReserved1, | |
748 ToString(deflater.GetOutput(deflater.CurrentOutputSize()))); | |
749 AppendTo(&frames_to_output, | |
750 WebSocketFrameHeader::kOpCodeBinary, | |
751 kFinal, | |
752 ""); | |
753 | |
754 ReadFramesStub stub(OK, &frames_to_output); | |
755 CompletionCallback callback; | |
756 ScopedVector<WebSocketFrame> frames; | |
757 { | |
758 InSequence s; | |
759 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
760 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
761 } | |
762 | |
763 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
764 ASSERT_EQ(2u, frames.size()); | |
765 EXPECT_EQ(WebSocketFrameHeader::kOpCodeBinary, frames[0]->header.opcode); | |
766 EXPECT_FALSE(frames[0]->header.final); | |
767 EXPECT_FALSE(frames[0]->header.reserved1); | |
768 EXPECT_EQ(kChunkSize, static_cast<size_t>(frames[0]->header.payload_length)); | |
769 | |
770 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, | |
771 frames[1]->header.opcode); | |
772 EXPECT_TRUE(frames[1]->header.final); | |
773 EXPECT_FALSE(frames[1]->header.reserved1); | |
774 EXPECT_EQ(0u, static_cast<size_t>(frames[1]->header.payload_length)); | |
775 EXPECT_EQ(original_data, ToString(frames[0]) + ToString(frames[1])); | |
776 } | |
777 | |
778 TEST_F(WebSocketDeflateStreamTest, | |
779 Reserved1TurnsOnDuringReadingCompressedContinuationFrame) { | |
780 const std::string data1("\xf2\x48\xcd", 3); | |
781 const std::string data2("\xc9\xc9\x07\x00", 4); | |
782 ScopedVector<WebSocketFrame> frames_to_output; | |
783 AppendTo(&frames_to_output, | |
784 WebSocketFrameHeader::kOpCodeText, | |
785 kReserved1, | |
786 data1); | |
787 AppendTo(&frames_to_output, | |
788 WebSocketFrameHeader::kOpCodeContinuation, | |
789 kFinal | kReserved1, | |
790 data2); | |
791 ReadFramesStub stub(OK, &frames_to_output); | |
792 CompletionCallback callback; | |
793 ScopedVector<WebSocketFrame> frames; | |
794 | |
795 { | |
796 InSequence s; | |
797 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
798 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
799 } | |
800 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR, | |
801 deflate_stream_->ReadFrames(&frames, callback)); | |
802 } | |
803 | |
804 TEST_F(WebSocketDeflateStreamTest, | |
805 Reserved1TurnsOnDuringReadingUncompressedContinuationFrame) { | |
806 ScopedVector<WebSocketFrame> frames_to_output; | |
807 AppendTo(&frames_to_output, | |
808 WebSocketFrameHeader::kOpCodeText, | |
809 kNoFlag, | |
810 "hello"); | |
811 AppendTo(&frames_to_output, | |
812 WebSocketFrameHeader::kOpCodeContinuation, | |
813 kFinal | kReserved1, | |
814 "world"); | |
815 ReadFramesStub stub(OK, &frames_to_output); | |
816 CompletionCallback callback; | |
817 ScopedVector<WebSocketFrame> frames; | |
818 | |
819 { | |
820 InSequence s; | |
821 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
822 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
823 } | |
824 ASSERT_EQ(ERR_WS_PROTOCOL_ERROR, | |
825 deflate_stream_->ReadFrames(&frames, callback)); | |
826 } | |
827 | |
828 TEST_F(WebSocketDeflateStreamTest, ReadCompressedMessages) { | |
829 ScopedVector<WebSocketFrame> frames_to_output; | |
830 AppendTo(&frames_to_output, | |
831 WebSocketFrameHeader::kOpCodeText, | |
832 kFinal | kReserved1, | |
833 std::string( | |
834 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x31\x04\x00", 13)); | |
835 AppendTo(&frames_to_output, | |
836 WebSocketFrameHeader::kOpCodeText, | |
837 kFinal | kReserved1, | |
838 std::string("\x4a\x86\x33\x8d\x00\x00", 6)); | |
839 ReadFramesStub stub(OK, &frames_to_output); | |
840 CompletionCallback callback; | |
841 ScopedVector<WebSocketFrame> frames; | |
842 | |
843 { | |
844 InSequence s; | |
845 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
846 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
847 } | |
848 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
849 ASSERT_EQ(2u, frames.size()); | |
850 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
851 EXPECT_TRUE(frames[0]->header.final); | |
852 EXPECT_FALSE(frames[0]->header.reserved1); | |
853 EXPECT_EQ("compressed1", ToString(frames[0])); | |
854 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode); | |
855 EXPECT_TRUE(frames[1]->header.final); | |
856 EXPECT_FALSE(frames[1]->header.reserved1); | |
857 EXPECT_EQ("compressed2", ToString(frames[1])); | |
858 } | |
859 | |
860 TEST_F(WebSocketDeflateStreamTest, ReadUncompressedMessages) { | |
861 ScopedVector<WebSocketFrame> frames_to_output; | |
862 AppendTo(&frames_to_output, | |
863 WebSocketFrameHeader::kOpCodeText, | |
864 kFinal, | |
865 "uncompressed1"); | |
866 AppendTo(&frames_to_output, | |
867 WebSocketFrameHeader::kOpCodeText, | |
868 kFinal, | |
869 "uncompressed2"); | |
870 ReadFramesStub stub(OK, &frames_to_output); | |
871 CompletionCallback callback; | |
872 ScopedVector<WebSocketFrame> frames; | |
873 | |
874 { | |
875 InSequence s; | |
876 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
877 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
878 } | |
879 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
880 ASSERT_EQ(2u, frames.size()); | |
881 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
882 EXPECT_TRUE(frames[0]->header.final); | |
883 EXPECT_FALSE(frames[0]->header.reserved1); | |
884 EXPECT_EQ("uncompressed1", ToString(frames[0])); | |
885 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode); | |
886 EXPECT_TRUE(frames[1]->header.final); | |
887 EXPECT_FALSE(frames[1]->header.reserved1); | |
888 EXPECT_EQ("uncompressed2", ToString(frames[1])); | |
889 } | |
890 | |
891 TEST_F(WebSocketDeflateStreamTest, | |
892 ReadCompressedMessageThenUncompressedMessage) { | |
893 ScopedVector<WebSocketFrame> frames_to_output; | |
894 AppendTo(&frames_to_output, | |
895 WebSocketFrameHeader::kOpCodeText, | |
896 kFinal | kReserved1, | |
897 std::string( | |
898 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12)); | |
899 AppendTo(&frames_to_output, | |
900 WebSocketFrameHeader::kOpCodeText, | |
901 kFinal, | |
902 "uncompressed"); | |
903 ReadFramesStub stub(OK, &frames_to_output); | |
904 CompletionCallback callback; | |
905 ScopedVector<WebSocketFrame> frames; | |
906 | |
907 { | |
908 InSequence s; | |
909 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
910 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
911 } | |
912 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
913 ASSERT_EQ(2u, frames.size()); | |
914 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
915 EXPECT_TRUE(frames[0]->header.final); | |
916 EXPECT_FALSE(frames[0]->header.reserved1); | |
917 EXPECT_EQ("compressed", ToString(frames[0])); | |
918 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode); | |
919 EXPECT_TRUE(frames[1]->header.final); | |
920 EXPECT_FALSE(frames[1]->header.reserved1); | |
921 EXPECT_EQ("uncompressed", ToString(frames[1])); | |
922 } | |
923 | |
924 TEST_F(WebSocketDeflateStreamTest, | |
925 ReadUncompressedMessageThenCompressedMessage) { | |
926 ScopedVector<WebSocketFrame> frames_to_output; | |
927 AppendTo(&frames_to_output, | |
928 WebSocketFrameHeader::kOpCodeText, | |
929 kFinal, | |
930 "uncompressed"); | |
931 AppendTo(&frames_to_output, | |
932 WebSocketFrameHeader::kOpCodeText, | |
933 kFinal | kReserved1, | |
934 std::string( | |
935 "\x4a\xce\xcf\x2d\x28\x4a\x2d\x2e\x4e\x4d\x01\x00", 12)); | |
936 ReadFramesStub stub(OK, &frames_to_output); | |
937 CompletionCallback callback; | |
938 ScopedVector<WebSocketFrame> frames; | |
939 | |
940 { | |
941 InSequence s; | |
942 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
943 .WillOnce(Invoke(&stub, &ReadFramesStub::Call)); | |
944 } | |
945 ASSERT_EQ(OK, deflate_stream_->ReadFrames(&frames, callback)); | |
946 ASSERT_EQ(2u, frames.size()); | |
947 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
948 EXPECT_TRUE(frames[0]->header.final); | |
949 EXPECT_FALSE(frames[0]->header.reserved1); | |
950 EXPECT_EQ("uncompressed", ToString(frames[0])); | |
951 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[1]->header.opcode); | |
952 EXPECT_TRUE(frames[1]->header.final); | |
953 EXPECT_FALSE(frames[1]->header.reserved1); | |
954 EXPECT_EQ("compressed", ToString(frames[1])); | |
955 } | |
956 | |
957 // This is a regression test for crbug.com/343506. | |
958 TEST_F(WebSocketDeflateStreamTest, ReadEmptyAsyncFrame) { | |
959 ScopedVector<ReadFramesStub> stub_vector; | |
960 stub_vector.push_back(new ReadFramesStub(ERR_IO_PENDING)); | |
961 stub_vector.push_back(new ReadFramesStub(ERR_IO_PENDING)); | |
962 MockCallback mock_callback; | |
963 CompletionCallback callback = | |
964 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); | |
965 ScopedVector<WebSocketFrame> frames; | |
966 | |
967 { | |
968 InSequence s; | |
969 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
970 .WillOnce(Invoke(stub_vector[0], &ReadFramesStub::Call)); | |
971 | |
972 EXPECT_CALL(*mock_stream_, ReadFrames(&frames, _)) | |
973 .WillOnce(Invoke(stub_vector[1], &ReadFramesStub::Call)); | |
974 | |
975 EXPECT_CALL(mock_callback, Call(OK)); | |
976 } | |
977 | |
978 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->ReadFrames(&frames, callback)); | |
979 AppendTo(stub_vector[0]->frames_passed(), | |
980 WebSocketFrameHeader::kOpCodeText, | |
981 kReserved1, | |
982 std::string()); | |
983 stub_vector[0]->callback().Run(OK); | |
984 AppendTo(stub_vector[1]->frames_passed(), | |
985 WebSocketFrameHeader::kOpCodeContinuation, | |
986 kFinal, | |
987 std::string("\x02\x00")); | |
988 stub_vector[1]->callback().Run(OK); | |
989 ASSERT_EQ(1u, frames.size()); | |
990 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames[0]->header.opcode); | |
991 EXPECT_EQ("", ToString(frames[0])); | |
992 } | |
993 | |
994 TEST_F(WebSocketDeflateStreamTest, WriteEmpty) { | |
995 ScopedVector<WebSocketFrame> frames; | |
996 CompletionCallback callback; | |
997 { | |
998 InSequence s; | |
999 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)).Times(0); | |
1000 } | |
1001 EXPECT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); | |
1002 } | |
1003 | |
1004 TEST_F(WebSocketDeflateStreamTest, WriteFailedImmediately) { | |
1005 ScopedVector<WebSocketFrame> frames; | |
1006 CompletionCallback callback; | |
1007 { | |
1008 InSequence s; | |
1009 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) | |
1010 .WillOnce(Return(ERR_FAILED)); | |
1011 } | |
1012 | |
1013 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "hello"); | |
1014 predictor_->AddFramesToBeInput(frames); | |
1015 EXPECT_EQ(ERR_FAILED, deflate_stream_->WriteFrames(&frames, callback)); | |
1016 predictor_->Clear(); | |
1017 } | |
1018 | |
1019 TEST_F(WebSocketDeflateStreamTest, WriteFrameImmediately) { | |
1020 ScopedVector<WebSocketFrame> frames; | |
1021 CompletionCallback callback; | |
1022 WriteFramesStub stub(predictor_, OK); | |
1023 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); | |
1024 predictor_->AddFramesToBeInput(frames); | |
1025 { | |
1026 InSequence s; | |
1027 EXPECT_CALL(*mock_stream_, WriteFrames(_, _)) | |
1028 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); | |
1029 } | |
1030 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); | |
1031 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); | |
1032 ASSERT_EQ(1u, frames_passed.size()); | |
1033 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); | |
1034 EXPECT_TRUE(frames_passed[0]->header.final); | |
1035 EXPECT_TRUE(frames_passed[0]->header.reserved1); | |
1036 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), | |
1037 ToString(frames_passed[0])); | |
1038 } | |
1039 | |
1040 TEST_F(WebSocketDeflateStreamTest, WriteFrameAsync) { | |
1041 WriteFramesStub stub(predictor_, ERR_IO_PENDING); | |
1042 MockCallback mock_callback, checkpoint; | |
1043 CompletionCallback callback = | |
1044 base::Bind(&MockCallback::Call, base::Unretained(&mock_callback)); | |
1045 ScopedVector<WebSocketFrame> frames; | |
1046 { | |
1047 InSequence s; | |
1048 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) | |
1049 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); | |
1050 EXPECT_CALL(checkpoint, Call(0)); | |
1051 EXPECT_CALL(mock_callback, Call(OK)); | |
1052 } | |
1053 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); | |
1054 predictor_->AddFramesToBeInput(frames); | |
1055 ASSERT_EQ(ERR_IO_PENDING, deflate_stream_->WriteFrames(&frames, callback)); | |
1056 | |
1057 checkpoint.Call(0); | |
1058 stub.callback().Run(OK); | |
1059 | |
1060 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); | |
1061 ASSERT_EQ(1u, frames_passed.size()); | |
1062 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); | |
1063 EXPECT_TRUE(frames_passed[0]->header.final); | |
1064 EXPECT_TRUE(frames_passed[0]->header.reserved1); | |
1065 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), | |
1066 ToString(frames_passed[0])); | |
1067 } | |
1068 | |
1069 TEST_F(WebSocketDeflateStreamTest, WriteControlFrameBetweenDataFrames) { | |
1070 ScopedVector<WebSocketFrame> frames; | |
1071 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "Hel"); | |
1072 AppendTo(&frames, WebSocketFrameHeader::kOpCodePing, kFinal); | |
1073 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "lo"); | |
1074 predictor_->AddFramesToBeInput(frames); | |
1075 WriteFramesStub stub(predictor_, OK); | |
1076 CompletionCallback callback; | |
1077 | |
1078 { | |
1079 InSequence s; | |
1080 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) | |
1081 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); | |
1082 } | |
1083 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); | |
1084 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); | |
1085 ASSERT_EQ(2u, frames_passed.size()); | |
1086 EXPECT_EQ(WebSocketFrameHeader::kOpCodePing, frames_passed[0]->header.opcode); | |
1087 EXPECT_TRUE(frames_passed[0]->header.final); | |
1088 EXPECT_FALSE(frames_passed[0]->header.reserved1); | |
1089 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode); | |
1090 EXPECT_TRUE(frames_passed[1]->header.final); | |
1091 EXPECT_TRUE(frames_passed[1]->header.reserved1); | |
1092 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), | |
1093 ToString(frames_passed[1])); | |
1094 } | |
1095 | |
1096 TEST_F(WebSocketDeflateStreamTest, WriteEmptyMessage) { | |
1097 ScopedVector<WebSocketFrame> frames; | |
1098 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal); | |
1099 predictor_->AddFramesToBeInput(frames); | |
1100 WriteFramesStub stub(predictor_, OK); | |
1101 CompletionCallback callback; | |
1102 | |
1103 { | |
1104 InSequence s; | |
1105 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) | |
1106 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); | |
1107 } | |
1108 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); | |
1109 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); | |
1110 ASSERT_EQ(1u, frames_passed.size()); | |
1111 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); | |
1112 EXPECT_TRUE(frames_passed[0]->header.final); | |
1113 EXPECT_TRUE(frames_passed[0]->header.reserved1); | |
1114 EXPECT_EQ(std::string("\x00", 1), ToString(frames_passed[0])); | |
1115 } | |
1116 | |
1117 TEST_F(WebSocketDeflateStreamTest, WriteUncompressedMessage) { | |
1118 ScopedVector<WebSocketFrame> frames; | |
1119 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAA"); | |
1120 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AAA"); | |
1121 predictor_->AddFramesToBeInput(frames); | |
1122 WriteFramesStub stub(predictor_, OK); | |
1123 CompletionCallback callback; | |
1124 | |
1125 predictor_->set_result(WebSocketDeflatePredictor::DO_NOT_DEFLATE); | |
1126 | |
1127 { | |
1128 InSequence s; | |
1129 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) | |
1130 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); | |
1131 } | |
1132 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); | |
1133 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); | |
1134 ASSERT_EQ(2u, frames_passed.size()); | |
1135 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); | |
1136 EXPECT_FALSE(frames_passed[0]->header.final); | |
1137 EXPECT_FALSE(frames_passed[0]->header.reserved1); | |
1138 EXPECT_EQ("AAAA", ToString(frames_passed[0])); | |
1139 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, | |
1140 frames_passed[1]->header.opcode); | |
1141 EXPECT_TRUE(frames_passed[1]->header.final); | |
1142 EXPECT_FALSE(frames_passed[1]->header.reserved1); | |
1143 EXPECT_EQ("AAA", ToString(frames_passed[1])); | |
1144 } | |
1145 | |
1146 TEST_F(WebSocketDeflateStreamTest, LargeDeflatedFramesShouldBeSplit) { | |
1147 WebSocketDeflater deflater(WebSocketDeflater::TAKE_OVER_CONTEXT); | |
1148 LinearCongruentialGenerator lcg(133); | |
1149 WriteFramesStub stub(predictor_, OK); | |
1150 CompletionCallback callback; | |
1151 const size_t size = 1024; | |
1152 | |
1153 { | |
1154 InSequence s; | |
1155 EXPECT_CALL(*mock_stream_, WriteFrames(_, _)) | |
1156 .WillRepeatedly(Invoke(&stub, &WriteFramesStub::Call)); | |
1157 } | |
1158 ScopedVector<WebSocketFrame> total_compressed_frames; | |
1159 | |
1160 deflater.Initialize(kWindowBits); | |
1161 while (true) { | |
1162 bool is_final = (total_compressed_frames.size() >= 2); | |
1163 ScopedVector<WebSocketFrame> frames; | |
1164 std::string data; | |
1165 for (size_t i = 0; i < size; ++i) | |
1166 data += static_cast<char>(lcg.Generate()); | |
1167 deflater.AddBytes(data.data(), data.size()); | |
1168 FrameFlag flag = is_final ? kFinal : kNoFlag; | |
1169 AppendTo(&frames, WebSocketFrameHeader::kOpCodeBinary, flag, data); | |
1170 predictor_->AddFramesToBeInput(frames); | |
1171 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); | |
1172 total_compressed_frames.insert(total_compressed_frames.end(), | |
1173 stub.frames()->begin(), | |
1174 stub.frames()->end()); | |
1175 stub.frames()->weak_clear(); | |
1176 if (is_final) | |
1177 break; | |
1178 } | |
1179 deflater.Finish(); | |
1180 std::string total_deflated; | |
1181 for (size_t i = 0; i < total_compressed_frames.size(); ++i) { | |
1182 WebSocketFrame* frame = total_compressed_frames[i]; | |
1183 const WebSocketFrameHeader& header = frame->header; | |
1184 if (i > 0) { | |
1185 EXPECT_EQ(header.kOpCodeContinuation, header.opcode); | |
1186 EXPECT_FALSE(header.reserved1); | |
1187 } else { | |
1188 EXPECT_EQ(header.kOpCodeBinary, header.opcode); | |
1189 EXPECT_TRUE(header.reserved1); | |
1190 } | |
1191 const bool is_final_frame = (i + 1 == total_compressed_frames.size()); | |
1192 EXPECT_EQ(is_final_frame, header.final); | |
1193 if (!is_final_frame) | |
1194 EXPECT_GT(header.payload_length, 0ul); | |
1195 total_deflated += ToString(frame); | |
1196 } | |
1197 EXPECT_EQ(total_deflated, | |
1198 ToString(deflater.GetOutput(deflater.CurrentOutputSize()))); | |
1199 } | |
1200 | |
1201 TEST_F(WebSocketDeflateStreamTest, WriteMultipleMessages) { | |
1202 ScopedVector<WebSocketFrame> frames; | |
1203 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); | |
1204 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); | |
1205 predictor_->AddFramesToBeInput(frames); | |
1206 WriteFramesStub stub(predictor_, OK); | |
1207 CompletionCallback callback; | |
1208 | |
1209 { | |
1210 InSequence s; | |
1211 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) | |
1212 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); | |
1213 } | |
1214 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); | |
1215 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); | |
1216 ASSERT_EQ(2u, frames_passed.size()); | |
1217 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); | |
1218 EXPECT_TRUE(frames_passed[0]->header.final); | |
1219 EXPECT_TRUE(frames_passed[0]->header.reserved1); | |
1220 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), | |
1221 ToString(frames_passed[0])); | |
1222 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode); | |
1223 EXPECT_TRUE(frames_passed[1]->header.final); | |
1224 EXPECT_TRUE(frames_passed[1]->header.reserved1); | |
1225 EXPECT_EQ(std::string("\xf2\x00\x11\x00\x00", 5), ToString(frames_passed[1])); | |
1226 } | |
1227 | |
1228 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest, | |
1229 WriteMultipleMessages) { | |
1230 ScopedVector<WebSocketFrame> frames; | |
1231 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); | |
1232 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kFinal, "Hello"); | |
1233 predictor_->AddFramesToBeInput(frames); | |
1234 WriteFramesStub stub(predictor_, OK); | |
1235 CompletionCallback callback; | |
1236 | |
1237 { | |
1238 InSequence s; | |
1239 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) | |
1240 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); | |
1241 } | |
1242 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); | |
1243 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); | |
1244 ASSERT_EQ(2u, frames_passed.size()); | |
1245 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); | |
1246 EXPECT_TRUE(frames_passed[0]->header.final); | |
1247 EXPECT_TRUE(frames_passed[0]->header.reserved1); | |
1248 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), | |
1249 ToString(frames_passed[0])); | |
1250 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[1]->header.opcode); | |
1251 EXPECT_TRUE(frames_passed[1]->header.final); | |
1252 EXPECT_TRUE(frames_passed[1]->header.reserved1); | |
1253 EXPECT_EQ(std::string("\xf2\x48\xcd\xc9\xc9\x07\x00", 7), | |
1254 ToString(frames_passed[1])); | |
1255 } | |
1256 | |
1257 // In order to check the stream works correctly for multiple | |
1258 // "PossiblyCompressedMessage"s, we test various messages at one test case. | |
1259 TEST_F(WebSocketDeflateStreamWithDoNotTakeOverContextTest, | |
1260 WritePossiblyCompressMessages) { | |
1261 ScopedVector<WebSocketFrame> frames; | |
1262 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "He"); | |
1263 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "llo"); | |
1264 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "AAAAAAAAAA"); | |
1265 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "AA"); | |
1266 AppendTo(&frames, WebSocketFrameHeader::kOpCodeText, kNoFlag, "XX"); | |
1267 AppendTo(&frames, WebSocketFrameHeader::kOpCodeContinuation, kFinal, "YY"); | |
1268 predictor_->AddFramesToBeInput(frames); | |
1269 WriteFramesStub stub(predictor_, OK); | |
1270 CompletionCallback callback; | |
1271 predictor_->set_result(WebSocketDeflatePredictor::TRY_DEFLATE); | |
1272 | |
1273 { | |
1274 InSequence s; | |
1275 EXPECT_CALL(*mock_stream_, WriteFrames(&frames, _)) | |
1276 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); | |
1277 } | |
1278 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames, callback)); | |
1279 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); | |
1280 ASSERT_EQ(5u, frames_passed.size()); | |
1281 | |
1282 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[0]->header.opcode); | |
1283 EXPECT_FALSE(frames_passed[0]->header.final); | |
1284 EXPECT_FALSE(frames_passed[0]->header.reserved1); | |
1285 EXPECT_EQ("He", ToString(frames_passed[0])); | |
1286 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, | |
1287 frames_passed[1]->header.opcode); | |
1288 EXPECT_TRUE(frames_passed[1]->header.final); | |
1289 EXPECT_FALSE(frames_passed[1]->header.reserved1); | |
1290 EXPECT_EQ("llo", ToString(frames_passed[1])); | |
1291 | |
1292 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[2]->header.opcode); | |
1293 EXPECT_TRUE(frames_passed[2]->header.final); | |
1294 EXPECT_TRUE(frames_passed[2]->header.reserved1); | |
1295 EXPECT_EQ(std::string("\x72\x74\x44\x00\x00\x00", 6), | |
1296 ToString(frames_passed[2])); | |
1297 | |
1298 EXPECT_EQ(WebSocketFrameHeader::kOpCodeText, frames_passed[3]->header.opcode); | |
1299 EXPECT_FALSE(frames_passed[3]->header.final); | |
1300 EXPECT_FALSE(frames_passed[3]->header.reserved1); | |
1301 EXPECT_EQ("XX", ToString(frames_passed[3])); | |
1302 EXPECT_EQ(WebSocketFrameHeader::kOpCodeContinuation, | |
1303 frames_passed[4]->header.opcode); | |
1304 EXPECT_TRUE(frames_passed[4]->header.final); | |
1305 EXPECT_FALSE(frames_passed[4]->header.reserved1); | |
1306 EXPECT_EQ("YY", ToString(frames_passed[4])); | |
1307 } | |
1308 | |
1309 // This is based on the similar test from websocket_deflater_test.cc | |
1310 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits8) { | |
1311 SetUpWithWindowBits(8); | |
1312 CompletionCallback callback; | |
1313 AddCompressibleFrameString(); | |
1314 WriteFramesStub stub(predictor_, OK); | |
1315 { | |
1316 InSequence s; | |
1317 EXPECT_CALL(*mock_stream_, WriteFrames(_, _)) | |
1318 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); | |
1319 } | |
1320 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames_, callback)); | |
1321 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); | |
1322 ASSERT_EQ(1u, frames_passed.size()); | |
1323 EXPECT_EQ(std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x39\xa3" | |
1324 "(?7\xb3\x34\x17\x00", 21), | |
1325 ToString(frames_passed[0])); | |
1326 } | |
1327 | |
1328 // The same input with window_bits=10 returns smaller output. | |
1329 TEST_F(WebSocketDeflateStreamWithClientWindowBitsTest, WindowBits10) { | |
1330 SetUpWithWindowBits(10); | |
1331 CompletionCallback callback; | |
1332 AddCompressibleFrameString(); | |
1333 WriteFramesStub stub(predictor_, OK); | |
1334 { | |
1335 InSequence s; | |
1336 EXPECT_CALL(*mock_stream_, WriteFrames(_, _)) | |
1337 .WillOnce(Invoke(&stub, &WriteFramesStub::Call)); | |
1338 } | |
1339 ASSERT_EQ(OK, deflate_stream_->WriteFrames(&frames_, callback)); | |
1340 const ScopedVector<WebSocketFrame>& frames_passed = *stub.frames(); | |
1341 ASSERT_EQ(1u, frames_passed.size()); | |
1342 EXPECT_EQ( | |
1343 std::string("r\xce(\xca\xcf\xcd,\xcdM\x1c\xe1\xc0\x19\x1a\x0e\0\0", 17), | |
1344 ToString(frames_passed[0])); | |
1345 } | |
1346 | |
1347 } // namespace | |
1348 | |
1349 } // namespace net | |
OLD | NEW |