mirror of
https://github.com/boostorg/mqtt5.git
synced 2025-07-30 20:47:37 +02:00
Separate tests into unit & integration
Summary: - Separate tests into unit & integration - Update paths in workflows - Cut test execution time Reviewers: ivica Reviewed By: ivica Subscribers: miljen, iljazovic Differential Revision: https://repo.mireo.local/D27374
This commit is contained in:
12
.github/workflows/ci.yml
vendored
12
.github/workflows/ci.yml
vendored
@ -96,15 +96,15 @@ jobs:
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cmake -S test\\unit -B test\\unit\\build -A ${{ matrix.architecture }} ^
|
||||
cmake -S test -B test\\build -A ${{ matrix.architecture }} ^
|
||||
-DCMAKE_CXX_FLAGS="${{ env.CXXFLAGS }}" -DCMAKE_EXE_LINKER_FLAGS="${{ env.LDFLAGS }}" ^
|
||||
-DCMAKE_CXX_STANDARD="${{ matrix.cxxstd }}" -DCMAKE_BUILD_TYPE="${{ matrix.build-type }}" ^
|
||||
-DBoost_INCLUDE_DIR="${{ github.workspace }}\\boost_${{ env.BOOST_DIR_VER_NAME }}"
|
||||
cmake --build test\\unit\\build -j 4
|
||||
cmake --build test\\build -j 4
|
||||
|
||||
- name: Run tests
|
||||
run: |
|
||||
.\\test\\unit\\build\\${{ matrix.build-type }}\\mqtt-test.exe --log_level=test_suite
|
||||
.\\test\\build\\${{ matrix.build-type }}\\mqtt-test.exe --log_level=test_suite
|
||||
|
||||
posix:
|
||||
name: "${{ matrix.toolset }} std=c++${{ matrix.cxxstd }} ${{ matrix.build-type }}"
|
||||
@ -193,11 +193,11 @@ jobs:
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cmake -S test/unit -B test/unit/build \
|
||||
cmake -S test -B test/build \
|
||||
-DCMAKE_CXX_COMPILER="${{ matrix.compiler }}" -DCMAKE_CXX_FLAGS="${{ env.CXXFLAGS }}" \
|
||||
-DCMAKE_CXX_STANDARD="${{ matrix.cxxstd }}" -DCMAKE_EXE_LINKER_FLAGS="${{ env.LDFLAGS }}" -DCMAKE_BUILD_TYPE="${{ matrix.build-type }}" \
|
||||
-DBoost_INCLUDE_DIR="/usr/local/boost_${{ env.BOOST_DIR_VER_NAME }}"
|
||||
cmake --build test/unit/build -j 4
|
||||
cmake --build test/build -j 4
|
||||
|
||||
- name: Run tests
|
||||
run: ./test/unit/build/mqtt-test --log_level=test_suite
|
||||
run: ./test/build/mqtt-test --log_level=test_suite
|
||||
|
8
.github/workflows/coverage.yml
vendored
8
.github/workflows/coverage.yml
vendored
@ -60,17 +60,17 @@ jobs:
|
||||
|
||||
- name: Build tests
|
||||
run: |
|
||||
cmake -S test/unit -B test/unit/build -DCMAKE_CXX_COMPILER="${{ matrix.compiler }}" -DCMAKE_CXX_FLAGS="${{ matrix.cxxflags }}" \
|
||||
cmake -S test -B test/build -DCMAKE_CXX_COMPILER="${{ matrix.compiler }}" -DCMAKE_CXX_FLAGS="${{ matrix.cxxflags }}" \
|
||||
-DCMAKE_EXE_LINKER_FLAGS="${{ matrix.ldflags }}" -DCMAKE_BUILD_TYPE="Coverage" \
|
||||
-DBoost_INCLUDE_DIR="/usr/local/boost_${{ env.BOOST_DIR_VER_NAME }}"
|
||||
cmake --build test/unit/build -j 4
|
||||
cmake --build test/build -j 4
|
||||
|
||||
- name: Run tests
|
||||
run: ./test/unit/build/mqtt-test --log_level=test_suite
|
||||
run: ./test/build/mqtt-test --log_level=test_suite
|
||||
|
||||
- name: Generate Coverage Report
|
||||
run: |
|
||||
lcov --capture --output-file coverage.info --directory test/unit/build
|
||||
lcov --capture --output-file coverage.info --directory test/build
|
||||
lcov --remove coverage.info '/usr/include/*' --output-file coverage.info
|
||||
lcov --remove coverage.info '**/test/*' --output-file coverage.info
|
||||
lcov --remove coverage.info '**/boost/*' --output-file coverage.info
|
||||
|
23
test/CMakeLists.txt
Normal file
23
test/CMakeLists.txt
Normal file
@ -0,0 +1,23 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(async-mqtt5-tests CXX)
|
||||
|
||||
include(../cmake/project-is-top-level.cmake)
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
find_package(async-mqtt5 REQUIRED)
|
||||
enable_testing()
|
||||
endif()
|
||||
|
||||
file(GLOB integration_tests "integration/*.cpp")
|
||||
file(GLOB unit_tests "unit/*.cpp")
|
||||
|
||||
add_executable(mqtt-test src/run_tests.cpp ${integration_tests} ${unit_tests})
|
||||
|
||||
target_include_directories(mqtt-test PRIVATE include)
|
||||
target_compile_definitions(mqtt-test PRIVATE BOOST_TEST_NO_MAIN=1)
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
target_link_libraries(mqtt-test PRIVATE Async::MQTT5 OpenSSL::SSL)
|
||||
|
||||
add_test(NAME mqtt-test COMMAND mqtt-test)
|
@ -288,61 +288,4 @@ private:
|
||||
|
||||
} // end namespace async_mqtt5::test
|
||||
|
||||
|
||||
|
||||
// Funs temporarily moved out of network service
|
||||
//
|
||||
//void process_packet(const std::string& packet) {
|
||||
// using enum control_code_e;
|
||||
//
|
||||
// auto code = extract_code(uint8_t(*packet.data()));
|
||||
// if (code == connack)
|
||||
// determine_network_properties(packet);
|
||||
// else if (code == puback || code == pubcomp)
|
||||
// _num_outgoing_publishes--;
|
||||
//}
|
||||
//
|
||||
//void determine_network_properties(const std::string& connack) {
|
||||
// auto begin = connack.cbegin() + 1 /* fixed header */;
|
||||
// auto _ = decoders::type_parse(begin, connack.cend(), decoders::basic::varint_);
|
||||
// auto rv = decoders::decode_connack(connack.size(), begin);
|
||||
// const auto& [session_present, reason_code, ca_props] = *rv;
|
||||
//
|
||||
// if (ca_props[prop::receive_maximum])
|
||||
// _max_receive = *ca_props[prop::receive_maximum];
|
||||
// else
|
||||
// _max_receive = MAX_LIMIT;
|
||||
//}
|
||||
//
|
||||
//void count_outgoing_publishes(
|
||||
// const std::vector<std::string>& packets
|
||||
//) {
|
||||
// for (const auto& packet : packets) {
|
||||
// auto code = extract_code(uint8_t(*packet.data()));
|
||||
// if (code == control_code_e::publish) {
|
||||
// auto flags = *packet.data() & 0b00001111;
|
||||
// auto qos = extract_qos(flags);
|
||||
//
|
||||
// if (qos != qos_e::at_most_once)
|
||||
// _num_outgoing_publishes++;
|
||||
//
|
||||
// BOOST_ASIO_CHECK_MESSAGE(
|
||||
// _num_outgoing_publishes <= _max_receive,
|
||||
// "There are more outgoing PUBLISH packets than\
|
||||
// it is allowed by the Maxmimum Receive Limit!"
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
// write_to_network stuff
|
||||
|
||||
//auto packets = to_packets(buffers);
|
||||
//count_outgoing_publishes(packets);
|
||||
//// TODO: this is just for debug right now
|
||||
//if (!write_ec)
|
||||
// for (const auto& packet : packets)
|
||||
// test::log(to_readable_packet(packet, write_ec, false));
|
||||
|
||||
#endif // ASYNC_MQTT5_TEST_TEST_BROKER_HPP
|
@ -190,8 +190,7 @@ BOOST_AUTO_TEST_CASE(rerunning_the_client) {
|
||||
using client_type = mqtt_client<stream_type>;
|
||||
client_type c(ioc, "");
|
||||
|
||||
c.brokers("broker.hivemq.com", 1883)
|
||||
.credentials("test-cli", "", "")
|
||||
c.brokers("broker.hivemq.com,broker.hivemq.com", 1883) // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
auto [ec] = co_await c.async_publish<qos_e::at_most_once>(
|
@ -149,8 +149,7 @@ BOOST_AUTO_TEST_CASE(websocket_tcp_client_check) {
|
||||
using client_type = mqtt_client<stream_type>;
|
||||
client_type c(ioc, "");
|
||||
|
||||
c.credentials("websocket-tcp-tester", "", "")
|
||||
.brokers("broker.hivemq.com/mqtt", 8000)
|
||||
c.brokers("broker.hivemq.com/mqtt", 8000)
|
||||
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
|
||||
.run();
|
||||
|
||||
@ -186,8 +185,7 @@ BOOST_AUTO_TEST_CASE(openssl_tls_client_check) {
|
||||
using client_type = mqtt_client<stream_type, decltype(tls_context)>;
|
||||
client_type c(ioc, "", std::move(tls_context));
|
||||
|
||||
c.credentials("openssl-tls-tester", "", "")
|
||||
.brokers("broker.hivemq.com", 8883)
|
||||
c.brokers("broker.hivemq.com", 8883)
|
||||
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
|
||||
.run();
|
||||
|
||||
@ -225,8 +223,7 @@ BOOST_AUTO_TEST_CASE(websocket_tls_client_check) {
|
||||
using client_type = mqtt_client<stream_type, decltype(tls_context)>;
|
||||
client_type c(ioc, "", std::move(tls_context));
|
||||
|
||||
c.credentials("websocket-tls-tester", "", "")
|
||||
.brokers("broker.hivemq.com/mqtt", 8884)
|
||||
c.brokers("broker.hivemq.com/mqtt", 8884)
|
||||
.will({ "test/mqtt-test", "Client disconnected!", qos_e::at_least_once })
|
||||
.run();
|
||||
|
@ -1,193 +1,14 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#include <async_mqtt5/mqtt_client.hpp>
|
||||
|
||||
#include <async_mqtt5/impl/publish_rec_op.hpp>
|
||||
|
||||
#include "test_common/message_exchange.hpp"
|
||||
#include "test_common/test_service.hpp"
|
||||
#include "test_common/test_stream.hpp"
|
||||
|
||||
using namespace async_mqtt5;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(publish_rec_op/*, *boost::unit_test::disabled()*/)
|
||||
|
||||
template <qos_e qos>
|
||||
void receive_publish() {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
std::string topic = "topic";
|
||||
std::string payload = "payload";
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(
|
||||
false, reason_codes::success.value(), {}
|
||||
);
|
||||
|
||||
auto publish = encoders::encode_publish(
|
||||
1, topic, payload, qos, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
|
||||
auto puback = encoders::encode_puback(1, reason_codes::success.value(), {});
|
||||
|
||||
auto pubrec = encoders::encode_pubrec(1, reason_codes::success.value(), {});
|
||||
auto pubrel = encoders::encode_pubrel(1, reason_codes::success.value(), {});
|
||||
auto pubcomp = encoders::encode_pubcomp(1, reason_codes::success.value(), {});
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.send(publish, after(10ms));
|
||||
|
||||
if constexpr (qos == qos_e::at_least_once) {
|
||||
broker_side
|
||||
.expect(puback)
|
||||
.complete_with(success, after(1ms));
|
||||
} else if constexpr (qos == qos_e::exactly_once) {
|
||||
broker_side
|
||||
.expect(pubrec)
|
||||
.complete_with(success, after(1ms))
|
||||
.reply_with(pubrel, after(2ms))
|
||||
.expect(pubcomp)
|
||||
.complete_with(success, after(1ms));
|
||||
}
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
.run();
|
||||
|
||||
c.async_receive(
|
||||
[&](
|
||||
error_code ec,
|
||||
std::string rec_topic, std::string rec_payload,
|
||||
publish_props
|
||||
) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_EQUAL(topic, rec_topic);
|
||||
BOOST_CHECK_EQUAL(payload, rec_payload);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(10));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(receive_publish_qos0) {
|
||||
receive_publish<qos_e::at_most_once>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(receive_publish_qos1) {
|
||||
receive_publish<qos_e::at_least_once>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(receive_publish_qos2) {
|
||||
receive_publish<qos_e::exactly_once>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_reconnect) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
std::string topic = "topic";
|
||||
std::string payload = "payload";
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(
|
||||
false, reason_codes::success.value(), {}
|
||||
);
|
||||
|
||||
auto publish = encoders::encode_publish(
|
||||
1, topic, payload, qos_e::exactly_once, retain_e::yes, dup_e::no, {}
|
||||
);
|
||||
|
||||
auto pubrec = encoders::encode_pubrec(1, reason_codes::success.value(), {});
|
||||
auto pubrel = encoders::encode_pubrel(1, reason_codes::success.value(), {});
|
||||
auto pubcomp = encoders::encode_pubcomp(1, reason_codes::success.value(), {});
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
error_code fail = asio::error::not_connected;
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.send(publish, after(10ms))
|
||||
.expect(pubrec)
|
||||
.complete_with(success, after(1ms))
|
||||
.reply_with(pubrel, after(2ms))
|
||||
.expect(pubcomp)
|
||||
.complete_with(fail, after(1ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.send(pubrel, after(10ms))
|
||||
.expect(pubcomp)
|
||||
.complete_with(success, after(1ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
.run();
|
||||
|
||||
c.async_receive(
|
||||
[&](
|
||||
error_code ec,
|
||||
std::string rec_topic, std::string rec_payload,
|
||||
publish_props
|
||||
) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_EQUAL(topic, rec_topic);
|
||||
BOOST_CHECK_EQUAL(payload, rec_payload);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(10));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
BOOST_AUTO_TEST_SUITE(malformed_packet/* , *boost::unit_test::disabled()*/)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_malformed_publish) {
|
||||
using test::after;
|
||||
@ -230,11 +51,11 @@ BOOST_AUTO_TEST_CASE(test_malformed_publish) {
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::seconds(4));
|
||||
timer.expires_after(std::chrono::seconds(2));
|
||||
timer.async_wait([&](auto) { c.cancel(); });
|
||||
|
||||
ioc.run();
|
||||
@ -303,7 +124,7 @@ BOOST_AUTO_TEST_CASE(test_malformed_pubrel, *boost::unit_test::disabled()) {
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
c.async_receive(
|
||||
@ -322,7 +143,180 @@ BOOST_AUTO_TEST_CASE(test_malformed_pubrel, *boost::unit_test::disabled()) {
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(10));
|
||||
ioc.run_for(std::chrono::seconds(2));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(malformed_puback) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(false, reason_codes::success.value(), {});
|
||||
|
||||
auto publish = encoders::encode_publish(
|
||||
1, "t", "p", qos_e::at_least_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
auto malformed_puback = encoders::encode_puback(1, uint8_t(0x04), {});
|
||||
|
||||
auto publish_dup = encoders::encode_publish(
|
||||
1, "t", "p", qos_e::at_least_once, retain_e::no, dup_e::yes, {}
|
||||
);
|
||||
auto puback = encoders::encode_puback(1, reason_codes::success.value(), {});
|
||||
|
||||
disconnect_props dc_props;
|
||||
dc_props[prop::reason_string] = "Malformed PUBACK: invalid Reason Code";
|
||||
auto disconnect = encoders::encode_disconnect(
|
||||
reason_codes::malformed_packet.value(), dc_props
|
||||
);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(publish)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(malformed_puback, after(0ms))
|
||||
.expect(disconnect)
|
||||
.complete_with(success, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(publish_dup)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(puback, after(0ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::at_least_once>(
|
||||
"t", "p", retain_e::no, publish_props {},
|
||||
[&](error_code ec, reason_code rc, auto) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK_EQUAL(rc, reason_codes::success);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(2));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(malformed_pubrec_pubcomp) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(false, reason_codes::success.value(), {});
|
||||
|
||||
auto publish = encoders::encode_publish(
|
||||
1, "t", "p", qos_e::exactly_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
auto malformed_pubrec = encoders::encode_pubrec(1, uint8_t(0x04), {});
|
||||
|
||||
auto publish_dup = encoders::encode_publish(
|
||||
1, "t", "p", qos_e::exactly_once, retain_e::no, dup_e::yes, {}
|
||||
);
|
||||
auto pubrec = encoders::encode_pubrec(1, reason_codes::success.value(), {});
|
||||
|
||||
auto pubrel = encoders::encode_pubrel(1, reason_codes::success.value(), {});
|
||||
auto malformed_pubcomp = encoders::encode_pubcomp(1, uint8_t(0x04), {});
|
||||
auto pubcomp = encoders::encode_pubcomp(1, reason_codes::success.value(), {});
|
||||
|
||||
disconnect_props dc_props;
|
||||
dc_props[prop::reason_string] = "Malformed PUBREC: invalid Reason Code";
|
||||
auto disconnect_on_pubrec = encoders::encode_disconnect(
|
||||
reason_codes::malformed_packet.value(), dc_props
|
||||
);
|
||||
|
||||
dc_props[prop::reason_string] = "Malformed PUBCOMP: invalid Reason Code";
|
||||
auto disconnect_on_pubcomp = encoders::encode_disconnect(
|
||||
reason_codes::malformed_packet.value(), dc_props
|
||||
);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(publish)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(malformed_pubrec, after(0ms))
|
||||
.expect(disconnect_on_pubrec)
|
||||
.complete_with(success, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(publish_dup)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(pubrec, after(0ms))
|
||||
.expect(pubrel)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(malformed_pubcomp, after(0ms))
|
||||
.expect(disconnect_on_pubcomp)
|
||||
.complete_with(success, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(pubrel)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(pubcomp, after(0ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::exactly_once>(
|
||||
"t", "p", retain_e::no, publish_props {},
|
||||
[&](error_code ec, reason_code rc, auto) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK_EQUAL(rc, reason_codes::success);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(6));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
190
test/integration/publish_receive.cpp
Normal file
190
test/integration/publish_receive.cpp
Normal file
@ -0,0 +1,190 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#include <async_mqtt5/mqtt_client.hpp>
|
||||
|
||||
#include "test_common/message_exchange.hpp"
|
||||
#include "test_common/test_service.hpp"
|
||||
#include "test_common/test_stream.hpp"
|
||||
|
||||
using namespace async_mqtt5;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(publish_receive/*, *boost::unit_test::disabled()*/)
|
||||
|
||||
template <qos_e qos>
|
||||
void receive_publish() {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
std::string topic = "topic";
|
||||
std::string payload = "payload";
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(
|
||||
false, reason_codes::success.value(), {}
|
||||
);
|
||||
|
||||
auto publish = encoders::encode_publish(
|
||||
1, topic, payload, qos, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
|
||||
auto puback = encoders::encode_puback(1, reason_codes::success.value(), {});
|
||||
|
||||
auto pubrec = encoders::encode_pubrec(1, reason_codes::success.value(), {});
|
||||
auto pubrel = encoders::encode_pubrel(1, reason_codes::success.value(), {});
|
||||
auto pubcomp = encoders::encode_pubcomp(1, reason_codes::success.value(), {});
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.send(publish, after(10ms));
|
||||
|
||||
if constexpr (qos == qos_e::at_least_once) {
|
||||
broker_side
|
||||
.expect(puback)
|
||||
.complete_with(success, after(1ms));
|
||||
} else if constexpr (qos == qos_e::exactly_once) {
|
||||
broker_side
|
||||
.expect(pubrec)
|
||||
.complete_with(success, after(1ms))
|
||||
.reply_with(pubrel, after(2ms))
|
||||
.expect(pubcomp)
|
||||
.complete_with(success, after(1ms));
|
||||
}
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
.run();
|
||||
|
||||
c.async_receive(
|
||||
[&](
|
||||
error_code ec,
|
||||
std::string rec_topic, std::string rec_payload,
|
||||
publish_props
|
||||
) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_EQUAL(topic, rec_topic);
|
||||
BOOST_CHECK_EQUAL(payload, rec_payload);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(10));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_receive_publish_qos0) {
|
||||
receive_publish<qos_e::at_most_once>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_receive_publish_qos1) {
|
||||
receive_publish<qos_e::at_least_once>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_receive_publish_qos2) {
|
||||
receive_publish<qos_e::exactly_once>();
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_waiting_on_pubrel) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
std::string topic = "topic";
|
||||
std::string payload = "payload";
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(
|
||||
false, reason_codes::success.value(), {}
|
||||
);
|
||||
|
||||
auto publish = encoders::encode_publish(
|
||||
1, topic, payload, qos_e::exactly_once, retain_e::yes, dup_e::no, {}
|
||||
);
|
||||
|
||||
auto pubrec = encoders::encode_pubrec(1, reason_codes::success.value(), {});
|
||||
auto pubrel = encoders::encode_pubrel(1, reason_codes::success.value(), {});
|
||||
auto pubcomp = encoders::encode_pubcomp(1, reason_codes::success.value(), {});
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
error_code fail = asio::error::not_connected;
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.send(publish, after(10ms))
|
||||
.expect(pubrec)
|
||||
.complete_with(success, after(1ms))
|
||||
.reply_with(pubrel, after(2ms))
|
||||
.expect(pubcomp)
|
||||
.complete_with(fail, after(1ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.send(pubrel, after(10ms))
|
||||
.expect(pubcomp)
|
||||
.complete_with(success, after(1ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
c.async_receive(
|
||||
[&](
|
||||
error_code ec,
|
||||
std::string rec_topic, std::string rec_payload,
|
||||
publish_props
|
||||
) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_EQUAL(topic, rec_topic);
|
||||
BOOST_CHECK_EQUAL(payload, rec_payload);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(10));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
@ -1,240 +1,19 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <chrono>
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#include <async_mqtt5/impl/codecs/message_encoders.hpp>
|
||||
|
||||
#include <async_mqtt5.hpp>
|
||||
#include <async_mqtt5/mqtt_client.hpp>
|
||||
|
||||
#include "test_common/message_exchange.hpp"
|
||||
#include "test_common/test_service.hpp"
|
||||
#include "test_common/test_stream.hpp"
|
||||
|
||||
using namespace async_mqtt5;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(framework/*, *boost::unit_test::disabled()*/)
|
||||
BOOST_AUTO_TEST_SUITE(publish_send/*, *boost::unit_test::disabled()*/)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(publish_qos_0) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(
|
||||
false, reason_codes::success.value(), {}
|
||||
);
|
||||
auto publish_1 = encoders::encode_publish(
|
||||
1, "t", "p_1", qos_e::at_most_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(connack, after(20ms))
|
||||
.expect(publish_1);
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::at_most_once>(
|
||||
"t", "p_1", retain_e::no, publish_props{},
|
||||
[&](error_code ec) {
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
++handlers_called;
|
||||
}
|
||||
);
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::seconds(1));
|
||||
timer.async_wait([&](auto) { c.cancel(); });
|
||||
|
||||
|
||||
ioc.run();
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(two_publishes_qos_1_with_fail_on_write) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 2;
|
||||
int handlers_called = 0;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(
|
||||
false, reason_codes::success.value(), {}
|
||||
);
|
||||
auto publish_1 = encoders::encode_publish(
|
||||
1, "t", "p_1", qos_e::at_least_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
auto puback_1 = encoders::encode_puback(
|
||||
1, reason_codes::success.value(), {}
|
||||
);
|
||||
auto publish_2 = encoders::encode_publish(
|
||||
2, "t", "p_2", qos_e::at_least_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
auto puback_2 = encoders::encode_puback(
|
||||
2, reason_codes::success.value(), {}
|
||||
);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
error_code fail = asio::error::not_connected;
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(connack, after(10ms))
|
||||
.expect(publish_1, publish_2)
|
||||
.complete_with(fail, after(10ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(connack, after(10ms))
|
||||
.expect(publish_1, publish_2)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(puback_1, puback_2, after(20ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::at_least_once>(
|
||||
"t", "p_1", retain_e::no, publish_props{},
|
||||
[&](error_code ec, reason_code rc, auto) {
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_MESSAGE(!rc, rc.message());
|
||||
++handlers_called;
|
||||
}
|
||||
);
|
||||
|
||||
c.async_publish<qos_e::at_least_once>(
|
||||
"t", "p_2", retain_e::no, publish_props{},
|
||||
[&](error_code ec, reason_code rc, auto) {
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_MESSAGE(!rc, rc.message());
|
||||
++handlers_called;
|
||||
}
|
||||
);
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::seconds(6));
|
||||
timer.async_wait([&](auto) { c.cancel(); });
|
||||
|
||||
ioc.run();
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(send_publish_qos_2_with_fail_on_read) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(
|
||||
false, reason_codes::success.value(), {}
|
||||
);
|
||||
auto publish = encoders::encode_publish(
|
||||
1, "t_1", "p_1", qos_e::exactly_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
auto pubrec = encoders::encode_pubrec(
|
||||
1, reason_codes::success.value(), {}
|
||||
);
|
||||
auto pubrel = encoders::encode_pubrel(
|
||||
1, reason_codes::success.value(), {}
|
||||
);
|
||||
auto pubcomp = encoders::encode_pubcomp(
|
||||
1, reason_codes::success.value(), {}
|
||||
);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
error_code fail = asio::error::not_connected;
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(connack, after(20ms))
|
||||
.expect(publish)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(pubrec, after(25ms))
|
||||
.expect(pubrel)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(fail, after(10ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(connack, after(20ms))
|
||||
.expect(pubrel)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(pubcomp, after(20ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
|
||||
c.brokers("127.0.0.1")
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::exactly_once>(
|
||||
"t_1", "p_1", retain_e::no, publish_props{},
|
||||
[&](error_code ec, reason_code rc, auto) {
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_MESSAGE(!rc, rc.message());
|
||||
++handlers_called;
|
||||
}
|
||||
);
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::seconds(7));
|
||||
timer.async_wait([&](auto) { c.cancel(); });
|
||||
|
||||
ioc.run();
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_ordering_after_reconnect) {
|
||||
BOOST_AUTO_TEST_CASE(ordering_after_reconnect) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
@ -299,7 +78,7 @@ BOOST_AUTO_TEST_CASE(test_ordering_after_reconnect) {
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::at_least_once>(
|
||||
@ -308,6 +87,9 @@ BOOST_AUTO_TEST_CASE(test_ordering_after_reconnect) {
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_MESSAGE(!rc, rc.message());
|
||||
++handlers_called;
|
||||
|
||||
if (handlers_called == expected_handlers_called)
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
@ -317,14 +99,13 @@ BOOST_AUTO_TEST_CASE(test_ordering_after_reconnect) {
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_MESSAGE(!rc, rc.message());
|
||||
++handlers_called;
|
||||
|
||||
if (handlers_called == expected_handlers_called)
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::seconds(7));
|
||||
timer.async_wait([&](auto) { c.cancel(); });
|
||||
|
||||
ioc.run();
|
||||
ioc.run_for(std::chrono::seconds(1));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
@ -421,14 +202,12 @@ BOOST_AUTO_TEST_CASE(throttling) {
|
||||
BOOST_CHECK_MESSAGE(!rc, rc.message());
|
||||
BOOST_CHECK_EQUAL(handlers_called, 2);
|
||||
++handlers_called;
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::seconds(2));
|
||||
timer.async_wait([&](auto) { c.cancel(); });
|
||||
|
||||
ioc.run();
|
||||
ioc.run_for(std::chrono::seconds(1));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
@ -519,4 +298,5 @@ BOOST_AUTO_TEST_CASE(cancel_multiple_ops) {
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
150
test/integration/read_message.cpp
Normal file
150
test/integration/read_message.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <boost/asio/prepend.hpp>
|
||||
#include <boost/asio/post.hpp>
|
||||
|
||||
#include <async_mqtt5/mqtt_client.hpp>
|
||||
|
||||
#include "test_common/message_exchange.hpp"
|
||||
#include "test_common/test_service.hpp"
|
||||
#include "test_common/test_stream.hpp"
|
||||
|
||||
using namespace async_mqtt5;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(read_message/*, *boost::unit_test::disabled()*/)
|
||||
|
||||
void test_receive_malformed_packet(
|
||||
std::string malformed_packet, std::string reason_string
|
||||
) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
connack_props co_props;
|
||||
co_props[prop::maximum_packet_size] = 2000;
|
||||
auto connack = encoders::encode_connack(false, reason_codes::success.value(), co_props);
|
||||
|
||||
disconnect_props dc_props;
|
||||
dc_props[prop::reason_string] = reason_string;
|
||||
auto disconnect = encoders::encode_disconnect(
|
||||
reason_codes::malformed_packet.value(), dc_props
|
||||
);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.send(malformed_packet, after(5ms))
|
||||
.expect(disconnect)
|
||||
.complete_with(success, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms));
|
||||
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::milliseconds(100));
|
||||
timer.async_wait([&](auto) { c.cancel(); });
|
||||
|
||||
ioc.run();
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(forbidden_packet_type) {
|
||||
test_receive_malformed_packet(
|
||||
std::string({ 0x00 }),
|
||||
"Malformed Packet received from the Server"
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(malformed_varint) {
|
||||
test_receive_malformed_packet(
|
||||
std::string({ 0x10, -1 /* 0xFF */, -1, -1, -1 }),
|
||||
"Malformed Packet received from the Server"
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(malformed_fixed_header) {
|
||||
test_receive_malformed_packet(
|
||||
std::string({ 0x60, 1, 0 }),
|
||||
"Malformed Packet received from the Server"
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(packet_larger_than_allowed) {
|
||||
test_receive_malformed_packet(
|
||||
std::string({ 0x10, -1, -1, -1, 0 }),
|
||||
"Malformed Packet received from the Server"
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(receive_malformed_publish) {
|
||||
test_receive_malformed_packet(
|
||||
std::string({ 0x30, 1, -1 }),
|
||||
"Malformed PUBLISH received: cannot decode"
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(receive_disconnect) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(false, reason_codes::success.value(), {});
|
||||
|
||||
auto disconnect = encoders::encode_disconnect(0x00, {});
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.send(disconnect, after(5ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms));
|
||||
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
asio::steady_timer timer(c.get_executor());
|
||||
timer.expires_after(std::chrono::milliseconds(100));
|
||||
timer.async_wait([&](auto) { c.cancel(); });
|
||||
|
||||
ioc.run();
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
312
test/integration/resending.cpp
Normal file
312
test/integration/resending.cpp
Normal file
@ -0,0 +1,312 @@
|
||||
#include <boost/test/unit_test.hpp>
|
||||
|
||||
#include <async_mqtt5/mqtt_client.hpp>
|
||||
|
||||
#include "test_common/message_exchange.hpp"
|
||||
#include "test_common/test_service.hpp"
|
||||
#include "test_common/test_stream.hpp"
|
||||
|
||||
using namespace async_mqtt5;
|
||||
|
||||
BOOST_AUTO_TEST_SUITE(resending/* , *boost::unit_test::disabled()*/)
|
||||
|
||||
BOOST_AUTO_TEST_CASE(resend_multiple_publishes) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 2;
|
||||
int handlers_called = 0;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(
|
||||
false, reason_codes::success.value(), {}
|
||||
);
|
||||
auto publish_1 = encoders::encode_publish(
|
||||
1, "t", "p_1", qos_e::at_least_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
auto puback_1 = encoders::encode_puback(
|
||||
1, reason_codes::success.value(), {}
|
||||
);
|
||||
auto publish_2 = encoders::encode_publish(
|
||||
2, "t", "p_2", qos_e::at_least_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
auto puback_2 = encoders::encode_puback(
|
||||
2, reason_codes::success.value(), {}
|
||||
);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
error_code fail = asio::error::not_connected;
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(connack, after(10ms))
|
||||
.expect(publish_1, publish_2)
|
||||
.complete_with(fail, after(10ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(connack, after(10ms))
|
||||
.expect(publish_1, publish_2)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(puback_1, puback_2, after(20ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::at_least_once>(
|
||||
"t", "p_1", retain_e::no, publish_props{},
|
||||
[&](error_code ec, reason_code rc, auto) {
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_MESSAGE(!rc, rc.message());
|
||||
++handlers_called;
|
||||
|
||||
if (handlers_called == expected_handlers_called)
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
c.async_publish<qos_e::at_least_once>(
|
||||
"t", "p_2", retain_e::no, publish_props{},
|
||||
[&](error_code ec, reason_code rc, auto) {
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_MESSAGE(!rc, rc.message());
|
||||
++handlers_called;
|
||||
|
||||
if (handlers_called == expected_handlers_called)
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(6));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(resend_pubrel) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(
|
||||
false, reason_codes::success.value(), {}
|
||||
);
|
||||
auto publish = encoders::encode_publish(
|
||||
1, "t_1", "p_1", qos_e::exactly_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
auto pubrec = encoders::encode_pubrec(
|
||||
1, reason_codes::success.value(), {}
|
||||
);
|
||||
auto pubrel = encoders::encode_pubrel(
|
||||
1, reason_codes::success.value(), {}
|
||||
);
|
||||
auto pubcomp = encoders::encode_pubcomp(
|
||||
1, reason_codes::success.value(), {}
|
||||
);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
error_code fail = asio::error::not_connected;
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(connack, after(20ms))
|
||||
.expect(publish)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(pubrec, after(25ms))
|
||||
.expect(pubrel)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(fail, after(10ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(connack, after(20ms))
|
||||
.expect(pubrel)
|
||||
.complete_with(success, after(10ms))
|
||||
.reply_with(pubcomp, after(20ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::exactly_once>(
|
||||
"t_1", "p_1", retain_e::no, publish_props{},
|
||||
[&](error_code ec, reason_code rc, auto) {
|
||||
BOOST_CHECK_MESSAGE(!ec, ec.message());
|
||||
BOOST_CHECK_MESSAGE(!rc, rc.message());
|
||||
++handlers_called;
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(6));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(resend_subscribe) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// data
|
||||
std::vector<subscribe_topic> topics = {
|
||||
subscribe_topic { "topic", subscribe_options {} }
|
||||
};
|
||||
subscribe_props subscribe_props;
|
||||
|
||||
std::vector<uint8_t> rcs = { reason_codes::granted_qos_0.value() };
|
||||
suback_props suback_props;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(false, reason_codes::success.value(), {});
|
||||
|
||||
auto subscribe = encoders::encode_subscribe(1, topics, subscribe_props);
|
||||
auto suback = encoders::encode_suback(1, rcs, suback_props);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
error_code fail = asio::error::not_connected;
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(subscribe)
|
||||
.complete_with(fail, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(subscribe)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(suback, after(0ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
c.async_subscribe(
|
||||
topics, subscribe_props,
|
||||
[&](error_code ec, std::vector<reason_code> rcs, auto) {
|
||||
handlers_called++;
|
||||
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_ASSERT(rcs.size() == 1);
|
||||
BOOST_CHECK_EQUAL(rcs[0], reason_codes::granted_qos_0);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(10));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(resend_unsubscribe) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// data
|
||||
std::vector<std::string> topics = { "topic" };
|
||||
unsubscribe_props unsubscribe_props;
|
||||
|
||||
std::vector<uint8_t> rcs = { reason_codes::success.value() };
|
||||
unsuback_props unsuback_props;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(false, reason_codes::success.value(), {});
|
||||
|
||||
auto unsubscribe = encoders::encode_unsubscribe(1, topics, unsubscribe_props);
|
||||
auto unsuback = encoders::encode_unsuback(1, rcs, unsuback_props);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
error_code fail = asio::error::not_connected;
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(unsubscribe)
|
||||
.complete_with(fail, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(unsubscribe)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(unsuback, after(0ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1,127.0.0.1") // to avoid reconnect backoff
|
||||
.run();
|
||||
|
||||
c.async_unsubscribe(
|
||||
topics, unsubscribe_props,
|
||||
[&](error_code ec, std::vector<reason_code> rcs, auto) {
|
||||
handlers_called++;
|
||||
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_ASSERT(rcs.size() == 1);
|
||||
BOOST_CHECK_EQUAL(rcs[0], reason_codes::success);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(10));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END();
|
@ -1,35 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.15)
|
||||
|
||||
project(async-mqtt5-tests CXX)
|
||||
|
||||
include(../../cmake/project-is-top-level.cmake)
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
find_package(async-mqtt5 REQUIRED)
|
||||
enable_testing()
|
||||
endif()
|
||||
|
||||
add_executable(
|
||||
mqtt-test
|
||||
src/run_tests.cpp
|
||||
test/cancellation.cpp
|
||||
test/client_broker.cpp
|
||||
test/compilation_checks.cpp
|
||||
test/coroutine.cpp
|
||||
test/disconnect_op.cpp
|
||||
test/publish_rec_op.cpp
|
||||
test/publish_send_op.cpp
|
||||
test/serialization.cpp
|
||||
test/session.cpp
|
||||
test/string_validation.cpp
|
||||
test/subscribe_op.cpp
|
||||
test/unsubscribe_op.cpp
|
||||
)
|
||||
|
||||
target_include_directories(mqtt-test PRIVATE include)
|
||||
target_compile_definitions(mqtt-test PRIVATE BOOST_TEST_NO_MAIN=1)
|
||||
|
||||
find_package(OpenSSL REQUIRED)
|
||||
target_link_libraries(mqtt-test PRIVATE Async::MQTT5 OpenSSL::SSL)
|
||||
|
||||
add_test(NAME mqtt-test COMMAND mqtt-test)
|
@ -5,14 +5,10 @@
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/steady_timer.hpp>
|
||||
|
||||
#include <async_mqtt5/mqtt_client.hpp>
|
||||
|
||||
#include <async_mqtt5/impl/client_service.hpp>
|
||||
#include <async_mqtt5/impl/publish_send_op.hpp>
|
||||
|
||||
#include "test_common/message_exchange.hpp"
|
||||
#include "test_common/test_service.hpp"
|
||||
#include "test_common/test_stream.hpp"
|
||||
|
||||
using namespace async_mqtt5;
|
||||
|
||||
@ -304,177 +300,5 @@ BOOST_AUTO_TEST_CASE(test_publish_cancellation) {
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_malformed_puback) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(false, reason_codes::success.value(), {});
|
||||
|
||||
auto publish = encoders::encode_publish(
|
||||
1, "t", "p", qos_e::at_least_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
auto malformed_puback = encoders::encode_puback(1, uint8_t(0x04), {});
|
||||
|
||||
auto publish_dup = encoders::encode_publish(
|
||||
1, "t", "p", qos_e::at_least_once, retain_e::no, dup_e::yes, {}
|
||||
);
|
||||
auto puback = encoders::encode_puback(1, reason_codes::success.value(), {});
|
||||
|
||||
disconnect_props dc_props;
|
||||
dc_props[prop::reason_string] = "Malformed PUBACK: invalid Reason Code";
|
||||
auto disconnect = encoders::encode_disconnect(
|
||||
reason_codes::malformed_packet.value(), dc_props
|
||||
);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(publish)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(malformed_puback, after(0ms))
|
||||
.expect(disconnect)
|
||||
.complete_with(success, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(publish_dup)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(puback, after(0ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::at_least_once>(
|
||||
"t", "p", retain_e::no, publish_props {},
|
||||
[&](error_code ec, reason_code rc, auto) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK_EQUAL(rc, reason_codes::success);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(10));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_malformed_pubrec_pubcomp) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(false, reason_codes::success.value(), {});
|
||||
|
||||
auto publish = encoders::encode_publish(
|
||||
1, "t", "p", qos_e::exactly_once, retain_e::no, dup_e::no, {}
|
||||
);
|
||||
auto malformed_pubrec = encoders::encode_pubrec(1, uint8_t(0x04), {});
|
||||
|
||||
auto publish_dup = encoders::encode_publish(
|
||||
1, "t", "p", qos_e::exactly_once, retain_e::no, dup_e::yes, {}
|
||||
);
|
||||
auto pubrec = encoders::encode_pubrec(1, reason_codes::success.value(), {});
|
||||
|
||||
auto pubrel = encoders::encode_pubrel(1, reason_codes::success.value(), {});
|
||||
auto malformed_pubcomp = encoders::encode_pubcomp(1, uint8_t(0x04), {});
|
||||
auto pubcomp = encoders::encode_pubcomp(1, reason_codes::success.value(), {});
|
||||
|
||||
disconnect_props dc_props;
|
||||
dc_props[prop::reason_string] = "Malformed PUBREC: invalid Reason Code";
|
||||
auto disconnect_on_pubrec = encoders::encode_disconnect(
|
||||
reason_codes::malformed_packet.value(), dc_props
|
||||
);
|
||||
|
||||
dc_props[prop::reason_string] = "Malformed PUBCOMP: invalid Reason Code";
|
||||
auto disconnect_on_pubcomp = encoders::encode_disconnect(
|
||||
reason_codes::malformed_packet.value(), dc_props
|
||||
);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(publish)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(malformed_pubrec, after(0ms))
|
||||
.expect(disconnect_on_pubrec)
|
||||
.complete_with(success, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(publish_dup)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(pubrec, after(0ms))
|
||||
.expect(pubrel)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(malformed_pubcomp, after(0ms))
|
||||
.expect(disconnect_on_pubcomp)
|
||||
.complete_with(success, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(pubrel)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(pubcomp, after(0ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
.run();
|
||||
|
||||
c.async_publish<qos_e::exactly_once>(
|
||||
"t", "p", retain_e::no, publish_props {},
|
||||
[&](error_code ec, reason_code rc, auto) {
|
||||
++handlers_called;
|
||||
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_CHECK_EQUAL(rc, reason_codes::success);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(15));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
@ -2,13 +2,9 @@
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
|
||||
#include <async_mqtt5/mqtt_client.hpp>
|
||||
|
||||
#include <async_mqtt5/impl/subscribe_op.hpp>
|
||||
|
||||
#include "test_common/message_exchange.hpp"
|
||||
#include "test_common/test_service.hpp"
|
||||
#include "test_common/test_stream.hpp"
|
||||
|
||||
using namespace async_mqtt5;
|
||||
|
||||
@ -282,75 +278,4 @@ BOOST_AUTO_TEST_CASE(test_packet_too_large) {
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_resending) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// data
|
||||
std::vector<subscribe_topic> topics = {
|
||||
subscribe_topic { "topic", subscribe_options {} }
|
||||
};
|
||||
subscribe_props subscribe_props;
|
||||
|
||||
std::vector<uint8_t> rcs = { reason_codes::granted_qos_0.value() };
|
||||
suback_props suback_props;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(false, reason_codes::success.value(), {});
|
||||
|
||||
auto subscribe = encoders::encode_subscribe(1, topics, subscribe_props);
|
||||
auto suback = encoders::encode_suback(1, rcs, suback_props);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
error_code fail = asio::error::not_connected;
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(subscribe)
|
||||
.complete_with(fail, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(subscribe)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(suback, after(0ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
.run();
|
||||
|
||||
c.async_subscribe(
|
||||
topics, subscribe_props,
|
||||
[&](error_code ec, std::vector<reason_code> rcs, auto) {
|
||||
handlers_called++;
|
||||
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_ASSERT(rcs.size() == 1);
|
||||
BOOST_CHECK_EQUAL(rcs[0], reason_codes::granted_qos_0);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(10));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
@ -2,13 +2,9 @@
|
||||
|
||||
#include <boost/asio/io_context.hpp>
|
||||
|
||||
#include <async_mqtt5/mqtt_client.hpp>
|
||||
|
||||
#include <async_mqtt5/impl/unsubscribe_op.hpp>
|
||||
|
||||
#include "test_common/message_exchange.hpp"
|
||||
#include "test_common/test_service.hpp"
|
||||
#include "test_common/test_stream.hpp"
|
||||
|
||||
using namespace async_mqtt5;
|
||||
|
||||
@ -133,73 +129,4 @@ BOOST_AUTO_TEST_CASE(test_packet_too_large) {
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(test_resending) {
|
||||
using test::after;
|
||||
using std::chrono_literals::operator ""ms;
|
||||
|
||||
constexpr int expected_handlers_called = 1;
|
||||
int handlers_called = 0;
|
||||
|
||||
// data
|
||||
std::vector<std::string> topics = { "topic " };
|
||||
unsubscribe_props unsubscribe_props;
|
||||
|
||||
std::vector<uint8_t> rcs = { reason_codes::success.value() };
|
||||
unsuback_props unsuback_props;
|
||||
|
||||
// packets
|
||||
auto connect = encoders::encode_connect(
|
||||
"", std::nullopt, std::nullopt, 10, false, {}, std::nullopt
|
||||
);
|
||||
auto connack = encoders::encode_connack(false, reason_codes::success.value(), {});
|
||||
|
||||
auto unsubscribe = encoders::encode_unsubscribe(1, topics, unsubscribe_props);
|
||||
auto unsuback = encoders::encode_unsuback(1, rcs, unsuback_props);
|
||||
|
||||
test::msg_exchange broker_side;
|
||||
error_code success {};
|
||||
error_code fail = asio::error::not_connected;
|
||||
|
||||
broker_side
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(unsubscribe)
|
||||
.complete_with(fail, after(0ms))
|
||||
.expect(connect)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(connack, after(0ms))
|
||||
.expect(unsubscribe)
|
||||
.complete_with(success, after(0ms))
|
||||
.reply_with(unsuback, after(0ms));
|
||||
|
||||
asio::io_context ioc;
|
||||
auto executor = ioc.get_executor();
|
||||
auto& broker = asio::make_service<test::test_broker>(
|
||||
ioc, executor, std::move(broker_side)
|
||||
);
|
||||
|
||||
using client_type = mqtt_client<test::test_stream>;
|
||||
client_type c(executor, "");
|
||||
c.brokers("127.0.0.1")
|
||||
.run();
|
||||
|
||||
c.async_unsubscribe(
|
||||
topics, unsubscribe_props,
|
||||
[&](error_code ec, std::vector<reason_code> rcs, auto) {
|
||||
handlers_called++;
|
||||
|
||||
BOOST_CHECK(!ec);
|
||||
BOOST_ASSERT(rcs.size() == 1);
|
||||
BOOST_CHECK_EQUAL(rcs[0], reason_codes::success);
|
||||
|
||||
c.cancel();
|
||||
}
|
||||
);
|
||||
|
||||
ioc.run_for(std::chrono::seconds(10));
|
||||
BOOST_CHECK_EQUAL(handlers_called, expected_handlers_called);
|
||||
BOOST_CHECK(broker.received_all_expected());
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
Reference in New Issue
Block a user