Formatting: Apply to C++ files

This commit is contained in:
Roger A. Light
2025-09-17 11:19:46 +01:00
parent 460995652e
commit 4c24b92e34
127 changed files with 2234 additions and 1552 deletions

View File

@@ -1,5 +1,6 @@
#include "temperature_conversion.h"
int main(int argc, char *argv[])
{
class mqtt_tempconv *tempconv;

View File

@@ -17,6 +17,7 @@ mqtt_tempconv::~mqtt_tempconv()
{
}
void mqtt_tempconv::on_connect(int rc)
{
printf("Connected with code %d.\n", rc);
@@ -26,6 +27,7 @@ void mqtt_tempconv::on_connect(int rc)
}
}
void mqtt_tempconv::on_message(const struct mosquitto_message *message)
{
double temp_celsius, temp_fahrenheit;
@@ -42,6 +44,7 @@ void mqtt_tempconv::on_message(const struct mosquitto_message *message)
}
}
void mqtt_tempconv::on_subscribe(int mid, int qos_count, const int *granted_qos)
{
printf("Subscription succeeded.\n");

View File

@@ -5,13 +5,13 @@
class mqtt_tempconv : public mosqpp::mosquittopp
{
public:
mqtt_tempconv(const char *id, const char *host, int port);
~mqtt_tempconv();
public:
mqtt_tempconv(const char *id, const char *host, int port);
~mqtt_tempconv();
void on_connect(int rc);
void on_message(const struct mosquitto_message *message);
void on_subscribe(int mid, int qos_count, const int *granted_qos);
void on_connect(int rc);
void on_message(const struct mosquitto_message *message);
void on_subscribe(int mid, int qos_count, const int *granted_qos);
};
#endif

View File

@@ -31,6 +31,7 @@ Contributors:
/* The fuzz-only main function. */
extern "C" int db_dump_fuzz_main(int argc, char *argv[]);
void run_db_dump(char *filename)
{
char *argv[2];
@@ -44,6 +45,7 @@ void run_db_dump(char *filename)
free(argv[0]);
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char filename[100];
@@ -53,7 +55,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
snprintf(filename, sizeof(filename), "db_dump_%d.db", getpid());
fptr = fopen(filename, "wb");
if(!fptr) return 1;
if(!fptr){
return 1;
}
fwrite(data, 1, size, fptr);
fclose(fptr);

View File

@@ -31,6 +31,7 @@ Contributors:
/* The fuzz-only main function. */
extern "C" int db_dump_fuzz_main(int argc, char *argv[]);
void run_db_dump(char *filename)
{
char *argv[3];
@@ -46,6 +47,7 @@ void run_db_dump(char *filename)
free(argv[1]);
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char filename[100];
@@ -55,7 +57,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
snprintf(filename, sizeof(filename), "db_dump_client_stats_%d.db", getpid());
fptr = fopen(filename, "wb");
if(!fptr) return 1;
if(!fptr){
return 1;
}
fwrite(data, 1, size, fptr);
fclose(fptr);

View File

@@ -31,6 +31,7 @@ Contributors:
/* The fuzz-only main function. */
extern "C" int db_dump_fuzz_main(int argc, char *argv[]);
void run_db_dump(char *filename)
{
char *argv[3];
@@ -46,6 +47,7 @@ void run_db_dump(char *filename)
free(argv[1]);
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char filename[100];
@@ -55,7 +57,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
snprintf(filename, sizeof(filename), "db_dump_stats_%d.db", getpid());
fptr = fopen(filename, "wb");
if(!fptr) return 1;
if(!fptr){
return 1;
}
fwrite(data, 1, size, fptr);
fclose(fptr);

View File

@@ -31,6 +31,7 @@ Contributors:
/* The fuzz-only main function. */
extern "C" int mosquitto_passwd_fuzz_main(int argc, char *argv[]);
void run_mosquitto_passwd(char *filename)
{
char *argv[5];
@@ -50,6 +51,7 @@ void run_mosquitto_passwd(char *filename)
free(argv[4]);
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char filename[100];
@@ -59,7 +61,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
snprintf(filename, sizeof(filename), "mosquitto_passwd_%d", getpid());
fptr = fopen(filename, "wb");
if(!fptr) return 1;
if(!fptr){
return 1;
}
fwrite(data, 1, size, fptr);
fclose(fptr);

View File

@@ -35,6 +35,7 @@ Contributors:
/* The broker fuzz-only main function. */
extern "C" int mosquitto_fuzz_main(int argc, char *argv[]);
void *run_broker(void *args)
{
char *argv[4];
@@ -64,6 +65,7 @@ void recv_timeout(int sock, void *buf, size_t len, int timeout_us)
(void)recv(sock, buf, len, 0);
}
int connect_retrying(int port)
{
struct sockaddr_in addr;
@@ -91,6 +93,7 @@ int connect_retrying(int port)
return sock;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
struct fuzz_data fuzz;

View File

@@ -45,7 +45,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
snprintf(filename, sizeof(filename), "/tmp/acl_file_%d", getpid());
fptr = fopen(filename, "wb");
if(!fptr) return 1;
if(!fptr){
return 1;
}
fwrite(data, 1, size, fptr);
fclose(fptr);

View File

@@ -19,6 +19,7 @@ Contributors:
#define kMaxInputLength 100000
#include "fuzz_packet_read_base.h"
extern "C" int fuzz_packet_read_init(struct mosquitto *context)
{
context->protocol = mosq_p_mqtt5;
@@ -26,12 +27,14 @@ extern "C" int fuzz_packet_read_init(struct mosquitto *context)
return !context->auth_method;
}
extern "C" void fuzz_packet_read_cleanup(struct mosquitto *context)
{
free(context->auth_method);
context->auth_method = NULL;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
int rc = fuzz_packet_read_base(data, size, handle__auth);

View File

@@ -19,6 +19,7 @@ Contributors:
#define kMaxInputLength 100000
#include "fuzz_packet_read_base.h"
extern "C" int fuzz_basic_auth(int event, void *event_data, void *userdata)
{
struct mosquitto_evt_basic_auth *ed = (struct mosquitto_evt_basic_auth *)event_data;
@@ -33,6 +34,7 @@ extern "C" int fuzz_basic_auth(int event, void *event_data, void *userdata)
}
}
extern "C" int fuzz_packet_read_init(struct mosquitto *context)
{
context->listener->security_options->pid = (mosquitto_plugin_id_t *)calloc(1, sizeof(mosquitto_plugin_id_t));
@@ -45,6 +47,7 @@ extern "C" int fuzz_packet_read_init(struct mosquitto *context)
return 0;
}
extern "C" void fuzz_packet_read_cleanup(struct mosquitto *context)
{
mosquitto_callback_unregister(context->listener->security_options->pid,
@@ -54,6 +57,7 @@ extern "C" void fuzz_packet_read_cleanup(struct mosquitto *context)
context->listener->security_options->pid = NULL;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
return fuzz_packet_read_base(data, size, handle__connect);

View File

@@ -18,6 +18,7 @@ Contributors:
#include "fuzz_packet_read_base.h"
extern "C" int fuzz_acl_check(int event, void *event_data, void *userdata)
{
struct mosquitto_evt_acl_check *ed = (struct mosquitto_evt_acl_check *)event_data;
@@ -32,6 +33,7 @@ extern "C" int fuzz_acl_check(int event, void *event_data, void *userdata)
}
}
extern "C" int fuzz_packet_read_init(struct mosquitto *context)
{
context->listener->security_options->pid = (mosquitto_plugin_id_t *)calloc(1, sizeof(mosquitto_plugin_id_t));
@@ -44,6 +46,7 @@ extern "C" int fuzz_packet_read_init(struct mosquitto *context)
return 0;
}
extern "C" void fuzz_packet_read_cleanup(struct mosquitto *context)
{
mosquitto_callback_unregister(context->listener->security_options->pid,
@@ -53,6 +56,7 @@ extern "C" void fuzz_packet_read_cleanup(struct mosquitto *context)
context->listener->security_options->pid = NULL;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
return fuzz_packet_read_base(data, size, handle__publish);

View File

@@ -19,6 +19,7 @@ Contributors:
#define kMaxInputLength 100000
#include "fuzz_packet_read_base.h"
extern "C" int fuzz_acl_check(int event, void *event_data, void *userdata)
{
struct mosquitto_evt_acl_check *ed = (struct mosquitto_evt_acl_check *)event_data;
@@ -33,6 +34,7 @@ extern "C" int fuzz_acl_check(int event, void *event_data, void *userdata)
}
}
extern "C" int fuzz_packet_read_init(struct mosquitto *context)
{
context->listener->security_options->pid = (mosquitto_plugin_id_t *)calloc(1, sizeof(mosquitto_plugin_id_t));
@@ -45,6 +47,7 @@ extern "C" int fuzz_packet_read_init(struct mosquitto *context)
return 0;
}
extern "C" void fuzz_packet_read_cleanup(struct mosquitto *context)
{
mosquitto_callback_unregister(context->listener->security_options->pid,
@@ -54,6 +57,7 @@ extern "C" void fuzz_packet_read_cleanup(struct mosquitto *context)
context->listener->security_options->pid = NULL;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
return fuzz_packet_read_base(data, size, handle__subscribe);

View File

@@ -19,6 +19,7 @@ Contributors:
#define kMaxInputLength 100000
#include "fuzz_packet_read_base.h"
extern "C" int fuzz_acl_check(int event, void *event_data, void *userdata)
{
struct mosquitto_evt_acl_check *ed = (struct mosquitto_evt_acl_check *)event_data;
@@ -33,6 +34,7 @@ extern "C" int fuzz_acl_check(int event, void *event_data, void *userdata)
}
}
extern "C" int fuzz_packet_read_init(struct mosquitto *context)
{
context->listener->security_options->pid = (mosquitto_plugin_id_t *)calloc(1, sizeof(mosquitto_plugin_id_t));
@@ -45,6 +47,7 @@ extern "C" int fuzz_packet_read_init(struct mosquitto *context)
return 0;
}
extern "C" void fuzz_packet_read_cleanup(struct mosquitto *context)
{
mosquitto_callback_unregister(context->listener->security_options->pid,
@@ -54,6 +57,7 @@ extern "C" void fuzz_packet_read_cleanup(struct mosquitto *context)
context->listener->security_options->pid = NULL;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
return fuzz_packet_read_base(data, size, handle__unsubscribe);

View File

@@ -45,7 +45,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
snprintf(filename, sizeof(filename), "/tmp/password_file_%d", getpid());
fptr = fopen(filename, "wb");
if(!fptr) return 1;
if(!fptr){
return 1;
}
fwrite(data, 1, size, fptr);
fclose(fptr);

View File

@@ -45,7 +45,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
snprintf(filename, sizeof(filename), "/tmp/psk_file_%d", getpid());
fptr = fopen(filename, "wb");
if(!fptr) return 1;
if(!fptr){
return 1;
}
fwrite(data, 1, size, fptr);
fclose(fptr);

View File

@@ -30,8 +30,10 @@ extern "C" {
#include "mosquitto_broker_internal.h"
}
//int sub__messages_queue(const char *source_id, const char *topic, uint8_t qos, int retain, struct mosquitto__base_msg **stored)
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
struct mosquitto__config config = {0};

View File

@@ -18,15 +18,18 @@ Contributors:
#include "fuzz_packet_read_base.h"
extern "C" int fuzz_packet_read_init(struct mosquitto *context)
{
return 0;
}
extern "C" void fuzz_packet_read_cleanup(struct mosquitto *context)
{
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
return fuzz_packet_read_base(data, size, handle__packet);

View File

@@ -32,6 +32,7 @@ Contributors:
/* The broker fuzz-only main function. */
extern "C" int mosquitto_fuzz_main(int argc, char *argv[]);
void run_broker(char *filename)
{
char *argv[5];
@@ -51,7 +52,6 @@ void run_broker(char *filename)
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char filename[100];
@@ -65,7 +65,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
snprintf(filename, sizeof(filename), "/tmp/mosquitto_%d.conf", getpid());
fptr = fopen(filename, "wb");
if(!fptr) return 1;
if(!fptr){
return 1;
}
fwrite(data, 1, size, fptr);
fclose(fptr);

View File

@@ -35,6 +35,7 @@ Contributors:
/* The broker fuzz-only main function. */
extern "C" int mosquitto_fuzz_main(int argc, char *argv[]);
void *run_broker(void *args)
{
char *argv[4];
@@ -64,6 +65,7 @@ void recv_timeout(int sock, void *buf, size_t len, int timeout_us)
(void)recv(sock, buf, len, 0);
}
int connect_retrying(int port)
{
struct sockaddr_in addr;
@@ -91,6 +93,7 @@ int connect_retrying(int port)
return sock;
}
static bool initialise(pthread_t *thread)
{
FILE *fptr;
@@ -113,6 +116,7 @@ static bool initialise(pthread_t *thread)
return true;
}
void deinitialise(pthread_t *thread)
{
pthread_join(*thread, NULL);

View File

@@ -17,6 +17,7 @@ Contributors:
*/
#include <mosquitto.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
mosquitto_pub_topic_check2((const char *)data, size);

View File

@@ -17,6 +17,7 @@ Contributors:
*/
#include <mosquitto.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
mosquitto_sub_topic_check2((const char *)data, size);

View File

@@ -19,6 +19,7 @@ Contributors:
#include <cstdlib>
#include <cstring>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char *buf;

View File

@@ -17,6 +17,7 @@ Contributors:
*/
#include <mosquitto.h>
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
mosquitto_validate_utf8((const char *)data, (int)size);

View File

@@ -40,6 +40,7 @@ extern "C" {
extern struct mosquitto_db db;
void run_dynsec(char *filename)
{
struct mosquitto_plugin_id_t identifier;
@@ -63,6 +64,7 @@ void run_dynsec(char *filename)
db.config = NULL;
}
extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
char filename[100];
@@ -72,7 +74,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
snprintf(filename, sizeof(filename), "/tmp/dynsec%d.conf", getpid());
fptr = fopen(filename, "wb");
if(!fptr) return 1;
if(!fptr){
return 1;
}
fwrite(data, 1, size, fptr);
fclose(fptr);

View File

@@ -88,76 +88,126 @@ mosqpp_EXPORT int property_check_all(int command, const mosquitto_property *prop
* library. Please see mosquitto.h for details of the functions.
*/
class mosqpp_EXPORT mosquittopp {
private:
struct mosquitto *m_mosq;
public:
mosquittopp(const char *id=NULL, bool clean_session=true);
virtual ~mosquittopp();
private:
struct mosquitto *m_mosq;
public:
mosquittopp(const char *id=NULL, bool clean_session=true);
virtual ~mosquittopp();
int reinitialise(const char *id, bool clean_session);
int socket();
int will_set(const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
int will_set_v5(const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false, mosquitto_property *properties=NULL);
int will_clear();
int username_pw_set(const char *username, const char *password=NULL);
int connect(const char *host, int port=1883, int keepalive=60);
int connect(const char *host, int port, int keepalive, const char *bind_address);
int connect_v5(const char *host, int port, int keepalive, const char *bind_address, const mosquitto_property *properties);
int connect_async(const char *host, int port=1883, int keepalive=60);
int connect_async(const char *host, int port, int keepalive, const char *bind_address);
int reconnect();
int reconnect_async();
int disconnect();
int disconnect_v5(int reason_code, const mosquitto_property *properties);
int publish(int *mid, const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
int publish_v5(int *mid, const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false, const mosquitto_property *properties=NULL);
int subscribe(int *mid, const char *sub, int qos=0);
int subscribe_v5(int *mid, const char *sub, int qos=0, int options=0, const mosquitto_property *properties=NULL);
int unsubscribe(int *mid, const char *sub);
int unsubscribe_v5(int *mid, const char *sub, const mosquitto_property *properties);
void reconnect_delay_set(unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff);
int max_inflight_messages_set(unsigned int max_inflight_messages);
void message_retry_set(unsigned int message_retry);
void user_data_set(void *userdata);
int tls_set(const char *cafile, const char *capath=NULL, const char *certfile=NULL, const char *keyfile=NULL, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)=NULL);
int ext_auth_continue(const char *auth_method, uint16_t auth_data_len=0, const void *auth_data=NULL, const mosquitto_property *properties=NULL);
int tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL);
int tls_insecure_set(bool value);
int tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL);
int opts_set(enum mosq_opt_t option, void *value);
int int_option(enum mosq_opt_t option, int value);
int string_option(enum mosq_opt_t option, const char *value);
int void_option(enum mosq_opt_t option, void *value);
int reinitialise(const char *id, bool clean_session);
int socket();
int will_set(const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
int will_set_v5(const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false, mosquitto_property *properties=NULL);
int will_clear();
int username_pw_set(const char *username, const char *password=NULL);
int connect(const char *host, int port=1883, int keepalive=60);
int connect(const char *host, int port, int keepalive, const char *bind_address);
int connect_v5(const char *host, int port, int keepalive, const char *bind_address, const mosquitto_property *properties);
int connect_async(const char *host, int port=1883, int keepalive=60);
int connect_async(const char *host, int port, int keepalive, const char *bind_address);
int reconnect();
int reconnect_async();
int disconnect();
int disconnect_v5(int reason_code, const mosquitto_property *properties);
int publish(int *mid, const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
int publish_v5(int *mid, const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false, const mosquitto_property *properties=NULL);
int subscribe(int *mid, const char *sub, int qos=0);
int subscribe_v5(int *mid, const char *sub, int qos=0, int options=0, const mosquitto_property *properties=NULL);
int unsubscribe(int *mid, const char *sub);
int unsubscribe_v5(int *mid, const char *sub, const mosquitto_property *properties);
void reconnect_delay_set(unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff);
int max_inflight_messages_set(unsigned int max_inflight_messages);
void message_retry_set(unsigned int message_retry);
void user_data_set(void *userdata);
int tls_set(const char *cafile, const char *capath=NULL, const char *certfile=NULL, const char *keyfile=NULL, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)=NULL);
int ext_auth_continue(const char *auth_method, uint16_t auth_data_len=0, const void *auth_data=NULL, const mosquitto_property *properties=NULL);
int tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL);
int tls_insecure_set(bool value);
int tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL);
int opts_set(enum mosq_opt_t option, void *value);
int int_option(enum mosq_opt_t option, int value);
int string_option(enum mosq_opt_t option, const char *value);
int void_option(enum mosq_opt_t option, void *value);
int loop(int timeout=-1, int max_packets=1);
int loop_misc();
int loop_read(int max_packets=1);
int loop_write(int max_packets=1);
int loop_forever(int timeout=-1, int max_packets=1);
int loop_start();
int loop_stop(bool force=false);
bool want_write();
int threaded_set(bool threaded=true);
int socks5_set(const char *host, int port=1080, const char *username=NULL, const char *password=NULL);
int loop(int timeout=-1, int max_packets=1);
int loop_misc();
int loop_read(int max_packets=1);
int loop_write(int max_packets=1);
int loop_forever(int timeout=-1, int max_packets=1);
int loop_start();
int loop_stop(bool force=false);
bool want_write();
int threaded_set(bool threaded=true);
int socks5_set(const char *host, int port=1080, const char *username=NULL, const char *password=NULL);
// names in the functions commented to prevent unused parameter warning
virtual void MOSQ_USED on_pre_connect() {return;}
virtual void MOSQ_USED on_connect(int /*rc*/) {return;}
virtual void MOSQ_USED on_connect_with_flags(int /*rc*/, int /*flags*/) {return;}
virtual void MOSQ_USED on_connect_v5(int /*rc*/, int /*flags*/, const mosquitto_property * /*props*/) {return;}
virtual void MOSQ_USED on_disconnect(int /*rc*/) {return;}
virtual void MOSQ_USED on_disconnect_v5(int /*rc*/, const mosquitto_property * /*props*/) {return;}
virtual void MOSQ_USED on_publish(int /*mid*/) {return;}
virtual void MOSQ_USED on_publish_v5(int /*mid*/, int /*reason_code*/, const mosquitto_property * /*props*/) {return;}
virtual void MOSQ_USED on_message(const struct mosquitto_message * /*message*/) {return;}
virtual void MOSQ_USED on_message_v5(const struct mosquitto_message * /*message*/, const mosquitto_property * /*props*/) {return;}
virtual void MOSQ_USED on_subscribe(int /*mid*/, int /*qos_count*/, const int * /*granted_qos*/) {return;}
virtual void MOSQ_USED on_subscribe_v5(int /*mid*/, int /*qos_count*/, const int * /*granted_qos*/, const mosquitto_property * /*props*/) {return;}
virtual void MOSQ_USED on_unsubscribe(int /*mid*/) {return;}
virtual void MOSQ_USED on_unsubscribe_v5(int /*mid*/, const mosquitto_property * /*props*/) {return;}
virtual void MOSQ_USED on_log(int /*level*/, const char * /*str*/) {return;}
virtual void MOSQ_USED on_error() {return;}
virtual int MOSQ_USED on_ext_auth(const char * /*auth_method*/, uint16_t /*auth_data_len*/, const void * /*auth_data*/, const mosquitto_property * /*props*/) {return MOSQ_ERR_AUTH;}
// names in the functions commented to prevent unused parameter warning
virtual void MOSQ_USED on_pre_connect()
{return;}
virtual void MOSQ_USED on_connect(int /*rc*/)
{return;}
virtual void MOSQ_USED on_connect_with_flags(int /*rc*/, int /*flags*/)
{return;}
virtual void MOSQ_USED on_connect_v5(int /*rc*/, int /*flags*/, const mosquitto_property * /*props*/)
{return;}
virtual void MOSQ_USED on_disconnect(int /*rc*/)
{return;}
virtual void MOSQ_USED on_disconnect_v5(int /*rc*/, const mosquitto_property * /*props*/)
{return;}
virtual void MOSQ_USED on_publish(int /*mid*/)
{return;}
virtual void MOSQ_USED on_publish_v5(int /*mid*/, int /*reason_code*/, const mosquitto_property * /*props*/)
{return;}
virtual void MOSQ_USED on_message(const struct mosquitto_message * /*message*/)
{return;}
virtual void MOSQ_USED on_message_v5(const struct mosquitto_message * /*message*/, const mosquitto_property * /*props*/)
{return;}
virtual void MOSQ_USED on_subscribe(int /*mid*/, int /*qos_count*/, const int * /*granted_qos*/)
{return;}
virtual void MOSQ_USED on_subscribe_v5(int /*mid*/, int /*qos_count*/, const int * /*granted_qos*/, const mosquitto_property * /*props*/)
{return;}
virtual void MOSQ_USED on_unsubscribe(int /*mid*/)
{return;}
virtual void MOSQ_USED on_unsubscribe_v5(int /*mid*/, const mosquitto_property * /*props*/)
{return;}
virtual void MOSQ_USED on_log(int /*level*/, const char * /*str*/)
{return;}
virtual void MOSQ_USED on_error()
{return;}
virtual int MOSQ_USED on_ext_auth(const char * /*auth_method*/, uint16_t /*auth_data_len*/, const void * /*auth_data*/, const mosquitto_property * /*props*/)
{return MOSQ_ERR_AUTH;}
};
}

File diff suppressed because it is too large Load Diff

View File

@@ -21,159 +21,170 @@ Copyright (c) 2022 Cedalo GmbH
namespace t = testing;
struct pending_payload{
struct pending_payload {
struct pending_payload *next, *prev;
char payload[1024];
};
class CtrlShellBrokerTest : public ::t::Test
{
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<EditLineMock> editline_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
LIBMOSQ_CB_connect on_connect{};
LIBMOSQ_CB_message on_message{};
LIBMOSQ_CB_subscribe on_subscribe{};
LIBMOSQ_CB_publish_v5 on_publish{};
struct pending_payload *pending_payloads = nullptr;
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<EditLineMock> editline_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
LIBMOSQ_CB_connect on_connect{};
LIBMOSQ_CB_message on_message{};
LIBMOSQ_CB_subscribe on_subscribe{};
LIBMOSQ_CB_publish_v5 on_publish{};
struct pending_payload *pending_payloads = nullptr;
void expect_setup(struct mosq_config *config)
{
editline_mock_.reset();
EXPECT_CALL(editline_mock_, rl_bind_key(t::Eq('\t'), t::_));
EXPECT_CALL(editline_mock_, add_history(t::_)).WillRepeatedly(t::Return(0));
EXPECT_CALL(editline_mock_, clear_history()).Times(t::AnyNumber());
config->no_colour = true;
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StartsWith("mosquitto_ctrl shell v")));
void expect_setup(struct mosq_config *config)
{
editline_mock_.reset();
EXPECT_CALL(editline_mock_, rl_bind_key(t::Eq('\t'), t::_));
EXPECT_CALL(editline_mock_, add_history(t::_)).WillRepeatedly(t::Return(0));
EXPECT_CALL(editline_mock_, clear_history()).Times(t::AnyNumber());
config->no_colour = true;
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StartsWith("mosquitto_ctrl shell v")));
}
void expect_connect(struct mosquitto *mosq, const char *host, int port)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_new(t::Eq(nullptr), t::Eq(true), t::Eq(nullptr)))
.WillOnce(t::Return(mosq));
EXPECT_CALL(libmosquitto_mock_, mosquitto_int_option(t::Eq(mosq), MOSQ_OPT_PROTOCOL_VERSION, 5));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_subscribe>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_subscribe));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish_v5_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_publish_v5>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_publish));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect(t::Eq(mosq), t::StrEq(host), port, 60));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_start(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_connect>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_connect));
EXPECT_CALL(libmosquitto_mock_, mosquitto_message_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_message>()))
.WillOnce(t::SaveArg<1>(&this->on_message));
}
void expect_disconnect(struct mosquitto *mosq)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_disconnect(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_stop(t::Eq(mosq), false));
EXPECT_CALL(libmosquitto_mock_, mosquitto_destroy(t::Eq(mosq)));
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
}
void expect_connect(struct mosquitto *mosq, const char *host, int port)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_new(t::Eq(nullptr), t::Eq(true), t::Eq(nullptr)))
.WillOnce(t::Return(mosq));
EXPECT_CALL(libmosquitto_mock_, mosquitto_int_option(t::Eq(mosq), MOSQ_OPT_PROTOCOL_VERSION, 5));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_subscribe>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_subscribe));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish_v5_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_publish_v5>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_publish));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect(t::Eq(mosq), t::StrEq(host), port, 60));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_start(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_connect>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_connect));
EXPECT_CALL(libmosquitto_mock_, mosquitto_message_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_message>()))
.WillOnce(t::SaveArg<1>(&this->on_message));
}
void expect_request_response(struct mosquitto *mosq, const char *request, const char *respons)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", respons);
void expect_disconnect(struct mosquitto *mosq)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_disconnect(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_stop(t::Eq(mosq), false));
EXPECT_CALL(libmosquitto_mock_, mosquitto_destroy(t::Eq(mosq)));
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
}
void expect_request_response(struct mosquitto *mosq, const char *request, const char *respons)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", respons);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, pp](){
DL_APPEND(this->pending_payloads, pp);
return 0;
}));
}
void expect_request_response_success(struct mosquitto *mosq, const char *request, const char *command)
{
char response[100];
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\"}]}", command);
expect_request_response(mosq, request, response);
}
void expect_request_response_empty(struct mosquitto *mosq, const char *command)
{
char request[100];
char response[100];
snprintf(request, sizeof(request), "{\"commands\":[{\"command\":\"%s\"}]}", command);
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\",\"data\":{}}]}", command);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, &command](){
append_empty_response(command);
return 0;
}));
}
void append_response(const char *response)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", response);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, pp](){
DL_APPEND(this->pending_payloads, pp);
}
return 0;
}));
}
void append_empty_response(const char *command)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload),
void expect_request_response_success(struct mosquitto *mosq, const char *request, const char *command)
{
char response[100];
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\"}]}", command);
expect_request_response(mosq, request, response);
}
void expect_request_response_empty(struct mosquitto *mosq, const char *command)
{
char request[100];
char response[100];
snprintf(request, sizeof(request), "{\"commands\":[{\"command\":\"%s\"}]}", command);
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\",\"data\":{}}]}", command);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, &command](){
append_empty_response(command);
return 0;
}));
}
void append_response(const char *response)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", response);
DL_APPEND(this->pending_payloads, pp);
}
void append_empty_response(const char *command)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload),
"{\"responses\":[{\"command\":\"%s\",\"data\":{}}]}", command);
DL_APPEND(this->pending_payloads, pp);
}
DL_APPEND(this->pending_payloads, pp);
}
void expect_broker(const char *host, int port)
{
char buf[200];
snprintf(buf, sizeof(buf), "connect mqtt://%s:%d", host, port);
char *s_conn = strdup(buf);
EXPECT_CALL(editline_mock_, readline(t::StrEq("> ")))
.WillOnce(t::Return(s_conn));
void expect_broker(const char *host, int port)
{
char buf[200];
snprintf(buf, sizeof(buf), "connect mqtt://%s:%d", host, port);
char *s_conn = strdup(buf);
EXPECT_CALL(editline_mock_, readline(t::StrEq("mqtt://localhost:1883> ")))
.WillOnce(t::Return(strdup("broker")));
EXPECT_CALL(editline_mock_, readline(t::StrEq("> ")))
.WillOnce(t::Return(s_conn));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe(t::_, nullptr, t::StrEq("$CONTROL/broker/v1/response"), 1))
.WillOnce(t::Return(0));
}
EXPECT_CALL(editline_mock_, readline(t::StrEq("mqtt://localhost:1883> ")))
.WillOnce(t::Return(strdup("broker")));
void expect_connect_and_messages(struct mosquitto *mosq)
{
/* This is a hacky way of working around the async mqtt send/receive which we don't directly control.
* Each send starts a wait which times out after two seconds. We use that call to produce the effect we want.
*/
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
.WillRepeatedly(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
struct pending_payload *pp = pending_payloads;
if(pp){
DL_DELETE(pending_payloads, pp);
msg.payload = pp->payload;
msg.payloadlen = (int)strlen((char *)msg.payload);
this->on_message(mosq, nullptr, &msg);
free(pp);
}
data.response_received = true;
return 0;
}));
}
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe(t::_, nullptr, t::StrEq("$CONTROL/broker/v1/response"), 1))
.WillOnce(t::Return(0));
}
void expect_connect_and_messages(struct mosquitto *mosq)
{
/* This is a hacky way of working around the async mqtt send/receive which we don't directly control.
* Each send starts a wait which times out after two seconds. We use that call to produce the effect we want.
*/
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
.WillRepeatedly(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
struct pending_payload *pp = pending_payloads;
if(pp){
DL_DELETE(pending_payloads, pp);
msg.payload = pp->payload;
msg.payloadlen = (int)strlen((char *)msg.payload);
this->on_message(mosq, nullptr, &msg);
free(pp);
}
data.response_received = true;
return 0;
}));
}
};
@@ -229,29 +240,29 @@ TEST_F(CtrlShellBrokerTest, SubscribeDenied)
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(&mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
this->on_connect(&mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
.WillOnce(t::Invoke([this, &mosq](){
int granted_qos[1] = {128};
this->on_subscribe(&mosq, nullptr, 1, 1, granted_qos);
data.response_received = true;
return 0;
}))
int granted_qos[1] = {128};
this->on_subscribe(&mosq, nullptr, 1, 1, granted_qos);
data.response_received = true;
return 0;
}))
.WillRepeatedly(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
struct pending_payload *pp = pending_payloads;
if(pp){
DL_DELETE(pending_payloads, pp);
msg.payload = pp->payload;
msg.payloadlen = (int)strlen((char *)msg.payload);
this->on_message(&mosq, nullptr, &msg);
free(pp);
}
data.response_received = true;
return 0;
}));
mosquitto_message msg{};
struct pending_payload *pp = pending_payloads;
if(pp){
DL_DELETE(pending_payloads, pp);
msg.payload = pp->payload;
msg.payloadlen = (int)strlen((char *)msg.payload);
this->on_message(&mosq, nullptr, &msg);
free(pp);
}
data.response_received = true;
return 0;
}));
const char *outputs[] = {
"Subscribe failed, check you have permission to access this module.\n",
@@ -291,24 +302,24 @@ TEST_F(CtrlShellBrokerTest, PublishDenied)
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(&mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
this->on_connect(&mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
.WillOnce(t::Invoke([this, &mosq](){
int granted_qos[1] = {1};
this->on_subscribe(&mosq, nullptr, 1, 1, granted_qos);
data.response_received = true;
return 0;
}))
int granted_qos[1] = {1};
this->on_subscribe(&mosq, nullptr, 1, 1, granted_qos);
data.response_received = true;
return 0;
}))
.WillOnce(t::Invoke([this, &mosq](){
this->on_publish(&mosq, nullptr, 1, 128, nullptr);
data.response_received = true;
return 0;
}));
this->on_publish(&mosq, nullptr, 1, 128, nullptr);
data.response_received = true;
return 0;
}));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(&mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq("{\"commands\":[{\"command\":\"listListeners\"}]}"), 1, false));
t::StrEq("{\"commands\":[{\"command\":\"listListeners\"}]}"), 1, false));
const char *outputs[] = {
"Publish failed, check you have permission to access this module.\n",
@@ -339,9 +350,9 @@ TEST_F(CtrlShellBrokerTest, ListListeners)
const char request[] = "{\"commands\":[{\"command\":\"listListeners\"}]}";
const char response[] = "{\"responses\":[{\"command\":\"listListeners\",\"data\":{"
"\"listeners\":["
"{\"port\":1883,\"protocol\":\"mqtt\",\"tls\":false}"
"]}}]}";
"\"listeners\":["
"{\"port\":1883,\"protocol\":\"mqtt\",\"tls\":false}"
"]}}]}";
expect_request_response(&mosq, request, response);
const char *outputs[] = {
@@ -379,9 +390,9 @@ TEST_F(CtrlShellBrokerTest, ListListenersInvalidResponse)
const char request[] = "{\"commands\":[{\"command\":\"listListeners\"}]}";
const char response[] = "{\"responses\":[{\"command\":\"listListeners\",\"data\":{"
"\"listeners\":["
"{\"protocol\":\"mqtt\",\"tls\":false}"
"]}}]}";
"\"listeners\":["
"{\"protocol\":\"mqtt\",\"tls\":false}"
"]}}]}";
expect_request_response(&mosq, request, response);
const char *outputs[] = {
@@ -413,9 +424,9 @@ TEST_F(CtrlShellBrokerTest, ListPlugins)
const char request[] = "{\"commands\":[{\"command\":\"listPlugins\"}]}";
const char response[] = "{\"responses\":[{\"command\":\"listPlugins\",\"data\":{"
"\"plugins\":["
"{\"name\":\"plugin1\",\"control-endpoints\":[\"$CONTROL/plugin1\"]}"
"]}}]}";
"\"plugins\":["
"{\"name\":\"plugin1\",\"control-endpoints\":[\"$CONTROL/plugin1\"]}"
"]}}]}";
expect_request_response(&mosq, request, response);
const char *outputs[] = {
@@ -450,9 +461,9 @@ TEST_F(CtrlShellBrokerTest, ListPluginsInvalidResponse)
const char request[] = "{\"commands\":[{\"command\":\"listPlugins\"}]}";
const char response[] = "{\"responses\":[{\"command\":\"listPlugins\",\"data\":{"
"\"plugins\":["
"{\"control-endpoints\":[\"$CONTROL/plugin1\"]}"
"]}}]}";
"\"plugins\":["
"{\"control-endpoints\":[\"$CONTROL/plugin1\"]}"
"]}}]}";
expect_request_response(&mosq, request, response);
const char *outputs[] = {

View File

@@ -19,47 +19,49 @@ Copyright (c) 2022 Cedalo GmbH
#include "pthread_mock.hpp"
extern "C" {
char **completion_matcher(const char *text, int start, int end);
char *completion_generator(const char *text, int state);
void ctrl_shell__cleanup(void);
char **completion_matcher(const char *text, int start, int end);
char *completion_generator(const char *text, int state);
void ctrl_shell__cleanup(void);
}
namespace t = testing;
class CtrlShellCompletionTest : public ::t::Test
{
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
void expect_setup()
{
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillRepeatedly(t::Invoke([](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
data.response_received = true;
return 0;
}));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe(t::_, t::_, t::_, 1))
.WillRepeatedly(t::Return(0));
void expect_setup()
{
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillRepeatedly(t::Invoke([](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
data.response_received = true;
return 0;
}));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::_, nullptr, t::_, t::_, t::_, 1, false))
.WillRepeatedly(t::Return(0));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe(t::_, t::_, t::_, 1))
.WillRepeatedly(t::Return(0));
rl_readline_name = "mosquitto_ctrl";
rl_completion_entry_function = completion_generator;
rl_attempted_completion_function = completion_matcher;
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::_, nullptr, t::_, t::_, t::_, 1, false))
.WillRepeatedly(t::Return(0));
ctrl_shell__load_module(ctrl_shell__dynsec_init);
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
rl_readline_name = "mosquitto_ctrl";
rl_completion_entry_function = completion_generator;
rl_attempted_completion_function = completion_matcher;
ctrl_shell__load_module(ctrl_shell__dynsec_init);
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
}
};
TEST_F(CtrlShellCompletionTest, NoMatch)
@@ -84,17 +86,19 @@ TEST_F(CtrlShellCompletionTest, MatchArg1)
ASSERT_NE(matches, nullptr);
EXPECT_STREQ(matches[0], "add");
for(match_count = 1; matches[match_count]; match_count++);
for(match_count = 1; matches[match_count]; match_count++){
;
}
ASSERT_EQ(match_count, 5);
char *match_array[4] = {matches[1], matches[2], matches[3], matches[4]};
EXPECT_THAT(match_array, t::UnorderedElementsAreArray({
t::StrEq("addGroupRole"),
t::StrEq("addRoleACL"),
t::StrEq("addGroupClient"),
t::StrEq("addClientRole")
}));
t::StrEq("addGroupRole"),
t::StrEq("addRoleACL"),
t::StrEq("addGroupClient"),
t::StrEq("addClientRole")
}));
for(int i=0; i<match_count; i++){
free(matches[i]);
}

File diff suppressed because it is too large Load Diff

View File

@@ -22,54 +22,58 @@ namespace t = testing;
class CtrlShellHelpTest : public ::t::Test
{
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<EditLineMock> editline_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
LIBMOSQ_CB_connect on_connect{};
LIBMOSQ_CB_message on_message{};
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<EditLineMock> editline_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
LIBMOSQ_CB_connect on_connect{};
LIBMOSQ_CB_message on_message{};
void expect_setup(struct mosq_config *config)
{
editline_mock_.reset();
EXPECT_CALL(editline_mock_, rl_bind_key(t::Eq('\t'), t::_));
EXPECT_CALL(editline_mock_, add_history(t::_)).WillRepeatedly(t::Return(0));
EXPECT_CALL(editline_mock_, clear_history()).Times(t::AnyNumber());
config->no_colour = true;
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StartsWith("mosquitto_ctrl shell v")));
}
void expect_connect(struct mosquitto *mosq, const char *host, int port)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_new(t::Eq(nullptr), t::Eq(true), t::Eq(nullptr)))
.WillOnce(t::Return(mosq));
EXPECT_CALL(libmosquitto_mock_, mosquitto_int_option(t::Eq(mosq), MOSQ_OPT_PROTOCOL_VERSION, 5));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish_v5_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect(t::Eq(mosq), t::StrEq(host), port, 60));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_start(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_connect>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_connect));
EXPECT_CALL(libmosquitto_mock_, mosquitto_message_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_message>()))
.WillOnce(t::SaveArg<1>(&this->on_message));
}
void expect_disconnect(struct mosquitto *mosq)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_disconnect(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_stop(t::Eq(mosq), false));
EXPECT_CALL(libmosquitto_mock_, mosquitto_destroy(t::Eq(mosq)));
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
void expect_setup(struct mosq_config *config)
{
editline_mock_.reset();
EXPECT_CALL(editline_mock_, rl_bind_key(t::Eq('\t'), t::_));
EXPECT_CALL(editline_mock_, add_history(t::_)).WillRepeatedly(t::Return(0));
EXPECT_CALL(editline_mock_, clear_history()).Times(t::AnyNumber());
config->no_colour = true;
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StartsWith("mosquitto_ctrl shell v")));
}
void expect_connect(struct mosquitto *mosq, const char *host, int port)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_new(t::Eq(nullptr), t::Eq(true), t::Eq(nullptr)))
.WillOnce(t::Return(mosq));
EXPECT_CALL(libmosquitto_mock_, mosquitto_int_option(t::Eq(mosq), MOSQ_OPT_PROTOCOL_VERSION, 5));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish_v5_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect(t::Eq(mosq), t::StrEq(host), port, 60));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_start(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_connect>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_connect));
EXPECT_CALL(libmosquitto_mock_, mosquitto_message_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_message>()))
.WillOnce(t::SaveArg<1>(&this->on_message));
}
void expect_disconnect(struct mosquitto *mosq)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_disconnect(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_stop(t::Eq(mosq), false));
EXPECT_CALL(libmosquitto_mock_, mosquitto_destroy(t::Eq(mosq)));
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
}
};
TEST_F(CtrlShellHelpTest, PreConnectHelp)
@@ -103,19 +107,19 @@ TEST_F(CtrlShellHelpTest, PreConnectHelp)
"OK\n\n",
"auth [username]\n",
"\nSet a username and password prior to connecting to a broker.\n", /* help auth */
"\nSet a username and password prior to connecting to a broker.\n", /* help auth */
"connect\n",
"connect mqtt://hostname[:port]\n",
"connect mqtts://hostname[:port]\n",
"connect ws://hostname[:port]\n",
"connect wss://hostname[:port]\n",
"\nConnect to a broker using the provided transport and port.\n",
"If no URL is provided, connects to mqtt://localhost:1883\n", /* help connect */
"connect mqtt://hostname[:port]\n",
"connect mqtts://hostname[:port]\n",
"connect ws://hostname[:port]\n",
"connect wss://hostname[:port]\n",
"\nConnect to a broker using the provided transport and port.\n",
"If no URL is provided, connects to mqtt://localhost:1883\n", /* help connect */
"exit\n",
"\nQuit the program\n", /* help exit */
"\nQuit the program\n", /* help exit */
"help <command>\n",
"\nFind help on a command using 'help <command>'\n",
"Press tab multiple times to find currently available commands.\n", /* help help */
"\nFind help on a command using 'help <command>'\n",
"Press tab multiple times to find currently available commands.\n", /* help help */
"Unknown command 'unknown'\n", /* help unknown */
};
expect_outputs(outputs, sizeof(outputs)/sizeof(char *));
@@ -161,10 +165,10 @@ TEST_F(CtrlShellHelpTest, Connect)
/* This is a hacky way of working around the async mqtt CONNECT/CONNACK which we don't directly control. */
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(&mosq, nullptr, 0);
data.response_received = true;
return 0;
}));
this->on_connect(&mosq, nullptr, 0);
data.response_received = true;
return 0;
}));
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq("\n")));
ctrl_shell__main(&config);
@@ -205,10 +209,10 @@ TEST_F(CtrlShellHelpTest, PostConnectHelp)
*/
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(&mosq, nullptr, 0);
data.response_received = true;
return 0;
}));
this->on_connect(&mosq, nullptr, 0);
data.response_received = true;
return 0;
}));
const char *outputs[] = {
"This is the mosquitto_ctrl interactive shell, for controlling aspects of a mosquitto broker.\n",
@@ -225,16 +229,16 @@ TEST_F(CtrlShellHelpTest, PostConnectHelp)
"\n",
"dynsec\n",
"\nStart the dynamic-security control mode.\n", /* help dynsec */
"\nStart the dynamic-security control mode.\n", /* help dynsec */
"broker\n",
"\nStart the broker control mode.\n", /* help broker */
"\nStart the broker control mode.\n", /* help broker */
"disconnect\n",
"\nDisconnect from the broker\n", /* help disconnect */
"\nDisconnect from the broker\n", /* help disconnect */
"exit\n",
"\nQuit the program\n", /* help exit */
"\nQuit the program\n", /* help exit */
"help <command>\n",
"\nFind help on a command using 'help <command>'\n",
"Press tab multiple times to find currently available commands.\n", /* help help */
"\nFind help on a command using 'help <command>'\n",
"Press tab multiple times to find currently available commands.\n", /* help help */
"Unknown command 'unknown'\n", /* help unknown */
};
expect_outputs(outputs, sizeof(outputs)/sizeof(char *));
@@ -286,16 +290,16 @@ TEST_F(CtrlShellHelpTest, BrokerHelp)
*/
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(&mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
this->on_connect(&mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg);
data.response_received = true;
return 0;
}));
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg);
data.response_received = true;
return 0;
}));
const char *outputs[] = {
"This is the mosquitto_ctrl interactive shell, for controlling aspects of a mosquitto broker.\n",
@@ -307,18 +311,18 @@ TEST_F(CtrlShellHelpTest, BrokerHelp)
"Unknown command 'unknown'\n",
"listPlugins\n",
"\nLists currently loaded plugins.\n",
"\nLists currently loaded plugins.\n",
"listListeners\n",
"\nLists current listeners.\n",
"\nLists current listeners.\n",
"disconnect\n",
"\nDisconnect from the broker\n", /* help disconnect */
"\nDisconnect from the broker\n", /* help disconnect */
"return\n",
"\nLeave broker mode.\n",
"\nLeave broker mode.\n",
"exit\n",
"\nQuit the program\n", /* help exit */
"\nQuit the program\n", /* help exit */
"help <command>\n",
"\nFind help on a command using 'help <command>'\n",
"Press tab multiple times to find currently available commands.\n", /* help help */
"\nFind help on a command using 'help <command>'\n",
"Press tab multiple times to find currently available commands.\n", /* help help */
"Invalid response from broker.\n",
};
expect_outputs(outputs, sizeof(outputs)/sizeof(char *));
@@ -399,39 +403,47 @@ TEST_F(CtrlShellHelpTest, DynsecHelp)
*/
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(&mosq, nullptr, 0); data.response_received = true; return 0; }))
this->on_connect(&mosq, nullptr, 0); data.response_received = true; return 0;
}))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0; }))
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0;
}))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0; }))
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0;
}))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0; }))
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0;
}))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0; }))
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0;
}))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0; }))
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0;
}))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0; }))
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0;
}))
.WillOnce(t::Invoke([this, &mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0; }));
mosquitto_message msg{};
this->on_message(&mosq, nullptr, &msg); data.response_received = true; return 0;
}));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(&mosq), nullptr, t::StrEq("$CONTROL/dynamic-security/v1"), t::_,
t::StrEq("{\"commands\":[{\"command\":\"listClients\"}]}"), 1, false))
t::StrEq("{\"commands\":[{\"command\":\"listClients\"}]}"), 1, false))
.WillOnce(t::Return(0));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(&mosq), nullptr, t::StrEq("$CONTROL/dynamic-security/v1"), t::_,
t::StrEq("{\"commands\":[{\"command\":\"listGroups\"}]}"), 1, false))
t::StrEq("{\"commands\":[{\"command\":\"listGroups\"}]}"), 1, false))
.WillOnce(t::Return(0));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(&mosq), nullptr, t::StrEq("$CONTROL/dynamic-security/v1"), t::_,
t::StrEq("{\"commands\":[{\"command\":\"listRoles\"}]}"), 1, false))
t::StrEq("{\"commands\":[{\"command\":\"listRoles\"}]}"), 1, false))
.WillOnce(t::Return(0));
const char *outputs[] = {
@@ -444,100 +456,100 @@ TEST_F(CtrlShellHelpTest, DynsecHelp)
"Unknown command 'unknown'\n",
"addClientRole <username> <rolename>\n",
"\nAdds a role directly to a client.\n",
"\nAdds a role directly to a client.\n",
"addGroupClient <groupname> <username>\n",
"\nAdds a client to a group.\n",
"\nAdds a client to a group.\n",
"addGroupRole <groupname> <rolename>\n",
"\nAdds a role to a group.\n",
"\nAdds a role to a group.\n",
"addRoleACL <rolename> publishClientReceive allow|deny [priority] <topic>\n",
"addRoleACL <rolename> publishClientSend allow|deny [priority] <topic>\n",
"addRoleACL <rolename> subscribeLiteral allow|deny [priority] <topic>\n",
"addRoleACL <rolename> subscribePattern allow|deny [priority] <topic>\n",
"addRoleACL <rolename> unsubscribeLiteral allow|deny [priority] <topic>\n",
"addRoleACL <rolename> unsubscribePattern allow|deny [priority] <topic>\n",
"\nAdds an ACL to a role, with an optional priority.\n",
"\nACLs of a specific type within a role are processed in order from highest to lowest priority with the first matching ACL applying.\n",
"addRoleACL <rolename> publishClientSend allow|deny [priority] <topic>\n",
"addRoleACL <rolename> subscribeLiteral allow|deny [priority] <topic>\n",
"addRoleACL <rolename> subscribePattern allow|deny [priority] <topic>\n",
"addRoleACL <rolename> unsubscribeLiteral allow|deny [priority] <topic>\n",
"addRoleACL <rolename> unsubscribePattern allow|deny [priority] <topic>\n",
"\nAdds an ACL to a role, with an optional priority.\n",
"\nACLs of a specific type within a role are processed in order from highest to lowest priority with the first matching ACL applying.\n",
"createClient <username> [password [clientid]]\n",
"\nCreate a client with password and optional client id.\n",
"\nCreate a client with password and optional client id.\n",
"createGroup <groupname>\n",
"\nCreate a new group.\n",
"\nCreate a new group.\n",
"createRole <rolename>\n",
"\nCreate a new role.\n",
"\nCreate a new role.\n",
"deleteClient <username>\n",
"\nDelete a client\n",
"\nDelete a client\n",
"deleteGroup <groupname>\n",
"\nDelete a group\n",
"\nDelete a group\n",
"deleteRole <rolename>\n",
"\nDelete a role\n",
"\nDelete a role\n",
"disableClient <username>\n",
"\nDisable a client. This client will not be able to log in, and will be kicked if it has an existing session.\n",
"\nDisable a client. This client will not be able to log in, and will be kicked if it has an existing session.\n",
"enableClient <username>\n",
"\nEnable a client. Disabled clients are unable to log in.\n",
"\nEnable a client. Disabled clients are unable to log in.\n",
"getAnonymousGroup\n",
"\nPrint the group configured as the anonymous group.\n",
"\nPrint the group configured as the anonymous group.\n",
"getClient <username>\n",
"\nPrint details of a client and its groups and direct roles.\n",
"\nPrint details of a client and its groups and direct roles.\n",
"getDefaultACLAccess\n",
"\nPrint the default allow/deny values for the different classes of ACL.\n",
"\nPrint the default allow/deny values for the different classes of ACL.\n",
"getDetails\n",
"\nPrint details including the client, group, and role count, and the current change index.\n",
"\nPrint details including the client, group, and role count, and the current change index.\n",
"getGroup <groupname>\n",
"\nPrint details of a group and its roles.\n",
"\nPrint details of a group and its roles.\n",
"getRole <rolename>\n",
"\nPrint details of a role and its ACLs.\n",
"\nPrint details of a role and its ACLs.\n",
"listClients [count [offset]]\n",
"\nPrint a list of clients configured in the dynsec plugin, with an optional total count and list offset.\n",
"\nPrint a list of clients configured in the dynsec plugin, with an optional total count and list offset.\n",
"listGroups [count [offset]]\n",
"\nPrint a list of groups configured in the dynsec plugin, with an optional total count and list offset.\n",
"\nPrint a list of groups configured in the dynsec plugin, with an optional total count and list offset.\n",
"listRoles [count [offset]]\n",
"\nPrint a list of roles configured in the dynsec plugin, with an optional total count and list offset.\n",
"\nPrint a list of roles configured in the dynsec plugin, with an optional total count and list offset.\n",
"removeClientRole <username> <rolename>\n",
"\nRemoves a role from a client, where the role was directly attached to the client.\n",
"\nRemoves a role from a client, where the role was directly attached to the client.\n",
"removeGroupClient <groupname> <username>\n",
"\nRemoves a client from a group.\n",
"\nRemoves a client from a group.\n",
"removeGroupRole <groupname> <rolename>\n",
"\nRemoves a role from a group.\n",
"\nRemoves a role from a group.\n",
"removeRoleACL <rolename> publishClientReceive <topic>\n",
"removeRoleACL <rolename> publishClientSend <topic>\n",
"removeRoleACL <rolename> subscribeLiteral <topic>\n",
"removeRoleACL <rolename> subscribePattern <topic>\n",
"removeRoleACL <rolename> unsubscribeLiteral <topic>\n",
"removeRoleACL <rolename> unsubscribePattern <topic>\n",
"\nRemoves an ACL from a role.\n",
"removeRoleACL <rolename> publishClientSend <topic>\n",
"removeRoleACL <rolename> subscribeLiteral <topic>\n",
"removeRoleACL <rolename> subscribePattern <topic>\n",
"removeRoleACL <rolename> unsubscribeLiteral <topic>\n",
"removeRoleACL <rolename> unsubscribePattern <topic>\n",
"\nRemoves an ACL from a role.\n",
"setAnonymousGroup <groupname>\n",
"\nSets the anonymous group to a new group.\n",
"\nSets the anonymous group to a new group.\n",
"setClientId <username>\n",
"setClientId <username> <clientid>\n",
"\nSets or clears the clientid associated with a client. If a client has a clientid, all three of username, password, and clientid must match for a client to be able to authenticate.\n",
"setClientId <username> <clientid>\n",
"\nSets or clears the clientid associated with a client. If a client has a clientid, all three of username, password, and clientid must match for a client to be able to authenticate.\n",
"setClientPassword <username> [password]\n",
"\nSets a new password for a client.\n",
"\nSets a new password for a client.\n",
"setDefaultACLAccess publishClientReceive allow|deny\n",
"setDefaultACLAccess publishClientSend allow|deny\n",
"setDefaultACLAccess subscribe allow|deny\n",
"setDefaultACLAccess unsubscribe allow|deny\n",
"\nSets the default ACL access to use for an ACL type. The default access will be applied if no other ACL rules match.\n",
"Setting a rule to 'allow' means that if no ACLs match, it will be accepted.\n",
"Setting a rule to 'deny' means that if no ACLs match, it will be denied.\n",
"setDefaultACLAccess publishClientSend allow|deny\n",
"setDefaultACLAccess subscribe allow|deny\n",
"setDefaultACLAccess unsubscribe allow|deny\n",
"\nSets the default ACL access to use for an ACL type. The default access will be applied if no other ACL rules match.\n",
"Setting a rule to 'allow' means that if no ACLs match, it will be accepted.\n",
"Setting a rule to 'deny' means that if no ACLs match, it will be denied.\n",
"modifyClient <username> textName <textname>\n",
"modifyClient <username> textDescription <textdescription>\n",
"\nModify the text name or text description for a client.\n",
"These are free-text fields for your own use.\n",
"modifyClient <username> textDescription <textdescription>\n",
"\nModify the text name or text description for a client.\n",
"These are free-text fields for your own use.\n",
"modifyGroup <groupname> textName <textname>\n",
"modifyGroup <groupname> textDescription <textdescription>\n",
"\nModify the text name or text description for a group.\n",
"modifyGroup <groupname> textDescription <textdescription>\n",
"\nModify the text name or text description for a group.\n",
"modifyRole <rolename> textName <textname>\n",
"modifyRole <rolename> textDescription <textdescription>\n",
"modifyRole <rolename> allowWildcardSubs true|false\n",
"\nModify the text name or text description for a role.\n",
"modifyRole <rolename> textDescription <textdescription>\n",
"modifyRole <rolename> allowWildcardSubs true|false\n",
"\nModify the text name or text description for a role.\n",
"disconnect\n",
"\nDisconnect from the broker\n", /* help disconnect */
"\nDisconnect from the broker\n", /* help disconnect */
"return\n",
"\nLeave dynsec mode.\n",
"\nLeave dynsec mode.\n",
"exit\n",
"\nQuit the program\n", /* help exit */
"\nQuit the program\n", /* help exit */
"help <command>\n",
"\nFind help on a command using 'help <command>'\n", "Press tab multiple times to find currently available commands.\n", /* help help */
"\nFind help on a command using 'help <command>'\n", "Press tab multiple times to find currently available commands.\n", /* help help */
"Invalid response from broker.\n",
};
expect_outputs(outputs, sizeof(outputs)/sizeof(char *));

View File

@@ -21,156 +21,167 @@ Copyright (c) 2022 Cedalo GmbH
namespace t = testing;
struct pending_payload{
struct pending_payload {
struct pending_payload *next, *prev;
char payload[1024];
};
class CtrlShellOptionsTest : public ::t::Test
{
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<EditLineMock> editline_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
LIBMOSQ_CB_connect on_connect{};
LIBMOSQ_CB_message on_message{};
struct pending_payload *pending_payloads = nullptr;
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<EditLineMock> editline_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
LIBMOSQ_CB_connect on_connect{};
LIBMOSQ_CB_message on_message{};
struct pending_payload *pending_payloads = nullptr;
void expect_setup(struct mosq_config *config)
{
editline_mock_.reset();
EXPECT_CALL(editline_mock_, rl_bind_key(t::Eq('\t'), t::_));
EXPECT_CALL(editline_mock_, add_history(t::_)).WillRepeatedly(t::Return(0));
EXPECT_CALL(editline_mock_, clear_history()).Times(t::AnyNumber());
config->no_colour = true;
config->port = PORT_UNDEFINED;
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StartsWith("mosquitto_ctrl shell v")));
void expect_setup(struct mosq_config *config)
{
editline_mock_.reset();
EXPECT_CALL(editline_mock_, rl_bind_key(t::Eq('\t'), t::_));
EXPECT_CALL(editline_mock_, add_history(t::_)).WillRepeatedly(t::Return(0));
EXPECT_CALL(editline_mock_, clear_history()).Times(t::AnyNumber());
config->no_colour = true;
config->port = PORT_UNDEFINED;
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StartsWith("mosquitto_ctrl shell v")));
}
void expect_connect(struct mosquitto *mosq, const char *host, int port)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_new(t::Eq(nullptr), t::Eq(true), t::Eq(nullptr)))
.WillOnce(t::Return(mosq));
EXPECT_CALL(libmosquitto_mock_, mosquitto_int_option(t::Eq(mosq), MOSQ_OPT_PROTOCOL_VERSION, 5));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish_v5_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect(t::Eq(mosq), t::StrEq(host), port, 60));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_start(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_connect>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_connect));
EXPECT_CALL(libmosquitto_mock_, mosquitto_message_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_message>()))
.WillOnce(t::SaveArg<1>(&this->on_message));
}
void expect_disconnect(struct mosquitto *mosq)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_disconnect(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_stop(t::Eq(mosq), false));
EXPECT_CALL(libmosquitto_mock_, mosquitto_destroy(t::Eq(mosq)));
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
}
void expect_connect(struct mosquitto *mosq, const char *host, int port)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_new(t::Eq(nullptr), t::Eq(true), t::Eq(nullptr)))
.WillOnce(t::Return(mosq));
EXPECT_CALL(libmosquitto_mock_, mosquitto_int_option(t::Eq(mosq), MOSQ_OPT_PROTOCOL_VERSION, 5));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish_v5_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect(t::Eq(mosq), t::StrEq(host), port, 60));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_start(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_connect>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_connect));
EXPECT_CALL(libmosquitto_mock_, mosquitto_message_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_message>()))
.WillOnce(t::SaveArg<1>(&this->on_message));
}
void expect_request_response(struct mosquitto *mosq, const char *request, const char *respons)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", respons);
void expect_disconnect(struct mosquitto *mosq)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_disconnect(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_stop(t::Eq(mosq), false));
EXPECT_CALL(libmosquitto_mock_, mosquitto_destroy(t::Eq(mosq)));
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
}
void expect_request_response(struct mosquitto *mosq, const char *request, const char *respons)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", respons);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, pp](){
DL_APPEND(this->pending_payloads, pp);
return 0;
}));
}
void expect_request_response_success(struct mosquitto *mosq, const char *request, const char *command)
{
char response[100];
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\"}]}", command);
expect_request_response(mosq, request, response);
}
void expect_request_response_empty(struct mosquitto *mosq, const char *command)
{
char request[100];
char response[100];
snprintf(request, sizeof(request), "{\"commands\":[{\"command\":\"%s\"}]}", command);
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\",\"data\":{}}]}", command);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, &command](){
append_empty_response(command);
return 0;
}));
}
void append_response(const char *response)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", response);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, pp](){
DL_APPEND(this->pending_payloads, pp);
}
return 0;
}));
}
void append_empty_response(const char *command)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload),
void expect_request_response_success(struct mosquitto *mosq, const char *request, const char *command)
{
char response[100];
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\"}]}", command);
expect_request_response(mosq, request, response);
}
void expect_request_response_empty(struct mosquitto *mosq, const char *command)
{
char request[100];
char response[100];
snprintf(request, sizeof(request), "{\"commands\":[{\"command\":\"%s\"}]}", command);
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\",\"data\":{}}]}", command);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, &command](){
append_empty_response(command);
return 0;
}));
}
void append_response(const char *response)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", response);
DL_APPEND(this->pending_payloads, pp);
}
void append_empty_response(const char *command)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload),
"{\"responses\":[{\"command\":\"%s\",\"data\":{}}]}", command);
DL_APPEND(this->pending_payloads, pp);
}
DL_APPEND(this->pending_payloads, pp);
}
void expect_broker(const char *host, int port)
{
char buf[200];
snprintf(buf, sizeof(buf), "connect mqtt://%s:%d", host, port);
char *s_conn = strdup(buf);
EXPECT_CALL(editline_mock_, readline(t::StrEq("> ")))
.WillOnce(t::Return(s_conn));
void expect_broker(const char *host, int port)
{
char buf[200];
snprintf(buf, sizeof(buf), "connect mqtt://%s:%d", host, port);
char *s_conn = strdup(buf);
EXPECT_CALL(editline_mock_, readline(t::StrEq("mqtt://localhost:1883> ")))
.WillOnce(t::Return(strdup("broker")));
EXPECT_CALL(editline_mock_, readline(t::StrEq("> ")))
.WillOnce(t::Return(s_conn));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe(t::_, nullptr, t::StrEq("$CONTROL/broker/v1/response"), 1))
.WillOnce(t::Return(0));
}
EXPECT_CALL(editline_mock_, readline(t::StrEq("mqtt://localhost:1883> ")))
.WillOnce(t::Return(strdup("broker")));
void expect_connect_and_messages(struct mosquitto *mosq)
{
/* This is a hacky way of working around the async mqtt send/receive which we don't directly control.
* Each send starts a wait which times out after two seconds. We use that call to produce the effect we want.
*/
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
.WillRepeatedly(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
struct pending_payload *pp = pending_payloads;
if(pp){
DL_DELETE(pending_payloads, pp);
msg.payload = pp->payload;
msg.payloadlen = (int)strlen((char *)msg.payload);
this->on_message(mosq, nullptr, &msg);
free(pp);
}
data.response_received = true;
return 0;
}));
}
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe(t::_, nullptr, t::StrEq("$CONTROL/broker/v1/response"), 1))
.WillOnce(t::Return(0));
}
void expect_connect_and_messages(struct mosquitto *mosq)
{
/* This is a hacky way of working around the async mqtt send/receive which we don't directly control.
* Each send starts a wait which times out after two seconds. We use that call to produce the effect we want.
*/
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
.WillRepeatedly(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
struct pending_payload *pp = pending_payloads;
if(pp){
DL_DELETE(pending_payloads, pp);
msg.payload = pp->payload;
msg.payloadlen = (int)strlen((char *)msg.payload);
this->on_message(mosq, nullptr, &msg);
free(pp);
}
data.response_received = true;
return 0;
}));
}
};
@@ -406,12 +417,12 @@ TEST_F(CtrlShellOptionsTest, ConnectCertNotFound)
.WillOnce(t::Return(strdup("exit")));
EXPECT_CALL(libmosquitto_mock_, mosquitto_tls_set(
t::_,
t::StrEq("missing cafile"),
t::StrEq("missing capath"),
t::StrEq("missing certfile"),
t::StrEq("missing keyfile"),
nullptr))
t::_,
t::StrEq("missing cafile"),
t::StrEq("missing capath"),
t::StrEq("missing certfile"),
t::StrEq("missing keyfile"),
nullptr))
.WillOnce(t::Return(MOSQ_ERR_INVAL));
const char *outputs[] = {
@@ -455,12 +466,12 @@ TEST_F(CtrlShellOptionsTest, ConnectCertError)
.WillOnce(t::Return(strdup("exit")));
EXPECT_CALL(libmosquitto_mock_, mosquitto_tls_set(
t::_,
t::StrEq("cafile"),
t::StrEq("capath"),
t::StrEq("certfile"),
t::StrEq("keyfile"),
nullptr))
t::_,
t::StrEq("cafile"),
t::StrEq("capath"),
t::StrEq("certfile"),
t::StrEq("keyfile"),
nullptr))
.WillOnce(t::Return(MOSQ_ERR_TLS));
const char *outputs[] = {

View File

@@ -22,72 +22,78 @@ namespace t = testing;
class CtrlShellPreConnectTest : public ::t::Test
{
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<EditLineMock> editline_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
LIBMOSQ_CB_connect on_connect{};
LIBMOSQ_CB_message on_message{};
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<EditLineMock> editline_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
LIBMOSQ_CB_connect on_connect{};
LIBMOSQ_CB_message on_message{};
void expect_setup(struct mosq_config *config)
{
editline_mock_.reset();
EXPECT_CALL(editline_mock_, rl_bind_key(t::Eq('\t'), t::_));
EXPECT_CALL(editline_mock_, add_history(t::_)).WillRepeatedly(t::Return(0));
EXPECT_CALL(editline_mock_, clear_history()).Times(t::AnyNumber());
config->no_colour = true;
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StartsWith("mosquitto_ctrl shell v")));
void expect_setup(struct mosq_config *config)
{
editline_mock_.reset();
EXPECT_CALL(editline_mock_, rl_bind_key(t::Eq('\t'), t::_));
EXPECT_CALL(editline_mock_, add_history(t::_)).WillRepeatedly(t::Return(0));
EXPECT_CALL(editline_mock_, clear_history()).Times(t::AnyNumber());
config->no_colour = true;
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StartsWith("mosquitto_ctrl shell v")));
}
void expect_connect(struct mosquitto *mosq, const char *host, int port)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_new(t::Eq(nullptr), t::Eq(true), t::Eq(nullptr)))
.WillOnce(t::Return(mosq));
EXPECT_CALL(libmosquitto_mock_, mosquitto_int_option(t::Eq(mosq), MOSQ_OPT_PROTOCOL_VERSION, 5));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish_v5_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect(t::Eq(mosq), t::StrEq(host), port, 60));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_start(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_connect>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_connect));
EXPECT_CALL(libmosquitto_mock_, mosquitto_message_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_message>()))
.WillOnce(t::SaveArg<1>(&this->on_message));
}
void expect_disconnect(struct mosquitto *mosq)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_disconnect(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_stop(t::Eq(mosq), false));
EXPECT_CALL(libmosquitto_mock_, mosquitto_destroy(t::Eq(mosq)));
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
}
void expect_connect(struct mosquitto *mosq, const char *host, int port)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_new(t::Eq(nullptr), t::Eq(true), t::Eq(nullptr)))
.WillOnce(t::Return(mosq));
EXPECT_CALL(libmosquitto_mock_, mosquitto_int_option(t::Eq(mosq), MOSQ_OPT_PROTOCOL_VERSION, 5));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish_v5_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect(t::Eq(mosq), t::StrEq(host), port, 60));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_start(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_connect>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_connect));
EXPECT_CALL(libmosquitto_mock_, mosquitto_message_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_message>()))
.WillOnce(t::SaveArg<1>(&this->on_message));
}
void expect_disconnect(struct mosquitto *mosq)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_disconnect(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_stop(t::Eq(mosq), false));
EXPECT_CALL(libmosquitto_mock_, mosquitto_destroy(t::Eq(mosq)));
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
}
void expect_empty_connect_and_messages(struct mosquitto *mosq)
{
/* This is a hacky way of working around the async mqtt send/receive which we don't directly control.
* Each send starts a wait which times out after two seconds. We use that call to produce the effect we want.
*/
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
.WillRepeatedly(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
this->on_message(mosq, nullptr, &msg);
data.response_received = true;
return 0;
}));
}
void expect_empty_connect_and_messages(struct mosquitto *mosq)
{
/* This is a hacky way of working around the async mqtt send/receive which we don't directly control.
* Each send starts a wait which times out after two seconds. We use that call to produce the effect we want.
*/
EXPECT_CALL(pthread_mock_, pthread_cond_timedwait(t::_, t::_, t::_))
.WillOnce(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
this->on_connect(mosq, nullptr, 0);
data.response_received = true;
return 0;
}))
.WillRepeatedly(t::Invoke([this, mosq](pthread_cond_t *, pthread_mutex_t *, const struct timespec *){
mosquitto_message msg{};
this->on_message(mosq, nullptr, &msg);
data.response_received = true;
return 0;
}));
}
};
@@ -106,9 +112,9 @@ TEST_F(CtrlShellPreConnectTest, AuthNoUsername)
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell_fgets(t::_, t::_, t::_))
.WillOnce(t::Invoke([](char *s, int size, FILE *){
snprintf(s, (size_t)size, "password1");
return s;
}));
snprintf(s, (size_t)size, "password1");
return s;
}));
const char *outputs[] = {
"password:",
@@ -132,9 +138,9 @@ TEST_F(CtrlShellPreConnectTest, AuthWithUsername)
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell_fgets(t::_, t::_, t::_))
.WillOnce(t::Invoke([](char *s, int size, FILE *){
snprintf(s, (size_t)size, "password1");
return s;
}));
snprintf(s, (size_t)size, "password1");
return s;
}));
const char *outputs[] = {
"password:",

View File

@@ -21,113 +21,122 @@ Copyright (c) 2022 Cedalo GmbH
namespace t = testing;
struct pending_payload{
struct pending_payload {
struct pending_payload *next, *prev;
char payload[1024];
};
class CtrlShellTest : public ::t::Test
{
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<EditLineMock> editline_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
LIBMOSQ_CB_connect on_connect{};
LIBMOSQ_CB_message on_message{};
struct pending_payload *pending_payloads = nullptr;
public:
::t::StrictMock<CtrlShellMock> ctrl_shell_mock_{};
::t::StrictMock<EditLineMock> editline_mock_{};
::t::StrictMock<LibMosquittoMock> libmosquitto_mock_{};
::t::StrictMock<PThreadMock> pthread_mock_{};
LIBMOSQ_CB_connect on_connect{};
LIBMOSQ_CB_message on_message{};
struct pending_payload *pending_payloads = nullptr;
void expect_setup(struct mosq_config *config)
{
editline_mock_.reset();
EXPECT_CALL(editline_mock_, rl_bind_key(t::Eq('\t'), t::_));
EXPECT_CALL(editline_mock_, add_history(t::_)).WillRepeatedly(t::Return(0));
EXPECT_CALL(editline_mock_, clear_history()).Times(t::AnyNumber());
config->no_colour = true;
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StartsWith("mosquitto_ctrl shell v")));
void expect_setup(struct mosq_config *config)
{
editline_mock_.reset();
EXPECT_CALL(editline_mock_, rl_bind_key(t::Eq('\t'), t::_));
EXPECT_CALL(editline_mock_, add_history(t::_)).WillRepeatedly(t::Return(0));
EXPECT_CALL(editline_mock_, clear_history()).Times(t::AnyNumber());
config->no_colour = true;
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StartsWith("mosquitto_ctrl shell v")));
}
void expect_connect(struct mosquitto *mosq, const char *host, int port)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_new(t::Eq(nullptr), t::Eq(true), t::Eq(nullptr)))
.WillOnce(t::Return(mosq));
EXPECT_CALL(libmosquitto_mock_, mosquitto_int_option(t::Eq(mosq), MOSQ_OPT_PROTOCOL_VERSION, 5));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish_v5_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect(t::Eq(mosq), t::StrEq(host), port, 60));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_start(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_connect>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_connect));
EXPECT_CALL(libmosquitto_mock_, mosquitto_message_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_message>()))
.WillOnce(t::SaveArg<1>(&this->on_message));
}
void expect_disconnect(struct mosquitto *mosq)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_disconnect(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_stop(t::Eq(mosq), false));
EXPECT_CALL(libmosquitto_mock_, mosquitto_destroy(t::Eq(mosq)));
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
}
void expect_connect(struct mosquitto *mosq, const char *host, int port)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_new(t::Eq(nullptr), t::Eq(true), t::Eq(nullptr)))
.WillOnce(t::Return(mosq));
EXPECT_CALL(libmosquitto_mock_, mosquitto_int_option(t::Eq(mosq), MOSQ_OPT_PROTOCOL_VERSION, 5));
EXPECT_CALL(libmosquitto_mock_, mosquitto_subscribe_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish_v5_callback_set(t::Eq(mosq), t::_));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect(t::Eq(mosq), t::StrEq(host), port, 60));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_start(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_connect_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_connect>()))
.WillRepeatedly(t::SaveArg<1>(&this->on_connect));
EXPECT_CALL(libmosquitto_mock_, mosquitto_message_callback_set(t::Eq(mosq), t::A<LIBMOSQ_CB_message>()))
.WillOnce(t::SaveArg<1>(&this->on_message));
}
void expect_request_response(struct mosquitto *mosq, const char *request, const char *respons)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", respons);
void expect_disconnect(struct mosquitto *mosq)
{
EXPECT_CALL(libmosquitto_mock_, mosquitto_disconnect(t::Eq(mosq)));
EXPECT_CALL(libmosquitto_mock_, mosquitto_loop_stop(t::Eq(mosq), false));
EXPECT_CALL(libmosquitto_mock_, mosquitto_destroy(t::Eq(mosq)));
}
void expect_outputs(const char **outputs, size_t count)
{
for(size_t i=0; i<count; i++){
EXPECT_CALL(ctrl_shell_mock_, ctrl_shell__output(t::StrEq(outputs[i]))).Times(t::AtLeast(1));
}
}
void expect_request_response(struct mosquitto *mosq, const char *request, const char *respons)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", respons);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, pp](){
DL_APPEND(this->pending_payloads, pp);
return 0;
}));
}
void expect_request_response_success(struct mosquitto *mosq, const char *request, const char *command)
{
char response[100];
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\"}]}", command);
expect_request_response(mosq, request, response);
}
void expect_request_response_empty(struct mosquitto *mosq, const char *command)
{
char request[100];
char response[100];
snprintf(request, sizeof(request), "{\"commands\":[{\"command\":\"%s\"}]}", command);
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\",\"data\":{}}]}", command);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, &command](){
append_empty_response(command);
return 0;
}));
}
void append_response(const char *response)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", response);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, pp](){
DL_APPEND(this->pending_payloads, pp);
}
return 0;
}));
}
void append_empty_response(const char *command)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload),
void expect_request_response_success(struct mosquitto *mosq, const char *request, const char *command)
{
char response[100];
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\"}]}", command);
expect_request_response(mosq, request, response);
}
void expect_request_response_empty(struct mosquitto *mosq, const char *command)
{
char request[100];
char response[100];
snprintf(request, sizeof(request), "{\"commands\":[{\"command\":\"%s\"}]}", command);
snprintf(response, sizeof(response), "{\"responses\":[{\"command\":\"%s\",\"data\":{}}]}", command);
EXPECT_CALL(libmosquitto_mock_, mosquitto_publish(t::Eq(mosq), nullptr, t::StrEq("$CONTROL/broker/v1"), t::_,
t::StrEq(request), 1, false))
.WillOnce(t::Invoke([this, &command](){
append_empty_response(command);
return 0;
}));
}
void append_response(const char *response)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload), "%s", response);
DL_APPEND(this->pending_payloads, pp);
}
void append_empty_response(const char *command)
{
struct pending_payload *pp = (struct pending_payload *)calloc(1, sizeof(struct pending_payload));
snprintf(pp->payload, sizeof(pp->payload),
"{\"responses\":[{\"command\":\"%s\",\"data\":{}}]}", command);
DL_APPEND(this->pending_payloads, pp);
}
DL_APPEND(this->pending_payloads, pp);
}
};

View File

@@ -5,17 +5,18 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect_v5(int rc, int flags, const mosquitto_property *props);
void on_disconnect_v5(int rc, const mosquitto_property *props);
void on_connect_v5(int rc, int flags, const mosquitto_property *props);
void on_disconnect_v5(int rc, const mosquitto_property *props);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect_v5(int rc, int flags, const mosquitto_property *props)
{
assert(flags == 0);
@@ -29,6 +30,7 @@ void mosquittopp_test::on_connect_v5(int rc, int flags, const mosquitto_property
}
}
void mosquittopp_test::on_disconnect_v5(int rc, const mosquitto_property *props)
{
assert(props == NULL);
@@ -55,7 +57,9 @@ int main(int argc, char *argv[])
mosquitto_property_add_int32(&props, MQTT_PROP_MAXIMUM_PACKET_SIZE, 1000);
rc = mosq->connect_v5("localhost", port, 60, NULL, props);
mosquitto_property_free_all(&props);
if(rc != MOSQ_ERR_SUCCESS) return rc;
if(rc != MOSQ_ERR_SUCCESS){
return rc;
}
while(run == -1){
mosq->loop();

View File

@@ -5,17 +5,18 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect(int rc);
void on_disconnect(int rc);
void on_connect(int rc);
void on_disconnect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -25,6 +26,7 @@ void mosquittopp_test::on_connect(int rc)
}
}
void mosquittopp_test::on_disconnect(int rc)
{
run = rc;

View File

@@ -5,17 +5,18 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect(int rc);
void on_disconnect(int rc);
void on_connect(int rc);
void on_disconnect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -25,6 +26,7 @@ void mosquittopp_test::on_connect(int rc)
}
}
void mosquittopp_test::on_disconnect(int rc)
{
run = rc;
@@ -45,9 +47,9 @@ int main(int argc, char *argv[])
mosq = new mosquittopp_test("01-con-discon-will");
/* Set twice, so it has to clear the old settings */
mosq->will_set("will/topic", strlen("will-payload"), "will-payload", 1, true);
mosq->will_clear();
/* Set twice, so it has to clear the old settings */
mosq->will_set("will/topic", strlen("will-payload"), "will-payload", 1, true);
mosq->will_clear();
mosq->connect("localhost", port, 60);

View File

@@ -5,17 +5,18 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect(int rc);
void on_disconnect(int rc);
void on_connect(int rc);
void on_disconnect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -25,11 +26,13 @@ void mosquittopp_test::on_connect(int rc)
}
}
void mosquittopp_test::on_disconnect(int rc)
{
run = rc;
}
int main(int argc, char *argv[])
{
mosquittopp_test *mosq;

View File

@@ -5,17 +5,18 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect(int rc);
void on_disconnect(int rc);
void on_connect(int rc);
void on_disconnect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -25,6 +26,7 @@ void mosquittopp_test::on_connect(int rc)
}
}
void mosquittopp_test::on_disconnect(int rc)
{
run = rc;
@@ -44,9 +46,9 @@ int main(int argc, char *argv[])
mosq = new mosquittopp_test("01-con-discon-will");
/* Set twice, so it has to clear the old settings */
mosq->will_set("will/topic", strlen("will-payload"), "will-payload", 1, true);
mosq->will_set("will/topic", strlen("will-payload"), "will-payload", 1, true);
/* Set twice, so it has to clear the old settings */
mosq->will_set("will/topic", strlen("will-payload"), "will-payload", 1, true);
mosq->will_set("will/topic", strlen("will-payload"), "will-payload", 1, true);
mosq->connect("localhost", port, 60);

View File

@@ -6,18 +6,19 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect_v5(int rc, int flags, const mosquitto_property *props);
void on_disconnect_v5(int rc, const mosquitto_property *props);
int on_ext_auth(const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props);
void on_connect_v5(int rc, int flags, const mosquitto_property *props);
void on_disconnect_v5(int rc, const mosquitto_property *props);
int on_ext_auth(const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect_v5(int rc, int flags, const mosquitto_property *props)
{
assert(flags == 0);
@@ -31,6 +32,7 @@ void mosquittopp_test::on_connect_v5(int rc, int flags, const mosquitto_property
}
}
void mosquittopp_test::on_disconnect_v5(int rc, const mosquitto_property *props)
{
assert(props == NULL);
@@ -73,7 +75,9 @@ int main(int argc, char *argv[])
mosquitto_property_add_int32(&props, MQTT_PROP_MAXIMUM_PACKET_SIZE, 1000);
rc = mosq->connect_v5("localhost", port, 60, NULL, props);
mosquitto_property_free_all(&props);
if(rc != MOSQ_ERR_SUCCESS) return rc;
if(rc != MOSQ_ERR_SUCCESS){
return rc;
}
while(run == -1){
mosq->loop();

View File

@@ -6,18 +6,19 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect_v5(int rc, int flags, const mosquitto_property *props);
void on_disconnect_v5(int rc, const mosquitto_property *props);
int on_ext_auth(const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props);
void on_connect_v5(int rc, int flags, const mosquitto_property *props);
void on_disconnect_v5(int rc, const mosquitto_property *props);
int on_ext_auth(const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect_v5(int rc, int flags, const mosquitto_property *props)
{
assert(flags == 0);
@@ -31,6 +32,7 @@ void mosquittopp_test::on_connect_v5(int rc, int flags, const mosquitto_property
}
}
void mosquittopp_test::on_disconnect_v5(int rc, const mosquitto_property *props)
{
assert(props == NULL);
@@ -67,7 +69,9 @@ int main(int argc, char *argv[])
mosquitto_property_add_int32(&props, MQTT_PROP_MAXIMUM_PACKET_SIZE, 1000);
rc = mosq->connect_v5("localhost", port, 60, NULL, props);
mosquitto_property_free_all(&props);
if(rc != MOSQ_ERR_SUCCESS) return rc;
if(rc != MOSQ_ERR_SUCCESS){
return rc;
}
while(run == -1){
mosq->loop();

View File

@@ -4,16 +4,17 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect(int rc);
void on_connect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -21,6 +22,7 @@ void mosquittopp_test::on_connect(int rc)
}
}
int main(int argc, char *argv[])
{
mosquittopp_test *mosq;
@@ -39,7 +41,9 @@ int main(int argc, char *argv[])
while(run == -1){
rc = mosq->loop();
if(rc) break;
if(rc){
break;
}
}
delete mosq;

View File

@@ -5,17 +5,18 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id, bool clean_session);
public:
mosquittopp_test(const char *id, bool clean_session);
void on_connect(int rc);
void on_disconnect(int rc);
void on_connect(int rc);
void on_disconnect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id, bool clean_session) : mosqpp::mosquittopp(id, clean_session)
{
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -25,6 +26,7 @@ void mosquittopp_test::on_connect(int rc)
}
}
void mosquittopp_test::on_disconnect(int rc)
{
run = rc;

View File

@@ -4,23 +4,25 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_pre_connect();
void on_connect(int rc);
void on_disconnect(int rc);
void on_pre_connect();
void on_connect(int rc);
void on_disconnect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_pre_connect()
{
username_pw_set("uname", ";'[08gn=#");
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -30,6 +32,7 @@ void mosquittopp_test::on_connect(int rc)
}
}
void mosquittopp_test::on_disconnect(int rc)
{
run = rc;

View File

@@ -4,16 +4,17 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect(int rc);
void on_connect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -21,6 +22,7 @@ void mosquittopp_test::on_connect(int rc)
}
}
int main(int argc, char *argv[])
{
mosquittopp_test *mosq;
@@ -40,7 +42,9 @@ int main(int argc, char *argv[])
while(run == -1){
rc = mosq->loop();
if(rc) break;
if(rc){
break;
}
}
delete mosq;

View File

@@ -5,17 +5,18 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect(int rc);
void on_disconnect(int rc);
void on_connect(int rc);
void on_disconnect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -25,6 +26,7 @@ void mosquittopp_test::on_connect(int rc)
}
}
void mosquittopp_test::on_disconnect(int rc)
{
run = rc;

View File

@@ -5,17 +5,18 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect(int rc);
void on_disconnect(int rc);
void on_connect(int rc);
void on_disconnect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -25,11 +26,13 @@ void mosquittopp_test::on_connect(int rc)
}
}
void mosquittopp_test::on_disconnect(int rc)
{
run = rc;
}
int main(int argc, char *argv[])
{
mosquittopp_test *mosq;

View File

@@ -5,17 +5,18 @@ static int run = -1;
class mosquittopp_test : public mosqpp::mosquittopp
{
public:
mosquittopp_test(const char *id);
public:
mosquittopp_test(const char *id);
void on_connect(int rc);
void on_disconnect(int rc);
void on_connect(int rc);
void on_disconnect(int rc);
};
mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id)
{
}
void mosquittopp_test::on_connect(int rc)
{
if(rc){
@@ -25,11 +26,13 @@ void mosquittopp_test::on_connect(int rc)
}
}
void mosquittopp_test::on_disconnect(int rc)
{
run = rc;
}
int main(int argc, char *argv[])
{
mosquittopp_test *mosq;

View File

@@ -6,6 +6,7 @@
#define QOS 2
static int mydata = 1;
int cb(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *msg)
{
assert(mosq);
@@ -15,6 +16,7 @@ int cb(struct mosquitto *mosq, void *userdata, const struct mosquitto_message *m
return 1;
}
int main(int argc, char *argv[])
{
int port;

View File

@@ -3,6 +3,7 @@
#define QOS 2
int main(int argc, char *argv[])
{
int port;

Some files were not shown because too many files have changed in this diff Show More