Skip to content

Commit

Permalink
use asio without boost
Browse files Browse the repository at this point in the history
This removes the last dependency to boost (except the boost test driver).
  • Loading branch information
ursfassler committed Dec 29, 2023
1 parent 9d4ef37 commit 1533c19
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 92 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/run-all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
g++ \
gcovr \
git \
libboost-system-dev \
libasio-dev \
libboost-test-dev \
libtclap-dev \
make \
Expand Down
44 changes: 0 additions & 44 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ endif()
project(Cucumber-Cpp)

option(BUILD_SHARED_LIBS "Generate shared libraries" OFF)
option(CUKE_USE_STATIC_BOOST "Statically link Boost (except boost::test)" ${WIN32})
option(CUKE_USE_STATIC_GTEST "Statically link Google Test" ON)
option(CUKE_ENABLE_BOOST_TEST "Enable Boost.Test framework" ON)
option(CUKE_ENABLE_EXAMPLES "Build examples" OFF)
Expand Down Expand Up @@ -114,55 +113,12 @@ endif()
set(BOOST_MIN_VERSION "1.70")

set(Boost_USE_STATIC_RUNTIME OFF)
set(CUKE_CORE_BOOST_LIBS system)
if(CUKE_ENABLE_BOOST_TEST)
# "An external test runner utility is required to link with dynamic library" (Boost User's Guide)
set(Boost_USE_STATIC_LIBS OFF)
set(CMAKE_CXX_FLAGS "-DBOOST_TEST_DYN_LINK ${CMAKE_CXX_FLAGS}")
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS unit_test_framework)
endif()

if(CUKE_USE_STATIC_BOOST)
set(Boost_USE_STATIC_LIBS ON)
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${CUKE_CORE_BOOST_LIBS} REQUIRED)
else()
set(CMAKE_CXX_FLAGS "-DBOOST_ALL_DYN_LINK ${CMAKE_CXX_FLAGS}")
set(Boost_USE_STATIC_LIBS OFF)
find_package(Boost ${BOOST_MIN_VERSION} COMPONENTS ${CUKE_CORE_BOOST_LIBS} REQUIRED)
endif()

# Create import targets for CMake versions older than 3.5 (actually older FindBoost.cmake)
if(Boost_USE_STATIC_LIBS)
set(LIBRARY_TYPE STATIC)
else()
# Just because we don't ask for static doesn't mean we're not getting static
set(LIBRARY_TYPE UNKNOWN)
endif()
if(Boost_INCLUDE_DIRS AND NOT TARGET Boost::boost)
add_library(Boost::boost INTERFACE IMPORTED)
set_target_properties(Boost::boost PROPERTIES
"INTERFACE_INCLUDE_DIRECTORIES" "${Boost_INCLUDE_DIRS}")
endif()
if(Boost_SYSTEM_LIBRARY AND NOT TARGET Boost::system)
add_library(Boost::system ${LIBRARY_TYPE} IMPORTED)
set_target_properties(Boost::system PROPERTIES
"IMPORTED_LOCATION" "${Boost_SYSTEM_LIBRARY}"
"INTERFACE_LINK_LIBRARIES" "Boost::boost"
)
if(Boost_USE_STATIC_LIBS)
set_target_properties(Boost::system PROPERTIES
"COMPILE_DEFINITIONS" BOOST_ERROR_CODE_HEADER_ONLY=1
)
endif()
endif()
if(Boost_UNIT_TEST_FRAMEWORK_LIBRARY AND NOT TARGET Boost::unit_test_framework)
add_library(Boost::unit_test_framework ${LIBRARY_TYPE} IMPORTED)
set_target_properties(Boost::unit_test_framework PROPERTIES
"IMPORTED_LOCATION" "${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}"
"INTERFACE_LINK_LIBRARIES" "Boost::boost"
)
endif()

#
# GTest
#
Expand Down
21 changes: 10 additions & 11 deletions include/cucumber-cpp/internal/connectors/wire/WireServer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

#include <string>

#include <boost/asio.hpp>
#include <asio.hpp>

namespace cucumber {
namespace internal {
Expand All @@ -29,15 +29,14 @@ class CUCUMBER_CPP_EXPORT SocketServer {

protected:
const ProtocolHandler* protocolHandler;
boost::asio::io_service ios;
asio::io_service ios;

template<typename Protocol>
void doListen(
boost::asio::basic_socket_acceptor<Protocol>& acceptor,
const typename Protocol::endpoint& endpoint
asio::basic_socket_acceptor<Protocol>& acceptor, const typename Protocol::endpoint& endpoint
);
template<typename Protocol>
void doAcceptOnce(boost::asio::basic_socket_acceptor<Protocol>& acceptor);
void doAcceptOnce(asio::basic_socket_acceptor<Protocol>& acceptor);
void processStream(std::iostream& stream);
};

Expand All @@ -64,7 +63,7 @@ class CUCUMBER_CPP_EXPORT TCPSocketServer : public SocketServer {
/**
* Bind and listen to a TCP port on the given endpoint
*/
void listen(const boost::asio::ip::tcp::endpoint endpoint);
void listen(const asio::ip::tcp::endpoint endpoint);

/**
* Endpoint (IP address and port number) that this server is currently
Expand All @@ -73,15 +72,15 @@ class CUCUMBER_CPP_EXPORT TCPSocketServer : public SocketServer {
* @throw std::system_error when not listening on any socket or
* the endpoint cannot be determined.
*/
boost::asio::ip::tcp::endpoint listenEndpoint() const;
asio::ip::tcp::endpoint listenEndpoint() const;

void acceptOnce() override;

private:
boost::asio::ip::tcp::acceptor acceptor;
asio::ip::tcp::acceptor acceptor;
};

#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
#if defined(ASIO_HAS_LOCAL_SOCKETS)
/**
* Socket server that calls a protocol handler line by line
*/
Expand All @@ -103,14 +102,14 @@ class CUCUMBER_CPP_EXPORT UnixSocketServer : public SocketServer {
* @throw std::system_error when not listening on any socket or
* the endpoint cannot be determined.
*/
boost::asio::local::stream_protocol::endpoint listenEndpoint() const;
asio::local::stream_protocol::endpoint listenEndpoint() const;

void acceptOnce() override;

~UnixSocketServer() override;

private:
boost::asio::local::stream_protocol::acceptor acceptor;
asio::local::stream_protocol::acceptor acceptor;
};
#endif

Expand Down
2 changes: 0 additions & 2 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -106,8 +106,6 @@ foreach(TARGET
$<INSTALL_INTERFACE:$<INSTALL_PREFIX>/include>
)
target_link_libraries(${TARGET}
PUBLIC
Boost::boost
PRIVATE
${CUKE_EXTRA_PRIVATE_LIBRARIES}
)
Expand Down
24 changes: 9 additions & 15 deletions src/connectors/wire/WireServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,14 @@
namespace cucumber {
namespace internal {

using namespace boost::asio;
using namespace boost::asio::ip;
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
using namespace boost::asio::local;
#endif

SocketServer::SocketServer(const ProtocolHandler* protocolHandler) :
protocolHandler(protocolHandler),
ios() {
}

template<typename Protocol>
void SocketServer::doListen(
basic_socket_acceptor<Protocol>& acceptor, const typename Protocol::endpoint& endpoint
asio::basic_socket_acceptor<Protocol>& acceptor, const typename Protocol::endpoint& endpoint
) {
if (acceptor.is_open())
throw std::system_error(asio::error::already_open);
Expand All @@ -28,7 +22,7 @@ void SocketServer::doListen(
}

template<typename Protocol>
void SocketServer::doAcceptOnce(basic_socket_acceptor<Protocol>& acceptor) {
void SocketServer::doAcceptOnce(asio::basic_socket_acceptor<Protocol>& acceptor) {
typename Protocol::iostream stream;
acceptor.accept(*stream.rdbuf());
processStream(stream);
Expand All @@ -47,23 +41,23 @@ TCPSocketServer::TCPSocketServer(const ProtocolHandler* protocolHandler) :
}

void TCPSocketServer::listen(const port_type port) {
listen(tcp::endpoint(tcp::v4(), port));
listen(asio::ip::tcp::endpoint(asio::ip::tcp::v4(), port));
}

void TCPSocketServer::listen(const tcp::endpoint endpoint) {
void TCPSocketServer::listen(const asio::ip::tcp::endpoint endpoint) {
doListen(acceptor, endpoint);
acceptor.set_option(tcp::no_delay(true));
acceptor.set_option(asio::ip::tcp::no_delay(true));
}

tcp::endpoint TCPSocketServer::listenEndpoint() const {
asio::ip::tcp::endpoint TCPSocketServer::listenEndpoint() const {
return acceptor.local_endpoint();
}

void TCPSocketServer::acceptOnce() {
doAcceptOnce(acceptor);
}

#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
#if defined(ASIO_HAS_LOCAL_SOCKETS)
UnixSocketServer::UnixSocketServer(const ProtocolHandler* protocolHandler) :
SocketServer(protocolHandler),
acceptor(ios) {
Expand All @@ -73,10 +67,10 @@ void UnixSocketServer::listen(const std::string& unixPath) {
if (std::filesystem::status(unixPath).type() == std::filesystem::file_type::socket)
std::filesystem::remove(unixPath);

doListen(acceptor, stream_protocol::endpoint(unixPath));
doListen(acceptor, asio::local::stream_protocol::endpoint(unixPath));
}

stream_protocol::endpoint UnixSocketServer::listenEndpoint() const {
asio::local::stream_protocol::endpoint UnixSocketServer::listenEndpoint() const {
return acceptor.local_endpoint();
}

Expand Down
10 changes: 4 additions & 6 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ void acceptWireProtocol(
JsonWireMessageCodec wireCodec;
WireProtocolHandler protocolHandler(wireCodec, cukeEngine);
std::unique_ptr<SocketServer> server;
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
#if defined(ASIO_HAS_LOCAL_SOCKETS)
if (!unixPath.empty()) {
UnixSocketServer* const unixServer = new UnixSocketServer(&protocolHandler);
server.reset(unixServer);
Expand All @@ -31,9 +31,7 @@ void acceptWireProtocol(
{
TCPSocketServer* const tcpServer = new TCPSocketServer(&protocolHandler);
server.reset(tcpServer);
tcpServer->listen(
boost::asio::ip::tcp::endpoint(boost::asio::ip::address::from_string(host), port)
);
tcpServer->listen(asio::ip::tcp::endpoint(asio::ip::address::from_string(host), port));
if (verbose)
std::clog << "Listening on " << tcpServer->listenEndpoint() << std::endl;
}
Expand All @@ -60,7 +58,7 @@ int CUCUMBER_CPP_EXPORT main(int argc, char** argv) {
);
cmd.add(portArg);

#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
#if defined(ASIO_HAS_LOCAL_SOCKETS)
TCLAP::ValueArg<std::string> unixArg(
"u",
"unix",
Expand All @@ -77,7 +75,7 @@ int CUCUMBER_CPP_EXPORT main(int argc, char** argv) {
std::string unixPath;
std::string listenHost = listenArg.getValue();
int port = portArg.getValue();
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
#if defined(ASIO_HAS_LOCAL_SOCKETS)
unixPath = unixArg.getValue();
#endif

Expand Down
22 changes: 9 additions & 13 deletions tests/integration/WireServerTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@
#include <sstream>

using namespace cucumber::internal;
using namespace boost::asio::ip;
#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
using namespace boost::asio::local;
#endif
using namespace testing;

static const auto THREAD_TEST_TIMEOUT = std::chrono::milliseconds(4000);
Expand Down Expand Up @@ -94,7 +90,7 @@ class TCPSocketServerTest : public SocketServerTest {

TEST_F(TCPSocketServerTest, exitsOnFirstConnectionClosed) {
// given
tcp::iostream client(server->listenEndpoint());
asio::ip::tcp::iostream client(server->listenEndpoint());
ASSERT_THAT(client, IsConnected());
ASSERT_THAT(server->listenEndpoint().address().to_string(), std::string("0.0.0.0"));

Expand All @@ -107,11 +103,11 @@ TEST_F(TCPSocketServerTest, exitsOnFirstConnectionClosed) {

TEST_F(TCPSocketServerTest, moreThanOneClientCanConnect) {
// given
tcp::iostream client1(server->listenEndpoint());
asio::ip::tcp::iostream client1(server->listenEndpoint());
ASSERT_THAT(client1, IsConnected());

// when
tcp::iostream client2(server->listenEndpoint());
asio::ip::tcp::iostream client2(server->listenEndpoint());

// then
ASSERT_THAT(client2, IsConnected());
Expand All @@ -126,7 +122,7 @@ TEST_F(TCPSocketServerTest, receiveAndSendsSingleLineMassages) {
}

// given
tcp::iostream client(server->listenEndpoint());
asio::ip::tcp::iostream client(server->listenEndpoint());
ASSERT_THAT(client, IsConnected());

// when
Expand All @@ -145,7 +141,7 @@ class TCPSocketServerLocalhostTest : public SocketServerTest {

SocketServer* createListeningServer() override {
server.reset(new TCPSocketServer(&protocolHandler));
server->listen(tcp::endpoint(boost::asio::ip::address::from_string("127.0.0.1"), 0));
server->listen(asio::ip::tcp::endpoint(asio::ip::address::from_string("127.0.0.1"), 0));
return server.get();
}

Expand All @@ -156,7 +152,7 @@ class TCPSocketServerLocalhostTest : public SocketServerTest {

TEST_F(TCPSocketServerLocalhostTest, listensOnLocalhost) {
// given
tcp::iostream client(server->listenEndpoint());
asio::ip::tcp::iostream client(server->listenEndpoint());
ASSERT_THAT(client, IsConnected());
ASSERT_THAT(server->listenEndpoint().address().to_string(), std::string("127.0.0.1"));

Expand All @@ -167,7 +163,7 @@ TEST_F(TCPSocketServerLocalhostTest, listensOnLocalhost) {
EXPECT_THAT(serverThread, EventuallyTerminates());
}

#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
#if defined(ASIO_HAS_LOCAL_SOCKETS)
class UnixSocketServerTest : public SocketServerTest {
protected:
std::unique_ptr<UnixSocketServer> server;
Expand Down Expand Up @@ -204,14 +200,14 @@ class UnixSocketServerTest : public SocketServerTest {
* created at startup and removed on shutdown.
*/
TEST_F(UnixSocketServerTest, fullLifecycle) {
stream_protocol::endpoint socketName = server->listenEndpoint();
asio::local::stream_protocol::endpoint socketName = server->listenEndpoint();
EXPECT_CALL(protocolHandler, handle("X")).WillRepeatedly(Return("Y"));

// socket created at startup
ASSERT_TRUE(std::filesystem::exists(socketName.path()));

// traffic flows
stream_protocol::iostream client(socketName);
asio::local::stream_protocol::iostream client(socketName);
client << "X" << std::endl << std::flush;
EXPECT_THAT(client, EventuallyReceives("Y"));

Expand Down

0 comments on commit 1533c19

Please sign in to comment.