Commit 6ba2117b authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

ScopedBoundPort

Summary:
[Folly] `ScopedBoundPort`.

An RAII class for `bind`ing, but not `listen`ing, an ephemral port.

Useful when there is a need to test server-down cases - in such cases, a guaranteed-not-listening port is required.

Extracted from a unit-test in Thrift; switches the Thrift test to use this extracted implementation instead.

Reviewed By: djwatson

Differential Revision: D3714293

fbshipit-source-id: 649fba1a0b7f0519b8297a3183d03c5dde23ddc6
parent 74d1af87
......@@ -227,6 +227,7 @@ nobase_follyinclude_HEADERS = \
io/async/test/MockAsyncTransport.h \
io/async/test/MockAsyncUDPSocket.h \
io/async/test/MockTimeoutManager.h \
io/async/test/ScopedBoundPort.h \
io/async/test/SocketPair.h \
io/async/test/TimeUtil.h \
io/async/test/UndelayedDestruction.h \
......@@ -415,6 +416,7 @@ libfolly_la_SOURCES = \
io/async/SSLContext.cpp \
io/async/ScopedEventBaseThread.cpp \
io/async/HHWheelTimer.cpp \
io/async/test/ScopedBoundPort.cpp \
io/async/test/SocketPair.cpp \
io/async/test/TimeUtil.cpp \
io/async/ssl/OpenSSLUtils.cpp \
......
......@@ -351,6 +351,17 @@ class AsyncServerSocket : public DelayedDestruction
*/
void getAddress(SocketAddress* addressReturn) const;
/**
* Get the local address to which the socket is bound.
*
* Throws TTransportException on error.
*/
SocketAddress getAddress() const {
SocketAddress ret;
getAddress(&ret);
return ret;
}
/**
* Get all the local addresses to which the socket is bound.
*
......
/*
* Copyright 2016 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.
*/
#include <folly/io/async/test/ScopedBoundPort.h>
#include <folly/Memory.h>
#include <folly/io/async/AsyncServerSocket.h>
#include <folly/io/async/ScopedEventBaseThread.h>
namespace folly {
ScopedBoundPort::ScopedBoundPort(IPAddress host) {
ebth_ = folly::make_unique<ScopedEventBaseThread>();
ebth_->getEventBase()->runInEventBaseThreadAndWait([&] {
sock_ = AsyncServerSocket::newSocket(ebth_->getEventBase());
sock_->bind(SocketAddress(host, 0));
});
}
ScopedBoundPort::~ScopedBoundPort() {
ebth_->getEventBase()->runInEventBaseThread([sock = std::move(sock_)]{});
}
SocketAddress ScopedBoundPort::getAddress() const {
return sock_->getAddress();
}
}
/*
* Copyright 2016 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 <memory>
#include <utility>
#include <folly/IPAddress.h>
#include <folly/IPAddressV6.h>
#include <folly/SocketAddress.h>
namespace folly {
class AsyncServerSocket;
class ScopedEventBaseThread;
/***
* ScopedBoundPort
*
* Binds to an ephemeral port in the ctor but does not listen. Unbinds from the
* port in the dtor.
*
* While an instance is in scope, we know at least one port which is guaranteed
* not to be listening - the port the instance binds but does not listen.
*
* Useful for testing server-down cases.
*
* Example:
*
* TEST(MyClient, WhenTheServerIsDown_ThrowsServerDownException) {
* folly::ScopedBoundPort bound;
* MyClient client(bound.getAddress(), 100ms);
* EXPECT_THROW(client.getData(), ServerDownException);
* }
*/
class ScopedBoundPort {
public:
explicit ScopedBoundPort(IPAddress host = IPAddressV6("::1"));
~ScopedBoundPort();
SocketAddress getAddress() const;
private:
std::unique_ptr<ScopedEventBaseThread> ebth_;
std::shared_ptr<AsyncServerSocket> sock_;
};
}
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