From ef2e3d4b5062d61a61aae45487a8bda5540295a9 Mon Sep 17 00:00:00 2001 From: Andrey Ignatov Date: Sat, 4 Feb 2017 01:28:42 -0800 Subject: [PATCH] Expose testing callbacks from AsyncSocketTest2. Summary: `TestConnectionEventCallback` and `TestAcceptCallback` are very handy and can be used in other tests outside folly. Specifically I'm going to use them in `ConnectHookTest`. It'll also allow to avoid copy/paste in `TransparentTlsTest`. Reviewed By: plapukhov Differential Revision: D4507461 fbshipit-source-id: dfaa97e26036ebb11da17a53d4a73431a295f4d4 --- folly/Makefile.am | 1 + folly/io/async/test/AsyncSocketTest2.cpp | 214 +--------------------- folly/io/async/test/AsyncSocketTest2.h | 224 +++++++++++++++++++++++ 3 files changed, 229 insertions(+), 210 deletions(-) create mode 100644 folly/io/async/test/AsyncSocketTest2.h diff --git a/folly/Makefile.am b/folly/Makefile.am index 75dceafd..eedc1dd0 100644 --- a/folly/Makefile.am +++ b/folly/Makefile.am @@ -242,6 +242,7 @@ nobase_follyinclude_HEADERS = \ io/async/VirtualEventBase.h \ io/async/WriteChainAsyncTransportWrapper.h \ io/async/test/AsyncSSLSocketTest.h \ + io/async/test/AsyncSocketTest2.h \ io/async/test/BlockingSocket.h \ io/async/test/MockAsyncSocket.h \ io/async/test/MockAsyncServerSocket.h \ diff --git a/folly/io/async/test/AsyncSocketTest2.cpp b/folly/io/async/test/AsyncSocketTest2.cpp index 13f23b75..5dada116 100644 --- a/folly/io/async/test/AsyncSocketTest2.cpp +++ b/folly/io/async/test/AsyncSocketTest2.cpp @@ -13,11 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include + #include -#include #include #include -#include #include #include #include @@ -50,6 +51,7 @@ using std::chrono::milliseconds; using boost::scoped_array; using namespace folly; +using namespace folly::test; using namespace testing; namespace fsp = folly::portability::sockets; @@ -1584,214 +1586,6 @@ TEST(AsyncSocket, ConnectReadUninstallRead) { /////////////////////////////////////////////////////////////////////////// // AsyncServerSocket tests /////////////////////////////////////////////////////////////////////////// -namespace { -/** - * Helper ConnectionEventCallback class for the test code. - * It maintains counters protected by a spin lock. - */ -class TestConnectionEventCallback : - public AsyncServerSocket::ConnectionEventCallback { - public: - virtual void onConnectionAccepted( - const int /* socket */, - const SocketAddress& /* addr */) noexcept override { - folly::RWSpinLock::WriteHolder holder(spinLock_); - connectionAccepted_++; - } - - virtual void onConnectionAcceptError(const int /* err */) noexcept override { - folly::RWSpinLock::WriteHolder holder(spinLock_); - connectionAcceptedError_++; - } - - virtual void onConnectionDropped( - const int /* socket */, - const SocketAddress& /* addr */) noexcept override { - folly::RWSpinLock::WriteHolder holder(spinLock_); - connectionDropped_++; - } - - virtual void onConnectionEnqueuedForAcceptorCallback( - const int /* socket */, - const SocketAddress& /* addr */) noexcept override { - folly::RWSpinLock::WriteHolder holder(spinLock_); - connectionEnqueuedForAcceptCallback_++; - } - - virtual void onConnectionDequeuedByAcceptorCallback( - const int /* socket */, - const SocketAddress& /* addr */) noexcept override { - folly::RWSpinLock::WriteHolder holder(spinLock_); - connectionDequeuedByAcceptCallback_++; - } - - virtual void onBackoffStarted() noexcept override { - folly::RWSpinLock::WriteHolder holder(spinLock_); - backoffStarted_++; - } - - virtual void onBackoffEnded() noexcept override { - folly::RWSpinLock::WriteHolder holder(spinLock_); - backoffEnded_++; - } - - virtual void onBackoffError() noexcept override { - folly::RWSpinLock::WriteHolder holder(spinLock_); - backoffError_++; - } - - unsigned int getConnectionAccepted() const { - folly::RWSpinLock::ReadHolder holder(spinLock_); - return connectionAccepted_; - } - - unsigned int getConnectionAcceptedError() const { - folly::RWSpinLock::ReadHolder holder(spinLock_); - return connectionAcceptedError_; - } - - unsigned int getConnectionDropped() const { - folly::RWSpinLock::ReadHolder holder(spinLock_); - return connectionDropped_; - } - - unsigned int getConnectionEnqueuedForAcceptCallback() const { - folly::RWSpinLock::ReadHolder holder(spinLock_); - return connectionEnqueuedForAcceptCallback_; - } - - unsigned int getConnectionDequeuedByAcceptCallback() const { - folly::RWSpinLock::ReadHolder holder(spinLock_); - return connectionDequeuedByAcceptCallback_; - } - - unsigned int getBackoffStarted() const { - folly::RWSpinLock::ReadHolder holder(spinLock_); - return backoffStarted_; - } - - unsigned int getBackoffEnded() const { - folly::RWSpinLock::ReadHolder holder(spinLock_); - return backoffEnded_; - } - - unsigned int getBackoffError() const { - folly::RWSpinLock::ReadHolder holder(spinLock_); - return backoffError_; - } - - private: - mutable folly::RWSpinLock spinLock_; - unsigned int connectionAccepted_{0}; - unsigned int connectionAcceptedError_{0}; - unsigned int connectionDropped_{0}; - unsigned int connectionEnqueuedForAcceptCallback_{0}; - unsigned int connectionDequeuedByAcceptCallback_{0}; - unsigned int backoffStarted_{0}; - unsigned int backoffEnded_{0}; - unsigned int backoffError_{0}; -}; - -/** - * Helper AcceptCallback class for the test code - * It records the callbacks that were invoked, and also supports calling - * generic std::function objects in each callback. - */ -class TestAcceptCallback : public AsyncServerSocket::AcceptCallback { - public: - enum EventType { - TYPE_START, - TYPE_ACCEPT, - TYPE_ERROR, - TYPE_STOP - }; - struct EventInfo { - EventInfo(int fd, const folly::SocketAddress& addr) - : type(TYPE_ACCEPT), - fd(fd), - address(addr), - errorMsg() {} - explicit EventInfo(const std::string& msg) - : type(TYPE_ERROR), - fd(-1), - address(), - errorMsg(msg) {} - explicit EventInfo(EventType et) - : type(et), - fd(-1), - address(), - errorMsg() {} - - EventType type; - int fd; // valid for TYPE_ACCEPT - folly::SocketAddress address; // valid for TYPE_ACCEPT - string errorMsg; // valid for TYPE_ERROR - }; - typedef std::deque EventList; - - TestAcceptCallback() - : connectionAcceptedFn_(), - acceptErrorFn_(), - acceptStoppedFn_(), - events_() {} - - std::deque* getEvents() { - return &events_; - } - - void setConnectionAcceptedFn( - const std::function& fn) { - connectionAcceptedFn_ = fn; - } - void setAcceptErrorFn(const std::function& fn) { - acceptErrorFn_ = fn; - } - void setAcceptStartedFn(const std::function& fn) { - acceptStartedFn_ = fn; - } - void setAcceptStoppedFn(const std::function& fn) { - acceptStoppedFn_ = fn; - } - - void connectionAccepted( - int fd, const folly::SocketAddress& clientAddr) noexcept override { - events_.emplace_back(fd, clientAddr); - - if (connectionAcceptedFn_) { - connectionAcceptedFn_(fd, clientAddr); - } - } - void acceptError(const std::exception& ex) noexcept override { - events_.emplace_back(ex.what()); - - if (acceptErrorFn_) { - acceptErrorFn_(ex); - } - } - void acceptStarted() noexcept override { - events_.emplace_back(TYPE_START); - - if (acceptStartedFn_) { - acceptStartedFn_(); - } - } - void acceptStopped() noexcept override { - events_.emplace_back(TYPE_STOP); - - if (acceptStoppedFn_) { - acceptStoppedFn_(); - } - } - - private: - std::function connectionAcceptedFn_; - std::function acceptErrorFn_; - std::function acceptStartedFn_; - std::function acceptStoppedFn_; - - std::deque events_; -}; -} /** * Make sure accepted sockets have O_NONBLOCK and TCP_NODELAY set diff --git a/folly/io/async/test/AsyncSocketTest2.h b/folly/io/async/test/AsyncSocketTest2.h new file mode 100644 index 00000000..dacb8e54 --- /dev/null +++ b/folly/io/async/test/AsyncSocketTest2.h @@ -0,0 +1,224 @@ +/* + * Copyright 2017 Facebook, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include +#include +#include +#include + +#include + +#include + +namespace folly { +namespace test { + +/** + * Helper ConnectionEventCallback class for the test code. + * It maintains counters protected by a spin lock. + */ +class TestConnectionEventCallback + : public AsyncServerSocket::ConnectionEventCallback { + public: + virtual void onConnectionAccepted( + const int /* socket */, + const SocketAddress& /* addr */) noexcept override { + folly::RWSpinLock::WriteHolder holder(spinLock_); + connectionAccepted_++; + } + + virtual void onConnectionAcceptError(const int /* err */) noexcept override { + folly::RWSpinLock::WriteHolder holder(spinLock_); + connectionAcceptedError_++; + } + + virtual void onConnectionDropped( + const int /* socket */, + const SocketAddress& /* addr */) noexcept override { + folly::RWSpinLock::WriteHolder holder(spinLock_); + connectionDropped_++; + } + + virtual void onConnectionEnqueuedForAcceptorCallback( + const int /* socket */, + const SocketAddress& /* addr */) noexcept override { + folly::RWSpinLock::WriteHolder holder(spinLock_); + connectionEnqueuedForAcceptCallback_++; + } + + virtual void onConnectionDequeuedByAcceptorCallback( + const int /* socket */, + const SocketAddress& /* addr */) noexcept override { + folly::RWSpinLock::WriteHolder holder(spinLock_); + connectionDequeuedByAcceptCallback_++; + } + + virtual void onBackoffStarted() noexcept override { + folly::RWSpinLock::WriteHolder holder(spinLock_); + backoffStarted_++; + } + + virtual void onBackoffEnded() noexcept override { + folly::RWSpinLock::WriteHolder holder(spinLock_); + backoffEnded_++; + } + + virtual void onBackoffError() noexcept override { + folly::RWSpinLock::WriteHolder holder(spinLock_); + backoffError_++; + } + + unsigned int getConnectionAccepted() const { + folly::RWSpinLock::ReadHolder holder(spinLock_); + return connectionAccepted_; + } + + unsigned int getConnectionAcceptedError() const { + folly::RWSpinLock::ReadHolder holder(spinLock_); + return connectionAcceptedError_; + } + + unsigned int getConnectionDropped() const { + folly::RWSpinLock::ReadHolder holder(spinLock_); + return connectionDropped_; + } + + unsigned int getConnectionEnqueuedForAcceptCallback() const { + folly::RWSpinLock::ReadHolder holder(spinLock_); + return connectionEnqueuedForAcceptCallback_; + } + + unsigned int getConnectionDequeuedByAcceptCallback() const { + folly::RWSpinLock::ReadHolder holder(spinLock_); + return connectionDequeuedByAcceptCallback_; + } + + unsigned int getBackoffStarted() const { + folly::RWSpinLock::ReadHolder holder(spinLock_); + return backoffStarted_; + } + + unsigned int getBackoffEnded() const { + folly::RWSpinLock::ReadHolder holder(spinLock_); + return backoffEnded_; + } + + unsigned int getBackoffError() const { + folly::RWSpinLock::ReadHolder holder(spinLock_); + return backoffError_; + } + + private: + mutable folly::RWSpinLock spinLock_; + unsigned int connectionAccepted_{0}; + unsigned int connectionAcceptedError_{0}; + unsigned int connectionDropped_{0}; + unsigned int connectionEnqueuedForAcceptCallback_{0}; + unsigned int connectionDequeuedByAcceptCallback_{0}; + unsigned int backoffStarted_{0}; + unsigned int backoffEnded_{0}; + unsigned int backoffError_{0}; +}; + +/** + * Helper AcceptCallback class for the test code + * It records the callbacks that were invoked, and also supports calling + * generic std::function objects in each callback. + */ +class TestAcceptCallback : public AsyncServerSocket::AcceptCallback { + public: + enum EventType { TYPE_START, TYPE_ACCEPT, TYPE_ERROR, TYPE_STOP }; + struct EventInfo { + EventInfo(int fd, const folly::SocketAddress& addr) + : type(TYPE_ACCEPT), fd(fd), address(addr), errorMsg() {} + explicit EventInfo(const std::string& msg) + : type(TYPE_ERROR), fd(-1), address(), errorMsg(msg) {} + explicit EventInfo(EventType et) + : type(et), fd(-1), address(), errorMsg() {} + + EventType type; + int fd; // valid for TYPE_ACCEPT + folly::SocketAddress address; // valid for TYPE_ACCEPT + std::string errorMsg; // valid for TYPE_ERROR + }; + typedef std::deque EventList; + + TestAcceptCallback() + : connectionAcceptedFn_(), + acceptErrorFn_(), + acceptStoppedFn_(), + events_() {} + + std::deque* getEvents() { + return &events_; + } + + void setConnectionAcceptedFn( + const std::function& fn) { + connectionAcceptedFn_ = fn; + } + void setAcceptErrorFn(const std::function& fn) { + acceptErrorFn_ = fn; + } + void setAcceptStartedFn(const std::function& fn) { + acceptStartedFn_ = fn; + } + void setAcceptStoppedFn(const std::function& fn) { + acceptStoppedFn_ = fn; + } + + void connectionAccepted( + int fd, + const folly::SocketAddress& clientAddr) noexcept override { + events_.emplace_back(fd, clientAddr); + + if (connectionAcceptedFn_) { + connectionAcceptedFn_(fd, clientAddr); + } + } + void acceptError(const std::exception& ex) noexcept override { + events_.emplace_back(ex.what()); + + if (acceptErrorFn_) { + acceptErrorFn_(ex); + } + } + void acceptStarted() noexcept override { + events_.emplace_back(TYPE_START); + + if (acceptStartedFn_) { + acceptStartedFn_(); + } + } + void acceptStopped() noexcept override { + events_.emplace_back(TYPE_STOP); + + if (acceptStoppedFn_) { + acceptStoppedFn_(); + } + } + + private: + std::function connectionAcceptedFn_; + std::function acceptErrorFn_; + std::function acceptStartedFn_; + std::function acceptStoppedFn_; + + std::deque events_; +}; +} +} -- 2.34.1