| Index: net/websockets/websocket_channel_test.cc
|
| diff --git a/net/websockets/websocket_channel_test.cc b/net/websockets/websocket_channel_test.cc
|
| index 25e9cdc050865e86278f66f1c5584d4e9eb1e1b2..b01c03a15921fd08e50714bf4c88d7d5af50f813 100644
|
| --- a/net/websockets/websocket_channel_test.cc
|
| +++ b/net/websockets/websocket_channel_test.cc
|
| @@ -38,36 +38,32 @@
|
|
|
| namespace net {
|
|
|
| -// Printing helpers to allow GoogleMock to print frame chunks. These are
|
| -// explicitly designed to look like the static initialisation format we use in
|
| -// these tests. They have to live in the net namespace in order to be found by
|
| +// Printing helpers to allow GoogleMock to print frames. These are explicitly
|
| +// designed to look like the static initialisation format we use in these
|
| +// tests. They have to live in the net namespace in order to be found by
|
| // GoogleMock; a nested anonymous namespace will not work.
|
|
|
| std::ostream& operator<<(std::ostream& os, const WebSocketFrameHeader& header) {
|
| - return os << "{" << (header.final ? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", "
|
| + return os << (header.final ? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", "
|
| << header.opcode << ", "
|
| - << (header.masked ? "MASKED" : "NOT_MASKED") << ", "
|
| - << header.payload_length << "}";
|
| + << (header.masked ? "MASKED" : "NOT_MASKED");
|
| }
|
|
|
| -std::ostream& operator<<(std::ostream& os, const WebSocketFrameChunk& chunk) {
|
| - os << "{";
|
| - if (chunk.header) {
|
| - os << *chunk.header;
|
| - } else {
|
| - os << "{NO_HEADER}";
|
| +std::ostream& operator<<(std::ostream& os, const WebSocketFrame& frame) {
|
| + os << "{" << frame.header << ", ";
|
| + if (frame.data) {
|
| + return os << "\"" << base::StringPiece(frame.data->data(),
|
| + frame.header.payload_length)
|
| + << "\"}";
|
| }
|
| - return os << ", " << (chunk.final_chunk ? "FINAL_CHUNK" : "NOT_FINAL_CHUNK")
|
| - << ", \""
|
| - << base::StringPiece(chunk.data->data(), chunk.data->size())
|
| - << "\"}";
|
| + return os << "NULL}";
|
| }
|
|
|
| std::ostream& operator<<(std::ostream& os,
|
| - const ScopedVector<WebSocketFrameChunk>& vector) {
|
| + const ScopedVector<WebSocketFrame>& vector) {
|
| os << "{";
|
| bool first = true;
|
| - for (ScopedVector<WebSocketFrameChunk>::const_iterator it = vector.begin();
|
| + for (ScopedVector<WebSocketFrame>::const_iterator it = vector.begin();
|
| it != vector.end();
|
| ++it) {
|
| if (!first) {
|
| @@ -81,7 +77,7 @@ std::ostream& operator<<(std::ostream& os,
|
| }
|
|
|
| std::ostream& operator<<(std::ostream& os,
|
| - const ScopedVector<WebSocketFrameChunk>* vector) {
|
| + const ScopedVector<WebSocketFrame>* vector) {
|
| return os << '&' << *vector;
|
| }
|
|
|
| @@ -97,7 +93,7 @@ using ::testing::_;
|
|
|
| // A selection of characters that have traditionally been mangled in some
|
| // environment or other, for testing 8-bit cleanliness.
|
| -const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL
|
| +const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL
|
| '\0', // nul
|
| '\x7F', // DEL
|
| '\x80', '\xFF', // NOT VALID UTF-8
|
| @@ -170,12 +166,12 @@ class FakeWebSocketStream : public WebSocketStream {
|
| return ERR_IO_PENDING;
|
| }
|
|
|
| - virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback) OVERRIDE {
|
| return ERR_IO_PENDING;
|
| }
|
|
|
| - virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback) OVERRIDE {
|
| return ERR_IO_PENDING;
|
| }
|
| @@ -198,12 +194,7 @@ class FakeWebSocketStream : public WebSocketStream {
|
|
|
| // To make the static initialisers easier to read, we use enums rather than
|
| // bools.
|
| -
|
| -// NO_HEADER means there shouldn't be a header included in the generated
|
| -// WebSocketFrameChunk. The static initialiser always has a header, but we can
|
| -// avoid specifying the rest of the fields.
|
| enum IsFinal {
|
| - NO_HEADER,
|
| NOT_FINAL_FRAME,
|
| FINAL_FRAME
|
| };
|
| @@ -213,54 +204,33 @@ enum IsMasked {
|
| MASKED
|
| };
|
|
|
| -enum IsFinalChunk {
|
| - NOT_FINAL_CHUNK,
|
| - FINAL_CHUNK
|
| -};
|
| -
|
| -// This is used to initialise a WebSocketFrameChunk but is statically
|
| -// initialisable.
|
| -struct InitFrameChunk {
|
| - struct FrameHeader {
|
| - IsFinal final;
|
| - // Reserved fields omitted for now. Add them if you need them.
|
| - WebSocketFrameHeader::OpCode opcode;
|
| - IsMasked masked;
|
| - // payload_length is the length of the whole frame. The length of the data
|
| - // members from every chunk in the frame must add up to the payload_length.
|
| - uint64 payload_length;
|
| - };
|
| - FrameHeader header;
|
| -
|
| - // Directly equivalent to WebSocketFrameChunk::final_chunk
|
| - IsFinalChunk final_chunk;
|
| +// This is used to initialise a WebSocketFrame but is statically initialisable.
|
| +struct InitFrame {
|
| + IsFinal final;
|
| + // Reserved fields omitted for now. Add them if you need them.
|
| + WebSocketFrameHeader::OpCode opcode;
|
| + IsMasked masked;
|
|
|
| // Will be used to create the IOBuffer member. Can be NULL for NULL data. Is a
|
| - // nul-terminated string for ease-of-use. This means it is not 8-bit clean,
|
| - // but this is not an issue for test data.
|
| + // nul-terminated string for ease-of-use. |header.payload_length| is
|
| + // initialised from |strlen(data)|. This means it is not 8-bit clean, but this
|
| + // is not an issue for test data.
|
| const char* const data;
|
| };
|
|
|
| // For GoogleMock
|
| -std::ostream& operator<<(std::ostream& os, const InitFrameChunk& chunk) {
|
| - os << "{";
|
| - if (chunk.header.final != NO_HEADER) {
|
| - os << "{" << (chunk.header.final == FINAL_FRAME ? "FINAL_FRAME"
|
| - : "NOT_FINAL_FRAME") << ", "
|
| - << chunk.header.opcode << ", "
|
| - << (chunk.header.masked == MASKED ? "MASKED" : "NOT_MASKED") << ", "
|
| - << chunk.header.payload_length << "}";
|
| -
|
| - } else {
|
| - os << "{NO_HEADER}";
|
| +std::ostream& operator<<(std::ostream& os, const InitFrame& frame) {
|
| + os << "{" << (frame.final == FINAL_FRAME ? "FINAL_FRAME" : "NOT_FINAL_FRAME")
|
| + << ", " << frame.opcode << ", "
|
| + << (frame.masked == MASKED ? "MASKED" : "NOT_MASKED") << ", ";
|
| + if (frame.data) {
|
| + return os << "\"" << frame.data << "\"}";
|
| }
|
| - return os << ", " << (chunk.final_chunk == FINAL_CHUNK ? "FINAL_CHUNK"
|
| - : "NOT_FINAL_CHUNK")
|
| - << ", \"" << chunk.data << "\"}";
|
| + return os << "NULL}";
|
| }
|
|
|
| template <size_t N>
|
| -std::ostream& operator<<(std::ostream& os, const InitFrameChunk (&chunks)[N]) {
|
| +std::ostream& operator<<(std::ostream& os, const InitFrame (&frames)[N]) {
|
| os << "{";
|
| bool first = true;
|
| for (size_t i = 0; i < N; ++i) {
|
| @@ -269,119 +239,92 @@ std::ostream& operator<<(std::ostream& os, const InitFrameChunk (&chunks)[N]) {
|
| } else {
|
| first = false;
|
| }
|
| - os << chunks[i];
|
| + os << frames[i];
|
| }
|
| return os << "}";
|
| }
|
|
|
| -// Convert a const array of InitFrameChunks to the format used at
|
| +// Convert a const array of InitFrame structs to the format used at
|
| // runtime. Templated on the size of the array to save typing.
|
| template <size_t N>
|
| -ScopedVector<WebSocketFrameChunk> CreateFrameChunkVector(
|
| - const InitFrameChunk (&source_chunks)[N]) {
|
| - ScopedVector<WebSocketFrameChunk> result_chunks;
|
| - result_chunks.reserve(N);
|
| +ScopedVector<WebSocketFrame> CreateFrameVector(
|
| + const InitFrame (&source_frames)[N]) {
|
| + ScopedVector<WebSocketFrame> result_frames;
|
| + result_frames.reserve(N);
|
| for (size_t i = 0; i < N; ++i) {
|
| - scoped_ptr<WebSocketFrameChunk> result_chunk(new WebSocketFrameChunk);
|
| - size_t chunk_length =
|
| - source_chunks[i].data ? strlen(source_chunks[i].data) : 0;
|
| - if (source_chunks[i].header.final != NO_HEADER) {
|
| - const InitFrameChunk::FrameHeader& source_header =
|
| - source_chunks[i].header;
|
| - scoped_ptr<WebSocketFrameHeader> result_header(
|
| - new WebSocketFrameHeader(source_header.opcode));
|
| - result_header->final = (source_header.final == FINAL_FRAME);
|
| - result_header->masked = (source_header.masked == MASKED);
|
| - result_header->payload_length = source_header.payload_length;
|
| - DCHECK(chunk_length <= source_header.payload_length);
|
| - result_chunk->header.swap(result_header);
|
| - }
|
| - result_chunk->final_chunk = (source_chunks[i].final_chunk == FINAL_CHUNK);
|
| - if (source_chunks[i].data) {
|
| - result_chunk->data = new IOBufferWithSize(chunk_length);
|
| - memcpy(result_chunk->data->data(), source_chunks[i].data, chunk_length);
|
| + const InitFrame& source_frame = source_frames[i];
|
| + scoped_ptr<WebSocketFrame> result_frame(
|
| + new WebSocketFrame(source_frame.opcode));
|
| + size_t frame_length = source_frame.data ? strlen(source_frame.data) : 0;
|
| + WebSocketFrameHeader& result_header = result_frame->header;
|
| + result_header.final = (source_frame.final == FINAL_FRAME);
|
| + result_header.masked = (source_frame.masked == MASKED);
|
| + result_header.payload_length = frame_length;
|
| + if (source_frames[i].data) {
|
| + result_frame->data = new IOBuffer(frame_length);
|
| + memcpy(result_frame->data->data(), source_frames[i].data, frame_length);
|
| }
|
| - result_chunks.push_back(result_chunk.release());
|
| + result_frames.push_back(result_frame.release());
|
| }
|
| - return result_chunks.Pass();
|
| + return result_frames.Pass();
|
| }
|
|
|
| // A GoogleMock action which can be used to respond to call to ReadFrames with
|
| -// some frames. Use like ReadFrames(_, _).WillOnce(ReturnChunks(&chunks));
|
| -// |chunks| is an array of InitFrameChunks needs to be passed by pointer because
|
| -// otherwise it will be reduced to a pointer and lose the array size
|
| -// information.
|
| -ACTION_P(ReturnChunks, source_chunks) {
|
| - *arg0 = CreateFrameChunkVector(*source_chunks);
|
| +// some frames. Use like ReadFrames(_, _).WillOnce(ReturnFrames(&frames));
|
| +// |frames| is an array of InitFrame. |frames| needs to be passed by pointer
|
| +// because otherwise it will be treated as a pointer and the array size
|
| +// information will be lost.
|
| +ACTION_P(ReturnFrames, source_frames) {
|
| + *arg0 = CreateFrameVector(*source_frames);
|
| return OK;
|
| }
|
|
|
| // The implementation of a GoogleMock matcher which can be used to compare a
|
| -// ScopedVector<WebSocketFrameChunk>* against an expectation defined as an array
|
| -// of InitFrameChunks. Although it is possible to compose built-in GoogleMock
|
| -// matchers to check the contents of a WebSocketFrameChunk, the results are so
|
| +// ScopedVector<WebSocketFrame>* against an expectation defined as an array of
|
| +// InitFrame objects. Although it is possible to compose built-in GoogleMock
|
| +// matchers to check the contents of a WebSocketFrame, the results are so
|
| // unreadable that it is better to use this matcher.
|
| template <size_t N>
|
| -class EqualsChunksMatcher
|
| - : public ::testing::MatcherInterface<ScopedVector<WebSocketFrameChunk>*> {
|
| +class EqualsFramesMatcher
|
| + : public ::testing::MatcherInterface<ScopedVector<WebSocketFrame>*> {
|
| public:
|
| - EqualsChunksMatcher(const InitFrameChunk (*expect_chunks)[N])
|
| - : expect_chunks_(expect_chunks) {}
|
| + EqualsFramesMatcher(const InitFrame (*expect_frames)[N])
|
| + : expect_frames_(expect_frames) {}
|
|
|
| - virtual bool MatchAndExplain(ScopedVector<WebSocketFrameChunk>* actual_chunks,
|
| + virtual bool MatchAndExplain(ScopedVector<WebSocketFrame>* actual_frames,
|
| ::testing::MatchResultListener* listener) const {
|
| - if (actual_chunks->size() != N) {
|
| - *listener << "the vector size is " << actual_chunks->size();
|
| + if (actual_frames->size() != N) {
|
| + *listener << "the vector size is " << actual_frames->size();
|
| return false;
|
| }
|
| for (size_t i = 0; i < N; ++i) {
|
| - const WebSocketFrameChunk& actual_chunk = *(*actual_chunks)[i];
|
| - const InitFrameChunk& expected_chunk = (*expect_chunks_)[i];
|
| - // Testing that the absence or presence of a header is the same for both.
|
| - if ((!actual_chunk.header) !=
|
| - (expected_chunk.header.final == NO_HEADER)) {
|
| - *listener << "the header is "
|
| - << (actual_chunk.header ? "present" : "absent");
|
| + const WebSocketFrame& actual_frame = *(*actual_frames)[i];
|
| + const InitFrame& expected_frame = (*expect_frames_)[i];
|
| + if (actual_frame.header.final != (expected_frame.final == FINAL_FRAME)) {
|
| + *listener << "the frame is marked as "
|
| + << (actual_frame.header.final ? "" : "not ") << "final";
|
| return false;
|
| }
|
| - if (actual_chunk.header) {
|
| - if (actual_chunk.header->final !=
|
| - (expected_chunk.header.final == FINAL_FRAME)) {
|
| - *listener << "the frame is marked as "
|
| - << (actual_chunk.header->final ? "" : "not ") << "final";
|
| - return false;
|
| - }
|
| - if (actual_chunk.header->opcode != expected_chunk.header.opcode) {
|
| - *listener << "the opcode is " << actual_chunk.header->opcode;
|
| - return false;
|
| - }
|
| - if (actual_chunk.header->masked !=
|
| - (expected_chunk.header.masked == MASKED)) {
|
| - *listener << "the frame is "
|
| - << (actual_chunk.header->masked ? "masked" : "not masked");
|
| - return false;
|
| - }
|
| - if (actual_chunk.header->payload_length !=
|
| - expected_chunk.header.payload_length) {
|
| - *listener << "the payload length is "
|
| - << actual_chunk.header->payload_length;
|
| - return false;
|
| - }
|
| + if (actual_frame.header.opcode != expected_frame.opcode) {
|
| + *listener << "the opcode is " << actual_frame.header.opcode;
|
| + return false;
|
| }
|
| - if (actual_chunk.final_chunk !=
|
| - (expected_chunk.final_chunk == FINAL_CHUNK)) {
|
| - *listener << "the chunk is marked as "
|
| - << (actual_chunk.final_chunk ? "" : "not ") << "final";
|
| + if (actual_frame.header.masked != (expected_frame.masked == MASKED)) {
|
| + *listener << "the frame is "
|
| + << (actual_frame.header.masked ? "masked" : "not masked");
|
| return false;
|
| }
|
| - if (actual_chunk.data->size() !=
|
| - base::checked_numeric_cast<int>(strlen(expected_chunk.data))) {
|
| - *listener << "the data size is " << actual_chunk.data->size();
|
| + const size_t expected_length =
|
| + expected_frame.data ? strlen(expected_frame.data) : 0;
|
| + if (actual_frame.header.payload_length != expected_length) {
|
| + *listener << "the payload length is "
|
| + << actual_frame.header.payload_length;
|
| return false;
|
| }
|
| - if (memcmp(actual_chunk.data->data(),
|
| - expected_chunk.data,
|
| - actual_chunk.data->size()) != 0) {
|
| + if (expected_length != 0 &&
|
| + memcmp(actual_frame.data->data(),
|
| + expected_frame.data,
|
| + actual_frame.header.payload_length) != 0) {
|
| *listener << "the data content differs";
|
| return false;
|
| }
|
| @@ -390,23 +333,23 @@ class EqualsChunksMatcher
|
| }
|
|
|
| virtual void DescribeTo(std::ostream* os) const {
|
| - *os << "matches " << *expect_chunks_;
|
| + *os << "matches " << *expect_frames_;
|
| }
|
|
|
| virtual void DescribeNegationTo(std::ostream* os) const {
|
| - *os << "does not match " << *expect_chunks_;
|
| + *os << "does not match " << *expect_frames_;
|
| }
|
|
|
| private:
|
| - const InitFrameChunk (*expect_chunks_)[N];
|
| + const InitFrame (*expect_frames_)[N];
|
| };
|
|
|
| -// The definition of EqualsChunks GoogleMock matcher. Unlike the ReturnChunks
|
| +// The definition of EqualsFrames GoogleMock matcher. Unlike the ReturnFrames
|
| // action, this can take the array by reference.
|
| template <size_t N>
|
| -::testing::Matcher<ScopedVector<WebSocketFrameChunk>*> EqualsChunks(
|
| - const InitFrameChunk (&chunks)[N]) {
|
| - return ::testing::MakeMatcher(new EqualsChunksMatcher<N>(&chunks));
|
| +::testing::Matcher<ScopedVector<WebSocketFrame>*> EqualsFrames(
|
| + const InitFrame (&frames)[N]) {
|
| + return ::testing::MakeMatcher(new EqualsFramesMatcher<N>(&frames));
|
| }
|
|
|
| // A FakeWebSocketStream whose ReadFrames() function returns data.
|
| @@ -427,39 +370,38 @@ class ReadableFakeWebSocketStream : public FakeWebSocketStream {
|
| CHECK(!read_frames_pending_);
|
| }
|
|
|
| - // Prepares a fake responses. Fake responses will be returned from
|
| - // ReadFrames() in the same order they were prepared with PrepareReadFrames()
|
| - // and PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will
|
| + // Prepares a fake response. Fake responses will be returned from ReadFrames()
|
| + // in the same order they were prepared with PrepareReadFrames() and
|
| + // PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will
|
| // return ERR_IO_PENDING and the callback will be scheduled to run on the
|
| // message loop. This requires the test case to run the message loop. If
|
| // |async| is SYNC, the response will be returned synchronously. |error| is
|
| // returned directly from ReadFrames() in the synchronous case, or passed to
|
| - // the callback in the asynchronous case. |chunks| will be converted to a
|
| - // ScopedVector<WebSocketFrameChunks> and copied to the pointer that was
|
| - // passed to ReadFrames().
|
| + // the callback in the asynchronous case. |frames| will be converted to a
|
| + // ScopedVector<WebSocketFrame> and copied to the pointer that was passed to
|
| + // ReadFrames().
|
| template <size_t N>
|
| void PrepareReadFrames(IsSync async,
|
| int error,
|
| - const InitFrameChunk (&chunks)[N]) {
|
| - responses_.push_back(
|
| - new Response(async, error, CreateFrameChunkVector(chunks)));
|
| + const InitFrame (&frames)[N]) {
|
| + responses_.push_back(new Response(async, error, CreateFrameVector(frames)));
|
| }
|
|
|
| // An alternate version of PrepareReadFrames for when we need to construct
|
| // the frames manually.
|
| void PrepareRawReadFrames(IsSync async,
|
| int error,
|
| - ScopedVector<WebSocketFrameChunk> chunks) {
|
| - responses_.push_back(new Response(async, error, chunks.Pass()));
|
| + ScopedVector<WebSocketFrame> frames) {
|
| + responses_.push_back(new Response(async, error, frames.Pass()));
|
| }
|
|
|
| // Prepares a fake error response (ie. there is no data).
|
| void PrepareReadFramesError(IsSync async, int error) {
|
| responses_.push_back(
|
| - new Response(async, error, ScopedVector<WebSocketFrameChunk>()));
|
| + new Response(async, error, ScopedVector<WebSocketFrame>()));
|
| }
|
|
|
| - virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback) OVERRIDE {
|
| CHECK(!read_frames_pending_);
|
| if (index_ >= responses_.size())
|
| @@ -470,34 +412,34 @@ class ReadableFakeWebSocketStream : public FakeWebSocketStream {
|
| FROM_HERE,
|
| base::Bind(&ReadableFakeWebSocketStream::DoCallback,
|
| base::Unretained(this),
|
| - frame_chunks,
|
| + frames,
|
| callback));
|
| return ERR_IO_PENDING;
|
| } else {
|
| - frame_chunks->swap(responses_[index_]->chunks);
|
| + frames->swap(responses_[index_]->frames);
|
| return responses_[index_++]->error;
|
| }
|
| }
|
|
|
| private:
|
| - void DoCallback(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + void DoCallback(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback) {
|
| read_frames_pending_ = false;
|
| - frame_chunks->swap(responses_[index_]->chunks);
|
| + frames->swap(responses_[index_]->frames);
|
| callback.Run(responses_[index_++]->error);
|
| return;
|
| }
|
|
|
| struct Response {
|
| - Response(IsSync async, int error, ScopedVector<WebSocketFrameChunk> chunks)
|
| - : async(async), error(error), chunks(chunks.Pass()) {}
|
| + Response(IsSync async, int error, ScopedVector<WebSocketFrame> frames)
|
| + : async(async), error(error), frames(frames.Pass()) {}
|
|
|
| IsSync async;
|
| int error;
|
| - ScopedVector<WebSocketFrameChunk> chunks;
|
| + ScopedVector<WebSocketFrame> frames;
|
|
|
| private:
|
| - // Bad things will happen if we attempt to copy or assign "chunks".
|
| + // Bad things will happen if we attempt to copy or assign |frames|.
|
| DISALLOW_COPY_AND_ASSIGN(Response);
|
| };
|
| ScopedVector<Response> responses_;
|
| @@ -516,7 +458,7 @@ class ReadableFakeWebSocketStream : public FakeWebSocketStream {
|
| // synchronously.
|
| class WriteableFakeWebSocketStream : public FakeWebSocketStream {
|
| public:
|
| - virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback) OVERRIDE {
|
| return OK;
|
| }
|
| @@ -525,7 +467,7 @@ class WriteableFakeWebSocketStream : public FakeWebSocketStream {
|
| // A FakeWebSocketStream where writes always fail.
|
| class UnWriteableFakeWebSocketStream : public FakeWebSocketStream {
|
| public:
|
| - virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback) OVERRIDE {
|
| return ERR_CONNECTION_RESET;
|
| }
|
| @@ -539,23 +481,22 @@ class UnWriteableFakeWebSocketStream : public FakeWebSocketStream {
|
| // otherwise the ReadFrames() callback will never be called.
|
| class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
|
| public:
|
| - EchoeyFakeWebSocketStream() : read_frame_chunks_(NULL), done_(false) {}
|
| + EchoeyFakeWebSocketStream() : read_frames_(NULL), done_(false) {}
|
|
|
| - virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback) OVERRIDE {
|
| // Users of WebSocketStream will not expect the ReadFrames() callback to be
|
| // called from within WriteFrames(), so post it to the message loop instead.
|
| - stored_frame_chunks_.insert(
|
| - stored_frame_chunks_.end(), frame_chunks->begin(), frame_chunks->end());
|
| - frame_chunks->weak_clear();
|
| + stored_frames_.insert(stored_frames_.end(), frames->begin(), frames->end());
|
| + frames->weak_clear();
|
| PostCallback();
|
| return OK;
|
| }
|
|
|
| - virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback) OVERRIDE {
|
| read_callback_ = callback;
|
| - read_frame_chunks_ = frame_chunks;
|
| + read_frames_ = frames;
|
| if (done_)
|
| PostCallback();
|
| return ERR_IO_PENDING;
|
| @@ -572,36 +513,34 @@ class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
|
| void DoCallback() {
|
| if (done_) {
|
| read_callback_.Run(ERR_CONNECTION_CLOSED);
|
| - } else if (!stored_frame_chunks_.empty()) {
|
| - done_ = MoveFrameChunks(read_frame_chunks_);
|
| - read_frame_chunks_ = NULL;
|
| + } else if (!stored_frames_.empty()) {
|
| + done_ = MoveFrames(read_frames_);
|
| + read_frames_ = NULL;
|
| read_callback_.Run(OK);
|
| }
|
| }
|
|
|
| - // Copy the chunks stored in stored_frame_chunks_ to |out|, while clearing the
|
| + // Copy the frames stored in stored_frames_ to |out|, while clearing the
|
| // "masked" header bit. Returns true if a Close Frame was seen, false
|
| // otherwise.
|
| - bool MoveFrameChunks(ScopedVector<WebSocketFrameChunk>* out) {
|
| + bool MoveFrames(ScopedVector<WebSocketFrame>* out) {
|
| bool seen_close = false;
|
| - *out = stored_frame_chunks_.Pass();
|
| - for (ScopedVector<WebSocketFrameChunk>::iterator it = out->begin();
|
| + *out = stored_frames_.Pass();
|
| + for (ScopedVector<WebSocketFrame>::iterator it = out->begin();
|
| it != out->end();
|
| ++it) {
|
| - WebSocketFrameHeader* header = (*it)->header.get();
|
| - if (header) {
|
| - header->masked = false;
|
| - if (header->opcode == WebSocketFrameHeader::kOpCodeClose)
|
| - seen_close = true;
|
| - }
|
| + WebSocketFrameHeader& header = (*it)->header;
|
| + header.masked = false;
|
| + if (header.opcode == WebSocketFrameHeader::kOpCodeClose)
|
| + seen_close = true;
|
| }
|
| return seen_close;
|
| }
|
|
|
| - ScopedVector<WebSocketFrameChunk> stored_frame_chunks_;
|
| + ScopedVector<WebSocketFrame> stored_frames_;
|
| CompletionCallback read_callback_;
|
| // Owned by the caller of ReadFrames().
|
| - ScopedVector<WebSocketFrameChunk>* read_frame_chunks_;
|
| + ScopedVector<WebSocketFrame>* read_frames_;
|
| // True if we should close the connection.
|
| bool done_;
|
| };
|
| @@ -612,7 +551,7 @@ class EchoeyFakeWebSocketStream : public FakeWebSocketStream {
|
| // run the message loop.
|
| class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
|
| public:
|
| - virtual int WriteFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback) OVERRIDE {
|
| base::MessageLoop::current()->PostTask(
|
| FROM_HERE, base::Bind(callback, ERR_CONNECTION_RESET));
|
| @@ -621,7 +560,7 @@ class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
|
| return ERR_IO_PENDING;
|
| }
|
|
|
| - virtual int ReadFrames(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback) OVERRIDE {
|
| read_callback_ = callback;
|
| return ERR_IO_PENDING;
|
| @@ -636,10 +575,10 @@ class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
|
| class MockWebSocketStream : public WebSocketStream {
|
| public:
|
| MOCK_METHOD2(ReadFrames,
|
| - int(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + int(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback));
|
| MOCK_METHOD2(WriteFrames,
|
| - int(ScopedVector<WebSocketFrameChunk>* frame_chunks,
|
| + int(ScopedVector<WebSocketFrame>* frames,
|
| const CompletionCallback& callback));
|
| MOCK_METHOD0(Close, void());
|
| MOCK_CONST_METHOD0(GetSubProtocol, std::string());
|
| @@ -846,8 +785,8 @@ TEST_F(WebSocketChannelTest, EverythingIsPassedToTheFactoryFunction) {
|
| // AddressSanitizer.
|
| TEST_F(WebSocketChannelDeletingTest, DeletingFromOnAddChannelResponseWorks) {
|
| CreateChannelAndConnect();
|
| - connect_data_.factory.connect_delegate
|
| - ->OnFailure(kWebSocketErrorNoStatusReceived);
|
| + connect_data_.factory.connect_delegate->OnFailure(
|
| + kWebSocketErrorNoStatusReceived);
|
| EXPECT_EQ(NULL, channel_.get());
|
| }
|
|
|
| @@ -869,8 +808,8 @@ TEST_F(WebSocketChannelEventInterfaceTest, ConnectFailureReported) {
|
|
|
| CreateChannelAndConnect();
|
|
|
| - connect_data_.factory.connect_delegate
|
| - ->OnFailure(kWebSocketErrorNoStatusReceived);
|
| + connect_data_.factory.connect_delegate->OnFailure(
|
| + kWebSocketErrorNoStatusReceived);
|
| }
|
|
|
| TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) {
|
| @@ -889,10 +828,9 @@ TEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) {
|
| TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) {
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5},
|
| - FINAL_CHUNK, "HELLO"}};
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks);
|
| + static const InitFrame frames[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
|
| set_stream(stream.Pass());
|
| {
|
| InSequence s;
|
| @@ -912,10 +850,10 @@ TEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) {
|
| TEST_F(WebSocketChannelEventInterfaceTest, CloseAfterHandshake) {
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 23},
|
| - FINAL_CHUNK, CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}};
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks);
|
| + static const InitFrame frames[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
|
| + NOT_MASKED, CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}};
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
|
| stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
|
| ERR_CONNECTION_CLOSED);
|
| set_stream(stream.Pass());
|
| @@ -954,13 +892,12 @@ TEST_F(WebSocketChannelEventInterfaceTest, ConnectionCloseAfterHandshake) {
|
| TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) {
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5},
|
| - FINAL_CHUNK, "HELLO"}};
|
| + static const InitFrame frames[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
|
| // We use this checkpoint object to verify that the callback isn't called
|
| // until we expect it to be.
|
| MockFunction<void(int)> checkpoint;
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
|
| set_stream(stream.Pass());
|
| {
|
| InSequence s;
|
| @@ -985,14 +922,12 @@ TEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) {
|
| TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) {
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks1[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5},
|
| - FINAL_CHUNK, "HELLO"}};
|
| - static const InitFrameChunk chunks2[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5},
|
| - FINAL_CHUNK, "WORLD"}};
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1);
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks2);
|
| + static const InitFrame frames1[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}};
|
| + static const InitFrame frames2[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "WORLD"}};
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames2);
|
| set_stream(stream.Pass());
|
| {
|
| InSequence s;
|
| @@ -1012,31 +947,29 @@ TEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) {
|
| base::MessageLoop::current()->RunUntilIdle();
|
| }
|
|
|
| -// Data frames that arrive in fragments are turned into individual frames
|
| +// Data frames are delivered the same regardless of how many reads they arrive
|
| +// as.
|
| TEST_F(WebSocketChannelEventInterfaceTest, FragmentedFrames) {
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| - // Here we have one message split into 3 frames which arrive in 3 chunks. The
|
| - // first frame is entirely in the first chunk, the second frame is split
|
| - // across all the chunks, and the final frame is entirely in the final
|
| - // chunk. The frame fragments are converted to separate frames so that they
|
| - // can be delivered immediatedly. So the EventInterface should see a Text
|
| - // message with 5 frames.
|
| - static const InitFrameChunk chunks1[] = {
|
| - {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 5},
|
| - FINAL_CHUNK, "THREE"},
|
| - {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED,
|
| - 7},
|
| - NOT_FINAL_CHUNK, " "}};
|
| - static const InitFrameChunk chunks2[] = {
|
| - {{NO_HEADER}, NOT_FINAL_CHUNK, "SMALL"}};
|
| - static const InitFrameChunk chunks3[] = {
|
| - {{NO_HEADER}, FINAL_CHUNK, " "},
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, 6},
|
| - FINAL_CHUNK, "FRAMES"}};
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1);
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2);
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3);
|
| + // Here we have one message which arrived in five frames split across three
|
| + // reads. It may have been reframed on arrival, but this class doesn't care
|
| + // about that.
|
| + static const InitFrame frames1[] = {
|
| + {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "THREE"},
|
| + {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
|
| + NOT_MASKED, " "}};
|
| + static const InitFrame frames2[] = {
|
| + {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
|
| + NOT_MASKED, "SMALL"}};
|
| + static const InitFrame frames3[] = {
|
| + {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
|
| + NOT_MASKED, " "},
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
|
| + NOT_MASKED, "FRAMES"}};
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
|
| set_stream(stream.Pass());
|
| {
|
| InSequence s;
|
| @@ -1068,112 +1001,16 @@ TEST_F(WebSocketChannelEventInterfaceTest, FragmentedFrames) {
|
| base::MessageLoop::current()->RunUntilIdle();
|
| }
|
|
|
| -// In the case when a single-frame message because fragmented, it must be
|
| -// correctly transformed to multiple frames.
|
| -TEST_F(WebSocketChannelEventInterfaceTest, MessageFragmentation) {
|
| - scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| - new ReadableFakeWebSocketStream);
|
| - // A single-frame Text message arrives in three chunks. This should be
|
| - // delivered as three frames.
|
| - static const InitFrameChunk chunks1[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 12},
|
| - NOT_FINAL_CHUNK, "TIME"}};
|
| - static const InitFrameChunk chunks2[] = {
|
| - {{NO_HEADER}, NOT_FINAL_CHUNK, " FOR "}};
|
| - static const InitFrameChunk chunks3[] = {{{NO_HEADER}, FINAL_CHUNK, "TEA"}};
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1);
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2);
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3);
|
| - set_stream(stream.Pass());
|
| - {
|
| - InSequence s;
|
| - EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
|
| - EXPECT_CALL(*event_interface_, OnFlowControl(_));
|
| - EXPECT_CALL(
|
| - *event_interface_,
|
| - OnDataFrame(
|
| - false, WebSocketFrameHeader::kOpCodeText, AsVector("TIME")));
|
| - EXPECT_CALL(*event_interface_,
|
| - OnDataFrame(false,
|
| - WebSocketFrameHeader::kOpCodeContinuation,
|
| - AsVector(" FOR ")));
|
| - EXPECT_CALL(
|
| - *event_interface_,
|
| - OnDataFrame(
|
| - true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("TEA")));
|
| - }
|
| -
|
| - CreateChannelAndConnectSuccessfully();
|
| - base::MessageLoop::current()->RunUntilIdle();
|
| -}
|
| -
|
| -// If a control message is fragmented, it must be re-assembled before being
|
| -// delivered. A control message can only be fragmented at the network level; it
|
| -// is not permitted to be split into multiple frames.
|
| -TEST_F(WebSocketChannelEventInterfaceTest, FragmentedControlMessage) {
|
| - scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| - new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks1[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7},
|
| - NOT_FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "")}};
|
| - static const InitFrameChunk chunks2[] = {
|
| - {{NO_HEADER}, NOT_FINAL_CHUNK, "Clo"}};
|
| - static const InitFrameChunk chunks3[] = {{{NO_HEADER}, FINAL_CHUNK, "se"}};
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1);
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2);
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3);
|
| - stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
|
| - ERR_CONNECTION_CLOSED);
|
| - set_stream(stream.Pass());
|
| - {
|
| - InSequence s;
|
| - EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
|
| - EXPECT_CALL(*event_interface_, OnFlowControl(_));
|
| - EXPECT_CALL(*event_interface_, OnClosingHandshake());
|
| - EXPECT_CALL(*event_interface_,
|
| - OnDropChannel(kWebSocketNormalClosure, "Close"));
|
| - }
|
| -
|
| - CreateChannelAndConnectSuccessfully();
|
| - base::MessageLoop::current()->RunUntilIdle();
|
| -}
|
| -
|
| -// The payload of a control frame is not permitted to exceed 125 bytes. RFC6455
|
| -// 5.5 "All control frames MUST have a payload length of 125 bytes or less"
|
| -TEST_F(WebSocketChannelEventInterfaceTest, OversizeControlMessageIsRejected) {
|
| - scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| - new ReadableFakeWebSocketStream);
|
| - static const size_t kPayloadLen = 126;
|
| - char payload[kPayloadLen + 1]; // allow space for trailing NUL
|
| - std::fill(payload, payload + kPayloadLen, 'A');
|
| - payload[kPayloadLen] = '\0';
|
| - // Not static because "payload" is constructed at runtime.
|
| - const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED,
|
| - kPayloadLen},
|
| - FINAL_CHUNK, payload}};
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks);
|
| - set_stream(stream.Pass());
|
| -
|
| - EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
|
| - EXPECT_CALL(*event_interface_, OnFlowControl(_));
|
| - EXPECT_CALL(*event_interface_,
|
| - OnDropChannel(kWebSocketErrorProtocolError, _));
|
| -
|
| - CreateChannelAndConnectSuccessfully();
|
| -}
|
| -
|
| // A control frame is not permitted to be split into multiple frames. RFC6455
|
| // 5.5 "All control frames ... MUST NOT be fragmented."
|
| TEST_F(WebSocketChannelEventInterfaceTest, MultiFrameControlMessageIsRejected) {
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks[] = {
|
| - {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 2},
|
| - FINAL_CHUNK, "Pi"},
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, 2},
|
| - FINAL_CHUNK, "ng"}};
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
|
| + static const InitFrame frames[] = {
|
| + {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, "Pi"},
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
|
| + NOT_MASKED, "ng"}};
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
|
| set_stream(stream.Pass());
|
| {
|
| InSequence s;
|
| @@ -1225,39 +1062,14 @@ TEST_F(WebSocketChannelEventInterfaceTest, ConnectionReset) {
|
| base::MessageLoop::current()->RunUntilIdle();
|
| }
|
|
|
| -// Connection closed in the middle of a Close message (server bug, etc.)
|
| -TEST_F(WebSocketChannelEventInterfaceTest, ConnectionClosedInMessage) {
|
| - scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| - new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7},
|
| - NOT_FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "")}};
|
| -
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
|
| - stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC,
|
| - ERR_CONNECTION_CLOSED);
|
| - set_stream(stream.Pass());
|
| - {
|
| - InSequence s;
|
| - EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
|
| - EXPECT_CALL(*event_interface_, OnFlowControl(_));
|
| - EXPECT_CALL(*event_interface_,
|
| - OnDropChannel(kWebSocketErrorAbnormalClosure, _));
|
| - }
|
| -
|
| - CreateChannelAndConnectSuccessfully();
|
| - base::MessageLoop::current()->RunUntilIdle();
|
| -}
|
| -
|
| // RFC6455 5.1 "A client MUST close a connection if it detects a masked frame."
|
| TEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) {
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 5}, FINAL_CHUNK,
|
| - "HELLO"}};
|
| + static const InitFrame frames[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}};
|
|
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
|
| set_stream(stream.Pass());
|
| {
|
| InSequence s;
|
| @@ -1276,10 +1088,9 @@ TEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) {
|
| TEST_F(WebSocketChannelEventInterfaceTest, UnknownOpCodeIsRejected) {
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, 4, NOT_MASKED, 5}, FINAL_CHUNK, "HELLO"}};
|
| + static const InitFrame frames[] = {{FINAL_FRAME, 4, NOT_MASKED, "HELLO"}};
|
|
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
|
| set_stream(stream.Pass());
|
| {
|
| InSequence s;
|
| @@ -1300,18 +1111,17 @@ TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) {
|
| new ReadableFakeWebSocketStream);
|
| // We have one message of type Text split into two frames. In the middle is a
|
| // control message of type Pong.
|
| - static const InitFrameChunk chunks1[] = {
|
| - {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, 6},
|
| - FINAL_CHUNK, "SPLIT "}};
|
| - static const InitFrameChunk chunks2[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, 0},
|
| - FINAL_CHUNK, ""}};
|
| - static const InitFrameChunk chunks3[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, 7},
|
| - FINAL_CHUNK, "MESSAGE"}};
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks1);
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks2);
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks3);
|
| + static const InitFrame frames1[] = {
|
| + {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
|
| + NOT_MASKED, "SPLIT "}};
|
| + static const InitFrame frames2[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}};
|
| + static const InitFrame frames3[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
|
| + NOT_MASKED, "MESSAGE"}};
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1);
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2);
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3);
|
| set_stream(stream.Pass());
|
| {
|
| InSequence s;
|
| @@ -1331,17 +1141,16 @@ TEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) {
|
| base::MessageLoop::current()->RunUntilIdle();
|
| }
|
|
|
| -// If a chunk has an invalid header, then the connection is closed and
|
| -// subsequent chunks must not trigger events.
|
| -TEST_F(WebSocketChannelEventInterfaceTest, HeaderlessChunkAfterInvalidChunk) {
|
| +// If a frame has an invalid header, then the connection is closed and
|
| +// subsequent frames must not trigger events.
|
| +TEST_F(WebSocketChannelEventInterfaceTest, FrameAfterInvalidFrame) {
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 11},
|
| - NOT_FINAL_CHUNK, "HELLO"},
|
| - {{NO_HEADER}, FINAL_CHUNK, " WORLD"}};
|
| + static const InitFrame frames[] = {
|
| + {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"},
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, " WORLD"}};
|
|
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, chunks);
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames);
|
| set_stream(stream.Pass());
|
| {
|
| InSequence s;
|
| @@ -1501,10 +1310,9 @@ TEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) {
|
| TEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) {
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 0},
|
| - FINAL_CHUNK, ""}};
|
| - stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, chunks);
|
| + static const InitFrame frames[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
|
| + stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames);
|
| stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC,
|
| ERR_CONNECTION_CLOSED);
|
| set_stream(stream.Pass());
|
| @@ -1521,12 +1329,12 @@ TEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) {
|
| // WebSocketChannel actually only sets the mask bit in the header, it doesn't
|
| // perform masking itself (not all transports actually use masking).
|
| TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) {
|
| - static const InitFrameChunk expected[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 13},
|
| - FINAL_CHUNK, "NEEDS MASKING"}};
|
| + static const InitFrame expected[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
|
| + MASKED, "NEEDS MASKING"}};
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
|
| .WillOnce(Return(OK));
|
|
|
| CreateChannelAndConnectSuccessfully();
|
| @@ -1537,12 +1345,12 @@ TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) {
|
| // RFC6455 5.5.1 "The application MUST NOT send any more data frames after
|
| // sending a Close frame."
|
| TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) {
|
| - static const InitFrameChunk expected[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 9},
|
| - FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
|
| + static const InitFrame expected[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
|
| + MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
|
| .WillOnce(Return(OK));
|
|
|
| CreateChannelAndConnectSuccessfully();
|
| @@ -1554,17 +1362,17 @@ TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) {
|
| // RFC6455 5.5.1 "If an endpoint receives a Close frame and did not previously
|
| // send a Close frame, the endpoint MUST send a Close frame in response."
|
| TEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) {
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7},
|
| - FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
|
| - static const InitFrameChunk expected[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 7},
|
| - FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
|
| + static const InitFrame frames[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
|
| + NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
|
| + static const InitFrame expected[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
|
| + MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
|
| - .WillOnce(ReturnChunks(&chunks))
|
| + .WillOnce(ReturnFrames(&frames))
|
| .WillRepeatedly(Return(ERR_IO_PENDING));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
|
| .WillOnce(Return(OK));
|
|
|
| CreateChannelAndConnectSuccessfully();
|
| @@ -1573,17 +1381,17 @@ TEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) {
|
| // The converse of the above case; after sending a Close frame, we should not
|
| // send another one.
|
| TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
|
| - static const InitFrameChunk expected[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 7},
|
| - FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 7},
|
| - FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
|
| + static const InitFrame expected[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
|
| + MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
|
| + static const InitFrame frames_init[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
|
| + NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
|
|
|
| // We store the parameters that were passed to ReadFrames() so that we can
|
| // call them explicitly later.
|
| CompletionCallback read_callback;
|
| - ScopedVector<WebSocketFrameChunk>* frame_chunks = NULL;
|
| + ScopedVector<WebSocketFrame>* frames = NULL;
|
|
|
| // Use a checkpoint to make the ordering of events clearer.
|
| MockFunction<void(int)> checkpoint;
|
| @@ -1591,11 +1399,11 @@ TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
|
| InSequence s;
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
|
| - .WillOnce(DoAll(SaveArg<0>(&frame_chunks),
|
| + .WillOnce(DoAll(SaveArg<0>(&frames),
|
| SaveArg<1>(&read_callback),
|
| Return(ERR_IO_PENDING)));
|
| EXPECT_CALL(checkpoint, Call(1));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
|
| .WillOnce(Return(OK));
|
| EXPECT_CALL(checkpoint, Call(2));
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
|
| @@ -1610,7 +1418,7 @@ TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
|
| channel_->StartClosingHandshake(kWebSocketNormalClosure, "Close");
|
| checkpoint.Call(2);
|
|
|
| - *frame_chunks = CreateFrameChunkVector(chunks);
|
| + *frames = CreateFrameVector(frames_init);
|
| read_callback.Run(OK);
|
| checkpoint.Call(3);
|
| }
|
| @@ -1621,17 +1429,15 @@ TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
|
| // CloseWithNoPayloadGivesStatus1005, above, for confirmation that code 1005 is
|
| // correctly generated internally.
|
| TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) {
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 0},
|
| - FINAL_CHUNK, ""}};
|
| - static const InitFrameChunk expected[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 0},
|
| - FINAL_CHUNK, ""}};
|
| + static const InitFrame frames[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
|
| + static const InitFrame expected[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
|
| - .WillOnce(ReturnChunks(&chunks))
|
| + .WillOnce(ReturnFrames(&frames))
|
| .WillRepeatedly(Return(ERR_IO_PENDING));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
|
| .WillOnce(Return(OK));
|
|
|
| CreateChannelAndConnectSuccessfully();
|
| @@ -1643,58 +1449,57 @@ TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) {
|
| // "Application data" as found in the message body of the Ping frame being
|
| // replied to."
|
| TEST_F(WebSocketChannelStreamTest, PingRepliedWithPong) {
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 16},
|
| - FINAL_CHUNK, "Application data"}};
|
| - static const InitFrameChunk expected[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, 16},
|
| - FINAL_CHUNK, "Application data"}};
|
| + static const InitFrame frames[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
|
| + NOT_MASKED, "Application data"}};
|
| + static const InitFrame expected[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
|
| + MASKED, "Application data"}};
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
|
| - .WillOnce(ReturnChunks(&chunks))
|
| + .WillOnce(ReturnFrames(&frames))
|
| .WillRepeatedly(Return(ERR_IO_PENDING));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
|
| .WillOnce(Return(OK));
|
|
|
| CreateChannelAndConnectSuccessfully();
|
| }
|
|
|
| TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) {
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 16},
|
| - FINAL_CHUNK, "Application data"}};
|
| - static const InitFrameChunk expected1[] = {
|
| - {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 6},
|
| - FINAL_CHUNK, "Hello "}};
|
| - static const InitFrameChunk expected2[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, 16},
|
| - FINAL_CHUNK, "Application data"}};
|
| - static const InitFrameChunk expected3[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, MASKED, 5},
|
| - FINAL_CHUNK, "World"}};
|
| - ScopedVector<WebSocketFrameChunk>* read_chunks;
|
| + static const InitFrame frames[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
|
| + NOT_MASKED, "Application data"}};
|
| + static const InitFrame expected1[] = {
|
| + {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
|
| + static const InitFrame expected2[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
|
| + MASKED, "Application data"}};
|
| + static const InitFrame expected3[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
|
| + MASKED, "World"}};
|
| + ScopedVector<WebSocketFrame>* read_frames;
|
| CompletionCallback read_callback;
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
|
| - .WillOnce(DoAll(SaveArg<0>(&read_chunks),
|
| + .WillOnce(DoAll(SaveArg<0>(&read_frames),
|
| SaveArg<1>(&read_callback),
|
| Return(ERR_IO_PENDING)))
|
| .WillRepeatedly(Return(ERR_IO_PENDING));
|
| {
|
| InSequence s;
|
|
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected1), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
|
| .WillOnce(Return(OK));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected2), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
|
| .WillOnce(Return(OK));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected3), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected3), _))
|
| .WillOnce(Return(OK));
|
| }
|
|
|
| CreateChannelAndConnectSuccessfully();
|
| channel_->SendFrame(
|
| false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello "));
|
| - *read_chunks = CreateFrameChunkVector(chunks);
|
| + *read_frames = CreateFrameVector(frames);
|
| read_callback.Run(OK);
|
| channel_->SendFrame(
|
| true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("World"));
|
| @@ -1703,12 +1508,10 @@ TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) {
|
| // WriteFrames() may not be called until the previous write has completed.
|
| // WebSocketChannel must buffer writes that happen in the meantime.
|
| TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
|
| - static const InitFrameChunk expected1[] = {
|
| - {{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 6},
|
| - FINAL_CHUNK, "Hello "}};
|
| - static const InitFrameChunk expected2[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 5}, FINAL_CHUNK,
|
| - "World"}};
|
| + static const InitFrame expected1[] = {
|
| + {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}};
|
| + static const InitFrame expected2[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "World"}};
|
| CompletionCallback write_callback;
|
| MockFunction<void(int)> checkpoint;
|
|
|
| @@ -1717,10 +1520,10 @@ TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
|
| {
|
| InSequence s;
|
| EXPECT_CALL(checkpoint, Call(1));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected1), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
|
| .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
|
| EXPECT_CALL(checkpoint, Call(2));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected2), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
|
| .WillOnce(Return(ERR_IO_PENDING));
|
| EXPECT_CALL(checkpoint, Call(3));
|
| }
|
| @@ -1741,27 +1544,22 @@ TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
|
| // important to get good throughput in the "many small messages" case.
|
| TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
|
| static const char input_letters[] = "Hello";
|
| - static const InitFrameChunk expected1[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK,
|
| - "H"}};
|
| - static const InitFrameChunk expected2[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK,
|
| - "e"},
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK,
|
| - "l"},
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK,
|
| - "l"},
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, 1}, FINAL_CHUNK,
|
| - "o"}};
|
| + static const InitFrame expected1[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "H"}};
|
| + static const InitFrame expected2[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "e"},
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"},
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "o"}};
|
| CompletionCallback write_callback;
|
|
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
|
| {
|
| InSequence s;
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected1), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
|
| .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected2), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
|
| .WillOnce(Return(ERR_IO_PENDING));
|
| }
|
|
|
| @@ -1781,12 +1579,12 @@ TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
|
| // even be using a different extension which uses that code to mean something
|
| // else.
|
| TEST_F(WebSocketChannelStreamTest, MuxErrorIsNotSentToStream) {
|
| - static const InitFrameChunk expected[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 16},
|
| - FINAL_CHUNK, CLOSE_DATA(GOING_AWAY, "Internal Error")}};
|
| + static const InitFrame expected[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
|
| + MASKED, CLOSE_DATA(GOING_AWAY, "Internal Error")}};
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
|
| .WillOnce(Return(OK));
|
| EXPECT_CALL(*mock_stream_, Close());
|
|
|
| @@ -1800,45 +1598,41 @@ TEST_F(WebSocketChannelStreamTest, MuxErrorIsNotSentToStream) {
|
| // protocol also has Binary frames and those need to be 8-bit clean. For the
|
| // sake of completeness, this test verifies that they are.
|
| TEST_F(WebSocketChannelStreamTest, WrittenBinaryFramesAre8BitClean) {
|
| - ScopedVector<WebSocketFrameChunk>* frame_chunks = NULL;
|
| + ScopedVector<WebSocketFrame>* frames = NULL;
|
|
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
|
| EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
|
| - .WillOnce(DoAll(SaveArg<0>(&frame_chunks), Return(ERR_IO_PENDING)));
|
| + .WillOnce(DoAll(SaveArg<0>(&frames), Return(ERR_IO_PENDING)));
|
|
|
| CreateChannelAndConnectSuccessfully();
|
| channel_->SendFrame(
|
| true,
|
| WebSocketFrameHeader::kOpCodeBinary,
|
| std::vector<char>(kBinaryBlob, kBinaryBlob + kBinaryBlobSize));
|
| - ASSERT_TRUE(frame_chunks != NULL);
|
| - ASSERT_EQ(1U, frame_chunks->size());
|
| - const WebSocketFrameChunk* out_chunk = (*frame_chunks)[0];
|
| - ASSERT_TRUE(out_chunk->header);
|
| - EXPECT_EQ(kBinaryBlobSize, out_chunk->header->payload_length);
|
| - ASSERT_TRUE(out_chunk->data);
|
| - EXPECT_EQ(kBinaryBlobSize, static_cast<size_t>(out_chunk->data->size()));
|
| - EXPECT_EQ(0, memcmp(kBinaryBlob, out_chunk->data->data(), kBinaryBlobSize));
|
| + ASSERT_TRUE(frames != NULL);
|
| + ASSERT_EQ(1U, frames->size());
|
| + const WebSocketFrame* out_frame = (*frames)[0];
|
| + EXPECT_EQ(kBinaryBlobSize, out_frame->header.payload_length);
|
| + ASSERT_TRUE(out_frame->data);
|
| + EXPECT_EQ(0, memcmp(kBinaryBlob, out_frame->data->data(), kBinaryBlobSize));
|
| }
|
|
|
| // Test the read path for 8-bit cleanliness as well.
|
| TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) {
|
| - scoped_ptr<WebSocketFrameHeader> frame_header(
|
| - new WebSocketFrameHeader(WebSocketFrameHeader::kOpCodeBinary));
|
| - frame_header->final = true;
|
| - frame_header->payload_length = kBinaryBlobSize;
|
| - scoped_ptr<WebSocketFrameChunk> frame_chunk(new WebSocketFrameChunk);
|
| - frame_chunk->header = frame_header.Pass();
|
| - frame_chunk->final_chunk = true;
|
| - frame_chunk->data = new IOBufferWithSize(kBinaryBlobSize);
|
| - memcpy(frame_chunk->data->data(), kBinaryBlob, kBinaryBlobSize);
|
| - ScopedVector<WebSocketFrameChunk> chunks;
|
| - chunks.push_back(frame_chunk.release());
|
| + scoped_ptr<WebSocketFrame> frame(
|
| + new WebSocketFrame(WebSocketFrameHeader::kOpCodeBinary));
|
| + WebSocketFrameHeader& frame_header = frame->header;
|
| + frame_header.final = true;
|
| + frame_header.payload_length = kBinaryBlobSize;
|
| + frame->data = new IOBuffer(kBinaryBlobSize);
|
| + memcpy(frame->data->data(), kBinaryBlob, kBinaryBlobSize);
|
| + ScopedVector<WebSocketFrame> frames;
|
| + frames.push_back(frame.release());
|
| scoped_ptr<ReadableFakeWebSocketStream> stream(
|
| new ReadableFakeWebSocketStream);
|
| stream->PrepareRawReadFrames(
|
| - ReadableFakeWebSocketStream::SYNC, OK, chunks.Pass());
|
| + ReadableFakeWebSocketStream::SYNC, OK, frames.Pass());
|
| set_stream(stream.Pass());
|
| EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _));
|
| EXPECT_CALL(*event_interface_, OnFlowControl(_));
|
| @@ -1856,17 +1650,17 @@ TEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) {
|
| // but the current implementation fails the connection. Since a Close has
|
| // already been sent, this just means closing the connection.
|
| TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
|
| - static const InitFrameChunk chunks[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 4},
|
| - FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "OK")},
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, 9},
|
| - FINAL_CHUNK, "Ping body"}};
|
| - static const InitFrameChunk expected[] = {
|
| - {{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 4},
|
| - FINAL_CHUNK, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
|
| + static const InitFrame frames[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
|
| + NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")},
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing,
|
| + NOT_MASKED, "Ping body"}};
|
| + static const InitFrame expected[] = {
|
| + {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
|
| + MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
|
| EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
|
| EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
|
| - .WillOnce(ReturnChunks(&chunks))
|
| + .WillOnce(ReturnFrames(&frames))
|
| .WillRepeatedly(Return(ERR_IO_PENDING));
|
| {
|
| // We only need to verify the relative order of WriteFrames() and
|
| @@ -1874,7 +1668,7 @@ TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
|
| // frame before calling ReadFrames() again, but that is an implementation
|
| // detail and better not to consider required behaviour.
|
| InSequence s;
|
| - EXPECT_CALL(*mock_stream_, WriteFrames(EqualsChunks(expected), _))
|
| + EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
|
| .WillOnce(Return(OK));
|
| EXPECT_CALL(*mock_stream_, Close()).Times(1);
|
| }
|
|
|