Commit ef2e3d4b authored by Andrey Ignatov's avatar Andrey Ignatov Committed by Facebook Github Bot

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
parent c847b1b4
......@@ -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 \
......
......@@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <folly/io/async/test/AsyncSocketTest2.h>
#include <folly/ExceptionWrapper.h>
#include <folly/RWSpinLock.h>
#include <folly/Random.h>
#include <folly/SocketAddress.h>
#include <folly/io/async/AsyncServerSocket.h>
#include <folly/io/async/AsyncSocket.h>
#include <folly/io/async/AsyncTimeout.h>
#include <folly/io/async/EventBase.h>
......@@ -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<EventInfo> EventList;
TestAcceptCallback()
: connectionAcceptedFn_(),
acceptErrorFn_(),
acceptStoppedFn_(),
events_() {}
std::deque<EventInfo>* getEvents() {
return &events_;
}
void setConnectionAcceptedFn(
const std::function<void(int, const folly::SocketAddress&)>& fn) {
connectionAcceptedFn_ = fn;
}
void setAcceptErrorFn(const std::function<void(const std::exception&)>& fn) {
acceptErrorFn_ = fn;
}
void setAcceptStartedFn(const std::function<void()>& fn) {
acceptStartedFn_ = fn;
}
void setAcceptStoppedFn(const std::function<void()>& 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<void(int, const folly::SocketAddress&)> connectionAcceptedFn_;
std::function<void(const std::exception&)> acceptErrorFn_;
std::function<void()> acceptStartedFn_;
std::function<void()> acceptStoppedFn_;
std::deque<EventInfo> events_;
};
}
/**
* Make sure accepted sockets have O_NONBLOCK and TCP_NODELAY set
......
/*
* 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 <deque>
#include <exception>
#include <functional>
#include <string>
#include <folly/RWSpinLock.h>
#include <folly/io/async/AsyncServerSocket.h>
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<EventInfo> EventList;
TestAcceptCallback()
: connectionAcceptedFn_(),
acceptErrorFn_(),
acceptStoppedFn_(),
events_() {}
std::deque<EventInfo>* getEvents() {
return &events_;
}
void setConnectionAcceptedFn(
const std::function<void(int, const folly::SocketAddress&)>& fn) {
connectionAcceptedFn_ = fn;
}
void setAcceptErrorFn(const std::function<void(const std::exception&)>& fn) {
acceptErrorFn_ = fn;
}
void setAcceptStartedFn(const std::function<void()>& fn) {
acceptStartedFn_ = fn;
}
void setAcceptStoppedFn(const std::function<void()>& 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<void(int, const folly::SocketAddress&)> connectionAcceptedFn_;
std::function<void(const std::exception&)> acceptErrorFn_;
std::function<void()> acceptStartedFn_;
std::function<void()> acceptStoppedFn_;
std::deque<EventInfo> events_;
};
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment