19ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 29ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 39ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// found in the LICENSE file. 49ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 59ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "net/websockets/websocket_channel.h" 69ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch#include <limits.h> 8558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include <string.h> 9558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include <iostream> 119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include <string> 129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include <vector> 139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/bind.h" 159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/bind_helpers.h" 169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/callback.h" 17558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#include "base/location.h" 189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/memory/scoped_ptr.h" 199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/memory/scoped_vector.h" 201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "base/memory/weak_ptr.h" 219ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/message_loop/message_loop.h" 229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "base/strings/string_piece.h" 239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "net/base/net_errors.h" 241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "net/base/test_completion_callback.h" 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/http/http_response_headers.h" 269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "net/url_request/url_request_context.h" 279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "net/websockets/websocket_errors.h" 289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "net/websockets/websocket_event_interface.h" 295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_handshake_request_info.h" 305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/websockets/websocket_handshake_response_info.h" 319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "net/websockets/websocket_mux.h" 329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "testing/gmock/include/gmock/gmock.h" 339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch#include "testing/gtest/include/gtest/gtest.h" 34ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "url/gurl.h" 35a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)#include "url/origin.h" 369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 37558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Hacky macros to construct the body of a Close message from a code and a 38558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// string, while ensuring the result is a compile-time constant string. 39558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Use like CLOSE_DATA(NORMAL_CLOSURE, "Explanation String") 40558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#define CLOSE_DATA(code, string) WEBSOCKET_CLOSE_CODE_AS_STRING_##code string 41558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#define WEBSOCKET_CLOSE_CODE_AS_STRING_NORMAL_CLOSURE "\x03\xe8" 42558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#define WEBSOCKET_CLOSE_CODE_AS_STRING_GOING_AWAY "\x03\xe9" 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#define WEBSOCKET_CLOSE_CODE_AS_STRING_PROTOCOL_ERROR "\x03\xea" 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define WEBSOCKET_CLOSE_CODE_AS_STRING_ABNORMAL_CLOSURE "\x03\xee" 45558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch#define WEBSOCKET_CLOSE_CODE_AS_STRING_SERVER_ERROR "\x03\xf3" 46558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochnamespace net { 489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Printing helpers to allow GoogleMock to print frames. These are explicitly 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// designed to look like the static initialisation format we use in these 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// tests. They have to live in the net namespace in order to be found by 529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// GoogleMock; a nested anonymous namespace will not work. 539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochstd::ostream& operator<<(std::ostream& os, const WebSocketFrameHeader& header) { 554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return os << (header.final ? "FINAL_FRAME" : "NOT_FINAL_FRAME") << ", " 569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch << header.opcode << ", " 574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << (header.masked ? "MASKED" : "NOT_MASKED"); 589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)std::ostream& operator<<(std::ostream& os, const WebSocketFrame& frame) { 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) os << "{" << frame.header << ", "; 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (frame.data.get()) { 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return os << "\"" << base::StringPiece(frame.data->data(), 644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frame.header.payload_length) 654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << "\"}"; 669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return os << "NULL}"; 68558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 69558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 70558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochstd::ostream& operator<<(std::ostream& os, 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const ScopedVector<WebSocketFrame>& vector) { 72558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch os << "{"; 73558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch bool first = true; 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (ScopedVector<WebSocketFrame>::const_iterator it = vector.begin(); 75558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch it != vector.end(); 76558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ++it) { 77558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!first) { 78558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch os << ",\n"; 79558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } else { 80558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch first = false; 81558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 82558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch os << **it; 83558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 84558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return os << "}"; 85558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 86558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 87558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochstd::ostream& operator<<(std::ostream& os, 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const ScopedVector<WebSocketFrame>* vector) { 89558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return os << '&' << *vector; 909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochnamespace { 939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using ::base::TimeDelta; 951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochusing ::testing::AnyNumber; 971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)using ::testing::DefaultValue; 989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochusing ::testing::InSequence; 999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochusing ::testing::MockFunction; 10046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)using ::testing::NotNull; 1019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochusing ::testing::Return; 102558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochusing ::testing::SaveArg; 1039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochusing ::testing::StrictMock; 1049ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochusing ::testing::_; 1059ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 106558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// A selection of characters that have traditionally been mangled in some 107558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// environment or other, for testing 8-bit cleanliness. 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)const char kBinaryBlob[] = {'\n', '\r', // BACKWARDS CRNL 109558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch '\0', // nul 110558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch '\x7F', // DEL 111558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch '\x80', '\xFF', // NOT VALID UTF-8 112558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch '\x1A', // Control-Z, EOF on DOS 113558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch '\x03', // Control-C 114558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch '\x04', // EOT, special for Unix terms 115558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch '\x1B', // ESC, often special 116558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch '\b', // backspace 117558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch '\'', // single-quote, special in PHP 118558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}; 119558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst size_t kBinaryBlobSize = arraysize(kBinaryBlob); 120558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 121558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// The amount of quota a new connection gets by default. 122558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// TODO(ricea): If kDefaultSendQuotaHighWaterMark changes, then this value will 123558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// need to be updated. 124558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst size_t kDefaultInitialQuota = 1 << 17; 125558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// The amount of bytes we need to send after the initial connection to trigger a 126558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// quota refresh. TODO(ricea): Change this if kDefaultSendQuotaHighWaterMark or 127558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// kDefaultSendQuotaLowWaterMark change. 128558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochconst size_t kDefaultQuotaRefreshTrigger = (1 << 16) + 1; 129558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 1301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// TestTimeouts::tiny_timeout() is 100ms! I could run halfway around the world 1311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// in that time! I would like my tests to run a bit quicker. 1321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const int kVeryTinyTimeoutMillis = 1; 1331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 134effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Enough quota to pass any test. 135effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochconst int64 kPlentyOfQuota = INT_MAX; 136effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)typedef WebSocketEventInterface::ChannelState ChannelState; 1381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const ChannelState CHANNEL_ALIVE = WebSocketEventInterface::CHANNEL_ALIVE; 1391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)const ChannelState CHANNEL_DELETED = WebSocketEventInterface::CHANNEL_DELETED; 1401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// This typedef mainly exists to avoid having to repeat the "NOLINT" incantation 1421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// all over the place. 143effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochtypedef StrictMock< MockFunction<void(int)> > Checkpoint; // NOLINT 1441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// This mock is for testing expectations about how the EventInterface is used. 1469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass MockWebSocketEventInterface : public WebSocketEventInterface { 1479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch public: 1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MockWebSocketEventInterface() {} 1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOCK_METHOD3(OnAddChannelResponse, 1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ChannelState(bool, 1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string&, 1535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string&)); // NOLINT 1549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch MOCK_METHOD3(OnDataFrame, 1551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ChannelState(bool, 1561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebSocketMessageType, 1571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::vector<char>&)); // NOLINT 1585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOCK_METHOD1(OnFlowControl, ChannelState(int64)); // NOLINT 1591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) MOCK_METHOD0(OnClosingHandshake, ChannelState(void)); // NOLINT 1605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOCK_METHOD1(OnFailChannel, ChannelState(const std::string&)); // NOLINT 1615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOCK_METHOD3(OnDropChannel, 1625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ChannelState(bool, uint16, const std::string&)); // NOLINT 1635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // We can't use GMock with scoped_ptr. 1655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ChannelState OnStartOpeningHandshake( 1665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo>) OVERRIDE { 1675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnStartOpeningHandshakeCalled(); 1685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CHANNEL_ALIVE; 1695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 1705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ChannelState OnFinishOpeningHandshake( 1715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo>) OVERRIDE { 1725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFinishOpeningHandshakeCalled(); 1735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CHANNEL_ALIVE; 1745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 17546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual ChannelState OnSSLCertificateError( 17646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks, 17746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const GURL& url, 17846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const SSLInfo& ssl_info, 17946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool fatal) OVERRIDE { 18046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) OnSSLCertificateErrorCalled( 18146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) ssl_error_callbacks.get(), url, ssl_info, fatal); 18246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return CHANNEL_ALIVE; 18346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 1845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOCK_METHOD0(OnStartOpeningHandshakeCalled, void()); // NOLINT 1865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MOCK_METHOD0(OnFinishOpeningHandshakeCalled, void()); // NOLINT 18746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) MOCK_METHOD4( 18846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) OnSSLCertificateErrorCalled, 18946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) void(SSLErrorCallbacks*, const GURL&, const SSLInfo&, bool)); // NOLINT 1909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 1919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// This fake EventInterface is for tests which need a WebSocketEventInterface 1939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// implementation but are not verifying how it is used. 1949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass FakeWebSocketEventInterface : public WebSocketEventInterface { 1951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual ChannelState OnAddChannelResponse( 1969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch bool fail, 1975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& selected_protocol, 1985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& extensions) OVERRIDE { 1991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return fail ? CHANNEL_DELETED : CHANNEL_ALIVE; 2001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual ChannelState OnDataFrame(bool fin, 2021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebSocketMessageType type, 2031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::vector<char>& data) OVERRIDE { 2041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return CHANNEL_ALIVE; 2051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual ChannelState OnFlowControl(int64 quota) OVERRIDE { 2071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return CHANNEL_ALIVE; 2081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual ChannelState OnClosingHandshake() OVERRIDE { return CHANNEL_ALIVE; } 2105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ChannelState OnFailChannel(const std::string& message) OVERRIDE { 2115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CHANNEL_DELETED; 2125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ChannelState OnDropChannel(bool was_clean, 2145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint16 code, 2151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& reason) OVERRIDE { 2161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return CHANNEL_DELETED; 2171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ChannelState OnStartOpeningHandshake( 2195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo> request) OVERRIDE { 2205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CHANNEL_ALIVE; 2215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 2225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ChannelState OnFinishOpeningHandshake( 2235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo> response) OVERRIDE { 2245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return CHANNEL_ALIVE; 2255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 22646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual ChannelState OnSSLCertificateError( 22746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks, 22846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const GURL& url, 22946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const SSLInfo& ssl_info, 23046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool fatal) OVERRIDE { 23146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return CHANNEL_ALIVE; 23246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 2339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 2349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// This fake WebSocketStream is for tests that require a WebSocketStream but are 2369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// not testing the way it is used. It has minimal functionality to return 2379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// the |protocol| and |extensions| that it was constructed with. 2389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass FakeWebSocketStream : public WebSocketStream { 2399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch public: 2409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Constructs with empty protocol and extensions. 2419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch FakeWebSocketStream() {} 2429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Constructs with specified protocol and extensions. 2449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch FakeWebSocketStream(const std::string& protocol, 2459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const std::string& extensions) 2469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch : protocol_(protocol), extensions_(extensions) {} 2479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames, 2499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const CompletionCallback& callback) OVERRIDE { 2509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return ERR_IO_PENDING; 2519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 2529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames, 2549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const CompletionCallback& callback) OVERRIDE { 2559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return ERR_IO_PENDING; 2569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 2579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch virtual void Close() OVERRIDE {} 2599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Returns the string passed to the constructor. 2619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch virtual std::string GetSubProtocol() const OVERRIDE { return protocol_; } 2629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Returns the string passed to the constructor. 2649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch virtual std::string GetExtensions() const OVERRIDE { return extensions_; } 2659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch private: 2679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // The string to return from GetSubProtocol(). 2689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch std::string protocol_; 2699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // The string to return from GetExtensions(). 2719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch std::string extensions_; 2729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 2739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// To make the static initialisers easier to read, we use enums rather than 2759ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// bools. 2765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)enum IsFinal { NOT_FINAL_FRAME, FINAL_FRAME }; 2779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)enum IsMasked { NOT_MASKED, MASKED }; 2799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// This is used to initialise a WebSocketFrame but is statically initialisable. 2814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)struct InitFrame { 2824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IsFinal final; 2834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Reserved fields omitted for now. Add them if you need them. 2844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WebSocketFrameHeader::OpCode opcode; 2854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IsMasked masked; 2869ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2879ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Will be used to create the IOBuffer member. Can be NULL for NULL data. Is a 2884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // nul-terminated string for ease-of-use. |header.payload_length| is 2894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // initialised from |strlen(data)|. This means it is not 8-bit clean, but this 2904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // is not an issue for test data. 2919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const char* const data; 2929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 2939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 294558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// For GoogleMock 2954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)std::ostream& operator<<(std::ostream& os, const InitFrame& frame) { 2964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) os << "{" << (frame.final == FINAL_FRAME ? "FINAL_FRAME" : "NOT_FINAL_FRAME") 2974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << ", " << frame.opcode << ", " 2984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << (frame.masked == MASKED ? "MASKED" : "NOT_MASKED") << ", "; 2994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (frame.data) { 3004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return os << "\"" << frame.data << "\"}"; 301558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 3024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return os << "NULL}"; 303558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 304558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 305558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochtemplate <size_t N> 3064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)std::ostream& operator<<(std::ostream& os, const InitFrame (&frames)[N]) { 307558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch os << "{"; 308558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch bool first = true; 309558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch for (size_t i = 0; i < N; ++i) { 310558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (!first) { 311558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch os << ",\n"; 312558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } else { 313558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch first = false; 314558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 3154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) os << frames[i]; 316558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 317558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return os << "}"; 318558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 319558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 3204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Convert a const array of InitFrame structs to the format used at 3219ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// runtime. Templated on the size of the array to save typing. 3229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochtemplate <size_t N> 3234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ScopedVector<WebSocketFrame> CreateFrameVector( 3244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const InitFrame (&source_frames)[N]) { 3254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ScopedVector<WebSocketFrame> result_frames; 3264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result_frames.reserve(N); 3279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch for (size_t i = 0; i < N; ++i) { 3284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const InitFrame& source_frame = source_frames[i]; 3294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<WebSocketFrame> result_frame( 3304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new WebSocketFrame(source_frame.opcode)); 3314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) size_t frame_length = source_frame.data ? strlen(source_frame.data) : 0; 3324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WebSocketFrameHeader& result_header = result_frame->header; 3334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result_header.final = (source_frame.final == FINAL_FRAME); 3344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result_header.masked = (source_frame.masked == MASKED); 3354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result_header.payload_length = frame_length; 3364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (source_frame.data) { 3374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result_frame->data = new IOBuffer(frame_length); 3384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) memcpy(result_frame->data->data(), source_frame.data, frame_length); 3399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 3404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) result_frames.push_back(result_frame.release()); 3419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 3424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return result_frames.Pass(); 3439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 3449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 3459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// A GoogleMock action which can be used to respond to call to ReadFrames with 3464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// some frames. Use like ReadFrames(_, _).WillOnce(ReturnFrames(&frames)); 3474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// |frames| is an array of InitFrame. |frames| needs to be passed by pointer 3484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// because otherwise it will be treated as a pointer and the array size 3494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// information will be lost. 3504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)ACTION_P(ReturnFrames, source_frames) { 3514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *arg0 = CreateFrameVector(*source_frames); 3529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return OK; 3539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 3549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 355558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// The implementation of a GoogleMock matcher which can be used to compare a 3564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// ScopedVector<WebSocketFrame>* against an expectation defined as an array of 3574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// InitFrame objects. Although it is possible to compose built-in GoogleMock 3584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// matchers to check the contents of a WebSocketFrame, the results are so 359558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// unreadable that it is better to use this matcher. 360558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochtemplate <size_t N> 3614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)class EqualsFramesMatcher 3624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : public ::testing::MatcherInterface<ScopedVector<WebSocketFrame>*> { 363558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch public: 3644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EqualsFramesMatcher(const InitFrame (*expect_frames)[N]) 3654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : expect_frames_(expect_frames) {} 366558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 3674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual bool MatchAndExplain(ScopedVector<WebSocketFrame>* actual_frames, 368558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ::testing::MatchResultListener* listener) const { 3694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (actual_frames->size() != N) { 3704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *listener << "the vector size is " << actual_frames->size(); 371558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return false; 372558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 373558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch for (size_t i = 0; i < N; ++i) { 3744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const WebSocketFrame& actual_frame = *(*actual_frames)[i]; 3754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const InitFrame& expected_frame = (*expect_frames_)[i]; 3764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (actual_frame.header.final != (expected_frame.final == FINAL_FRAME)) { 3774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *listener << "the frame is marked as " 3784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << (actual_frame.header.final ? "" : "not ") << "final"; 379558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return false; 380558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 3814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (actual_frame.header.opcode != expected_frame.opcode) { 3824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *listener << "the opcode is " << actual_frame.header.opcode; 3834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return false; 384558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 3854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (actual_frame.header.masked != (expected_frame.masked == MASKED)) { 3864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *listener << "the frame is " 3874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << (actual_frame.header.masked ? "masked" : "not masked"); 388558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return false; 389558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 3904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const size_t expected_length = 3914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) expected_frame.data ? strlen(expected_frame.data) : 0; 3924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (actual_frame.header.payload_length != expected_length) { 3934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *listener << "the payload length is " 3944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) << actual_frame.header.payload_length; 395558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return false; 396558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 3974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (expected_length != 0 && 3984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) memcmp(actual_frame.data->data(), 3994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) expected_frame.data, 4004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) actual_frame.header.payload_length) != 0) { 401558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch *listener << "the data content differs"; 402558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return false; 403558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 404558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 405558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return true; 406558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 407558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 408558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch virtual void DescribeTo(std::ostream* os) const { 4094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *os << "matches " << *expect_frames_; 410558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 411558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 412558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch virtual void DescribeNegationTo(std::ostream* os) const { 4134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *os << "does not match " << *expect_frames_; 414558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 415558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 416558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch private: 4174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const InitFrame (*expect_frames_)[N]; 418558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}; 419558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 4204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// The definition of EqualsFrames GoogleMock matcher. Unlike the ReturnFrames 421558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// action, this can take the array by reference. 422558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochtemplate <size_t N> 4234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)::testing::Matcher<ScopedVector<WebSocketFrame>*> EqualsFrames( 4244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const InitFrame (&frames)[N]) { 4254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return ::testing::MakeMatcher(new EqualsFramesMatcher<N>(&frames)); 426558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 427558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 4281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// TestClosure works like TestCompletionCallback, but doesn't take an argument. 4291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class TestClosure { 4301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) public: 4311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Closure closure() { return base::Bind(callback_.callback(), OK); } 4321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void WaitForResult() { callback_.WaitForResult(); } 4341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) private: 4361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Delegate to TestCompletionCallback for the implementation. 4371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TestCompletionCallback callback_; 4381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 4391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// A GoogleMock action to run a Closure. 4411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ACTION_P(InvokeClosure, closure) { closure.Run(); } 4421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// A GoogleMock action to run a Closure and return CHANNEL_DELETED. 4441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)ACTION_P(InvokeClosureReturnDeleted, closure) { 4451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) closure.Run(); 4461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return WebSocketEventInterface::CHANNEL_DELETED; 4471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 4481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 4499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// A FakeWebSocketStream whose ReadFrames() function returns data. 4509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass ReadableFakeWebSocketStream : public FakeWebSocketStream { 4519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch public: 4525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) enum IsSync { SYNC, ASYNC }; 4539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 4549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // After constructing the object, call PrepareReadFrames() once for each 4559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // time you wish it to return from the test. 4569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ReadableFakeWebSocketStream() : index_(0), read_frames_pending_(false) {} 4579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 4589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Check that all the prepared responses have been consumed. 4599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch virtual ~ReadableFakeWebSocketStream() { 4609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CHECK(index_ >= responses_.size()); 4619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CHECK(!read_frames_pending_); 4629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 4639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 4644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Prepares a fake response. Fake responses will be returned from ReadFrames() 4654e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // in the same order they were prepared with PrepareReadFrames() and 4664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // PrepareReadFramesError(). If |async| is ASYNC, then ReadFrames() will 4679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // return ERR_IO_PENDING and the callback will be scheduled to run on the 4689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // message loop. This requires the test case to run the message loop. If 4699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // |async| is SYNC, the response will be returned synchronously. |error| is 4709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // returned directly from ReadFrames() in the synchronous case, or passed to 4714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // the callback in the asynchronous case. |frames| will be converted to a 4724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // ScopedVector<WebSocketFrame> and copied to the pointer that was passed to 4734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // ReadFrames(). 4749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch template <size_t N> 4759ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch void PrepareReadFrames(IsSync async, 4769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch int error, 4774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const InitFrame (&frames)[N]) { 4784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) responses_.push_back(new Response(async, error, CreateFrameVector(frames))); 4799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 4809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 481558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // An alternate version of PrepareReadFrames for when we need to construct 482558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // the frames manually. 483558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch void PrepareRawReadFrames(IsSync async, 484558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch int error, 4854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ScopedVector<WebSocketFrame> frames) { 4864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) responses_.push_back(new Response(async, error, frames.Pass())); 487558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 488558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 4899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Prepares a fake error response (ie. there is no data). 4909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch void PrepareReadFramesError(IsSync async, int error) { 4919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch responses_.push_back( 4924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new Response(async, error, ScopedVector<WebSocketFrame>())); 4939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 4949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 4954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames, 4969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const CompletionCallback& callback) OVERRIDE { 4979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CHECK(!read_frames_pending_); 4989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (index_ >= responses_.size()) 4999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return ERR_IO_PENDING; 5009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (responses_[index_]->async == ASYNC) { 5019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch read_frames_pending_ = true; 5029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->PostTask( 5039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch FROM_HERE, 5049ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::Bind(&ReadableFakeWebSocketStream::DoCallback, 5059ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::Unretained(this), 5064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frames, 5079ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch callback)); 5089ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return ERR_IO_PENDING; 5099ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } else { 5104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frames->swap(responses_[index_]->frames); 5119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return responses_[index_++]->error; 5129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 5139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 5149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch private: 5164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) void DoCallback(ScopedVector<WebSocketFrame>* frames, 5179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const CompletionCallback& callback) { 5189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch read_frames_pending_ = false; 5194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frames->swap(responses_[index_]->frames); 5209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch callback.Run(responses_[index_++]->error); 5219ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return; 5229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 5239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch struct Response { 5254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Response(IsSync async, int error, ScopedVector<WebSocketFrame> frames) 5264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : async(async), error(error), frames(frames.Pass()) {} 5279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch IsSync async; 5299ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch int error; 5304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ScopedVector<WebSocketFrame> frames; 5319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch private: 5334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Bad things will happen if we attempt to copy or assign |frames|. 5349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch DISALLOW_COPY_AND_ASSIGN(Response); 5359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch }; 5369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ScopedVector<Response> responses_; 5379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // The index into the responses_ array of the next response to be returned. 5399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch size_t index_; 5409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // True when an async response from ReadFrames() is pending. This only applies 5429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // to "real" async responses. Once all the prepared responses have been 5439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // returned, ReadFrames() returns ERR_IO_PENDING but read_frames_pending_ is 5449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // not set to true. 5459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch bool read_frames_pending_; 5469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 5479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// A FakeWebSocketStream where writes always complete successfully and 5499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// synchronously. 5509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass WriteableFakeWebSocketStream : public FakeWebSocketStream { 5519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch public: 5524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames, 5539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const CompletionCallback& callback) OVERRIDE { 5549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return OK; 5559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 5569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 5579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// A FakeWebSocketStream where writes always fail. 5599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass UnWriteableFakeWebSocketStream : public FakeWebSocketStream { 5609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch public: 5614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames, 5629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const CompletionCallback& callback) OVERRIDE { 5639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return ERR_CONNECTION_RESET; 5649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 5659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 5669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// A FakeWebSocketStream which echoes any frames written back. Clears the 5689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// "masked" header bit, but makes no other checks for validity. Tests using this 5699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// must run the MessageLoop to receive the callback(s). If a message with opcode 5709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Close is echoed, then an ERR_CONNECTION_CLOSED is returned in the next 5719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// callback. The test must do something to cause WriteFrames() to be called, 5729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// otherwise the ReadFrames() callback will never be called. 5739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass EchoeyFakeWebSocketStream : public FakeWebSocketStream { 5749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch public: 5754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EchoeyFakeWebSocketStream() : read_frames_(NULL), done_(false) {} 5769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames, 5789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const CompletionCallback& callback) OVERRIDE { 5799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Users of WebSocketStream will not expect the ReadFrames() callback to be 5809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // called from within WriteFrames(), so post it to the message loop instead. 5814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stored_frames_.insert(stored_frames_.end(), frames->begin(), frames->end()); 5824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frames->weak_clear(); 5839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch PostCallback(); 5849ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return OK; 5859ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 5869ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames, 5889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const CompletionCallback& callback) OVERRIDE { 5899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch read_callback_ = callback; 5904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) read_frames_ = frames; 5919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (done_) 5929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch PostCallback(); 5939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return ERR_IO_PENDING; 5949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 5959ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 5969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch private: 5979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch void PostCallback() { 5989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->PostTask( 5999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch FROM_HERE, 6009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::Bind(&EchoeyFakeWebSocketStream::DoCallback, 6019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::Unretained(this))); 6029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 6039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 6049ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch void DoCallback() { 6059ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch if (done_) { 6069ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch read_callback_.Run(ERR_CONNECTION_CLOSED); 6074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else if (!stored_frames_.empty()) { 6084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) done_ = MoveFrames(read_frames_); 6094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) read_frames_ = NULL; 6109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch read_callback_.Run(OK); 6119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 6129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 6139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 6144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Copy the frames stored in stored_frames_ to |out|, while clearing the 6159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // "masked" header bit. Returns true if a Close Frame was seen, false 6169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // otherwise. 6174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) bool MoveFrames(ScopedVector<WebSocketFrame>* out) { 6189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch bool seen_close = false; 6194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *out = stored_frames_.Pass(); 6204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (ScopedVector<WebSocketFrame>::iterator it = out->begin(); 6219ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch it != out->end(); 6229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ++it) { 6234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WebSocketFrameHeader& header = (*it)->header; 6244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) header.masked = false; 6254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (header.opcode == WebSocketFrameHeader::kOpCodeClose) 6264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) seen_close = true; 6279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 6289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return seen_close; 6299ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 6309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 6314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ScopedVector<WebSocketFrame> stored_frames_; 6329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CompletionCallback read_callback_; 6339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Owned by the caller of ReadFrames(). 6344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ScopedVector<WebSocketFrame>* read_frames_; 6359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // True if we should close the connection. 6369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch bool done_; 6379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 6389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 639558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// A FakeWebSocketStream where writes trigger a connection reset. 640558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// This differs from UnWriteableFakeWebSocketStream in that it is asynchronous 641558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// and triggers ReadFrames to return a reset as well. Tests using this need to 6421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// run the message loop. There are two tricky parts here: 6431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// 1. Calling the write callback may call Close(), after which the read callback 6441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// should not be called. 6451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// 2. Calling either callback may delete the stream altogether. 646558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochclass ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream { 647558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch public: 6481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ResetOnWriteFakeWebSocketStream() : closed_(false), weak_ptr_factory_(this) {} 6491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 6504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual int WriteFrames(ScopedVector<WebSocketFrame>* frames, 651558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch const CompletionCallback& callback) OVERRIDE { 652558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch base::MessageLoop::current()->PostTask( 6531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 6541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed, 6551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 6561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) callback, 6571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ERR_CONNECTION_RESET)); 658558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch base::MessageLoop::current()->PostTask( 6591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) FROM_HERE, 6601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::Bind(&ResetOnWriteFakeWebSocketStream::CallCallbackUnlessClosed, 6611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) weak_ptr_factory_.GetWeakPtr(), 6621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) read_callback_, 6631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ERR_CONNECTION_RESET)); 664558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return ERR_IO_PENDING; 665558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 666558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 6674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) virtual int ReadFrames(ScopedVector<WebSocketFrame>* frames, 668558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch const CompletionCallback& callback) OVERRIDE { 669558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch read_callback_ = callback; 670558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return ERR_IO_PENDING; 671558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 672558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 6731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual void Close() OVERRIDE { closed_ = true; } 6741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 675558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch private: 6761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) void CallCallbackUnlessClosed(const CompletionCallback& callback, int value) { 6771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!closed_) 6781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) callback.Run(value); 6791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 6801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 681558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CompletionCallback read_callback_; 6821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool closed_; 6831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // An IO error can result in the socket being deleted, so we use weak pointers 6841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // to ensure correct behaviour in that case. 6851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::WeakPtrFactory<ResetOnWriteFakeWebSocketStream> weak_ptr_factory_; 686558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}; 687558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 6889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// This mock is for verifying that WebSocket protocol semantics are obeyed (to 6899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// the extent that they are implemented in WebSocketCommon). 6909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass MockWebSocketStream : public WebSocketStream { 6919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch public: 6929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch MOCK_METHOD2(ReadFrames, 6934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int(ScopedVector<WebSocketFrame>* frames, 6949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const CompletionCallback& callback)); 6959ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch MOCK_METHOD2(WriteFrames, 6964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int(ScopedVector<WebSocketFrame>* frames, 6979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const CompletionCallback& callback)); 6989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch MOCK_METHOD0(Close, void()); 6999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch MOCK_CONST_METHOD0(GetSubProtocol, std::string()); 7009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch MOCK_CONST_METHOD0(GetExtensions, std::string()); 7019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch MOCK_METHOD0(AsWebSocketStream, WebSocketStream*()); 7029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 7039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)struct ArgumentCopyingWebSocketStreamCreator { 705f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<WebSocketStreamRequest> Create( 7069ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const GURL& socket_url, 7079ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const std::vector<std::string>& requested_subprotocols, 708a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) const url::Origin& origin, 7099ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch URLRequestContext* url_request_context, 7109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch const BoundNetLog& net_log, 7119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate) { 7129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch this->socket_url = socket_url; 7139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch this->requested_subprotocols = requested_subprotocols; 7149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch this->origin = origin; 7159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch this->url_request_context = url_request_context; 7169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch this->net_log = net_log; 7179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch this->connect_delegate = connect_delegate.Pass(); 7189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return make_scoped_ptr(new WebSocketStreamRequest); 7199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 7209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7219ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch GURL socket_url; 722a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) url::Origin origin; 7239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch std::vector<std::string> requested_subprotocols; 7249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch URLRequestContext* url_request_context; 7259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch BoundNetLog net_log; 7269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<WebSocketStream::ConnectDelegate> connect_delegate; 7279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 7289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7299ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Converts a std::string to a std::vector<char>. For test purposes, it is 7309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// convenient to be able to specify data as a string, but the 7319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// WebSocketEventInterface requires the vector<char> type. 7329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochstd::vector<char> AsVector(const std::string& s) { 7339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return std::vector<char>(s.begin(), s.end()); 7349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 7359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 73646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)class FakeSSLErrorCallbacks 73746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) : public WebSocketEventInterface::SSLErrorCallbacks { 73846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) public: 73946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual void CancelSSLRequest(int error, const SSLInfo* ssl_info) OVERRIDE {} 74046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual void ContinueSSLRequest() OVERRIDE {} 74146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)}; 74246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 7439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Base class for all test fixtures. 7449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass WebSocketChannelTest : public ::testing::Test { 7459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch protected: 7469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch WebSocketChannelTest() : stream_(new FakeWebSocketStream) {} 7479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Creates a new WebSocketChannel and connects it, using the settings stored 7499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // in |connect_data_|. 7509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch void CreateChannelAndConnect() { 7514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) channel_.reset(new WebSocketChannel(CreateEventInterface(), 7524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) &connect_data_.url_request_context)); 7539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch channel_->SendAddChannelRequestForTesting( 7548bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) connect_data_.socket_url, 7559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch connect_data_.requested_subprotocols, 7569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch connect_data_.origin, 757f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Bind(&ArgumentCopyingWebSocketStreamCreator::Create, 758f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::Unretained(&connect_data_.creator))); 7599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 7609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Same as CreateChannelAndConnect(), but calls the on_success callback as 7629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // well. This method is virtual so that subclasses can also set the stream. 7639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch virtual void CreateChannelAndConnectSuccessfully() { 7649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnect(); 765effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Most tests aren't concerned with flow control from the renderer, so allow 766effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // MAX_INT quota units. 767effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(kPlentyOfQuota); 768f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass()); 7699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 7709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Returns a WebSocketEventInterface to be passed to the WebSocketChannel. 7729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // This implementation returns a newly-created fake. Subclasses may return a 7739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // mock instead. 7749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch virtual scoped_ptr<WebSocketEventInterface> CreateEventInterface() { 7759ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return scoped_ptr<WebSocketEventInterface>(new FakeWebSocketEventInterface); 7769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 7779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // This method serves no other purpose than to provide a nice syntax for 7799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // assigning to stream_. class T must be a subclass of WebSocketStream or you 7809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // will have unpleasant compile errors. 7819ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch template <class T> 7829ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch void set_stream(scoped_ptr<T> stream) { 7839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Since the definition of "PassAs" depends on the type T, the C++ standard 7849ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // requires the "template" keyword to indicate that "PassAs" should be 7859ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // parsed as a template method. 7869ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch stream_ = stream.template PassAs<WebSocketStream>(); 7879ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 7889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 7899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // A struct containing the data that will be used to connect the channel. 7908bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Grouped for readability. 7919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch struct ConnectData { 792a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ConnectData() : socket_url("ws://ws/"), origin("http://ws") {} 793f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 7948bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // URLRequestContext object. 7958bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) URLRequestContext url_request_context; 7968bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 7979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // URL to (pretend to) connect to. 7988bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) GURL socket_url; 7999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Requested protocols for the request. 8009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch std::vector<std::string> requested_subprotocols; 8018bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) // Origin of the request 802a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) url::Origin origin; 8038bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 804f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // A fake WebSocketStreamCreator that just records its arguments. 805f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ArgumentCopyingWebSocketStreamCreator creator; 8069ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch }; 8079ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ConnectData connect_data_; 8089ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 8099ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // The channel we are testing. Not initialised until SetChannel() is called. 8109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<WebSocketChannel> channel_; 8119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 8129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // A mock or fake stream for tests that need one. 8139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<WebSocketStream> stream_; 8149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 8159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 8161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// enum of WebSocketEventInterface calls. These are intended to be or'd together 8171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// in order to instruct WebSocketChannelDeletingTest when it should fail. 8181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)enum EventInterfaceCall { 8191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EVENT_ON_ADD_CHANNEL_RESPONSE = 0x1, 8201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EVENT_ON_DATA_FRAME = 0x2, 8211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EVENT_ON_FLOW_CONTROL = 0x4, 8221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EVENT_ON_CLOSING_HANDSHAKE = 0x8, 8235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EVENT_ON_FAIL_CHANNEL = 0x10, 8245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EVENT_ON_DROP_CHANNEL = 0x20, 8255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EVENT_ON_START_OPENING_HANDSHAKE = 0x40, 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EVENT_ON_FINISH_OPENING_HANDSHAKE = 0x80, 82746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EVENT_ON_SSL_CERTIFICATE_ERROR = 0x100, 8281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 8291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 830558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochclass WebSocketChannelDeletingTest : public WebSocketChannelTest { 831558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch public: 8321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ChannelState DeleteIfDeleting(EventInterfaceCall call) { 8331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (deleting_ & call) { 8341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_.reset(); 8351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return CHANNEL_DELETED; 8361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } else { 8371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return CHANNEL_ALIVE; 8381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 8391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 840558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 841558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch protected: 8421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebSocketChannelDeletingTest() 8431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) : deleting_(EVENT_ON_ADD_CHANNEL_RESPONSE | EVENT_ON_DATA_FRAME | 8441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EVENT_ON_FLOW_CONTROL | 8451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EVENT_ON_CLOSING_HANDSHAKE | 8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EVENT_ON_FAIL_CHANNEL | 8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EVENT_ON_DROP_CHANNEL | 8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EVENT_ON_START_OPENING_HANDSHAKE | 84946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EVENT_ON_FINISH_OPENING_HANDSHAKE | 85046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EVENT_ON_SSL_CERTIFICATE_ERROR) {} 851558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Create a ChannelDeletingFakeWebSocketEventInterface. Defined out-of-line to 852558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // avoid circular dependency. 853558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch virtual scoped_ptr<WebSocketEventInterface> CreateEventInterface() OVERRIDE; 8541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 8551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Tests can set deleting_ to a bitmap of EventInterfaceCall members that they 8561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // want to cause Channel deletion. The default is for all calls to cause 8571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // deletion. 8581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) int deleting_; 859558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}; 860558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 861558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// A FakeWebSocketEventInterface that deletes the WebSocketChannel on failure to 862558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// connect. 863558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochclass ChannelDeletingFakeWebSocketEventInterface 864558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch : public FakeWebSocketEventInterface { 865558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch public: 866558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ChannelDeletingFakeWebSocketEventInterface( 867558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebSocketChannelDeletingTest* fixture) 868558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch : fixture_(fixture) {} 869558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 8701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual ChannelState OnAddChannelResponse( 871558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch bool fail, 8725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& selected_protocol, 8735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& extensions) OVERRIDE { 8741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return fixture_->DeleteIfDeleting(EVENT_ON_ADD_CHANNEL_RESPONSE); 8751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 8761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 8771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual ChannelState OnDataFrame(bool fin, 8781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebSocketMessageType type, 8791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::vector<char>& data) OVERRIDE { 8801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return fixture_->DeleteIfDeleting(EVENT_ON_DATA_FRAME); 8811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 8821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 8831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual ChannelState OnFlowControl(int64 quota) OVERRIDE { 8841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return fixture_->DeleteIfDeleting(EVENT_ON_FLOW_CONTROL); 8851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 8861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 8871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual ChannelState OnClosingHandshake() OVERRIDE { 8881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return fixture_->DeleteIfDeleting(EVENT_ON_CLOSING_HANDSHAKE); 8891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 8901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 8915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ChannelState OnFailChannel(const std::string& message) OVERRIDE { 8925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return fixture_->DeleteIfDeleting(EVENT_ON_FAIL_CHANNEL); 8935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 8945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 8955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ChannelState OnDropChannel(bool was_clean, 8965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint16 code, 8971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) const std::string& reason) OVERRIDE { 8981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return fixture_->DeleteIfDeleting(EVENT_ON_DROP_CHANNEL); 899558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 900558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 9015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ChannelState OnStartOpeningHandshake( 9025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo> request) OVERRIDE { 9035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return fixture_->DeleteIfDeleting(EVENT_ON_START_OPENING_HANDSHAKE); 9045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual ChannelState OnFinishOpeningHandshake( 9065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo> response) OVERRIDE { 9075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return fixture_->DeleteIfDeleting(EVENT_ON_FINISH_OPENING_HANDSHAKE); 9085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 90946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) virtual ChannelState OnSSLCertificateError( 91046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<SSLErrorCallbacks> ssl_error_callbacks, 91146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const GURL& url, 91246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const SSLInfo& ssl_info, 91346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) bool fatal) OVERRIDE { 91446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return fixture_->DeleteIfDeleting(EVENT_ON_SSL_CERTIFICATE_ERROR); 91546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 917558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch private: 918558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // A pointer to the test fixture. Owned by the test harness; this object will 919558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // be deleted before it is. 920558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebSocketChannelDeletingTest* fixture_; 921558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch}; 922558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 923558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochscoped_ptr<WebSocketEventInterface> 924558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochWebSocketChannelDeletingTest::CreateEventInterface() { 925558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch return scoped_ptr<WebSocketEventInterface>( 926558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch new ChannelDeletingFakeWebSocketEventInterface(this)); 927558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 928558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 9299ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Base class for tests which verify that EventInterface methods are called 9309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// appropriately. 9319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass WebSocketChannelEventInterfaceTest : public WebSocketChannelTest { 9329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch protected: 9339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch WebSocketChannelEventInterfaceTest() 9341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) : event_interface_(new StrictMock<MockWebSocketEventInterface>) { 9351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DefaultValue<ChannelState>::Set(CHANNEL_ALIVE); 9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ON_CALL(*event_interface_, OnAddChannelResponse(true, _, _)) 9375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillByDefault(Return(CHANNEL_DELETED)); 9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ON_CALL(*event_interface_, OnDropChannel(_, _, _)) 9391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillByDefault(Return(CHANNEL_DELETED)); 9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ON_CALL(*event_interface_, OnFailChannel(_)) 9411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillByDefault(Return(CHANNEL_DELETED)); 9421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 9431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 9441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual ~WebSocketChannelEventInterfaceTest() { 9451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DefaultValue<ChannelState>::Clear(); 9461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 9479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 9489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // Tests using this fixture must set expectations on the event_interface_ mock 9499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // object before calling CreateChannelAndConnect() or 9509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // CreateChannelAndConnectSuccessfully(). This will only work once per test 9519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // case, but once should be enough. 9529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch virtual scoped_ptr<WebSocketEventInterface> CreateEventInterface() OVERRIDE { 9539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch return scoped_ptr<WebSocketEventInterface>(event_interface_.release()); 9549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 9559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 9569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<MockWebSocketEventInterface> event_interface_; 9579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 9589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 9599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Base class for tests which verify that WebSocketStream methods are called 9609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// appropriately by using a MockWebSocketStream. 9619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdochclass WebSocketChannelStreamTest : public WebSocketChannelTest { 9629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch protected: 9639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch WebSocketChannelStreamTest() 9649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch : mock_stream_(new StrictMock<MockWebSocketStream>) {} 9659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 9669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch virtual void CreateChannelAndConnectSuccessfully() OVERRIDE { 9679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(mock_stream_.Pass()); 9689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch WebSocketChannelTest::CreateChannelAndConnectSuccessfully(); 9699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 9709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 9719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<MockWebSocketStream> mock_stream_; 9729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch}; 9739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 9745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Fixture for tests which test UTF-8 validation of sent Text frames via the 9755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// EventInterface. 9765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class WebSocketChannelSendUtf8Test 9775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : public WebSocketChannelEventInterfaceTest { 9785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 9795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void SetUp() { 9805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 9815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // For the purpose of the tests using this fixture, it doesn't matter 9825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // whether these methods are called or not. 9835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(_, _, _)) 9845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .Times(AnyNumber()); 9855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)) 9865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .Times(AnyNumber()); 9875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 9885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 9895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 990effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Fixture for tests which test use of receive quota from the renderer. 991effb81e5f8246d0db0270817048dc992db66e9fbBen Murdochclass WebSocketChannelFlowControlTest 992effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch : public WebSocketChannelEventInterfaceTest { 993effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch protected: 994effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // Tests using this fixture should use CreateChannelAndConnectWithQuota() 995effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch // instead of CreateChannelAndConnectSuccessfully(). 996effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch void CreateChannelAndConnectWithQuota(int64 quota) { 997effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateChannelAndConnect(); 998effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(quota); 999effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass()); 1000effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 1001effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 1002effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch virtual void CreateChannelAndConnectSuccesfully() { NOTREACHED(); } 1003effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch}; 1004effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 10055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Fixture for tests which test UTF-8 validation of received Text frames using a 10065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// mock WebSocketStream. 10075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class WebSocketChannelReceiveUtf8Test : public WebSocketChannelStreamTest { 10085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 10095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) virtual void SetUp() { 10105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // For the purpose of the tests using this fixture, it doesn't matter 10115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // whether these methods are called or not. 10125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 10135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 10145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 10155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 10165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1017f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Simple test that everything that should be passed to the creator function is 1018f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// passed to the creator function. 1019f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebSocketChannelTest, EverythingIsPassedToTheCreatorFunction) { 10208bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) connect_data_.socket_url = GURL("ws://example.com/test"); 1021a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) connect_data_.origin = url::Origin("http://example.com"); 10229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch connect_data_.requested_subprotocols.push_back("Sinbad"); 10239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 10249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnect(); 10259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1026f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const ArgumentCopyingWebSocketStreamCreator& actual = connect_data_.creator; 10278bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 10288bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) EXPECT_EQ(&connect_data_.url_request_context, actual.url_request_context); 10298bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) 10308bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) EXPECT_EQ(connect_data_.socket_url, actual.socket_url); 10319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_EQ(connect_data_.requested_subprotocols, 10328bcbed890bc3ce4d7a057a8f32cab53fa534672eTorne (Richard Coles) actual.requested_subprotocols); 1033a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_EQ(connect_data_.origin.string(), actual.origin.string()); 10349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 10359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 10365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Verify that calling SendFlowControl before the connection is established does 10375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// not cause a crash. 10385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelTest, SendFlowControlDuringHandshakeOkay) { 10395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnect(); 10405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(channel_); 10415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFlowControl(65536); 10425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 10435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 10441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Any WebSocketEventInterface methods can delete the WebSocketChannel and 10451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// return CHANNEL_DELETED. The WebSocketChannelDeletingTests are intended to 10461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// verify that there are no use-after-free bugs when this happens. Problems will 10471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// probably only be found when running under Address Sanitizer or a similar 10481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// tool. 10491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnAddChannelResponseFail) { 1050558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnect(); 10511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(channel_); 10525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_data_.creator.connect_delegate->OnFailure("bye"); 1053558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_EQ(NULL, channel_.get()); 1054558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 1055558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 10561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Deletion is possible (due to IPC failure) even if the connect succeeds. 10571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnAddChannelResponseSuccess) { 10581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 10591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 10601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 10611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 10621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnDataFrameSync) { 10631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 10641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 10651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = { 10661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}}; 10671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 10681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 10691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) deleting_ = EVENT_ON_DATA_FRAME; 10701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 10711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 10721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 10731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 10741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 10751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnDataFrameAsync) { 10761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 10771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 10781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = { 10791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}}; 10801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 10811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 10821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) deleting_ = EVENT_ON_DATA_FRAME; 10831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 10841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 10851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_TRUE(channel_); 10861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 10871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 10881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 10891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 10901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnFlowControlAfterConnect) { 10911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) deleting_ = EVENT_ON_FLOW_CONTROL; 10921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 10931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 10941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 10951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 10961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 10971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnFlowControlAfterSend) { 10981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 10991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Avoid deleting the channel yet. 11005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL | EVENT_ON_DROP_CHANNEL; 11011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 11021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(channel_); 11031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) deleting_ = EVENT_ON_FLOW_CONTROL; 11041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->SendFrame(true, 11051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebSocketFrameHeader::kOpCodeText, 11061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::vector<char>(kDefaultInitialQuota, 'B')); 11071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 11081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 11091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 11101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnClosingHandshakeSync) { 11111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 11121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 11131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = { 11141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 11151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}}; 11161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 11171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 11181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) deleting_ = EVENT_ON_CLOSING_HANDSHAKE; 11191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 11201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 11211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 11221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 11231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnClosingHandshakeAsync) { 11241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 11251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 11261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = { 11271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 11281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}}; 11291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 11301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 11311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) deleting_ = EVENT_ON_CLOSING_HANDSHAKE; 11321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 11331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(channel_); 11341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 11351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 11361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 11371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 11381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnDropChannelWriteError) { 11391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(make_scoped_ptr(new UnWriteableFakeWebSocketStream)); 11401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) deleting_ = EVENT_ON_DROP_CHANNEL; 11411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 11421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(channel_); 11431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->SendFrame( 11441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) true, WebSocketFrameHeader::kOpCodeText, AsVector("this will fail")); 11451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 11461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 11471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 11481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnDropChannelReadError) { 11491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 11501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 11511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC, 11521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ERR_FAILED); 11531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 11541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) deleting_ = EVENT_ON_DROP_CHANNEL; 11551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 11561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(channel_); 11571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 11581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 11591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 11601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 11615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnNotifyStartOpeningHandshakeError) { 11625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 11635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new ReadableFakeWebSocketStream); 11645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 11655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}}; 11665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 11675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_stream(stream.Pass()); 11685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_START_OPENING_HANDSHAKE; 11695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 11715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(channel_); 11725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->OnStartOpeningHandshake(scoped_ptr<WebSocketHandshakeRequestInfo>( 11735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new WebSocketHandshakeRequestInfo(GURL("http://www.example.com/"), 11745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time()))); 11755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 11765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 11775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 11785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, OnNotifyFinishOpeningHandshakeError) { 11805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 11815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new ReadableFakeWebSocketStream); 11825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 11835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}}; 11845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 11855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_stream(stream.Pass()); 11865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FINISH_OPENING_HANDSHAKE; 11875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 11885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 11895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ASSERT_TRUE(channel_); 11905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<HttpResponseHeaders> response_headers( 11915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new HttpResponseHeaders("")); 11925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->OnFinishOpeningHandshake(scoped_ptr<WebSocketHandshakeResponseInfo>( 11935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new WebSocketHandshakeResponseInfo(GURL("http://www.example.com/"), 11945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 200, 11955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "OK", 11965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) response_headers, 11975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time()))); 11985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 11995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 12005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 12015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 12021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, FailChannelInSendFrame) { 12031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 12045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL; 12051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 12061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(channel_); 12071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->SendFrame(true, 12081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebSocketFrameHeader::kOpCodeText, 12091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) std::vector<char>(kDefaultInitialQuota * 2, 'T')); 12101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 12111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 12121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 12131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, FailChannelInOnReadDone) { 12141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 12151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 12161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC, 12171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ERR_WS_PROTOCOL_ERROR); 12181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 12195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL; 12201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 12211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(channel_); 12221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 12231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 12241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 12251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 12261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, FailChannelDueToMaskedFrame) { 12271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 12281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 12291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = { 12301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}}; 12311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 12321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 12335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL; 12341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 12351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 12361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 12371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 12381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 12391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, FailChannelDueToBadControlFrame) { 12401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 12411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 12421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = { 1243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {FINAL_FRAME, 0xF, NOT_MASKED, ""}}; 12441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 12451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 12465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL; 12471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 12481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 12491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 12501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 12511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Version of above test with NULL data. 1253f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, FailChannelDueToBadControlFrameNull) { 1254f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 1255f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new ReadableFakeWebSocketStream); 1256f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const InitFrame frames[] = { 1257a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {FINAL_FRAME, 0xF, NOT_MASKED, NULL}}; 1258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 1259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) set_stream(stream.Pass()); 12605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL; 1261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 1263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 1264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 12661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, FailChannelDueToPongAfterClose) { 12671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 12681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 12691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = { 12705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 12715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CLOSE_DATA(NORMAL_CLOSURE, "Success")}, 12725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}}; 12731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 12741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 12755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL; 12761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 12771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 12781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 12791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 12801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1281f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, FailChannelDueToPongAfterCloseNull) { 1282f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 1283f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new ReadableFakeWebSocketStream); 1284f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const InitFrame frames[] = { 12855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 12865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CLOSE_DATA(NORMAL_CLOSURE, "Success")}, 12875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, NULL}}; 1288f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 1289f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) set_stream(stream.Pass()); 12905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL; 1291f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1292f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 1293f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 1294f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1295f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 12961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, FailChannelDueToUnknownOpCode) { 12971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 12981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 12991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = {{FINAL_FRAME, 0x7, NOT_MASKED, ""}}; 13001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 13011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 13025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL; 13031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 13041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 13051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 13061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 13071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 1308f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, FailChannelDueToUnknownOpCodeNull) { 1309f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 1310f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new ReadableFakeWebSocketStream); 1311f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const InitFrame frames[] = {{FINAL_FRAME, 0x7, NOT_MASKED, NULL}}; 1312f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 1313f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) set_stream(stream.Pass()); 13145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL; 13155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 13165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 13175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 13185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 13195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 13205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelDeletingTest, FailChannelDueInvalidCloseReason) { 13215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 13225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new ReadableFakeWebSocketStream); 13235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 13245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 13255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}}; 13265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 13275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_stream(stream.Pass()); 13285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) deleting_ = EVENT_ON_FAIL_CHANNEL; 1329f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1330f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 1331f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_EQ(NULL, channel_.get()); 1332f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1333f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 13349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, ConnectSuccessReported) { 13359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // false means success. 13365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, "", "")); 13379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // OnFlowControl is always called immediately after connect to provide initial 13389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // quota to the renderer. 13399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 13409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 13419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnect(); 13429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1343f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass()); 13449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 13459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 13469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, ConnectFailureReported) { 13475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFailChannel("hello")); 13489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 13499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnect(); 13509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 13515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_data_.creator.connect_delegate->OnFailure("hello"); 13529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 13539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1354f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, NonWebSocketSchemeRejected) { 13555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(true, "", "")); 1356f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) connect_data_.socket_url = GURL("http://www.google.com/"); 1357f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateChannelAndConnect(); 1358f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1359f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 13609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, ProtocolPassed) { 13615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, "Bob", "")); 13629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 13639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 13649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnect(); 13659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1366f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) connect_data_.creator.connect_delegate->OnSuccess( 13679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<WebSocketStream>(new FakeWebSocketStream("Bob", ""))); 13689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 13699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 13705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, ExtensionsPassed) { 13715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, 13725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnAddChannelResponse(false, "", "extension1, extension2")); 13735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 13745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 13755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnect(); 13765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 13775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_data_.creator.connect_delegate->OnSuccess(scoped_ptr<WebSocketStream>( 13785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new FakeWebSocketStream("", "extension1, extension2"))); 13795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 13805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 13819ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// The first frames from the server can arrive together with the handshake, in 13829ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// which case they will be available as soon as ReadFrames() is called the first 13839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// time. 13849ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, DataLeftFromHandshake) { 13859ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 13869ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 13874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 13884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}}; 13894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 13909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 13919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 13929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 13935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 13949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 13959ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL( 13969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *event_interface_, 13979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame( 13989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO"))); 13999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 14009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 14019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 14029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 14039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 14049ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// A remote server could accept the handshake, but then immediately send a 14059ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Close frame. 14069ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, CloseAfterHandshake) { 14079ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 14089ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 14094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 14104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 14114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, CLOSE_DATA(SERVER_ERROR, "Internal Server Error")}}; 14124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 14139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, 14149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERR_CONNECTION_CLOSED); 14159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 14169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 14179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 14185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 14199ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 14209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnClosingHandshake()); 14215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL( 14225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *event_interface_, 14235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel( 14245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, kWebSocketErrorInternalServerError, "Internal Server Error")); 14259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 14269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 14279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 14289ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 14299ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 14309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// A remote server could close the connection immediately after sending the 14319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// handshake response (most likely a bug in the server). 14329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, ConnectionCloseAfterHandshake) { 14339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 14349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 14359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, 14369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERR_CONNECTION_CLOSED); 14379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 14389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 14399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 14405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 14419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 14429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, 14435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(false, kWebSocketErrorAbnormalClosure, _)); 14449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 14459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 14469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 14479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 14489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 14499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, NormalAsyncRead) { 14509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 14519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 14524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 14534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}}; 14549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // We use this checkpoint object to verify that the callback isn't called 14559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // until we expect it to be. 14561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Checkpoint checkpoint; 14574e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 14589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 14599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 14609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 14615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 14629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 14639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(checkpoint, Call(1)); 14649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL( 14659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *event_interface_, 14669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame( 14679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO"))); 14689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(checkpoint, Call(2)); 14699ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 14709ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 14719ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 14729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch checkpoint.Call(1); 14739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 14749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch checkpoint.Call(2); 14759ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 14769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 14779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Extra data can arrive while a read is being processed, resulting in the next 14789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// read completing synchronously. 14799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, AsyncThenSyncRead) { 14809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 14819ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 14824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames1[] = { 14834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "HELLO"}}; 14844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames2[] = { 14854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "WORLD"}}; 14864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1); 14874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames2); 14889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 14899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 14909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 14915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 14929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 14939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL( 14949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *event_interface_, 14959ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame( 14969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch true, WebSocketFrameHeader::kOpCodeText, AsVector("HELLO"))); 14979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL( 14989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *event_interface_, 14999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame( 15009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch true, WebSocketFrameHeader::kOpCodeText, AsVector("WORLD"))); 15019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 15029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 15039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 15049ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 15059ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 15069ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 15074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Data frames are delivered the same regardless of how many reads they arrive 15084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// as. 15094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, FragmentedMessage) { 15109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 15119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 15124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // Here we have one message which arrived in five frames split across three 15134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // reads. It may have been reframed on arrival, but this class doesn't care 15144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // about that. 15154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames1[] = { 15164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "THREE"}, 15174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 15184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, " "}}; 15194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames2[] = { 15204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 15214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, "SMALL"}}; 15224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames3[] = { 15234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 15244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, " "}, 15254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 15264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, "FRAMES"}}; 15274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1); 15284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2); 15294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3); 15309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 15319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 15329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 15335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 15349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 15359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL( 15369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *event_interface_, 15379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame( 15389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch false, WebSocketFrameHeader::kOpCodeText, AsVector("THREE"))); 15399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL( 15409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *event_interface_, 15419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame( 15429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch false, WebSocketFrameHeader::kOpCodeContinuation, AsVector(" "))); 15439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, 15449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame(false, 15459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch WebSocketFrameHeader::kOpCodeContinuation, 15469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch AsVector("SMALL"))); 15479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL( 15489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *event_interface_, 15499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame( 15509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch false, WebSocketFrameHeader::kOpCodeContinuation, AsVector(" "))); 15519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, 15529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame(true, 15539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch WebSocketFrameHeader::kOpCodeContinuation, 15549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch AsVector("FRAMES"))); 15559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 15569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 15579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 15589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 15599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 15609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1561f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// A message can consist of one frame with NULL payload. 1562f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, NullMessage) { 1563f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 1564f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new ReadableFakeWebSocketStream); 1565f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const InitFrame frames[] = { 1566f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, NULL}}; 1567f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 1568f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) set_stream(stream.Pass()); 15695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 1570f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1571f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL( 1572f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *event_interface_, 1573f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) OnDataFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector(""))); 1574f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 1575f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1576f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 15779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Connection closed by the remote host without a closing handshake. 15789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, AsyncAbnormalClosure) { 15799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 15809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 15819ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC, 15829ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERR_CONNECTION_CLOSED); 15839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 15849ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 15859ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 15865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 15879ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 15889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, 15895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(false, kWebSocketErrorAbnormalClosure, _)); 15909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 15919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 15929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 15939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 15949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 15959ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 15969ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// A connection reset should produce the same event as an unexpected closure. 15979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, ConnectionReset) { 15989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 15999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 16009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC, 16019ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch ERR_CONNECTION_RESET); 16029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 16039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 16049ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 16055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 16069ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 16079ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, 16085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(false, kWebSocketErrorAbnormalClosure, _)); 16099ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 16109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 16119ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 16129ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 16139ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 16149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 16159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// RFC6455 5.1 "A client MUST close a connection if it detects a masked frame." 16169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, MaskedFramesAreRejected) { 16179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 16189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 16194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 16204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}}; 16219ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 16224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 16239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 16249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 16259ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 16265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 16279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 16285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL( 16295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *event_interface_, 16305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel( 16315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "A server must not mask any frames that it sends to the client.")); 16329ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 16339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 16349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 16359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 16369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 16379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 16389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// RFC6455 5.2 "If an unknown opcode is received, the receiving endpoint MUST 16399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// _Fail the WebSocket Connection_." 16409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, UnknownOpCodeIsRejected) { 16419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 16429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 16434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = {{FINAL_FRAME, 4, NOT_MASKED, "HELLO"}}; 16449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 16454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 16469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 16479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 16489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 16495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 16509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 16519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, 16525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel("Unrecognized frame opcode: 4")); 16539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 16549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 16559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 16569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 16579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 16589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 16599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// RFC6455 5.4 "Control frames ... MAY be injected in the middle of a 16609ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// fragmented message." 16619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, ControlFrameInDataMessage) { 16629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 16639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch new ReadableFakeWebSocketStream); 16649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // We have one message of type Text split into two frames. In the middle is a 16659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // control message of type Pong. 16664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames1[] = { 16674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, 16684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, "SPLIT "}}; 16694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames2[] = { 16704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, ""}}; 16714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames3[] = { 16724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 16734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, "MESSAGE"}}; 16744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames1); 16754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames2); 16764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames3); 16779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(stream.Pass()); 16789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 16799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 16805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 16819ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 16829ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL( 16839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch *event_interface_, 16849ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame( 16859ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch false, WebSocketFrameHeader::kOpCodeText, AsVector("SPLIT "))); 16869ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, 16879ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch OnDataFrame(true, 16889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch WebSocketFrameHeader::kOpCodeContinuation, 16899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch AsVector("MESSAGE"))); 16909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 16919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 16929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 16939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 16949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 16959ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 1696f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// It seems redundant to repeat the entirety of the above test, so just test a 1697f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// Pong with NULL data. 1698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, PongWithNullData) { 1699f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 1700f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new ReadableFakeWebSocketStream); 1701f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const InitFrame frames[] = { 1702f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, NOT_MASKED, NULL}}; 1703f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 1704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) set_stream(stream.Pass()); 17055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 1706f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1707f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1708f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 1709f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 1710f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 17124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// If a frame has an invalid header, then the connection is closed and 17134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// subsequent frames must not trigger events. 17144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, FrameAfterInvalidFrame) { 1715558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 1716558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch new ReadableFakeWebSocketStream); 17174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 17184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "HELLO"}, 17194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, " WORLD"}}; 1720558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 17214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 1722558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch set_stream(stream.Pass()); 1723558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch { 1724558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch InSequence s; 17255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 1726558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 17275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL( 17285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *event_interface_, 17295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel( 17305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "A server must not mask any frames that it sends to the client.")); 1731558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 1732558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 1733558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 1734558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 1735558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 1736558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 17379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// If the renderer sends lots of small writes, we don't want to update the quota 17389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// for each one. 17399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, SmallWriteDoesntUpdateQuota) { 17409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 17419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 17429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 17435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 17449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 17459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 17469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 17479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 17489ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("B")); 17499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 17509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 17519ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// If we send enough to go below send_quota_low_water_mask_ we should get our 17529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// quota refreshed. 17539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, LargeWriteUpdatesQuota) { 17549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 17559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // We use this checkpoint object to verify that the quota update comes after 17569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // the write. 17571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Checkpoint checkpoint; 17589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 17599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 17605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 17619ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 17629ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(checkpoint, Call(1)); 17639ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 17649ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(checkpoint, Call(2)); 17659ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 17669ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 17679ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 17689ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch checkpoint.Call(1); 1769558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->SendFrame(true, 1770558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebSocketFrameHeader::kOpCodeText, 1771558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch std::vector<char>(kDefaultInitialQuota, 'B')); 17729ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch checkpoint.Call(2); 17739ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 17749ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 17759ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// Verify that our quota actually is refreshed when we are told it is. 17769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, QuotaReallyIsRefreshed) { 17779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 17781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Checkpoint checkpoint; 17799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 17809ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 17815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 17829ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 17839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(checkpoint, Call(1)); 17849ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 17859ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(checkpoint, Call(2)); 17869ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // If quota was not really refreshed, we would get an OnDropChannel() 17879ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // message. 17889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 17899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(checkpoint, Call(3)); 17909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 17919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 17929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 17939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch checkpoint.Call(1); 17949ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch channel_->SendFrame(true, 17959ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch WebSocketFrameHeader::kOpCodeText, 1796558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch std::vector<char>(kDefaultQuotaRefreshTrigger, 'D')); 17979ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch checkpoint.Call(2); 17989ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch // We should have received more quota at this point. 17999ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch channel_->SendFrame(true, 18009ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch WebSocketFrameHeader::kOpCodeText, 1801558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch std::vector<char>(kDefaultQuotaRefreshTrigger, 'E')); 18029ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch checkpoint.Call(3); 18039ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 18049ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 18059ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// If we send more than the available quota then the connection will be closed 18069ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// with an error. 18079ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, WriteOverQuotaIsRejected) { 18089ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(make_scoped_ptr(new WriteableFakeWebSocketStream)); 18099ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 18109ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 18115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 1812558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota)); 18135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFailChannel("Send quota exceeded")); 18149ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 18159ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 18169ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 18179ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch channel_->SendFrame(true, 18189ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch WebSocketFrameHeader::kOpCodeText, 1819558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch std::vector<char>(kDefaultInitialQuota + 1, 'C')); 18209ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 18219ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 18229ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// If a write fails, the channel is dropped. 18239ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, FailedWrite) { 18249ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(make_scoped_ptr(new UnWriteableFakeWebSocketStream)); 18251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Checkpoint checkpoint; 18269ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 18279ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 18285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 18299ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 18309ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(checkpoint, Call(1)); 18319ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, 18325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(false, kWebSocketErrorAbnormalClosure, _)); 18339ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(checkpoint, Call(2)); 18349ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 18359ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 18369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 18379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch checkpoint.Call(1); 18389ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 18399ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("H")); 18409ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch checkpoint.Call(2); 18419ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 18429ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 18439ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// OnDropChannel() is called exactly once when StartClosingHandshake() is used. 18449ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, SendCloseDropsChannel) { 18459ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch set_stream(make_scoped_ptr(new EchoeyFakeWebSocketStream)); 18469ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch { 18479ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch InSequence s; 18485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 18499ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 18509ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*event_interface_, 18515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(true, kWebSocketNormalClosure, "Fred")); 18529ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch } 18539ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 18549ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 18559ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 18569ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch channel_->StartClosingHandshake(kWebSocketNormalClosure, "Fred"); 18579ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 18589ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 18599ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 18605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// StartClosingHandshake() also works before connection completes, and calls 18615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// OnDropChannel. 18625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, CloseDuringConnection) { 18635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, 18645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(false, kWebSocketErrorAbnormalClosure, "")); 18655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 18665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnect(); 18675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->StartClosingHandshake(kWebSocketNormalClosure, "Joe"); 18685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 18695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 1870558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// OnDropChannel() is only called once when a write() on the socket triggers a 1871558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// connection reset. 1872558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, OnDropChannelCalledOnce) { 1873558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch set_stream(make_scoped_ptr(new ResetOnWriteFakeWebSocketStream)); 18745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 1875558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1876558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 1877558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*event_interface_, 18785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(false, kWebSocketErrorAbnormalClosure, "")) 1879558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .Times(1); 1880558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 1881558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 1882558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 1883558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("yt?")); 1884558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch base::MessageLoop::current()->RunUntilIdle(); 1885558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 1886558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 1887558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// When the remote server sends a Close frame with an empty payload, 1888558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// WebSocketChannel should report code 1005, kWebSocketErrorNoStatusReceived. 1889558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, CloseWithNoPayloadGivesStatus1005) { 1890558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 1891558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch new ReadableFakeWebSocketStream); 18924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 18934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}}; 18944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 1895558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, 1896558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch ERR_CONNECTION_CLOSED); 1897558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch set_stream(stream.Pass()); 18985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 1899558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1900558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*event_interface_, OnClosingHandshake()); 1901558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*event_interface_, 19025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(true, kWebSocketErrorNoStatusReceived, _)); 1903558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 1904558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 1905558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 1906558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 1907f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// A version of the above test with NULL payload. 1908f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, 1909f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CloseWithNullPayloadGivesStatus1005) { 1910f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 1911f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) new ReadableFakeWebSocketStream); 1912f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const InitFrame frames[] = { 1913f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, NULL}}; 1914f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 1915f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, 1916f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) ERR_CONNECTION_CLOSED); 1917f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) set_stream(stream.Pass()); 19185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 1919f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 1920f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*event_interface_, OnClosingHandshake()); 1921f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*event_interface_, 19225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(true, kWebSocketErrorNoStatusReceived, _)); 1923f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 1924f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 1925f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 1926f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 19275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// If ReadFrames() returns ERR_WS_PROTOCOL_ERROR, then the connection must be 19285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// failed. 19294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, SyncProtocolErrorGivesStatus1002) { 19304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 19314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new ReadableFakeWebSocketStream); 19324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, 19334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ERR_WS_PROTOCOL_ERROR); 19344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) set_stream(stream.Pass()); 19355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 19364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 19374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 19385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header")); 19394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 19404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 19414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 19424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 19434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Async version of above test. 19444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, AsyncProtocolErrorGivesStatus1002) { 19454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 19464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new ReadableFakeWebSocketStream); 19474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) stream->PrepareReadFramesError(ReadableFakeWebSocketStream::ASYNC, 19484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ERR_WS_PROTOCOL_ERROR); 19494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) set_stream(stream.Pass()); 19505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 19514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 19524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 19535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFailChannel("Invalid frame header")); 19545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 19565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 19575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 19585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, StartHandshakeRequest) { 19605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 19615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InSequence s; 19625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 19635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 19645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled()); 19655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 19685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo> request_info( 19705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new WebSocketHandshakeRequestInfo(GURL("ws://www.example.com/"), 19715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time())); 19725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_data_.creator.connect_delegate->OnStartOpeningHandshake( 19735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) request_info.Pass()); 19745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 19765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 19775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, FinishHandshakeRequest) { 19795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 19805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InSequence s; 19815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 19825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 19835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFinishOpeningHandshakeCalled()); 19845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 19854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 19864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 19875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 19885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<HttpResponseHeaders> response_headers( 19895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new HttpResponseHeaders("")); 19905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo> response_info( 19915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new WebSocketHandshakeResponseInfo(GURL("ws://www.example.com/"), 19925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 200, 19935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "OK", 19945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) response_headers, 19955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time())); 19965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_data_.creator.connect_delegate->OnFinishOpeningHandshake( 19975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) response_info.Pass()); 19985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 19995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 20005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, FailJustAfterHandshake) { 20025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 20035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InSequence s; 20045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnStartOpeningHandshakeCalled()); 20055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFinishOpeningHandshakeCalled()); 20065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFailChannel("bye")); 20075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 20085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnect(); 20105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketStream::ConnectDelegate* connect_delegate = 20125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_data_.creator.connect_delegate.get(); 20135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) GURL url("ws://www.example.com/"); 20145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeRequestInfo> request_info( 20155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new WebSocketHandshakeRequestInfo(url, base::Time())); 20165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_refptr<HttpResponseHeaders> response_headers( 20175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new HttpResponseHeaders("")); 20185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<WebSocketHandshakeResponseInfo> response_info( 20195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new WebSocketHandshakeResponseInfo(url, 20205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 200, 20215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "OK", 20225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) response_headers, 20235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::Time())); 20245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_delegate->OnStartOpeningHandshake(request_info.Pass()); 20255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_delegate->OnFinishOpeningHandshake(response_info.Pass()); 20265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) connect_delegate->OnFailure("bye"); 20284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 20294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 20304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 20315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Any frame after close is invalid. This test uses a Text frame. See also 20325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// test "PingAfterCloseIfRejected". 20335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, DataAfterCloseIsRejected) { 20345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 20355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new ReadableFakeWebSocketStream); 20365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 20375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, 20385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CLOSE_DATA(NORMAL_CLOSURE, "OK")}, 20395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "Payload"}}; 20405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 20415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_stream(stream.Pass()); 20425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 20435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 20445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 20465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InSequence s; 20475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnClosingHandshake()); 20485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, 20495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel("Data frame received after close")); 20505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 20515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 20535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 20545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A Close frame with a one-byte payload elicits a specific console error 20565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// message. 20575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, OneByteClosePayloadMessage) { 20585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 20595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new ReadableFakeWebSocketStream); 20605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 20615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, "\x03"}}; 20625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 20635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_stream(stream.Pass()); 20645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 20655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 20665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL( 20675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *event_interface_, 20685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel( 20695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Received a broken close frame containing an invalid size body.")); 20705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 20725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 20735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A Close frame with a reserved status code also elicits a specific console 20755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// error message. 20765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadReservedStatusMessage) { 20775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 20785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new ReadableFakeWebSocketStream); 20795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 20805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 20815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOT_MASKED, CLOSE_DATA(ABNORMAL_CLOSURE, "Not valid on wire")}}; 20825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 20835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_stream(stream.Pass()); 20845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 20855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 20865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL( 20875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *event_interface_, 20885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel( 20895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Received a broken close frame containing a reserved status code.")); 20905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 20925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 20935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 20945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A Close frame with invalid UTF-8 also elicits a specific console error 20955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// message. 20965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, ClosePayloadInvalidReason) { 20975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 20985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new ReadableFakeWebSocketStream); 20995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 21005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 21015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}}; 21025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 21035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_stream(stream.Pass()); 21045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 21055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 21065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL( 21075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *event_interface_, 21085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel( 21095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) "Received a broken close frame containing invalid UTF-8.")); 21105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 21115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 21125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 21135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2114a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// The reserved bits must all be clear on received frames. Extensions should 2115a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// clear the bits when they are set correctly before passing on the frame. 2116a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, ReservedBitsMustNotBeSet) { 2117a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 2118a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new ReadableFakeWebSocketStream); 2119a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static const InitFrame frames[] = { 2120a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, 2121a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOT_MASKED, "sakana"}}; 2122a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // It is not worth adding support for reserved bits to InitFrame just for this 2123a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) // one test, so set the bit manually. 2124a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ScopedVector<WebSocketFrame> raw_frames = CreateFrameVector(frames); 2125a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) raw_frames[0]->header.reserved1 = true; 2126a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stream->PrepareRawReadFrames( 2127a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) ReadableFakeWebSocketStream::SYNC, OK, raw_frames.Pass()); 2128a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_stream(stream.Pass()); 2129a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 2130a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 2131a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*event_interface_, 2132a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnFailChannel( 2133a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "One or more reserved bits are on: reserved1 = 1, " 2134a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "reserved2 = 0, reserved3 = 0")); 2135a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 2136a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 2137a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 2138a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 21391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// The closing handshake times out and sends an OnDropChannel event if no 21401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// response to the client Close message is received. 21411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, 21421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ClientInitiatedClosingHandshakeTimesOut) { 21431e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 21441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 21451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFramesError(ReadableFakeWebSocketStream::SYNC, 21461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ERR_IO_PENDING); 21471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 21485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 21491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 21501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // This checkpoint object verifies that the OnDropChannel message comes after 21511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // the timeout. 21521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Checkpoint checkpoint; 21531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TestClosure completion; 21541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) { 21551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) InSequence s; 21561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(checkpoint, Call(1)); 21571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*event_interface_, 21585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(false, kWebSocketErrorAbnormalClosure, _)) 21591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(InvokeClosureReturnDeleted(completion.closure())); 21601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 21611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 21621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // OneShotTimer is not very friendly to testing; there is no apparent way to 21631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // set an expectation on it. Instead the tests need to infer that the timeout 21641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // was fired by the behaviour of the WebSocketChannel object. 21651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->SetClosingHandshakeTimeoutForTesting( 21661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis)); 21671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->StartClosingHandshake(kWebSocketNormalClosure, ""); 21681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) checkpoint.Call(1); 21691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) completion.WaitForResult(); 21701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 21711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 21721e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// The closing handshake times out and sends an OnDropChannel event if a Close 21731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// message is received but the connection isn't closed by the remote host. 21741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, 21751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ServerInitiatedClosingHandshakeTimesOut) { 21761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 21771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) new ReadableFakeWebSocketStream); 21781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = { 21791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 21801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}}; 21811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 21821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(stream.Pass()); 21835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 21841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(_)); 21851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Checkpoint checkpoint; 21861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TestClosure completion; 21871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) { 21881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) InSequence s; 21891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(checkpoint, Call(1)); 21901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnClosingHandshake()); 21911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*event_interface_, 21925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnDropChannel(false, kWebSocketErrorAbnormalClosure, _)) 21931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(InvokeClosureReturnDeleted(completion.closure())); 21941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 21951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 21961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->SetClosingHandshakeTimeoutForTesting( 21971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis)); 21981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) checkpoint.Call(1); 21991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) completion.WaitForResult(); 22001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 22011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2202effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// The renderer should provide us with some quota immediately, and then 2203effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// WebSocketChannel calls ReadFrames as soon as the stream is available. 2204effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST_F(WebSocketChannelStreamTest, FlowControlEarly) { 2205effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Checkpoint checkpoint; 2206effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 2207effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2208effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { 2209effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InSequence s; 2210effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(checkpoint, Call(1)); 2211effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 2212effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch .WillOnce(Return(ERR_IO_PENDING)); 2213effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(checkpoint, Call(2)); 2214effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2215effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2216effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch set_stream(mock_stream_.Pass()); 2217effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateChannelAndConnect(); 2218effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(kPlentyOfQuota); 2219effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch checkpoint.Call(1); 2220effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass()); 2221effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch checkpoint.Call(2); 2222effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 2223effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2224effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// If for some reason the connect succeeds before the renderer sends us quota, 2225effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// we shouldn't call ReadFrames() immediately. 2226effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// TODO(ricea): Actually we should call ReadFrames() with a small limit so we 2227effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// can still handle control frames. This should be done once we have any API to 2228effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// expose quota to the lower levels. 2229effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST_F(WebSocketChannelStreamTest, FlowControlLate) { 2230effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Checkpoint checkpoint; 2231effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 2232effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2233effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { 2234effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InSequence s; 2235effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(checkpoint, Call(1)); 2236effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 2237effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch .WillOnce(Return(ERR_IO_PENDING)); 2238effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(checkpoint, Call(2)); 2239effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2240effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2241effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch set_stream(mock_stream_.Pass()); 2242effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateChannelAndConnect(); 2243effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass()); 2244effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch checkpoint.Call(1); 2245effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(kPlentyOfQuota); 2246effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch checkpoint.Call(2); 2247effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 2248effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2249effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// We should stop calling ReadFrames() when all quota is used. 2250effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST_F(WebSocketChannelStreamTest, FlowControlStopsReadFrames) { 2251effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static const InitFrame frames[] = { 2252effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}}; 2253effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2254effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 2255effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2256effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 2257effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch .WillOnce(ReturnFrames(&frames)); 2258effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2259effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch set_stream(mock_stream_.Pass()); 2260effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateChannelAndConnect(); 2261effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(4); 2262effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass()); 2263effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 2264effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2265effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// Providing extra quota causes ReadFrames() to be called again. 2266effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST_F(WebSocketChannelStreamTest, FlowControlStartsWithMoreQuota) { 2267effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static const InitFrame frames[] = { 2268effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}}; 2269effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Checkpoint checkpoint; 2270effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2271effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 2272effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2273effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { 2274effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InSequence s; 2275effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 2276effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch .WillOnce(ReturnFrames(&frames)); 2277effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(checkpoint, Call(1)); 2278effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 2279effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch .WillOnce(Return(ERR_IO_PENDING)); 2280effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2281effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2282effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch set_stream(mock_stream_.Pass()); 2283effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateChannelAndConnect(); 2284effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(4); 2285effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass()); 2286effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch checkpoint.Call(1); 2287effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(4); 2288effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 2289effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2290effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// ReadFrames() isn't called again until all pending data has been passed to 2291effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// the renderer. 2292effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST_F(WebSocketChannelStreamTest, ReadFramesNotCalledUntilQuotaAvailable) { 2293effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static const InitFrame frames[] = { 2294effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}}; 2295effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Checkpoint checkpoint; 2296effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2297effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 2298effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2299effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { 2300effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InSequence s; 2301effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 2302effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch .WillOnce(ReturnFrames(&frames)); 2303effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(checkpoint, Call(1)); 2304effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(checkpoint, Call(2)); 2305effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 2306effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch .WillOnce(Return(ERR_IO_PENDING)); 2307effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2308effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2309effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch set_stream(mock_stream_.Pass()); 2310effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateChannelAndConnect(); 2311effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(2); 2312effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass()); 2313effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch checkpoint.Call(1); 2314effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(2); 2315effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch checkpoint.Call(2); 2316effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(2); 2317effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 2318effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2319effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// A message that needs to be split into frames to fit within quota should 2320effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// maintain correct semantics. 2321effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitSync) { 2322effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 2323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new ReadableFakeWebSocketStream); 2324effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static const InitFrame frames[] = { 2325effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}}; 2326effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 2327effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch set_stream(stream.Pass()); 2328effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { 2329effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InSequence s; 2330effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 2331effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 2332effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL( 2333effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *event_interface_, 2334effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("FO"))); 2335effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL( 2336effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *event_interface_, 2337effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame( 2338effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("U"))); 2339effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL( 2340effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *event_interface_, 2341effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame( 2342effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("R"))); 2343effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2344effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2345effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateChannelAndConnectWithQuota(2); 2346effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(1); 2347effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(1); 2348effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 2349effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2350effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// The code path for async messages is slightly different, so test it 2351effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// separately. 2352effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST_F(WebSocketChannelFlowControlTest, SingleFrameMessageSplitAsync) { 2353effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 2354effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new ReadableFakeWebSocketStream); 2355effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static const InitFrame frames[] = { 2356effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "FOUR"}}; 2357effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch stream->PrepareReadFrames(ReadableFakeWebSocketStream::ASYNC, OK, frames); 2358effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch set_stream(stream.Pass()); 2359effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch Checkpoint checkpoint; 2360effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { 2361effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InSequence s; 2362effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 2363effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 2364effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(checkpoint, Call(1)); 2365effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL( 2366effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *event_interface_, 2367effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(false, WebSocketFrameHeader::kOpCodeText, AsVector("FO"))); 2368effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(checkpoint, Call(2)); 2369effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL( 2370effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *event_interface_, 2371effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame( 2372effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("U"))); 2373effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(checkpoint, Call(3)); 2374effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL( 2375effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch *event_interface_, 2376effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame( 2377effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("R"))); 2378effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2379effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2380effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateChannelAndConnectWithQuota(2); 2381effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch checkpoint.Call(1); 2382effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch base::MessageLoop::current()->RunUntilIdle(); 2383effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch checkpoint.Call(2); 2384effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(1); 2385effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch checkpoint.Call(3); 2386effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(1); 2387effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 2388effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2389effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// A message split into multiple frames which is further split due to quota 2390effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// restrictions should stil be correct. 2391effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// TODO(ricea): The message ends up split into more frames than are strictly 2392effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// necessary. The complexity/performance tradeoffs here need further 2393effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// examination. 2394effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST_F(WebSocketChannelFlowControlTest, MultipleFrameSplit) { 2395effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 2396effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new ReadableFakeWebSocketStream); 2397effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static const InitFrame frames[] = { 2398effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, 2399effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NOT_MASKED, "FIRST FRAME IS 25 BYTES. "}, 2400effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 2401effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NOT_MASKED, "SECOND FRAME IS 26 BYTES. "}, 2402effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 2403effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NOT_MASKED, "FINAL FRAME IS 24 BYTES."}}; 2404effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 2405effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch set_stream(stream.Pass()); 2406effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { 2407effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InSequence s; 2408effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 2409effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 2410effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, 2411effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(false, 2412effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebSocketFrameHeader::kOpCodeText, 2413effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AsVector("FIRST FRAME IS"))); 2414effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, 2415effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(false, 2416effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebSocketFrameHeader::kOpCodeContinuation, 2417effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AsVector(" 25 BYTES. "))); 2418effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, 2419effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(false, 2420effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebSocketFrameHeader::kOpCodeContinuation, 2421effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AsVector("SECOND FRAME IS 26 BYTES. "))); 2422effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, 2423effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(false, 2424effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebSocketFrameHeader::kOpCodeContinuation, 2425effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AsVector("FINAL "))); 2426effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, 2427effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(true, 2428effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebSocketFrameHeader::kOpCodeContinuation, 2429effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AsVector("FRAME IS 24 BYTES."))); 2430effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2431effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateChannelAndConnectWithQuota(14); 2432effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(43); 2433effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(32); 2434effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 2435effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2436effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// An empty message handled when we are out of quota must not be delivered 2437effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// out-of-order with respect to other messages. 2438effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST_F(WebSocketChannelFlowControlTest, EmptyMessageNoQuota) { 2439effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 2440effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch new ReadableFakeWebSocketStream); 2441effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch static const InitFrame frames[] = { 2442effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, 2443effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NOT_MASKED, "FIRST MESSAGE"}, 2444effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, 24455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu NOT_MASKED, NULL}, 2446effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, 2447effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch NOT_MASKED, "THIRD MESSAGE"}}; 2448effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 2449effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch set_stream(stream.Pass()); 2450effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch { 2451effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch InSequence s; 2452effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 2453effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 2454effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, 2455effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(false, 2456effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebSocketFrameHeader::kOpCodeText, 2457effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AsVector("FIRST "))); 2458effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, 2459effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(true, 2460effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebSocketFrameHeader::kOpCodeContinuation, 2461effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AsVector("MESSAGE"))); 2462effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, 2463effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(true, 2464effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebSocketFrameHeader::kOpCodeText, 2465effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AsVector(""))); 2466effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch EXPECT_CALL(*event_interface_, 2467effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch OnDataFrame(true, 2468effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch WebSocketFrameHeader::kOpCodeText, 2469effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch AsVector("THIRD MESSAGE"))); 2470effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch } 2471effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 2472effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch CreateChannelAndConnectWithQuota(6); 2473effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(128); 2474effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch} 2475effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch 24769ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// RFC6455 5.1 "a client MUST mask all frames that it sends to the server". 24779ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// WebSocketChannel actually only sets the mask bit in the header, it doesn't 24789ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch// perform masking itself (not all transports actually use masking). 24799ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben MurdochTEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) { 24804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected[] = { 24814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, 24824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MASKED, "NEEDS MASKING"}}; 24839ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 24845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 24859ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 24864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 2487558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 24889ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 24899ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch CreateChannelAndConnectSuccessfully(); 24909ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch channel_->SendFrame( 24919ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch true, WebSocketFrameHeader::kOpCodeText, AsVector("NEEDS MASKING")); 24929ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} 24939ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch 2494558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// RFC6455 5.5.1 "The application MUST NOT send any more data frames after 2495558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// sending a Close frame." 2496558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) { 24974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected[] = { 24984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 24994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}}; 2500558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 25015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2502558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 25034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 2504558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 2505558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2506558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2507558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->StartClosingHandshake(1000, "Success"); 2508558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->SendFrame( 2509558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch true, WebSocketFrameHeader::kOpCodeText, AsVector("SHOULD BE IGNORED")); 2510558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2511558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2512558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// RFC6455 5.5.1 "If an endpoint receives a Close frame and did not previously 2513558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// send a Close frame, the endpoint MUST send a Close frame in response." 2514558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) { 25154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 25164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 25174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}}; 25184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected[] = { 25194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 25204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}}; 2521558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 25225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2523558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 25244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 2525558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillRepeatedly(Return(ERR_IO_PENDING)); 25264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 2527558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 2528558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2529558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2530558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2531558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2532558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// The converse of the above case; after sending a Close frame, we should not 2533558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// send another one. 2534558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) { 25354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected[] = { 25364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 25374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}}; 25384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames_init[] = { 25394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 25404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}}; 2541558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2542558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // We store the parameters that were passed to ReadFrames() so that we can 2543558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // call them explicitly later. 2544558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CompletionCallback read_callback; 25454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ScopedVector<WebSocketFrame>* frames = NULL; 2546558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 25475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // These are not interesting. 25485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 25495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 25505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 2551558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Use a checkpoint to make the ordering of events clearer. 25521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Checkpoint checkpoint; 2553558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch { 2554558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch InSequence s; 2555558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 25564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .WillOnce(DoAll(SaveArg<0>(&frames), 2557558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch SaveArg<1>(&read_callback), 2558558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch Return(ERR_IO_PENDING))); 2559558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(checkpoint, Call(1)); 25604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 2561558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 2562558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(checkpoint, Call(2)); 2563558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 2564558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(ERR_IO_PENDING)); 2565558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(checkpoint, Call(3)); 2566558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // WriteFrames() must not be called again. GoogleMock will ensure that the 2567558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // test fails if it is. 2568558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 2569558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2570558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2571558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch checkpoint.Call(1); 2572558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->StartClosingHandshake(kWebSocketNormalClosure, "Close"); 2573558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch checkpoint.Call(2); 2574558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 25754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *frames = CreateFrameVector(frames_init); 2576558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch read_callback.Run(OK); 2577558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch checkpoint.Call(3); 2578558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2579558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 25801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Invalid close status codes should not be sent on the network. 25811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelStreamTest, InvalidCloseStatusCodeNotSent) { 25821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame expected[] = { 25831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 25845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MASKED, CLOSE_DATA(SERVER_ERROR, "")}}; 25851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 25861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 25875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 25881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 25891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(Return(ERR_IO_PENDING)); 25901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 25911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)); 25921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 25931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 25941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->StartClosingHandshake(999, ""); 25951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 25961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 25971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// A Close frame with a reason longer than 123 bytes cannot be sent on the 25981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// network. 25991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelStreamTest, LongCloseReasonNotSent) { 26001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame expected[] = { 26011e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 26025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MASKED, CLOSE_DATA(SERVER_ERROR, "")}}; 26031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 26041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 26055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 26061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 26071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(Return(ERR_IO_PENDING)); 26081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 26091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)); 26101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 26111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 26121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->StartClosingHandshake(1000, std::string(124, 'A')); 26131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 26141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 2615558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// We generate code 1005, kWebSocketErrorNoStatusReceived, when there is no 2616558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// status in the Close message from the other side. Code 1005 is not allowed to 2617558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// appear on the wire, so we should not echo it back. See test 2618558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// CloseWithNoPayloadGivesStatus1005, above, for confirmation that code 1005 is 2619558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// correctly generated internally. 2620558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) { 26214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 26224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}}; 26234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected[] = { 26244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}}; 2625558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 26265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2627558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 26284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 2629558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillRepeatedly(Return(ERR_IO_PENDING)); 26304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 2631558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 2632558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2633558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2634558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2635558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2636f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoedNull) { 2637f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const InitFrame frames[] = { 2638f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, NULL}}; 2639f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const InitFrame expected[] = { 2640f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}}; 2641f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 26425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 26435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 26445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 26455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 26465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 26475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(Return(OK)); 26485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 26495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 26505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 26515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 26525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Receiving an invalid UTF-8 payload in a Close frame causes us to fail the 26535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// connection. 26545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelStreamTest, CloseFrameInvalidUtf8) { 26555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 26565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 26575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "\xFF")}}; 26585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame expected[] = { 26595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 26605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MASKED, CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in Close frame")}}; 26615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 26625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 26635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2664f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 2665f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 2666f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 2667f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 2668f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) .WillOnce(Return(OK)); 26695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()); 2670f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2671f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 2672f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 2673f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2674558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// RFC6455 5.5.2 "Upon receipt of a Ping frame, an endpoint MUST send a Pong 2675558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// frame in response" 2676558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// 5.5.3 "A Pong frame sent in response to a Ping frame must have identical 2677558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// "Application data" as found in the message body of the Ping frame being 2678558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// replied to." 2679558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelStreamTest, PingRepliedWithPong) { 26804e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 26814e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, 26824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, "Application data"}}; 26834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected[] = { 26844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, 26854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MASKED, "Application data"}}; 2686558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 26875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2688558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 26894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 2690558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillRepeatedly(Return(ERR_IO_PENDING)); 26914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 2692558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 2693558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2694558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2695558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2696558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 26975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A ping with a NULL payload should be responded to with a Pong with a NULL 2698f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)// payload. 26995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelStreamTest, NullPingRepliedWithNullPong) { 2700f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const InitFrame frames[] = { 2701f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, NULL}}; 2702f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) static const InitFrame expected[] = { 27035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, NULL}}; 2704f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 27055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2706f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 2707f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 2708f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 2709f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 2710f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) .WillOnce(Return(OK)); 2711f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2712f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 2713f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)} 2714f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2715558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) { 27164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 27174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, 27184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, "Application data"}}; 27194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected1[] = { 27204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}}; 27214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected2[] = { 27224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, 27234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MASKED, "Application data"}}; 27244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected3[] = { 27254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 27264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MASKED, "World"}}; 27274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ScopedVector<WebSocketFrame>* read_frames; 2728558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CompletionCallback read_callback; 2729558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 27305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2731558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 27324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .WillOnce(DoAll(SaveArg<0>(&read_frames), 2733558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch SaveArg<1>(&read_callback), 2734558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch Return(ERR_IO_PENDING))) 2735558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillRepeatedly(Return(ERR_IO_PENDING)); 2736558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch { 2737558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch InSequence s; 2738558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 27394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _)) 2740558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 27414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _)) 2742558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 27434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected3), _)) 2744558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 2745558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 2746558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2747558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2748558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->SendFrame( 2749558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello ")); 27504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) *read_frames = CreateFrameVector(frames); 2751558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch read_callback.Run(OK); 2752558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->SendFrame( 2753558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("World")); 2754558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2755558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2756558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// WriteFrames() may not be called until the previous write has completed. 2757558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// WebSocketChannel must buffer writes that happen in the meantime. 2758558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) { 27594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected1[] = { 27604e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "Hello "}}; 27614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected2[] = { 27624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "World"}}; 2763558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CompletionCallback write_callback; 27641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Checkpoint checkpoint; 2765558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2766558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 27675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2768558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 2769558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch { 2770558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch InSequence s; 2771558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(checkpoint, Call(1)); 27724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _)) 2773558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING))); 2774558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(checkpoint, Call(2)); 27754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _)) 2776558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(ERR_IO_PENDING)); 2777558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(checkpoint, Call(3)); 2778558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 2779558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2780558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2781558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch checkpoint.Call(1); 2782558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->SendFrame( 2783558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch false, WebSocketFrameHeader::kOpCodeText, AsVector("Hello ")); 2784558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->SendFrame( 2785558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch true, WebSocketFrameHeader::kOpCodeText, AsVector("World")); 2786558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch checkpoint.Call(2); 2787558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch write_callback.Run(OK); 2788558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch checkpoint.Call(3); 2789558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2790558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2791558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// WebSocketChannel must buffer frames while it is waiting for a write to 2792558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// complete, and then send them in a single batch. The batching behaviour is 2793558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// important to get good throughput in the "many small messages" case. 2794558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) { 2795558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch static const char input_letters[] = "Hello"; 27964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected1[] = { 27974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "H"}}; 27984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected2[] = { 27994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "e"}, 28004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"}, 28014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "l"}, 28024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "o"}}; 2803558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CompletionCallback write_callback; 2804558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2805558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 28065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2807558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 2808558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch { 2809558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch InSequence s; 28104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _)) 2811558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING))); 28124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _)) 2813558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(ERR_IO_PENDING)); 2814558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 2815558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2816558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2817558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch for (size_t i = 0; i < strlen(input_letters); ++i) { 2818558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->SendFrame(true, 2819558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebSocketFrameHeader::kOpCodeText, 2820558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch std::vector<char>(1, input_letters[i])); 2821558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 2822558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch write_callback.Run(OK); 2823558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2824558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2825effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// When the renderer sends more on a channel than it has quota for, we send the 2826effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch// remote server a kWebSocketErrorGoingAway error code. 2827effb81e5f8246d0db0270817048dc992db66e9fbBen MurdochTEST_F(WebSocketChannelStreamTest, SendGoingAwayOnRendererQuotaExceeded) { 28284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected[] = { 28294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 28305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MASKED, CLOSE_DATA(GOING_AWAY, "")}}; 2831558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 28325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2833558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 28344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 2835558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 2836558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, Close()); 2837558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2838558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2839558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->SendFrame(true, 2840558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebSocketFrameHeader::kOpCodeText, 2841558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch std::vector<char>(kDefaultInitialQuota + 1, 'C')); 2842558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2843558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2844558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// For convenience, most of these tests use Text frames. However, the WebSocket 2845558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// protocol also has Binary frames and those need to be 8-bit clean. For the 2846558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// sake of completeness, this test verifies that they are. 2847558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelStreamTest, WrittenBinaryFramesAre8BitClean) { 28484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ScopedVector<WebSocketFrame>* frames = NULL; 2849558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2850558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 28515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 2852558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING)); 2853558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, WriteFrames(_, _)) 28544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .WillOnce(DoAll(SaveArg<0>(&frames), Return(ERR_IO_PENDING))); 2855558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2856558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2857558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch channel_->SendFrame( 2858558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch true, 2859558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebSocketFrameHeader::kOpCodeBinary, 2860558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch std::vector<char>(kBinaryBlob, kBinaryBlob + kBinaryBlobSize)); 28614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ASSERT_TRUE(frames != NULL); 28624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ASSERT_EQ(1U, frames->size()); 28634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const WebSocketFrame* out_frame = (*frames)[0]; 28644e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(kBinaryBlobSize, out_frame->header.payload_length); 28651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ASSERT_TRUE(out_frame->data.get()); 28664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_EQ(0, memcmp(kBinaryBlob, out_frame->data->data(), kBinaryBlobSize)); 2867558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2868558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2869558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// Test the read path for 8-bit cleanliness as well. 2870558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelEventInterfaceTest, ReadBinaryFramesAre8BitClean) { 28714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) scoped_ptr<WebSocketFrame> frame( 28724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) new WebSocketFrame(WebSocketFrameHeader::kOpCodeBinary)); 28734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WebSocketFrameHeader& frame_header = frame->header; 28744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frame_header.final = true; 28754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frame_header.payload_length = kBinaryBlobSize; 28764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frame->data = new IOBuffer(kBinaryBlobSize); 28774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) memcpy(frame->data->data(), kBinaryBlob, kBinaryBlobSize); 28784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ScopedVector<WebSocketFrame> frames; 28794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) frames.push_back(frame.release()); 2880558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch scoped_ptr<ReadableFakeWebSocketStream> stream( 2881558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch new ReadableFakeWebSocketStream); 2882558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch stream->PrepareRawReadFrames( 28834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ReadableFakeWebSocketStream::SYNC, OK, frames.Pass()); 2884558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch set_stream(stream.Pass()); 28855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 2886558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*event_interface_, OnFlowControl(_)); 2887558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*event_interface_, 2888558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch OnDataFrame(true, 2889558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch WebSocketFrameHeader::kOpCodeBinary, 2890558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch std::vector<char>(kBinaryBlob, 2891558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch kBinaryBlob + kBinaryBlobSize))); 2892558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 2893558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 2894558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 2895558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 28965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Invalid UTF-8 is not permitted in Text frames. 28975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelSendUtf8Test, InvalidUtf8Rejected) { 28985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL( 28995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *event_interface_, 29005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel("Browser sent a text frame containing invalid UTF-8")); 29015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 29035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, WebSocketFrameHeader::kOpCodeText, AsVector("\xff")); 29065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 29075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A Text message cannot end with a partial UTF-8 character. 29095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInFinalFrame) { 29105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL( 29115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *event_interface_, 29125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel("Browser sent a text frame containing invalid UTF-8")); 29135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 29155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, WebSocketFrameHeader::kOpCodeText, AsVector("\xc2")); 29185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 29195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A non-final Text frame may end with a partial UTF-8 character (compare to 29215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// previous test). 29225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelSendUtf8Test, IncompleteCharacterInNonFinalFrame) { 29235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 29245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, WebSocketFrameHeader::kOpCodeText, AsVector("\xc2")); 29275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 29285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// UTF-8 parsing context must be retained between frames. 29305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelSendUtf8Test, ValidCharacterSplitBetweenFrames) { 29315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 29325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, WebSocketFrameHeader::kOpCodeText, AsVector("\xf1")); 29355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame(true, 29365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketFrameHeader::kOpCodeContinuation, 29375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AsVector("\x80\xa0\xbf")); 29385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 29395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Similarly, an invalid character should be detected even if split. 29415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelSendUtf8Test, InvalidCharacterSplit) { 29425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL( 29435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *event_interface_, 29445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel("Browser sent a text frame containing invalid UTF-8")); 29455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 29475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, WebSocketFrameHeader::kOpCodeText, AsVector("\xe1")); 29505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame(true, 29515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketFrameHeader::kOpCodeContinuation, 29525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) AsVector("\x80\xa0\xbf")); 29535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 29545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// An invalid character must be detected in continuation frames. 29565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelSendUtf8Test, InvalidByteInContinuation) { 29575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL( 29585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *event_interface_, 29595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel("Browser sent a text frame containing invalid UTF-8")); 29605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 29625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, WebSocketFrameHeader::kOpCodeText, AsVector("foo")); 29655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("bar")); 29675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("\xff")); 29695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 29705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// However, continuation frames of a Binary frame will not be tested for UTF-8 29725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// validity. 29735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelSendUtf8Test, BinaryContinuationNotChecked) { 29745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 29755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, WebSocketFrameHeader::kOpCodeBinary, AsVector("foo")); 29785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, WebSocketFrameHeader::kOpCodeContinuation, AsVector("bar")); 29805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 29815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, WebSocketFrameHeader::kOpCodeContinuation, AsVector("\xff")); 29825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 29835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Multiple text messages can be validated without the validation state getting 29855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// confused. 29865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelSendUtf8Test, ValidateMultipleTextMessages) { 29875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 29885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("foo")); 29905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector("bar")); 29915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 29925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 29935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// UTF-8 validation is enforced on received Text frames. 29945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, ReceivedInvalidUtf8) { 29955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 29965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) new ReadableFakeWebSocketStream); 29975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 29985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xff"}}; 29995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 30005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) set_stream(stream.Pass()); 30015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 30035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota)); 30045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*event_interface_, 30055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) OnFailChannel("Could not decode a text frame as UTF-8.")); 30065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 30085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) base::MessageLoop::current()->RunUntilIdle(); 30095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 30105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Invalid UTF-8 is not sent over the network. 30125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelStreamTest, InvalidUtf8TextFrameNotSent) { 30135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame expected[] = {{FINAL_FRAME, 30145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) WebSocketFrameHeader::kOpCodeClose, 30155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MASKED, CLOSE_DATA(GOING_AWAY, "")}}; 30165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 30175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 30185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 30195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 30205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 30215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(Return(OK)); 30225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()).Times(1); 30235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 30255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel_->SendFrame( 30275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, WebSocketFrameHeader::kOpCodeText, AsVector("\xff")); 30285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 30295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// The rest of the tests for receiving invalid UTF-8 test the communication with 30315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// the server. Since there is only one code path, it would be redundant to 30325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// perform the same tests on the EventInterface as well. 30335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// If invalid UTF-8 is received in a Text frame, the connection is failed. 30355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelReceiveUtf8Test, InvalidTextFrameRejected) { 30365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 30375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xff"}}; 30385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame expected[] = { 30395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 30405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}}; 30415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) { 30425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) InSequence s; 30435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 30445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 30455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 30465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 30475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(Return(OK)); 30485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()).Times(1); 30495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 30505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 30525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 30535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A received Text message is not permitted to end with a partial UTF-8 30555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// character. 30565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterReceived) { 30575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 30585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}}; 30595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame expected[] = { 30605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 30615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}}; 30625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 30635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 30645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 30655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 30665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(Return(OK)); 30675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()).Times(1); 30685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 30705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 30715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// However, a non-final Text frame may end with a partial UTF-8 character. 30735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterIncompleteMessage) { 30745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 30755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}}; 30765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 30775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 30785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 30795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 30815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 30825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// However, it will become an error if it is followed by an empty final frame. 30845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelReceiveUtf8Test, TricksyIncompleteCharacter) { 30855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 30865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}, 30875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, ""}}; 30885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame expected[] = { 30895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 30905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}}; 30915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 30925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 30935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 30945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 30955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(Return(OK)); 30965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()).Times(1); 30975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 30985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 30995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 31005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// UTF-8 parsing context must be retained between received frames of the same 31025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// message. 31035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedParsingContextRetained) { 31045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 31055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xf1"}, 31065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 31075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOT_MASKED, "\x80\xa0\xbf"}}; 31085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 31095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 31105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 31115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 31135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 31145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// An invalid character must be detected even if split between frames. 31165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelReceiveUtf8Test, SplitInvalidCharacterReceived) { 31175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 31185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xe1"}, 31195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 31205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOT_MASKED, "\x80\xa0\xbf"}}; 31215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame expected[] = { 31225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 31235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}}; 31245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 31255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 31265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 31275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 31285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(Return(OK)); 31295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()).Times(1); 31305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 31325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 31335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// An invalid character received in a continuation frame must be detected. 31355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelReceiveUtf8Test, InvalidReceivedIncontinuation) { 31365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 31375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"}, 31385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 31395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOT_MASKED, "bar"}, 31405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 31415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOT_MASKED, "\xff"}}; 31425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame expected[] = { 31435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, 31445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}}; 31455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 31465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 31475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 31485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 31495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(Return(OK)); 31505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()).Times(1); 31515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 31535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 31545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Continuations of binary frames must not be tested for UTF-8 validity. 31565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedBinaryNotUtf8Tested) { 31575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 31585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeBinary, NOT_MASKED, "foo"}, 31595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 31605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOT_MASKED, "bar"}, 31615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 31625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NOT_MASKED, "\xff"}}; 31635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 31645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 31655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 31665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 31685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 31695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Multiple Text messages can be validated. 31715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)TEST_F(WebSocketChannelReceiveUtf8Test, ValidateMultipleReceived) { 31725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) static const InitFrame frames[] = { 31735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"}, 31745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "bar"}}; 31755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 31765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 31775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 31785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 31795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 31805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 31815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 3182a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// A new data message cannot start in the middle of another data message. 3183a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, BogusContinuation) { 3184a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 3185a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new ReadableFakeWebSocketStream); 3186a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static const InitFrame frames[] = { 3187a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeBinary, 3188a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOT_MASKED, "frame1"}, 3189a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, 3190a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOT_MASKED, "frame2"}}; 3191a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 3192a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_stream(stream.Pass()); 3193a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3194a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 3195a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota)); 3196a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL( 3197a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *event_interface_, 3198a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnDataFrame( 3199a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) false, WebSocketFrameHeader::kOpCodeBinary, AsVector("frame1"))); 3200a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL( 3201a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *event_interface_, 3202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnFailChannel( 3203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) "Received start of new message but previous message is unfinished.")); 3204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3205a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 3206a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 3207a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3208a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// A new message cannot start with a Continuation frame. 3209a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, MessageStartingWithContinuation) { 3210a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 3211a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new ReadableFakeWebSocketStream); 3212a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static const InitFrame frames[] = { 3213a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 3214a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOT_MASKED, "continuation"}}; 3215a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 3216a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_stream(stream.Pass()); 3217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3218a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 3219a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota)); 3220a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*event_interface_, 3221a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnFailChannel("Received unexpected continuation frame.")); 3222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 3224a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 3225a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3226a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// A frame passed to the renderer must be either non-empty or have the final bit 3227a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)// set. 3228a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, DataFramesNonEmptyOrFinal) { 3229a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) scoped_ptr<ReadableFakeWebSocketStream> stream( 3230a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) new ReadableFakeWebSocketStream); 3231a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) static const InitFrame frames[] = { 3232a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, ""}, 3233a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, 3234a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) NOT_MASKED, ""}, 3235a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation, NOT_MASKED, ""}}; 3236a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) stream->PrepareReadFrames(ReadableFakeWebSocketStream::SYNC, OK, frames); 3237a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) set_stream(stream.Pass()); 3238a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnAddChannelResponse(false, _, _)); 3240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL(*event_interface_, OnFlowControl(kDefaultInitialQuota)); 3241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) EXPECT_CALL( 3242a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) *event_interface_, 3243a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) OnDataFrame(true, WebSocketFrameHeader::kOpCodeText, AsVector(""))); 3244a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 3245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 3246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)} 3247a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) 324846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Calls to OnSSLCertificateError() must be passed through to the event 324946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// interface with the correct URL attached. 325046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)TEST_F(WebSocketChannelEventInterfaceTest, OnSSLCertificateErrorCalled) { 325146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const GURL wss_url("wss://example.com/sslerror"); 325246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) connect_data_.socket_url = wss_url; 325346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const SSLInfo ssl_info; 325446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const bool fatal = true; 325546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) scoped_ptr<WebSocketEventInterface::SSLErrorCallbacks> fake_callbacks( 325646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) new FakeSSLErrorCallbacks); 325746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 325846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) EXPECT_CALL(*event_interface_, 325946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) OnSSLCertificateErrorCalled(NotNull(), wss_url, _, fatal)); 326046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 326146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) CreateChannelAndConnect(); 326246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) connect_data_.creator.connect_delegate->OnSSLCertificateError( 326346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) fake_callbacks.Pass(), ssl_info, fatal); 326446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)} 326546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 3266558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// If we receive another frame after Close, it is not valid. It is not 3267558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// completely clear what behaviour is required from the standard in this case, 3268558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// but the current implementation fails the connection. Since a Close has 3269558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// already been sent, this just means closing the connection. 3270558790d6acca3451cf3a6b497803a5f07d0bec58Ben MurdochTEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) { 32714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame frames[] = { 32724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 32734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}, 32744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, 32754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) NOT_MASKED, "Ping body"}}; 32764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected[] = { 32774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 32784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}}; 3279558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 32805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 3281558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 32824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 3283558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillRepeatedly(Return(ERR_IO_PENDING)); 3284558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch { 3285558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // We only need to verify the relative order of WriteFrames() and 3286558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Close(). The current implementation calls WriteFrames() for the Close 3287558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // frame before calling ReadFrames() again, but that is an implementation 3288558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // detail and better not to consider required behaviour. 3289558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch InSequence s; 32904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 3291558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch .WillOnce(Return(OK)); 3292558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch EXPECT_CALL(*mock_stream_, Close()).Times(1); 3293558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 3294558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 3295558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CreateChannelAndConnectSuccessfully(); 3296558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch} 3297558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 32984e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// A protocol error from the remote server should result in a close frame with 32994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// status 1002, followed by the connection closing. 33004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)TEST_F(WebSocketChannelStreamTest, ProtocolError) { 33014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) static const InitFrame expected[] = { 33024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 33034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) MASKED, CLOSE_DATA(PROTOCOL_ERROR, "WebSocket Protocol Error")}}; 33044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 33055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 33064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 33074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .WillOnce(Return(ERR_WS_PROTOCOL_ERROR)); 33084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 33094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) .WillOnce(Return(OK)); 33104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()); 33114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 33124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) CreateChannelAndConnectSuccessfully(); 33134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 33144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 33151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// Set the closing handshake timeout to a very tiny value before connecting. 33161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)class WebSocketChannelStreamTimeoutTest : public WebSocketChannelStreamTest { 33171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) protected: 33181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) WebSocketChannelStreamTimeoutTest() {} 33191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 33201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) virtual void CreateChannelAndConnectSuccessfully() OVERRIDE { 33211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) set_stream(mock_stream_.Pass()); 33221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnect(); 3323effb81e5f8246d0db0270817048dc992db66e9fbBen Murdoch channel_->SendFlowControl(kPlentyOfQuota); 33241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->SetClosingHandshakeTimeoutForTesting( 33251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TimeDelta::FromMilliseconds(kVeryTinyTimeoutMillis)); 3326f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) connect_data_.creator.connect_delegate->OnSuccess(stream_.Pass()); 33271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 33281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)}; 33291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 33301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// In this case the server initiates the closing handshake with a Close 33311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// message. WebSocketChannel responds with a matching Close message, and waits 33321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// for the server to close the TCP/IP connection. The server never closes the 33331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// connection, so the closing handshake times out and WebSocketChannel closes 33341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// the connection itself. 33351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelStreamTimeoutTest, ServerInitiatedCloseTimesOut) { 33361e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = { 33371e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 33381e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}}; 33391e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame expected[] = { 33401e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 33411e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}}; 33421e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 33435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 33441e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 33451e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(ReturnFrames(&frames)) 33461e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 33471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Checkpoint checkpoint; 33481e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TestClosure completion; 33491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) { 33501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) InSequence s; 33511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 33521e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(Return(OK)); 33531e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(checkpoint, Call(1)); 33541e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()) 33551e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(InvokeClosure(completion.closure())); 33561e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 33571e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 33581e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 33591e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) checkpoint.Call(1); 33601e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) completion.WaitForResult(); 33611e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 33621e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 33631e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// In this case the client initiates the closing handshake by sending a Close 33641e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// message. WebSocketChannel waits for a Close message in response from the 33651e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// server. The server never responds to the Close message, so the closing 33661e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// handshake times out and WebSocketChannel closes the connection. 33671e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelStreamTimeoutTest, ClientInitiatedCloseTimesOut) { 33681e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame expected[] = { 33691e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 33701e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}}; 33711e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 33725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 33731e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 33741e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillRepeatedly(Return(ERR_IO_PENDING)); 33751e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TestClosure completion; 33761e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) { 33771e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) InSequence s; 33781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 33791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(Return(OK)); 33801e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()) 33811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(InvokeClosure(completion.closure())); 33821e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 33831e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 33841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 33851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK"); 33861e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) completion.WaitForResult(); 33871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 33881e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 33891e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// In this case the client initiates the closing handshake and the server 33901e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// responds with a matching Close message. WebSocketChannel waits for the server 33911e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// to close the TCP/IP connection, but it never does. The closing handshake 33921e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)// times out and WebSocketChannel closes the connection. 33931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)TEST_F(WebSocketChannelStreamTimeoutTest, ConnectionCloseTimesOut) { 33941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame expected[] = { 33951e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 33961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}}; 33971e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) static const InitFrame frames[] = { 33981e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) {FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, 33991e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) NOT_MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}}; 34001e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber()); 34015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber()); 34021e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) TestClosure completion; 34031e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ScopedVector<WebSocketFrame>* read_frames = NULL; 34041e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CompletionCallback read_callback; 34051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) { 34061e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) InSequence s; 34071e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Copy the arguments to ReadFrames so that the test can call the callback 34081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // after it has send the close message. 34091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 34101e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(DoAll(SaveArg<0>(&read_frames), 34111e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) SaveArg<1>(&read_callback), 34121e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) Return(ERR_IO_PENDING))); 34131e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The first real event that happens is the client sending the Close 34141e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // message. 34151e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _)) 34161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(Return(OK)); 34171e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The |read_frames| callback is called (from this test case) at this 34181e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // point. ReadFrames is called again by WebSocketChannel, waiting for 34191e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // ERR_CONNECTION_CLOSED. 34201e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, ReadFrames(_, _)) 34211e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(Return(ERR_IO_PENDING)); 34221e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // The timeout happens and so WebSocketChannel closes the stream. 34231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) EXPECT_CALL(*mock_stream_, Close()) 34241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) .WillOnce(InvokeClosure(completion.closure())); 34251e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 34261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 34271e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) CreateChannelAndConnectSuccessfully(); 34281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) channel_->StartClosingHandshake(kWebSocketNormalClosure, "OK"); 34291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) ASSERT_TRUE(read_frames); 34301e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Provide the "Close" message from the server. 34311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) *read_frames = CreateFrameVector(frames); 34321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) read_callback.Run(OK); 34331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) completion.WaitForResult(); 34341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 34351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 34369ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} // namespace 34379ab5563a3196760eb381d102cbb2bc0f7abc6a50Ben Murdoch} // namespace net 3438