#include "librbd/migration/HttpClient.h"
#include "gtest/gtest.h"
#include "gmock/gmock.h"
+#include <unistd.h>
#include <boost/asio/ip/tcp.hpp>
#include <boost/beast/core.hpp>
#include <boost/beast/http.hpp>
TestMockFixture::TearDown();
}
+ // if we have a racing where another thread manages to bind and listen the
+ // port picked by this acceptor, try again.
+ static constexpr int MAX_BIND_RETRIES = 42;
+
void create_acceptor(bool reuse) {
- m_acceptor.emplace(*m_image_ctx->asio_engine,
+ for (int retries = 0;; retries++) {
+ try {
+ m_acceptor.emplace(*m_image_ctx->asio_engine,
boost::asio::ip::tcp::endpoint(
boost::asio::ip::tcp::v4(), m_server_port), reuse);
+ // yay!
+ break;
+ } catch (const boost::system::system_error& e) {
+ if (retries == MAX_BIND_RETRIES) {
+ throw;
+ }
+ if (e.code() != boost::system::errc::address_in_use) {
+ throw;
+ }
+ }
+ // backoff a little bit
+ usleep(retries * 10'000);
+ }
m_server_port = m_acceptor->local_endpoint().port();
}
#include "rgw/rgw_http_client.h"
#include "global/global_init.h"
#include "common/ceph_argparse.h"
+#include <unistd.h>
#include <curl/curl.h>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/write.hpp>
using namespace std;
+namespace {
+ using tcp = boost::asio::ip::tcp;
+
+ // if we have a racing where another thread manages to bind and listen the
+ // port picked by this acceptor, try again.
+ static constexpr int MAX_BIND_RETRIES = 42;
+
+ tcp::acceptor try_bind(boost::asio::io_context& ioctx) {
+ using tcp = boost::asio::ip::tcp;
+ tcp::endpoint endpoint(tcp::v4(), 0);
+ tcp::acceptor acceptor(ioctx);
+ acceptor.open(endpoint.protocol());
+ for (int retries = 0;; retries++) {
+ try {
+ acceptor.bind(endpoint);
+ // yay!
+ break;
+ } catch (const boost::system::system_error& e) {
+ if (retries == MAX_BIND_RETRIES) {
+ throw;
+ }
+ if (e.code() != boost::system::errc::address_in_use) {
+ throw;
+ }
+ }
+ // backoff a little bit
+ usleep(retries * 10'000);
+ }
+ return acceptor;
+ }
+}
+
TEST(HTTPManager, ReadTruncated)
{
using tcp = boost::asio::ip::tcp;
- tcp::endpoint endpoint(tcp::v4(), 0);
boost::asio::io_context ioctx;
- tcp::acceptor acceptor(ioctx);
- acceptor.open(endpoint.protocol());
- acceptor.bind(endpoint);
+ auto acceptor = try_bind(ioctx);
acceptor.listen();
std::thread server{[&] {
TEST(HTTPManager, Head)
{
using tcp = boost::asio::ip::tcp;
- tcp::endpoint endpoint(tcp::v4(), 0);
boost::asio::io_context ioctx;
- tcp::acceptor acceptor(ioctx);
- acceptor.open(endpoint.protocol());
- acceptor.bind(endpoint);
+ auto acceptor = try_bind(ioctx);
acceptor.listen();
std::thread server{[&] {