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 \
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 \
*/
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.
*
--- /dev/null
+/*
+ * 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();
+}
+}
--- /dev/null
+/*
+ * 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_;
+};
+}