From b51a943a48cce0cafa38211179fbb10b8448b39e Mon Sep 17 00:00:00 2001 From: henri Date: Wed, 8 May 2013 11:52:28 +0000 Subject: [PATCH] Added a minimal regression test suite for nsock. --- CHANGELOG | 2 + nsock/tests/Makefile | 35 +++++++++++ nsock/tests/basic.c | 52 +++++++++++++++ nsock/tests/run_tests.sh | 35 +++++++++++ nsock/tests/test-common.h | 84 +++++++++++++++++++++++++ nsock/tests/tests_main.c | 61 ++++++++++++++++++ nsock/tests/timer.c | 129 ++++++++++++++++++++++++++++++++++++++ 7 files changed, 398 insertions(+) create mode 100644 nsock/tests/Makefile create mode 100644 nsock/tests/basic.c create mode 100755 nsock/tests/run_tests.sh create mode 100644 nsock/tests/test-common.h create mode 100644 nsock/tests/tests_main.c create mode 100644 nsock/tests/timer.c diff --git a/CHANGELOG b/CHANGELOG index c733db4d7..691546a7d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ # Nmap Changelog ($Id$); -*-text-*- +o [Nsock] Added a minimal regression test suite for nsock. [Henri Doreau] + o [NSE] Updated redis-brute.nse and redis-info.nse to work against the latest versions of redis server. [Henri Doreau] diff --git a/nsock/tests/Makefile b/nsock/tests/Makefile new file mode 100644 index 000000000..38498a1d6 --- /dev/null +++ b/nsock/tests/Makefile @@ -0,0 +1,35 @@ +# +# nsock regression test suite +# Same license as nmap -- see http://nmap.org/book/man-legal.html +## + +NBASEDIR=../../nbase +NSOCKLIB=../src/libnsock.a +NBASELIB=$(NBASEDIR)/libnbase.a + +CC = gcc +CFLAGS = -Wall -O0 -ggdb -I../include/ -I$(NBASEDIR) +LDFLAGS = -lssl -lpcap -lcrypto + +SRC = tests_main.c \ + basic.c \ + timer.c + +OBJ = $(SRC:.c=.o) + +EXE = tests_main + +all: $(SRC) $(EXE) + +$(EXE): $(OBJ) + $(CC) $(LDFLAGS) $(OBJ) -o $@ $(NSOCKLIB) $(NBASELIB) + +.c.o: + $(CC) -c $(CFLAGS) $< -o $@ + +clean: + $(RM) $(OBJ) $(EXE) + +rebuild: clean $(EXE) + +.PHONY: clean rebuild diff --git a/nsock/tests/basic.c b/nsock/tests/basic.c new file mode 100644 index 000000000..f14db3c4d --- /dev/null +++ b/nsock/tests/basic.c @@ -0,0 +1,52 @@ +/* + * Nsock regression test suite + * Same license as nmap -- see http://nmap.org/book/man-legal.html + */ + +#include "test-common.h" + + +struct basic_test_data { + nsock_pool nsp; +}; + +static int basic_setup(void **tdata) { + struct basic_test_data *btd; + + btd = calloc(1, sizeof(struct basic_test_data)); + if (btd == NULL) + return -ENOMEM; + + btd->nsp = nsp_new(NULL); + + *tdata = btd; + return 0; +} + +static int basic_teardown(void *tdata) { + struct basic_test_data *btd = (struct basic_test_data *)tdata; + + if (tdata) { + nsp_delete(btd->nsp); + free(tdata); + } + return 0; +} + +static int basic_udata(void *tdata) { + struct basic_test_data *btd = (struct basic_test_data *)tdata; + + AssertEqual(nsp_getud(btd->nsp), NULL); + nsp_setud(btd->nsp, btd); + AssertEqual(nsp_getud(btd->nsp), btd); + return 0; +} + +const struct test_case TestPoolUserData = { + .t_name = "nsock pool user data", + .t_setup = basic_setup, + .t_run = basic_udata, + .t_teardown = basic_teardown +}; + + diff --git a/nsock/tests/run_tests.sh b/nsock/tests/run_tests.sh new file mode 100755 index 000000000..7e5688f34 --- /dev/null +++ b/nsock/tests/run_tests.sh @@ -0,0 +1,35 @@ +#!/bin/sh + +# nsock regression test suite +# Same license as nmap -- see http://nmap.org/book/man-legal.html + +EXEC_MAIN=./tests_main + +if [ -n "$1" ] +then + case "$1" in + "gdb") + TRACER="gdb --args" + ;; + + "trace") + TRACER="strace" + ;; + + "leak") + TRACER="valgrind --leak-check=yes" + ;; + + "-h") + echo "Usage: `basename $0` [gdb|trace|leak]" + exit 0 + ;; + + *) + echo "Unknown mode $1" + exit 1 + ;; + esac +fi + +$TRACER $EXEC_MAIN diff --git a/nsock/tests/test-common.h b/nsock/tests/test-common.h new file mode 100644 index 000000000..4ffd571ad --- /dev/null +++ b/nsock/tests/test-common.h @@ -0,0 +1,84 @@ +/* + * Nsock regression test suite + * Same license as nmap -- see http://nmap.org/book/man-legal.html + */ + + +#ifndef __TEST_COMMON_H +#define __TEST_COMMON_H + +#include +#include +#include +#include +#include +#include +#include + + +#define __ASSERT_BASE(stmt) do { \ + if (!(stmt)) { \ + fprintf(stderr, "(%s:%d) Assertion failed: " #stmt "\n", \ + __FILE__, __LINE__); \ + return -EINVAL; \ + } \ + } while (0) + + +#define AssertNonNull(a) __ASSERT_BASE((a) != NULL); +#define AssertEqual(a, b) __ASSERT_BASE((a) == (b)); +#define AssertStrEqual(a, b) __ASSERT_BASE(strcmp((a), (b)) == 0); + + +struct test_case { + const char *t_name; + int (*t_setup)(void **tdata); + int (*t_run)(void *tdata); + int (*t_teardown)(void *tdata); +}; + + +static inline const char *get_test_name(const struct test_case *test) { + return test->t_name; +} + +static inline int test_setup(const struct test_case *test, void **tdata) { + int rc; + + assert(test); + + if (test->t_setup) + rc = test->t_setup(tdata); + else + rc = 0; + + return rc; +} + +static inline int test_run(const struct test_case *test, void *tdata) { + int rc; + + assert(test); + + if (test->t_run) + rc = test->t_run(tdata); + else + rc = 0; + + return rc; +} + +static inline int test_teardown(const struct test_case *test, void *tdata) { + int rc; + + assert(test); + + if (test->t_teardown) + rc = test->t_teardown(tdata); + else + rc = 0; + + return rc; +} + +#endif /* ^__TEST_COMMON_H */ diff --git a/nsock/tests/tests_main.c b/nsock/tests/tests_main.c new file mode 100644 index 000000000..a84e408d6 --- /dev/null +++ b/nsock/tests/tests_main.c @@ -0,0 +1,61 @@ +/* + * Nsock regression test suite + * Same license as nmap -- see http://nmap.org/book/man-legal.html + */ + + +#include "test-common.h" + + +#define RESET "\033[0m" +#define BOLDRED "\033[1m\033[31m" +#define BOLDGREEN "\033[1m\033[32m" + +#define TEST_FAILED "[" BOLDRED "FAILED" RESET "]" +#define TEST_OK "[" BOLDGREEN "OK" RESET "]" + + +extern const struct test_case TestPoolUserData; +extern const struct test_case TestTimer; + + +static const struct test_case *TestCases[] = { + /* ---- basic.c */ + &TestPoolUserData, + /* ---- timer.c */ + &TestTimer, + NULL +}; + +static int test_case_run(const struct test_case *test) { + int rc; + void *tdata = NULL; + + rc = test_setup(test, &tdata); + if (rc) + return rc; + + rc = test_run(test, tdata); + if (rc) + return rc; + + return test_teardown(test, tdata); +} + +int main(int ac, char **av) { + int rc, i; + + for (i = 0; TestCases[i] != NULL; i++) { + const struct test_case *current = TestCases[i]; + const char *name = get_test_name(current); + + rc = test_case_run(current); + if (rc) { + printf(TEST_FAILED " %s (%s)\n", name, strerror(-rc)); + break; + } + printf(TEST_OK " %s\n", name); + } + return rc; +} + diff --git a/nsock/tests/timer.c b/nsock/tests/timer.c new file mode 100644 index 000000000..fac8d4455 --- /dev/null +++ b/nsock/tests/timer.c @@ -0,0 +1,129 @@ +/* + * Nsock regression test suite + * Same license as nmap -- see http://nmap.org/book/man-legal.html + */ + +#include "test-common.h" +#include + +#define TIMERS_BUFFLEN 1024 + + +struct timer_test_data { + nsock_pool nsp; + nsock_event_id timer_list[TIMERS_BUFFLEN]; + size_t timer_count; + int stop; /* set to non-zero to stop the test */ +}; + + +static void timer_handler(nsock_pool nsp, nsock_event nse, void *tdata); + + +static void add_timer(struct timer_test_data *ttd, int timeout) { + nsock_event_id id; + + id = nsock_timer_create(ttd->nsp, timer_handler, timeout, ttd); + ttd->timer_list[ttd->timer_count++] = id; +} + +static void timer_handler(nsock_pool nsp, nsock_event nse, void *tdata) { + struct timer_test_data *ttd = (struct timer_test_data *)tdata; + int rnd, rnd2; + + if (nse_status(nse) != NSE_STATUS_SUCCESS) { + ttd->stop = -nsp_geterrorcode(nsp); + return; + } + + if (ttd->timer_count > TIMERS_BUFFLEN - 3) + return; + + rnd = rand() % ttd->timer_count; + rnd2 = rand() % 3; + + switch (rnd2) { + case 0: + /* Do nothing */ + /* Actually I think I'll create two timers :) */ + add_timer(ttd, rand() % 3000); + add_timer(ttd, rand() % 3000); + break; + + case 1: + /* Try to kill another id (which may or may not be active */ + nsock_event_cancel(nsp, ttd->timer_list[rnd], rand() % 2); + break; + + case 2: + /* Create a new timer */ + add_timer(ttd, rand() % 3000); + break; + + default: + assert(0); + } +} + +static int timer_setup(void **tdata) { + struct timer_test_data *ttd; + + srand(time(NULL)); + + ttd = calloc(1, sizeof(struct timer_test_data)); + if (ttd == NULL) + return -ENOMEM; + + ttd->nsp = nsp_new(NULL); + AssertNonNull(ttd->nsp); + + *tdata = ttd; + return 0; +} + +static int timer_teardown(void *tdata) { + struct timer_test_data *ttd = (struct timer_test_data *)tdata; + + if (tdata) { + nsp_delete(ttd->nsp); + free(tdata); + } + return 0; +} + +static int timer_totalmess(void *tdata) { + struct timer_test_data *ttd = (struct timer_test_data *)tdata; + enum nsock_loopstatus loopret; + int num_loops = 0; + + add_timer(ttd, 1800); + add_timer(ttd, 800); + add_timer(ttd, 1300); + add_timer(ttd, 0); + add_timer(ttd, 100); + + /* Now lets get this party started right! */ + while (num_loops++ < 5 && !ttd->stop) { + loopret = nsock_loop(ttd->nsp, 1500); + switch (loopret) { + case NSOCK_LOOP_TIMEOUT: + /* nothing to do */ + break; + + case NSOCK_LOOP_NOEVENTS: + return 0; + + default: + return -(nsp_geterrorcode(ttd->nsp)); + } + } + return ttd->stop; +} + +const struct test_case TestTimer = { + .t_name = "test timer operations", + .t_setup = timer_setup, + .t_run = timer_totalmess, + .t_teardown = timer_teardown +}; +