blob: 487a4dcfa787db956c2898b143da4bb8351ece27 [file] [log] [blame]
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "third_party/blink/renderer/modules/direct_sockets/tcp_socket.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
#include "third_party/blink/renderer/bindings/core/v8/script_promise_tester.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_dom_exception.h"
#include "third_party/blink/renderer/platform/heap/heap.h"
namespace blink {
namespace {
class TCPSocketCreator {
STACK_ALLOCATED();
public:
TCPSocketCreator() = default;
~TCPSocketCreator() = default;
TCPSocket* Create(const V8TestingScope& scope) {
auto* script_state = scope.GetScriptState();
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
auto* tcp_socket = MakeGarbageCollected<TCPSocket>(*resolver);
create_promise_ = resolver->Promise();
return tcp_socket;
}
ScriptPromise GetSciptPromise() { return create_promise_; }
private:
ScriptPromise create_promise_;
};
TEST(TCPSocketTest, Create) {
V8TestingScope scope;
TCPSocketCreator tcp_socket_creator;
auto create_promise = tcp_socket_creator.GetSciptPromise();
EXPECT_TRUE(create_promise.IsEmpty());
tcp_socket_creator.Create(scope);
auto* script_state = scope.GetScriptState();
create_promise = tcp_socket_creator.GetSciptPromise();
ScriptPromiseTester create_tester(script_state, create_promise);
EXPECT_TRUE(create_promise.IsAssociatedWith(script_state));
ASSERT_FALSE(create_tester.IsFulfilled());
}
TEST(TCPSocketTest, CloseBeforeInit) {
V8TestingScope scope;
TCPSocketCreator tcp_socket_creator;
auto* tcp_socket = tcp_socket_creator.Create(scope);
auto* script_state = scope.GetScriptState();
auto create_promise = tcp_socket_creator.GetSciptPromise();
ScriptPromiseTester create_tester(script_state, create_promise);
ASSERT_FALSE(create_tester.IsRejected());
auto close_promise =
tcp_socket->close(script_state, scope.GetExceptionState());
ScriptPromiseTester close_tester(script_state, close_promise);
create_tester.WaitUntilSettled();
ASSERT_TRUE(create_tester.IsRejected());
DOMException* create_exception = V8DOMException::ToImplWithTypeCheck(
scope.GetIsolate(), create_tester.Value().V8Value());
ASSERT_TRUE(create_exception);
EXPECT_EQ(create_exception->name(), "AbortError");
EXPECT_EQ(create_exception->message(), "The request was aborted locally");
close_tester.WaitUntilSettled();
ASSERT_TRUE(close_tester.IsFulfilled());
}
TEST(TCPSocketTest, CloseAfterInitWithoutResultOK) {
V8TestingScope scope;
TCPSocketCreator tcp_socket_creator;
auto* tcp_socket = tcp_socket_creator.Create(scope);
auto* script_state = scope.GetScriptState();
auto create_promise = tcp_socket_creator.GetSciptPromise();
ScriptPromiseTester create_tester(script_state, create_promise);
ASSERT_FALSE(create_tester.IsRejected());
int32_t result = net::Error::ERR_FAILED;
tcp_socket->Init(result, net::IPEndPoint(), net::IPEndPoint(),
mojo::ScopedDataPipeConsumerHandle(),
mojo::ScopedDataPipeProducerHandle());
auto close_promise =
tcp_socket->close(script_state, scope.GetExceptionState());
ScriptPromiseTester close_tester(script_state, close_promise);
create_tester.WaitUntilSettled();
ASSERT_TRUE(create_tester.IsRejected());
DOMException* create_exception = V8DOMException::ToImplWithTypeCheck(
scope.GetIsolate(), create_tester.Value().V8Value());
ASSERT_TRUE(create_exception);
EXPECT_EQ(create_exception->name(), "NotAllowedError");
EXPECT_EQ(create_exception->message(), "Permission denied");
close_tester.WaitUntilSettled();
ASSERT_TRUE(close_tester.IsFulfilled());
}
TEST(TCPSocketTest, CloseAfterInitWithResultOK) {
V8TestingScope scope;
TCPSocketCreator tcp_socket_creator;
auto* tcp_socket = tcp_socket_creator.Create(scope);
auto* script_state = scope.GetScriptState();
auto create_promise = tcp_socket_creator.GetSciptPromise();
ScriptPromiseTester create_tester(script_state, create_promise);
ASSERT_FALSE(create_tester.IsFulfilled());
int32_t result = net::Error::OK;
tcp_socket->Init(result, net::IPEndPoint(), net::IPEndPoint(),
mojo::ScopedDataPipeConsumerHandle(),
mojo::ScopedDataPipeProducerHandle());
EXPECT_TRUE(tcp_socket->readable());
EXPECT_TRUE(tcp_socket->writable());
auto close_promise =
tcp_socket->close(script_state, scope.GetExceptionState());
ScriptPromiseTester close_tester(script_state, close_promise);
create_tester.WaitUntilSettled();
ASSERT_TRUE(create_tester.IsFulfilled());
close_tester.WaitUntilSettled();
ASSERT_TRUE(close_tester.IsFulfilled());
}
TEST(TCPSocketTest, OnSocketObserverConnectionError) {
V8TestingScope scope;
TCPSocketCreator tcp_socket_creator;
auto* tcp_socket = tcp_socket_creator.Create(scope);
auto* script_state = scope.GetScriptState();
auto create_promise = tcp_socket_creator.GetSciptPromise();
ScriptPromiseTester create_tester(script_state, create_promise);
ASSERT_FALSE(create_tester.IsRejected());
// Trigger OnSocketObserverConnectionError().
auto observer = tcp_socket->GetTCPSocketObserver();
observer.reset();
create_tester.WaitUntilSettled();
ASSERT_TRUE(create_tester.IsRejected());
DOMException* create_exception = V8DOMException::ToImplWithTypeCheck(
scope.GetIsolate(), create_tester.Value().V8Value());
ASSERT_TRUE(create_exception);
EXPECT_EQ(create_exception->name(), "NetworkError");
EXPECT_EQ(create_exception->message(),
"The request was aborted due to connection error");
}
} // namespace
} // namespace blink