Problem: Dependency on googletest framework

Currently cppzmq as relatively simple and header only library depends on rather
complex unit test framework googletest.
Current issues:
- Googletest requires downloading and building it every time on travis
as cache support is limited there
- Googletest build is signifficant with comparison to cppzmq unittests
total runtime

Solution: Port existing tests to Catch - header only C++ framework and
gain ~20% build speed up on travis.

Why Catch?
It is well know C++ header only testing framework. It works well, it is
being kept up to date and maintainers seem to pay attention to
community's comments and issues.
We can not use Catch2 currently as we still support pre-C++11 compilers.
This commit is contained in:
Pawel Kurdybacha 2018-09-23 17:14:25 +01:00
parent 5af24314c3
commit ae15964907
18 changed files with 332 additions and 389 deletions

View File

@ -22,7 +22,7 @@ There are other C++ bindings for ZeroMQ with different design goals. In particul
Supported platforms
===================
- Only a subset of the platforms that are supported by libzmq itself are supported. Some features already require a compiler supporting C++11. In the future, probably all features will require C++11. To build and run the tests, cmake and googletest are required.
- Only a subset of the platforms that are supported by libzmq itself are supported. Some features already require a compiler supporting C++11. In the future, probably all features will require C++11. To build and run the tests, CMake and Catch are required.
- Tested libzmq versions are
- 4.2.0 (without DRAFT API)
- 4.2.5 (with and without DRAFT API)

View File

@ -20,7 +20,7 @@ environment:
cache:
- libzmq -> appveyor.yml
- Build/tests/googletest -> tests/cmake/googletest-download.cmake
- Build/catch -> tests/cmake/catch.cmake
before_build:
- if not exist libzmq (

View File

@ -1 +0,0 @@
googletest integration into CMake and travis-ci was based on https://github.com/bast/gtest-demo

View File

@ -1,27 +0,0 @@
Copyright (c) 2015-2018, Radovan Bast
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of gtest-demo nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -9,11 +9,7 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
include(cmake/googletest.cmake)
fetch_googletest(
${PROJECT_SOURCE_DIR}/cmake
${PROJECT_BINARY_DIR}/googletest
)
include(cmake/catch.cmake)
add_executable(
unit_tests
@ -24,14 +20,15 @@ add_executable(
active_poller.cpp
multipart.cpp
monitor.cpp
)
)
add_dependencies(unit_tests catch)
target_include_directories(unit_tests PUBLIC ${CATCH_INCLUDE_DIR})
target_link_libraries(
unit_tests
PRIVATE gtest
PRIVATE gmock_main
PRIVATE cppzmq
)
)
OPTION (COVERAGE "Enable gcda file generation needed by lcov" OFF)
@ -45,4 +42,4 @@ add_test(
unit
COMMAND
${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_BINDIR}/unit_tests
)
)

View File

@ -7,10 +7,10 @@
#include <array>
#include <memory>
TEST(active_poller, create_destroy)
TEST_CASE("create destroy", "[active_poller]")
{
zmq::active_poller_t active_poller;
ASSERT_TRUE(active_poller.empty());
CHECK(active_poller.empty());
}
static_assert(!std::is_copy_constructible<zmq::active_poller_t>::value,
@ -18,72 +18,72 @@ static_assert(!std::is_copy_constructible<zmq::active_poller_t>::value,
static_assert(!std::is_copy_assignable<zmq::active_poller_t>::value,
"active_active_poller_t should not be copy-assignable");
TEST(active_poller, move_construct_empty)
TEST_CASE("move construct empty", "[active_poller]")
{
zmq::active_poller_t a;
ASSERT_TRUE(a.empty());
CHECK(a.empty());
zmq::active_poller_t b = std::move(a);
ASSERT_TRUE(b.empty());
ASSERT_EQ(0u, a.size());
ASSERT_EQ(0u, b.size());
CHECK(b.empty());
CHECK(0u == a.size());
CHECK(0u == b.size());
}
TEST(active_poller, move_assign_empty)
TEST_CASE("move assign empty", "[active_poller]")
{
zmq::active_poller_t a;
ASSERT_TRUE(a.empty());
CHECK(a.empty());
zmq::active_poller_t b;
ASSERT_TRUE(b.empty());
CHECK(b.empty());
b = std::move(a);
ASSERT_EQ(0u, a.size());
ASSERT_EQ(0u, b.size());
ASSERT_TRUE(a.empty());
ASSERT_TRUE(b.empty());
CHECK(0u == a.size());
CHECK(0u == b.size());
CHECK(a.empty());
CHECK(b.empty());
}
TEST(active_poller, move_construct_non_empty)
TEST_CASE("move construct non empty", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::active_poller_t a;
a.add(socket, ZMQ_POLLIN, [](short) {});
ASSERT_FALSE(a.empty());
ASSERT_EQ(1u, a.size());
CHECK_FALSE(a.empty());
CHECK(1u == a.size());
zmq::active_poller_t b = std::move(a);
ASSERT_TRUE(a.empty());
ASSERT_EQ(0u, a.size());
ASSERT_FALSE(b.empty());
ASSERT_EQ(1u, b.size());
CHECK(a.empty());
CHECK(0u == a.size());
CHECK_FALSE(b.empty());
CHECK(1u == b.size());
}
TEST(active_poller, move_assign_non_empty)
TEST_CASE("move assign non empty", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::active_poller_t a;
a.add(socket, ZMQ_POLLIN, [](short) {});
ASSERT_FALSE(a.empty());
ASSERT_EQ(1u, a.size());
CHECK_FALSE(a.empty());
CHECK(1u == a.size());
zmq::active_poller_t b;
b = std::move(a);
ASSERT_TRUE(a.empty());
ASSERT_EQ(0u, a.size());
ASSERT_FALSE(b.empty());
ASSERT_EQ(1u, b.size());
CHECK(a.empty());
CHECK(0u == a.size());
CHECK_FALSE(b.empty());
CHECK(1u == b.size());
}
TEST(active_poller, add_handler)
TEST_CASE("add handler", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::active_poller_t active_poller;
zmq::active_poller_t::handler_t handler;
ASSERT_NO_THROW(active_poller.add(socket, ZMQ_POLLIN, handler));
CHECK_NOTHROW(active_poller.add(socket, ZMQ_POLLIN, handler));
}
TEST(active_poller, add_handler_invalid_events_type)
TEST_CASE("add handler invalid events type", "[active_poller]")
{
/// \todo is it good that this is accepted? should probably already be
/// checked by zmq_poller_add/modify in libzmq:
@ -93,12 +93,12 @@ TEST(active_poller, add_handler_invalid_events_type)
zmq::active_poller_t active_poller;
zmq::active_poller_t::handler_t handler;
short invalid_events_type = 2 << 10;
ASSERT_NO_THROW(active_poller.add(socket, invalid_events_type, handler));
ASSERT_FALSE(active_poller.empty());
ASSERT_EQ(1u, active_poller.size());
CHECK_NOTHROW(active_poller.add(socket, invalid_events_type, handler));
CHECK_FALSE(active_poller.empty());
CHECK(1u == active_poller.size());
}
TEST(active_poller, add_handler_twice_throws)
TEST_CASE("add handler twice throws", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
@ -106,41 +106,41 @@ TEST(active_poller, add_handler_twice_throws)
zmq::active_poller_t::handler_t handler;
active_poller.add(socket, ZMQ_POLLIN, handler);
/// \todo the actual error code should be checked
ASSERT_THROW(active_poller.add(socket, ZMQ_POLLIN, handler), zmq::error_t);
CHECK_THROWS_AS(active_poller.add(socket, ZMQ_POLLIN, handler), zmq::error_t);
}
TEST(active_poller, wait_with_no_handlers_throws)
TEST_CASE("wait with no handlers throws", "[active_poller]")
{
zmq::active_poller_t active_poller;
/// \todo the actual error code should be checked
ASSERT_THROW(active_poller.wait(std::chrono::milliseconds{10}), zmq::error_t);
CHECK_THROWS_AS(active_poller.wait(std::chrono::milliseconds{10}), zmq::error_t);
}
TEST(active_poller, remove_unregistered_throws)
TEST_CASE("remove unregistered throws", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::active_poller_t active_poller;
/// \todo the actual error code should be checked
ASSERT_THROW(active_poller.remove(socket), zmq::error_t);
CHECK_THROWS_AS(active_poller.remove(socket), zmq::error_t);
}
TEST(active_poller, remove_registered_empty)
TEST_CASE("remove registered empty", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::active_poller_t active_poller;
active_poller.add(socket, ZMQ_POLLIN, zmq::active_poller_t::handler_t{});
ASSERT_NO_THROW(active_poller.remove(socket));
CHECK_NOTHROW(active_poller.remove(socket));
}
TEST(active_poller, remove_registered_non_empty)
TEST_CASE("remove registered non empty", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::active_poller_t active_poller;
active_poller.add(socket, ZMQ_POLLIN, [](short) {});
ASSERT_NO_THROW(active_poller.remove(socket));
CHECK_NOTHROW(active_poller.remove(socket));
}
namespace
@ -153,25 +153,25 @@ struct server_client_setup : common_server_client_setup
};
}
TEST(active_poller, poll_basic)
TEST_CASE("poll basic", "[active_poller]")
{
server_client_setup s;
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
zmq::active_poller_t active_poller;
bool message_received = false;
zmq::active_poller_t::handler_t handler = [&message_received](short events) {
ASSERT_TRUE(0 != (events & ZMQ_POLLIN));
CHECK(0 != (events & ZMQ_POLLIN));
message_received = true;
};
ASSERT_NO_THROW(active_poller.add(s.server, ZMQ_POLLIN, handler));
ASSERT_EQ(1, active_poller.wait(std::chrono::milliseconds{-1}));
ASSERT_TRUE(message_received);
CHECK_NOTHROW(active_poller.add(s.server, ZMQ_POLLIN, handler));
CHECK(1 == active_poller.wait(std::chrono::milliseconds{-1}));
CHECK(message_received);
}
/// \todo this contains multiple test cases that should be split up
TEST(active_poller, client_server)
TEST_CASE("client server", "[active_poller]")
{
const std::string send_msg = "Hi";
@ -184,125 +184,126 @@ TEST(active_poller, client_server)
zmq::active_poller_t::handler_t handler = [&](short e) {
if (0 != (e & ZMQ_POLLIN)) {
zmq::message_t zmq_msg;
ASSERT_NO_THROW(s.server.recv(&zmq_msg)); // get message
CHECK_NOTHROW(s.server.recv(&zmq_msg)); // get message
std::string recv_msg(zmq_msg.data<char>(), zmq_msg.size());
ASSERT_EQ(send_msg, recv_msg);
CHECK(send_msg == recv_msg);
} else if (0 != (e & ~ZMQ_POLLOUT)) {
ASSERT_TRUE(false) << "Unexpected event type " << events;
INFO("Unexpected event type " << events);
REQUIRE(false);
}
events = e;
};
ASSERT_NO_THROW(active_poller.add(s.server, ZMQ_POLLIN, handler));
CHECK_NOTHROW(active_poller.add(s.server, ZMQ_POLLIN, handler));
// client sends message
ASSERT_NO_THROW(s.client.send(zmq::message_t{send_msg}));
CHECK_NOTHROW(s.client.send(zmq::message_t{send_msg}));
ASSERT_EQ(1, active_poller.wait(std::chrono::milliseconds{-1}));
ASSERT_EQ(events, ZMQ_POLLIN);
CHECK(1 == active_poller.wait(std::chrono::milliseconds{-1}));
CHECK(events == ZMQ_POLLIN);
// Re-add server socket with pollout flag
ASSERT_NO_THROW(active_poller.remove(s.server));
ASSERT_NO_THROW(active_poller.add(s.server, ZMQ_POLLIN | ZMQ_POLLOUT, handler));
ASSERT_EQ(1, active_poller.wait(std::chrono::milliseconds{-1}));
ASSERT_EQ(events, ZMQ_POLLOUT);
CHECK_NOTHROW(active_poller.remove(s.server));
CHECK_NOTHROW(active_poller.add(s.server, ZMQ_POLLIN | ZMQ_POLLOUT, handler));
CHECK(1 == active_poller.wait(std::chrono::milliseconds{-1}));
CHECK(events == ZMQ_POLLOUT);
}
TEST(active_poller, add_invalid_socket_throws)
TEST_CASE("add invalid socket throws", "[active_poller]")
{
zmq::context_t context;
zmq::active_poller_t active_poller;
zmq::socket_t a{context, zmq::socket_type::router};
zmq::socket_t b{std::move(a)};
ASSERT_THROW(active_poller.add(a, ZMQ_POLLIN, zmq::active_poller_t::handler_t{}),
CHECK_THROWS_AS(active_poller.add(a, ZMQ_POLLIN, zmq::active_poller_t::handler_t{}),
zmq::error_t);
}
TEST(active_poller, remove_invalid_socket_throws)
TEST_CASE("remove invalid socket throws", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::active_poller_t active_poller;
ASSERT_NO_THROW(
CHECK_NOTHROW(
active_poller.add(socket, ZMQ_POLLIN, zmq::active_poller_t::handler_t{}));
ASSERT_EQ(1u, active_poller.size());
CHECK(1u == active_poller.size());
std::vector<zmq::socket_t> sockets;
sockets.emplace_back(std::move(socket));
ASSERT_THROW(active_poller.remove(socket), zmq::error_t);
ASSERT_EQ(1u, active_poller.size());
CHECK_THROWS_AS(active_poller.remove(socket), zmq::error_t);
CHECK(1u == active_poller.size());
}
TEST(active_poller, wait_on_added_empty_handler)
TEST_CASE("wait on added empty handler", "[active_poller]")
{
server_client_setup s;
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
zmq::active_poller_t active_poller;
zmq::active_poller_t::handler_t handler;
ASSERT_NO_THROW(active_poller.add(s.server, ZMQ_POLLIN, handler));
ASSERT_NO_THROW(active_poller.wait(std::chrono::milliseconds{-1}));
CHECK_NOTHROW(active_poller.add(s.server, ZMQ_POLLIN, handler));
CHECK_NOTHROW(active_poller.wait(std::chrono::milliseconds{-1}));
}
TEST(active_poller, modify_empty_throws)
TEST_CASE("modify empty throws", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::push};
zmq::active_poller_t active_poller;
ASSERT_THROW(active_poller.modify(socket, ZMQ_POLLIN), zmq::error_t);
CHECK_THROWS_AS(active_poller.modify(socket, ZMQ_POLLIN), zmq::error_t);
}
TEST(active_poller, modify_invalid_socket_throws)
TEST_CASE("modify invalid socket throws", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t a{context, zmq::socket_type::push};
zmq::socket_t b{std::move(a)};
zmq::active_poller_t active_poller;
ASSERT_THROW(active_poller.modify(a, ZMQ_POLLIN), zmq::error_t);
CHECK_THROWS_AS(active_poller.modify(a, ZMQ_POLLIN), zmq::error_t);
}
TEST(active_poller, modify_not_added_throws)
TEST_CASE("modify not added throws", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t a{context, zmq::socket_type::push};
zmq::socket_t b{context, zmq::socket_type::push};
zmq::active_poller_t active_poller;
ASSERT_NO_THROW(
CHECK_NOTHROW(
active_poller.add(a, ZMQ_POLLIN, zmq::active_poller_t::handler_t{}));
ASSERT_THROW(active_poller.modify(b, ZMQ_POLLIN), zmq::error_t);
CHECK_THROWS_AS(active_poller.modify(b, ZMQ_POLLIN), zmq::error_t);
}
TEST(active_poller, modify_simple)
TEST_CASE("modify simple", "[active_poller]")
{
zmq::context_t context;
zmq::socket_t a{context, zmq::socket_type::push};
zmq::active_poller_t active_poller;
ASSERT_NO_THROW(
CHECK_NOTHROW(
active_poller.add(a, ZMQ_POLLIN, zmq::active_poller_t::handler_t{}));
ASSERT_NO_THROW(active_poller.modify(a, ZMQ_POLLIN | ZMQ_POLLOUT));
CHECK_NOTHROW(active_poller.modify(a, ZMQ_POLLIN | ZMQ_POLLOUT));
}
TEST(active_poller, poll_client_server)
TEST_CASE("poll client server", "[active_poller]")
{
// Setup server and client
server_client_setup s;
// Setup active_poller
zmq::active_poller_t active_poller;
ASSERT_NO_THROW(active_poller.add(s.server, ZMQ_POLLIN, s.handler));
CHECK_NOTHROW(active_poller.add(s.server, ZMQ_POLLIN, s.handler));
// client sends message
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
// wait for message and verify events
ASSERT_NO_THROW(active_poller.wait(std::chrono::milliseconds{500}));
ASSERT_EQ(s.events, ZMQ_POLLIN);
CHECK_NOTHROW(active_poller.wait(std::chrono::milliseconds{500}));
CHECK(s.events == ZMQ_POLLIN);
// Modify server socket with pollout flag
ASSERT_NO_THROW(active_poller.modify(s.server, ZMQ_POLLIN | ZMQ_POLLOUT));
ASSERT_EQ(1, active_poller.wait(std::chrono::milliseconds{500}));
ASSERT_EQ(s.events, ZMQ_POLLIN | ZMQ_POLLOUT);
CHECK_NOTHROW(active_poller.modify(s.server, ZMQ_POLLIN | ZMQ_POLLOUT));
CHECK(1 == active_poller.wait(std::chrono::milliseconds{500}));
CHECK(s.events == (ZMQ_POLLIN | ZMQ_POLLOUT));
}
TEST(active_poller, wait_one_return)
TEST_CASE("wait one return", "[active_poller]")
{
// Setup server and client
server_client_setup s;
@ -311,70 +312,70 @@ TEST(active_poller, wait_one_return)
// Setup active_poller
zmq::active_poller_t active_poller;
ASSERT_NO_THROW(
CHECK_NOTHROW(
active_poller.add(s.server, ZMQ_POLLIN, [&count](short) { ++count; }));
// client sends message
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
// wait for message and verify events
ASSERT_EQ(1, active_poller.wait(std::chrono::milliseconds{500}));
ASSERT_EQ(1u, count);
CHECK(1 == active_poller.wait(std::chrono::milliseconds{500}));
CHECK(1u == count);
}
TEST(active_poller, wait_on_move_constructed_active_poller)
TEST_CASE("wait on move constructed active_poller", "[active_poller]")
{
server_client_setup s;
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
zmq::active_poller_t a;
zmq::active_poller_t::handler_t handler;
ASSERT_NO_THROW(a.add(s.server, ZMQ_POLLIN, handler));
CHECK_NOTHROW(a.add(s.server, ZMQ_POLLIN, handler));
zmq::active_poller_t b{std::move(a)};
ASSERT_EQ(1u, b.size());
CHECK(1u == b.size());
/// \todo the actual error code should be checked
ASSERT_THROW(a.wait(std::chrono::milliseconds{10}), zmq::error_t);
ASSERT_TRUE(b.wait(std::chrono::milliseconds{-1}));
CHECK_THROWS_AS(a.wait(std::chrono::milliseconds{10}), zmq::error_t);
CHECK(b.wait(std::chrono::milliseconds{-1}));
}
TEST(active_poller, wait_on_move_assigned_active_poller)
TEST_CASE("wait on move assigned active_poller", "[active_poller]")
{
server_client_setup s;
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
zmq::active_poller_t a;
zmq::active_poller_t::handler_t handler;
ASSERT_NO_THROW(a.add(s.server, ZMQ_POLLIN, handler));
CHECK_NOTHROW(a.add(s.server, ZMQ_POLLIN, handler));
zmq::active_poller_t b;
b = {std::move(a)};
ASSERT_EQ(1u, b.size());
CHECK(1u == b.size());
/// \todo the actual error code should be checked
ASSERT_THROW(a.wait(std::chrono::milliseconds{10}), zmq::error_t);
ASSERT_TRUE(b.wait(std::chrono::milliseconds{-1}));
CHECK_THROWS_AS(a.wait(std::chrono::milliseconds{10}), zmq::error_t);
CHECK(b.wait(std::chrono::milliseconds{-1}));
}
TEST(active_poller, received_on_move_constructed_active_poller)
TEST_CASE("received on move constructed active_poller", "[active_poller]")
{
// Setup server and client
server_client_setup s;
int count = 0;
// Setup active_poller a
zmq::active_poller_t a;
ASSERT_NO_THROW(a.add(s.server, ZMQ_POLLIN, [&count](short) { ++count; }));
CHECK_NOTHROW(a.add(s.server, ZMQ_POLLIN, [&count](short) { ++count; }));
// client sends message
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
// wait for message and verify it is received
ASSERT_EQ(1, a.wait(std::chrono::milliseconds{500}));
ASSERT_EQ(1u, count);
CHECK(1 == a.wait(std::chrono::milliseconds{500}));
CHECK(1u == count);
// Move construct active_poller b
zmq::active_poller_t b{std::move(a)};
// client sends message again
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
// wait for message and verify it is received
ASSERT_EQ(1, b.wait(std::chrono::milliseconds{500}));
ASSERT_EQ(2u, count);
CHECK(1 == b.wait(std::chrono::milliseconds{500}));
CHECK(2u == count);
}
TEST(active_poller, remove_from_handler)
TEST_CASE("remove from handler", "[active_poller]")
{
constexpr auto ITER_NO = 10;
@ -387,18 +388,18 @@ TEST(active_poller, remove_from_handler)
zmq::active_poller_t active_poller;
int count = 0;
for (auto i = 0; i < ITER_NO; ++i) {
ASSERT_NO_THROW(
CHECK_NOTHROW(
active_poller.add(setup_list[i].server, ZMQ_POLLIN, [&, i](short events) {
ASSERT_EQ(events, ZMQ_POLLIN);
CHECK(events == ZMQ_POLLIN);
active_poller.remove(setup_list[ITER_NO - i - 1].server);
ASSERT_EQ(ITER_NO - i - 1, active_poller.size());
CHECK((ITER_NO - i - 1) == active_poller.size());
}));
++count;
}
ASSERT_EQ(ITER_NO, active_poller.size());
CHECK(ITER_NO == active_poller.size());
// Clients send messages
for (auto &s : setup_list) {
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
}
// Wait for all servers to receive a message
@ -408,8 +409,8 @@ TEST(active_poller, remove_from_handler)
}
// Fire all handlers in one wait
ASSERT_EQ(ITER_NO, active_poller.wait(std::chrono::milliseconds{-1}));
ASSERT_EQ(ITER_NO, count);
CHECK(ITER_NO == active_poller.wait(std::chrono::milliseconds{-1}));
CHECK(ITER_NO == count);
}
#endif

16
tests/cmake/catch.cmake Normal file
View File

@ -0,0 +1,16 @@
include(ExternalProject)
ExternalProject_Add(
catch
PREFIX ${CMAKE_BINARY_DIR}/catch
URL "https://raw.githubusercontent.com/catchorg/Catch2/Catch1.x/single_include/catch.hpp"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
DOWNLOAD_NO_EXTRACT ON
)
# Expose variable CATCH_INCLUDE_DIR to parent scope
ExternalProject_Get_Property(catch DOWNLOAD_DIR)
set(CATCH_INCLUDE_DIR ${DOWNLOAD_DIR} CACHE INTERNAL "Path to include catch")

View File

@ -1,20 +0,0 @@
# code copied from https://crascit.com/2015/07/25/cmake-gtest/
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(
googletest
SOURCE_DIR "@GOOGLETEST_DOWNLOAD_ROOT@/googletest-src"
BINARY_DIR "@GOOGLETEST_DOWNLOAD_ROOT@/googletest-build"
GIT_REPOSITORY
https://github.com/google/googletest.git
GIT_TAG
release-1.8.0
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)

View File

@ -1,38 +0,0 @@
# the following code to fetch googletest
# is inspired by and adapted after https://crascit.com/2015/07/25/cmake-gtest/
# download and unpack googletest at configure time
macro(fetch_googletest _download_module_path _download_root)
set(GOOGLETEST_DOWNLOAD_ROOT ${_download_root})
configure_file(
${_download_module_path}/googletest-download.cmake
${_download_root}/CMakeLists.txt
@ONLY
)
unset(GOOGLETEST_DOWNLOAD_ROOT)
execute_process(
COMMAND
"${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" .
WORKING_DIRECTORY
${_download_root}
)
execute_process(
COMMAND
"${CMAKE_COMMAND}" --build .
WORKING_DIRECTORY
${_download_root}
)
if (MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /D_SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING")
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
endif()
# adds the targers: gtest, gtest_main, gmock, gmock_main
add_subdirectory(
${_download_root}/googletest-src
${_download_root}/googletest-build
EXCLUDE_FROM_ALL
)
endmacro()

View File

@ -1,15 +1,14 @@
#include <gtest/gtest.h>
#include <catch.hpp>
#include <zmq.hpp>
TEST(context, create_default_destroy)
TEST_CASE("context construct default and destroy", "[context]")
{
zmq::context_t context;
}
TEST(context, create_close)
TEST_CASE("context create, close and destroy", "[context]")
{
zmq::context_t context;
context.close();
ASSERT_EQ(NULL, (void *) context);
CHECK(NULL == (void *) context);
}

View File

@ -1,7 +0,0 @@
#include "gtest/gtest.h"
int main(int argc, char **argv)
{
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}

View File

@ -1,4 +1,5 @@
#include <gtest/gtest.h>
#define CATCH_CONFIG_MAIN
#include <catch.hpp>
#include <zmq.hpp>
#if defined(ZMQ_CPP11)
@ -8,129 +9,131 @@ static_assert(!std::is_copy_assignable<zmq::message_t>::value,
"message_t should not be copy-assignable");
#endif
TEST(message, constructor_default)
TEST_CASE("message default constructed", "[message]")
{
const zmq::message_t message;
ASSERT_EQ(0u, message.size());
CHECK(0u == message.size());
}
namespace {
const char *const data = "Hi";
}
TEST(message, constructor_iterators)
TEST_CASE("message constructor with iterators", "[message]")
{
const std::string hi(data);
const zmq::message_t hi_msg(hi.begin(), hi.end());
ASSERT_EQ(2u, hi_msg.size());
ASSERT_EQ(0, memcmp(data, hi_msg.data(), 2));
CHECK(2u == hi_msg.size());
CHECK(0 == memcmp(data, hi_msg.data(), 2));
}
TEST(message, constructor_pointer_size)
TEST_CASE("message constructor with buffer and size", "[message]")
{
const std::string hi(data);
const zmq::message_t hi_msg(hi.data(), hi.size());
ASSERT_EQ(2u, hi_msg.size());
ASSERT_EQ(0, memcmp(data, hi_msg.data(), 2));
CHECK(2u == hi_msg.size());
CHECK(0 == memcmp(data, hi_msg.data(), 2));
}
TEST(message, constructor_char_array)
TEST_CASE("message constructor with char array", "[message]")
{
const zmq::message_t hi_msg(data, strlen(data));
ASSERT_EQ(2u, hi_msg.size());
ASSERT_EQ(0, memcmp(data, hi_msg.data(), 2));
CHECK(2u == hi_msg.size());
CHECK(0 == memcmp(data, hi_msg.data(), 2));
}
#if defined(ZMQ_BUILD_DRAFT_API) && defined(ZMQ_CPP11)
TEST(message, constructor_container)
TEST_CASE("message constructor with container", "[message]")
{
const std::string hi(data);
zmq::message_t hi_msg(hi);
ASSERT_EQ(2u, hi_msg.size());
ASSERT_EQ(0, memcmp(data, hi_msg.data(), 2));
CHECK(2u == hi_msg.size());
CHECK(0 == memcmp(data, hi_msg.data(), 2));
}
#endif
#ifdef ZMQ_HAS_RVALUE_REFS
TEST(message, constructor_move)
TEST_CASE("message move constructor", "[message]")
{
zmq::message_t hi_msg(zmq::message_t(data, strlen(data)));
}
TEST(message, assign_move_empty_before)
TEST_CASE("message assign move empty before", "[message]")
{
zmq::message_t hi_msg;
hi_msg = zmq::message_t(data, strlen(data));
ASSERT_EQ(2u, hi_msg.size());
ASSERT_EQ(0, memcmp(data, hi_msg.data(), 2));
CHECK(2u == hi_msg.size());
CHECK(0 == memcmp(data, hi_msg.data(), 2));
}
TEST(message, assign_move_empty_after)
TEST_CASE("message assign move empty after", "[message]")
{
zmq::message_t hi_msg(data, strlen(data));
hi_msg = zmq::message_t();
ASSERT_EQ(0u, hi_msg.size());
CHECK(0u == hi_msg.size());
}
TEST(message, assign_move_empty_before_and_after)
TEST_CASE("message assign move empty before and after", "[message]")
{
zmq::message_t hi_msg;
hi_msg = zmq::message_t();
ASSERT_EQ(0u, hi_msg.size());
CHECK(0u == hi_msg.size());
}
#endif
TEST(message, equality_self)
TEST_CASE("message equality self", "[message]")
{
const zmq::message_t hi_msg(data, strlen(data));
ASSERT_EQ(hi_msg, hi_msg);
CHECK(hi_msg == hi_msg);
}
TEST(message, equality_equal)
TEST_CASE("message equality equal", "[message]")
{
const zmq::message_t hi_msg_a(data, strlen(data));
const zmq::message_t hi_msg_b(data, strlen(data));
ASSERT_EQ(hi_msg_a, hi_msg_b);
CHECK(hi_msg_a == hi_msg_b);
}
TEST(message, equality_equal_empty)
TEST_CASE("message equality equal empty", "[message]")
{
const zmq::message_t msg_a;
const zmq::message_t msg_b;
ASSERT_EQ(msg_a, msg_b);
CHECK(msg_a == msg_b);
}
TEST(message, equality_non_equal)
TEST_CASE("message equality non equal", "[message]")
{
const zmq::message_t msg_a("Hi", 2);
const zmq::message_t msg_b("Hello", 5);
ASSERT_NE(msg_a, msg_b);
CHECK(msg_a != msg_b);
}
TEST(message, equality_non_equal_rhs_empty)
TEST_CASE("message equality non equal rhs empty", "[message]")
{
const zmq::message_t msg_a("Hi", 2);
const zmq::message_t msg_b;
ASSERT_NE(msg_a, msg_b);
CHECK(msg_a != msg_b);
}
TEST(message, equality_non_equal_lhs_empty)
TEST_CASE("message equality non equal lhs empty", "[message]")
{
const zmq::message_t msg_a;
const zmq::message_t msg_b("Hi", 2);
ASSERT_NE(msg_a, msg_b);
CHECK(msg_a != msg_b);
}
#if defined(ZMQ_BUILD_DRAFT_API) && ZMQ_VERSION >= ZMQ_MAKE_VERSION(4, 2, 0)
TEST(message, routing_id_persists)
TEST_CASE("message routing id persists", "[message]")
{
zmq::message_t msg;
msg.set_routing_id(123);
ASSERT_EQ(123u, msg.routing_id());
CHECK(123u == msg.routing_id());
}
TEST(message, group_persists)
TEST_CASE("message group persists", "[message]")
{
zmq::message_t msg;
msg.set_group("mygroup");
ASSERT_STREQ("mygroup", msg.group());
CHECK(std::string(msg.group()) == "mygroup");
}
#endif

View File

@ -1,26 +1,39 @@
#include "testutil.hpp"
#include <gmock/gmock.h>
#ifdef ZMQ_CPP11
#include <thread>
#include <mutex>
#include <condition_variable>
#endif
class mock_monitor_t : public zmq::monitor_t
{
public:
MOCK_METHOD2(on_event_connect_delayed, void(const zmq_event_t &, const char *));
MOCK_METHOD2(on_event_connected, void(const zmq_event_t &, const char *));
void on_event_connect_delayed(const zmq_event_t &, const char *) ZMQ_OVERRIDE
{
++connect_delayed;
++total;
}
void on_event_connected(const zmq_event_t &, const char *) ZMQ_OVERRIDE
{
++connected;
++total;
}
int total{0};
int connect_delayed{0};
int connected{0};
};
TEST(monitor, create_destroy)
#endif
TEST_CASE("monitor create destroy", "[monitor]")
{
zmq::monitor_t monitor;
}
#if defined(ZMQ_CPP11)
TEST(monitor, init_check)
TEST_CASE("monitor init event count", "[monitor]")
{
common_server_client_setup s{false};
mock_monitor_t monitor;
@ -31,41 +44,48 @@ TEST(monitor, init_check)
++event_count;
};
EXPECT_CALL(monitor, on_event_connect_delayed(testing::_, testing::_))
.Times(1)
.WillOnce(testing::Invoke(count_event));
EXPECT_CALL(monitor, on_event_connected(testing::_, testing::_))
.Times(1)
.WillOnce(testing::Invoke(count_event));
monitor.init(s.client, "inproc://foo");
ASSERT_FALSE(monitor.check_event(0));
CHECK_FALSE(monitor.check_event(0));
s.init();
while (monitor.check_event(100) && event_count < expected_event_count) {
while (monitor.check_event(100) && monitor.total < expected_event_count) {
}
CHECK(monitor.connect_delayed == 1);
CHECK(monitor.connected == 1);
}
TEST(monitor, init_abort)
TEST_CASE("monitor init abort", "[monitor]")
{
class mock_monitor : public mock_monitor_t
{
public:
mock_monitor(std::function<void(void)> handle_connected)
: handle_connected{std::move(handle_connected)}
{}
void on_event_connected(const zmq_event_t &e, const char *m) ZMQ_OVERRIDE
{
mock_monitor_t::on_event_connected(e, m);
handle_connected();
}
std::function<void(void)> handle_connected;
};
common_server_client_setup s(false);
mock_monitor_t monitor;
monitor.init(s.client, "inproc://foo");
std::mutex mutex;
std::condition_variable cond_var;
bool done{false};
EXPECT_CALL(monitor, on_event_connect_delayed(testing::_, testing::_))
.Times(1);
EXPECT_CALL(monitor, on_event_connected(testing::_, testing::_))
.Times(1)
.WillOnce(testing::Invoke([&](const zmq_event_t &, const char *) {
mock_monitor monitor([&]() {
std::lock_guard<std::mutex> lock(mutex);
done = true;
cond_var.notify_one();
}));
});
monitor.init(s.client, "inproc://foo");
auto thread = std::thread([&monitor] {
while (monitor.check_event(-1)) {
@ -75,10 +95,11 @@ TEST(monitor, init_abort)
s.init();
{
std::unique_lock<std::mutex> lock(mutex);
EXPECT_TRUE(cond_var.wait_for(lock, std::chrono::seconds(1),
CHECK(cond_var.wait_for(lock, std::chrono::seconds(1),
[&done] { return done; }));
}
CHECK(monitor.connect_delayed == 1);
CHECK(monitor.connected == 1);
monitor.abort();
thread.join();
}

View File

@ -1,10 +1,10 @@
#include <gtest/gtest.h>
#include <catch.hpp>
#include <zmq_addon.hpp>
#ifdef ZMQ_HAS_RVALUE_REFS
/// \todo split this up into separate test cases
///
TEST(multipart, legacy_test)
TEST_CASE("multipart legacy test", "[multipart]")
{
using namespace zmq;

View File

@ -5,7 +5,7 @@
#include <array>
#include <memory>
TEST(poller, create_destroy)
TEST_CASE("poller create destroy", "[poller]")
{
zmq::poller_t<> poller;
}
@ -15,20 +15,20 @@ static_assert(!std::is_copy_constructible<zmq::poller_t<>>::value,
static_assert(!std::is_copy_assignable<zmq::poller_t<>>::value,
"poller_t should not be copy-assignable");
TEST(poller, move_construct_empty)
TEST_CASE("poller move construct empty", "[poller]")
{
zmq::poller_t<> a;
zmq::poller_t<> b = std::move(a);
}
TEST(poller, move_assign_empty)
TEST_CASE("poller move assign empty", "[poller]")
{
zmq::poller_t<> a;
zmq::poller_t<> b;
b = std::move(a);
}
TEST(poller, move_construct_non_empty)
TEST_CASE("poller move construct non empty", "[poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
@ -38,7 +38,7 @@ TEST(poller, move_construct_non_empty)
zmq::poller_t<> b = std::move(a);
}
TEST(poller, move_assign_non_empty)
TEST_CASE("poller move assign non empty", "[poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
@ -49,24 +49,24 @@ TEST(poller, move_assign_non_empty)
b = std::move(a);
}
TEST(poller, add_nullptr)
TEST_CASE("poller add nullptr", "[poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::poller_t<> poller;
ASSERT_NO_THROW(poller.add(socket, ZMQ_POLLIN, nullptr));
CHECK_NOTHROW(poller.add(socket, ZMQ_POLLIN, nullptr));
}
TEST(poller, add_non_nullptr)
TEST_CASE("poller add non nullptr", "[poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::poller_t<> poller;
int i;
ASSERT_NO_THROW(poller.add(socket, ZMQ_POLLIN, &i));
CHECK_NOTHROW(poller.add(socket, ZMQ_POLLIN, &i));
}
TEST(poller, add_handler_invalid_events_type)
TEST_CASE("poller add handler invalid events type", "[poller]")
{
/// \todo is it good that this is accepted? should probably already be
/// checked by zmq_poller_add/modify in libzmq:
@ -75,195 +75,196 @@ TEST(poller, add_handler_invalid_events_type)
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::poller_t<> poller;
short invalid_events_type = 2 << 10;
ASSERT_NO_THROW(poller.add(socket, invalid_events_type, nullptr));
CHECK_NOTHROW(poller.add(socket, invalid_events_type, nullptr));
}
TEST(poller, add_handler_twice_throws)
TEST_CASE("poller add handler twice throws", "[poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::poller_t<> poller;
poller.add(socket, ZMQ_POLLIN, nullptr);
/// \todo the actual error code should be checked
ASSERT_THROW(poller.add(socket, ZMQ_POLLIN, nullptr), zmq::error_t);
CHECK_THROWS_AS(poller.add(socket, ZMQ_POLLIN, nullptr), zmq::error_t);
}
TEST(poller, wait_with_no_handlers_throws)
TEST_CASE("poller wait with no handlers throws", "[poller]")
{
zmq::poller_t<> poller;
std::vector<zmq_poller_event_t> events;
/// \todo the actual error code should be checked
ASSERT_THROW(poller.wait_all(events, std::chrono::milliseconds{10}),
CHECK_THROWS_AS(poller.wait_all(events, std::chrono::milliseconds{10}),
zmq::error_t);
}
TEST(poller, remove_unregistered_throws)
TEST_CASE("poller remove unregistered throws", "[poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::poller_t<> poller;
/// \todo the actual error code should be checked
ASSERT_THROW(poller.remove(socket), zmq::error_t);
CHECK_THROWS_AS(poller.remove(socket), zmq::error_t);
}
TEST(poller, remove_registered_empty)
TEST_CASE("poller remove registered empty", "[poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::poller_t<> poller;
poller.add(socket, ZMQ_POLLIN, nullptr);
ASSERT_NO_THROW(poller.remove(socket));
CHECK_NOTHROW(poller.remove(socket));
}
TEST(poller, remove_registered_non_empty)
TEST_CASE("poller remove registered non empty", "[poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::poller_t<> poller;
poller.add(socket, ZMQ_POLLIN, nullptr);
ASSERT_NO_THROW(poller.remove(socket));
int empty{};
poller.add(socket, ZMQ_POLLIN, &empty);
CHECK_NOTHROW(poller.remove(socket));
}
TEST(poller, poll_basic)
TEST_CASE("poller poll basic", "[poller]")
{
common_server_client_setup s;
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
zmq::poller_t<int> poller;
std::vector<zmq_poller_event_t> events{1};
int i = 0;
ASSERT_NO_THROW(poller.add(s.server, ZMQ_POLLIN, &i));
ASSERT_EQ(1, poller.wait_all(events, std::chrono::milliseconds{-1}));
ASSERT_EQ(s.server, events[0].socket);
ASSERT_EQ(&i, events[0].user_data);
CHECK_NOTHROW(poller.add(s.server, ZMQ_POLLIN, &i));
CHECK(1 == poller.wait_all(events, std::chrono::milliseconds{-1}));
CHECK(s.server == events[0].socket);
CHECK(&i == events[0].user_data);
}
TEST(poller, add_invalid_socket_throws)
TEST_CASE("poller add invalid socket throws", "[poller]")
{
zmq::context_t context;
zmq::poller_t<> poller;
zmq::socket_t a{context, zmq::socket_type::router};
zmq::socket_t b{std::move(a)};
ASSERT_THROW(poller.add(a, ZMQ_POLLIN, nullptr), zmq::error_t);
CHECK_THROWS_AS(poller.add(a, ZMQ_POLLIN, nullptr), zmq::error_t);
}
TEST(poller, remove_invalid_socket_throws)
TEST_CASE("poller remove invalid socket throws", "[poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::router};
zmq::poller_t<> poller;
ASSERT_NO_THROW(poller.add(socket, ZMQ_POLLIN, nullptr));
CHECK_NOTHROW(poller.add(socket, ZMQ_POLLIN, nullptr));
std::vector<zmq::socket_t> sockets;
sockets.emplace_back(std::move(socket));
ASSERT_THROW(poller.remove(socket), zmq::error_t);
ASSERT_NO_THROW(poller.remove(sockets[0]));
CHECK_THROWS_AS(poller.remove(socket), zmq::error_t);
CHECK_NOTHROW(poller.remove(sockets[0]));
}
TEST(poller, modify_empty_throws)
TEST_CASE("poller modify empty throws", "[poller]")
{
zmq::context_t context;
zmq::socket_t socket{context, zmq::socket_type::push};
zmq::poller_t<> poller;
ASSERT_THROW(poller.modify(socket, ZMQ_POLLIN), zmq::error_t);
CHECK_THROWS_AS(poller.modify(socket, ZMQ_POLLIN), zmq::error_t);
}
TEST(poller, modify_invalid_socket_throws)
TEST_CASE("poller modify invalid socket throws", "[poller]")
{
zmq::context_t context;
zmq::socket_t a{context, zmq::socket_type::push};
zmq::socket_t b{std::move(a)};
zmq::poller_t<> poller;
ASSERT_THROW(poller.modify(a, ZMQ_POLLIN), zmq::error_t);
CHECK_THROWS_AS(poller.modify(a, ZMQ_POLLIN), zmq::error_t);
}
TEST(poller, modify_not_added_throws)
TEST_CASE("poller modify not added throws", "[poller]")
{
zmq::context_t context;
zmq::socket_t a{context, zmq::socket_type::push};
zmq::socket_t b{context, zmq::socket_type::push};
zmq::poller_t<> poller;
ASSERT_NO_THROW(poller.add(a, ZMQ_POLLIN, nullptr));
ASSERT_THROW(poller.modify(b, ZMQ_POLLIN), zmq::error_t);
CHECK_NOTHROW(poller.add(a, ZMQ_POLLIN, nullptr));
CHECK_THROWS_AS(poller.modify(b, ZMQ_POLLIN), zmq::error_t);
}
TEST(poller, modify_simple)
TEST_CASE("poller modify simple", "[poller]")
{
zmq::context_t context;
zmq::socket_t a{context, zmq::socket_type::push};
zmq::poller_t<> poller;
ASSERT_NO_THROW(poller.add(a, ZMQ_POLLIN, nullptr));
ASSERT_NO_THROW(poller.modify(a, ZMQ_POLLIN | ZMQ_POLLOUT));
CHECK_NOTHROW(poller.add(a, ZMQ_POLLIN, nullptr));
CHECK_NOTHROW(poller.modify(a, ZMQ_POLLIN | ZMQ_POLLOUT));
}
TEST(poller, poll_client_server)
TEST_CASE("poller poll client server", "[poller]")
{
// Setup server and client
common_server_client_setup s;
// Setup poller
zmq::poller_t<> poller;
ASSERT_NO_THROW(poller.add(s.server, ZMQ_POLLIN, s.server));
CHECK_NOTHROW(poller.add(s.server, ZMQ_POLLIN, s.server));
// client sends message
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
// wait for message and verify events
std::vector<zmq_poller_event_t> events(1);
ASSERT_EQ(1, poller.wait_all(events, std::chrono::milliseconds{500}));
ASSERT_EQ(ZMQ_POLLIN, events[0].events);
CHECK(1 == poller.wait_all(events, std::chrono::milliseconds{500}));
CHECK(ZMQ_POLLIN == events[0].events);
// Modify server socket with pollout flag
ASSERT_NO_THROW(poller.modify(s.server, ZMQ_POLLIN | ZMQ_POLLOUT));
ASSERT_EQ(1, poller.wait_all(events, std::chrono::milliseconds{500}));
ASSERT_EQ(ZMQ_POLLIN | ZMQ_POLLOUT, events[0].events);
CHECK_NOTHROW(poller.modify(s.server, ZMQ_POLLIN | ZMQ_POLLOUT));
CHECK(1 == poller.wait_all(events, std::chrono::milliseconds{500}));
CHECK((ZMQ_POLLIN | ZMQ_POLLOUT) == events[0].events);
}
TEST(poller, wait_one_return)
TEST_CASE("poller wait one return", "[poller]")
{
// Setup server and client
common_server_client_setup s;
// Setup poller
zmq::poller_t<> poller;
ASSERT_NO_THROW(poller.add(s.server, ZMQ_POLLIN, nullptr));
CHECK_NOTHROW(poller.add(s.server, ZMQ_POLLIN, nullptr));
// client sends message
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
// wait for message and verify events
std::vector<zmq_poller_event_t> events(1);
ASSERT_EQ(1, poller.wait_all(events, std::chrono::milliseconds{500}));
CHECK(1 == poller.wait_all(events, std::chrono::milliseconds{500}));
}
TEST(poller, wait_on_move_constructed_poller)
TEST_CASE("poller wait on move constructed", "[poller]")
{
common_server_client_setup s;
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
zmq::poller_t<> a;
ASSERT_NO_THROW(a.add(s.server, ZMQ_POLLIN, nullptr));
CHECK_NOTHROW(a.add(s.server, ZMQ_POLLIN, nullptr));
zmq::poller_t<> b{std::move(a)};
std::vector<zmq_poller_event_t> events(1);
/// \todo the actual error code should be checked
ASSERT_THROW(a.wait_all(events, std::chrono::milliseconds{10}), zmq::error_t);
ASSERT_EQ(1, b.wait_all(events, std::chrono::milliseconds{-1}));
CHECK_THROWS_AS(a.wait_all(events, std::chrono::milliseconds{10}), zmq::error_t);
CHECK(1 == b.wait_all(events, std::chrono::milliseconds{-1}));
}
TEST(poller, wait_on_move_assigned_poller)
TEST_CASE("poller wait on move assigned", "[poller]")
{
common_server_client_setup s;
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
zmq::poller_t<> a;
ASSERT_NO_THROW(a.add(s.server, ZMQ_POLLIN, nullptr));
CHECK_NOTHROW(a.add(s.server, ZMQ_POLLIN, nullptr));
zmq::poller_t<> b;
b = {std::move(a)};
/// \todo the actual error code should be checked
/// \todo the TEST_CASE error code should be checked
std::vector<zmq_poller_event_t> events(1);
ASSERT_THROW(a.wait_all(events, std::chrono::milliseconds{10}), zmq::error_t);
ASSERT_EQ(1, b.wait_all(events, std::chrono::milliseconds{-1}));
CHECK_THROWS_AS(a.wait_all(events, std::chrono::milliseconds{10}), zmq::error_t);
CHECK(1 == b.wait_all(events, std::chrono::milliseconds{-1}));
}
TEST(poller, remove_from_handler)
TEST_CASE("poller remove from handler", "[poller]")
{
constexpr auto ITER_NO = 10;
@ -275,11 +276,11 @@ TEST(poller, remove_from_handler)
// Setup poller
zmq::poller_t<> poller;
for (auto i = 0; i < ITER_NO; ++i) {
ASSERT_NO_THROW(poller.add(setup_list[i].server, ZMQ_POLLIN, nullptr));
CHECK_NOTHROW(poller.add(setup_list[i].server, ZMQ_POLLIN, nullptr));
}
// Clients send messages
for (auto &s : setup_list) {
ASSERT_NO_THROW(s.client.send(zmq::message_t{"Hi"}));
CHECK_NOTHROW(s.client.send(zmq::message_t{"Hi"}));
}
// Wait for all servers to receive a message
@ -290,7 +291,7 @@ TEST(poller, remove_from_handler)
// Fire all handlers in one wait
std::vector<zmq_poller_event_t> events(ITER_NO);
ASSERT_EQ(ITER_NO, poller.wait_all(events, std::chrono::milliseconds{-1}));
CHECK(ITER_NO == poller.wait_all(events, std::chrono::milliseconds{-1}));
}
#endif

View File

@ -1,29 +1,29 @@
#include <gtest/gtest.h>
#include <catch.hpp>
#include <zmq.hpp>
TEST(socket, create_destroy)
TEST_CASE("socket create destroy", "[socket]")
{
zmq::context_t context;
zmq::socket_t socket(context, ZMQ_ROUTER);
}
#ifdef ZMQ_CPP11
TEST(socket, create_by_enum_destroy)
TEST_CASE("socket create by enum and destroy", "[socket]")
{
zmq::context_t context;
zmq::socket_t socket(context, zmq::socket_type::router);
}
#endif
TEST(socket, send_receive_const_buffer)
TEST_CASE("socket sends and receives const buffer", "[socket]")
{
zmq::context_t context;
zmq::socket_t sender(context, ZMQ_PAIR);
zmq::socket_t receiver(context, ZMQ_PAIR);
receiver.bind("inproc://test");
sender.connect("inproc://test");
ASSERT_EQ(2, sender.send("Hi", 2));
CHECK(2 == sender.send("Hi", 2));
char buf[2];
ASSERT_EQ(2, receiver.recv(buf, 2));
ASSERT_EQ(0, memcmp(buf, "Hi", 2));
CHECK(2 == receiver.recv(buf, 2));
CHECK(0 == memcmp(buf, "Hi", 2));
}

View File

@ -1,6 +1,6 @@
#pragma once
#include <gtest/gtest.h>
#include <catch.hpp>
#include <zmq.hpp>
#if defined(ZMQ_CPP11)
@ -18,12 +18,12 @@ class loopback_ip4_binder
// and constructor/destructor are not.
void bind(zmq::socket_t &socket)
{
ASSERT_NO_THROW(socket.bind("tcp://127.0.0.1:*"));
REQUIRE_NOTHROW(socket.bind("tcp://127.0.0.1:*"));
std::array<char, 100> endpoint{};
size_t endpoint_size = endpoint.size();
ASSERT_NO_THROW(
REQUIRE_NOTHROW(
socket.getsockopt(ZMQ_LAST_ENDPOINT, endpoint.data(), &endpoint_size));
ASSERT_TRUE(endpoint_size < endpoint.size());
REQUIRE(endpoint_size < endpoint.size());
endpoint_ = std::string{endpoint.data()};
}
std::string endpoint_;
@ -40,7 +40,7 @@ struct common_server_client_setup
void init()
{
endpoint = loopback_ip4_binder{server}.endpoint();
ASSERT_NO_THROW(client.connect(endpoint));
REQUIRE_NOTHROW(client.connect(endpoint));
}
zmq::context_t context;

View File

@ -34,18 +34,16 @@
#define ZMQ_DEPRECATED(msg) __attribute__((deprecated(msg)))
#endif
#if (__cplusplus >= 201103L)
#define ZMQ_CPP11
#define ZMQ_NOTHROW noexcept
#define ZMQ_EXPLICIT explicit
#elif (defined(_MSC_VER) && (_MSC_VER >= 1900))
#if (__cplusplus >= 201103L) || (defined(_MSC_VER) && (_MSC_VER >= 1900))
#define ZMQ_CPP11
#define ZMQ_NOTHROW noexcept
#define ZMQ_EXPLICIT explicit
#define ZMQ_OVERRIDE override
#else
#define ZMQ_CPP03
#define ZMQ_NOTHROW
#define ZMQ_EXPLICIT
#define ZMQ_OVERRIDE
#endif
#include <zmq.h>