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.
5 #include "net/websockets/websocket_channel.h"
14 #include "base/bind.h"
15 #include "base/bind_helpers.h"
16 #include "base/callback.h"
17 #include "base/location.h"
18 #include "base/memory/scoped_ptr.h"
19 #include "base/memory/scoped_vector.h"
20 #include "base/memory/weak_ptr.h"
21 #include "base/message_loop/message_loop.h"
22 #include "base/strings/string_piece.h"
23 #include "net/base/net_errors.h"
24 #include "net/base/test_completion_callback.h"
25 #include "net/http/http_response_headers.h"
26 #include "net/url_request/url_request_context.h"
27 #include "net/websockets/websocket_errors.h"
28 #include "net/websockets/websocket_event_interface.h"
29 #include "net/websockets/websocket_handshake_request_info.h"
30 #include "net/websockets/websocket_handshake_response_info.h"
31 #include "net/websockets/websocket_mux.h"
32 #include "testing/gmock/include/gmock/gmock.h"
33 #include "testing/gtest/include/gtest/gtest.h"
35 #include "url/origin.h"
37 // Hacky macros to construct the body of a Close message from a code and a
38 // string, while ensuring the result is a compile-time constant string.
39 // Use like CLOSE_DATA(NORMAL_CLOSURE, "Explanation String")
40 #define CLOSE_DATA(code, string) WEBSOCKET_CLOSE_CODE_AS_STRING_##code string
41 #define WEBSOCKET_CLOSE_CODE_AS_STRING_NORMAL_CLOSURE "\x03\xe8"
42 #define WEBSOCKET_CLOSE_CODE_AS_STRING_GOING_AWAY "\x03\xe9"
43 #define WEBSOCKET_CLOSE_CODE_AS_STRING_PROTOCOL_ERROR "\x03\xea"
44 #define WEBSOCKET_CLOSE_CODE_AS_STRING_ABNORMAL_CLOSURE "\x03\xee"
45 #define WEBSOCKET_CLOSE_CODE_AS_STRING_SERVER_ERROR "\x03\xf3"
49 // Printing helpers to allow GoogleMock to print frames. These are explicitly
50 // designed to look like the static initialisation format we use in these
51 // tests. They have to live in the net namespace in order to be found by
52 // GoogleMock; a nested anonymous namespace will not work.
54 std::ostream
& operator<<(std::ostream
& os
, const WebSocketFrameHeader
& header
) {
55 return os
<< (header
.final
? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", "
56 << header
.opcode
<< ", "
57 << (header
.masked
? "MASKED" : "NOT_MASKED");
60 std::ostream
& operator<<(std::ostream
& os
, const WebSocketFrame
& frame
) {
61 os
<< "{" << frame
.header
<< ", ";
63 return os
<< "\"" << base::StringPiece(frame
.data
->data(),
64 frame
.header
.payload_length
)
70 std::ostream
& operator<<(std::ostream
& os
,
71 const ScopedVector
<WebSocketFrame
>& vector
) {
74 for (ScopedVector
<WebSocketFrame
>::const_iterator it
= vector
.begin();
87 std::ostream
& operator<<(std::ostream
& os
,
88 const ScopedVector
<WebSocketFrame
>* vector
) {
89 return os
<< '&' << *vector
;
94 using ::base::TimeDelta
;
96 using ::testing::AnyNumber
;
97 using ::testing::DefaultValue
;
98 using ::testing::InSequence
;
99 using ::testing::MockFunction
;
100 using ::testing::Return
;
101 using ::testing::SaveArg
;
102 using ::testing::StrictMock
;
105 // A selection of characters that have traditionally been mangled in some
106 // environment or other, for testing 8-bit cleanliness.
107 const char kBinaryBlob
[] = {'\n', '\r', // BACKWARDS CRNL
110 '\x80', '\xFF', // NOT VALID UTF-8
111 '\x1A', // Control-Z, EOF on DOS
113 '\x04', // EOT, special for Unix terms
114 '\x1B', // ESC, often special
116 '\'', // single-quote, special in PHP
118 const size_t kBinaryBlobSize
= arraysize(kBinaryBlob
);
120 // The amount of quota a new connection gets by default.
121 // TODO(ricea): If kDefaultSendQuotaHighWaterMark changes, then this value will
122 // need to be updated.
123 const size_t kDefaultInitialQuota
= 1 << 17;
124 // The amount of bytes we need to send after the initial connection to trigger a
125 // quota refresh. TODO(ricea): Change this if kDefaultSendQuotaHighWaterMark or
126 // kDefaultSendQuotaLowWaterMark change.
127 const size_t kDefaultQuotaRefreshTrigger
= (1 << 16) + 1;
129 // TestTimeouts::tiny_timeout() is 100ms! I could run halfway around the world
130 // in that time! I would like my tests to run a bit quicker.
131 const int kVeryTinyTimeoutMillis
= 1;
133 // Enough quota to pass any test.
134 const int64 kPlentyOfQuota
= INT_MAX
;
136 typedef WebSocketEventInterface::ChannelState ChannelState
;
137 const ChannelState CHANNEL_ALIVE
= WebSocketEventInterface::CHANNEL_ALIVE
;
138 const ChannelState CHANNEL_DELETED
= WebSocketEventInterface::CHANNEL_DELETED
;
140 // This typedef mainly exists to avoid having to repeat the "NOLINT" incantation
141 // all over the place.
142 typedef StrictMock
< MockFunction
<void(int)> > Checkpoint
; // NOLINT
144 // This mock is for testing expectations about how the EventInterface is used.
145 class MockWebSocketEventInterface
: public WebSocketEventInterface
{
147 MockWebSocketEventInterface() {}
149 MOCK_METHOD3(OnAddChannelResponse
,
152 const std::string
&)); // NOLINT
153 MOCK_METHOD3(OnDataFrame
,
155 WebSocketMessageType
,
156 const std::vector
<char>&)); // NOLINT
157 MOCK_METHOD1(OnFlowControl
, ChannelState(int64
)); // NOLINT
158 MOCK_METHOD0(OnClosingHandshake
, ChannelState(void)); // NOLINT
159 MOCK_METHOD1(OnFailChannel
, ChannelState(const std::string
&)); // NOLINT
160 MOCK_METHOD3(OnDropChannel
,
161 ChannelState(bool, uint16
, const std::string
&)); // NOLINT
163 // We can't use GMock with scoped_ptr.
164 ChannelState
OnStartOpeningHandshake(
165 scoped_ptr
<WebSocketHandshakeRequestInfo
>) OVERRIDE
{
166 OnStartOpeningHandshakeCalled();
167 return CHANNEL_ALIVE
;
169 ChannelState
OnFinishOpeningHandshake(
170 scoped_ptr
<WebSocketHandshakeResponseInfo
>) OVERRIDE
{
171 OnFinishOpeningHandshakeCalled();
172 return CHANNEL_ALIVE
;
175 MOCK_METHOD0(OnStartOpeningHandshakeCalled
, void()); // NOLINT
176 MOCK_METHOD0(OnFinishOpeningHandshakeCalled
, void()); // NOLINT
179 // This fake EventInterface is for tests which need a WebSocketEventInterface
180 // implementation but are not verifying how it is used.
181 class FakeWebSocketEventInterface
: public WebSocketEventInterface
{
182 virtual ChannelState
OnAddChannelResponse(
184 const std::string
& selected_protocol
,
185 const std::string
& extensions
) OVERRIDE
{
186 return fail
? CHANNEL_DELETED
: CHANNEL_ALIVE
;
188 virtual ChannelState
OnDataFrame(bool fin
,
189 WebSocketMessageType type
,
190 const std::vector
<char>& data
) OVERRIDE
{
191 return CHANNEL_ALIVE
;
193 virtual ChannelState
OnFlowControl(int64 quota
) OVERRIDE
{
194 return CHANNEL_ALIVE
;
196 virtual ChannelState
OnClosingHandshake() OVERRIDE
{ return CHANNEL_ALIVE
; }
197 virtual ChannelState
OnFailChannel(const std::string
& message
) OVERRIDE
{
198 return CHANNEL_DELETED
;
200 virtual ChannelState
OnDropChannel(bool was_clean
,
202 const std::string
& reason
) OVERRIDE
{
203 return CHANNEL_DELETED
;
205 virtual ChannelState
OnStartOpeningHandshake(
206 scoped_ptr
<WebSocketHandshakeRequestInfo
> request
) OVERRIDE
{
207 return CHANNEL_ALIVE
;
209 virtual ChannelState
OnFinishOpeningHandshake(
210 scoped_ptr
<WebSocketHandshakeResponseInfo
> response
) OVERRIDE
{
211 return CHANNEL_ALIVE
;
215 // This fake WebSocketStream is for tests that require a WebSocketStream but are
216 // not testing the way it is used. It has minimal functionality to return
217 // the |protocol| and |extensions| that it was constructed with.
218 class FakeWebSocketStream
: public WebSocketStream
{
220 // Constructs with empty protocol and extensions.
221 FakeWebSocketStream() {}
223 // Constructs with specified protocol and extensions.
224 FakeWebSocketStream(const std::string
& protocol
,
225 const std::string
& extensions
)
226 : protocol_(protocol
), extensions_(extensions
) {}
228 virtual int ReadFrames(ScopedVector
<WebSocketFrame
>* frames
,
229 const CompletionCallback
& callback
) OVERRIDE
{
230 return ERR_IO_PENDING
;
233 virtual int WriteFrames(ScopedVector
<WebSocketFrame
>* frames
,
234 const CompletionCallback
& callback
) OVERRIDE
{
235 return ERR_IO_PENDING
;
238 virtual void Close() OVERRIDE
{}
240 // Returns the string passed to the constructor.
241 virtual std::string
GetSubProtocol() const OVERRIDE
{ return protocol_
; }
243 // Returns the string passed to the constructor.
244 virtual std::string
GetExtensions() const OVERRIDE
{ return extensions_
; }
247 // The string to return from GetSubProtocol().
248 std::string protocol_
;
250 // The string to return from GetExtensions().
251 std::string extensions_
;
254 // To make the static initialisers easier to read, we use enums rather than
256 enum IsFinal
{ NOT_FINAL_FRAME
, FINAL_FRAME
};
258 enum IsMasked
{ NOT_MASKED
, MASKED
};
260 // This is used to initialise a WebSocketFrame but is statically initialisable.
263 // Reserved fields omitted for now. Add them if you need them.
264 WebSocketFrameHeader::OpCode opcode
;
267 // Will be used to create the IOBuffer member. Can be NULL for NULL data. Is a
268 // nul-terminated string for ease-of-use. |header.payload_length| is
269 // initialised from |strlen(data)|. This means it is not 8-bit clean, but this
270 // is not an issue for test data.
271 const char* const data
;
275 std::ostream
& operator<<(std::ostream
& os
, const InitFrame
& frame
) {
276 os
<< "{" << (frame
.final
== FINAL_FRAME
? "FINAL_FRAME" : "NOT_FINAL_FRAME")
277 << ", " << frame
.opcode
<< ", "
278 << (frame
.masked
== MASKED
? "MASKED" : "NOT_MASKED") << ", ";
280 return os
<< "\"" << frame
.data
<< "\"}";
282 return os
<< "NULL}";
286 std::ostream
& operator<<(std::ostream
& os
, const InitFrame (&frames
)[N
]) {
289 for (size_t i
= 0; i
< N
; ++i
) {
300 // Convert a const array of InitFrame structs to the format used at
301 // runtime. Templated on the size of the array to save typing.
303 ScopedVector
<WebSocketFrame
> CreateFrameVector(
304 const InitFrame (&source_frames
)[N
]) {
305 ScopedVector
<WebSocketFrame
> result_frames
;
306 result_frames
.reserve(N
);
307 for (size_t i
= 0; i
< N
; ++i
) {
308 const InitFrame
& source_frame
= source_frames
[i
];
309 scoped_ptr
<WebSocketFrame
> result_frame(
310 new WebSocketFrame(source_frame
.opcode
));
311 size_t frame_length
= source_frame
.data
? strlen(source_frame
.data
) : 0;
312 WebSocketFrameHeader
& result_header
= result_frame
->header
;
313 result_header
.final
= (source_frame
.final
== FINAL_FRAME
);
314 result_header
.masked
= (source_frame
.masked
== MASKED
);
315 result_header
.payload_length
= frame_length
;
316 if (source_frame
.data
) {
317 result_frame
->data
= new IOBuffer(frame_length
);
318 memcpy(result_frame
->data
->data(), source_frame
.data
, frame_length
);
320 result_frames
.push_back(result_frame
.release());
322 return result_frames
.Pass();
325 // A GoogleMock action which can be used to respond to call to ReadFrames with
326 // some frames. Use like ReadFrames(_, _).WillOnce(ReturnFrames(&frames));
327 // |frames| is an array of InitFrame. |frames| needs to be passed by pointer
328 // because otherwise it will be treated as a pointer and the array size
329 // information will be lost.
330 ACTION_P(ReturnFrames
, source_frames
) {
331 *arg0
= CreateFrameVector(*source_frames
);
335 // The implementation of a GoogleMock matcher which can be used to compare a
336 // ScopedVector<WebSocketFrame>* against an expectation defined as an array of
337 // InitFrame objects. Although it is possible to compose built-in GoogleMock
338 // matchers to check the contents of a WebSocketFrame, the results are so
339 // unreadable that it is better to use this matcher.
341 class EqualsFramesMatcher
342 : public ::testing::MatcherInterface
<ScopedVector
<WebSocketFrame
>*> {
344 EqualsFramesMatcher(const InitFrame (*expect_frames
)[N
])
345 : expect_frames_(expect_frames
) {}
347 virtual bool MatchAndExplain(ScopedVector
<WebSocketFrame
>* actual_frames
,
348 ::testing::MatchResultListener
* listener
) const {
349 if (actual_frames
->size() != N
) {
350 *listener
<< "the vector size is " << actual_frames
->size();
353 for (size_t i
= 0; i
< N
; ++i
) {
354 const WebSocketFrame
& actual_frame
= *(*actual_frames
)[i
];
355 const InitFrame
& expected_frame
= (*expect_frames_
)[i
];
356 if (actual_frame
.header
.final
!= (expected_frame
.final
== FINAL_FRAME
)) {
357 *listener
<< "the frame is marked as "
358 << (actual_frame
.header
.final
? "" : "not ") << "final";
361 if (actual_frame
.header
.opcode
!= expected_frame
.opcode
) {
362 *listener
<< "the opcode is " << actual_frame
.header
.opcode
;
365 if (actual_frame
.header
.masked
!= (expected_frame
.masked
== MASKED
)) {
366 *listener
<< "the frame is "
367 << (actual_frame
.header
.masked
? "masked" : "not masked");
370 const size_t expected_length
=
371 expected_frame
.data
? strlen(expected_frame
.data
) : 0;
372 if (actual_frame
.header
.payload_length
!= expected_length
) {
373 *listener
<< "the payload length is "
374 << actual_frame
.header
.payload_length
;
377 if (expected_length
!= 0 &&
378 memcmp(actual_frame
.data
->data(),
380 actual_frame
.header
.payload_length
) != 0) {
381 *listener
<< "the data content differs";
388 virtual void DescribeTo(std::ostream
* os
) const {
389 *os
<< "matches " << *expect_frames_
;
392 virtual void DescribeNegationTo(std::ostream
* os
) const {
393 *os
<< "does not match " << *expect_frames_
;
397 const InitFrame (*expect_frames_
)[N
];
400 // The definition of EqualsFrames GoogleMock matcher. Unlike the ReturnFrames
401 // action, this can take the array by reference.
403 ::testing::Matcher
<ScopedVector
<WebSocketFrame
>*> EqualsFrames(
404 const InitFrame (&frames
)[N
]) {
405 return ::testing::MakeMatcher(new EqualsFramesMatcher
<N
>(&frames
));
408 // TestClosure works like TestCompletionCallback, but doesn't take an argument.
411 base::Closure
closure() { return base::Bind(callback_
.callback(), OK
); }
413 void WaitForResult() { callback_
.WaitForResult(); }
416 // Delegate to TestCompletionCallback for the implementation.
417 TestCompletionCallback callback_
;
420 // A GoogleMock action to run a Closure.
421 ACTION_P(InvokeClosure
, closure
) { closure
.Run(); }
423 // A GoogleMock action to run a Closure and return CHANNEL_DELETED.
424 ACTION_P(InvokeClosureReturnDeleted
, closure
) {
426 return WebSocketEventInterface::CHANNEL_DELETED
;
429 // A FakeWebSocketStream whose ReadFrames() function returns data.
430 class ReadableFakeWebSocketStream
: public FakeWebSocketStream
{
432 enum IsSync
{ SYNC
, ASYNC
};
434 // After constructing the object, call PrepareReadFrames() once for each
435 // time you wish it to return from the test.
436 ReadableFakeWebSocketStream() : index_(0), read_frames_pending_(false) {}
438 // Check that all the prepared responses have been consumed.
439 virtual ~ReadableFakeWebSocketStream() {
440 CHECK(index_
>= responses_
.size());
441 CHECK(!read_frames_pending_
);
444 // Prepares a fake response. Fake responses will be returned from ReadFrames()
445 // in the same order they were prepared with PrepareReadFrames() and
446 // PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will
447 // return ERR_IO_PENDING and the callback will be scheduled to run on the
448 // message loop. This requires the test case to run the message loop. If
449 // |async| is SYNC, the response will be returned synchronously. |error| is
450 // returned directly from ReadFrames() in the synchronous case, or passed to
451 // the callback in the asynchronous case. |frames| will be converted to a
452 // ScopedVector<WebSocketFrame> and copied to the pointer that was passed to
455 void PrepareReadFrames(IsSync async
,
457 const InitFrame (&frames
)[N
]) {
458 responses_
.push_back(new Response(async
, error
, CreateFrameVector(frames
)));
461 // An alternate version of PrepareReadFrames for when we need to construct
462 // the frames manually.
463 void PrepareRawReadFrames(IsSync async
,
465 ScopedVector
<WebSocketFrame
> frames
) {
466 responses_
.push_back(new Response(async
, error
, frames
.Pass()));
469 // Prepares a fake error response (ie. there is no data).
470 void PrepareReadFramesError(IsSync async
, int error
) {
471 responses_
.push_back(
472 new Response(async
, error
, ScopedVector
<WebSocketFrame
>()));
475 virtual int ReadFrames(ScopedVector
<WebSocketFrame
>* frames
,
476 const CompletionCallback
& callback
) OVERRIDE
{
477 CHECK(!read_frames_pending_
);
478 if (index_
>= responses_
.size())
479 return ERR_IO_PENDING
;
480 if (responses_
[index_
]->async
== ASYNC
) {
481 read_frames_pending_
= true;
482 base::MessageLoop::current()->PostTask(
484 base::Bind(&ReadableFakeWebSocketStream::DoCallback
,
485 base::Unretained(this),
488 return ERR_IO_PENDING
;
490 frames
->swap(responses_
[index_
]->frames
);
491 return responses_
[index_
++]->error
;
496 void DoCallback(ScopedVector
<WebSocketFrame
>* frames
,
497 const CompletionCallback
& callback
) {
498 read_frames_pending_
= false;
499 frames
->swap(responses_
[index_
]->frames
);
500 callback
.Run(responses_
[index_
++]->error
);
505 Response(IsSync async
, int error
, ScopedVector
<WebSocketFrame
> frames
)
506 : async(async
), error(error
), frames(frames
.Pass()) {}
510 ScopedVector
<WebSocketFrame
> frames
;
513 // Bad things will happen if we attempt to copy or assign |frames|.
514 DISALLOW_COPY_AND_ASSIGN(Response
);
516 ScopedVector
<Response
> responses_
;
518 // The index into the responses_ array of the next response to be returned.
521 // True when an async response from ReadFrames() is pending. This only applies
522 // to "real" async responses. Once all the prepared responses have been
523 // returned, ReadFrames() returns ERR_IO_PENDING but read_frames_pending_ is
525 bool read_frames_pending_
;
528 // A FakeWebSocketStream where writes always complete successfully and
530 class WriteableFakeWebSocketStream
: public FakeWebSocketStream
{
532 virtual int WriteFrames(ScopedVector
<WebSocketFrame
>* frames
,
533 const CompletionCallback
& callback
) OVERRIDE
{
538 // A FakeWebSocketStream where writes always fail.
539 class UnWriteableFakeWebSocketStream
: public FakeWebSocketStream
{
541 virtual int WriteFrames(ScopedVector
<WebSocketFrame
>* frames
,
542 const CompletionCallback
& callback
) OVERRIDE
{
543 return ERR_CONNECTION_RESET
;
547 // A FakeWebSocketStream which echoes any frames written back. Clears the
548 // "masked" header bit, but makes no other checks for validity. Tests using this
549 // must run the MessageLoop to receive the callback(s). If a message with opcode
550 // Close is echoed, then an ERR_CONNECTION_CLOSED is returned in the next
551 // callback. The test must do something to cause WriteFrames() to be called,
552 // otherwise the ReadFrames() callback will never be called.
553 class EchoeyFakeWebSocketStream
: public FakeWebSocketStream
{
555 EchoeyFakeWebSocketStream() : read_frames_(NULL
), done_(false) {}
557 virtual int WriteFrames(ScopedVector
<WebSocketFrame
>* frames
,
558 const CompletionCallback
& callback
) OVERRIDE
{
559 // Users of WebSocketStream will not expect the ReadFrames() callback to be
560 // called from within WriteFrames(), so post it to the message loop instead.
561 stored_frames_
.insert(stored_frames_
.end(), frames
->begin(), frames
->end());
562 frames
->weak_clear();
567 virtual int ReadFrames(ScopedVector
<WebSocketFrame
>* frames
,
568 const CompletionCallback
& callback
) OVERRIDE
{
569 read_callback_
= callback
;
570 read_frames_
= frames
;
573 return ERR_IO_PENDING
;
577 void PostCallback() {
578 base::MessageLoop::current()->PostTask(
580 base::Bind(&EchoeyFakeWebSocketStream::DoCallback
,
581 base::Unretained(this)));
586 read_callback_
.Run(ERR_CONNECTION_CLOSED
);
587 } else if (!stored_frames_
.empty()) {
588 done_
= MoveFrames(read_frames_
);
590 read_callback_
.Run(OK
);
594 // Copy the frames stored in stored_frames_ to |out|, while clearing the
595 // "masked" header bit. Returns true if a Close Frame was seen, false
597 bool MoveFrames(ScopedVector
<WebSocketFrame
>* out
) {
598 bool seen_close
= false;
599 *out
= stored_frames_
.Pass();
600 for (ScopedVector
<WebSocketFrame
>::iterator it
= out
->begin();
603 WebSocketFrameHeader
& header
= (*it
)->header
;
604 header
.masked
= false;
605 if (header
.opcode
== WebSocketFrameHeader::kOpCodeClose
)
611 ScopedVector
<WebSocketFrame
> stored_frames_
;
612 CompletionCallback read_callback_
;
613 // Owned by the caller of ReadFrames().
614 ScopedVector
<WebSocketFrame
>* read_frames_
;
615 // True if we should close the connection.
619 // A FakeWebSocketStream where writes trigger a connection reset.
620 // This differs from UnWriteableFakeWebSocketStream in that it is asynchronous
621 // and triggers ReadFrames to return a reset as well. Tests using this need to
622 // run the message loop. There are two tricky parts here:
623 // 1. Calling the write callback may call Close(), after which the read callback
624 // should not be called.
625 // 2. Calling either callback may delete the stream altogether.
626 class ResetOnWriteFakeWebSocketStream
: public FakeWebSocketStream
{
628 ResetOnWriteFakeWebSocketStream() : closed_(false), weak_ptr_factory_(this) {}
630 virtual int WriteFrames(ScopedVector
<WebSocketFrame
>* frames
,
631 const CompletionCallback
& callback
) OVERRIDE
{
632 base::MessageLoop::current()->PostTask(
634 base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed
,
635 weak_ptr_factory_
.GetWeakPtr(),
637 ERR_CONNECTION_RESET
));
638 base::MessageLoop::current()->PostTask(
640 base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed
,
641 weak_ptr_factory_
.GetWeakPtr(),
643 ERR_CONNECTION_RESET
));
644 return ERR_IO_PENDING
;
647 virtual int ReadFrames(ScopedVector
<WebSocketFrame
>* frames
,
648 const CompletionCallback
& callback
) OVERRIDE
{
649 read_callback_
= callback
;
650 return ERR_IO_PENDING
;
653 virtual void Close() OVERRIDE
{ closed_
= true; }
656 void CallCallbackUnlessClosed(const CompletionCallback
& callback
, int value
) {
661 CompletionCallback read_callback_
;
663 // An IO error can result in the socket being deleted, so we use weak pointers
664 // to ensure correct behaviour in that case.
665 base::WeakPtrFactory
<ResetOnWriteFakeWebSocketStream
> weak_ptr_factory_
;
668 // This mock is for verifying that WebSocket protocol semantics are obeyed (to
669 // the extent that they are implemented in WebSocketCommon).
670 class MockWebSocketStream
: public WebSocketStream
{
672 MOCK_METHOD2(ReadFrames
,
673 int(ScopedVector
<WebSocketFrame
>* frames
,
674 const CompletionCallback
& callback
));
675 MOCK_METHOD2(WriteFrames
,
676 int(ScopedVector
<WebSocketFrame
>* frames
,
677 const CompletionCallback
& callback
));
678 MOCK_METHOD0(Close
, void());
679 MOCK_CONST_METHOD0(GetSubProtocol
, std::string());
680 MOCK_CONST_METHOD0(GetExtensions
, std::string());
681 MOCK_METHOD0(AsWebSocketStream
, WebSocketStream
*());
684 struct ArgumentCopyingWebSocketStreamCreator
{
685 scoped_ptr
<WebSocketStreamRequest
> Create(
686 const GURL
& socket_url
,
687 const std::vector
<std::string
>& requested_subprotocols
,
688 const url::Origin
& origin
,
689 URLRequestContext
* url_request_context
,
690 const BoundNetLog
& net_log
,
691 scoped_ptr
<WebSocketStream::ConnectDelegate
> connect_delegate
) {
692 this->socket_url
= socket_url
;
693 this->requested_subprotocols
= requested_subprotocols
;
694 this->origin
= origin
;
695 this->url_request_context
= url_request_context
;
696 this->net_log
= net_log
;
697 this->connect_delegate
= connect_delegate
.Pass();
698 return make_scoped_ptr(new WebSocketStreamRequest
);
703 std::vector
<std::string
> requested_subprotocols
;
704 URLRequestContext
* url_request_context
;
706 scoped_ptr
<WebSocketStream::ConnectDelegate
> connect_delegate
;
709 // Converts a std::string to a std::vector<char>. For test purposes, it is
710 // convenient to be able to specify data as a string, but the
711 // WebSocketEventInterface requires the vector<char> type.
712 std::vector
<char> AsVector(const std::string
& s
) {
713 return std::vector
<char>(s
.begin(), s
.end());
716 // Base class for all test fixtures.
717 class WebSocketChannelTest
: public ::testing::Test
{
719 WebSocketChannelTest() : stream_(new FakeWebSocketStream
) {}
721 // Creates a new WebSocketChannel and connects it, using the settings stored
722 // in |connect_data_|.
723 void CreateChannelAndConnect() {
724 channel_
.reset(new WebSocketChannel(CreateEventInterface(),
725 &connect_data_
.url_request_context
));
726 channel_
->SendAddChannelRequestForTesting(
727 connect_data_
.socket_url
,
728 connect_data_
.requested_subprotocols
,
729 connect_data_
.origin
,
730 base::Bind(&ArgumentCopyingWebSocketStreamCreator::Create
,
731 base::Unretained(&connect_data_
.creator
)));
734 // Same as CreateChannelAndConnect(), but calls the on_success callback as
735 // well. This method is virtual so that subclasses can also set the stream.
736 virtual void CreateChannelAndConnectSuccessfully() {
737 CreateChannelAndConnect();
738 // Most tests aren't concerned with flow control from the renderer, so allow
739 // MAX_INT quota units.
740 channel_
->SendFlowControl(kPlentyOfQuota
);
741 connect_data_
.creator
.connect_delegate
->OnSuccess(stream_
.Pass());
744 // Returns a WebSocketEventInterface to be passed to the WebSocketChannel.
745 // This implementation returns a newly-created fake. Subclasses may return a
747 virtual scoped_ptr
<WebSocketEventInterface
> CreateEventInterface() {
748 return scoped_ptr
<WebSocketEventInterface
>(new FakeWebSocketEventInterface
);
751 // This method serves no other purpose than to provide a nice syntax for
752 // assigning to stream_. class T must be a subclass of WebSocketStream or you
753 // will have unpleasant compile errors.
755 void set_stream(scoped_ptr
<T
> stream
) {
756 // Since the definition of "PassAs" depends on the type T, the C++ standard
757 // requires the "template" keyword to indicate that "PassAs" should be
758 // parsed as a template method.
759 stream_
= stream
.template PassAs
<WebSocketStream
>();
762 // A struct containing the data that will be used to connect the channel.
763 // Grouped for readability.
765 ConnectData() : socket_url("ws://ws/"), origin("http://ws") {}
767 // URLRequestContext object.
768 URLRequestContext url_request_context
;
770 // URL to (pretend to) connect to.
772 // Requested protocols for the request.
773 std::vector
<std::string
> requested_subprotocols
;
774 // Origin of the request
777 // A fake WebSocketStreamCreator that just records its arguments.
778 ArgumentCopyingWebSocketStreamCreator creator
;
780 ConnectData connect_data_
;
782 // The channel we are testing. Not initialised until SetChannel() is called.
783 scoped_ptr
<WebSocketChannel
> channel_
;
785 // A mock or fake stream for tests that need one.
786 scoped_ptr
<WebSocketStream
> stream_
;
789 // enum of WebSocketEventInterface calls. These are intended to be or'd together
790 // in order to instruct WebSocketChannelDeletingTest when it should fail.
791 enum EventInterfaceCall
{
792 EVENT_ON_ADD_CHANNEL_RESPONSE
= 0x1,
793 EVENT_ON_DATA_FRAME
= 0x2,
794 EVENT_ON_FLOW_CONTROL
= 0x4,
795 EVENT_ON_CLOSING_HANDSHAKE
= 0x8,
796 EVENT_ON_FAIL_CHANNEL
= 0x10,
797 EVENT_ON_DROP_CHANNEL
= 0x20,
798 EVENT_ON_START_OPENING_HANDSHAKE
= 0x40,
799 EVENT_ON_FINISH_OPENING_HANDSHAKE
= 0x80,
802 class WebSocketChannelDeletingTest
: public WebSocketChannelTest
{
804 ChannelState
DeleteIfDeleting(EventInterfaceCall call
) {
805 if (deleting_
& call
) {
807 return CHANNEL_DELETED
;
809 return CHANNEL_ALIVE
;
814 WebSocketChannelDeletingTest()
815 : deleting_(EVENT_ON_ADD_CHANNEL_RESPONSE
| EVENT_ON_DATA_FRAME
|
816 EVENT_ON_FLOW_CONTROL
|
817 EVENT_ON_CLOSING_HANDSHAKE
|
818 EVENT_ON_FAIL_CHANNEL
|
819 EVENT_ON_DROP_CHANNEL
|
820 EVENT_ON_START_OPENING_HANDSHAKE
|
821 EVENT_ON_FINISH_OPENING_HANDSHAKE
) {}
822 // Create a ChannelDeletingFakeWebSocketEventInterface. Defined out-of-line to
823 // avoid circular dependency.
824 virtual scoped_ptr
<WebSocketEventInterface
> CreateEventInterface() OVERRIDE
;
826 // Tests can set deleting_ to a bitmap of EventInterfaceCall members that they
827 // want to cause Channel deletion. The default is for all calls to cause
832 // A FakeWebSocketEventInterface that deletes the WebSocketChannel on failure to
834 class ChannelDeletingFakeWebSocketEventInterface
835 : public FakeWebSocketEventInterface
{
837 ChannelDeletingFakeWebSocketEventInterface(
838 WebSocketChannelDeletingTest
* fixture
)
839 : fixture_(fixture
) {}
841 virtual ChannelState
OnAddChannelResponse(
843 const std::string
& selected_protocol
,
844 const std::string
& extensions
) OVERRIDE
{
845 return fixture_
->DeleteIfDeleting(EVENT_ON_ADD_CHANNEL_RESPONSE
);
848 virtual ChannelState
OnDataFrame(bool fin
,
849 WebSocketMessageType type
,
850 const std::vector
<char>& data
) OVERRIDE
{
851 return fixture_
->DeleteIfDeleting(EVENT_ON_DATA_FRAME
);
854 virtual ChannelState
OnFlowControl(int64 quota
) OVERRIDE
{
855 return fixture_
->DeleteIfDeleting(EVENT_ON_FLOW_CONTROL
);
858 virtual ChannelState
OnClosingHandshake() OVERRIDE
{
859 return fixture_
->DeleteIfDeleting(EVENT_ON_CLOSING_HANDSHAKE
);
862 virtual ChannelState
OnFailChannel(const std::string
& message
) OVERRIDE
{
863 return fixture_
->DeleteIfDeleting(EVENT_ON_FAIL_CHANNEL
);
866 virtual ChannelState
OnDropChannel(bool was_clean
,
868 const std::string
& reason
) OVERRIDE
{
869 return fixture_
->DeleteIfDeleting(EVENT_ON_DROP_CHANNEL
);
872 virtual ChannelState
OnStartOpeningHandshake(
873 scoped_ptr
<WebSocketHandshakeRequestInfo
> request
) OVERRIDE
{
874 return fixture_
->DeleteIfDeleting(EVENT_ON_START_OPENING_HANDSHAKE
);
876 virtual ChannelState
OnFinishOpeningHandshake(
877 scoped_ptr
<WebSocketHandshakeResponseInfo
> response
) OVERRIDE
{
878 return fixture_
->DeleteIfDeleting(EVENT_ON_FINISH_OPENING_HANDSHAKE
);
882 // A pointer to the test fixture. Owned by the test harness; this object will
883 // be deleted before it is.
884 WebSocketChannelDeletingTest
* fixture_
;
887 scoped_ptr
<WebSocketEventInterface
>
888 WebSocketChannelDeletingTest::CreateEventInterface() {
889 return scoped_ptr
<WebSocketEventInterface
>(
890 new ChannelDeletingFakeWebSocketEventInterface(this));
893 // Base class for tests which verify that EventInterface methods are called
895 class WebSocketChannelEventInterfaceTest
: public WebSocketChannelTest
{
897 WebSocketChannelEventInterfaceTest()
898 : event_interface_(new StrictMock
<MockWebSocketEventInterface
>) {
899 DefaultValue
<ChannelState
>::Set(CHANNEL_ALIVE
);
900 ON_CALL(*event_interface_
, OnAddChannelResponse(true, _
, _
))
901 .WillByDefault(Return(CHANNEL_DELETED
));
902 ON_CALL(*event_interface_
, OnDropChannel(_
, _
, _
))
903 .WillByDefault(Return(CHANNEL_DELETED
));
904 ON_CALL(*event_interface_
, OnFailChannel(_
))
905 .WillByDefault(Return(CHANNEL_DELETED
));
908 virtual ~WebSocketChannelEventInterfaceTest() {
909 DefaultValue
<ChannelState
>::Clear();
912 // Tests using this fixture must set expectations on the event_interface_ mock
913 // object before calling CreateChannelAndConnect() or
914 // CreateChannelAndConnectSuccessfully(). This will only work once per test
915 // case, but once should be enough.
916 virtual scoped_ptr
<WebSocketEventInterface
> CreateEventInterface() OVERRIDE
{
917 return scoped_ptr
<WebSocketEventInterface
>(event_interface_
.release());
920 scoped_ptr
<MockWebSocketEventInterface
> event_interface_
;
923 // Base class for tests which verify that WebSocketStream methods are called
924 // appropriately by using a MockWebSocketStream.
925 class WebSocketChannelStreamTest
: public WebSocketChannelTest
{
927 WebSocketChannelStreamTest()
928 : mock_stream_(new StrictMock
<MockWebSocketStream
>) {}
930 virtual void CreateChannelAndConnectSuccessfully() OVERRIDE
{
931 set_stream(mock_stream_
.Pass());
932 WebSocketChannelTest::CreateChannelAndConnectSuccessfully();
935 scoped_ptr
<MockWebSocketStream
> mock_stream_
;
938 // Fixture for tests which test UTF-8 validation of sent Text frames via the
940 class WebSocketChannelSendUtf8Test
941 : public WebSocketChannelEventInterfaceTest
{
943 virtual void SetUp() {
944 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream
));
945 // For the purpose of the tests using this fixture, it doesn't matter
946 // whether these methods are called or not.
947 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(_
, _
, _
))
949 EXPECT_CALL(*event_interface_
, OnFlowControl(_
))
954 // Fixture for tests which test use of receive quota from the renderer.
955 class WebSocketChannelFlowControlTest
956 : public WebSocketChannelEventInterfaceTest
{
958 // Tests using this fixture should use CreateChannelAndConnectWithQuota()
959 // instead of CreateChannelAndConnectSuccessfully().
960 void CreateChannelAndConnectWithQuota(int64 quota
) {
961 CreateChannelAndConnect();
962 channel_
->SendFlowControl(quota
);
963 connect_data_
.creator
.connect_delegate
->OnSuccess(stream_
.Pass());
966 virtual void CreateChannelAndConnectSuccesfully() { NOTREACHED(); }
969 // Fixture for tests which test UTF-8 validation of received Text frames using a
970 // mock WebSocketStream.
971 class WebSocketChannelReceiveUtf8Test
: public WebSocketChannelStreamTest
{
973 virtual void SetUp() {
974 // For the purpose of the tests using this fixture, it doesn't matter
975 // whether these methods are called or not.
976 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
977 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
981 // Simple test that everything that should be passed to the creator function is
982 // passed to the creator function.
983 TEST_F(WebSocketChannelTest
, EverythingIsPassedToTheCreatorFunction
) {
984 connect_data_
.socket_url
= GURL("ws://example.com/test");
985 connect_data_
.origin
= url::Origin("http://example.com");
986 connect_data_
.requested_subprotocols
.push_back("Sinbad");
988 CreateChannelAndConnect();
990 const ArgumentCopyingWebSocketStreamCreator
& actual
= connect_data_
.creator
;
992 EXPECT_EQ(&connect_data_
.url_request_context
, actual
.url_request_context
);
994 EXPECT_EQ(connect_data_
.socket_url
, actual
.socket_url
);
995 EXPECT_EQ(connect_data_
.requested_subprotocols
,
996 actual
.requested_subprotocols
);
997 EXPECT_EQ(connect_data_
.origin
.string(), actual
.origin
.string());
1000 // Verify that calling SendFlowControl before the connection is established does
1001 // not cause a crash.
1002 TEST_F(WebSocketChannelTest
, SendFlowControlDuringHandshakeOkay
) {
1003 CreateChannelAndConnect();
1004 ASSERT_TRUE(channel_
);
1005 channel_
->SendFlowControl(65536);
1008 // Any WebSocketEventInterface methods can delete the WebSocketChannel and
1009 // return CHANNEL_DELETED. The WebSocketChannelDeletingTests are intended to
1010 // verify that there are no use-after-free bugs when this happens. Problems will
1011 // probably only be found when running under Address Sanitizer or a similar
1013 TEST_F(WebSocketChannelDeletingTest
, OnAddChannelResponseFail
) {
1014 CreateChannelAndConnect();
1015 EXPECT_TRUE(channel_
);
1016 connect_data_
.creator
.connect_delegate
->OnFailure("bye");
1017 EXPECT_EQ(NULL
, channel_
.get());
1020 // Deletion is possible (due to IPC failure) even if the connect succeeds.
1021 TEST_F(WebSocketChannelDeletingTest
, OnAddChannelResponseSuccess
) {
1022 CreateChannelAndConnectSuccessfully();
1023 EXPECT_EQ(NULL
, channel_
.get());
1026 TEST_F(WebSocketChannelDeletingTest
, OnDataFrameSync
) {
1027 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1028 new ReadableFakeWebSocketStream
);
1029 static const InitFrame frames
[] = {
1030 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "HELLO"}};
1031 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1032 set_stream(stream
.Pass());
1033 deleting_
= EVENT_ON_DATA_FRAME
;
1035 CreateChannelAndConnectSuccessfully();
1036 EXPECT_EQ(NULL
, channel_
.get());
1039 TEST_F(WebSocketChannelDeletingTest
, OnDataFrameAsync
) {
1040 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1041 new ReadableFakeWebSocketStream
);
1042 static const InitFrame frames
[] = {
1043 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "HELLO"}};
1044 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
1045 set_stream(stream
.Pass());
1046 deleting_
= EVENT_ON_DATA_FRAME
;
1048 CreateChannelAndConnectSuccessfully();
1049 EXPECT_TRUE(channel_
);
1050 base::MessageLoop::current()->RunUntilIdle();
1051 EXPECT_EQ(NULL
, channel_
.get());
1054 TEST_F(WebSocketChannelDeletingTest
, OnFlowControlAfterConnect
) {
1055 deleting_
= EVENT_ON_FLOW_CONTROL
;
1057 CreateChannelAndConnectSuccessfully();
1058 EXPECT_EQ(NULL
, channel_
.get());
1061 TEST_F(WebSocketChannelDeletingTest
, OnFlowControlAfterSend
) {
1062 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream
));
1063 // Avoid deleting the channel yet.
1064 deleting_
= EVENT_ON_FAIL_CHANNEL
| EVENT_ON_DROP_CHANNEL
;
1065 CreateChannelAndConnectSuccessfully();
1066 ASSERT_TRUE(channel_
);
1067 deleting_
= EVENT_ON_FLOW_CONTROL
;
1068 channel_
->SendFrame(true,
1069 WebSocketFrameHeader::kOpCodeText
,
1070 std::vector
<char>(kDefaultInitialQuota
, 'B'));
1071 EXPECT_EQ(NULL
, channel_
.get());
1074 TEST_F(WebSocketChannelDeletingTest
, OnClosingHandshakeSync
) {
1075 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1076 new ReadableFakeWebSocketStream
);
1077 static const InitFrame frames
[] = {
1078 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
1079 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "Success")}};
1080 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1081 set_stream(stream
.Pass());
1082 deleting_
= EVENT_ON_CLOSING_HANDSHAKE
;
1083 CreateChannelAndConnectSuccessfully();
1084 EXPECT_EQ(NULL
, channel_
.get());
1087 TEST_F(WebSocketChannelDeletingTest
, OnClosingHandshakeAsync
) {
1088 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1089 new ReadableFakeWebSocketStream
);
1090 static const InitFrame frames
[] = {
1091 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
1092 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "Success")}};
1093 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
1094 set_stream(stream
.Pass());
1095 deleting_
= EVENT_ON_CLOSING_HANDSHAKE
;
1096 CreateChannelAndConnectSuccessfully();
1097 ASSERT_TRUE(channel_
);
1098 base::MessageLoop::current()->RunUntilIdle();
1099 EXPECT_EQ(NULL
, channel_
.get());
1102 TEST_F(WebSocketChannelDeletingTest
, OnDropChannelWriteError
) {
1103 set_stream(make_scoped_ptr(new UnWriteableFakeWebSocketStream
));
1104 deleting_
= EVENT_ON_DROP_CHANNEL
;
1105 CreateChannelAndConnectSuccessfully();
1106 ASSERT_TRUE(channel_
);
1107 channel_
->SendFrame(
1108 true, WebSocketFrameHeader::kOpCodeText
, AsVector("this will fail"));
1109 EXPECT_EQ(NULL
, channel_
.get());
1112 TEST_F(WebSocketChannelDeletingTest
, OnDropChannelReadError
) {
1113 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1114 new ReadableFakeWebSocketStream
);
1115 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC
,
1117 set_stream(stream
.Pass());
1118 deleting_
= EVENT_ON_DROP_CHANNEL
;
1119 CreateChannelAndConnectSuccessfully();
1120 ASSERT_TRUE(channel_
);
1121 base::MessageLoop::current()->RunUntilIdle();
1122 EXPECT_EQ(NULL
, channel_
.get());
1125 TEST_F(WebSocketChannelDeletingTest
, OnNotifyStartOpeningHandshakeError
) {
1126 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1127 new ReadableFakeWebSocketStream
);
1128 static const InitFrame frames
[] = {
1129 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "HELLO"}};
1130 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
1131 set_stream(stream
.Pass());
1132 deleting_
= EVENT_ON_START_OPENING_HANDSHAKE
;
1134 CreateChannelAndConnectSuccessfully();
1135 ASSERT_TRUE(channel_
);
1136 channel_
->OnStartOpeningHandshake(scoped_ptr
<WebSocketHandshakeRequestInfo
>(
1137 new WebSocketHandshakeRequestInfo(GURL("http://www.example.com/"),
1139 base::MessageLoop::current()->RunUntilIdle();
1140 EXPECT_EQ(NULL
, channel_
.get());
1143 TEST_F(WebSocketChannelDeletingTest
, OnNotifyFinishOpeningHandshakeError
) {
1144 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1145 new ReadableFakeWebSocketStream
);
1146 static const InitFrame frames
[] = {
1147 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "HELLO"}};
1148 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
1149 set_stream(stream
.Pass());
1150 deleting_
= EVENT_ON_FINISH_OPENING_HANDSHAKE
;
1152 CreateChannelAndConnectSuccessfully();
1153 ASSERT_TRUE(channel_
);
1154 scoped_refptr
<HttpResponseHeaders
> response_headers(
1155 new HttpResponseHeaders(""));
1156 channel_
->OnFinishOpeningHandshake(scoped_ptr
<WebSocketHandshakeResponseInfo
>(
1157 new WebSocketHandshakeResponseInfo(GURL("http://www.example.com/"),
1162 base::MessageLoop::current()->RunUntilIdle();
1163 EXPECT_EQ(NULL
, channel_
.get());
1166 TEST_F(WebSocketChannelDeletingTest
, FailChannelInSendFrame
) {
1167 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream
));
1168 deleting_
= EVENT_ON_FAIL_CHANNEL
;
1169 CreateChannelAndConnectSuccessfully();
1170 ASSERT_TRUE(channel_
);
1171 channel_
->SendFrame(true,
1172 WebSocketFrameHeader::kOpCodeText
,
1173 std::vector
<char>(kDefaultInitialQuota
* 2, 'T'));
1174 EXPECT_EQ(NULL
, channel_
.get());
1177 TEST_F(WebSocketChannelDeletingTest
, FailChannelInOnReadDone
) {
1178 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1179 new ReadableFakeWebSocketStream
);
1180 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC
,
1181 ERR_WS_PROTOCOL_ERROR
);
1182 set_stream(stream
.Pass());
1183 deleting_
= EVENT_ON_FAIL_CHANNEL
;
1184 CreateChannelAndConnectSuccessfully();
1185 ASSERT_TRUE(channel_
);
1186 base::MessageLoop::current()->RunUntilIdle();
1187 EXPECT_EQ(NULL
, channel_
.get());
1190 TEST_F(WebSocketChannelDeletingTest
, FailChannelDueToMaskedFrame
) {
1191 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1192 new ReadableFakeWebSocketStream
);
1193 static const InitFrame frames
[] = {
1194 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "HELLO"}};
1195 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1196 set_stream(stream
.Pass());
1197 deleting_
= EVENT_ON_FAIL_CHANNEL
;
1199 CreateChannelAndConnectSuccessfully();
1200 EXPECT_EQ(NULL
, channel_
.get());
1203 TEST_F(WebSocketChannelDeletingTest
, FailChannelDueToBadControlFrame
) {
1204 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1205 new ReadableFakeWebSocketStream
);
1206 static const InitFrame frames
[] = {
1207 {FINAL_FRAME
, 0xF, NOT_MASKED
, ""}};
1208 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1209 set_stream(stream
.Pass());
1210 deleting_
= EVENT_ON_FAIL_CHANNEL
;
1212 CreateChannelAndConnectSuccessfully();
1213 EXPECT_EQ(NULL
, channel_
.get());
1216 // Version of above test with NULL data.
1217 TEST_F(WebSocketChannelDeletingTest
, FailChannelDueToBadControlFrameNull
) {
1218 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1219 new ReadableFakeWebSocketStream
);
1220 static const InitFrame frames
[] = {
1221 {FINAL_FRAME
, 0xF, NOT_MASKED
, NULL
}};
1222 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1223 set_stream(stream
.Pass());
1224 deleting_
= EVENT_ON_FAIL_CHANNEL
;
1226 CreateChannelAndConnectSuccessfully();
1227 EXPECT_EQ(NULL
, channel_
.get());
1230 TEST_F(WebSocketChannelDeletingTest
, FailChannelDueToPongAfterClose
) {
1231 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1232 new ReadableFakeWebSocketStream
);
1233 static const InitFrame frames
[] = {
1234 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, NOT_MASKED
,
1235 CLOSE_DATA(NORMAL_CLOSURE
, "Success")},
1236 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePong
, NOT_MASKED
, ""}};
1237 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1238 set_stream(stream
.Pass());
1239 deleting_
= EVENT_ON_FAIL_CHANNEL
;
1241 CreateChannelAndConnectSuccessfully();
1242 EXPECT_EQ(NULL
, channel_
.get());
1245 TEST_F(WebSocketChannelDeletingTest
, FailChannelDueToPongAfterCloseNull
) {
1246 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1247 new ReadableFakeWebSocketStream
);
1248 static const InitFrame frames
[] = {
1249 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, NOT_MASKED
,
1250 CLOSE_DATA(NORMAL_CLOSURE
, "Success")},
1251 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePong
, NOT_MASKED
, NULL
}};
1252 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1253 set_stream(stream
.Pass());
1254 deleting_
= EVENT_ON_FAIL_CHANNEL
;
1256 CreateChannelAndConnectSuccessfully();
1257 EXPECT_EQ(NULL
, channel_
.get());
1260 TEST_F(WebSocketChannelDeletingTest
, FailChannelDueToUnknownOpCode
) {
1261 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1262 new ReadableFakeWebSocketStream
);
1263 static const InitFrame frames
[] = {{FINAL_FRAME
, 0x7, NOT_MASKED
, ""}};
1264 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1265 set_stream(stream
.Pass());
1266 deleting_
= EVENT_ON_FAIL_CHANNEL
;
1268 CreateChannelAndConnectSuccessfully();
1269 EXPECT_EQ(NULL
, channel_
.get());
1272 TEST_F(WebSocketChannelDeletingTest
, FailChannelDueToUnknownOpCodeNull
) {
1273 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1274 new ReadableFakeWebSocketStream
);
1275 static const InitFrame frames
[] = {{FINAL_FRAME
, 0x7, NOT_MASKED
, NULL
}};
1276 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1277 set_stream(stream
.Pass());
1278 deleting_
= EVENT_ON_FAIL_CHANNEL
;
1280 CreateChannelAndConnectSuccessfully();
1281 EXPECT_EQ(NULL
, channel_
.get());
1284 TEST_F(WebSocketChannelDeletingTest
, FailChannelDueInvalidCloseReason
) {
1285 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1286 new ReadableFakeWebSocketStream
);
1287 static const InitFrame frames
[] = {
1288 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
1289 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "\xFF")}};
1290 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1291 set_stream(stream
.Pass());
1292 deleting_
= EVENT_ON_FAIL_CHANNEL
;
1294 CreateChannelAndConnectSuccessfully();
1295 EXPECT_EQ(NULL
, channel_
.get());
1298 TEST_F(WebSocketChannelEventInterfaceTest
, ConnectSuccessReported
) {
1299 // false means success.
1300 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, "", ""));
1301 // OnFlowControl is always called immediately after connect to provide initial
1302 // quota to the renderer.
1303 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1305 CreateChannelAndConnect();
1307 connect_data_
.creator
.connect_delegate
->OnSuccess(stream_
.Pass());
1310 TEST_F(WebSocketChannelEventInterfaceTest
, ConnectFailureReported
) {
1311 EXPECT_CALL(*event_interface_
, OnFailChannel("hello"));
1313 CreateChannelAndConnect();
1315 connect_data_
.creator
.connect_delegate
->OnFailure("hello");
1318 TEST_F(WebSocketChannelEventInterfaceTest
, NonWebSocketSchemeRejected
) {
1319 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(true, "", ""));
1320 connect_data_
.socket_url
= GURL("http://www.google.com/");
1321 CreateChannelAndConnect();
1324 TEST_F(WebSocketChannelEventInterfaceTest
, ProtocolPassed
) {
1325 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, "Bob", ""));
1326 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1328 CreateChannelAndConnect();
1330 connect_data_
.creator
.connect_delegate
->OnSuccess(
1331 scoped_ptr
<WebSocketStream
>(new FakeWebSocketStream("Bob", "")));
1334 TEST_F(WebSocketChannelEventInterfaceTest
, ExtensionsPassed
) {
1335 EXPECT_CALL(*event_interface_
,
1336 OnAddChannelResponse(false, "", "extension1, extension2"));
1337 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1339 CreateChannelAndConnect();
1341 connect_data_
.creator
.connect_delegate
->OnSuccess(scoped_ptr
<WebSocketStream
>(
1342 new FakeWebSocketStream("", "extension1, extension2")));
1345 // The first frames from the server can arrive together with the handshake, in
1346 // which case they will be available as soon as ReadFrames() is called the first
1348 TEST_F(WebSocketChannelEventInterfaceTest
, DataLeftFromHandshake
) {
1349 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1350 new ReadableFakeWebSocketStream
);
1351 static const InitFrame frames
[] = {
1352 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "HELLO"}};
1353 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1354 set_stream(stream
.Pass());
1357 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1358 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1362 true, WebSocketFrameHeader::kOpCodeText
, AsVector("HELLO")));
1365 CreateChannelAndConnectSuccessfully();
1368 // A remote server could accept the handshake, but then immediately send a
1370 TEST_F(WebSocketChannelEventInterfaceTest
, CloseAfterHandshake
) {
1371 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1372 new ReadableFakeWebSocketStream
);
1373 static const InitFrame frames
[] = {
1374 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
1375 NOT_MASKED
, CLOSE_DATA(SERVER_ERROR
, "Internal Server Error")}};
1376 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1377 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC
,
1378 ERR_CONNECTION_CLOSED
);
1379 set_stream(stream
.Pass());
1382 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1383 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1384 EXPECT_CALL(*event_interface_
, OnClosingHandshake());
1388 true, kWebSocketErrorInternalServerError
, "Internal Server Error"));
1391 CreateChannelAndConnectSuccessfully();
1394 // A remote server could close the connection immediately after sending the
1395 // handshake response (most likely a bug in the server).
1396 TEST_F(WebSocketChannelEventInterfaceTest
, ConnectionCloseAfterHandshake
) {
1397 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1398 new ReadableFakeWebSocketStream
);
1399 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC
,
1400 ERR_CONNECTION_CLOSED
);
1401 set_stream(stream
.Pass());
1404 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1405 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1406 EXPECT_CALL(*event_interface_
,
1407 OnDropChannel(false, kWebSocketErrorAbnormalClosure
, _
));
1410 CreateChannelAndConnectSuccessfully();
1413 TEST_F(WebSocketChannelEventInterfaceTest
, NormalAsyncRead
) {
1414 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1415 new ReadableFakeWebSocketStream
);
1416 static const InitFrame frames
[] = {
1417 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "HELLO"}};
1418 // We use this checkpoint object to verify that the callback isn't called
1419 // until we expect it to be.
1420 Checkpoint checkpoint
;
1421 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
1422 set_stream(stream
.Pass());
1425 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1426 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1427 EXPECT_CALL(checkpoint
, Call(1));
1431 true, WebSocketFrameHeader::kOpCodeText
, AsVector("HELLO")));
1432 EXPECT_CALL(checkpoint
, Call(2));
1435 CreateChannelAndConnectSuccessfully();
1437 base::MessageLoop::current()->RunUntilIdle();
1441 // Extra data can arrive while a read is being processed, resulting in the next
1442 // read completing synchronously.
1443 TEST_F(WebSocketChannelEventInterfaceTest
, AsyncThenSyncRead
) {
1444 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1445 new ReadableFakeWebSocketStream
);
1446 static const InitFrame frames1
[] = {
1447 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "HELLO"}};
1448 static const InitFrame frames2
[] = {
1449 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "WORLD"}};
1450 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames1
);
1451 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames2
);
1452 set_stream(stream
.Pass());
1455 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1456 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1460 true, WebSocketFrameHeader::kOpCodeText
, AsVector("HELLO")));
1464 true, WebSocketFrameHeader::kOpCodeText
, AsVector("WORLD")));
1467 CreateChannelAndConnectSuccessfully();
1468 base::MessageLoop::current()->RunUntilIdle();
1471 // Data frames are delivered the same regardless of how many reads they arrive
1473 TEST_F(WebSocketChannelEventInterfaceTest
, FragmentedMessage
) {
1474 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1475 new ReadableFakeWebSocketStream
);
1476 // Here we have one message which arrived in five frames split across three
1477 // reads. It may have been reframed on arrival, but this class doesn't care
1479 static const InitFrame frames1
[] = {
1480 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "THREE"},
1481 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
1483 static const InitFrame frames2
[] = {
1484 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
1485 NOT_MASKED
, "SMALL"}};
1486 static const InitFrame frames3
[] = {
1487 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
1489 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
1490 NOT_MASKED
, "FRAMES"}};
1491 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames1
);
1492 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames2
);
1493 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames3
);
1494 set_stream(stream
.Pass());
1497 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1498 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1502 false, WebSocketFrameHeader::kOpCodeText
, AsVector("THREE")));
1506 false, WebSocketFrameHeader::kOpCodeContinuation
, AsVector(" ")));
1507 EXPECT_CALL(*event_interface_
,
1509 WebSocketFrameHeader::kOpCodeContinuation
,
1510 AsVector("SMALL")));
1514 false, WebSocketFrameHeader::kOpCodeContinuation
, AsVector(" ")));
1515 EXPECT_CALL(*event_interface_
,
1517 WebSocketFrameHeader::kOpCodeContinuation
,
1518 AsVector("FRAMES")));
1521 CreateChannelAndConnectSuccessfully();
1522 base::MessageLoop::current()->RunUntilIdle();
1525 // A message can consist of one frame with NULL payload.
1526 TEST_F(WebSocketChannelEventInterfaceTest
, NullMessage
) {
1527 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1528 new ReadableFakeWebSocketStream
);
1529 static const InitFrame frames
[] = {
1530 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, NULL
}};
1531 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1532 set_stream(stream
.Pass());
1533 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1534 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1537 OnDataFrame(true, WebSocketFrameHeader::kOpCodeText
, AsVector("")));
1538 CreateChannelAndConnectSuccessfully();
1541 // Connection closed by the remote host without a closing handshake.
1542 TEST_F(WebSocketChannelEventInterfaceTest
, AsyncAbnormalClosure
) {
1543 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1544 new ReadableFakeWebSocketStream
);
1545 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC
,
1546 ERR_CONNECTION_CLOSED
);
1547 set_stream(stream
.Pass());
1550 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1551 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1552 EXPECT_CALL(*event_interface_
,
1553 OnDropChannel(false, kWebSocketErrorAbnormalClosure
, _
));
1556 CreateChannelAndConnectSuccessfully();
1557 base::MessageLoop::current()->RunUntilIdle();
1560 // A connection reset should produce the same event as an unexpected closure.
1561 TEST_F(WebSocketChannelEventInterfaceTest
, ConnectionReset
) {
1562 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1563 new ReadableFakeWebSocketStream
);
1564 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC
,
1565 ERR_CONNECTION_RESET
);
1566 set_stream(stream
.Pass());
1569 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1570 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1571 EXPECT_CALL(*event_interface_
,
1572 OnDropChannel(false, kWebSocketErrorAbnormalClosure
, _
));
1575 CreateChannelAndConnectSuccessfully();
1576 base::MessageLoop::current()->RunUntilIdle();
1579 // RFC6455 5.1 "A client MUST close a connection if it detects a masked frame."
1580 TEST_F(WebSocketChannelEventInterfaceTest
, MaskedFramesAreRejected
) {
1581 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1582 new ReadableFakeWebSocketStream
);
1583 static const InitFrame frames
[] = {
1584 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "HELLO"}};
1586 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
1587 set_stream(stream
.Pass());
1590 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1591 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1595 "A server must not mask any frames that it sends to the client."));
1598 CreateChannelAndConnectSuccessfully();
1599 base::MessageLoop::current()->RunUntilIdle();
1602 // RFC6455 5.2 "If an unknown opcode is received, the receiving endpoint MUST
1603 // _Fail the WebSocket Connection_."
1604 TEST_F(WebSocketChannelEventInterfaceTest
, UnknownOpCodeIsRejected
) {
1605 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1606 new ReadableFakeWebSocketStream
);
1607 static const InitFrame frames
[] = {{FINAL_FRAME
, 4, NOT_MASKED
, "HELLO"}};
1609 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
1610 set_stream(stream
.Pass());
1613 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1614 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1615 EXPECT_CALL(*event_interface_
,
1616 OnFailChannel("Unrecognized frame opcode: 4"));
1619 CreateChannelAndConnectSuccessfully();
1620 base::MessageLoop::current()->RunUntilIdle();
1623 // RFC6455 5.4 "Control frames ... MAY be injected in the middle of a
1624 // fragmented message."
1625 TEST_F(WebSocketChannelEventInterfaceTest
, ControlFrameInDataMessage
) {
1626 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1627 new ReadableFakeWebSocketStream
);
1628 // We have one message of type Text split into two frames. In the middle is a
1629 // control message of type Pong.
1630 static const InitFrame frames1
[] = {
1631 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
,
1632 NOT_MASKED
, "SPLIT "}};
1633 static const InitFrame frames2
[] = {
1634 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePong
, NOT_MASKED
, ""}};
1635 static const InitFrame frames3
[] = {
1636 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
1637 NOT_MASKED
, "MESSAGE"}};
1638 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames1
);
1639 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames2
);
1640 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames3
);
1641 set_stream(stream
.Pass());
1644 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1645 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1649 false, WebSocketFrameHeader::kOpCodeText
, AsVector("SPLIT ")));
1650 EXPECT_CALL(*event_interface_
,
1652 WebSocketFrameHeader::kOpCodeContinuation
,
1653 AsVector("MESSAGE")));
1656 CreateChannelAndConnectSuccessfully();
1657 base::MessageLoop::current()->RunUntilIdle();
1660 // It seems redundant to repeat the entirety of the above test, so just test a
1661 // Pong with NULL data.
1662 TEST_F(WebSocketChannelEventInterfaceTest
, PongWithNullData
) {
1663 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1664 new ReadableFakeWebSocketStream
);
1665 static const InitFrame frames
[] = {
1666 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePong
, NOT_MASKED
, NULL
}};
1667 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
1668 set_stream(stream
.Pass());
1669 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1670 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1672 CreateChannelAndConnectSuccessfully();
1673 base::MessageLoop::current()->RunUntilIdle();
1676 // If a frame has an invalid header, then the connection is closed and
1677 // subsequent frames must not trigger events.
1678 TEST_F(WebSocketChannelEventInterfaceTest
, FrameAfterInvalidFrame
) {
1679 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1680 new ReadableFakeWebSocketStream
);
1681 static const InitFrame frames
[] = {
1682 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "HELLO"},
1683 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, " WORLD"}};
1685 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
1686 set_stream(stream
.Pass());
1689 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1690 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1694 "A server must not mask any frames that it sends to the client."));
1697 CreateChannelAndConnectSuccessfully();
1698 base::MessageLoop::current()->RunUntilIdle();
1701 // If the renderer sends lots of small writes, we don't want to update the quota
1703 TEST_F(WebSocketChannelEventInterfaceTest
, SmallWriteDoesntUpdateQuota
) {
1704 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream
));
1707 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1708 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1711 CreateChannelAndConnectSuccessfully();
1712 channel_
->SendFrame(true, WebSocketFrameHeader::kOpCodeText
, AsVector("B"));
1715 // If we send enough to go below send_quota_low_water_mask_ we should get our
1717 TEST_F(WebSocketChannelEventInterfaceTest
, LargeWriteUpdatesQuota
) {
1718 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream
));
1719 // We use this checkpoint object to verify that the quota update comes after
1721 Checkpoint checkpoint
;
1724 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1725 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1726 EXPECT_CALL(checkpoint
, Call(1));
1727 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1728 EXPECT_CALL(checkpoint
, Call(2));
1731 CreateChannelAndConnectSuccessfully();
1733 channel_
->SendFrame(true,
1734 WebSocketFrameHeader::kOpCodeText
,
1735 std::vector
<char>(kDefaultInitialQuota
, 'B'));
1739 // Verify that our quota actually is refreshed when we are told it is.
1740 TEST_F(WebSocketChannelEventInterfaceTest
, QuotaReallyIsRefreshed
) {
1741 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream
));
1742 Checkpoint checkpoint
;
1745 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1746 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1747 EXPECT_CALL(checkpoint
, Call(1));
1748 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1749 EXPECT_CALL(checkpoint
, Call(2));
1750 // If quota was not really refreshed, we would get an OnDropChannel()
1752 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1753 EXPECT_CALL(checkpoint
, Call(3));
1756 CreateChannelAndConnectSuccessfully();
1758 channel_
->SendFrame(true,
1759 WebSocketFrameHeader::kOpCodeText
,
1760 std::vector
<char>(kDefaultQuotaRefreshTrigger
, 'D'));
1762 // We should have received more quota at this point.
1763 channel_
->SendFrame(true,
1764 WebSocketFrameHeader::kOpCodeText
,
1765 std::vector
<char>(kDefaultQuotaRefreshTrigger
, 'E'));
1769 // If we send more than the available quota then the connection will be closed
1771 TEST_F(WebSocketChannelEventInterfaceTest
, WriteOverQuotaIsRejected
) {
1772 set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream
));
1775 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1776 EXPECT_CALL(*event_interface_
, OnFlowControl(kDefaultInitialQuota
));
1777 EXPECT_CALL(*event_interface_
, OnFailChannel("Send quota exceeded"));
1780 CreateChannelAndConnectSuccessfully();
1781 channel_
->SendFrame(true,
1782 WebSocketFrameHeader::kOpCodeText
,
1783 std::vector
<char>(kDefaultInitialQuota
+ 1, 'C'));
1786 // If a write fails, the channel is dropped.
1787 TEST_F(WebSocketChannelEventInterfaceTest
, FailedWrite
) {
1788 set_stream(make_scoped_ptr(new UnWriteableFakeWebSocketStream
));
1789 Checkpoint checkpoint
;
1792 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1793 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1794 EXPECT_CALL(checkpoint
, Call(1));
1795 EXPECT_CALL(*event_interface_
,
1796 OnDropChannel(false, kWebSocketErrorAbnormalClosure
, _
));
1797 EXPECT_CALL(checkpoint
, Call(2));
1800 CreateChannelAndConnectSuccessfully();
1803 channel_
->SendFrame(true, WebSocketFrameHeader::kOpCodeText
, AsVector("H"));
1807 // OnDropChannel() is called exactly once when StartClosingHandshake() is used.
1808 TEST_F(WebSocketChannelEventInterfaceTest
, SendCloseDropsChannel
) {
1809 set_stream(make_scoped_ptr(new EchoeyFakeWebSocketStream
));
1812 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1813 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1814 EXPECT_CALL(*event_interface_
,
1815 OnDropChannel(true, kWebSocketNormalClosure
, "Fred"));
1818 CreateChannelAndConnectSuccessfully();
1820 channel_
->StartClosingHandshake(kWebSocketNormalClosure
, "Fred");
1821 base::MessageLoop::current()->RunUntilIdle();
1824 // StartClosingHandshake() also works before connection completes, and calls
1826 TEST_F(WebSocketChannelEventInterfaceTest
, CloseDuringConnection
) {
1827 EXPECT_CALL(*event_interface_
,
1828 OnDropChannel(false, kWebSocketErrorAbnormalClosure
, ""));
1830 CreateChannelAndConnect();
1831 channel_
->StartClosingHandshake(kWebSocketNormalClosure
, "Joe");
1834 // OnDropChannel() is only called once when a write() on the socket triggers a
1835 // connection reset.
1836 TEST_F(WebSocketChannelEventInterfaceTest
, OnDropChannelCalledOnce
) {
1837 set_stream(make_scoped_ptr(new ResetOnWriteFakeWebSocketStream
));
1838 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1839 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1841 EXPECT_CALL(*event_interface_
,
1842 OnDropChannel(false, kWebSocketErrorAbnormalClosure
, ""))
1845 CreateChannelAndConnectSuccessfully();
1847 channel_
->SendFrame(true, WebSocketFrameHeader::kOpCodeText
, AsVector("yt?"));
1848 base::MessageLoop::current()->RunUntilIdle();
1851 // When the remote server sends a Close frame with an empty payload,
1852 // WebSocketChannel should report code 1005, kWebSocketErrorNoStatusReceived.
1853 TEST_F(WebSocketChannelEventInterfaceTest
, CloseWithNoPayloadGivesStatus1005
) {
1854 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1855 new ReadableFakeWebSocketStream
);
1856 static const InitFrame frames
[] = {
1857 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, NOT_MASKED
, ""}};
1858 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1859 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC
,
1860 ERR_CONNECTION_CLOSED
);
1861 set_stream(stream
.Pass());
1862 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1863 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1864 EXPECT_CALL(*event_interface_
, OnClosingHandshake());
1865 EXPECT_CALL(*event_interface_
,
1866 OnDropChannel(true, kWebSocketErrorNoStatusReceived
, _
));
1868 CreateChannelAndConnectSuccessfully();
1871 // A version of the above test with NULL payload.
1872 TEST_F(WebSocketChannelEventInterfaceTest
,
1873 CloseWithNullPayloadGivesStatus1005
) {
1874 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1875 new ReadableFakeWebSocketStream
);
1876 static const InitFrame frames
[] = {
1877 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, NOT_MASKED
, NULL
}};
1878 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
1879 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC
,
1880 ERR_CONNECTION_CLOSED
);
1881 set_stream(stream
.Pass());
1882 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1883 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1884 EXPECT_CALL(*event_interface_
, OnClosingHandshake());
1885 EXPECT_CALL(*event_interface_
,
1886 OnDropChannel(true, kWebSocketErrorNoStatusReceived
, _
));
1888 CreateChannelAndConnectSuccessfully();
1891 // If ReadFrames() returns ERR_WS_PROTOCOL_ERROR, then the connection must be
1893 TEST_F(WebSocketChannelEventInterfaceTest
, SyncProtocolErrorGivesStatus1002
) {
1894 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1895 new ReadableFakeWebSocketStream
);
1896 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC
,
1897 ERR_WS_PROTOCOL_ERROR
);
1898 set_stream(stream
.Pass());
1899 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1900 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1902 EXPECT_CALL(*event_interface_
, OnFailChannel("Invalid frame header"));
1904 CreateChannelAndConnectSuccessfully();
1907 // Async version of above test.
1908 TEST_F(WebSocketChannelEventInterfaceTest
, AsyncProtocolErrorGivesStatus1002
) {
1909 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1910 new ReadableFakeWebSocketStream
);
1911 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC
,
1912 ERR_WS_PROTOCOL_ERROR
);
1913 set_stream(stream
.Pass());
1914 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1915 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1917 EXPECT_CALL(*event_interface_
, OnFailChannel("Invalid frame header"));
1919 CreateChannelAndConnectSuccessfully();
1920 base::MessageLoop::current()->RunUntilIdle();
1923 TEST_F(WebSocketChannelEventInterfaceTest
, StartHandshakeRequest
) {
1926 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1927 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1928 EXPECT_CALL(*event_interface_
, OnStartOpeningHandshakeCalled());
1931 CreateChannelAndConnectSuccessfully();
1933 scoped_ptr
<WebSocketHandshakeRequestInfo
> request_info(
1934 new WebSocketHandshakeRequestInfo(GURL("ws://www.example.com/"),
1936 connect_data_
.creator
.connect_delegate
->OnStartOpeningHandshake(
1937 request_info
.Pass());
1939 base::MessageLoop::current()->RunUntilIdle();
1942 TEST_F(WebSocketChannelEventInterfaceTest
, FinishHandshakeRequest
) {
1945 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
1946 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
1947 EXPECT_CALL(*event_interface_
, OnFinishOpeningHandshakeCalled());
1950 CreateChannelAndConnectSuccessfully();
1952 scoped_refptr
<HttpResponseHeaders
> response_headers(
1953 new HttpResponseHeaders(""));
1954 scoped_ptr
<WebSocketHandshakeResponseInfo
> response_info(
1955 new WebSocketHandshakeResponseInfo(GURL("ws://www.example.com/"),
1960 connect_data_
.creator
.connect_delegate
->OnFinishOpeningHandshake(
1961 response_info
.Pass());
1962 base::MessageLoop::current()->RunUntilIdle();
1965 TEST_F(WebSocketChannelEventInterfaceTest
, FailJustAfterHandshake
) {
1968 EXPECT_CALL(*event_interface_
, OnStartOpeningHandshakeCalled());
1969 EXPECT_CALL(*event_interface_
, OnFinishOpeningHandshakeCalled());
1970 EXPECT_CALL(*event_interface_
, OnFailChannel("bye"));
1973 CreateChannelAndConnect();
1975 WebSocketStream::ConnectDelegate
* connect_delegate
=
1976 connect_data_
.creator
.connect_delegate
.get();
1977 GURL
url("ws://www.example.com/");
1978 scoped_ptr
<WebSocketHandshakeRequestInfo
> request_info(
1979 new WebSocketHandshakeRequestInfo(url
, base::Time()));
1980 scoped_refptr
<HttpResponseHeaders
> response_headers(
1981 new HttpResponseHeaders(""));
1982 scoped_ptr
<WebSocketHandshakeResponseInfo
> response_info(
1983 new WebSocketHandshakeResponseInfo(url
,
1988 connect_delegate
->OnStartOpeningHandshake(request_info
.Pass());
1989 connect_delegate
->OnFinishOpeningHandshake(response_info
.Pass());
1991 connect_delegate
->OnFailure("bye");
1992 base::MessageLoop::current()->RunUntilIdle();
1995 // Any frame after close is invalid. This test uses a Text frame. See also
1996 // test "PingAfterCloseIfRejected".
1997 TEST_F(WebSocketChannelEventInterfaceTest
, DataAfterCloseIsRejected
) {
1998 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
1999 new ReadableFakeWebSocketStream
);
2000 static const InitFrame frames
[] = {
2001 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, NOT_MASKED
,
2002 CLOSE_DATA(NORMAL_CLOSURE
, "OK")},
2003 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "Payload"}};
2004 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
2005 set_stream(stream
.Pass());
2006 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2007 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2011 EXPECT_CALL(*event_interface_
, OnClosingHandshake());
2012 EXPECT_CALL(*event_interface_
,
2013 OnFailChannel("Data frame received after close"));
2016 CreateChannelAndConnectSuccessfully();
2019 // A Close frame with a one-byte payload elicits a specific console error
2021 TEST_F(WebSocketChannelEventInterfaceTest
, OneByteClosePayloadMessage
) {
2022 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2023 new ReadableFakeWebSocketStream
);
2024 static const InitFrame frames
[] = {
2025 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, NOT_MASKED
, "\x03"}};
2026 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
2027 set_stream(stream
.Pass());
2028 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2029 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2033 "Received a broken close frame containing an invalid size body."));
2035 CreateChannelAndConnectSuccessfully();
2038 // A Close frame with a reserved status code also elicits a specific console
2040 TEST_F(WebSocketChannelEventInterfaceTest
, ClosePayloadReservedStatusMessage
) {
2041 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2042 new ReadableFakeWebSocketStream
);
2043 static const InitFrame frames
[] = {
2044 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2045 NOT_MASKED
, CLOSE_DATA(ABNORMAL_CLOSURE
, "Not valid on wire")}};
2046 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
2047 set_stream(stream
.Pass());
2048 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2049 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2053 "Received a broken close frame containing a reserved status code."));
2055 CreateChannelAndConnectSuccessfully();
2058 // A Close frame with invalid UTF-8 also elicits a specific console error
2060 TEST_F(WebSocketChannelEventInterfaceTest
, ClosePayloadInvalidReason
) {
2061 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2062 new ReadableFakeWebSocketStream
);
2063 static const InitFrame frames
[] = {
2064 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2065 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "\xFF")}};
2066 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
2067 set_stream(stream
.Pass());
2068 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2069 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2073 "Received a broken close frame containing invalid UTF-8."));
2075 CreateChannelAndConnectSuccessfully();
2078 // The reserved bits must all be clear on received frames. Extensions should
2079 // clear the bits when they are set correctly before passing on the frame.
2080 TEST_F(WebSocketChannelEventInterfaceTest
, ReservedBitsMustNotBeSet
) {
2081 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2082 new ReadableFakeWebSocketStream
);
2083 static const InitFrame frames
[] = {
2084 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
,
2085 NOT_MASKED
, "sakana"}};
2086 // It is not worth adding support for reserved bits to InitFrame just for this
2087 // one test, so set the bit manually.
2088 ScopedVector
<WebSocketFrame
> raw_frames
= CreateFrameVector(frames
);
2089 raw_frames
[0]->header
.reserved1
= true;
2090 stream
->PrepareRawReadFrames(
2091 ReadableFakeWebSocketStream::SYNC
, OK
, raw_frames
.Pass());
2092 set_stream(stream
.Pass());
2093 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2094 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2095 EXPECT_CALL(*event_interface_
,
2097 "One or more reserved bits are on: reserved1 = 1, "
2098 "reserved2 = 0, reserved3 = 0"));
2100 CreateChannelAndConnectSuccessfully();
2103 // The closing handshake times out and sends an OnDropChannel event if no
2104 // response to the client Close message is received.
2105 TEST_F(WebSocketChannelEventInterfaceTest
,
2106 ClientInitiatedClosingHandshakeTimesOut
) {
2107 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2108 new ReadableFakeWebSocketStream
);
2109 stream
->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC
,
2111 set_stream(stream
.Pass());
2112 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2113 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2114 // This checkpoint object verifies that the OnDropChannel message comes after
2116 Checkpoint checkpoint
;
2117 TestClosure completion
;
2120 EXPECT_CALL(checkpoint
, Call(1));
2121 EXPECT_CALL(*event_interface_
,
2122 OnDropChannel(false, kWebSocketErrorAbnormalClosure
, _
))
2123 .WillOnce(InvokeClosureReturnDeleted(completion
.closure()));
2125 CreateChannelAndConnectSuccessfully();
2126 // OneShotTimer is not very friendly to testing; there is no apparent way to
2127 // set an expectation on it. Instead the tests need to infer that the timeout
2128 // was fired by the behaviour of the WebSocketChannel object.
2129 channel_
->SetClosingHandshakeTimeoutForTesting(
2130 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis
));
2131 channel_
->StartClosingHandshake(kWebSocketNormalClosure
, "");
2133 completion
.WaitForResult();
2136 // The closing handshake times out and sends an OnDropChannel event if a Close
2137 // message is received but the connection isn't closed by the remote host.
2138 TEST_F(WebSocketChannelEventInterfaceTest
,
2139 ServerInitiatedClosingHandshakeTimesOut
) {
2140 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2141 new ReadableFakeWebSocketStream
);
2142 static const InitFrame frames
[] = {
2143 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2144 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "OK")}};
2145 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
2146 set_stream(stream
.Pass());
2147 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2148 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2149 Checkpoint checkpoint
;
2150 TestClosure completion
;
2153 EXPECT_CALL(checkpoint
, Call(1));
2154 EXPECT_CALL(*event_interface_
, OnClosingHandshake());
2155 EXPECT_CALL(*event_interface_
,
2156 OnDropChannel(false, kWebSocketErrorAbnormalClosure
, _
))
2157 .WillOnce(InvokeClosureReturnDeleted(completion
.closure()));
2159 CreateChannelAndConnectSuccessfully();
2160 channel_
->SetClosingHandshakeTimeoutForTesting(
2161 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis
));
2163 completion
.WaitForResult();
2166 // The renderer should provide us with some quota immediately, and then
2167 // WebSocketChannel calls ReadFrames as soon as the stream is available.
2168 TEST_F(WebSocketChannelStreamTest
, FlowControlEarly
) {
2169 Checkpoint checkpoint
;
2170 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2171 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2174 EXPECT_CALL(checkpoint
, Call(1));
2175 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2176 .WillOnce(Return(ERR_IO_PENDING
));
2177 EXPECT_CALL(checkpoint
, Call(2));
2180 set_stream(mock_stream_
.Pass());
2181 CreateChannelAndConnect();
2182 channel_
->SendFlowControl(kPlentyOfQuota
);
2184 connect_data_
.creator
.connect_delegate
->OnSuccess(stream_
.Pass());
2188 // If for some reason the connect succeeds before the renderer sends us quota,
2189 // we shouldn't call ReadFrames() immediately.
2190 // TODO(ricea): Actually we should call ReadFrames() with a small limit so we
2191 // can still handle control frames. This should be done once we have any API to
2192 // expose quota to the lower levels.
2193 TEST_F(WebSocketChannelStreamTest
, FlowControlLate
) {
2194 Checkpoint checkpoint
;
2195 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2196 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2199 EXPECT_CALL(checkpoint
, Call(1));
2200 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2201 .WillOnce(Return(ERR_IO_PENDING
));
2202 EXPECT_CALL(checkpoint
, Call(2));
2205 set_stream(mock_stream_
.Pass());
2206 CreateChannelAndConnect();
2207 connect_data_
.creator
.connect_delegate
->OnSuccess(stream_
.Pass());
2209 channel_
->SendFlowControl(kPlentyOfQuota
);
2213 // We should stop calling ReadFrames() when all quota is used.
2214 TEST_F(WebSocketChannelStreamTest
, FlowControlStopsReadFrames
) {
2215 static const InitFrame frames
[] = {
2216 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "FOUR"}};
2218 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2219 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2220 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2221 .WillOnce(ReturnFrames(&frames
));
2223 set_stream(mock_stream_
.Pass());
2224 CreateChannelAndConnect();
2225 channel_
->SendFlowControl(4);
2226 connect_data_
.creator
.connect_delegate
->OnSuccess(stream_
.Pass());
2229 // Providing extra quota causes ReadFrames() to be called again.
2230 TEST_F(WebSocketChannelStreamTest
, FlowControlStartsWithMoreQuota
) {
2231 static const InitFrame frames
[] = {
2232 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "FOUR"}};
2233 Checkpoint checkpoint
;
2235 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2236 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2239 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2240 .WillOnce(ReturnFrames(&frames
));
2241 EXPECT_CALL(checkpoint
, Call(1));
2242 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2243 .WillOnce(Return(ERR_IO_PENDING
));
2246 set_stream(mock_stream_
.Pass());
2247 CreateChannelAndConnect();
2248 channel_
->SendFlowControl(4);
2249 connect_data_
.creator
.connect_delegate
->OnSuccess(stream_
.Pass());
2251 channel_
->SendFlowControl(4);
2254 // ReadFrames() isn't called again until all pending data has been passed to
2256 TEST_F(WebSocketChannelStreamTest
, ReadFramesNotCalledUntilQuotaAvailable
) {
2257 static const InitFrame frames
[] = {
2258 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "FOUR"}};
2259 Checkpoint checkpoint
;
2261 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2262 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2265 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2266 .WillOnce(ReturnFrames(&frames
));
2267 EXPECT_CALL(checkpoint
, Call(1));
2268 EXPECT_CALL(checkpoint
, Call(2));
2269 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2270 .WillOnce(Return(ERR_IO_PENDING
));
2273 set_stream(mock_stream_
.Pass());
2274 CreateChannelAndConnect();
2275 channel_
->SendFlowControl(2);
2276 connect_data_
.creator
.connect_delegate
->OnSuccess(stream_
.Pass());
2278 channel_
->SendFlowControl(2);
2280 channel_
->SendFlowControl(2);
2283 // A message that needs to be split into frames to fit within quota should
2284 // maintain correct semantics.
2285 TEST_F(WebSocketChannelFlowControlTest
, SingleFrameMessageSplitSync
) {
2286 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2287 new ReadableFakeWebSocketStream
);
2288 static const InitFrame frames
[] = {
2289 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "FOUR"}};
2290 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
2291 set_stream(stream
.Pass());
2294 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2295 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2298 OnDataFrame(false, WebSocketFrameHeader::kOpCodeText
, AsVector("FO")));
2302 false, WebSocketFrameHeader::kOpCodeContinuation
, AsVector("U")));
2306 true, WebSocketFrameHeader::kOpCodeContinuation
, AsVector("R")));
2309 CreateChannelAndConnectWithQuota(2);
2310 channel_
->SendFlowControl(1);
2311 channel_
->SendFlowControl(1);
2314 // The code path for async messages is slightly different, so test it
2316 TEST_F(WebSocketChannelFlowControlTest
, SingleFrameMessageSplitAsync
) {
2317 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2318 new ReadableFakeWebSocketStream
);
2319 static const InitFrame frames
[] = {
2320 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "FOUR"}};
2321 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC
, OK
, frames
);
2322 set_stream(stream
.Pass());
2323 Checkpoint checkpoint
;
2326 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2327 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2328 EXPECT_CALL(checkpoint
, Call(1));
2331 OnDataFrame(false, WebSocketFrameHeader::kOpCodeText
, AsVector("FO")));
2332 EXPECT_CALL(checkpoint
, Call(2));
2336 false, WebSocketFrameHeader::kOpCodeContinuation
, AsVector("U")));
2337 EXPECT_CALL(checkpoint
, Call(3));
2341 true, WebSocketFrameHeader::kOpCodeContinuation
, AsVector("R")));
2344 CreateChannelAndConnectWithQuota(2);
2346 base::MessageLoop::current()->RunUntilIdle();
2348 channel_
->SendFlowControl(1);
2350 channel_
->SendFlowControl(1);
2353 // A message split into multiple frames which is further split due to quota
2354 // restrictions should stil be correct.
2355 // TODO(ricea): The message ends up split into more frames than are strictly
2356 // necessary. The complexity/performance tradeoffs here need further
2358 TEST_F(WebSocketChannelFlowControlTest
, MultipleFrameSplit
) {
2359 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2360 new ReadableFakeWebSocketStream
);
2361 static const InitFrame frames
[] = {
2362 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
,
2363 NOT_MASKED
, "FIRST FRAME IS 25 BYTES. "},
2364 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
2365 NOT_MASKED
, "SECOND FRAME IS 26 BYTES. "},
2366 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
2367 NOT_MASKED
, "FINAL FRAME IS 24 BYTES."}};
2368 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
2369 set_stream(stream
.Pass());
2372 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2373 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2374 EXPECT_CALL(*event_interface_
,
2376 WebSocketFrameHeader::kOpCodeText
,
2377 AsVector("FIRST FRAME IS")));
2378 EXPECT_CALL(*event_interface_
,
2380 WebSocketFrameHeader::kOpCodeContinuation
,
2381 AsVector(" 25 BYTES. ")));
2382 EXPECT_CALL(*event_interface_
,
2384 WebSocketFrameHeader::kOpCodeContinuation
,
2385 AsVector("SECOND FRAME IS 26 BYTES. ")));
2386 EXPECT_CALL(*event_interface_
,
2388 WebSocketFrameHeader::kOpCodeContinuation
,
2389 AsVector("FINAL ")));
2390 EXPECT_CALL(*event_interface_
,
2392 WebSocketFrameHeader::kOpCodeContinuation
,
2393 AsVector("FRAME IS 24 BYTES.")));
2395 CreateChannelAndConnectWithQuota(14);
2396 channel_
->SendFlowControl(43);
2397 channel_
->SendFlowControl(32);
2400 // An empty message handled when we are out of quota must not be delivered
2401 // out-of-order with respect to other messages.
2402 TEST_F(WebSocketChannelFlowControlTest
, EmptyMessageNoQuota
) {
2403 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2404 new ReadableFakeWebSocketStream
);
2405 static const InitFrame frames
[] = {
2406 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
,
2407 NOT_MASKED
, "FIRST MESSAGE"},
2408 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
,
2410 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
,
2411 NOT_MASKED
, "THIRD MESSAGE"}};
2412 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
2413 set_stream(stream
.Pass());
2416 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2417 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2418 EXPECT_CALL(*event_interface_
,
2420 WebSocketFrameHeader::kOpCodeText
,
2421 AsVector("FIRST ")));
2422 EXPECT_CALL(*event_interface_
,
2424 WebSocketFrameHeader::kOpCodeContinuation
,
2425 AsVector("MESSAGE")));
2426 EXPECT_CALL(*event_interface_
,
2428 WebSocketFrameHeader::kOpCodeText
,
2430 EXPECT_CALL(*event_interface_
,
2432 WebSocketFrameHeader::kOpCodeText
,
2433 AsVector("THIRD MESSAGE")));
2436 CreateChannelAndConnectWithQuota(6);
2437 channel_
->SendFlowControl(128);
2440 // RFC6455 5.1 "a client MUST mask all frames that it sends to the server".
2441 // WebSocketChannel actually only sets the mask bit in the header, it doesn't
2442 // perform masking itself (not all transports actually use masking).
2443 TEST_F(WebSocketChannelStreamTest
, SentFramesAreMasked
) {
2444 static const InitFrame expected
[] = {
2445 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
,
2446 MASKED
, "NEEDS MASKING"}};
2447 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2448 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2449 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
)).WillOnce(Return(ERR_IO_PENDING
));
2450 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2451 .WillOnce(Return(OK
));
2453 CreateChannelAndConnectSuccessfully();
2454 channel_
->SendFrame(
2455 true, WebSocketFrameHeader::kOpCodeText
, AsVector("NEEDS MASKING"));
2458 // RFC6455 5.5.1 "The application MUST NOT send any more data frames after
2459 // sending a Close frame."
2460 TEST_F(WebSocketChannelStreamTest
, NothingIsSentAfterClose
) {
2461 static const InitFrame expected
[] = {
2462 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2463 MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "Success")}};
2464 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2465 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2466 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
)).WillOnce(Return(ERR_IO_PENDING
));
2467 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2468 .WillOnce(Return(OK
));
2470 CreateChannelAndConnectSuccessfully();
2471 channel_
->StartClosingHandshake(1000, "Success");
2472 channel_
->SendFrame(
2473 true, WebSocketFrameHeader::kOpCodeText
, AsVector("SHOULD BE IGNORED"));
2476 // RFC6455 5.5.1 "If an endpoint receives a Close frame and did not previously
2477 // send a Close frame, the endpoint MUST send a Close frame in response."
2478 TEST_F(WebSocketChannelStreamTest
, CloseIsEchoedBack
) {
2479 static const InitFrame frames
[] = {
2480 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2481 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "Close")}};
2482 static const InitFrame expected
[] = {
2483 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2484 MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "Close")}};
2485 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2486 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2487 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2488 .WillOnce(ReturnFrames(&frames
))
2489 .WillRepeatedly(Return(ERR_IO_PENDING
));
2490 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2491 .WillOnce(Return(OK
));
2493 CreateChannelAndConnectSuccessfully();
2496 // The converse of the above case; after sending a Close frame, we should not
2497 // send another one.
2498 TEST_F(WebSocketChannelStreamTest
, CloseOnlySentOnce
) {
2499 static const InitFrame expected
[] = {
2500 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2501 MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "Close")}};
2502 static const InitFrame frames_init
[] = {
2503 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2504 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "Close")}};
2506 // We store the parameters that were passed to ReadFrames() so that we can
2507 // call them explicitly later.
2508 CompletionCallback read_callback
;
2509 ScopedVector
<WebSocketFrame
>* frames
= NULL
;
2511 // These are not interesting.
2512 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2513 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2515 // Use a checkpoint to make the ordering of events clearer.
2516 Checkpoint checkpoint
;
2519 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2520 .WillOnce(DoAll(SaveArg
<0>(&frames
),
2521 SaveArg
<1>(&read_callback
),
2522 Return(ERR_IO_PENDING
)));
2523 EXPECT_CALL(checkpoint
, Call(1));
2524 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2525 .WillOnce(Return(OK
));
2526 EXPECT_CALL(checkpoint
, Call(2));
2527 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2528 .WillOnce(Return(ERR_IO_PENDING
));
2529 EXPECT_CALL(checkpoint
, Call(3));
2530 // WriteFrames() must not be called again. GoogleMock will ensure that the
2531 // test fails if it is.
2534 CreateChannelAndConnectSuccessfully();
2536 channel_
->StartClosingHandshake(kWebSocketNormalClosure
, "Close");
2539 *frames
= CreateFrameVector(frames_init
);
2540 read_callback
.Run(OK
);
2544 // Invalid close status codes should not be sent on the network.
2545 TEST_F(WebSocketChannelStreamTest
, InvalidCloseStatusCodeNotSent
) {
2546 static const InitFrame expected
[] = {
2547 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2548 MASKED
, CLOSE_DATA(SERVER_ERROR
, "")}};
2550 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2551 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2552 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2553 .WillOnce(Return(ERR_IO_PENDING
));
2555 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
));
2557 CreateChannelAndConnectSuccessfully();
2558 channel_
->StartClosingHandshake(999, "");
2561 // A Close frame with a reason longer than 123 bytes cannot be sent on the
2563 TEST_F(WebSocketChannelStreamTest
, LongCloseReasonNotSent
) {
2564 static const InitFrame expected
[] = {
2565 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2566 MASKED
, CLOSE_DATA(SERVER_ERROR
, "")}};
2568 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2569 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2570 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2571 .WillOnce(Return(ERR_IO_PENDING
));
2573 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
));
2575 CreateChannelAndConnectSuccessfully();
2576 channel_
->StartClosingHandshake(1000, std::string(124, 'A'));
2579 // We generate code 1005, kWebSocketErrorNoStatusReceived, when there is no
2580 // status in the Close message from the other side. Code 1005 is not allowed to
2581 // appear on the wire, so we should not echo it back. See test
2582 // CloseWithNoPayloadGivesStatus1005, above, for confirmation that code 1005 is
2583 // correctly generated internally.
2584 TEST_F(WebSocketChannelStreamTest
, Code1005IsNotEchoed
) {
2585 static const InitFrame frames
[] = {
2586 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, NOT_MASKED
, ""}};
2587 static const InitFrame expected
[] = {
2588 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, MASKED
, ""}};
2589 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2590 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2591 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2592 .WillOnce(ReturnFrames(&frames
))
2593 .WillRepeatedly(Return(ERR_IO_PENDING
));
2594 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2595 .WillOnce(Return(OK
));
2597 CreateChannelAndConnectSuccessfully();
2600 TEST_F(WebSocketChannelStreamTest
, Code1005IsNotEchoedNull
) {
2601 static const InitFrame frames
[] = {
2602 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, NOT_MASKED
, NULL
}};
2603 static const InitFrame expected
[] = {
2604 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, MASKED
, ""}};
2605 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2606 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2607 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2608 .WillOnce(ReturnFrames(&frames
))
2609 .WillRepeatedly(Return(ERR_IO_PENDING
));
2610 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2611 .WillOnce(Return(OK
));
2613 CreateChannelAndConnectSuccessfully();
2616 // Receiving an invalid UTF-8 payload in a Close frame causes us to fail the
2618 TEST_F(WebSocketChannelStreamTest
, CloseFrameInvalidUtf8
) {
2619 static const InitFrame frames
[] = {
2620 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2621 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "\xFF")}};
2622 static const InitFrame expected
[] = {
2623 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2624 MASKED
, CLOSE_DATA(PROTOCOL_ERROR
, "Invalid UTF-8 in Close frame")}};
2626 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2627 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2628 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2629 .WillOnce(ReturnFrames(&frames
))
2630 .WillRepeatedly(Return(ERR_IO_PENDING
));
2631 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2632 .WillOnce(Return(OK
));
2633 EXPECT_CALL(*mock_stream_
, Close());
2635 CreateChannelAndConnectSuccessfully();
2638 // RFC6455 5.5.2 "Upon receipt of a Ping frame, an endpoint MUST send a Pong
2639 // frame in response"
2640 // 5.5.3 "A Pong frame sent in response to a Ping frame must have identical
2641 // "Application data" as found in the message body of the Ping frame being
2643 TEST_F(WebSocketChannelStreamTest
, PingRepliedWithPong
) {
2644 static const InitFrame frames
[] = {
2645 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePing
,
2646 NOT_MASKED
, "Application data"}};
2647 static const InitFrame expected
[] = {
2648 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePong
,
2649 MASKED
, "Application data"}};
2650 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2651 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2652 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2653 .WillOnce(ReturnFrames(&frames
))
2654 .WillRepeatedly(Return(ERR_IO_PENDING
));
2655 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2656 .WillOnce(Return(OK
));
2658 CreateChannelAndConnectSuccessfully();
2661 // A ping with a NULL payload should be responded to with a Pong with a NULL
2663 TEST_F(WebSocketChannelStreamTest
, NullPingRepliedWithNullPong
) {
2664 static const InitFrame frames
[] = {
2665 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePing
, NOT_MASKED
, NULL
}};
2666 static const InitFrame expected
[] = {
2667 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePong
, MASKED
, NULL
}};
2668 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2669 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2670 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2671 .WillOnce(ReturnFrames(&frames
))
2672 .WillRepeatedly(Return(ERR_IO_PENDING
));
2673 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2674 .WillOnce(Return(OK
));
2676 CreateChannelAndConnectSuccessfully();
2679 TEST_F(WebSocketChannelStreamTest
, PongInTheMiddleOfDataMessage
) {
2680 static const InitFrame frames
[] = {
2681 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePing
,
2682 NOT_MASKED
, "Application data"}};
2683 static const InitFrame expected1
[] = {
2684 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "Hello "}};
2685 static const InitFrame expected2
[] = {
2686 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePong
,
2687 MASKED
, "Application data"}};
2688 static const InitFrame expected3
[] = {
2689 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
2691 ScopedVector
<WebSocketFrame
>* read_frames
;
2692 CompletionCallback read_callback
;
2693 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2694 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2695 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2696 .WillOnce(DoAll(SaveArg
<0>(&read_frames
),
2697 SaveArg
<1>(&read_callback
),
2698 Return(ERR_IO_PENDING
)))
2699 .WillRepeatedly(Return(ERR_IO_PENDING
));
2703 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected1
), _
))
2704 .WillOnce(Return(OK
));
2705 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected2
), _
))
2706 .WillOnce(Return(OK
));
2707 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected3
), _
))
2708 .WillOnce(Return(OK
));
2711 CreateChannelAndConnectSuccessfully();
2712 channel_
->SendFrame(
2713 false, WebSocketFrameHeader::kOpCodeText
, AsVector("Hello "));
2714 *read_frames
= CreateFrameVector(frames
);
2715 read_callback
.Run(OK
);
2716 channel_
->SendFrame(
2717 true, WebSocketFrameHeader::kOpCodeContinuation
, AsVector("World"));
2720 // WriteFrames() may not be called until the previous write has completed.
2721 // WebSocketChannel must buffer writes that happen in the meantime.
2722 TEST_F(WebSocketChannelStreamTest
, WriteFramesOneAtATime
) {
2723 static const InitFrame expected1
[] = {
2724 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "Hello "}};
2725 static const InitFrame expected2
[] = {
2726 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "World"}};
2727 CompletionCallback write_callback
;
2728 Checkpoint checkpoint
;
2730 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2731 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2732 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
)).WillOnce(Return(ERR_IO_PENDING
));
2735 EXPECT_CALL(checkpoint
, Call(1));
2736 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected1
), _
))
2737 .WillOnce(DoAll(SaveArg
<1>(&write_callback
), Return(ERR_IO_PENDING
)));
2738 EXPECT_CALL(checkpoint
, Call(2));
2739 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected2
), _
))
2740 .WillOnce(Return(ERR_IO_PENDING
));
2741 EXPECT_CALL(checkpoint
, Call(3));
2744 CreateChannelAndConnectSuccessfully();
2746 channel_
->SendFrame(
2747 false, WebSocketFrameHeader::kOpCodeText
, AsVector("Hello "));
2748 channel_
->SendFrame(
2749 true, WebSocketFrameHeader::kOpCodeText
, AsVector("World"));
2751 write_callback
.Run(OK
);
2755 // WebSocketChannel must buffer frames while it is waiting for a write to
2756 // complete, and then send them in a single batch. The batching behaviour is
2757 // important to get good throughput in the "many small messages" case.
2758 TEST_F(WebSocketChannelStreamTest
, WaitingMessagesAreBatched
) {
2759 static const char input_letters
[] = "Hello";
2760 static const InitFrame expected1
[] = {
2761 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "H"}};
2762 static const InitFrame expected2
[] = {
2763 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "e"},
2764 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "l"},
2765 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "l"},
2766 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, MASKED
, "o"}};
2767 CompletionCallback write_callback
;
2769 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2770 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2771 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
)).WillOnce(Return(ERR_IO_PENDING
));
2774 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected1
), _
))
2775 .WillOnce(DoAll(SaveArg
<1>(&write_callback
), Return(ERR_IO_PENDING
)));
2776 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected2
), _
))
2777 .WillOnce(Return(ERR_IO_PENDING
));
2780 CreateChannelAndConnectSuccessfully();
2781 for (size_t i
= 0; i
< strlen(input_letters
); ++i
) {
2782 channel_
->SendFrame(true,
2783 WebSocketFrameHeader::kOpCodeText
,
2784 std::vector
<char>(1, input_letters
[i
]));
2786 write_callback
.Run(OK
);
2789 // When the renderer sends more on a channel than it has quota for, we send the
2790 // remote server a kWebSocketErrorGoingAway error code.
2791 TEST_F(WebSocketChannelStreamTest
, SendGoingAwayOnRendererQuotaExceeded
) {
2792 static const InitFrame expected
[] = {
2793 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
2794 MASKED
, CLOSE_DATA(GOING_AWAY
, "")}};
2795 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2796 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2797 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
)).WillOnce(Return(ERR_IO_PENDING
));
2798 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2799 .WillOnce(Return(OK
));
2800 EXPECT_CALL(*mock_stream_
, Close());
2802 CreateChannelAndConnectSuccessfully();
2803 channel_
->SendFrame(true,
2804 WebSocketFrameHeader::kOpCodeText
,
2805 std::vector
<char>(kDefaultInitialQuota
+ 1, 'C'));
2808 // For convenience, most of these tests use Text frames. However, the WebSocket
2809 // protocol also has Binary frames and those need to be 8-bit clean. For the
2810 // sake of completeness, this test verifies that they are.
2811 TEST_F(WebSocketChannelStreamTest
, WrittenBinaryFramesAre8BitClean
) {
2812 ScopedVector
<WebSocketFrame
>* frames
= NULL
;
2814 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2815 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2816 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
)).WillOnce(Return(ERR_IO_PENDING
));
2817 EXPECT_CALL(*mock_stream_
, WriteFrames(_
, _
))
2818 .WillOnce(DoAll(SaveArg
<0>(&frames
), Return(ERR_IO_PENDING
)));
2820 CreateChannelAndConnectSuccessfully();
2821 channel_
->SendFrame(
2823 WebSocketFrameHeader::kOpCodeBinary
,
2824 std::vector
<char>(kBinaryBlob
, kBinaryBlob
+ kBinaryBlobSize
));
2825 ASSERT_TRUE(frames
!= NULL
);
2826 ASSERT_EQ(1U, frames
->size());
2827 const WebSocketFrame
* out_frame
= (*frames
)[0];
2828 EXPECT_EQ(kBinaryBlobSize
, out_frame
->header
.payload_length
);
2829 ASSERT_TRUE(out_frame
->data
);
2830 EXPECT_EQ(0, memcmp(kBinaryBlob
, out_frame
->data
->data(), kBinaryBlobSize
));
2833 // Test the read path for 8-bit cleanliness as well.
2834 TEST_F(WebSocketChannelEventInterfaceTest
, ReadBinaryFramesAre8BitClean
) {
2835 scoped_ptr
<WebSocketFrame
> frame(
2836 new WebSocketFrame(WebSocketFrameHeader::kOpCodeBinary
));
2837 WebSocketFrameHeader
& frame_header
= frame
->header
;
2838 frame_header
.final
= true;
2839 frame_header
.payload_length
= kBinaryBlobSize
;
2840 frame
->data
= new IOBuffer(kBinaryBlobSize
);
2841 memcpy(frame
->data
->data(), kBinaryBlob
, kBinaryBlobSize
);
2842 ScopedVector
<WebSocketFrame
> frames
;
2843 frames
.push_back(frame
.release());
2844 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2845 new ReadableFakeWebSocketStream
);
2846 stream
->PrepareRawReadFrames(
2847 ReadableFakeWebSocketStream::SYNC
, OK
, frames
.Pass());
2848 set_stream(stream
.Pass());
2849 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2850 EXPECT_CALL(*event_interface_
, OnFlowControl(_
));
2851 EXPECT_CALL(*event_interface_
,
2853 WebSocketFrameHeader::kOpCodeBinary
,
2854 std::vector
<char>(kBinaryBlob
,
2855 kBinaryBlob
+ kBinaryBlobSize
)));
2857 CreateChannelAndConnectSuccessfully();
2860 // Invalid UTF-8 is not permitted in Text frames.
2861 TEST_F(WebSocketChannelSendUtf8Test
, InvalidUtf8Rejected
) {
2864 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2866 CreateChannelAndConnectSuccessfully();
2868 channel_
->SendFrame(
2869 true, WebSocketFrameHeader::kOpCodeText
, AsVector("\xff"));
2872 // A Text message cannot end with a partial UTF-8 character.
2873 TEST_F(WebSocketChannelSendUtf8Test
, IncompleteCharacterInFinalFrame
) {
2876 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2878 CreateChannelAndConnectSuccessfully();
2880 channel_
->SendFrame(
2881 true, WebSocketFrameHeader::kOpCodeText
, AsVector("\xc2"));
2884 // A non-final Text frame may end with a partial UTF-8 character (compare to
2886 TEST_F(WebSocketChannelSendUtf8Test
, IncompleteCharacterInNonFinalFrame
) {
2887 CreateChannelAndConnectSuccessfully();
2889 channel_
->SendFrame(
2890 false, WebSocketFrameHeader::kOpCodeText
, AsVector("\xc2"));
2893 // UTF-8 parsing context must be retained between frames.
2894 TEST_F(WebSocketChannelSendUtf8Test
, ValidCharacterSplitBetweenFrames
) {
2895 CreateChannelAndConnectSuccessfully();
2897 channel_
->SendFrame(
2898 false, WebSocketFrameHeader::kOpCodeText
, AsVector("\xf1"));
2899 channel_
->SendFrame(true,
2900 WebSocketFrameHeader::kOpCodeContinuation
,
2901 AsVector("\x80\xa0\xbf"));
2904 // Similarly, an invalid character should be detected even if split.
2905 TEST_F(WebSocketChannelSendUtf8Test
, InvalidCharacterSplit
) {
2908 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2910 CreateChannelAndConnectSuccessfully();
2912 channel_
->SendFrame(
2913 false, WebSocketFrameHeader::kOpCodeText
, AsVector("\xe1"));
2914 channel_
->SendFrame(true,
2915 WebSocketFrameHeader::kOpCodeContinuation
,
2916 AsVector("\x80\xa0\xbf"));
2919 // An invalid character must be detected in continuation frames.
2920 TEST_F(WebSocketChannelSendUtf8Test
, InvalidByteInContinuation
) {
2923 OnFailChannel("Browser sent a text frame containing invalid UTF-8"));
2925 CreateChannelAndConnectSuccessfully();
2927 channel_
->SendFrame(
2928 false, WebSocketFrameHeader::kOpCodeText
, AsVector("foo"));
2929 channel_
->SendFrame(
2930 false, WebSocketFrameHeader::kOpCodeContinuation
, AsVector("bar"));
2931 channel_
->SendFrame(
2932 true, WebSocketFrameHeader::kOpCodeContinuation
, AsVector("\xff"));
2935 // However, continuation frames of a Binary frame will not be tested for UTF-8
2937 TEST_F(WebSocketChannelSendUtf8Test
, BinaryContinuationNotChecked
) {
2938 CreateChannelAndConnectSuccessfully();
2940 channel_
->SendFrame(
2941 false, WebSocketFrameHeader::kOpCodeBinary
, AsVector("foo"));
2942 channel_
->SendFrame(
2943 false, WebSocketFrameHeader::kOpCodeContinuation
, AsVector("bar"));
2944 channel_
->SendFrame(
2945 true, WebSocketFrameHeader::kOpCodeContinuation
, AsVector("\xff"));
2948 // Multiple text messages can be validated without the validation state getting
2950 TEST_F(WebSocketChannelSendUtf8Test
, ValidateMultipleTextMessages
) {
2951 CreateChannelAndConnectSuccessfully();
2953 channel_
->SendFrame(true, WebSocketFrameHeader::kOpCodeText
, AsVector("foo"));
2954 channel_
->SendFrame(true, WebSocketFrameHeader::kOpCodeText
, AsVector("bar"));
2957 // UTF-8 validation is enforced on received Text frames.
2958 TEST_F(WebSocketChannelEventInterfaceTest
, ReceivedInvalidUtf8
) {
2959 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
2960 new ReadableFakeWebSocketStream
);
2961 static const InitFrame frames
[] = {
2962 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "\xff"}};
2963 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
2964 set_stream(stream
.Pass());
2966 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
2967 EXPECT_CALL(*event_interface_
, OnFlowControl(kDefaultInitialQuota
));
2968 EXPECT_CALL(*event_interface_
,
2969 OnFailChannel("Could not decode a text frame as UTF-8."));
2971 CreateChannelAndConnectSuccessfully();
2972 base::MessageLoop::current()->RunUntilIdle();
2975 // Invalid UTF-8 is not sent over the network.
2976 TEST_F(WebSocketChannelStreamTest
, InvalidUtf8TextFrameNotSent
) {
2977 static const InitFrame expected
[] = {{FINAL_FRAME
,
2978 WebSocketFrameHeader::kOpCodeClose
,
2979 MASKED
, CLOSE_DATA(GOING_AWAY
, "")}};
2980 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
2981 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
2982 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
2983 .WillRepeatedly(Return(ERR_IO_PENDING
));
2984 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
2985 .WillOnce(Return(OK
));
2986 EXPECT_CALL(*mock_stream_
, Close()).Times(1);
2988 CreateChannelAndConnectSuccessfully();
2990 channel_
->SendFrame(
2991 true, WebSocketFrameHeader::kOpCodeText
, AsVector("\xff"));
2994 // The rest of the tests for receiving invalid UTF-8 test the communication with
2995 // the server. Since there is only one code path, it would be redundant to
2996 // perform the same tests on the EventInterface as well.
2998 // If invalid UTF-8 is received in a Text frame, the connection is failed.
2999 TEST_F(WebSocketChannelReceiveUtf8Test
, InvalidTextFrameRejected
) {
3000 static const InitFrame frames
[] = {
3001 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "\xff"}};
3002 static const InitFrame expected
[] = {
3003 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, MASKED
,
3004 CLOSE_DATA(PROTOCOL_ERROR
, "Invalid UTF-8 in text frame")}};
3007 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3008 .WillOnce(ReturnFrames(&frames
))
3009 .WillRepeatedly(Return(ERR_IO_PENDING
));
3010 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
3011 .WillOnce(Return(OK
));
3012 EXPECT_CALL(*mock_stream_
, Close()).Times(1);
3015 CreateChannelAndConnectSuccessfully();
3018 // A received Text message is not permitted to end with a partial UTF-8
3020 TEST_F(WebSocketChannelReceiveUtf8Test
, IncompleteCharacterReceived
) {
3021 static const InitFrame frames
[] = {
3022 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "\xc2"}};
3023 static const InitFrame expected
[] = {
3024 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, MASKED
,
3025 CLOSE_DATA(PROTOCOL_ERROR
, "Invalid UTF-8 in text frame")}};
3026 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3027 .WillOnce(ReturnFrames(&frames
))
3028 .WillRepeatedly(Return(ERR_IO_PENDING
));
3029 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
3030 .WillOnce(Return(OK
));
3031 EXPECT_CALL(*mock_stream_
, Close()).Times(1);
3033 CreateChannelAndConnectSuccessfully();
3036 // However, a non-final Text frame may end with a partial UTF-8 character.
3037 TEST_F(WebSocketChannelReceiveUtf8Test
, IncompleteCharacterIncompleteMessage
) {
3038 static const InitFrame frames
[] = {
3039 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "\xc2"}};
3040 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3041 .WillOnce(ReturnFrames(&frames
))
3042 .WillRepeatedly(Return(ERR_IO_PENDING
));
3044 CreateChannelAndConnectSuccessfully();
3047 // However, it will become an error if it is followed by an empty final frame.
3048 TEST_F(WebSocketChannelReceiveUtf8Test
, TricksyIncompleteCharacter
) {
3049 static const InitFrame frames
[] = {
3050 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "\xc2"},
3051 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
, NOT_MASKED
, ""}};
3052 static const InitFrame expected
[] = {
3053 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, MASKED
,
3054 CLOSE_DATA(PROTOCOL_ERROR
, "Invalid UTF-8 in text frame")}};
3055 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3056 .WillOnce(ReturnFrames(&frames
))
3057 .WillRepeatedly(Return(ERR_IO_PENDING
));
3058 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
3059 .WillOnce(Return(OK
));
3060 EXPECT_CALL(*mock_stream_
, Close()).Times(1);
3062 CreateChannelAndConnectSuccessfully();
3065 // UTF-8 parsing context must be retained between received frames of the same
3067 TEST_F(WebSocketChannelReceiveUtf8Test
, ReceivedParsingContextRetained
) {
3068 static const InitFrame frames
[] = {
3069 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "\xf1"},
3070 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
3071 NOT_MASKED
, "\x80\xa0\xbf"}};
3072 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3073 .WillOnce(ReturnFrames(&frames
))
3074 .WillRepeatedly(Return(ERR_IO_PENDING
));
3076 CreateChannelAndConnectSuccessfully();
3079 // An invalid character must be detected even if split between frames.
3080 TEST_F(WebSocketChannelReceiveUtf8Test
, SplitInvalidCharacterReceived
) {
3081 static const InitFrame frames
[] = {
3082 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "\xe1"},
3083 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
3084 NOT_MASKED
, "\x80\xa0\xbf"}};
3085 static const InitFrame expected
[] = {
3086 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, MASKED
,
3087 CLOSE_DATA(PROTOCOL_ERROR
, "Invalid UTF-8 in text frame")}};
3088 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3089 .WillOnce(ReturnFrames(&frames
))
3090 .WillRepeatedly(Return(ERR_IO_PENDING
));
3091 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
3092 .WillOnce(Return(OK
));
3093 EXPECT_CALL(*mock_stream_
, Close()).Times(1);
3095 CreateChannelAndConnectSuccessfully();
3098 // An invalid character received in a continuation frame must be detected.
3099 TEST_F(WebSocketChannelReceiveUtf8Test
, InvalidReceivedIncontinuation
) {
3100 static const InitFrame frames
[] = {
3101 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "foo"},
3102 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
3104 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
3105 NOT_MASKED
, "\xff"}};
3106 static const InitFrame expected
[] = {
3107 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
, MASKED
,
3108 CLOSE_DATA(PROTOCOL_ERROR
, "Invalid UTF-8 in text frame")}};
3109 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3110 .WillOnce(ReturnFrames(&frames
))
3111 .WillRepeatedly(Return(ERR_IO_PENDING
));
3112 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
3113 .WillOnce(Return(OK
));
3114 EXPECT_CALL(*mock_stream_
, Close()).Times(1);
3116 CreateChannelAndConnectSuccessfully();
3119 // Continuations of binary frames must not be tested for UTF-8 validity.
3120 TEST_F(WebSocketChannelReceiveUtf8Test
, ReceivedBinaryNotUtf8Tested
) {
3121 static const InitFrame frames
[] = {
3122 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeBinary
, NOT_MASKED
, "foo"},
3123 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
3125 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
3126 NOT_MASKED
, "\xff"}};
3127 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3128 .WillOnce(ReturnFrames(&frames
))
3129 .WillRepeatedly(Return(ERR_IO_PENDING
));
3131 CreateChannelAndConnectSuccessfully();
3134 // Multiple Text messages can be validated.
3135 TEST_F(WebSocketChannelReceiveUtf8Test
, ValidateMultipleReceived
) {
3136 static const InitFrame frames
[] = {
3137 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "foo"},
3138 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, "bar"}};
3139 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3140 .WillOnce(ReturnFrames(&frames
))
3141 .WillRepeatedly(Return(ERR_IO_PENDING
));
3143 CreateChannelAndConnectSuccessfully();
3146 // A new data message cannot start in the middle of another data message.
3147 TEST_F(WebSocketChannelEventInterfaceTest
, BogusContinuation
) {
3148 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
3149 new ReadableFakeWebSocketStream
);
3150 static const InitFrame frames
[] = {
3151 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeBinary
,
3152 NOT_MASKED
, "frame1"},
3153 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
,
3154 NOT_MASKED
, "frame2"}};
3155 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
3156 set_stream(stream
.Pass());
3158 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
3159 EXPECT_CALL(*event_interface_
, OnFlowControl(kDefaultInitialQuota
));
3163 false, WebSocketFrameHeader::kOpCodeBinary
, AsVector("frame1")));
3167 "Received start of new message but previous message is unfinished."));
3169 CreateChannelAndConnectSuccessfully();
3172 // A new message cannot start with a Continuation frame.
3173 TEST_F(WebSocketChannelEventInterfaceTest
, MessageStartingWithContinuation
) {
3174 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
3175 new ReadableFakeWebSocketStream
);
3176 static const InitFrame frames
[] = {
3177 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
3178 NOT_MASKED
, "continuation"}};
3179 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
3180 set_stream(stream
.Pass());
3182 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
3183 EXPECT_CALL(*event_interface_
, OnFlowControl(kDefaultInitialQuota
));
3184 EXPECT_CALL(*event_interface_
,
3185 OnFailChannel("Received unexpected continuation frame."));
3187 CreateChannelAndConnectSuccessfully();
3190 // A frame passed to the renderer must be either non-empty or have the final bit
3192 TEST_F(WebSocketChannelEventInterfaceTest
, DataFramesNonEmptyOrFinal
) {
3193 scoped_ptr
<ReadableFakeWebSocketStream
> stream(
3194 new ReadableFakeWebSocketStream
);
3195 static const InitFrame frames
[] = {
3196 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeText
, NOT_MASKED
, ""},
3197 {NOT_FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
,
3199 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeContinuation
, NOT_MASKED
, ""}};
3200 stream
->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC
, OK
, frames
);
3201 set_stream(stream
.Pass());
3203 EXPECT_CALL(*event_interface_
, OnAddChannelResponse(false, _
, _
));
3204 EXPECT_CALL(*event_interface_
, OnFlowControl(kDefaultInitialQuota
));
3207 OnDataFrame(true, WebSocketFrameHeader::kOpCodeText
, AsVector("")));
3209 CreateChannelAndConnectSuccessfully();
3212 // If we receive another frame after Close, it is not valid. It is not
3213 // completely clear what behaviour is required from the standard in this case,
3214 // but the current implementation fails the connection. Since a Close has
3215 // already been sent, this just means closing the connection.
3216 TEST_F(WebSocketChannelStreamTest
, PingAfterCloseIsRejected
) {
3217 static const InitFrame frames
[] = {
3218 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
3219 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "OK")},
3220 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodePing
,
3221 NOT_MASKED
, "Ping body"}};
3222 static const InitFrame expected
[] = {
3223 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
3224 MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "OK")}};
3225 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
3226 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
3227 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3228 .WillOnce(ReturnFrames(&frames
))
3229 .WillRepeatedly(Return(ERR_IO_PENDING
));
3231 // We only need to verify the relative order of WriteFrames() and
3232 // Close(). The current implementation calls WriteFrames() for the Close
3233 // frame before calling ReadFrames() again, but that is an implementation
3234 // detail and better not to consider required behaviour.
3236 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
3237 .WillOnce(Return(OK
));
3238 EXPECT_CALL(*mock_stream_
, Close()).Times(1);
3241 CreateChannelAndConnectSuccessfully();
3244 // A protocol error from the remote server should result in a close frame with
3245 // status 1002, followed by the connection closing.
3246 TEST_F(WebSocketChannelStreamTest
, ProtocolError
) {
3247 static const InitFrame expected
[] = {
3248 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
3249 MASKED
, CLOSE_DATA(PROTOCOL_ERROR
, "WebSocket Protocol Error")}};
3250 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
3251 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
3252 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3253 .WillOnce(Return(ERR_WS_PROTOCOL_ERROR
));
3254 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
3255 .WillOnce(Return(OK
));
3256 EXPECT_CALL(*mock_stream_
, Close());
3258 CreateChannelAndConnectSuccessfully();
3261 // Set the closing handshake timeout to a very tiny value before connecting.
3262 class WebSocketChannelStreamTimeoutTest
: public WebSocketChannelStreamTest
{
3264 WebSocketChannelStreamTimeoutTest() {}
3266 virtual void CreateChannelAndConnectSuccessfully() OVERRIDE
{
3267 set_stream(mock_stream_
.Pass());
3268 CreateChannelAndConnect();
3269 channel_
->SendFlowControl(kPlentyOfQuota
);
3270 channel_
->SetClosingHandshakeTimeoutForTesting(
3271 TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis
));
3272 connect_data_
.creator
.connect_delegate
->OnSuccess(stream_
.Pass());
3276 // In this case the server initiates the closing handshake with a Close
3277 // message. WebSocketChannel responds with a matching Close message, and waits
3278 // for the server to close the TCP/IP connection. The server never closes the
3279 // connection, so the closing handshake times out and WebSocketChannel closes
3280 // the connection itself.
3281 TEST_F(WebSocketChannelStreamTimeoutTest
, ServerInitiatedCloseTimesOut
) {
3282 static const InitFrame frames
[] = {
3283 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
3284 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "OK")}};
3285 static const InitFrame expected
[] = {
3286 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
3287 MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "OK")}};
3288 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
3289 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
3290 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3291 .WillOnce(ReturnFrames(&frames
))
3292 .WillRepeatedly(Return(ERR_IO_PENDING
));
3293 Checkpoint checkpoint
;
3294 TestClosure completion
;
3297 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
3298 .WillOnce(Return(OK
));
3299 EXPECT_CALL(checkpoint
, Call(1));
3300 EXPECT_CALL(*mock_stream_
, Close())
3301 .WillOnce(InvokeClosure(completion
.closure()));
3304 CreateChannelAndConnectSuccessfully();
3306 completion
.WaitForResult();
3309 // In this case the client initiates the closing handshake by sending a Close
3310 // message. WebSocketChannel waits for a Close message in response from the
3311 // server. The server never responds to the Close message, so the closing
3312 // handshake times out and WebSocketChannel closes the connection.
3313 TEST_F(WebSocketChannelStreamTimeoutTest
, ClientInitiatedCloseTimesOut
) {
3314 static const InitFrame expected
[] = {
3315 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
3316 MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "OK")}};
3317 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
3318 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
3319 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3320 .WillRepeatedly(Return(ERR_IO_PENDING
));
3321 TestClosure completion
;
3324 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
3325 .WillOnce(Return(OK
));
3326 EXPECT_CALL(*mock_stream_
, Close())
3327 .WillOnce(InvokeClosure(completion
.closure()));
3330 CreateChannelAndConnectSuccessfully();
3331 channel_
->StartClosingHandshake(kWebSocketNormalClosure
, "OK");
3332 completion
.WaitForResult();
3335 // In this case the client initiates the closing handshake and the server
3336 // responds with a matching Close message. WebSocketChannel waits for the server
3337 // to close the TCP/IP connection, but it never does. The closing handshake
3338 // times out and WebSocketChannel closes the connection.
3339 TEST_F(WebSocketChannelStreamTimeoutTest
, ConnectionCloseTimesOut
) {
3340 static const InitFrame expected
[] = {
3341 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
3342 MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "OK")}};
3343 static const InitFrame frames
[] = {
3344 {FINAL_FRAME
, WebSocketFrameHeader::kOpCodeClose
,
3345 NOT_MASKED
, CLOSE_DATA(NORMAL_CLOSURE
, "OK")}};
3346 EXPECT_CALL(*mock_stream_
, GetSubProtocol()).Times(AnyNumber());
3347 EXPECT_CALL(*mock_stream_
, GetExtensions()).Times(AnyNumber());
3348 TestClosure completion
;
3349 ScopedVector
<WebSocketFrame
>* read_frames
= NULL
;
3350 CompletionCallback read_callback
;
3353 // Copy the arguments to ReadFrames so that the test can call the callback
3354 // after it has send the close message.
3355 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3356 .WillOnce(DoAll(SaveArg
<0>(&read_frames
),
3357 SaveArg
<1>(&read_callback
),
3358 Return(ERR_IO_PENDING
)));
3359 // The first real event that happens is the client sending the Close
3361 EXPECT_CALL(*mock_stream_
, WriteFrames(EqualsFrames(expected
), _
))
3362 .WillOnce(Return(OK
));
3363 // The |read_frames| callback is called (from this test case) at this
3364 // point. ReadFrames is called again by WebSocketChannel, waiting for
3365 // ERR_CONNECTION_CLOSED.
3366 EXPECT_CALL(*mock_stream_
, ReadFrames(_
, _
))
3367 .WillOnce(Return(ERR_IO_PENDING
));
3368 // The timeout happens and so WebSocketChannel closes the stream.
3369 EXPECT_CALL(*mock_stream_
, Close())
3370 .WillOnce(InvokeClosure(completion
.closure()));
3373 CreateChannelAndConnectSuccessfully();
3374 channel_
->StartClosingHandshake(kWebSocketNormalClosure
, "OK");
3375 ASSERT_TRUE(read_frames
);
3376 // Provide the "Close" message from the server.
3377 *read_frames
= CreateFrameVector(frames
);
3378 read_callback
.Run(OK
);
3379 completion
.WaitForResult();