diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 000000000..6ed2df93f --- /dev/null +++ b/test/.gitignore @@ -0,0 +1,5 @@ +halinterface/ +rdk-wifi-hal/ + +.cache/ +compile_commands.json diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 000000000..fed4f1a99 --- /dev/null +++ b/test/Makefile @@ -0,0 +1,133 @@ +OW = $(PWD)/../source +HALIF = $(PWD)/halinterface +HAL = $(PWD)/rdk-wifi-hal + +INCLUDE = \ + -I $(OW)/db \ + -I $(OW)/stubs \ + -I $(OW)/../include \ + -I $(OW)/core/services/ \ + -I $(OW)/core \ + -I $(OW)/stats \ + -I $(OW)/utils \ + -I $(OW)/platform/common/ \ + -I $(OW)/platform/linux/ \ + -I $(OW)/platform/linux/he_bus/inc \ + -I $(OW)/ccsp/ \ + -I $(OW)/apps/ \ + -I $(OW)/apps/analytics/ \ + -I $(OW)/apps/levl/ \ + -I $(OW)/apps/csi/ \ + -I $(OW)/apps/sm \ + -I $(OW)/apps/motion/ \ + -I $(OW)/apps/whix/ \ + -I $(OW)/apps/harvester/ \ + -I $(OW)/apps/ocs/ \ + -I $(OW)/dml/linux/ \ + -I $(HALIF)/include \ + -I $(HAL)/src/ + +CFLAGS = \ + -Og -g3 -ggdb -pipe \ + -Wno-implicit-function-declaration \ + -DSTATIC=static + +CC = gcc + +ifneq ($(COV),) +CFLAGS += --coverage +endif + +all:: + @true + +clean:: + @true + +distclean:: clean + @true + +FORCE: + +LIBOW_SO = \ + $(OW)/core/wifi_ctrl.c \ + $(OW)/core/wifi_events.c \ + $(OW)/utils/collection.c + +libow.so: $(LIBOW_SO) + $(CC) $(INCLUDE) $(CFLAGS) \ + -shared -fPIC \ + -o $@ \ + $(LIBOW_SO) + +clean:: + rm -f libow.so + +libstubs.so: stubs.c + $(CC) $(CFLAGS) -shared -fPIC -o $@ stubs.c + +clean:: + rm -f libstubs.so + +libs:: libow.so libstubs.so + +ctrl-queue: ctrl-queue.c libow.so libstubs.so + $(CC) $(INCLUDE) $(CFLAGS) -o ctrl-queue ctrl-queue.c -L. -low -lstubs + +clean:: + rm -f ctrl-queue + +stubs.c: libow.so + $(CC) $(INCLUDE) $(CFLAGS) -o ignore ctrl-queue.c -L. -low 2>&1 | \ + grep 'undefined reference' | \ + cut -d\` -f2 | cut -d\' -f1 | \ + sort | uniq | \ + while read n ; do \ + echo "void $${n} (void) { ldk(); }" ; \ + done > $@ + sed -i '1i extern void ldk (void);' $@ + +clean:: + rm -f stubs.c + +all:: ctrl-queue + +r: + LD_LIBRARY_PATH=$$PWD ./ctrl-queue + +bt: + LD_LIBRARY_PATH=$$PWD gdb -q \ + -ex 'set confirm off' \ + -ex 'r' \ + -ex 'bt' \ + -ex 'q' \ + ./ctrl-queue + +gdb: + LD_LIBRARY_PATH=$$PWD gdb -q \ + -ex 'set confirm off' \ + -ex 'b main' \ + -ex 'r' \ + ./ctrl-queue + + +coverage.info: FORCE + lcov \ + --quiet \ + --rc branch_coverage=1 \ + --no-external \ + --capture \ + --directory . \ + --output-file coverage.info + +lcov: coverage.info + genhtml \ + --legend \ + --rc branch_coverage=1 \ + $< \ + -o tmp + +clean:: + rm -f coverage.info + [ -d tmp ] && rm -r tmp || true + rm -f *.gcda *.gcno diff --git a/test/ctrl-queue.c b/test/ctrl-queue.c new file mode 100644 index 000000000..220ec0f9a --- /dev/null +++ b/test/ctrl-queue.c @@ -0,0 +1,146 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define called() \ + do { \ + struct timeval tv; \ + gettimeofday(&tv, NULL); \ + printf("%ld.%03ld:%s:%d: Called\n", tv.tv_sec, tv.tv_usec / 1000, __func__, __LINE__); \ + } while (0) + +static wifi_ctrl_t *ldk_wifi_ctrl_g; +extern void ctrl_queue_loop(wifi_ctrl_t *); + +extern void ldk (void) { + assert(0); +} + +static unsigned char scheduler_executed = false; + +int scheduler_execute(struct scheduler *sched, struct timespec t_start, unsigned int timeout_ms) +{ + usleep(timeout_ms * 1000); + scheduler_executed = true; + return 0; +} + +wifi_ctrl_t *get_wifictrl_obj(void) { + return ldk_wifi_ctrl_g; +} + +wifi_mgr_t *get_wifimgr_obj(void) { + return NULL; +} + +int get_number_of_radios(wifi_platform_property_t *wifi_prop) { + return 1; +} + +int apps_mgr_event(wifi_apps_mgr_t *apps_mgr, wifi_event_t *event) { + // printf("%s:%d: Called\n", __func__, __LINE__); + return -1; +} + +void wifi_util_print(wifi_log_level_t level, wifi_dbg_type_t module, char *format, ...) +{ + va_list ap; + + va_start(ap, format); + vprintf(format, ap); + va_end(ap); +} + +struct ts { + uint64_t ts; +}; + +void handle_hal_indication(wifi_ctrl_t *ctrl, void *data, unsigned int len, + wifi_event_subtype_t subtype) { + struct ts *ts = data; + struct timespec tv; + clock_gettime(CLOCK_MONOTONIC, &tv); + const uint64_t delay = (tv.tv_sec * 1000 + tv.tv_nsec /1000 /1000) - ts->ts; + printf("%s:%d: Processing delay: %ld\n", __func__, __LINE__, delay); + assert(delay < 200); + + // simulate short event + usleep(10 * 1000); +} + +void handle_webconfig_event(wifi_ctrl_t *ctrl, const char *raw, unsigned int len, + wifi_event_subtype_t subtype) { + // simulate long event + usleep(200 * 1000); +} + +void * ctrl_queue_wrapper(void *arg) { + wifi_ctrl_t *ctrl = arg; + ctrl_queue_loop(ctrl); + return NULL; +} + +static void push_event(const wifi_event_type_t event) { + struct ts ts; + struct timespec tv; + memset(&ts, 0x0, sizeof(ts)); + clock_gettime(CLOCK_MONOTONIC, &tv); + ts.ts = tv.tv_sec * 1000 + tv.tv_nsec /1000 /1000; + push_event_to_ctrl_queue(&ts, sizeof(ts), event, 0, NULL); +} + +int main(int argc, char *argv[]) { + wifi_ctrl_t ctrl; + memset(&ctrl, 0x0, sizeof(ctrl)); + + /* Init ctrl-queue */ + clock_gettime(CLOCK_MONOTONIC, &ctrl.last_signalled_time); + clock_gettime(CLOCK_MONOTONIC, &ctrl.last_polled_time); + + pthread_condattr_t cond_attr; + pthread_condattr_init(&cond_attr); + pthread_condattr_setclock(&cond_attr, CLOCK_MONOTONIC); + pthread_cond_init(&ctrl.cond, &cond_attr); + pthread_condattr_destroy(&cond_attr); + + pthread_mutexattr_init(&ctrl.attr); + pthread_mutexattr_settype(&ctrl.attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(&ctrl.queue_lock, &ctrl.attr); + + ctrl.queue = queue_create(); + ctrl.poll_period = QUEUE_WIFI_CTRL_TASK_TIMEOUT; + ldk_wifi_ctrl_g = &ctrl; + + /* Event sequence */ + push_event(wifi_event_type_hal_ind); + push_event(wifi_event_type_hal_ind); + push_event(wifi_event_type_hal_ind); + push_event(wifi_event_type_webconfig); + push_event(wifi_event_type_hal_ind); + push_event(wifi_event_type_hal_ind); + + /* Spin thread */ + pthread_t tid; + pthread_create(&tid, NULL, ctrl_queue_wrapper, &ctrl); + while (0x42) { + pthread_mutex_lock(&ctrl.queue_lock); + int len = queue_count(ctrl.queue); + if ((len == 0) && (scheduler_executed == true)) { + ctrl.exit_ctrl = true; + pthread_cond_signal(&ctrl.cond); + pthread_mutex_unlock(&ctrl.queue_lock); + break; + } + pthread_mutex_unlock(&ctrl.queue_lock); + usleep(100 * 1000); + } + pthread_join(tid, NULL); + return 0; +}