From 81942fe05711a95dcc4445805a2ba69d2f3cc0ab Mon Sep 17 00:00:00 2001 From: Oskar Viljasaar <oskar.viljasaar@iopsys.eu> Date: Thu, 17 Sep 2020 14:00:32 +0200 Subject: [PATCH] initial test framework --- Makefile | 28 +++++ src/Makefile | 15 ++- test/cmocka/Makefile | 28 +++++ test/cmocka/unit_test_qos.c | 197 ++++++++++++++++++++++++++++++++++++ 4 files changed, 264 insertions(+), 4 deletions(-) create mode 100644 test/cmocka/Makefile create mode 100644 test/cmocka/unit_test_qos.c diff --git a/Makefile b/Makefile index c342593..b0f6618 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,7 @@ # Makefile for qosmngr +include common.mk + +QOSMNGR_LIB=libqosmngr.so subdirs ?= src @@ -6,3 +9,28 @@ subdirs ?= src all clean: @for i in $(subdirs) ; do [ -d $$i ] && $(MAKE) -C $$i $@; done + +qosmngr: + $(MAKE) all -C src + +${QOSMNGR_LIB}: + $(MAKE) CFLAGS+=-fPIC lib -C src + +test: ${QOSMNGR_LIB} + +unit-test: coverage + $(MAKE) -C test/cmocka unit-test QOSMNGR_LIB_DIR=$(PWD) + +coverage: CFLAGS += -g -O0 -fprofile-arcs -ftest-coverage -fPIC +coverage: LDFLAGS += --coverage +coverage: test qosmngr + $(foreach testprog, $(CODECOVERAGE_SRC), $(GCOV) $(testprog);) + +clean: + rm -f *.o libqosmngr.so $(PROG) + rm -f *.xml *.html + find -name '*.gcda' -exec rm {} -fv \; + find -name '*.gcno' -exec rm {} -fv \; + find -name '*.gcov' -exec rm {} -fv \; + make -C test/cmocka clean + make -C src clean \ No newline at end of file diff --git a/src/Makefile b/src/Makefile index c923b31..9b2ba4c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,8 @@ include ../common.mk PROG = $(PROJECT_TOPLEVEL)/qosmngr +SHARED_LIB = $(PROJECT_TOPLEVEL)/libqosmngr.so + OBJS = main.o qosmngr.o PROG_CFLAGS = $(CFLAGS) -I$(INCLUDE_DIR) -Wall -fstrict-aliasing @@ -10,9 +12,14 @@ PROG_LIBS = -luci -lubus -lubox -ljson-c -lblobmsg_json -lnl-genl-3 -lnl-3 -lgco %.o: %.c $(CC) $(PROG_CFLAGS) $(FPIC) -c -o $@ $< -.PHONY: version +.PHONY: clean + +all: $(PROG) + +lib: $(SHARED_LIB) -all: version $(PROG) +$(SHARED_LIB): $(OBJS) $(INCLUDE_DIR)/version.h + $(CC) $(PROG_LDFLAGS) -shared -o $@ $^ $(PROG_LIBS) version: $(INCLUDE_DIR)/version.h @@ -25,8 +32,8 @@ $(INCLUDE_DIR)/version.h: $(PROJECT_TOPLEVEL)/VERSION echo "const char *qosmngr_xtra_version = \"$$xver$$dirty\";" >> $@; \ ) -$(PROG): $(OBJS) +$(PROG): $(INCLUDE_DIR)/version.h $(OBJS) $(CC) $(PROG_LDFLAGS) -o $@ $^ $(PROG_LIBS) clean: - rm -f *.o libqosmngr.so $(PROG) $(INCLUDE_DIR)/version.h + rm -f *.o $(SHARED_LIB) $(PROG) $(INCLUDE_DIR)/version.h diff --git a/test/cmocka/Makefile b/test/cmocka/Makefile new file mode 100644 index 0000000..6529742 --- /dev/null +++ b/test/cmocka/Makefile @@ -0,0 +1,28 @@ +include ../../common.mk + +CC = gcc +QOSMNGR_LIB_DIR ?= $(shell dirname $(PWD)) +QOSMNGR_LIB = -lqosmngr -L$(QOSMNGR_LIB_DIR) +CMOCKA_LIB = -l cmocka +LIBS = $(QOSMNGR_LIB) $(CMOCKA_LIB) -lqos -pthread -luci -lubus -lubox -ljson-c -lblobmsg_json -lnl-genl-3 -lnl-3 -ljson-validator -ljson-schema-validator -ljson-editor +CFLAGS = -g -Wall -I$(INCLUDE_DIR) +LDFLAGS = $(LIBS) -Wl,-rpath=$(QOSMNGR_LIB_DIR) -I$(QOSMNGR_LIB_DIR) +UNIT_TESTS = unit_test_qos + +VALGRIND = valgrind --leak-check=full --show-reachable=no \ + --show-leak-kinds=all --errors-for-leak-kinds=all \ + --error-exitcode=1 --track-origins=yes + +%.o: %.c + $(CC) $(CFLAGS) $(FPIC) -c -o $@ $< + +unit_test_qos: unit_test_qos.o + $(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) + +unit-test: $(UNIT_TESTS) + $(foreach testprog, $(UNIT_TESTS), sudo $(VALGRIND) ./$(testprog);) + +.PHONY: clean + +clean: + rm $(UNIT_TESTS) *.o -fv diff --git a/test/cmocka/unit_test_qos.c b/test/cmocka/unit_test_qos.c new file mode 100644 index 0000000..617665a --- /dev/null +++ b/test/cmocka/unit_test_qos.c @@ -0,0 +1,197 @@ +#include <stdarg.h> +#include <stddef.h> +#include <setjmp.h> +#include <cmocka.h> + +#include <libubus.h> +#include <libubox/blobmsg_json.h> +#include <libubox/blobmsg.h> + +#include <json-validator.h> +#include <json-c/json.h> +#include <json-editor.h> + +#include <json-c/json_tokener.h> +#include <easy/easy.h> +#include <qos.h> + +#include <qosmngr.h> + +struct test_ctx { + struct blob_buf bb; + struct ubus_object qos; + FILE *fp; +}; + +/* declare qosmngr functions */ +int wl_radio_status(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + + +int wl_radio_get_param(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int sta_disconnect(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int nbr_transition(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int nbr_request(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int nbr_add(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wps_start(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wps_stop(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int vsie_add(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *ureq, const char *method, + struct blob_attr *msg); + +int vsie_del(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *ureq, const char *method, + struct blob_attr *msg); + +int nbr_del(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int sta_monitor(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wl_scan(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wl_autochannel(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int wps_set_ap_pin(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg); + +int qosmngr_event_main(const char *evmap_file); + +/* overload ubus_send_reply to prevent segfault*/ +int ubus_send_reply(struct ubus_context *ctx, struct ubus_request_data *req, + struct blob_attr *msg) +{ + return 0; +} + + +/* TODO: how to fix events without fopen and fclose every poll? */ +struct json_object *poll_test_log(FILE *fp, const char *prefix) +{ + char line[256] = {0}; + char msg[256] = {0}; + struct json_object *obj = NULL; + + //if (!fp) { + fp = fopen("/tmp/test.log", "r"); + if (!fp) + return NULL; + //} + + while (fgets(line, 256, fp)) { + char *ptr, *s; + char appended[32]; + + snprintf(appended, sizeof(appended), "%s:", prefix); + + ptr = strstr(line, appended); + if (!ptr) + continue; + + s = multi_tok(ptr, appended); + s = multi_tok(NULL, appended); + strncpy(msg, s, sizeof(msg)); + } + + if (strlen(msg)) + obj = json_tokener_parse(msg); + + fclose(fp); + return obj; +} + +static int group_setup(void **state) +{ + struct test_ctx *ctx = calloc(1, sizeof(struct test_ctx)); + + if (!ctx) + return -1; + + remove("/tmp/test.log"); + + ctx->qos.name = "qos"; + + memset(&ctx->bb, 0, sizeof(struct blob_buf)); + + *state = ctx; + return 0; +} + +static void test_api_get_stats(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + struct blob_buf *bb = &ctx->bb; + struct ubus_object *obj = &ctx->qos; + struct json_object *jobj, *tmp; + + blobmsg_add_string(bb, "ifname", "test"); + + tmp = json_object_get_by_string(jobj, "iface"); + assert_string_equal(json_object_get_string(tmp), "test"); + + json_object_put(jobj); + + return; +} + +static int group_teardown(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + + blob_buf_free(&ctx->bb); + free(ctx); + remove("/tmp/test.log"); + + /* TODO: fix event poll file */ + //if (ctx->fp) + //fclose(ctx->fp); + return 0; +} + +static int setup(void **state) +{ + struct test_ctx *ctx = (struct test_ctx *) *state; + + blob_buf_init(&ctx->bb, 0); + + return 0; +} + +int main(void) +{ + const struct CMUnitTest tests[] = { + cmocka_unit_test_setup(test_api_get_stats, setup), + }; + + return cmocka_run_group_tests(tests, group_setup, group_teardown); +} -- GitLab