Files
boost_mqtt5/test/integration/client.cpp
T

251 lines
6.1 KiB
C++
Raw Normal View History

2024-05-27 10:35:06 +02:00
//
// Copyright (c) 2023-2024 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 <boost/test/unit_test.hpp>
2023-12-06 08:25:12 +01:00
#include <boost/asio/use_awaitable.hpp>
#ifdef BOOST_ASIO_HAS_CO_AWAIT
2024-10-08 09:59:35 +02:00
#include <chrono>
#include <boost/asio/as_tuple.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/steady_timer.hpp>
2023-12-07 15:41:31 +01:00
#include <boost/asio/ssl.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/beast/ssl/ssl_stream.hpp> // async_teardown specialization for websocket ssl stream
2024-10-08 09:59:35 +02:00
#include <boost/system/error_code.hpp>
2023-10-06 11:51:04 +02:00
#include <async_mqtt5.hpp>
2023-12-07 15:41:31 +01:00
namespace async_mqtt5 {
template <typename StreamBase>
struct tls_handshake_type<asio::ssl::stream<StreamBase>> {
static constexpr auto client = asio::ssl::stream_base::client;
static constexpr auto server = asio::ssl::stream_base::server;
};
template <typename StreamBase>
void assign_tls_sni(
const authority_path& ap,
2024-01-02 11:40:53 +01:00
asio::ssl::context& /* ctx */,
2023-12-07 15:41:31 +01:00
asio::ssl::stream<StreamBase>& stream
) {
SSL_set_tlsext_host_name(stream.native_handle(), ap.host.c_str());
}
} // end namespace async_mqtt5
2024-05-02 13:04:21 +02:00
BOOST_AUTO_TEST_SUITE(client/*, *boost::unit_test::disabled()*/)
using namespace async_mqtt5;
namespace asio = boost::asio;
constexpr auto use_nothrow_awaitable = asio::as_tuple(asio::use_awaitable);
template<typename StreamType, typename TlsContext>
2024-05-02 13:04:21 +02:00
asio::awaitable<void> test_client(mqtt_client<StreamType, TlsContext>& c) {
// Note: Older versions of GCC compilers may not handle temporaries
// correctly in co_await expressions.
// (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98401)
publish_props pub_props;
auto [ec_0] = co_await c.template async_publish<qos_e::at_most_once>(
"test/mqtt-test", "hello world with qos0!", retain_e::yes, pub_props,
use_nothrow_awaitable
);
2024-02-05 12:11:35 +01:00
BOOST_TEST_WARN(!ec_0);
auto [ec_1, puback_rc, puback_props] = co_await c.template async_publish<qos_e::at_least_once>(
"test/mqtt-test", "hello world with qos1!",
retain_e::yes, pub_props,
use_nothrow_awaitable
);
2024-02-05 12:11:35 +01:00
BOOST_TEST_WARN(!ec_1);
BOOST_TEST_WARN(!puback_rc);
auto [ec_2, pubcomp_rc, pubcomp_props] = co_await c.template async_publish<qos_e::exactly_once>(
"test/mqtt-test", "hello world with qos2!",
retain_e::yes, pub_props,
use_nothrow_awaitable
);
2024-02-05 12:11:35 +01:00
BOOST_TEST_WARN(!ec_2);
BOOST_TEST_WARN(!pubcomp_rc);
2024-01-10 12:37:55 +01:00
subscribe_topic sub_topic = subscribe_topic {
"test/mqtt-test", async_mqtt5::subscribe_options {
2024-02-05 12:11:35 +01:00
qos_e::at_least_once,
2024-02-02 09:23:40 +01:00
no_local_e::no,
retain_as_published_e::retain,
retain_handling_e::send
}
2024-01-10 12:37:55 +01:00
};
subscribe_props sub_props;
auto [sub_ec, sub_codes, suback_props] = co_await c.async_subscribe(
sub_topic, sub_props, use_nothrow_awaitable
);
2024-02-05 12:11:35 +01:00
BOOST_TEST_WARN(!sub_ec);
if (!sub_codes[0])
auto [rec, topic, payload, publish_props] = co_await c.async_receive(use_nothrow_awaitable);
unsubscribe_props unsub_props;
auto [unsub_ec, unsub_codes, unsuback_props] = co_await c.async_unsubscribe(
"test/mqtt-test", unsub_props,
use_nothrow_awaitable
);
2024-02-05 12:11:35 +01:00
BOOST_TEST_WARN(!unsub_ec);
BOOST_TEST_WARN(!unsub_codes[0]);
co_await c.async_disconnect(use_nothrow_awaitable);
co_return;
}
BOOST_AUTO_TEST_CASE(tcp_client_check) {
asio::io_context ioc;
using stream_type = asio::ip::tcp::socket;
using client_type = mqtt_client<stream_type>;
client_type c(ioc);
2024-01-18 10:37:13 +01:00
c.brokers("broker.hivemq.com", 1883)
2024-01-16 13:04:21 +01:00
.async_run(asio::detached);
asio::steady_timer timer(ioc);
2023-12-07 15:41:31 +01:00
timer.expires_after(std::chrono::seconds(5));
timer.async_wait(
[&](boost::system::error_code ec) {
2024-02-05 12:11:35 +01:00
BOOST_TEST_WARN(ec, "Failed to receive all the expected replies!");
c.cancel();
}
);
co_spawn(ioc,
[&]() -> asio::awaitable<void> {
2024-05-02 13:04:21 +02:00
co_await test_client(c);
timer.cancel();
},
asio::detached
);
ioc.run();
}
BOOST_AUTO_TEST_CASE(websocket_tcp_client_check) {
asio::io_context ioc;
using stream_type = boost::beast::websocket::stream<
asio::ip::tcp::socket
>;
using client_type = mqtt_client<stream_type>;
client_type c(ioc);
2024-01-16 10:25:05 +01:00
c.brokers("broker.hivemq.com/mqtt", 8000)
2024-01-16 13:04:21 +01:00
.async_run(asio::detached);
asio::steady_timer timer(ioc);
2023-12-07 15:41:31 +01:00
timer.expires_after(std::chrono::seconds(5));
timer.async_wait(
[&](boost::system::error_code ec) {
2024-02-05 12:11:35 +01:00
BOOST_TEST_WARN(ec, "Failed to receive all the expected replies!");
2023-12-07 15:41:31 +01:00
c.cancel();
}
);
co_spawn(ioc,
[&]() -> asio::awaitable<void> {
2024-05-02 13:04:21 +02:00
co_await test_client(c);
2023-12-07 15:41:31 +01:00
timer.cancel();
},
asio::detached
);
ioc.run();
}
BOOST_AUTO_TEST_CASE(openssl_tls_client_check) {
asio::io_context ioc;
using stream_type = asio::ssl::stream<asio::ip::tcp::socket>;
asio::ssl::context tls_context(asio::ssl::context::tls_client);
using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, std::move(tls_context));
2023-12-07 15:41:31 +01:00
2024-01-16 10:25:05 +01:00
c.brokers("broker.hivemq.com", 8883)
2024-01-16 13:04:21 +01:00
.async_run(asio::detached);
2023-12-07 15:41:31 +01:00
asio::steady_timer timer(ioc);
timer.expires_after(std::chrono::seconds(5));
timer.async_wait(
[&](boost::system::error_code ec) {
2024-02-05 12:11:35 +01:00
BOOST_TEST_WARN(ec, "Failed to receive all the expected replies!");
2023-12-07 15:41:31 +01:00
c.cancel();
}
);
co_spawn(ioc,
[&]() -> asio::awaitable<void> {
2024-05-02 13:04:21 +02:00
co_await test_client(c);
2023-12-07 15:41:31 +01:00
timer.cancel();
},
asio::detached
);
ioc.run();
}
BOOST_AUTO_TEST_CASE(websocket_tls_client_check) {
asio::io_context ioc;
using stream_type = boost::beast::websocket::stream<
asio::ssl::stream<asio::ip::tcp::socket>
>;
asio::ssl::context tls_context(asio::ssl::context::tls_client);
using client_type = mqtt_client<stream_type, decltype(tls_context)>;
client_type c(ioc, std::move(tls_context));
2023-12-07 15:41:31 +01:00
2024-01-16 10:25:05 +01:00
c.brokers("broker.hivemq.com/mqtt", 8884)
2024-01-16 13:04:21 +01:00
.async_run(asio::detached);
2023-12-07 15:41:31 +01:00
asio::steady_timer timer(ioc);
timer.expires_after(std::chrono::seconds(5));
timer.async_wait(
[&](boost::system::error_code ec) {
2024-02-05 12:11:35 +01:00
BOOST_TEST_WARN(ec, "Failed to receive all the expected replies!");
c.cancel();
}
);
2023-11-24 11:50:47 +01:00
co_spawn(ioc,
[&]() -> asio::awaitable<void> {
2024-05-02 13:04:21 +02:00
co_await test_client(c);
timer.cancel();
},
asio::detached
);
ioc.run();
}
BOOST_AUTO_TEST_SUITE_END()
2023-12-06 08:25:12 +01:00
#endif