#include #include #include #include using namespace async_mqtt5; using byte_citer = detail::byte_citer; BOOST_AUTO_TEST_SUITE(serialization/*, *boost::unit_test::disabled()*/) BOOST_AUTO_TEST_CASE(test_connect) { // testing variables std::string_view client_id = "async_mqtt_client_id"; std::string_view uname = "username"; std::optional password = std::nullopt; uint16_t keep_alive = 60; bool clean_start = true; std::string will_topic = "will_topic"; std::string will_message = "will_message"; connect_props cprops; cprops[prop::session_expiry_interval] = 29; cprops[prop::user_property].emplace_back("connect user prop"); will w{ will_topic, will_message }; w[prop::content_type] = "will content type"; w[prop::response_topic] = "will response topic"; w[prop::user_property].emplace_back("first user prop"); w[prop::user_property].emplace_back("second user prop"); std::optional will_opt { std::move(w) }; auto msg = encoders::encode_connect( client_id, uname, password, keep_alive, clean_start, cprops, will_opt ); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing CONNECT fixed header failed."); const auto& [control_byte, remain_length] = *header; auto rv = decoders::decode_connect(remain_length, it); BOOST_CHECK_MESSAGE(rv, "Parsing CONNECT failed."); const auto& [client_id_, uname_, password_, keep_alive_, clean_start_, _, w_] = *rv; BOOST_CHECK_EQUAL(client_id_, client_id); BOOST_CHECK(uname_); BOOST_CHECK_EQUAL(*uname_, uname); BOOST_CHECK(password_ == password); BOOST_CHECK_EQUAL(keep_alive_, keep_alive); BOOST_CHECK_EQUAL(clean_start_, clean_start); BOOST_CHECK(w_); BOOST_CHECK_EQUAL((*w_).topic(), will_topic); BOOST_CHECK_EQUAL((*w_).message(), will_message); } BOOST_AUTO_TEST_CASE(test_connack) { // testing variables bool session_present = true; uint8_t reason_code = 0x89; bool wildcard_sub = true; connack_props cap; cap[prop::wildcard_subscription_available] = wildcard_sub; auto msg = encoders::encode_connack(session_present, reason_code, cap); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing CONNACK fixed header failed."); const auto& [control_byte, remain_length] = *header; auto rv = decoders::decode_connack(remain_length, it); BOOST_CHECK_MESSAGE(rv, "Parsing CONNACK failed."); const auto& [session_present_, reason_code_, caprops] = *rv; BOOST_CHECK_EQUAL(session_present_, session_present); BOOST_CHECK_EQUAL(reason_code_, reason_code); BOOST_CHECK_EQUAL(*caprops[prop::wildcard_subscription_available], wildcard_sub); } BOOST_AUTO_TEST_CASE(test_publish) { // testing variables uint16_t packet_id = 31283; std::string_view topic = "publish_topic"; std::string_view payload = "This is some payload I am publishing!"; uint8_t message_expiry = 70; std::string content_type = "application/octet-stream"; std::string publish_prop_1 = "first publish prop"; std::string publish_prop_2 = "second publish prop"; publish_props pp; pp[prop::message_expiry_interval] = message_expiry; pp[prop::content_type] = content_type; pp[prop::user_property].emplace_back(publish_prop_1); pp[prop::user_property].emplace_back(publish_prop_2); auto msg = encoders::encode_publish( packet_id, topic, payload, qos_e::at_least_once, retain_e::yes, dup_e::no, pp ); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing PUBLISH fixed header failed."); const auto& [control_byte, remain_length] = *header; auto rv = decoders::decode_publish(control_byte, remain_length, it); BOOST_CHECK_MESSAGE(rv, "Parsing PUBLISH failed."); const auto& [topic_, packet_id_, flags, pprops, payload_] = *rv; BOOST_CHECK(packet_id); BOOST_CHECK_EQUAL(*packet_id_, packet_id); BOOST_CHECK_EQUAL(topic_, topic); BOOST_CHECK_EQUAL(payload_, payload); BOOST_CHECK_EQUAL(*pprops[prop::message_expiry_interval], message_expiry); BOOST_CHECK_EQUAL(*pprops[prop::content_type], content_type); BOOST_CHECK_EQUAL(pprops[prop::user_property][0], publish_prop_1); BOOST_CHECK_EQUAL(pprops[prop::user_property][1], publish_prop_2); } BOOST_AUTO_TEST_CASE(test_large_publish) { // testing variables uint16_t packet_id = 40001; std::string_view topic = "publish_topic"; std::string large_payload(1'000'000, 'a'); auto msg = encoders::encode_publish( packet_id, topic, large_payload, qos_e::at_least_once, retain_e::yes, dup_e::no, publish_props{} ); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing PUBLISH fixed header failed."); const auto& [control_byte, remain_length] = *header; auto rv = decoders::decode_publish(control_byte, remain_length, it); BOOST_CHECK_MESSAGE(rv, "Parsing PUBLISH failed."); const auto& [topic_, packet_id_, flags, pprops, payload_] = *rv; BOOST_CHECK(packet_id); BOOST_CHECK_EQUAL(*packet_id_, packet_id); BOOST_CHECK_EQUAL(topic_, topic); BOOST_CHECK_EQUAL(payload_, large_payload); } BOOST_AUTO_TEST_CASE(test_puback) { // testing variables uint16_t packet_id = 9199; uint8_t reason_code = 0x93; std::string reason_string = "PUBACK reason string"; std::string user_prop = "PUBACK user prop"; puback_props pp; pp[prop::reason_string] = reason_string; pp[prop::user_property].emplace_back(user_prop); auto msg = encoders::encode_puback(packet_id, reason_code, pp); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing PUBACK fixed header failed."); auto packet_id_ = decoders::decode_packet_id(it); BOOST_CHECK(packet_id); BOOST_CHECK_EQUAL(*packet_id_, packet_id); const auto& [control_byte, remain_length] = *header; auto rv = decoders::decode_puback(remain_length - sizeof(uint16_t), it); BOOST_CHECK_MESSAGE(rv, "Parsing PUBACK failed."); const auto& [reason_code_, pprops] = *rv; BOOST_CHECK_EQUAL(reason_code_, reason_code); BOOST_CHECK_EQUAL(*pprops[prop::reason_string], reason_string); BOOST_CHECK_EQUAL(pprops[prop::user_property][0], user_prop); } BOOST_AUTO_TEST_CASE(test_subscribe) { //testing variables uint32_t sub_id = 1'234'567; subscribe_props sp; sp[prop::subscription_identifier] = sub_id; std::vector filters { { "subscribe topic", { qos_e::at_least_once } } }; uint16_t packet_id = 65535; auto msg = encoders::encode_subscribe(packet_id, filters, sp); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing SUBSCRIBE fixed header failed."); const auto& [control_byte, remain_length] = *header; auto packet_id_ = decoders::decode_packet_id(it); BOOST_CHECK(packet_id); BOOST_CHECK_EQUAL(*packet_id_, packet_id); auto rv = decoders::decode_subscribe(remain_length - sizeof(uint16_t), it); BOOST_CHECK_MESSAGE(rv, "Parsing SUBSCRIBE failed."); const auto& [props_, filters_] = *rv; BOOST_CHECK_EQUAL(std::get<0>(filters_[0]), filters[0].topic_filter); BOOST_CHECK_EQUAL(*props_[prop::subscription_identifier], sub_id); //TODO: sub options } BOOST_AUTO_TEST_CASE(test_suback) { //testing variables suback_props sp; std::vector reason_codes { 48, 28 }; uint16_t packet_id = 142; auto msg = encoders::encode_suback(packet_id, reason_codes, sp); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing SUBACK fixed header failed."); const auto& [control_byte, remain_length] = *header; auto packet_id_ = decoders::decode_packet_id(it); BOOST_CHECK(packet_id); BOOST_CHECK_EQUAL(*packet_id_, packet_id); auto rv = decoders::decode_suback(remain_length - sizeof(uint16_t), it); BOOST_CHECK_MESSAGE(rv, "Parsing SUBACK failed."); const auto& [sp_, reason_codes_] = *rv; BOOST_CHECK(reason_codes_ == reason_codes); } BOOST_AUTO_TEST_CASE(test_unsubscribe) { // testing variables unsubscribe_props sp; std::vector topics { "first topic", "second/topic" }; uint16_t packet_id = 14423; auto msg = encoders::encode_unsubscribe(packet_id, topics, sp); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing UNSUBSCRIBE fixed header failed."); const auto& [control_byte, remain_length] = *header; auto packet_id_ = decoders::decode_packet_id(it); BOOST_CHECK(packet_id); BOOST_CHECK_EQUAL(*packet_id_, packet_id); auto rv = decoders::decode_unsubscribe(remain_length - sizeof(uint16_t), it); BOOST_CHECK_MESSAGE(rv, "Parsing UNSUBSCRIBE failed."); const auto& [props_, topics_] = *rv; BOOST_CHECK(topics_ == topics); } BOOST_AUTO_TEST_CASE(test_unsuback) { // testing variables std::string reason_string = "some unsuback reason string"; unsuback_props sp; sp[prop::reason_string] = reason_string; std::vector reason_codes { 48, 28 }; uint16_t packet_id = 42; auto msg = encoders::encode_unsuback(packet_id, reason_codes, sp); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing UNSUBACK fixed header failed."); const auto& [control_byte, remain_length] = *header; auto packet_id_ = decoders::decode_packet_id(it); BOOST_CHECK(packet_id); BOOST_CHECK_EQUAL(*packet_id_, packet_id); auto rv = decoders::decode_unsuback(remain_length - sizeof(uint16_t), it); BOOST_CHECK_MESSAGE(header, "Parsing UNSUBACK failed."); const auto& [props_, reason_codes_] = *rv; BOOST_CHECK(reason_codes_ == reason_codes); BOOST_CHECK_EQUAL(*props_[prop::reason_string], reason_string); } BOOST_AUTO_TEST_CASE(test_disconnect) { // testing variables uint8_t reason_code = 0; std::string user_property = "DISCONNECT user property"; disconnect_props sp; sp[prop::user_property].emplace_back(user_property); auto msg = encoders::encode_disconnect(reason_code, sp); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing DISCONNECT fixed header failed."); const auto& [control_byte, remain_length] = *header; auto rv = decoders::decode_disconnect(remain_length, it); BOOST_CHECK_MESSAGE(header, "Parsing DISCONNECT failed."); const auto& [reason_code_, props_] = *rv; BOOST_CHECK_EQUAL(reason_code_, reason_code); BOOST_CHECK_EQUAL(props_[prop::user_property][0], user_property); } BOOST_AUTO_TEST_CASE(test_auth) { // testing variables uint8_t reason_code = 0x18; std::string reason_string = "AUTH reason"; std::string user_property = "AUTH user propety"; auth_props sp; sp[prop::reason_string] = reason_string; sp[prop::user_property].emplace_back(user_property); auto msg = encoders::encode_auth(reason_code, sp); byte_citer it = msg.cbegin(), last = msg.cend(); auto header = decoders::decode_fixed_header(it, last); BOOST_CHECK_MESSAGE(header, "Parsing AUTH fixed header failed."); const auto& [control_byte, remain_length] = *header; auto rv = decoders::decode_auth(remain_length, it); BOOST_CHECK_MESSAGE(rv, "Parsing AUTH failed."); const auto& [reason_code_, props_] = *rv; BOOST_CHECK_EQUAL(reason_code_, reason_code); BOOST_CHECK_EQUAL(*props_[prop::reason_string], reason_string); BOOST_CHECK_EQUAL(props_[prop::user_property][0], user_property); } BOOST_AUTO_TEST_SUITE_END()