diff --git a/.gitignore b/.gitignore index e20dc3cb..963228e6 100644 --- a/.gitignore +++ b/.gitignore @@ -73,6 +73,7 @@ test/unit/coverage.info test/unit/mosq_test test/unit/persist_read_test test/unit/persist_write_test +test/unit/subs_test test/unit/out/ www/cache/ diff --git a/test/unit/Makefile b/test/unit/Makefile index 85ee1d03..7c2e804e 100644 --- a/test/unit/Makefile +++ b/test/unit/Makefile @@ -69,6 +69,16 @@ PERSIST_WRITE_OBJS = \ utf8_mosq.o \ util_mosq.o +SUBS_TEST_OBJS = \ + subs_test.o \ + subs_stubs.o + +SUBS_OBJS = \ + database.o \ + memory_mosq.o \ + subs.o \ + topic_tok.o + all : test check : test @@ -85,6 +95,9 @@ persist_read_test : ${PERSIST_READ_TEST_OBJS} ${PERSIST_READ_OBJS} persist_write_test : ${PERSIST_WRITE_TEST_OBJS} ${PERSIST_WRITE_OBJS} $(CROSS_COMPILE)$(CC) $(LDFLAGS) -o $@ $^ $(LDADD) +subs_test : ${SUBS_TEST_OBJS} ${SUBS_OBJS} + $(CROSS_COMPILE)$(CC) $(LDFLAGS) -o $@ $^ $(LDADD) + bridge_topic.o : ../../src/bridge_topic.c $(CROSS_COMPILE)$(CC) $(CPPFLAGS) $(CFLAGS) -DWITH_BROKER -DWITH_BRIDGE -c -o $@ $^ @@ -134,13 +147,16 @@ util_topic.o : ../../lib/util_topic.c utf8_mosq.o : ../../lib/utf8_mosq.c $(CROSS_COMPILE)$(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $^ -test-lib : mosq_test +build : mosq_test bridge_topic_test persist_read_test persist_write_test subs_test + +test-lib : build ./mosq_test -test-broker : bridge_topic_test persist_read_test persist_write_test +test-broker : build ./bridge_topic_test ./persist_read_test ./persist_write_test + ./subs_test test : test-broker test-lib diff --git a/test/unit/subs_stubs.c b/test/unit/subs_stubs.c new file mode 100644 index 00000000..94a933be --- /dev/null +++ b/test/unit/subs_stubs.c @@ -0,0 +1,156 @@ +#include + +#define WITH_BROKER + +#include +#include +#include +#include +#include +#include + +#if 0 +extern uint64_t last_retained; +extern char *last_sub; +extern int last_qos; + +struct mosquitto *context__init(struct mosquitto_db *db, mosq_sock_t sock) +{ + return mosquitto__calloc(1, sizeof(struct mosquitto)); +} + + +int db__message_insert(struct mosquitto_db *db, struct mosquitto *context, uint16_t mid, enum mosquitto_msg_direction dir, int qos, bool retain, struct mosquitto_msg_store *stored, mosquitto_property *properties) +{ + return MOSQ_ERR_SUCCESS; +} + +void db__msg_store_ref_dec(struct mosquitto_db *db, struct mosquitto_msg_store **store) +{ +} + +void db__msg_store_ref_inc(struct mosquitto_msg_store *store) +{ + store->ref_count++; +} +#endif + +int log__printf(struct mosquitto *mosq, int priority, const char *fmt, ...) +{ + return 0; +} + +time_t mosquitto_time(void) +{ + return 123; +} + +#if 0 +int net__socket_close(struct mosquitto_db *db, struct mosquitto *mosq) +{ + return MOSQ_ERR_SUCCESS; +} + +int send__pingreq(struct mosquitto *mosq) +{ + return MOSQ_ERR_SUCCESS; +} + +int mosquitto_acl_check(struct mosquitto_db *db, struct mosquitto *context, const char *topic, long payloadlen, void* payload, int qos, bool retain, int access) +{ + return MOSQ_ERR_SUCCESS; +} + +int acl__find_acls(struct mosquitto_db *db, struct mosquitto *context) +{ + return MOSQ_ERR_SUCCESS; +} +#endif + + +int send__publish(struct mosquitto *mosq, uint16_t mid, const char *topic, uint32_t payloadlen, const void *payload, int qos, bool retain, bool dup, const mosquitto_property *cmsg_props, const mosquitto_property *store_props, uint32_t expiry_interval) +{ + return MOSQ_ERR_SUCCESS; +} + +int send__pubcomp(struct mosquitto *mosq, uint16_t mid) +{ + return MOSQ_ERR_SUCCESS; +} + +int send__pubrec(struct mosquitto *mosq, uint16_t mid, uint8_t reason_code) +{ + return MOSQ_ERR_SUCCESS; +} + +int send__pubrel(struct mosquitto *mosq, uint16_t mid) +{ + return MOSQ_ERR_SUCCESS; +} + +int mosquitto_acl_check(struct mosquitto_db *db, struct mosquitto *context, const char *topic, long payloadlen, void* payload, int qos, bool retain, int access) +{ + return MOSQ_ERR_SUCCESS; +} + +uint16_t mosquitto__mid_generate(struct mosquitto *mosq) +{ + static uint16_t mid = 1; + + return ++mid; +} + +int mosquitto_property_add_varint(mosquitto_property **proplist, int identifier, uint32_t value) +{ + return MOSQ_ERR_SUCCESS; +} + +int persist__backup(struct mosquitto_db *db, bool shutdown) +{ + return MOSQ_ERR_SUCCESS; +} + +int persist__restore(struct mosquitto_db *db) +{ + return MOSQ_ERR_SUCCESS; +} + +void mosquitto_property_free_all(mosquitto_property **properties) +{ +} + +int retain__init(struct mosquitto_db *db) +{ + return MOSQ_ERR_SUCCESS; +} + +void retain__clean(struct mosquitto_db *db, struct mosquitto__retainhier **retainhier) +{ +} + +int retain__queue(struct mosquitto_db *db, struct mosquitto *context, const char *sub, int sub_qos, uint32_t subscription_identifier) +{ + return MOSQ_ERR_SUCCESS; +} + +int retain__store(struct mosquitto_db *db, const char *topic, struct mosquitto_msg_store *stored, struct sub__token *tokens) +{ + return MOSQ_ERR_SUCCESS; +} + + +void util__decrement_receive_quota(struct mosquitto *mosq) +{ + if(mosq->msgs_in.inflight_quota > 0){ + mosq->msgs_in.inflight_quota--; + } +} + +void util__decrement_send_quota(struct mosquitto *mosq) +{ + if(mosq->msgs_out.inflight_quota > 0){ + mosq->msgs_out.inflight_quota--; + } +} + + diff --git a/test/unit/subs_test.c b/test/unit/subs_test.c new file mode 100644 index 00000000..3ae22229 --- /dev/null +++ b/test/unit/subs_test.c @@ -0,0 +1,116 @@ +/* Tests for subscription adding/removing + * + * FIXME - these need to be aggressive about finding failures, at the moment + * they are just confirming that good behaviour works. */ + +#include +#include + +#define WITH_BROKER +#define WITH_PERSISTENCE + +#include "mosquitto_broker_internal.h" + +static void hier_quick_check(struct mosquitto__subhier **sub, struct mosquitto *context, const char *topic) +{ + if(sub != NULL){ + CU_ASSERT_EQUAL((*sub)->topic_len, strlen(topic)); + CU_ASSERT_PTR_NOT_NULL((*sub)->topic); + if((*sub)->topic){ + CU_ASSERT_STRING_EQUAL((*sub)->topic, topic); + } + if(context){ + CU_ASSERT_PTR_NOT_NULL((*sub)->subs); + if((*sub)->subs){ + CU_ASSERT_PTR_EQUAL((*sub)->subs->context, context); + CU_ASSERT_PTR_NULL((*sub)->subs->next); + } + }else{ + CU_ASSERT_PTR_NULL((*sub)->subs); + } + (*sub) = (*sub)->children; + } +} + + +static void TEST_sub_add_single(void) +{ + struct mosquitto_db db; + struct mosquitto__config config; + struct mosquitto__listener listener; + struct mosquitto context; + struct mosquitto__subhier *sub; + int rc; + + memset(&db, 0, sizeof(struct mosquitto_db)); + memset(&config, 0, sizeof(struct mosquitto__config)); + memset(&listener, 0, sizeof(struct mosquitto__listener)); + memset(&context, 0, sizeof(struct mosquitto)); + + context.id = "client"; + + db.config = &config; + listener.port = 1883; + config.listeners = &listener; + config.listener_count = 1; + + db__open(&config, &db); + + rc = sub__add(&db, &context, "a/b/c/d/e", 0, 0, 0, &db.subs); + CU_ASSERT_EQUAL(rc, MOSQ_ERR_SUCCESS); + CU_ASSERT_PTR_NOT_NULL(db.subs); + if(db.subs){ + sub = db.subs; + + hier_quick_check(&sub, NULL, ""); + hier_quick_check(&sub, NULL, ""); + hier_quick_check(&sub, NULL, "a"); + hier_quick_check(&sub, NULL, "b"); + hier_quick_check(&sub, NULL, "c"); + hier_quick_check(&sub, NULL, "d"); + hier_quick_check(&sub, &context, "e"); + CU_ASSERT_PTR_NULL(sub); + } + mosquitto__free(context.subs); + db__close(&db); +} + + +/* ======================================================================== + * TEST SUITE SETUP + * ======================================================================== */ + + +int main(int argc, char *argv[]) +{ + CU_pSuite test_suite = NULL; + unsigned int fails; + + if(CU_initialize_registry() != CUE_SUCCESS){ + printf("Error initializing CUnit registry.\n"); + return 1; + } + + test_suite = CU_add_suite("Subs", NULL, NULL); + if(!test_suite){ + printf("Error adding CUnit Subs test suite.\n"); + CU_cleanup_registry(); + return 1; + } + + if(0 + || !CU_add_test(test_suite, "Sub add single", TEST_sub_add_single) + ){ + + printf("Error adding Subs CUnit tests.\n"); + CU_cleanup_registry(); + return 1; + } + + CU_basic_set_mode(CU_BRM_VERBOSE); + CU_basic_run_tests(); + fails = CU_get_number_of_failures(); + CU_cleanup_registry(); + + return (int)fails; +}