1
0
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:
fpagliughi 2020-10-24 13:23:02 -04:00
parent f5e0d7f1cf
commit 60a6e30add
11 changed files with 386 additions and 394 deletions

View File

@ -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;

View File

@ -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 );

View File

@ -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

View File

@ -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
)

View File

@ -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
}

View File

@ -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());

View File

@ -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

View File

@ -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
View 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");
}
}

View File

@ -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

View File

@ -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);