mirror of
https://github.com/eclipse/paho.mqtt.cpp.git
synced 2025-05-10 03:39:07 +08:00
Moved token unit tests to Catch2
This commit is contained in:
parent
f5e0d7f1cf
commit
60a6e30add
@ -118,7 +118,7 @@ private:
|
||||
|
||||
/** Client and token-related options have special access */
|
||||
friend class async_client;
|
||||
friend class token_test;
|
||||
friend class mock_async_client;
|
||||
|
||||
friend class connect_options;
|
||||
friend class response_options;
|
||||
|
@ -21,7 +21,6 @@
|
||||
#include "async_client_v3_test.h"
|
||||
#include "client_test.h"
|
||||
#include "iclient_persistence_test.h"
|
||||
#include "token_test.h"
|
||||
|
||||
using namespace CppUnit;
|
||||
|
||||
@ -30,7 +29,6 @@ using namespace CppUnit;
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( mqtt::iclient_persistence_test );
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( mqtt::token_test );
|
||||
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( mqtt::async_client_test );
|
||||
CPPUNIT_TEST_SUITE_REGISTRATION( mqtt::async_client_v3_test );
|
||||
|
@ -1,379 +0,0 @@
|
||||
// token_test.h
|
||||
// Unit tests for the token class in the Paho MQTT C++ library.
|
||||
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Guilherme M. Ferreira <guilherme.maciel.ferreira@gmail.com>
|
||||
* Copyright (c) 2016-2019 Frank Pagliughi <fpagliughi@mindspring.com>
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Guilherme M. Ferreira - initial implementation and documentation
|
||||
* Frank Pagliughi - additional tests. Made this test a friend of token.
|
||||
* Frank Pagliughi - Updated for token::Type
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __mqtt_token_test_h
|
||||
#define __mqtt_token_test_h
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <cppunit/ui/text/TestRunner.h>
|
||||
#include <cppunit/extensions/HelperMacros.h>
|
||||
|
||||
#include "mqtt/token.h"
|
||||
#include "dummy_async_client.h"
|
||||
#include "dummy_action_listener.h"
|
||||
|
||||
namespace mqtt {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class token_test : public CppUnit::TestFixture
|
||||
{
|
||||
CPPUNIT_TEST_SUITE( token_test );
|
||||
|
||||
CPPUNIT_TEST( test_user_constructor_client );
|
||||
CPPUNIT_TEST( test_user_constructor_client_token );
|
||||
CPPUNIT_TEST( test_user_constructor_client_string );
|
||||
CPPUNIT_TEST( test_user_constructor_client_vector );
|
||||
CPPUNIT_TEST( test_on_success_with_data );
|
||||
CPPUNIT_TEST( test_on_success_without_data );
|
||||
CPPUNIT_TEST( test_on_failure_with_data );
|
||||
CPPUNIT_TEST( test_on_failure_without_data );
|
||||
CPPUNIT_TEST( test_action_callback );
|
||||
CPPUNIT_TEST( test_wait_success );
|
||||
CPPUNIT_TEST( test_wait_failure );
|
||||
CPPUNIT_TEST( test_wait_for_timeout );
|
||||
|
||||
CPPUNIT_TEST_SUITE_END();
|
||||
|
||||
using milliseconds = std::chrono::milliseconds;
|
||||
using steady_clock = std::chrono::steady_clock;
|
||||
|
||||
mqtt::test::dummy_async_client cli;
|
||||
|
||||
static constexpr token::Type TYPE = token::Type::CONNECT;
|
||||
|
||||
public:
|
||||
void setUp() {}
|
||||
void tearDown() {}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test user constructor (iasync_client)
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_user_constructor_client() {
|
||||
mqtt::token tok{ TYPE, cli };
|
||||
CPPUNIT_ASSERT_EQUAL(0, tok.get_message_id());
|
||||
CPPUNIT_ASSERT_EQUAL(dynamic_cast<mqtt::iasync_client*>(&cli), tok.get_client());
|
||||
CPPUNIT_ASSERT(nullptr == tok.get_user_context());
|
||||
CPPUNIT_ASSERT(nullptr == tok.get_action_callback());
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
CPPUNIT_ASSERT(nullptr == tok.get_topics());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test user constructor (iasync_client, MQTTAsync_token)
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_user_constructor_client_token() {
|
||||
MQTTAsync_token id {2};
|
||||
mqtt::token tok{ TYPE, cli, id };
|
||||
CPPUNIT_ASSERT_EQUAL(id, tok.get_message_id());
|
||||
CPPUNIT_ASSERT_EQUAL(dynamic_cast<mqtt::iasync_client*>(&cli), tok.get_client());
|
||||
CPPUNIT_ASSERT(nullptr == tok.get_user_context());
|
||||
CPPUNIT_ASSERT(nullptr == tok.get_action_callback());
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
CPPUNIT_ASSERT(nullptr == tok.get_topics());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test user constructor (iasync_client, string)
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_user_constructor_client_string() {
|
||||
std::string topic { "topic" };
|
||||
mqtt::token tok{ TYPE, cli, topic };
|
||||
CPPUNIT_ASSERT_EQUAL(0, tok.get_message_id());
|
||||
CPPUNIT_ASSERT_EQUAL(dynamic_cast<mqtt::iasync_client*>(&cli), tok.get_client());
|
||||
CPPUNIT_ASSERT(nullptr == tok.get_user_context());
|
||||
CPPUNIT_ASSERT(nullptr == tok.get_action_callback());
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
CPPUNIT_ASSERT(nullptr != tok.get_topics());
|
||||
CPPUNIT_ASSERT_EQUAL(size_t(1), tok.get_topics()->size());
|
||||
CPPUNIT_ASSERT_EQUAL(topic, (*tok.get_topics())[0]);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test user constructor (iasync_client, vector<string>)
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_user_constructor_client_vector() {
|
||||
auto topics = string_collection::create({ "topic1", "topic2" });
|
||||
mqtt::token tok{ TYPE, cli, topics };
|
||||
CPPUNIT_ASSERT_EQUAL(0, tok.get_message_id());
|
||||
CPPUNIT_ASSERT_EQUAL(dynamic_cast<mqtt::iasync_client*>(&cli), tok.get_client());
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<void*>(nullptr), tok.get_user_context());
|
||||
CPPUNIT_ASSERT_EQUAL(static_cast<mqtt::iaction_listener*>(nullptr), tok.get_action_callback());
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
CPPUNIT_ASSERT(nullptr != tok.get_topics());
|
||||
CPPUNIT_ASSERT_EQUAL(size_t(2), tok.get_topics()->size());
|
||||
CPPUNIT_ASSERT_EQUAL((*topics)[0], (*tok.get_topics())[0]);
|
||||
CPPUNIT_ASSERT_EQUAL((*topics)[1], (*tok.get_topics())[1]);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test on success with data
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_on_success_with_data() {
|
||||
mqtt::token tok{ TYPE, cli };
|
||||
|
||||
constexpr int MESSAGE_ID = 12;
|
||||
MQTTAsync_successData data = {
|
||||
.token = MESSAGE_ID,
|
||||
};
|
||||
data.alt.connect.serverURI = const_cast<char*>("tcp://some_server.com");
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
token::on_success(&tok, &data);
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.is_complete());
|
||||
CPPUNIT_ASSERT_EQUAL(MESSAGE_ID, tok.get_message_id());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test on success without data
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_on_success_without_data() {
|
||||
mqtt::token tok{ TYPE, cli };
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
token::on_success(&tok, nullptr);
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.is_complete());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test on failure with data
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_on_failure_with_data() {
|
||||
mqtt::token tok{ TYPE, cli };
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
constexpr int MESSAGE_ID = 12;
|
||||
MQTTAsync_failureData data = {
|
||||
.token = MESSAGE_ID,
|
||||
.code = 13,
|
||||
.message = nullptr,
|
||||
};
|
||||
token::on_failure(&tok, &data);
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.is_complete());
|
||||
CPPUNIT_ASSERT_EQUAL(MESSAGE_ID, tok.get_message_id());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test on failure without data
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_on_failure_without_data() {
|
||||
mqtt::token tok{ TYPE, cli };
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
token::on_failure(&tok, nullptr);
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.is_complete());
|
||||
CPPUNIT_ASSERT_EQUAL(0, tok.get_message_id());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test set callbacks
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_action_callback() {
|
||||
mqtt::test::dummy_action_listener listener;
|
||||
mqtt::token tok{ TYPE, cli };
|
||||
tok.set_action_callback(listener);
|
||||
CPPUNIT_ASSERT_EQUAL(dynamic_cast<mqtt::iaction_listener*>(&listener), tok.get_action_callback());
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(false, listener.on_success_called);
|
||||
token::on_success(&tok, nullptr);
|
||||
CPPUNIT_ASSERT_EQUAL(true, listener.on_success_called);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(false, listener.on_failure_called);
|
||||
token::on_failure(&tok, nullptr);
|
||||
CPPUNIT_ASSERT_EQUAL(true, listener.on_failure_called);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test wait for completion on success case
|
||||
// All wait's should succeed immediately on successful completion.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_wait_success() {
|
||||
const auto TIMEOUT = milliseconds(10);
|
||||
|
||||
mqtt::token tok{ TYPE, cli };
|
||||
|
||||
// NOTE: Make sure the complete flag is already true and the return
|
||||
// code (rc) is MQTTASYNC_SUCCESS, so the token::wait()
|
||||
// returns immediately. Otherwise we will get stuck in a single thread
|
||||
// that can't change the complete flag.
|
||||
token::on_success(&tok, nullptr);
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.is_complete());
|
||||
|
||||
// A wait does not reset the "complete" flag.
|
||||
|
||||
try {
|
||||
tok.wait();
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.is_complete());
|
||||
}
|
||||
catch (...) {
|
||||
CPPUNIT_FAIL("token::wait() should not throw on success");
|
||||
}
|
||||
|
||||
// try_wait()
|
||||
try {
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.try_wait());
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.is_complete());
|
||||
}
|
||||
catch (...) {
|
||||
CPPUNIT_FAIL("token::wait() should not throw on success");
|
||||
}
|
||||
|
||||
// wait_for()
|
||||
try {
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.wait_for(TIMEOUT));
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.is_complete());
|
||||
}
|
||||
catch (...) {
|
||||
CPPUNIT_FAIL("token::wait_for() should not throw on success");
|
||||
}
|
||||
|
||||
// wait_until()
|
||||
const auto TO = steady_clock::now() + TIMEOUT;
|
||||
try {
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.wait_until(TO));
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.is_complete());
|
||||
}
|
||||
catch (...) {
|
||||
CPPUNIT_FAIL("token::wait_until() should not throw on success");
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test wait for completion on failure case
|
||||
// All wait's should throw if the action failed
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_wait_failure() {
|
||||
const auto TIMEOUT = milliseconds(10);
|
||||
|
||||
mqtt::token tok{ TYPE, cli };
|
||||
|
||||
// NOTE: Make sure the complete flag is already true and the return
|
||||
// code (rc) is MQTTASYNC_FAILURE, so the token::wait()
|
||||
// returns immediately. Otherwise we will get stuck in a single thread
|
||||
// that can't change the complete flag.
|
||||
constexpr int MESSAGE_ID = 12;
|
||||
MQTTAsync_failureData data = {
|
||||
.token = MESSAGE_ID,
|
||||
.code = MQTTASYNC_FAILURE,
|
||||
.message = nullptr,
|
||||
};
|
||||
token::on_failure(&tok, &data);
|
||||
|
||||
CPPUNIT_ASSERT_EQUAL(true, tok.is_complete());
|
||||
CPPUNIT_ASSERT_EQUAL(MESSAGE_ID, tok.get_message_id());
|
||||
CPPUNIT_ASSERT_EQUAL(MQTTASYNC_FAILURE, tok.get_return_code());
|
||||
|
||||
try {
|
||||
tok.wait();
|
||||
CPPUNIT_FAIL("token::wait() should throw on failure");
|
||||
}
|
||||
catch (mqtt::exception& ex) {
|
||||
CPPUNIT_ASSERT_EQUAL(MQTTASYNC_FAILURE, ex.get_return_code());
|
||||
}
|
||||
|
||||
try {
|
||||
tok.try_wait();
|
||||
CPPUNIT_FAIL("token::try_wait() should throw on failure");
|
||||
}
|
||||
catch (mqtt::exception& ex) {
|
||||
CPPUNIT_ASSERT_EQUAL(MQTTASYNC_FAILURE, ex.get_return_code());
|
||||
}
|
||||
|
||||
try {
|
||||
tok.wait_for(TIMEOUT);
|
||||
CPPUNIT_FAIL("token::wait_for() should throw on failure");
|
||||
}
|
||||
catch (mqtt::exception& ex) {
|
||||
CPPUNIT_ASSERT_EQUAL(MQTTASYNC_FAILURE, ex.get_return_code());
|
||||
}
|
||||
|
||||
try {
|
||||
tok.wait_until(steady_clock::now() + TIMEOUT);
|
||||
CPPUNIT_FAIL("token::wait_until() should throw on failure");
|
||||
}
|
||||
catch (mqtt::exception& ex) {
|
||||
CPPUNIT_ASSERT_EQUAL(MQTTASYNC_FAILURE, ex.get_return_code());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test wait for completion on failure due timeout case
|
||||
// All waits should return false, but not throw, on a timeout
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void test_wait_for_timeout() {
|
||||
const auto TIMEOUT = milliseconds(10);
|
||||
|
||||
mqtt::token tok{ TYPE, cli };
|
||||
|
||||
// Test for timeout on non-signaled token.
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
|
||||
// try_wait()
|
||||
try {
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.try_wait());
|
||||
}
|
||||
catch (...) {
|
||||
CPPUNIT_FAIL("token::try_wait() should not throw");
|
||||
}
|
||||
|
||||
// wait_for()
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
try {
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.wait_for(TIMEOUT));
|
||||
}
|
||||
catch (...) {
|
||||
CPPUNIT_FAIL("token::wait_for() should not throw on timeout");
|
||||
}
|
||||
|
||||
// wait_until()
|
||||
const auto TO = steady_clock::now() + TIMEOUT;
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.is_complete());
|
||||
try {
|
||||
CPPUNIT_ASSERT_EQUAL(false, tok.wait_until(TO));
|
||||
}
|
||||
catch (...) {
|
||||
CPPUNIT_FAIL("token::wait_until() should not throw on timeout");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// end namespace mqtt
|
||||
}
|
||||
|
||||
#endif // __mqtt_token_test_h
|
||||
|
@ -38,6 +38,7 @@ add_executable(unit_tests unit_tests.cpp
|
||||
test_properties.cpp
|
||||
test_response_options.cpp
|
||||
test_string_collection.cpp
|
||||
test_token.cpp
|
||||
test_topic.cpp
|
||||
test_will_options.cpp
|
||||
)
|
||||
|
@ -30,7 +30,6 @@
|
||||
#include "mqtt/connect_options.h"
|
||||
|
||||
namespace mqtt {
|
||||
namespace test {
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@ -39,6 +38,25 @@ class mock_async_client : public mqtt::iasync_client
|
||||
public:
|
||||
void remove_token(mqtt::token* tok) override {}
|
||||
|
||||
|
||||
static void succeed(mqtt::token* tok, MQTTAsync_successData* rsp) {
|
||||
token::on_success(tok, rsp);
|
||||
}
|
||||
|
||||
static void succeed5(mqtt::token* tok, MQTTAsync_successData5* rsp) {
|
||||
token::on_success5(tok, rsp);
|
||||
}
|
||||
|
||||
static void fail(mqtt::token* tok, MQTTAsync_failureData* rsp) {
|
||||
token::on_failure(tok, rsp);
|
||||
}
|
||||
|
||||
static void fail5(mqtt::token* tok, MQTTAsync_failureData5* rsp) {
|
||||
token::on_failure5(tok, rsp);
|
||||
}
|
||||
|
||||
// iface
|
||||
|
||||
mqtt::token_ptr connect() override {
|
||||
return mqtt::token_ptr{};
|
||||
}
|
||||
@ -185,10 +203,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// end namespace test
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// end namespace mqtt
|
||||
}
|
||||
|
@ -356,7 +356,7 @@ TEST_CASE("set_token", "[options]")
|
||||
REQUIRE(nullptr == c_struct.context);
|
||||
|
||||
SECTION("set token") {
|
||||
mqtt::test::mock_async_client ac;
|
||||
mock_async_client ac;
|
||||
auto tok = token::create(TOKEN_TYPE, ac);
|
||||
opts.set_token(tok);
|
||||
REQUIRE(tok == opts.get_token());
|
||||
|
@ -34,7 +34,7 @@ static const std::string EMPTY_STR;
|
||||
|
||||
static constexpr token::Type TOKEN_TYPE = token::Type::DISCONNECT;
|
||||
|
||||
static mqtt::test::mock_async_client cli;
|
||||
static mock_async_client cli;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test default constructor
|
||||
|
@ -37,7 +37,7 @@ using namespace mqtt;
|
||||
|
||||
static constexpr token::Type TOKEN_TYPE = token::Type::CONNECT;
|
||||
|
||||
static mqtt::test::mock_async_client cli;
|
||||
static mock_async_client cli;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test default constructor
|
||||
@ -113,7 +113,7 @@ TEST_CASE("delivery_response_options dflt constructor", "[options]")
|
||||
|
||||
TEST_CASE("delivery_response_options user constructor", "[options]")
|
||||
{
|
||||
mqtt::test::mock_async_client cli;
|
||||
mock_async_client cli;
|
||||
|
||||
mqtt::delivery_token_ptr token { new mqtt::delivery_token{ cli } };
|
||||
mqtt::delivery_response_options opts { token };
|
||||
@ -137,7 +137,7 @@ TEST_CASE("delivery_response_options set token", "[options]")
|
||||
|
||||
REQUIRE(c_struct.context == nullptr);
|
||||
|
||||
mqtt::test::mock_async_client cli;
|
||||
mock_async_client cli;
|
||||
mqtt::delivery_token_ptr token { new mqtt::delivery_token{ cli } };
|
||||
opts.set_token( token );
|
||||
REQUIRE(c_struct.context == token.get());
|
||||
|
358
test/unit/test_token.cpp
Normal file
358
test/unit/test_token.cpp
Normal file
@ -0,0 +1,358 @@
|
||||
// test_token.h
|
||||
//
|
||||
// Unit tests for the token class in the Paho MQTT C++ library.
|
||||
//
|
||||
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Guilherme M. Ferreira <guilherme.maciel.ferreira@gmail.com>
|
||||
* Copyright (c) 2016-2020 Frank Pagliughi <fpagliughi@mindspring.com>
|
||||
*
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
*
|
||||
* The Eclipse Public License is available at
|
||||
* http://www.eclipse.org/legal/epl-v10.html
|
||||
* and the Eclipse Distribution License is available at
|
||||
* http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
*
|
||||
* Contributors:
|
||||
* Guilherme M. Ferreira
|
||||
* - initial implementation and documentation
|
||||
* Frank Pagliughi
|
||||
* - additional tests. Made this test a friend of token.
|
||||
* - updated for token::Type
|
||||
* - Converted to use Catch2
|
||||
*******************************************************************************/
|
||||
|
||||
#define UNIT_TESTS
|
||||
|
||||
#include <cstring>
|
||||
#include "catch2/catch.hpp"
|
||||
#include "mqtt/token.h"
|
||||
#include "mock_async_client.h"
|
||||
#include "mock_action_listener.h"
|
||||
|
||||
using namespace mqtt;
|
||||
|
||||
using milliseconds = std::chrono::milliseconds;
|
||||
using steady_clock = std::chrono::steady_clock;
|
||||
|
||||
static mock_async_client cli;
|
||||
|
||||
static constexpr token::Type TYPE = token::Type::CONNECT;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test user constructor (iasync_client)
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token user constructor client", "[token]")
|
||||
{
|
||||
mqtt::token tok{TYPE, cli};
|
||||
REQUIRE(0 == tok.get_message_id());
|
||||
REQUIRE(dynamic_cast<mqtt::iasync_client*>(&cli) == tok.get_client());
|
||||
REQUIRE(nullptr == tok.get_user_context());
|
||||
REQUIRE(nullptr == tok.get_action_callback());
|
||||
REQUIRE(!tok.is_complete());
|
||||
REQUIRE(nullptr == tok.get_topics());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test user constructor (iasync_client, MQTTAsync_token)
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token user constructor client token", "[token]")
|
||||
{
|
||||
MQTTAsync_token id{2};
|
||||
mqtt::token tok{TYPE, cli, id};
|
||||
REQUIRE(id == tok.get_message_id());
|
||||
REQUIRE(dynamic_cast<mqtt::iasync_client*>(&cli) == tok.get_client());
|
||||
REQUIRE(nullptr == tok.get_user_context());
|
||||
REQUIRE(nullptr == tok.get_action_callback());
|
||||
REQUIRE(!tok.is_complete());
|
||||
REQUIRE(nullptr == tok.get_topics());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test user constructor (iasync_client, string)
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token user constructor client string", "[token]")
|
||||
{
|
||||
std::string topic{"topic"};
|
||||
mqtt::token tok{TYPE, cli, topic};
|
||||
REQUIRE(0 == tok.get_message_id());
|
||||
REQUIRE(dynamic_cast<mqtt::iasync_client*>(&cli) == tok.get_client());
|
||||
REQUIRE(nullptr == tok.get_user_context());
|
||||
REQUIRE(nullptr == tok.get_action_callback());
|
||||
REQUIRE(!tok.is_complete());
|
||||
REQUIRE(nullptr != tok.get_topics());
|
||||
REQUIRE(size_t(1) == tok.get_topics()->size());
|
||||
REQUIRE(topic == (*tok.get_topics())[0]);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test user constructor (iasync_client, vector<string>)
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token user constructor client vector", "[token]")
|
||||
{
|
||||
auto topics = string_collection::create({ "topic1", "topic2" });
|
||||
mqtt::token tok{TYPE, cli, topics};
|
||||
REQUIRE(0 == tok.get_message_id());
|
||||
REQUIRE(dynamic_cast<mqtt::iasync_client*>(&cli) == tok.get_client());
|
||||
REQUIRE(static_cast<void*>(nullptr) == tok.get_user_context());
|
||||
REQUIRE(static_cast<mqtt::iaction_listener*>(nullptr) == tok.get_action_callback());
|
||||
REQUIRE(!tok.is_complete());
|
||||
REQUIRE(nullptr != tok.get_topics());
|
||||
REQUIRE(size_t(2) == tok.get_topics()->size());
|
||||
REQUIRE((*topics)[0] == (*tok.get_topics())[0]);
|
||||
REQUIRE((*topics)[1] == (*tok.get_topics())[1]);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test on success with data
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token on success with data", "[token]")
|
||||
{
|
||||
mqtt::token tok{TYPE, cli};
|
||||
|
||||
constexpr int MESSAGE_ID = 12;
|
||||
MQTTAsync_successData data = {
|
||||
.token = MESSAGE_ID,
|
||||
};
|
||||
data.alt.connect.serverURI = const_cast<char*>("tcp://some_server.com");
|
||||
|
||||
REQUIRE(!tok.is_complete());
|
||||
mock_async_client::succeed(&tok, &data);
|
||||
REQUIRE(tok.is_complete());
|
||||
REQUIRE(MESSAGE_ID == tok.get_message_id());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test on success without data
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token on success without data", "[token]")
|
||||
{
|
||||
mqtt::token tok{TYPE, cli};
|
||||
|
||||
REQUIRE(!tok.is_complete());
|
||||
mock_async_client::succeed(&tok, nullptr);
|
||||
REQUIRE(tok.is_complete());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test on failure with data
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token on failure with data", "[token]")
|
||||
{
|
||||
mqtt::token tok{TYPE, cli};
|
||||
|
||||
REQUIRE(!tok.is_complete());
|
||||
constexpr int MESSAGE_ID = 12;
|
||||
MQTTAsync_failureData data = {
|
||||
.token = MESSAGE_ID,
|
||||
.code = 13,
|
||||
.message = nullptr,
|
||||
};
|
||||
mock_async_client::fail(&tok, &data);
|
||||
REQUIRE(tok.is_complete());
|
||||
REQUIRE(MESSAGE_ID == tok.get_message_id());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test on failure without data
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token on failure without data", "[token]")
|
||||
{
|
||||
mqtt::token tok{TYPE, cli};
|
||||
|
||||
REQUIRE(!tok.is_complete());
|
||||
mock_async_client::fail(&tok, nullptr);
|
||||
REQUIRE(tok.is_complete());
|
||||
REQUIRE(0 == tok.get_message_id());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test set callbacks
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token action callback", "[token]")
|
||||
{
|
||||
mock_action_listener listener;
|
||||
mqtt::token tok{TYPE, cli};
|
||||
tok.set_action_callback(listener);
|
||||
REQUIRE(dynamic_cast<mqtt::iaction_listener*>(&listener) == tok.get_action_callback());
|
||||
|
||||
REQUIRE(!listener.on_success_called);
|
||||
mock_async_client::succeed(&tok, nullptr);
|
||||
REQUIRE(listener.on_success_called);
|
||||
|
||||
REQUIRE(!listener.on_failure_called);
|
||||
mock_async_client::fail(&tok, nullptr);
|
||||
REQUIRE(listener.on_failure_called);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test wait for completion on success case
|
||||
// All wait's should succeed immediately on successful completion.
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token wait success", "[token]")
|
||||
{
|
||||
const auto TIMEOUT = milliseconds(10);
|
||||
|
||||
mqtt::token tok{TYPE, cli};
|
||||
|
||||
// NOTE: Make sure the complete flag is already true and the return
|
||||
// code (rc) is MQTTASYNC_SUCCESS, so the token::wait()
|
||||
// returns immediately. Otherwise we will get stuck in a single thread
|
||||
// that can't change the complete flag.
|
||||
mock_async_client::succeed(&tok, nullptr);
|
||||
REQUIRE(tok.is_complete());
|
||||
|
||||
// A wait does not reset the "complete" flag.
|
||||
|
||||
try {
|
||||
tok.wait();
|
||||
REQUIRE(tok.is_complete());
|
||||
}
|
||||
catch (...) {
|
||||
FAIL("token::wait() should not throw on success");
|
||||
}
|
||||
|
||||
// try_wait()
|
||||
try {
|
||||
REQUIRE(tok.try_wait());
|
||||
REQUIRE(tok.is_complete());
|
||||
}
|
||||
catch (...) {
|
||||
FAIL("token::wait() should not throw on success");
|
||||
}
|
||||
|
||||
// wait_for()
|
||||
try {
|
||||
REQUIRE(tok.wait_for(TIMEOUT));
|
||||
REQUIRE(tok.is_complete());
|
||||
}
|
||||
catch (...) {
|
||||
FAIL("token::wait_for() should not throw on success");
|
||||
}
|
||||
|
||||
// wait_until()
|
||||
const auto TO = steady_clock::now() + TIMEOUT;
|
||||
try {
|
||||
REQUIRE(tok.wait_until(TO));
|
||||
REQUIRE(tok.is_complete());
|
||||
}
|
||||
catch (...) {
|
||||
FAIL("token::wait_until() should not throw on success");
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test wait for completion on failure case
|
||||
// All wait's should throw if the action failed
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token wait failure", "[token]")
|
||||
{
|
||||
const auto TIMEOUT = milliseconds(10);
|
||||
|
||||
mqtt::token tok{TYPE, cli};
|
||||
|
||||
// NOTE: Make sure the complete flag is already true and the return
|
||||
// code (rc) is MQTTASYNC_FAILURE, so the token::wait()
|
||||
// returns immediately. Otherwise we will get stuck in a single thread
|
||||
// that can't change the complete flag.
|
||||
constexpr int MESSAGE_ID = 12;
|
||||
MQTTAsync_failureData data = {
|
||||
.token = MESSAGE_ID,
|
||||
.code = MQTTASYNC_FAILURE,
|
||||
.message = nullptr,
|
||||
};
|
||||
mock_async_client::fail(&tok, &data);
|
||||
|
||||
REQUIRE(tok.is_complete());
|
||||
REQUIRE(MESSAGE_ID == tok.get_message_id());
|
||||
REQUIRE(MQTTASYNC_FAILURE == tok.get_return_code());
|
||||
|
||||
try {
|
||||
tok.wait();
|
||||
FAIL("token::wait() should throw on failure");
|
||||
}
|
||||
catch (mqtt::exception& ex) {
|
||||
REQUIRE(MQTTASYNC_FAILURE == ex.get_return_code());
|
||||
}
|
||||
|
||||
try {
|
||||
tok.try_wait();
|
||||
FAIL("token::try_wait() should throw on failure");
|
||||
}
|
||||
catch (mqtt::exception& ex) {
|
||||
REQUIRE(MQTTASYNC_FAILURE == ex.get_return_code());
|
||||
}
|
||||
|
||||
try {
|
||||
tok.wait_for(TIMEOUT);
|
||||
FAIL("token::wait_for() should throw on failure");
|
||||
}
|
||||
catch (mqtt::exception& ex) {
|
||||
REQUIRE(MQTTASYNC_FAILURE == ex.get_return_code());
|
||||
}
|
||||
|
||||
try {
|
||||
tok.wait_until(steady_clock::now() + TIMEOUT);
|
||||
FAIL("token::wait_until() should throw on failure");
|
||||
}
|
||||
catch (mqtt::exception& ex) {
|
||||
REQUIRE(MQTTASYNC_FAILURE == ex.get_return_code());
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Test wait for completion on failure due timeout case
|
||||
// All waits should return false, but not throw, on a timeout
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
TEST_CASE("token wait for timeout", "[token]")
|
||||
{
|
||||
const auto TIMEOUT = milliseconds(10);
|
||||
|
||||
mqtt::token tok{TYPE, cli};
|
||||
|
||||
// Test for timeout on non-signaled token.
|
||||
REQUIRE(!tok.is_complete());
|
||||
|
||||
// try_wait()
|
||||
try {
|
||||
REQUIRE(!tok.try_wait());
|
||||
}
|
||||
catch (...) {
|
||||
FAIL("token::try_wait() should not throw");
|
||||
}
|
||||
|
||||
// wait_for()
|
||||
REQUIRE(!tok.is_complete());
|
||||
try {
|
||||
REQUIRE(!tok.wait_for(TIMEOUT));
|
||||
}
|
||||
catch (...) {
|
||||
FAIL("token::wait_for() should not throw on timeout");
|
||||
}
|
||||
|
||||
// wait_until()
|
||||
const auto TO = steady_clock::now() + TIMEOUT;
|
||||
REQUIRE(!tok.is_complete());
|
||||
try {
|
||||
REQUIRE(!tok.wait_until(TO));
|
||||
}
|
||||
catch (...) {
|
||||
FAIL("token::wait_until() should not throw on timeout");
|
||||
}
|
||||
}
|
||||
|
@ -44,7 +44,7 @@ static const char* BUF = "Hello there";
|
||||
static const size_t N = std::strlen(BUF);
|
||||
static const binary PAYLOAD { BUF };
|
||||
|
||||
static mqtt::test::mock_async_client cli;
|
||||
static mqtt::mock_async_client cli;
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Constructors
|
||||
|
@ -73,7 +73,7 @@ TEST_CASE("will_options default ctor", "[options]")
|
||||
|
||||
TEST_CASE("will_options string buf ctor", "[options]")
|
||||
{
|
||||
test::mock_async_client cli;
|
||||
mock_async_client cli;
|
||||
mqtt::topic topic { cli, TOPIC };
|
||||
|
||||
mqtt::will_options opts(topic, BUF, N, QOS, true);
|
||||
|
Loading…
x
Reference in New Issue
Block a user