2
0
mirror of https://github.com/boostorg/mqtt5.git synced 2026-01-19 04:22:11 +00:00

Mock timer and resolver in unit tests.

Summary:
* Removed all usage of real timers and resolvers in unit tests
* Moved most of the tests to test/unit folder
* cmake: split boost_mqtt5_tests into boost_mqtt5_unittests and boost_mqtt5_integrationtests

Reviewers: ivica

Reviewed By: ivica

Subscribers: miljen

Differential Revision: https://repo.mireo.local/D38186
This commit is contained in:
Bruno Iljazovic
2025-11-13 16:40:18 +01:00
parent d3fc7684eb
commit 6198b0e44a
47 changed files with 729 additions and 474 deletions

View File

@@ -142,6 +142,7 @@ jobs:
CXXFLAGS: ${{ matrix.cxxflags }} -Wall -Wextra
LDFLAGS: ${{ matrix.ldflags }}
CMAKE_BUILD_PARALLEL_LEVEL: 4
DEBIAN_FRONTEND: noninteractive
steps:
- name: Checkout
@@ -257,6 +258,7 @@ jobs:
env:
CXXFLAGS: ${{ matrix.cxxflags }} -Wall -Wextra
LDFLAGS: ${{ matrix.ldflags }}
DEBIAN_FRONTEND: noninteractive
steps:
- name: Checkout

View File

@@ -35,6 +35,7 @@ jobs:
CXXFLAGS: ${{ matrix.cxxflags }}
LDFLAGS: ${{ matrix.ldflags }}
CMAKE_BUILD_PARALLEL_LEVEL: 4
DEBIAN_FRONTEND: noninteractive
steps:
- name: Checkout

View File

@@ -91,7 +91,7 @@ private:
if (*_ihandler) {
auto h = std::move(*_ihandler);
auto ex = asio::get_associated_executor(h);
asio::require(ex, asio::execution::blocking.possibly)
(asio::require)(ex, asio::execution::blocking.possibly)
.execute([h = std::move(h)]() mutable {
std::move(h)(asio::error::operation_aborted);
});
@@ -160,7 +160,7 @@ public:
_waiting.pop_front();
if (!op) continue;
op.get_cancellation_slot().clear();
asio::require(_ex, asio::execution::blocking.never)
(asio::require)(_ex, asio::execution::blocking.never)
.execute([ex = _ex, op = std::move(op)]() mutable {
auto opex = asio::get_associated_executor(op, ex);
opex.execute(
@@ -178,7 +178,7 @@ private:
// The operation is equivalent to asio::post(_ex, op) but
// for some reason this form of execution is much faster.
void execute_op(queued_op_t op) {
asio::require(_ex, asio::execution::blocking.never)
(asio::require)(_ex, asio::execution::blocking.never)
.execute([ex = _ex, op = std::move(op)]() mutable {
auto opex = asio::get_associated_executor(op, ex);
opex.execute(

View File

@@ -13,7 +13,9 @@
#include <boost/mqtt5/detail/any_authenticator.hpp>
#include <chrono>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <cstdint>
#include <optional>
#include <string>
@@ -22,9 +24,6 @@ namespace boost::mqtt5::detail {
using byte_citer = std::string::const_iterator;
using time_stamp = std::chrono::time_point<std::chrono::steady_clock>;
using duration = time_stamp::duration;
struct credentials {
std::string client_id;
std::optional<std::string> username;
@@ -112,6 +111,16 @@ constexpr unsigned terminal = 0b100;
};
#ifdef BOOST_MQTT5_UNIT_TESTS
using timer_type = asio::basic_waitable_timer<BOOST_MQTT5_DETAIL_CLOCK_TYPE>;
using resolver_type = BOOST_MQTT5_DETAIL_RESOLVER_TYPE;
#else
using timer_type = asio::steady_timer;
using resolver_type = asio::ip::tcp::resolver;
#endif
using duration = timer_type::duration;
} // end namespace boost::mqtt5::detail
#endif // !BOOST_MQTT5_INTERNAL_TYPES_HPP

View File

@@ -204,8 +204,8 @@ private:
duration compute_read_timeout() const {
auto negotiated_ka = _svc.negotiated_keep_alive();
return negotiated_ka ?
std::chrono::milliseconds(3 * negotiated_ka * 1000 / 2) :
duration((std::numeric_limits<duration::rep>::max)());
duration(std::chrono::milliseconds(3 * negotiated_ka * 1000 / 2)) :
(duration::max)();
}
static bool valid_header(uint8_t control_byte) {

View File

@@ -20,7 +20,6 @@
#include <boost/asio/async_result.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/system/error_code.hpp>
#include <cstdint>
@@ -40,7 +39,7 @@ template <
>
class autoconnect_stream {
public:
using self_type = autoconnect_stream<StreamType, StreamContext, LoggerType>;
using self_type = autoconnect_stream;
using stream_type = StreamType;
using stream_context_type = StreamContext;
using logger_type = LoggerType;
@@ -50,7 +49,7 @@ private:
executor_type _stream_executor;
async_mutex _conn_mtx;
asio::steady_timer _read_timer, _connect_timer;
timer_type _read_timer, _connect_timer;
endpoints<logger_type> _endpoints;
stream_ptr _stream_ptr;

View File

@@ -266,8 +266,8 @@ private:
receive_channel _rec_channel;
asio::steady_timer _ping_timer;
asio::steady_timer _sentry_timer;
timer_type _ping_timer;
timer_type _sentry_timer;
client_service(const client_service& other) :
_executor(other._executor),

View File

@@ -10,8 +10,6 @@
#include <boost/mqtt5/types.hpp>
#include <boost/mqtt5/detail/internal_types.hpp>
#include <boost/mqtt5/impl/codecs/base_decoders.hpp>
#include <cstdint>
@@ -22,7 +20,7 @@
namespace boost::mqtt5::decoders {
using byte_citer = detail::byte_citer;
using byte_citer = std::string::const_iterator;
using fixed_header = std::tuple<
uint8_t, // control byte

View File

@@ -28,7 +28,6 @@
#include <boost/asio/error.hpp>
#include <boost/asio/experimental/parallel_group.hpp>
#include <boost/asio/prepend.hpp>
#include <boost/asio/steady_timer.hpp>
#include <cstdint>
#include <memory>
@@ -185,7 +184,7 @@ class terminal_disconnect_op {
static constexpr uint8_t seconds = 5;
std::shared_ptr<client_service> _svc_ptr;
std::unique_ptr<asio::steady_timer> _timer;
std::unique_ptr<timer_type> _timer;
using handler_type = Handler;
handler_type _handler;
@@ -196,7 +195,7 @@ public:
Handler&& handler
) :
_svc_ptr(std::move(svc_ptr)),
_timer(new asio::steady_timer(_svc_ptr->get_executor())),
_timer(new timer_type(_svc_ptr->get_executor())),
_handler(std::move(handler))
{}

View File

@@ -8,6 +8,7 @@
#ifndef BOOST_MQTT5_ENDPOINTS_HPP
#define BOOST_MQTT5_ENDPOINTS_HPP
#include <boost/mqtt5/detail/internal_types.hpp>
#include <boost/mqtt5/detail/log_invoke.hpp>
#include <boost/mqtt5/detail/internal_types.hpp>
@@ -141,8 +142,8 @@ template <typename LoggerType>
class endpoints {
using logger_type = LoggerType;
asio::ip::tcp::resolver _resolver;
asio::steady_timer& _connect_timer;
resolver_type _resolver;
timer_type& _connect_timer;
std::vector<authority_path> _servers;
@@ -156,7 +157,7 @@ class endpoints {
public:
template <typename Executor>
endpoints(
Executor ex, asio::steady_timer& timer,
Executor ex, timer_type& timer,
log_invoke<logger_type>& log
) :
_resolver(std::move(ex)), _connect_timer(timer),

View File

@@ -96,7 +96,7 @@ private:
auto negotiated_ka = _svc_ptr->negotiated_keep_alive();
return negotiated_ka ?
std::chrono::seconds(negotiated_ka) :
duration((std::numeric_limits<duration::rep>::max)());
(duration::max)();
}
void complete() {

View File

@@ -11,6 +11,7 @@
#include <boost/mqtt5/types.hpp>
#include <boost/mqtt5/detail/async_traits.hpp>
#include <boost/mqtt5/detail/internal_types.hpp>
#include <boost/mqtt5/impl/connect_op.hpp>

View File

@@ -10,36 +10,48 @@ project(boost_mqtt5_tests CXX)
file(GLOB integration_tests "integration/*.cpp")
file(GLOB unit_tests "unit/*.cpp")
add_executable(boost_mqtt5-tests src/run_tests.cpp ${integration_tests} ${unit_tests})
target_include_directories(boost_mqtt5-tests PRIVATE include)
target_compile_definitions(boost_mqtt5-tests PRIVATE BOOST_TEST_NO_MAIN=1)
add_executable(boost_mqtt5_unittests src/run_tests.cpp ${unit_tests})
add_executable(boost_mqtt5_integrationtests src/run_tests.cpp ${integration_tests})
if(BOOST_MQTT5_MAIN_PROJECT)
find_package(OpenSSL REQUIRED)
target_compile_definitions(boost_mqtt5-tests PRIVATE BOOST_MQTT5_EXTRA_DEPS=1)
target_link_libraries(
boost_mqtt5-tests PRIVATE
Boost::mqtt5
OpenSSL::SSL
)
else()
target_link_libraries(
boost_mqtt5-tests PRIVATE
Boost::mqtt5
Boost::included_unit_test_framework
)
# Follow the Boost convention: don't build test targets by default,
# and only when explicitly requested by building target tests
set_target_properties(boost_mqtt5-tests PROPERTIES EXCLUDE_FROM_ALL ON)
add_dependencies(tests boost_mqtt5-tests)
endif()
target_compile_definitions(boost_mqtt5_unittests PRIVATE BOOST_MQTT5_UNIT_TESTS=1)
foreach(BOOST_MQTT5_TEST boost_mqtt5_unittests boost_mqtt5_integrationtests)
target_include_directories(${BOOST_MQTT5_TEST} PRIVATE include)
target_compile_definitions(${BOOST_MQTT5_TEST} PRIVATE BOOST_TEST_NO_MAIN=1)
if(BOOST_MQTT5_MAIN_PROJECT)
target_compile_definitions(${BOOST_MQTT5_TEST} PRIVATE BOOST_MQTT5_EXTRA_DEPS=1)
target_link_libraries(
${BOOST_MQTT5_TEST} PRIVATE
Boost::mqtt5
OpenSSL::SSL
)
else()
target_link_libraries(
${BOOST_MQTT5_TEST} PRIVATE
Boost::mqtt5
Boost::included_unit_test_framework
)
# Follow the Boost convention: don't build test targets by default,
# and only when explicitly requested by building target tests
set_target_properties(${BOOST_MQTT5_TEST} PROPERTIES EXCLUDE_FROM_ALL ON)
endif()
endforeach()
include(CTest)
add_test(NAME boost_mqtt5-tests COMMAND boost_mqtt5-tests)
add_test(NAME boost_mqtt5_unittests COMMAND boost_mqtt5_unittests)
if (BOOST_MQTT5_PUBLIC_BROKER_TESTS)
set_property(TEST boost_mqtt5-tests PROPERTY ENVIRONMENT "BOOST_MQTT5_PUBLIC_BROKER_TESTS=1")
add_dependencies(tests boost_mqtt5_unittests)
if (BOOST_MQTT5_MAIN_PROJECT)
add_test(NAME boost_mqtt5_integrationtests COMMAND boost_mqtt5_integrationtests)
if (BOOST_MQTT5_PUBLIC_BROKER_TESTS)
set_property(TEST boost_mqtt5_integrationtests PROPERTY ENVIRONMENT "BOOST_MQTT5_PUBLIC_BROKER_TESTS=1")
endif()
endif()

View File

@@ -15,6 +15,7 @@ local requirements =
<define>BOOST_ALL_NO_LIB=1
<define>BOOST_ASIO_NO_DEPRECATED=1
<define>BOOST_TEST_NO_MAIN=1
<define>BOOST_MQTT5_UNIT_TESTS=1
<toolset>msvc:<cxxflags>"/bigobj"
<target-os>windows:<define>_WIN32_WINNT=0x0601
<library>/boost/test//included
@@ -25,5 +26,5 @@ run
[ glob "unit/*.cpp" ]
: requirements $(requirements)
<include>include
: target-name boost_mqtt5_tests
: target-name boost_mqtt5_unittests
;

View File

@@ -9,116 +9,64 @@
#define BOOST_MQTT5_TEST_DELAYED_OP_HPP
#include <boost/asio/append.hpp>
#include <boost/asio/bind_cancellation_slot.hpp>
#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/consign.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/prepend.hpp>
#include <boost/asio/recycling_allocator.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/type_traits/remove_cv_ref.hpp>
#include <chrono>
#include "test_timer.hpp"
namespace boost::mqtt5::test {
namespace asio = boost::asio;
using error_code = boost::system::error_code;
using time_stamp = std::chrono::time_point<std::chrono::steady_clock>;
using time_stamp = clock::time_point;
using duration = time_stamp::duration;
using rep = duration::rep;
template <typename ...BoundArgs>
class delayed_op {
struct on_timer {};
template <typename... BoundArgs>
struct delayed_op {
duration delay;
std::tuple<BoundArgs...> args;
std::unique_ptr<asio::steady_timer> _timer;
time_stamp::duration _delay;
asio::cancellation_slot _cancel_slot;
std::tuple<BoundArgs...> _args;
public:
template <typename Executor, typename ...Args>
delayed_op(
const Executor& ex, time_stamp::duration delay, Args&& ...args
) :
_timer(new asio::steady_timer(ex)), _delay(delay),
_args(std::move(args)...)
delayed_op(duration delay, BoundArgs... args)
: delay(delay), args(std::move(args)...)
{}
delayed_op(delayed_op&&) = default;
delayed_op(const delayed_op&) = delete;
delayed_op& operator=(delayed_op&&) = default;
delayed_op& operator=(const delayed_op&) = delete;
using allocator_type = asio::recycling_allocator<void>;
allocator_type get_allocator() const noexcept {
return allocator_type {};
}
using cancellation_slot_type = asio::cancellation_slot;
asio::cancellation_slot get_cancellation_slot() const noexcept {
return _cancel_slot;
}
using executor_type = asio::steady_timer::executor_type;
executor_type get_executor() const noexcept {
return _timer->get_executor();
}
template <typename CompletionHandler>
void perform(CompletionHandler&& handler) {
_cancel_slot = asio::get_associated_cancellation_slot(handler);
_timer->expires_after(_delay);
_timer->async_wait(
asio::prepend(std::move(*this), on_timer {}, std::move(handler))
);
}
template <typename CompletionHandler>
void operator()(on_timer, CompletionHandler&& h, error_code ec) {
// The timer places a handler into the cancellation slot
// and does not clear it. Therefore, we need to clear it explicitly
// to properly remove the corresponding cancellation signal
// in the test_broker.
get_cancellation_slot().clear();
auto bh = std::apply(
[h = std::move(h)](auto&&... args) mutable {
return asio::append(std::move(h), std::move(args)...);
},
_args
);
asio::dispatch(asio::prepend(std::move(bh), ec));
}
};
template <typename CompletionToken, typename ...BoundArgs>
template <typename CompletionToken, typename Executor, typename... BoundArgs>
decltype(auto) async_delay(
asio::cancellation_slot cancel_slot,
delayed_op<BoundArgs...>&& op,
const Executor& ex,
delayed_op<BoundArgs...> op,
CompletionToken&& token
) {
using Signature = void (error_code, boost::remove_cv_ref_t<BoundArgs>...);
auto initiation = [](
auto handler, asio::cancellation_slot cancel_slot,
delayed_op<BoundArgs...> op
) {
op.perform(
asio::bind_cancellation_slot(cancel_slot, std::move(handler))
auto initiation = [](auto handler, const Executor& ex, auto op) {
auto timer = std::make_unique<asio::basic_waitable_timer<clock>>(ex);
timer->expires_after(op.delay);
auto bound_handler = std::apply(
[h = std::move(handler)](auto&&... args) mutable {
return asio::append(std::move(h), std::move(args)...);
},
std::move(op.args)
);
timer->async_wait(
asio::consign(
[bh = std::move(bound_handler)](error_code ec) mutable {
asio::dispatch(asio::prepend(std::move(bh), ec));
}, std::move(timer)
)
);
};
return asio::async_initiate<CompletionToken, Signature>(
std::move(initiation), token, cancel_slot, std::move(op)
std::move(initiation), token, ex, std::move(op)
);
}
} // end namespace boost::mqtt5::test
#endif // BOOST_MQTT5_TEST_DELAYED_OP_HPP

View File

@@ -20,13 +20,13 @@
#include <type_traits>
#include <vector>
#include "test_common/delayed_op.hpp"
#include "delayed_op.hpp"
namespace boost::mqtt5::test {
using error_code = boost::system::error_code;
using time_stamp = std::chrono::time_point<std::chrono::steady_clock>;
using duration = time_stamp::duration;
using time_point = clock::time_point;
using duration = clock::duration;
class msg_exchange;
class broker_message;
@@ -57,10 +57,9 @@ public:
stream_message& operator=(stream_message&&) = default;
stream_message& operator=(const stream_message&) = delete;
template <typename Executor>
auto to_operation(const Executor& ex) {
auto to_operation() {
return delayed_op<error_code, std::vector<uint8_t>> {
ex, _after, _ec, std::move(_content)
_after, _ec, std::move(_content)
};
}
};
@@ -107,17 +106,15 @@ public:
template <typename ...Args>
broker_message& send(Args&& ...args);
template <typename Executor>
decltype(auto) write_completion(const Executor& ex) const {
return delayed_op<error_code>(ex, _complete_after, _write_ec);
decltype(auto) write_completion() const {
return delayed_op<error_code>(_complete_after, _write_ec);
}
template <typename Executor>
decltype(auto) pop_reply_ops(const Executor& ex) {
decltype(auto) pop_reply_ops() {
std::vector<delayed_op<error_code, std::vector<uint8_t>>> ret;
std::transform(
_replies.begin(), _replies.end(), std::back_inserter(ret),
[&ex](auto& r) { return r.to_operation(ex); }
[](auto& r) { return r.to_operation(); }
);
_replies.clear();
return ret;
@@ -187,9 +184,8 @@ public:
template <typename ...Args>
broker_message& send(Args&& ...args);
template <typename Executor>
decltype(auto) pop_send_op(const Executor& ex) {
return _message.to_operation(ex);
decltype(auto) pop_send_op() {
return _message.to_operation();
}
};
@@ -233,12 +229,11 @@ public:
return rv;
}
template <typename Executor>
auto pop_broker_ops(const Executor& ex) {
auto pop_broker_ops() {
std::vector<delayed_op<error_code, std::vector<uint8_t>>> ret;
std::transform(
_from_broker.begin(), _from_broker.end(), std::back_inserter(ret),
[&ex](auto& s) { return s.pop_send_op(ex); }
[](auto& s) { return s.pop_send_op(); }
);
_from_broker.clear();
return ret;

View File

@@ -8,11 +8,14 @@
#ifndef BOOST_MQTT5_TEST_AUTOCONNECT_STREAM_HPP
#define BOOST_MQTT5_TEST_AUTOCONNECT_STREAM_HPP
#include "test_broker.hpp"
#include <boost/mqtt5/detail/async_mutex.hpp>
#include <boost/mqtt5/detail/async_traits.hpp>
#include <boost/mqtt5/detail/log_invoke.hpp>
#include <boost/mqtt5/impl/endpoints.hpp>
#include <boost/mqtt5/impl/reconnect_op.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
@@ -22,6 +25,7 @@
#include <memory>
#include <string>
#include <utility>
#include <variant>
namespace boost::mqtt5::test {
@@ -47,7 +51,7 @@ private:
executor_type _stream_executor;
async_mutex _conn_mtx;
asio::steady_timer _connect_timer;
test_timer _connect_timer;
endpoints _endpoints;
stream_ptr _stream_ptr;

View File

@@ -17,7 +17,6 @@
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/async_result.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/dispatch.hpp>
#include <boost/asio/execution_context.hpp>
#include <boost/asio/ip/tcp.hpp>
@@ -35,8 +34,13 @@
#include <string>
#include <vector>
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "message_exchange.hpp"
#include "packet_util.hpp"
#include "test_timer.hpp"
#include "test_resolver.hpp"
#define BOOST_MQTT5_DETAIL_RESOLVER_TYPE boost::mqtt5::test::test_resolver
#define BOOST_MQTT5_DETAIL_CLOCK_TYPE boost::mqtt5::test::clock
namespace boost::mqtt5::test {
@@ -109,7 +113,6 @@ private:
pending_read _pending_read;
msg_exchange _broker_side;
std::vector<std::unique_ptr<asio::cancellation_signal>> _cancel_signals;
public:
explicit test_broker(
@@ -133,9 +136,6 @@ public:
get_executor(), asio::error::operation_aborted, 0
);
for (auto& cs : _cancel_signals)
cs->emit(asio::cancellation_type::terminal);
_broker_data.clear();
}
@@ -161,53 +161,48 @@ public:
executor_type ex = get_executor();
if (reply_action) {
const auto& expected = reply_action->expected_packets();
size_t buffers_size = std::distance(
asio::buffer_sequence_begin(buffers), asio::buffer_sequence_end(buffers)
);
BOOST_TEST(buffers_size == expected.size());
size_t num_packets = (std::min)(buffers_size, expected.size());
auto it = asio::buffer_sequence_begin(buffers);
for (size_t i = 0; i < num_packets; ++i, ++it) {
BOOST_TEST(it->size() == expected[i].size());
size_t len = (std::min)(it->size(), expected[i].size());
if (memcmp(it->data(), expected[i].data(), len))
BOOST_ERROR(
concat_strings(
"Packet mismatch!\nExpected: ",
to_readable_packet(expected[i]),
"\nReceived: ",
to_readable_packet(std::string((const char*)it->data(), it->size()))
)
);
}
} else
if (!reply_action.has_value()) {
BOOST_ERROR(
"Broker side did not expect: " <<
boost::algorithm::join(to_readable_packets(buffers), ",")
);
return asio::post(asio::prepend(std::move(handler), error_code{}, 0));
}
auto complete_op = reply_action ?
reply_action->write_completion(ex) :
delayed_op<error_code>(ex, 0ms, error_code {});
const auto& expected = reply_action->expected_packets();
size_t buffers_size = std::distance(
asio::buffer_sequence_begin(buffers), asio::buffer_sequence_end(buffers)
);
BOOST_TEST(buffers_size == expected.size());
size_t num_packets = (std::min)(buffers_size, expected.size());
auto it = asio::buffer_sequence_begin(buffers);
for (size_t i = 0; i < num_packets; ++i, ++it) {
BOOST_TEST(it->size() == expected[i].size());
size_t len = (std::min)(it->size(), expected[i].size());
if (memcmp(it->data(), expected[i].data(), len))
BOOST_ERROR(
concat_strings(
"Packet mismatch!\nExpected: ",
to_readable_packet(expected[i]),
"\nReceived: ",
to_readable_packet(std::string((const char*)it->data(), it->size()))
)
);
}
async_delay(
make_cancel_slot(), std::move(complete_op),
_ex, reply_action->write_completion(),
asio::prepend(
std::ref(*this), on_delayed_complete {},
std::move(handler), bytes_written
)
);
if (!reply_action.has_value())
return;
for (auto& op : reply_action->pop_reply_ops(ex))
for (auto& op : reply_action->pop_reply_ops())
async_delay(
make_cancel_slot(), std::move(op),
_ex, std::move(op),
asio::prepend(std::ref(*this), on_receive {})
);
};
@@ -239,8 +234,6 @@ public:
on_receive, error_code delay_ec,
error_code ec, std::vector<uint8_t> bytes
) {
remove_cancel_signal();
if (delay_ec) // asio::operation_aborted
return;
@@ -253,8 +246,6 @@ public:
on_delayed_complete, Handler handler, size_t bytes,
error_code delay_ec, error_code ec
) {
remove_cancel_signal();
if (delay_ec) { // asio::operation_aborted
ec = delay_ec;
bytes = 0;
@@ -267,6 +258,13 @@ public:
_pending_read.complete(get_executor(), asio::error::operation_aborted, 0);
}
static void run(asio::io_context& ioc) {
while (!ioc.stopped()) {
ioc.poll();
asio::use_service<timer_service<clock>>(ioc).advance();
}
}
private:
void shutdown() override {
@@ -274,9 +272,9 @@ private:
}
void launch_broker_ops() {
for (auto& op: _broker_side.pop_broker_ops(get_executor())) {
for (auto& op: _broker_side.pop_broker_ops()) {
async_delay(
asio::cancellation_slot {},
_ex,
std::move(op),
asio::prepend(std::ref(*this), on_receive {})
);
@@ -304,22 +302,6 @@ private:
_pending_read.complete(get_executor(), ec, bytes_read);
}
asio::cancellation_slot make_cancel_slot() {
_cancel_signals.push_back(
std::make_unique<asio::cancellation_signal>()
);
return _cancel_signals.back()->slot();
}
void remove_cancel_signal() {
_cancel_signals.erase(
std::remove_if(
_cancel_signals.begin(), _cancel_signals.end(),
[](auto& sig_ptr) { return !sig_ptr->slot().has_handler(); }
),
_cancel_signals.end()
);
}
};
} // end namespace boost::mqtt5::test

View File

@@ -0,0 +1,59 @@
//
// Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_MQTT5_TEST_RESOLVER_HPP
#define BOOST_MQTT5_TEST_RESOLVER_HPP
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/prepend.hpp>
namespace boost::mqtt5::test {
class test_resolver {
public:
using executor_type = asio::any_io_executor;
using results_type = asio::ip::tcp::resolver::results_type;
private:
executor_type _ex;
public:
static constexpr std::string_view invalid_host = "example.invalid";
explicit test_resolver(executor_type ex) : _ex(std::move(ex)) {}
executor_type get_executor() const noexcept { return _ex; }
template <typename CompletionToken>
decltype(auto) async_resolve(
std::string_view host, std::string_view port, CompletionToken&& token
) {
results_type results;
boost::system::error_code ec;
if (host == invalid_host)
ec = asio::error::host_not_found;
else
results = results_type::create(
asio::ip::tcp::endpoint(asio::ip::make_address_v4("127.0.0.1"), 1883),
std::string(host), std::string(port)
);
return asio::post(
get_executor(),
asio::prepend(
std::forward<CompletionToken>(token),
ec, results
)
);
}
};
} // namespace boost::mqtt5::test
#endif // !BOOST_MQTT5_TEST_RESOLVER_HPP

View File

@@ -8,6 +8,8 @@
#ifndef BOOST_MQTT5_TEST_TEST_SERVICE_HPP
#define BOOST_MQTT5_TEST_TEST_SERVICE_HPP
#include "test_broker.hpp"
#include <boost/mqtt5/types.hpp>
#include <boost/mqtt5/impl/client_service.hpp>

View File

@@ -18,21 +18,18 @@
#include <boost/asio/post.hpp>
#include <boost/asio/prepend.hpp>
#include <boost/asio/recycling_allocator.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/system/error_code.hpp>
#include <chrono>
#include <memory>
#include "test_common/test_broker.hpp"
#include "test_broker.hpp"
namespace boost::mqtt5::test {
namespace asio = boost::asio;
using error_code = boost::system::error_code;
using time_stamp = std::chrono::time_point<std::chrono::steady_clock>;
using duration = time_stamp::duration;
namespace detail {

View File

@@ -0,0 +1,207 @@
//
// Copyright (c) 2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#ifndef BOOST_MQTT5_TEST_TIMER_HPP
#define BOOST_MQTT5_TEST_TIMER_HPP
#include <vector>
#include <utility>
#include <boost/asio/any_completion_handler.hpp>
#include <boost/asio/any_io_executor.hpp>
#include <boost/asio/basic_waitable_timer.hpp>
#include <boost/asio/execution_context.hpp>
#include <boost/asio/post.hpp>
#include <boost/asio/prepend.hpp>
#include <boost/system/error_code.hpp>
namespace boost::mqtt5::test {
namespace asio = boost::asio;
class clock {
public:
using duration = std::chrono::duration<int64_t, std::milli>;
using time_point = std::chrono::time_point<clock, duration>;
using rep = duration::rep;
using period = duration::period;
static constexpr bool is_steady = false;
static time_point now() noexcept {
std::terminate();
}
};
template <typename Clock>
class timer_service : public boost::asio::execution_context::service {
public:
static inline boost::asio::execution_context::id id;
private:
using base = boost::asio::execution_context::service;
using error_code = boost::system::error_code;
using test_timer = boost::asio::basic_waitable_timer<Clock>;
std::vector<test_timer*> _timers;
typename Clock::time_point _simulation_time;
public:
explicit timer_service(boost::asio::execution_context& context)
: base(context) {}
void add_timer(test_timer* timer) {
_timers.push_back(timer);
}
void remove_timer(test_timer* timer) {
auto it = std::remove(_timers.begin(), _timers.end(), timer);
_timers.erase(it);
}
void advance() {
if (_timers.empty()) return;
auto it = std::min_element(
_timers.begin(), _timers.end(),
[](const test_timer* fst, const test_timer* snd) {
return fst->expiry() < snd->expiry();
}
);
_simulation_time = (*it)->expiry();
for (auto it = _timers.begin(); it != _timers.end();) {
auto* timer = *it;
if (timer->expiry() <= now()) {
timer->complete_post(error_code {});
it = _timers.erase(it);
}
else {
++it;
}
}
}
auto now() const { return _simulation_time; }
private:
void shutdown() noexcept override {
for (auto* timer : _timers)
timer->complete_post(asio::error::operation_aborted);
_timers.clear();
}
};
using test_timer = asio::basic_waitable_timer<clock>;
} // namespace boost::mqtt5::test
namespace boost::asio {
template <>
class basic_waitable_timer<boost::mqtt5::test::clock> {
public:
using executor_type = asio::any_io_executor;
using clock_type = boost::mqtt5::test::clock;
using duration = clock_type::duration;
using time_point = clock_type::time_point;
private:
using error_code = boost::system::error_code;
using service = boost::mqtt5::test::timer_service<clock_type>;
using signature = void (error_code);
friend class boost::mqtt5::test::timer_service<clock_type>;
executor_type _ex;
time_point _expires_at;
asio::any_completion_handler<signature> _handler;
asio::prefer_result_t<
executor_type, execution::outstanding_work_t::tracked_t> _handler_ex;
public:
explicit basic_waitable_timer(executor_type ex) : _ex(std::move(ex)) {}
basic_waitable_timer(executor_type ex, time_point expiry_time)
: _ex(std::move(ex)) { expires_at(expiry_time); }
basic_waitable_timer(executor_type ex, duration dur)
: _ex(std::move(ex)) { expires_after(dur); }
~basic_waitable_timer() {
if (_handler) {
get_service().remove_timer(this);
complete_post(asio::error::operation_aborted);
}
}
executor_type get_executor() const noexcept { return _ex; }
size_t expires_at(time_point expiry_time) {
_expires_at = expiry_time;
return 0;
}
size_t expires_after(duration dur) {
auto now = get_service().now();
if ((time_point::max)() - now < dur)
_expires_at = (time_point::max)();
else
_expires_at = now + dur;
return 0;
}
time_point expiry() const { return _expires_at; }
size_t cancel() {
if (_handler) {
get_service().remove_timer(this);
complete_post(asio::error::operation_aborted);
return 1;
}
return 0;
}
template <typename CompletionToken>
decltype(auto) async_wait(CompletionToken&& token) {
auto initiation = [this](auto handler) {
if (_expires_at <= get_service().now())
return asio::post(
get_executor(),
asio::prepend(std::move(handler), error_code {})
);
_handler = std::move(handler);
_handler_ex = asio::prefer(_ex, asio::execution::outstanding_work.tracked);
auto slot = asio::get_associated_cancellation_slot(_handler);
if (slot.is_connected())
slot.assign([this](asio::cancellation_type_t type) {
if (type != asio::cancellation_type_t::none)
cancel();
});
get_service().add_timer(this);
};
return asio::async_initiate<CompletionToken, signature>(
initiation, token
);
}
private:
service& get_service() const {
return use_service<service>(_ex.context());
}
void complete_post(error_code ec) {
asio::get_associated_cancellation_slot(_handler).clear();
asio::post(get_executor(), asio::prepend(std::move(_handler), ec));
_handler_ex = {};
}
};
} // namespace boost::asio
#endif // !BOOST_MQTT5_TEST_TIMER_HPP

133
test/integration/logger.cpp Normal file
View File

@@ -0,0 +1,133 @@
//
// Copyright (c) 2023-2025 Ivica Siladic, Bruno Iljazovic, Korina Simicevic
//
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/extra_deps.hpp"
#include "test_common/preconditions.hpp"
#include <boost/mqtt5/logger.hpp>
#include <boost/mqtt5/logger_traits.hpp>
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/detail/log_invoke.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/system/error_code.hpp>
#include <boost/test/tools/output_test_stream.hpp>
#include <boost/test/unit_test.hpp>
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>
#include <type_traits>
using namespace boost::mqtt5;
namespace asio = boost::asio;
void logger_test() {
BOOST_STATIC_ASSERT(has_at_resolve<logger>);
BOOST_STATIC_ASSERT(has_at_tcp_connect<logger>);
BOOST_STATIC_ASSERT(has_at_tls_handshake<logger>);
BOOST_STATIC_ASSERT(has_at_ws_handshake<logger>);
BOOST_STATIC_ASSERT(has_at_connack<logger>);
BOOST_STATIC_ASSERT(has_at_disconnect<logger>);
BOOST_STATIC_ASSERT(has_at_transport_error<logger>);
}
BOOST_AUTO_TEST_SUITE(logger_tests)
using error_code = boost::system::error_code;
class clog_redirect {
std::streambuf* _old_buffer;
public:
clog_redirect(std::streambuf* new_buffer) :
_old_buffer(std::clog.rdbuf(new_buffer))
{}
~clog_redirect() {
std::clog.rdbuf(_old_buffer);
}
};
bool contains(const std::string& str, const std::string& substr) {
return str.find(substr) != std::string::npos;
}
#ifdef BOOST_MQTT5_EXTRA_DEPS
using stream_type = boost::beast::websocket::stream<
asio::ssl::stream<asio::ip::tcp::socket>
>;
using context_type = asio::ssl::context;
using logger_type = logger;
using client_type = mqtt_client<stream_type, context_type, logger_type>;
BOOST_AUTO_TEST_CASE(client_successful_connect_debug,
* boost::unit_test::precondition(test::public_broker_cond))
{
boost::test_tools::output_test_stream output;
{
clog_redirect guard(output.rdbuf());
asio::io_context ioc;
asio::ssl::context tls_context(asio::ssl::context::tls_client);
client_type c(
ioc, std::move(tls_context), logger(log_level::debug)
);
c.brokers("broker.hivemq.com/mqtt", 8884)
.async_run(asio::detached);
c.async_disconnect([](error_code) {});
ioc.run();
}
std::string log = output.rdbuf()->str();
BOOST_TEST_MESSAGE(log);
BOOST_TEST_WARN(contains(log, "resolve"));
BOOST_TEST_WARN(contains(log, "TCP connect"));
BOOST_TEST_WARN(contains(log, "TLS handshake"));
BOOST_TEST_WARN(contains(log, "WebSocket handshake"));
BOOST_TEST_WARN(contains(log, "connack"));
}
BOOST_AUTO_TEST_CASE(client_successful_connect_warning,
* boost::unit_test::precondition(test::public_broker_cond))
{
boost::test_tools::output_test_stream output;
{
clog_redirect guard(output.rdbuf());
asio::io_context ioc;
asio::ssl::context tls_context(asio::ssl::context::tls_client);
client_type c(
ioc, std::move(tls_context), logger(log_level::warning)
);
c.brokers("broker.hivemq.com/mqtt", 8884)
.async_run(asio::detached);
c.async_disconnect([](error_code) {});
ioc.run();
}
// If connection is successful, nothing should be printed.
// However if the Broker is down or overloaded, this will cause logs to be printed.
// We should not fail the test because of it.
BOOST_TEST_WARN(output.is_empty());
}
#endif // BOOST_MQTT5_EXTRA_DEPS
BOOST_AUTO_TEST_SUITE_END();

View File

@@ -13,7 +13,6 @@
#include <boost/asio/error.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/thread_pool.hpp>
#include <boost/test/unit_test.hpp>
#include <chrono>
@@ -30,8 +29,8 @@ BOOST_AUTO_TEST_CASE(lock_mutex) {
constexpr int expected_handlers_called = 1;
int handlers_called = 0;
asio::thread_pool tp(1);
async_mutex mutex(tp.executor());
asio::io_context ioc;
async_mutex mutex(ioc.get_executor());
mutex.lock([&mutex, &handlers_called](error_code ec) {
++handlers_called;
@@ -41,13 +40,13 @@ BOOST_AUTO_TEST_CASE(lock_mutex) {
BOOST_TEST(!mutex.is_locked());
});
tp.wait();
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
}
BOOST_AUTO_TEST_CASE(get_executor) {
asio::thread_pool tp(1);
auto ex = tp.get_executor();
asio::io_context ioc;
auto ex = ioc.get_executor();
async_mutex mutex(ex);
BOOST_CHECK(mutex.get_executor() == ex);
}
@@ -56,11 +55,11 @@ BOOST_AUTO_TEST_CASE(bind_executor) {
constexpr int expected_handlers_called = 2;
int handlers_called = 0;
asio::thread_pool tp(1);
asio::io_context ioc;
async_mutex mutex(tp.get_executor());
auto s1 = asio::make_strand(tp.get_executor());
auto s2 = asio::make_strand(tp.get_executor());
async_mutex mutex(ioc.get_executor());
auto s1 = asio::make_strand(ioc.get_executor());
auto s2 = asio::make_strand(ioc.get_executor());
mutex.lock(
asio::bind_executor(
@@ -88,7 +87,7 @@ BOOST_AUTO_TEST_CASE(bind_executor) {
)
);
tp.wait();
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(!mutex.is_locked());
}
@@ -123,7 +122,7 @@ BOOST_AUTO_TEST_CASE(per_op_cancellation) {
cs.emit(asio::cancellation_type_t::terminal);
cs.slot().clear();
ioc.run();
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(!mutex.is_locked());
}
@@ -151,7 +150,7 @@ BOOST_AUTO_TEST_CASE(cancel_ops_by_destructor) {
mutex.lock(std::move(cancelled_op));
}
ioc.run();
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
}
@@ -180,7 +179,7 @@ BOOST_AUTO_TEST_CASE(cancel_ops) {
mutex.lock(cancelled_op);
mutex.cancel();
ioc.run();
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(!mutex.is_locked());
}

View File

@@ -5,12 +5,14 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/types.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/test/unit_test.hpp>
#include <chrono>
@@ -19,9 +21,6 @@
#include <string>
#include <vector>
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(async_sender/*, *boost::unit_test::disabled()*/)
@@ -130,7 +129,7 @@ BOOST_FIXTURE_TEST_CASE(publish_ordering_after_reconnect, shared_test_data) {
}
);
ioc.run_for(1s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -209,7 +208,7 @@ BOOST_FIXTURE_TEST_CASE(sub_unsub_ordering_after_reconnect, shared_test_data) {
}
);
ioc.run_for(1s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -274,7 +273,7 @@ BOOST_FIXTURE_TEST_CASE(throttling, shared_test_data) {
}
);
ioc.run_for(1s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -333,7 +332,7 @@ BOOST_FIXTURE_TEST_CASE(throttling_ordering, shared_test_data) {
}
);
ioc.run_for(1s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -377,7 +376,7 @@ BOOST_FIXTURE_TEST_CASE(prioritize_disconnect, shared_test_data) {
.async_run(asio::detached);
// give time to establish a connection
asio::steady_timer timer(executor);
test::test_timer timer(executor);
timer.expires_after(100ms);
timer.async_wait([&](error_code) {
c.async_publish<qos_e::at_least_once>(
@@ -407,7 +406,7 @@ BOOST_FIXTURE_TEST_CASE(prioritize_disconnect, shared_test_data) {
});
});
ioc.run_for(2s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}

View File

@@ -5,6 +5,9 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
#include <boost/asio/as_tuple.hpp>
#include <boost/asio/bind_cancellation_slot.hpp>
#include <boost/asio/cancellation_signal.hpp>
@@ -12,16 +15,12 @@
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/use_awaitable.hpp>
#include <boost/mqtt5.hpp>
#include <boost/test/unit_test.hpp>
#include <type_traits>
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
namespace boost::mqtt5::test {
@@ -190,7 +189,7 @@ void run_cancel_op_test() {
setup_cancel_op_test_case<op_type>(c, signal, handlers_called);
asio::steady_timer timer(c.get_executor());
test::test_timer timer(c.get_executor());
timer.expires_after(std::chrono::milliseconds(100));
timer.async_wait([&](error_code) {
if constexpr (c_type == client_cancel)
@@ -199,7 +198,7 @@ void run_cancel_op_test() {
signal.emit(asio::cancellation_type_t::terminal);
});
ioc.run();
test::test_broker::run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
}
@@ -341,7 +340,7 @@ BOOST_FIXTURE_TEST_CASE(rerunning_the_client, shared_test_data) {
asio::detached
);
ioc.run();
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
}

View File

@@ -5,6 +5,12 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/extra_deps.hpp"
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "test_common/test_authenticators.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/types.hpp>
@@ -13,7 +19,6 @@
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/test/unit_test.hpp>
#include <boost/type_traits/remove_cv_ref.hpp>
@@ -22,12 +27,6 @@
#include <optional>
#include <string>
#include "test_common/extra_deps.hpp"
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "test_common/test_authenticators.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
using namespace std::chrono_literals;
@@ -58,13 +57,13 @@ void run_test(
c.brokers("127.0.0.1")
.async_run(asio::detached);
asio::steady_timer timer(executor);
test::test_timer timer(executor);
timer.expires_after(700ms);
timer.async_wait(
[&c](error_code) { c.cancel(); }
);
ioc.run();
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
}
@@ -302,7 +301,7 @@ void run_test_with_post_fun(
c.brokers("127.0.0.1")
.async_run(asio::detached);
asio::steady_timer timer(executor);
test::test_timer timer(executor);
timer.expires_after(700ms);
timer.async_wait(
[&c, fun = std::forward<TestingClientFun>(client_fun)](error_code) {
@@ -311,7 +310,7 @@ void run_test_with_post_fun(
}
);
ioc.run();
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
}

View File

@@ -5,6 +5,9 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/test_authenticators.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/logger_traits.hpp>
#include <boost/mqtt5/types.hpp>
@@ -15,7 +18,6 @@
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/test/unit_test.hpp>
#include <chrono>
@@ -23,9 +25,6 @@
#include <string>
#include <vector>
#include "test_common/test_authenticators.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(connect_op/*, *boost::unit_test::disabled()*/)
@@ -72,7 +71,7 @@ void run_unit_test(
stream, mqtt_ctx, d, std::move(handler)
).perform(*std::begin(eps), std::move(ap));
ioc.run_for(1s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}

View File

@@ -9,6 +9,9 @@
#ifdef BOOST_ASIO_HAS_CO_AWAIT
#include "test_common/test_broker.hpp"
#include "test_common/extra_deps.hpp"
#include <boost/mqtt5.hpp>
#include <boost/asio/io_context.hpp>
@@ -19,8 +22,6 @@
#include <variant> // std::monostate
#include <vector>
#include "test_common/extra_deps.hpp"
namespace boost::mqtt5::test {
// the following code needs to compile

View File

@@ -5,22 +5,21 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/test_broker.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/types.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/test/unit_test.hpp>
#include <chrono>
#include <string>
#include "test_common/message_exchange.hpp"
#include "test_common/test_broker.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(disconnect/*, *boost::unit_test::disabled()*/)
@@ -52,14 +51,14 @@ void run_test(test::msg_exchange broker_side, TestCase&& test_case) {
ioc, executor, std::move(broker_side)
);
asio::steady_timer timer(executor);
test::test_timer timer(executor);
client_type c(executor);
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
.async_run(asio::detached);
test_case(c, timer);
ioc.run();
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
}
@@ -77,7 +76,7 @@ BOOST_FIXTURE_TEST_CASE(successful_disconnect, shared_test_data) {
run_test(
std::move(broker_side),
[&](client_type& c, asio::steady_timer& timer) {
[&](client_type& c, test::test_timer& timer) {
timer.expires_after(100ms);
timer.async_wait([&](error_code) {
c.async_disconnect(
@@ -114,7 +113,7 @@ BOOST_FIXTURE_TEST_CASE(successful_disconnect_in_queue, shared_test_data) {
run_test(
std::move(broker_side),
[&](client_type& c, asio::steady_timer& timer) {
[&](client_type& c, test::test_timer& timer) {
timer.expires_after(50ms);
timer.async_wait([&](error_code) {
c.async_publish<qos_e::at_most_once>(
@@ -150,7 +149,7 @@ BOOST_FIXTURE_TEST_CASE(disconnect_on_disconnected_client, shared_test_data) {
run_test(
std::move(broker_side),
[&](client_type& c, asio::steady_timer& timer) {
[&](client_type& c, test::test_timer& timer) {
timer.expires_after(50ms);
timer.async_wait([&](error_code) {
c.async_disconnect(
@@ -177,7 +176,7 @@ BOOST_FIXTURE_TEST_CASE(disconnect_in_queue_on_disconnected_client, shared_test_
run_test(
std::move(broker_side),
[&](client_type& c, asio::steady_timer& timer) {
[&](client_type& c, test::test_timer& timer) {
timer.expires_after(50ms);
timer.async_wait([&](error_code) {
c.async_publish<qos_e::at_most_once>(
@@ -216,7 +215,7 @@ BOOST_FIXTURE_TEST_CASE(resend_terminal_disconnect, shared_test_data) {
run_test(
std::move(broker_side),
[&](client_type& c, asio::steady_timer&) {
[&](client_type& c, test::test_timer&) {
c.async_disconnect(
[&](error_code ec) {
handlers_called++;
@@ -258,7 +257,7 @@ BOOST_FIXTURE_TEST_CASE(dont_resend_non_terminal_disconnect, shared_test_data) {
run_test(
std::move(broker_side),
[&](client_type& c, asio::steady_timer& timer) {
[&](client_type& c, test::test_timer& timer) {
timer.expires_after(50ms);
timer.async_wait([&](error_code) {
c.cancel();
@@ -292,7 +291,7 @@ BOOST_FIXTURE_TEST_CASE(omit_props, shared_test_data) {
run_test(
std::move(broker_side),
[&](client_type& c, asio::steady_timer&) {
[&](client_type& c, test::test_timer&) {
c.async_disconnect(
disconnect_rc_e::normal_disconnection, props,
[&](error_code ec) {
@@ -313,7 +312,7 @@ struct long_shutdown_stream : public test::test_stream {
template <typename ShutdownHandler>
void async_shutdown(long_shutdown_stream& stream, ShutdownHandler&& handler) {
auto timer = std::make_shared<asio::steady_timer>(stream.get_executor());
auto timer = std::make_shared<test::test_timer>(stream.get_executor());
timer->expires_after(std::chrono::seconds(10));
timer->async_wait(asio::consign(std::move(handler), std::move(timer)));
}
@@ -340,7 +339,7 @@ BOOST_DATA_TEST_CASE_F(
ioc, executor, std::move(broker_side)
);
asio::steady_timer timer(executor);
test::test_timer timer(executor);
mqtt_client<long_shutdown_stream> c(executor);
c.brokers("127.0.0.1")
.async_run(asio::detached);
@@ -363,7 +362,7 @@ BOOST_DATA_TEST_CASE_F(
signal.emit(asio::cancellation_type::all);
});
ioc.run_for(6s);
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
BOOST_TEST(handlers_called == expected_handlers_called);

View File

@@ -5,6 +5,8 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/test_service.hpp"
#include <boost/mqtt5/types.hpp>
#include <boost/mqtt5/impl/disconnect_op.hpp>
@@ -18,8 +20,6 @@
#include <memory>
#include <string>
#include "test_common/test_service.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(disconnect_op/*, *boost::unit_test::disabled()*/)
@@ -45,7 +45,7 @@ void run_malformed_props_test(const disconnect_props& dprops) {
> { svc_ptr, std::move(ctx), std::move(handler) }
.perform();
ioc.run_for(std::chrono::milliseconds(500));
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
}

View File

@@ -5,6 +5,8 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/test_broker.hpp"
#include <boost/mqtt5/impl/endpoints.hpp>
#include <boost/test/unit_test.hpp>
@@ -27,7 +29,7 @@ struct shared_test_data {
error_code success {};
asio::io_context ioc;
asio::steady_timer timer;
test::test_timer timer;
detail::log_invoke<noop_logger> logger;
detail::endpoints<noop_logger> ep;
@@ -47,7 +49,7 @@ BOOST_FIXTURE_TEST_CASE(empty_path, shared_test_data) {
BOOST_TEST(ec == asio::error::host_not_found);
}, [&finished](auto eptr) { finished = !eptr; });
ioc.run_for(1s);
test::test_broker::run(ioc);
BOOST_TEST(finished);
}
@@ -67,7 +69,7 @@ BOOST_FIXTURE_TEST_CASE(single_host, shared_test_data) {
BOOST_TEST(ec == asio::error::try_again);
}, [&finished](auto eptr) { finished = !eptr; });
ioc.run_for(1s);
test::test_broker::run(ioc);
BOOST_TEST(finished);
}
@@ -104,7 +106,7 @@ BOOST_FIXTURE_TEST_CASE(multiple_hosts, shared_test_data) {
}
}, [&finished](auto eptr) { finished = !eptr; });
ioc.run_for(1s);
test::test_broker::run(ioc);
BOOST_TEST(finished);
}
@@ -124,7 +126,7 @@ BOOST_FIXTURE_TEST_CASE(parse_failure, shared_test_data) {
BOOST_TEST(ec == asio::error::try_again);
}, [&finished](auto eptr) { finished = !eptr; });
ioc.run_for(1s);
test::test_broker::run(ioc);
BOOST_TEST(finished);
}

View File

@@ -5,6 +5,9 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/impl/codecs/message_encoders.hpp>
#include <boost/asio/bind_executor.hpp>
@@ -12,7 +15,6 @@
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/strand.hpp>
#include <boost/mqtt5.hpp>
#include <boost/test/unit_test.hpp>
@@ -22,9 +24,6 @@
#include <string>
#include <vector>
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
using strand_type = asio::strand<asio::any_io_executor>;
@@ -205,7 +204,7 @@ void run_test(
)
);
ioc.run_for(500ms);
test::test_broker::run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -261,7 +260,7 @@ BOOST_AUTO_TEST_CASE(immediate_executor_async_publish) {
"invalid/#", "", retain_e::no, publish_props {}, std::move(handler)
);
ioc.run();
test::test_broker::run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
}
@@ -290,7 +289,7 @@ BOOST_AUTO_TEST_CASE(immediate_executor_async_subscribe) {
{ "+topic", subscribe_options {} }, subscribe_props{}, std::move(handler)
);
ioc.run();
test::test_broker::run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
}
@@ -319,7 +318,7 @@ BOOST_AUTO_TEST_CASE(immediate_executor_async_unsubscribe) {
"some/topic#", unsubscribe_props {}, std::move(handler)
);
ioc.run();
test::test_broker::run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
}

View File

@@ -5,6 +5,9 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/logger.hpp>
#include <boost/mqtt5/logger_traits.hpp>
#include <boost/mqtt5/mqtt_client.hpp>
@@ -14,7 +17,6 @@
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/system_executor.hpp>
#include <boost/system/error_code.hpp>
#include <boost/test/tools/output_test_stream.hpp>
#include <boost/test/unit_test.hpp>
@@ -25,11 +27,6 @@
#include <string>
#include <type_traits>
#include "test_common/extra_deps.hpp"
#include "test_common/message_exchange.hpp"
#include "test_common/preconditions.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
namespace asio = boost::asio;
@@ -102,27 +99,11 @@ struct resolve_test_data {
std::string_view host = "localhost";
std::string_view port = "1883";
asio::ip::tcp::resolver::results_type endpoints() {
auto ex = asio::system_executor {};
asio::ip::tcp::resolver resolver(ex);
error_code ec;
auto eps = resolver.resolve(host, port, ec);
BOOST_TEST_REQUIRE(!ec);
return eps;
}
std::string endpoints_output() {
// Endpoints resolved depend on the platform.
auto eps = endpoints();
std::stringstream ss;
ss << "[";
for (auto it = eps.begin(); it != eps.end();) {
ss << it->endpoint().address().to_string();
if (++it != eps.end())
ss << ",";
}
ss << "]";
return ss.str();
auto endpoints() {
return asio::ip::tcp::resolver::results_type::create(
{ asio::ip::make_address("127.0.0.1"), 1883 },
std::string(host), std::string(port)
);
}
};
@@ -165,7 +146,7 @@ BOOST_FIXTURE_TEST_CASE(at_resolve_info, resolve_test_data) {
BOOST_FIXTURE_TEST_CASE(at_resolve_success_debug, resolve_test_data) {
const auto expected_output =
"[Boost.MQTT5] resolve: localhost:1883 - " + success_msg() + ". " + endpoints_output() + "\n"
"[Boost.MQTT5] resolve: localhost:1883 - " + success_msg() + ". [127.0.0.1]\n"
;
auto test_fun = [this] {
@@ -479,11 +460,11 @@ BOOST_AUTO_TEST_CASE(client_disconnect) {
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
.async_run(asio::detached);
asio::steady_timer timer(c.get_executor());
test::test_timer timer(c.get_executor());
timer.expires_after(100ms);
timer.async_wait([&c](error_code) { c.cancel(); });
ioc.run();
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
}
@@ -538,11 +519,11 @@ BOOST_AUTO_TEST_CASE(client_transport_error) {
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
.async_run(asio::detached);
asio::steady_timer timer(c.get_executor());
test::test_timer timer(c.get_executor());
timer.expires_after(100ms);
timer.async_wait([&c](error_code) { c.cancel(); });
ioc.run();
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
}
@@ -550,72 +531,4 @@ BOOST_AUTO_TEST_CASE(client_transport_error) {
BOOST_TEST(log == expected_msg);
}
#ifdef BOOST_MQTT5_EXTRA_DEPS
using stream_type = boost::beast::websocket::stream<
asio::ssl::stream<asio::ip::tcp::socket>
>;
using context_type = asio::ssl::context;
using logger_type = logger;
using client_type = mqtt_client<stream_type, context_type, logger_type>;
BOOST_AUTO_TEST_CASE(client_successful_connect_debug,
* boost::unit_test::precondition(test::public_broker_cond))
{
boost::test_tools::output_test_stream output;
{
clog_redirect guard(output.rdbuf());
asio::io_context ioc;
asio::ssl::context tls_context(asio::ssl::context::tls_client);
client_type c(
ioc, std::move(tls_context), logger(log_level::debug)
);
c.brokers("broker.hivemq.com/mqtt", 8884)
.async_run(asio::detached);
c.async_disconnect([](error_code) {});
ioc.run();
}
std::string log = output.rdbuf()->str();
BOOST_TEST_MESSAGE(log);
BOOST_TEST_WARN(contains(log, "resolve"));
BOOST_TEST_WARN(contains(log, "TCP connect"));
BOOST_TEST_WARN(contains(log, "TLS handshake"));
BOOST_TEST_WARN(contains(log, "WebSocket handshake"));
BOOST_TEST_WARN(contains(log, "connack"));
}
BOOST_AUTO_TEST_CASE(client_successful_connect_warning,
* boost::unit_test::precondition(test::public_broker_cond))
{
boost::test_tools::output_test_stream output;
{
clog_redirect guard(output.rdbuf());
asio::io_context ioc;
asio::ssl::context tls_context(asio::ssl::context::tls_client);
client_type c(
ioc, std::move(tls_context), logger(log_level::warning)
);
c.brokers("broker.hivemq.com/mqtt", 8884)
.async_run(asio::detached);
c.async_disconnect([](error_code) {});
ioc.run();
}
// If connection is successful, nothing should be printed.
// However if the Broker is down or overloaded, this will cause logs to be printed.
// We should not fail the test because of it.
BOOST_TEST_WARN(output.is_empty());
}
#endif // BOOST_MQTT5_EXTRA_DEPS
BOOST_AUTO_TEST_SUITE_END();

View File

@@ -5,6 +5,9 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/types.hpp>
@@ -18,9 +21,6 @@
#include <limits>
#include <string>
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(ping/*, *boost::unit_test::disabled()*/)
@@ -72,13 +72,13 @@ void run_test(
.keep_alive(keep_alive)
.async_run(asio::detached);
asio::steady_timer timer(c.get_executor());
test::test_timer timer(c.get_executor());
timer.expires_after(cancel_timeout);
timer.async_wait([&c](error_code) {
c.cancel();
});
ioc.run();
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
}

View File

@@ -5,6 +5,8 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/test_service.hpp"
#include <boost/mqtt5/types.hpp>
#include <boost/mqtt5/impl/client_service.hpp>
@@ -14,7 +16,6 @@
#include <boost/asio/cancellation_signal.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/test/unit_test.hpp>
#include <chrono>
@@ -23,8 +24,6 @@
#include <string>
#include <vector>
#include "test_common/test_service.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(publish_send_op/*, *boost::unit_test::disabled()*/)
@@ -50,7 +49,7 @@ BOOST_AUTO_TEST_CASE(pid_overrun) {
"test", "payload", retain_e::no, {}
);
ioc.run_for(std::chrono::milliseconds(500));
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
}
@@ -78,7 +77,7 @@ void run_test(
> { svc_ptr, std::move(handler) }
.perform(topic_name, payload, retain_e::yes, pprops);
ioc.run_for(std::chrono::milliseconds(500));
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
}

View File

@@ -5,12 +5,16 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "test_common/test_authenticators.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/types.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/test/unit_test.hpp>
#include <chrono>
@@ -19,12 +23,6 @@
#include <variant>
#include <vector>
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "test_common/test_authenticators.hpp"
#include "test_common/test_broker.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(re_authentication/*, *boost::unit_test::disabled()*/)
@@ -87,7 +85,7 @@ void run_test(
c.async_run(asio::detached);
asio::steady_timer timer(c.get_executor());
test::test_timer timer(c.get_executor());
// wait until the connection is established
timer.expires_after(20ms);
timer.async_wait([&](error_code) {
@@ -97,7 +95,7 @@ void run_test(
timer.async_wait([&c](error_code) { c.cancel(); });
});
ioc.run();
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
}

View File

@@ -5,13 +5,15 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/types.hpp>
#include <boost/asio/any_completion_handler.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/test/data/test_case.hpp>
#include <boost/test/unit_test.hpp>
@@ -19,9 +21,6 @@
#include <cstdint>
#include <string>
#include "test_common/message_exchange.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(read_message/*, *boost::unit_test::disabled()*/)
@@ -69,11 +68,11 @@ void test_receive_malformed_packet(
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
.async_run(asio::detached);
asio::steady_timer timer(c.get_executor());
test::test_timer timer(c.get_executor());
timer.expires_after(100ms);
timer.async_wait([&c](error_code) { c.cancel(); });
ioc.run();
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
}
@@ -167,11 +166,11 @@ BOOST_FIXTURE_TEST_CASE(receive_disconnect, shared_test_data) {
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
.async_run(asio::detached);
asio::steady_timer timer(c.get_executor());
test::test_timer timer(c.get_executor());
timer.expires_after(100ms);
timer.async_wait([&c](error_code) { c.cancel(); });
ioc.run();
broker.run(ioc);
BOOST_TEST(broker.received_all_expected());
}
@@ -216,7 +215,7 @@ BOOST_FIXTURE_TEST_CASE(receive_disconnect_while_reconnecting, shared_test_data)
}
);
ioc.run_for(1s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -253,7 +252,7 @@ void run_receive_test(
c.cancel();
});
ioc.run();
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}

View File

@@ -5,24 +5,23 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "test_common/test_broker.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/types.hpp>
#include <boost/algorithm/string/join.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/test/unit_test.hpp>
#include <cstdint>
#include <string>
#include <vector>
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "test_common/test_broker.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(receive_publish/*, *boost::unit_test::disabled()*/)
@@ -91,7 +90,7 @@ void run_test(
}
);
ioc.run_for(3s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -206,7 +205,7 @@ BOOST_FIXTURE_TEST_CASE(receive_publish_properties, shared_test_data) {
}
);
ioc.run();
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -469,7 +468,7 @@ BOOST_FIXTURE_TEST_CASE(receive_buffer_overflow, shared_test_data) {
c.brokers("127.0.0.1")
.async_run(asio::detached);
asio::steady_timer timer(executor);
test::test_timer timer(executor);
timer.expires_after(10s);
timer.async_wait(
[&](error_code) {
@@ -487,7 +486,7 @@ BOOST_FIXTURE_TEST_CASE(receive_buffer_overflow, shared_test_data) {
}
);
ioc.run();
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}

View File

@@ -5,7 +5,12 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/test_autoconnect_stream.hpp"
#include "test_common/test_broker.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/logger_traits.hpp>
#include <boost/mqtt5/logger.hpp>
#include <boost/mqtt5/detail/log_invoke.hpp>
@@ -20,10 +25,6 @@
#include <chrono>
#include <memory>
#include "test_common/test_autoconnect_stream.hpp"
#include "test_common/test_broker.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
using namespace std::chrono_literals;
@@ -132,7 +133,7 @@ void run_connect_to_localhost_test(int succeed_after) {
detail::reconnect_op(auto_stream, std::move(handler))
.perform(auto_stream.stream_pointer());
ioc.run();
broker.run(ioc);
BOOST_TEST(expected_handlers_called == handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -165,7 +166,7 @@ BOOST_AUTO_TEST_CASE(no_servers) {
detail::reconnect_op(auto_stream, std::move(handler))
.perform(auto_stream.stream_pointer());
ioc.run();
ioc.poll();
BOOST_TEST(expected_handlers_called == handlers_called);
}

View File

@@ -5,6 +5,10 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/types.hpp>
@@ -19,10 +23,6 @@
#include <cstdint>
#include <string>
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(send_publish/*, *boost::unit_test::disabled()*/)
@@ -101,7 +101,7 @@ void run_test(
}
);
ioc.run_for(2s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -551,7 +551,7 @@ void run_validation_test(
}
);
ioc.run_for(2s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -619,7 +619,7 @@ BOOST_FIXTURE_TEST_CASE(cancel_resending_publish, shared_test_data) {
);
cancel_signal.emit(asio::cancellation_type::total);
ioc.run_for(1s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}
@@ -689,7 +689,7 @@ BOOST_FIXTURE_TEST_CASE(send_big_publish, shared_test_data) {
}
);
ioc.run_for(2s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}

View File

@@ -20,7 +20,7 @@
#include <vector>
using namespace boost::mqtt5;
using byte_citer = detail::byte_citer;
using byte_citer = decoders::byte_citer;
BOOST_AUTO_TEST_SUITE(serialization/*, *boost::unit_test::disabled()*/)

View File

@@ -5,9 +5,10 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/test_service.hpp"
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/mqtt5.hpp>
#include <boost/test/unit_test.hpp>
@@ -15,8 +16,6 @@
#include <cstdint>
#include <string>
#include "test_common/test_service.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(session/*, *boost::unit_test::disabled()*/)
@@ -50,8 +49,8 @@ BOOST_AUTO_TEST_CASE(clear_waiting_on_pubrel) {
detail::publish_rec_op<client_service_type> { svc_ptr }.perform(pub_msg);
// let publish_rec_op reach wait_on_pubrel stage
asio::steady_timer timer(ioc.get_executor());
timer.expires_after(std::chrono::milliseconds(50));
test::test_timer timer(ioc.get_executor());
timer.expires_after(std::chrono::milliseconds(1));
timer.async_wait([&svc_ptr](error_code) {
BOOST_TEST(svc_ptr.use_count() == 2);
svc_ptr->update_session_state(); // session_present = false
@@ -59,7 +58,7 @@ BOOST_AUTO_TEST_CASE(clear_waiting_on_pubrel) {
BOOST_TEST(svc_ptr.use_count() == 1);
});
ioc.run();
test::test_broker::run(ioc);
}

View File

@@ -5,6 +5,10 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "test_common/test_stream.hpp"
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/types.hpp>
@@ -20,10 +24,6 @@
#include <string>
#include <vector>
#include "test_common/message_exchange.hpp"
#include "test_common/packet_util.hpp"
#include "test_common/test_stream.hpp"
using namespace boost::mqtt5;
namespace boost::mqtt5::test {
@@ -89,7 +89,7 @@ void run_test(
test_body(c, handlers_called);
ioc.run_for(5s);
broker.run(ioc);
BOOST_TEST(handlers_called == expected_handlers_called);
BOOST_TEST(broker.received_all_expected());
}

View File

@@ -5,6 +5,8 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/test_service.hpp"
#include <boost/mqtt5/types.hpp>
#include <boost/mqtt5/impl/subscribe_op.hpp>
@@ -19,8 +21,6 @@
#include <string>
#include <vector>
#include "test_common/test_service.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(subscribe_op/*, *boost::unit_test::disabled()*/)
@@ -47,7 +47,7 @@ BOOST_AUTO_TEST_CASE(pid_overrun) {
{ { "topic", { qos_e::exactly_once } } }, subscribe_props {}
);
ioc.run_for(std::chrono::milliseconds(500));
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
}
@@ -78,7 +78,7 @@ void run_test(
> { svc_ptr, std::move(handler) }
.perform(topics, sprops);
ioc.run_for(std::chrono::milliseconds(500));
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
}

View File

@@ -5,6 +5,9 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/test_broker.hpp"
#include "test_common/extra_deps.hpp"
#include <boost/mqtt5/mqtt_client.hpp>
#include <boost/mqtt5/detail/any_authenticator.hpp>
@@ -20,8 +23,6 @@
#include <string_view>
#include <type_traits>
#include "test_common/extra_deps.hpp"
using namespace boost::mqtt5;
struct good_authenticator {

View File

@@ -5,6 +5,8 @@
// (See accompanying file LICENSE or copy at http://www.boost.org/LICENSE_1_0.txt)
//
#include "test_common/test_service.hpp"
#include <boost/mqtt5/types.hpp>
#include <boost/mqtt5/impl/unsubscribe_op.hpp>
@@ -19,8 +21,6 @@
#include <string>
#include <vector>
#include "test_common/test_service.hpp"
using namespace boost::mqtt5;
BOOST_AUTO_TEST_SUITE(unsubscribe_op/*, *boost::unit_test::disabled()*/)
@@ -45,7 +45,7 @@ BOOST_AUTO_TEST_CASE(pid_overrun) {
> { svc_ptr, std::move(handler) }
.perform({ "topic" }, unsubscribe_props {});
ioc.run_for(std::chrono::milliseconds(500));
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
}
@@ -76,7 +76,7 @@ void run_test(
> { svc_ptr, std::move(handler) }
.perform(topics, uprops);
ioc.run_for(std::chrono::milliseconds(500));
ioc.poll();
BOOST_TEST(handlers_called == expected_handlers_called);
}