@@ -40,6 +40,7 @@ void logger_test() {
4040 BOOST_STATIC_ASSERT (has_at_ws_handshake<logger>);
4141 BOOST_STATIC_ASSERT (has_at_connack<logger>);
4242 BOOST_STATIC_ASSERT (has_at_disconnect<logger>);
43+ BOOST_STATIC_ASSERT (has_at_transport_error<logger>);
4344}
4445
4546BOOST_AUTO_TEST_SUITE (logger_tests)
@@ -417,6 +418,19 @@ BOOST_FIXTURE_TEST_CASE(at_disconnect_debug, disconnect_test_data) {
417418 test_logger_output (std::move (test_fun), expected_output);
418419}
419420
421+ // at_transport_error
422+
423+ BOOST_AUTO_TEST_CASE (at_transport_error_info) {
424+ const auto expected_output = " [Boost.MQTT5] transport layer error: End of file.\n " ;
425+
426+ auto test_fun = [] {
427+ logger l (log_level::info);
428+ l.at_transport_error (asio::error::eof);
429+ };
430+
431+ test_logger_output (std::move (test_fun), expected_output);
432+ }
433+
420434// Test that the mqtt_client calls logger functions as expected.
421435
422436BOOST_AUTO_TEST_CASE (client_disconnect) {
@@ -477,6 +491,65 @@ BOOST_AUTO_TEST_CASE(client_disconnect) {
477491 BOOST_TEST (log == expected_msg);
478492}
479493
494+ BOOST_AUTO_TEST_CASE (client_transport_error) {
495+ using test::after;
496+ using namespace std ::chrono_literals;
497+
498+ const auto & success = success_msg ();
499+ const auto expected_msg =
500+ " [Boost.MQTT5] resolve: 127.0.0.1:1883 - " + success + " .\n "
501+ " [Boost.MQTT5] TCP connect: 127.0.0.1:1883 - " + success + " .\n "
502+ " [Boost.MQTT5] transport layer error: End of file.\n "
503+ " [Boost.MQTT5] resolve: 127.0.0.1:1883 - " + success + " .\n "
504+ " [Boost.MQTT5] TCP connect: 127.0.0.1:1883 - " + success + " .\n "
505+ " [Boost.MQTT5] connack: The operation completed successfully.\n "
506+ ;
507+
508+ boost::test_tools::output_test_stream output;
509+ {
510+ clog_redirect guard (output.rdbuf ());
511+
512+ // packets
513+ auto connect = encoders::encode_connect (
514+ " " , std::nullopt , std::nullopt , 60 , false , test::dflt_cprops, std::nullopt
515+ );
516+ auto connack = encoders::encode_connack (false , uint8_t (0x00 ), {});
517+
518+ const std::string topic = " topic" , payload = " payload0" ;
519+ const std::string publish = encoders::encode_publish (
520+ 0 , topic, payload, qos_e::at_most_once, retain_e::no, dup_e::no, {}
521+ );
522+
523+ test::msg_exchange broker_side;
524+ broker_side
525+ .expect (connect)
526+ .complete_with (asio::error::eof, after (0ms))
527+ .expect (connect)
528+ .complete_with (error_code{}, after (0ms))
529+ .reply_with (connack, after (10ms));
530+
531+ asio::io_context ioc;
532+ auto executor = ioc.get_executor ();
533+ auto & broker = asio::make_service<test::test_broker>(
534+ ioc, executor, std::move (broker_side)
535+ );
536+
537+ mqtt_client<test::test_stream, std::monostate, logger> c (executor);
538+ c.brokers (" 127.0.0.1,127.0.0.1" ) // to avoid reconnect backoff
539+ .async_run (asio::detached);
540+
541+ asio::steady_timer timer (c.get_executor ());
542+ timer.expires_after (100ms);
543+ timer.async_wait ([&c](error_code) { c.cancel (); });
544+
545+ ioc.run ();
546+ BOOST_TEST (broker.received_all_expected ());
547+ }
548+
549+ std::string log = output.rdbuf ()->str ();
550+ BOOST_TEST (log == expected_msg);
551+ }
552+
480553#ifdef BOOST_MQTT5_EXTRA_DEPS
481554using stream_type = boost::beast::websocket::stream<
482555 asio::ssl::stream<asio::ip::tcp::socket>
0 commit comments