1
0
mirror of https://github.com/eclipse/paho.mqtt.cpp.git synced 2025-05-09 19:31:22 +08:00

Converted connect_options unit tests from CppUnit to Catch2

This commit is contained in:
fpagliughi 2020-08-24 00:27:56 -04:00
parent 51da7fb8f3
commit 9bc5403b62
7 changed files with 455 additions and 500 deletions

View File

@ -128,6 +128,12 @@ public:
* @param opt Another object to move into this new one.
*/
connect_options& operator=(connect_options&& opt);
/**
* Expose the underlying C struct for the unit tests.
*/
#if defined(UNIT_TESTS)
const MQTTAsync_connectOptions& c_struct() const { return opts_; }
#endif
/**
* Gets the "keep alive" interval.
* @return The keep alive interval in seconds.

View File

@ -1,486 +0,0 @@
// connect_options_test.h
// Unit tests for the connect_options class in the Paho MQTT C++ library.
/*******************************************************************************
* Copyright (c) 2016 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:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#ifndef __mqtt_connect_options_test_h
#define __mqtt_connect_options_test_h
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/extensions/HelperMacros.h>
#include "mqtt/connect_options.h"
#include "dummy_async_client.h"
namespace mqtt {
/////////////////////////////////////////////////////////////////////////////
class connect_options_test : public CppUnit::TestFixture
{
CPPUNIT_TEST_SUITE( connect_options_test );
CPPUNIT_TEST( test_dflt_constructor );
CPPUNIT_TEST( test_user_constructor );
CPPUNIT_TEST( test_copy_constructor );
CPPUNIT_TEST( test_move_constructor );
CPPUNIT_TEST( test_copy_assignment );
CPPUNIT_TEST( test_move_assignment );
CPPUNIT_TEST( test_set_user );
CPPUNIT_TEST( test_set_long_user );
CPPUNIT_TEST( test_set_will );
CPPUNIT_TEST( test_set_ssl );
CPPUNIT_TEST( test_set_token );
CPPUNIT_TEST( test_set_keep_alive );
CPPUNIT_TEST( test_set_connect_timeout );
CPPUNIT_TEST( test_set_servers );
CPPUNIT_TEST( test_set_auto_reconnect );
CPPUNIT_TEST_SUITE_END();
// C struct signature/eyecatcher
const char* CSIG = "MQTC";
const size_t CSIG_LEN = std::strlen(CSIG);
// These must match the C init struct
const int DFLT_KEEP_ALIVE = 60;
const int DFLT_CONNECT_TIMEOUT = 30;
const bool DFLT_AUTO_RECONNECT = false;
const std::string USER { "wally" };
const std::string PASSWD { "xyzpdq" };
const std::string EMPTY_STR;
const std::vector<string> URIsVec = {
"tcp://server1:1883",
"tcp://server2:1883",
"ssl://server3:8883"
};
const const_string_collection_ptr URIs = std::make_shared<const string_collection>(URIsVec);
static constexpr token::Type TOKEN_TYPE = token::Type::CONNECT;
public:
void setUp() {}
void tearDown() {}
// ----------------------------------------------------------------------
// Test the default constructor
// ----------------------------------------------------------------------
void test_dflt_constructor() {
mqtt::connect_options opts;
CPPUNIT_ASSERT_EQUAL(EMPTY_STR, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(EMPTY_STR, opts.get_password_str());
CPPUNIT_ASSERT_EQUAL(DFLT_KEEP_ALIVE, (int) opts.get_keep_alive_interval().count());
CPPUNIT_ASSERT_EQUAL(DFLT_CONNECT_TIMEOUT, (int) opts.get_connect_timeout().count());
CPPUNIT_ASSERT(!opts.get_servers());
CPPUNIT_ASSERT_EQUAL(DFLT_AUTO_RECONNECT, opts.get_automatic_reconnect());
const auto& c_struct = opts.opts_;
CPPUNIT_ASSERT(!memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
CPPUNIT_ASSERT_EQUAL(DFLT_KEEP_ALIVE, c_struct.keepAliveInterval);
CPPUNIT_ASSERT_EQUAL(DFLT_CONNECT_TIMEOUT, c_struct.connectTimeout);
CPPUNIT_ASSERT(c_struct.username == nullptr);
CPPUNIT_ASSERT(c_struct.password == nullptr);
CPPUNIT_ASSERT_EQUAL(0, c_struct.binarypwd.len);
CPPUNIT_ASSERT(c_struct.binarypwd.data == nullptr);
// No callbacks without a context token
CPPUNIT_ASSERT(c_struct.context == nullptr);
CPPUNIT_ASSERT(c_struct.onSuccess == nullptr);
CPPUNIT_ASSERT(c_struct.onFailure == nullptr);
// No will or SSL, for default
CPPUNIT_ASSERT(c_struct.will == nullptr);
CPPUNIT_ASSERT(c_struct.ssl == nullptr);
CPPUNIT_ASSERT_EQUAL(0, c_struct.serverURIcount);
CPPUNIT_ASSERT(nullptr == c_struct.serverURIs);
}
// ----------------------------------------------------------------------
// Test the constructor that takes user/password
// ----------------------------------------------------------------------
void test_user_constructor() {
mqtt::connect_options opts { USER, PASSWD };
const auto& c_struct = opts.opts_;
CPPUNIT_ASSERT(!memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
CPPUNIT_ASSERT(!strcmp(USER.c_str(), c_struct.username));
CPPUNIT_ASSERT(c_struct.password == nullptr);
CPPUNIT_ASSERT_EQUAL(PASSWD.size(), size_t(c_struct.binarypwd.len));
CPPUNIT_ASSERT(!memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
// No callbacks without a context token
CPPUNIT_ASSERT(c_struct.context == nullptr);
CPPUNIT_ASSERT(c_struct.onSuccess == nullptr);
CPPUNIT_ASSERT(c_struct.onFailure == nullptr);
}
// ----------------------------------------------------------------------
// Test the copy constructor
// ----------------------------------------------------------------------
void test_copy_constructor() {
mqtt::connect_options orgOpts { USER, PASSWD };
mqtt::connect_options opts { orgOpts };
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
const auto& c_struct = opts.opts_;
CPPUNIT_ASSERT(!memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
CPPUNIT_ASSERT(!strcmp(USER.c_str(), c_struct.username));
CPPUNIT_ASSERT(c_struct.password == nullptr);
CPPUNIT_ASSERT_EQUAL(PASSWD.size(), size_t(c_struct.binarypwd.len));
CPPUNIT_ASSERT(!memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
// Make sure it's a true copy, not linked to the original
orgOpts.set_user_name(EMPTY_STR);
orgOpts.set_password(EMPTY_STR);
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
}
// ----------------------------------------------------------------------
// Test the move constructor
// ----------------------------------------------------------------------
void test_move_constructor() {
mqtt::connect_options orgOpts { USER, PASSWD };
mqtt::connect_options opts { std::move(orgOpts) };
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
const auto& c_struct = opts.opts_;
CPPUNIT_ASSERT(!memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
CPPUNIT_ASSERT(!strcmp(USER.c_str(), c_struct.username));
CPPUNIT_ASSERT(c_struct.password == nullptr);
CPPUNIT_ASSERT_EQUAL(PASSWD.size(), size_t(c_struct.binarypwd.len));
CPPUNIT_ASSERT(!memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
// Make sure it's a true copy, not linked to the original
orgOpts.set_user_name(EMPTY_STR);
orgOpts.set_password(EMPTY_STR);
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
// Check that the original was moved
CPPUNIT_ASSERT_EQUAL(EMPTY_STR, orgOpts.get_user_name());
CPPUNIT_ASSERT_EQUAL(EMPTY_STR, orgOpts.get_password_str());
}
// ----------------------------------------------------------------------
// Test the copy assignment operator=(const&)
// ----------------------------------------------------------------------
void test_copy_assignment() {
mqtt::connect_options orgOpts { USER, PASSWD };
mqtt::connect_options opts;
opts = orgOpts;
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
const auto& c_struct = opts.opts_;
CPPUNIT_ASSERT(!memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
CPPUNIT_ASSERT(!strcmp(USER.c_str(), c_struct.username));
CPPUNIT_ASSERT(c_struct.password == nullptr);
CPPUNIT_ASSERT_EQUAL(PASSWD.size(), size_t(c_struct.binarypwd.len));
CPPUNIT_ASSERT(!memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
// Make sure it's a true copy, not linked to the original
orgOpts.set_user_name(EMPTY_STR);
orgOpts.set_password(EMPTY_STR);
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
// Self assignment should cause no harm
opts = opts;
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
}
// ----------------------------------------------------------------------
// Test the move assignment, operator=(&&)
// ----------------------------------------------------------------------
void test_move_assignment() {
mqtt::connect_options orgOpts { USER, PASSWD };
mqtt::connect_options opts { std::move(orgOpts) };
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
const auto& c_struct = opts.opts_;
CPPUNIT_ASSERT(!memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
CPPUNIT_ASSERT(!strcmp(USER.c_str(), c_struct.username));
CPPUNIT_ASSERT(c_struct.password == nullptr);
CPPUNIT_ASSERT_EQUAL(PASSWD.size(), size_t(c_struct.binarypwd.len));
CPPUNIT_ASSERT(!memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
// Make sure it's a true copy, not linked to the original
orgOpts.set_user_name(EMPTY_STR);
orgOpts.set_password(EMPTY_STR);
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
// Check that the original was moved
CPPUNIT_ASSERT_EQUAL(EMPTY_STR, orgOpts.get_user_name());
CPPUNIT_ASSERT_EQUAL(EMPTY_STR, orgOpts.get_password_str());
// Self assignment should cause no harm
// (clang++ is smart enough to warn about this)
#if !defined(__clang__)
opts = std::move(opts);
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
#endif
}
// ----------------------------------------------------------------------
// Test set/get of the user and password.
// ----------------------------------------------------------------------
void test_set_user() {
mqtt::connect_options opts;
const auto& c_struct = opts.opts_;
opts.set_user_name(USER);
opts.set_password(PASSWD);
CPPUNIT_ASSERT_EQUAL(USER, opts.get_user_name());
CPPUNIT_ASSERT_EQUAL(PASSWD, opts.get_password_str());
CPPUNIT_ASSERT(!strcmp(USER.c_str(), c_struct.username));
CPPUNIT_ASSERT(c_struct.password == nullptr);
CPPUNIT_ASSERT_EQUAL(PASSWD.size(), size_t(c_struct.binarypwd.len));
CPPUNIT_ASSERT(!memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
}
// ----------------------------------------------------------------------
// Test set/get of a long user name and password.
// ----------------------------------------------------------------------
void test_set_long_user() {
std::string user;
std::string passwd;
for (int i=0; i<1053; ++i) {
if (isprint(char(i))) user.push_back(char(i));
passwd.push_back(byte(i));
}
mqtt::connect_options orgOpts;
orgOpts.set_user_name(user);
orgOpts.set_password(passwd);
CPPUNIT_ASSERT_EQUAL(user, orgOpts.get_user_name());
CPPUNIT_ASSERT(passwd == orgOpts.get_password_str());
mqtt::connect_options opts;
opts = orgOpts;
CPPUNIT_ASSERT_EQUAL(user, opts.get_user_name());
CPPUNIT_ASSERT(passwd == opts.get_password_str());
const auto& c_struct = opts.opts_;
CPPUNIT_ASSERT(!strcmp(user.c_str(), c_struct.username));
CPPUNIT_ASSERT(c_struct.password == nullptr);
CPPUNIT_ASSERT_EQUAL(passwd.size(), size_t(c_struct.binarypwd.len));
CPPUNIT_ASSERT(!memcmp(passwd.data(), c_struct.binarypwd.data, PASSWD.size()));
}
// ----------------------------------------------------------------------
// Test set/get of will options
// ----------------------------------------------------------------------
void test_set_will() {
mqtt::connect_options opts;
const auto& c_struct = opts.opts_;
CPPUNIT_ASSERT(nullptr == c_struct.will);
mqtt::will_options willOpts;
opts.set_will(willOpts);
CPPUNIT_ASSERT(nullptr != c_struct.will);
CPPUNIT_ASSERT_EQUAL(&opts.will_.opts_, c_struct.will);
}
// ----------------------------------------------------------------------
// Test set/get of ssl options
// ----------------------------------------------------------------------
void test_set_ssl() {
mqtt::connect_options opts;
const auto& c_struct = opts.opts_;
CPPUNIT_ASSERT(nullptr == c_struct.ssl);
mqtt::ssl_options sslOpts;
opts.set_ssl(sslOpts);
CPPUNIT_ASSERT(nullptr != c_struct.ssl);
CPPUNIT_ASSERT_EQUAL(&opts.ssl_.opts_, c_struct.ssl);
}
// ----------------------------------------------------------------------
// Test set/get of context token
// ----------------------------------------------------------------------
void test_set_token() {
mqtt::connect_options opts;
const auto& c_struct = opts.opts_;
CPPUNIT_ASSERT(nullptr == c_struct.context);
mqtt::test::dummy_async_client ac;
auto tok = token::create(TOKEN_TYPE, ac);
opts.set_token(tok);
CPPUNIT_ASSERT_EQUAL(tok, opts.get_token());
CPPUNIT_ASSERT(tok.get() == c_struct.context);
}
// ----------------------------------------------------------------------
// Test set/get of keep alive interval
// ----------------------------------------------------------------------
void test_set_keep_alive() {
mqtt::connect_options opts;
const auto& c_struct = opts.opts_;
// Set as an int
const int KEEP_ALIVE_SEC = 30;
opts.set_keep_alive_interval(KEEP_ALIVE_SEC);
CPPUNIT_ASSERT_EQUAL(KEEP_ALIVE_SEC, (int) opts.get_keep_alive_interval().count());
CPPUNIT_ASSERT_EQUAL(KEEP_ALIVE_SEC, c_struct.keepAliveInterval);
// Set as an chrono
opts.set_keep_alive_interval(std::chrono::milliseconds(2*KEEP_ALIVE_SEC*1000));
CPPUNIT_ASSERT_EQUAL(2*KEEP_ALIVE_SEC, (int) opts.get_keep_alive_interval().count());
CPPUNIT_ASSERT_EQUAL(2*KEEP_ALIVE_SEC, c_struct.keepAliveInterval);
}
// ----------------------------------------------------------------------
// Test set/get of connect timeout
// ----------------------------------------------------------------------
void test_set_connect_timeout() {
mqtt::connect_options opts;
const auto& c_struct = opts.opts_;
// Set as an int
const int TIMEOUT_SEC = 10;
opts.set_connect_timeout(TIMEOUT_SEC);
CPPUNIT_ASSERT_EQUAL(TIMEOUT_SEC, (int) opts.get_connect_timeout().count());
CPPUNIT_ASSERT_EQUAL(TIMEOUT_SEC, c_struct.connectTimeout);
// Set as an chrono
opts.set_connect_timeout(std::chrono::milliseconds(2*TIMEOUT_SEC*1000));
CPPUNIT_ASSERT_EQUAL(2*TIMEOUT_SEC, (int) opts.get_connect_timeout().count());
CPPUNIT_ASSERT_EQUAL(2*TIMEOUT_SEC, c_struct.connectTimeout);
}
// ----------------------------------------------------------------------
// Test set/get of server URIs
// ----------------------------------------------------------------------
void test_set_servers() {
mqtt::connect_options opts;
const auto& c_struct = opts.opts_;
opts.set_servers(URIs);
CPPUNIT_ASSERT_EQUAL(URIs.get(), opts.get_servers().get());
// Check the C struct
CPPUNIT_ASSERT_EQUAL((int) URIsVec.size(), c_struct.serverURIcount);
CPPUNIT_ASSERT(!strcmp(URIsVec[0].c_str(), c_struct.serverURIs[0]));
CPPUNIT_ASSERT(!strcmp(URIsVec[1].c_str(), c_struct.serverURIs[1]));
CPPUNIT_ASSERT(!strcmp(URIsVec[2].c_str(), c_struct.serverURIs[2]));
}
// ----------------------------------------------------------------------
// Test set/get of the auto reconnect values
// ----------------------------------------------------------------------
void test_set_auto_reconnect() {
mqtt::connect_options opts;
const auto& c_struct = opts.opts_;
// Set as an int
const int TIMEOUT_SEC = 10;
opts.set_automatic_reconnect(TIMEOUT_SEC, 2*TIMEOUT_SEC);
CPPUNIT_ASSERT_EQUAL(true, opts.get_automatic_reconnect());
CPPUNIT_ASSERT_EQUAL(TIMEOUT_SEC, (int) opts.get_min_retry_interval().count());
CPPUNIT_ASSERT_EQUAL(2*TIMEOUT_SEC, (int) opts.get_max_retry_interval().count());
CPPUNIT_ASSERT_EQUAL(TIMEOUT_SEC, c_struct.minRetryInterval);
CPPUNIT_ASSERT_EQUAL(2*TIMEOUT_SEC, c_struct.maxRetryInterval);
// Set as an chrono
opts.set_automatic_reconnect(std::chrono::milliseconds(2000*TIMEOUT_SEC),
std::chrono::milliseconds(4000*TIMEOUT_SEC));
CPPUNIT_ASSERT_EQUAL(true, opts.get_automatic_reconnect());
CPPUNIT_ASSERT_EQUAL(2*TIMEOUT_SEC, (int) opts.get_min_retry_interval().count());
CPPUNIT_ASSERT_EQUAL(4*TIMEOUT_SEC, (int) opts.get_max_retry_interval().count());
CPPUNIT_ASSERT_EQUAL(2*TIMEOUT_SEC, c_struct.minRetryInterval);
CPPUNIT_ASSERT_EQUAL(4*TIMEOUT_SEC, c_struct.maxRetryInterval);
// Turn it off
opts.set_automatic_reconnect(false);
CPPUNIT_ASSERT_EQUAL(false, opts.get_automatic_reconnect());
}
};
/////////////////////////////////////////////////////////////////////////////
// end namespace mqtt
}
#endif // __mqtt_connect_options_test_h

View File

@ -21,7 +21,6 @@
#include "async_client_v3_test.h"
#include "client_test.h"
#include "ssl_options_test.h"
#include "connect_options_test.h"
#include "disconnect_options_test.h"
#include "response_options_test.h"
#include "delivery_response_options_test.h"
@ -39,7 +38,6 @@ int main(int argc, char* argv[])
CPPUNIT_TEST_SUITE_REGISTRATION( mqtt::ssl_options_test );
#endif
CPPUNIT_TEST_SUITE_REGISTRATION( mqtt::connect_options_test );
CPPUNIT_TEST_SUITE_REGISTRATION( mqtt::disconnect_options_test );
CPPUNIT_TEST_SUITE_REGISTRATION( mqtt::response_options_test );

View File

@ -30,6 +30,7 @@ find_package(Catch2 REQUIRED)
add_executable(unit_tests unit_tests.cpp
test_buffer_ref.cpp
test_connect_options.cpp
test_message.cpp
test_properties.cpp
test_string_collection.cpp

View File

@ -0,0 +1,436 @@
// test_connect_options.cpp
//
// Unit tests for the connect_options class in the Paho MQTT C++ library.
//
/*******************************************************************************
* 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:
* Frank Pagliughi - initial implementation and documentation
*******************************************************************************/
#define UNIT_TESTS
#include "catch2/catch.hpp"
#include "mqtt/connect_options.h"
#include "mock_async_client.h"
using namespace std::chrono;
using namespace mqtt;
// C struct signature/eyecatcher
static const char* CSIG = "MQTC";
static const size_t CSIG_LEN = std::strlen(CSIG);
// These must match the C init struct
static const int DFLT_KEEP_ALIVE = 60;
static const int DFLT_CONNECT_TIMEOUT = 30;
static const bool DFLT_AUTO_RECONNECT = false;
static const std::string USER { "wally" };
static const std::string PASSWD { "xyzpdq" };
static const std::string EMPTY_STR;
static const std::vector<string> URIsVec = {
"tcp://server1:1883",
"tcp://server2:1883",
"ssl://server3:8883"
};
const const_string_collection_ptr URIs = std::make_shared<const string_collection>(URIsVec);
static constexpr token::Type TOKEN_TYPE = token::Type::CONNECT;
// ----------------------------------------------------------------------
// Test the default constructor
// ----------------------------------------------------------------------
TEST_CASE("connect_options default ctor", "[options]")
{
mqtt::connect_options opts;
REQUIRE(EMPTY_STR == opts.get_user_name());
REQUIRE(EMPTY_STR == opts.get_password_str());
REQUIRE(DFLT_KEEP_ALIVE == (int) opts.get_keep_alive_interval().count());
REQUIRE(DFLT_CONNECT_TIMEOUT == (int) opts.get_connect_timeout().count());
REQUIRE_FALSE(opts.get_servers());
REQUIRE(DFLT_AUTO_RECONNECT == opts.get_automatic_reconnect());
const auto& c_struct = opts.c_struct();
REQUIRE(0 == memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
REQUIRE(DFLT_KEEP_ALIVE == c_struct.keepAliveInterval);
REQUIRE(DFLT_CONNECT_TIMEOUT == c_struct.connectTimeout);
REQUIRE(c_struct.username == nullptr);
REQUIRE(c_struct.password == nullptr);
REQUIRE(0 == c_struct.binarypwd.len);
REQUIRE(c_struct.binarypwd.data == nullptr);
// No callbacks without a context token
REQUIRE(c_struct.context == nullptr);
REQUIRE(c_struct.onSuccess == nullptr);
REQUIRE(c_struct.onFailure == nullptr);
// No will or SSL, for default
REQUIRE(c_struct.will == nullptr);
REQUIRE(c_struct.ssl == nullptr);
REQUIRE(0 == c_struct.serverURIcount);
REQUIRE(nullptr == c_struct.serverURIs);
}
// ----------------------------------------------------------------------
// Test the constructor that takes user/password
// ----------------------------------------------------------------------
TEST_CASE("connect_options user_constructor", "[options]")
{
mqtt::connect_options opts { USER, PASSWD };
const auto& c_struct = opts.c_struct();
REQUIRE(0 == memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
REQUIRE(0 == strcmp(USER.c_str(), c_struct.username));
REQUIRE(c_struct.password == nullptr);
REQUIRE(PASSWD.size() == size_t(c_struct.binarypwd.len));
REQUIRE(0 == memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
// No callbacks without a context token
REQUIRE(c_struct.context == nullptr);
REQUIRE(c_struct.onSuccess == nullptr);
REQUIRE(c_struct.onFailure == nullptr);
}
// ----------------------------------------------------------------------
// Test the copy constructor
// ----------------------------------------------------------------------
TEST_CASE("connect_options copy ctor", "[options]")
{
mqtt::connect_options orgOpts { USER, PASSWD };
mqtt::connect_options opts { orgOpts };
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
const auto& c_struct = opts.c_struct();
REQUIRE(0 == memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
REQUIRE(0 == strcmp(USER.c_str(), c_struct.username));
REQUIRE(c_struct.password == nullptr);
REQUIRE(PASSWD.size() == size_t(c_struct.binarypwd.len));
REQUIRE(0 == memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
// Make sure it's a true copy, not linked to the original
orgOpts.set_user_name(EMPTY_STR);
orgOpts.set_password(EMPTY_STR);
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
}
// ----------------------------------------------------------------------
// Test the move constructor
// ----------------------------------------------------------------------
TEST_CASE("connect_options move_constructor", "[options]")
{
mqtt::connect_options orgOpts { USER, PASSWD };
mqtt::connect_options opts { std::move(orgOpts) };
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
const auto& c_struct = opts.c_struct();
REQUIRE(0 == memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
REQUIRE(0 == strcmp(USER.c_str(), c_struct.username));
REQUIRE(c_struct.password == nullptr);
REQUIRE(PASSWD.size() == size_t(c_struct.binarypwd.len));
REQUIRE(0 == memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
// Make sure it's a true copy, not linked to the original
orgOpts.set_user_name(EMPTY_STR);
orgOpts.set_password(EMPTY_STR);
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
// Check that the original was moved
REQUIRE(EMPTY_STR == orgOpts.get_user_name());
REQUIRE(EMPTY_STR == orgOpts.get_password_str());
}
// ----------------------------------------------------------------------
// Test the copy assignment operator=(const&)
// ----------------------------------------------------------------------
TEST_CASE("connect_options copy_assignment", "[options]")
{
mqtt::connect_options orgOpts { USER, PASSWD };
mqtt::connect_options opts;
opts = orgOpts;
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
const auto& c_struct = opts.c_struct();
REQUIRE(0 == memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
REQUIRE(0 == strcmp(USER.c_str(), c_struct.username));
REQUIRE(c_struct.password == nullptr);
REQUIRE(PASSWD.size() == size_t(c_struct.binarypwd.len));
REQUIRE(0 == memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
// Make sure it's a true copy, not linked to the original
orgOpts.set_user_name(EMPTY_STR);
orgOpts.set_password(EMPTY_STR);
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
// Self assignment should cause no harm
opts = opts;
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
}
// ----------------------------------------------------------------------
// Test the move assignment, operator=(&&)
// ----------------------------------------------------------------------
TEST_CASE("connect_options move_assignment", "[options]")
{
mqtt::connect_options orgOpts { USER, PASSWD };
mqtt::connect_options opts { std::move(orgOpts) };
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
const auto& c_struct = opts.c_struct();
REQUIRE(0 == memcmp(&c_struct.struct_id, CSIG, CSIG_LEN));
REQUIRE(0 == strcmp(USER.c_str(), c_struct.username));
REQUIRE(c_struct.password == nullptr);
REQUIRE(PASSWD.size() == size_t(c_struct.binarypwd.len));
REQUIRE(0 == memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
// Make sure it's a true copy, not linked to the original
orgOpts.set_user_name(EMPTY_STR);
orgOpts.set_password(EMPTY_STR);
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
// Check that the original was moved
REQUIRE(EMPTY_STR == orgOpts.get_user_name());
REQUIRE(EMPTY_STR == orgOpts.get_password_str());
// Self assignment should cause no harm
// (clang++ is smart enough to warn about this)
#if !defined(__clang__)
opts = std::move(opts);
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
#endif
}
// ----------------------------------------------------------------------
// Test set/get of the user and password.
// ----------------------------------------------------------------------
TEST_CASE("connect_options set_user", "[options]")
{
mqtt::connect_options opts;
const auto& c_struct = opts.c_struct();
opts.set_user_name(USER);
opts.set_password(PASSWD);
REQUIRE(USER == opts.get_user_name());
REQUIRE(PASSWD == opts.get_password_str());
REQUIRE(0 == strcmp(USER.c_str(), c_struct.username));
REQUIRE(c_struct.password == nullptr);
REQUIRE(PASSWD.size() == size_t(c_struct.binarypwd.len));
REQUIRE(0 == memcmp(PASSWD.data(), c_struct.binarypwd.data, PASSWD.size()));
}
// ----------------------------------------------------------------------
// Test set/get of a long user name and password.
// ----------------------------------------------------------------------
TEST_CASE("connect_options set_long_user", "[options]")
{
std::string user;
std::string passwd;
for (int i=0; i<1053; ++i) {
if (isprint(char(i))) user.push_back(char(i));
passwd.push_back(byte(i));
}
mqtt::connect_options orgOpts;
orgOpts.set_user_name(user);
orgOpts.set_password(passwd);
REQUIRE(user == orgOpts.get_user_name());
REQUIRE(passwd == orgOpts.get_password_str());
mqtt::connect_options opts;
opts = orgOpts;
REQUIRE(user == opts.get_user_name());
REQUIRE(passwd == opts.get_password_str());
const auto& c_struct = opts.c_struct();
REQUIRE(0 == strcmp(user.c_str(), c_struct.username));
REQUIRE(c_struct.password == nullptr);
REQUIRE(passwd.size() == size_t(c_struct.binarypwd.len));
REQUIRE(0 == memcmp(passwd.data(), c_struct.binarypwd.data, PASSWD.size()));
}
// ----------------------------------------------------------------------
// Test set/get of will options
// ----------------------------------------------------------------------
TEST_CASE("connect_options set_will", "[options]")
{
mqtt::connect_options opts;
const auto& c_struct = opts.c_struct();
REQUIRE(nullptr == c_struct.will);
mqtt::will_options willOpts;
opts.set_will(willOpts);
REQUIRE(nullptr != c_struct.will);
//REQUIRE(&opts.will_.opts_ == c_struct.will);
}
// ----------------------------------------------------------------------
// Test set/get of ssl options
// ----------------------------------------------------------------------
TEST_CASE("connect_options set_ssl", "[options]")
{
mqtt::connect_options opts;
const auto& c_struct = opts.c_struct();
REQUIRE(nullptr == c_struct.ssl);
mqtt::ssl_options sslOpts;
opts.set_ssl(sslOpts);
REQUIRE(nullptr != c_struct.ssl);
//REQUIRE(&opts.ssl_.opts_ == c_struct.ssl);
}
// ----------------------------------------------------------------------
// Test set/get
// ----------------------------------------------------------------------
TEST_CASE("set_token", "[options]")
{
mqtt::connect_options opts;
const auto& c_struct = opts.c_struct();
REQUIRE(nullptr == c_struct.context);
SECTION("set token") {
mqtt::test::mock_async_client ac;
auto tok = token::create(TOKEN_TYPE, ac);
opts.set_token(tok);
REQUIRE(tok == opts.get_token());
REQUIRE(tok.get() == c_struct.context);
}
SECTION("keep alive") {
// Set as an int
const int KEEP_ALIVE_SEC = 30;
opts.set_keep_alive_interval(KEEP_ALIVE_SEC);
REQUIRE(KEEP_ALIVE_SEC == (int) opts.get_keep_alive_interval().count());
REQUIRE(KEEP_ALIVE_SEC == c_struct.keepAliveInterval);
// Set as an chrono
opts.set_keep_alive_interval(milliseconds(2*KEEP_ALIVE_SEC*1000));
REQUIRE(2*KEEP_ALIVE_SEC == (int) opts.get_keep_alive_interval().count());
REQUIRE(2*KEEP_ALIVE_SEC == c_struct.keepAliveInterval);
}
SECTION("connect timeout") {
// Set as an int
const int TIMEOUT_SEC = 10;
opts.set_connect_timeout(TIMEOUT_SEC);
REQUIRE(TIMEOUT_SEC == (int) opts.get_connect_timeout().count());
REQUIRE(TIMEOUT_SEC == c_struct.connectTimeout);
// Set as an chrono
opts.set_connect_timeout(std::chrono::milliseconds(2*TIMEOUT_SEC*1000));
REQUIRE(2*TIMEOUT_SEC == (int) opts.get_connect_timeout().count());
REQUIRE(2*TIMEOUT_SEC == c_struct.connectTimeout);
}
SECTION("set stervers") {
opts.set_servers(URIs);
REQUIRE(URIs.get() == opts.get_servers().get());
// Check the C struct
REQUIRE((int) URIsVec.size() == c_struct.serverURIcount);
REQUIRE(0 == strcmp(URIsVec[0].c_str(), c_struct.serverURIs[0]));
REQUIRE(0 == strcmp(URIsVec[1].c_str(), c_struct.serverURIs[1]));
REQUIRE(0 == strcmp(URIsVec[2].c_str(), c_struct.serverURIs[2]));
}
SECTION("set auto reconnect") {
// Set as an int
const int TIMEOUT_SEC = 10;
opts.set_automatic_reconnect(TIMEOUT_SEC, 2*TIMEOUT_SEC);
REQUIRE(opts.get_automatic_reconnect());
REQUIRE(TIMEOUT_SEC == (int) opts.get_min_retry_interval().count());
REQUIRE(2*TIMEOUT_SEC == (int) opts.get_max_retry_interval().count());
REQUIRE(TIMEOUT_SEC == c_struct.minRetryInterval);
REQUIRE(2*TIMEOUT_SEC == c_struct.maxRetryInterval);
// Set as an chrono
opts.set_automatic_reconnect(milliseconds(2000*TIMEOUT_SEC),
milliseconds(4000*TIMEOUT_SEC));
REQUIRE(opts.get_automatic_reconnect());
REQUIRE(2*TIMEOUT_SEC == (int) opts.get_min_retry_interval().count());
REQUIRE(4*TIMEOUT_SEC == (int) opts.get_max_retry_interval().count());
REQUIRE(2*TIMEOUT_SEC == c_struct.minRetryInterval);
REQUIRE(4*TIMEOUT_SEC == c_struct.maxRetryInterval);
// Turn it off
opts.set_automatic_reconnect(false);
REQUIRE_FALSE(opts.get_automatic_reconnect());
}
}