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

Unified Diff: third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp

Issue 2930263002: Add blink::WebSocketHandshakeThrottle (Closed)
Patch Set: Fixes from yhirano review Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
diff --git a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
index a17e61576cfacb9f6cadc100f50434e1611291ce..079360f07c3e18db1d44af14240dbf819e243095 100644
--- a/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
+++ b/third_party/WebKit/Source/modules/websockets/DocumentWebSocketChannelTest.cpp
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "modules/websockets/WebSocketChannel.h"
+#include "modules/websockets/DocumentWebSocketChannel.h"
#include <stdint.h>
#include <memory>
@@ -10,7 +10,7 @@
#include "core/dom/Document.h"
#include "core/fileapi/Blob.h"
#include "core/testing/DummyPageHolder.h"
-#include "modules/websockets/DocumentWebSocketChannel.h"
+#include "modules/websockets/WebSocketChannel.h"
#include "modules/websockets/WebSocketChannelClient.h"
#include "modules/websockets/WebSocketHandle.h"
#include "modules/websockets/WebSocketHandleClient.h"
@@ -19,6 +19,10 @@
#include "platform/wtf/PtrUtil.h"
#include "platform/wtf/Vector.h"
#include "platform/wtf/text/WTFString.h"
+#include "public/platform/WebCallbacks.h"
+#include "public/platform/WebSocketHandshakeThrottle.h"
+#include "public/platform/WebURL.h"
+#include "public/web/WebLocalFrame.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -89,16 +93,31 @@ class MockWebSocketHandle : public WebSocketHandle {
MOCK_METHOD2(Close, void(unsigned short, const String&));
};
+class MockWebSocketHandshakeThrottle : public WebSocketHandshakeThrottle {
+ public:
+ static MockWebSocketHandshakeThrottle* Create() {
+ return new testing::StrictMock<MockWebSocketHandshakeThrottle>();
+ }
+ MockWebSocketHandshakeThrottle() {}
+ ~MockWebSocketHandshakeThrottle() override { Destructor(); }
+
+ MOCK_METHOD3(ThrottleHandshake,
+ void(const WebURL&,
+ WebLocalFrame*,
+ WebCallbacks<void, const WebString&>*));
+
+ // This method is used to allow us to require that the destructor is called at
+ // a particular time.
+ MOCK_METHOD0(Destructor, void());
+};
+
class DocumentWebSocketChannelTest : public ::testing::Test {
public:
DocumentWebSocketChannelTest()
: page_holder_(DummyPageHolder::Create()),
channel_client_(MockWebSocketChannelClient::Create()),
handle_(MockWebSocketHandle::Create()),
- channel_(DocumentWebSocketChannel::Create(&page_holder_->GetDocument(),
- channel_client_.Get(),
- SourceLocation::Capture(),
- Handle())),
+ handshake_throttle_(nullptr),
sum_of_consumed_buffered_amount_(0) {
ON_CALL(*ChannelClient(), DidConsumeBufferedAmount(_))
.WillByDefault(Invoke(
@@ -107,6 +126,13 @@ class DocumentWebSocketChannelTest : public ::testing::Test {
~DocumentWebSocketChannelTest() { Channel()->Disconnect(); }
+ void SetUp() override {
+ channel_ = DocumentWebSocketChannel::CreateForTesting(
+ &page_holder_->GetDocument(), channel_client_.Get(),
+ SourceLocation::Capture(), Handle(),
+ WTF::WrapUnique(handshake_throttle_));
+ }
+
MockWebSocketChannelClient* ChannelClient() { return channel_client_.Get(); }
WebSocketChannel* Channel() {
@@ -117,6 +143,10 @@ class DocumentWebSocketChannelTest : public ::testing::Test {
return static_cast<WebSocketHandleClient*>(channel_.Get());
}
+ WebCallbacks<void, const WebString&>* WebCallbacks() {
+ return channel_.Get();
+ }
+
MockWebSocketHandle* Handle() { return handle_; }
void DidConsumeBufferedAmount(unsigned long a) {
@@ -140,6 +170,8 @@ class DocumentWebSocketChannelTest : public ::testing::Test {
std::unique_ptr<DummyPageHolder> page_holder_;
Persistent<MockWebSocketChannelClient> channel_client_;
MockWebSocketHandle* handle_;
+ // |handshake_throttle_| is owned by |channel_| once SetUp() has been called.
+ MockWebSocketHandshakeThrottle* handshake_throttle_;
Persistent<DocumentWebSocketChannel> channel_;
unsigned long sum_of_consumed_buffered_amount_;
};
@@ -775,6 +807,221 @@ TEST_F(DocumentWebSocketChannelTest, failFromWebSocket) {
SourceLocation::Create(String(), 0, 0, nullptr));
}
+class DocumentWebSocketChannelHandshakeThrottleTest
+ : public DocumentWebSocketChannelTest {
+ public:
+ DocumentWebSocketChannelHandshakeThrottleTest() {
+ handshake_throttle_ = MockWebSocketHandshakeThrottle::Create();
+ }
+
+ // Expectations for the normal result of calling Channel()->Connect() with a
+ // non-null throttle.
+ void NormalHandshakeExpectations() {
+ EXPECT_CALL(*Handle(), Initialize(_));
+ EXPECT_CALL(*Handle(), Connect(_, _, _, _, _, _));
+ EXPECT_CALL(*Handle(), FlowControl(_));
+ EXPECT_CALL(*handshake_throttle_, ThrottleHandshake(_, _, _));
+ }
+
+ static KURL url() { return KURL(KURL(), "ws://localhost/"); }
+};
+
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest, ThrottleArguments) {
+ EXPECT_CALL(*Handle(), Initialize(_));
+ EXPECT_CALL(*Handle(), Connect(_, _, _, _, _, _));
+ EXPECT_CALL(*Handle(), FlowControl(_));
+ EXPECT_CALL(*handshake_throttle_,
+ ThrottleHandshake(WebURL(url()), _, WebCallbacks()));
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ Channel()->Connect(url(), "");
+}
+
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest, ThrottleSucceedsFirst) {
+ Checkpoint checkpoint;
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(checkpoint, Call(2));
+ EXPECT_CALL(*ChannelClient(), DidConnect(String("a"), String("b")));
+ }
+ Channel()->Connect(url(), "");
+ checkpoint.Call(1);
+ WebCallbacks()->OnSuccess();
+ checkpoint.Call(2);
+ HandleClient()->DidConnect(Handle(), String("a"), String("b"));
+}
+
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest, HandshakeSucceedsFirst) {
+ Checkpoint checkpoint;
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(checkpoint, Call(1));
+ EXPECT_CALL(checkpoint, Call(2));
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(*ChannelClient(), DidConnect(String("a"), String("b")));
+ }
+ Channel()->Connect(url(), "");
+ checkpoint.Call(1);
+ HandleClient()->DidConnect(Handle(), String("a"), String("b"));
+ checkpoint.Call(2);
+ WebCallbacks()->OnSuccess();
+}
+
+// This happens if JS code calls close() during the handshake.
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest, FailDuringThrottle) {
+ Checkpoint checkpoint;
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(*ChannelClient(), DidError());
+ EXPECT_CALL(*ChannelClient(), DidClose(_, _, _));
+ EXPECT_CALL(checkpoint, Call(1));
+ }
+ Channel()->Connect(url(), "");
+ Channel()->Fail("close during handshake", kWarningMessageLevel,
+ SourceLocation::Create(String(), 0, 0, nullptr));
+ checkpoint.Call(1);
+}
+
+// It makes no difference to the behaviour if the WebSocketHandle has actually
+// connected.
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest,
+ FailDuringThrottleAfterConnect) {
+ Checkpoint checkpoint;
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(*ChannelClient(), DidError());
+ EXPECT_CALL(*ChannelClient(), DidClose(_, _, _));
+ EXPECT_CALL(checkpoint, Call(1));
+ }
+ Channel()->Connect(url(), "");
+ HandleClient()->DidConnect(Handle(), String("a"), String("b"));
+ Channel()->Fail("close during handshake", kWarningMessageLevel,
+ SourceLocation::Create(String(), 0, 0, nullptr));
+ checkpoint.Call(1);
+}
+
+// This happens if the JS context is destroyed during the handshake.
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest, CloseDuringThrottle) {
+ Checkpoint checkpoint;
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(*Handle(), Close(_, _));
+ EXPECT_CALL(checkpoint, Call(1));
+ }
+ Channel()->Connect(url(), "");
+ Channel()->Close(DocumentWebSocketChannel::kCloseEventCodeGoingAway, "");
+ checkpoint.Call(1);
+}
+
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest,
+ CloseDuringThrottleAfterConnect) {
+ Checkpoint checkpoint;
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(*Handle(), Close(_, _));
+ EXPECT_CALL(checkpoint, Call(1));
+ }
+ Channel()->Connect(url(), "");
+ HandleClient()->DidConnect(Handle(), String("a"), String("b"));
+ Channel()->Close(DocumentWebSocketChannel::kCloseEventCodeGoingAway, "");
+ checkpoint.Call(1);
+}
+
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest,
+ DisconnectDuringThrottle) {
+ Checkpoint checkpoint;
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(checkpoint, Call(1));
+ }
+ Channel()->Connect(url(), "");
+ Channel()->Disconnect();
+ checkpoint.Call(1);
+}
+
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest,
+ DisconnectDuringThrottleAfterConnect) {
+ Checkpoint checkpoint;
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(checkpoint, Call(1));
+ }
+ Channel()->Connect(url(), "");
+ HandleClient()->DidConnect(Handle(), String("a"), String("b"));
+ Channel()->Disconnect();
+ checkpoint.Call(1);
+}
+
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest,
+ ThrottleReportsErrorBeforeConnect) {
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(*ChannelClient(), DidError());
+ EXPECT_CALL(*ChannelClient(), DidClose(_, _, _));
+ }
+ Channel()->Connect(url(), "");
+ WebCallbacks()->OnError("Connection blocked by throttle");
+}
+
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest,
+ ThrottleReportsErrorAfterConnect) {
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(*ChannelClient(), DidError());
+ EXPECT_CALL(*ChannelClient(), DidClose(_, _, _));
+ }
+ Channel()->Connect(url(), "");
+ HandleClient()->DidConnect(Handle(), String("a"), String("b"));
+ WebCallbacks()->OnError("Connection blocked by throttle");
+}
+
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest,
+ ConnectFailBeforeThrottle) {
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(*ChannelClient(), DidError());
+ EXPECT_CALL(*ChannelClient(), DidClose(_, _, _));
+ }
+ Channel()->Connect(url(), "");
+ HandleClient()->DidFail(Handle(), "connect failed");
+}
+
+// TODO(ricea): Can this actually happen?
+TEST_F(DocumentWebSocketChannelHandshakeThrottleTest,
+ ConnectCloseBeforeThrottle) {
+ NormalHandshakeExpectations();
+ {
+ InSequence s;
+ EXPECT_CALL(*handshake_throttle_, Destructor());
+ EXPECT_CALL(*ChannelClient(), DidClose(_, _, _));
+ }
+ Channel()->Connect(url(), "");
+ HandleClient()->DidClose(Handle(), false,
+ WebSocketChannel::kCloseEventCodeProtocolError,
+ "connect error");
+}
+
} // namespace
} // namespace blink

Powered by Google App Engine
This is Rietveld 408576698