diff --git a/.gitignore b/.gitignore index f323d58..6a587c2 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ loop2.exe 3p/lib/* 3p/src/* 3p/include/* -build \ No newline at end of file +build +*.gcov \ No newline at end of file diff --git a/makefile b/makefile index 197ee4c..14b056f 100644 --- a/makefile +++ b/makefile @@ -59,7 +59,7 @@ endif .PHONY: all clean -all: build/microtcp.h build/microtcp.c build/echo_tcp build/echo_http +all: build/microtcp.h build/microtcp.c build/echo_tcp build/echo_http build/test 3p/lib/libtuntap.a: 3p/libtuntap/build/lib/libtuntap.a cp 3p/libtuntap/build/lib/libtuntap.a $(LIBDIR) @@ -139,7 +139,15 @@ build/microtcp.c: 3p/include/tinycthread.h 3p/src/tinycthread.c $(wildcard src/* build/echo_http: examples/microhttp/main.c $(LIBDIR)/libtuntap.a 3p/include/tuntap.h 3p/include/tuntap-export.h build/microtcp.h build/microtcp.c gcc examples/microhttp/main.c examples/microhttp/xhttp.c build/microtcp.c -o $@ $(CFLAGS) $(LFLAGS) -DDEBUG=1 -DARP_DEBUG -DMICROTCP_DEBUG -DIP_DEBUG -DICMP_DEBUG -DTCP_DEBUG -DMICROTCP_USING_MUX +build/test: tests/test.c tests/test_tcp_timer.c src/tcp_timer.c src/tcp_timer.h + gcc -fprofile-arcs -ftest-coverage tests/test.c tests/test_tcp_timer.c src/tcp_timer.c -o $@ -Wall -Wextra -DTCP_MAX_TIMERS=4 + +report: build/test + ./build/test + gcov -b build/test-tcp_timer.c + clean: + rm build/*.gcda build/*.gcno rm -fr build rm -fr 3p/libtuntap/build rm -f 3p/lib/* 3p/include/* \ No newline at end of file diff --git a/src/microtcp.c b/src/microtcp.c index 3e2b615..996abd2 100644 --- a/src/microtcp.c +++ b/src/microtcp.c @@ -826,8 +826,8 @@ microtcp_socket_t *microtcp_open(microtcp_t *mtcp, uint16_t port, errcode2 = MICROTCP_ERRCODE_SOCKETLIMIT; goto unlock_and_exit; // Socket limit reached } - - tcp_listener_t *listener = tcp_listener_create(&mtcp->tcp_state, port, socket, false, ready_to_accept); + + tcp_listener_t *listener = tcp_listener_create(&mtcp->tcp_state, port, false, socket, ready_to_accept); if (listener == NULL) { // FIXME: This error code should be more specific, // but the TCP module isn't stable yet diff --git a/src/tcp.c b/src/tcp.c index d7e47d9..3bcb58c 100644 --- a/src/tcp.c +++ b/src/tcp.c @@ -563,8 +563,10 @@ void tcp_process_segment(tcp_state_t *state, ip_address_t sender, move_from_non_established_list_to_non_accepted_queue(connection); - if (listener->callback_ready_to_accept) + if (listener->callback_ready_to_accept) { + assert(listener->callback_data); listener->callback_ready_to_accept(listener->callback_data); + } break; case TCP_STATE_ESTAB: @@ -698,9 +700,11 @@ tcp_listener_create(tcp_state_t *state, uint16_t port, bool reuse, return NULL; } - if (listener) + if (listener) { listener->closed = false; - else { + listener->callback_data = callback_data; + listener->callback_ready_to_accept = callback_ready_to_accept; + } else { // Pop a listener connection structure from the free list if (state->free_listener_list == NULL) { diff --git a/src/tcp_timer.c b/src/tcp_timer.c index 16a8ea9..5aa70c4 100644 --- a/src/tcp_timer.c +++ b/src/tcp_timer.c @@ -1,13 +1,20 @@ +#include + #ifndef MICROTCP_AMALGAMATION #include "tcp_timer.h" #endif void tcp_timerset_init(tcp_timerset_t *set) { - for (size_t i = 0; i < TCP_MAX_TIMEOUTS-1; i++) - set->pool[i].next = set->pool + i+1; - set->pool[TCP_MAX_TIMEOUTS-1].next = NULL; - set->free_list = set->pool; + static_assert(TCP_MAX_TIMERS >= 0); + if (TCP_MAX_TIMERS == 0) + set->free_list = NULL; + else { + for (size_t i = 0; i < TCP_MAX_TIMERS-1; i++) + set->pool[i].next = set->pool + i+1; + set->pool[TCP_MAX_TIMERS-1].next = NULL; + set->free_list = set->pool; + } set->used_list = NULL; } diff --git a/src/tcp_timer.h b/src/tcp_timer.h index 43db4b6..7841acb 100644 --- a/src/tcp_timer.h +++ b/src/tcp_timer.h @@ -1,6 +1,8 @@ #include +#ifndef TCP_MAX_TIMERS #define TCP_MAX_TIMERS 1024 +#endif typedef struct tcp_timerset_t tcp_timerset_t; typedef struct tcp_timer_t tcp_timer_t; diff --git a/tests/test.c b/tests/test.c new file mode 100644 index 0000000..1fe3f98 --- /dev/null +++ b/tests/test.c @@ -0,0 +1,8 @@ + +void test_tcp_timer(void); + +int main(void) +{ + test_tcp_timer(); + return 0; +} \ No newline at end of file diff --git a/tests/test_tcp_timer.c b/tests/test_tcp_timer.c new file mode 100644 index 0000000..8908967 --- /dev/null +++ b/tests/test_tcp_timer.c @@ -0,0 +1,166 @@ +#include +#include "../src/tcp_timer.h" + +static void set_int_variable_to_1(void *data) +{ + int *n = data; + *n = 1; +} + +static void test_timer(void) +{ + static_assert(TCP_MAX_TIMERS > 0); + + tcp_timerset_t set; + tcp_timerset_init(&set); + + int resolved = 0; + tcp_timer_t *t1 = tcp_timer_create(&set, 5, set_int_variable_to_1, &resolved); + + assert(t1); + assert(resolved == 0); + + tcp_timerset_step(&set, 1); + assert(resolved == 0); + + tcp_timerset_step(&set, 4); + assert(resolved == 1); + + tcp_timerset_free(&set); +} + +static void test_disabled_timer(void) +{ + static_assert(TCP_MAX_TIMERS > 0); + + tcp_timerset_t set; + tcp_timerset_init(&set); + + int resolved = 0; + tcp_timer_t *t1 = tcp_timer_create(&set, 5, set_int_variable_to_1, &resolved); + + assert(t1); + assert(resolved == 0); + + tcp_timer_disable(t1); + + tcp_timerset_step(&set, 1); + assert(resolved == 0); + + tcp_timerset_step(&set, 4); + assert(resolved == 0); + + tcp_timerset_free(&set); +} + +static void test_disabled_timer_2(void) +{ + static_assert(TCP_MAX_TIMERS > 0); + + tcp_timerset_t set; + tcp_timerset_init(&set); + + int resolved = 0; + tcp_timer_t *t1 = tcp_timer_create(&set, 5, set_int_variable_to_1, &resolved); + + assert(t1); + assert(resolved == 0); + + tcp_timerset_step(&set, 1); + assert(resolved == 0); + + tcp_timer_disable(t1); + + tcp_timerset_step(&set, 4); + assert(resolved == 0); + + tcp_timerset_free(&set); +} + +static void test_disabled_timer_3(void) +{ + static_assert(TCP_MAX_TIMERS > 0); + + tcp_timerset_t set; + tcp_timerset_init(&set); + + int resolved_1 = 0; + int resolved_2 = 0; + tcp_timer_t *t1 = tcp_timer_create(&set, 5, set_int_variable_to_1, &resolved_1); + tcp_timer_t *t2 = tcp_timer_create(&set, 5, set_int_variable_to_1, &resolved_2); + + assert(t1); + assert(t2); + assert(resolved_1 == 0); + assert(resolved_2 == 0); + + tcp_timerset_step(&set, 1); + assert(resolved_1 == 0); + assert(resolved_2 == 0); + + tcp_timer_disable(t1); + + tcp_timerset_step(&set, 4); + assert(resolved_1 == 0); + assert(resolved_2 == 1); + + tcp_timerset_free(&set); +} + +static void test_disabled_timer_4(void) +{ + static_assert(TCP_MAX_TIMERS > 0); + + tcp_timerset_t set; + tcp_timerset_init(&set); + + int resolved_1 = 0; + int resolved_2 = 0; + tcp_timer_t *t1 = tcp_timer_create(&set, 5, set_int_variable_to_1, &resolved_1); + tcp_timer_t *t2 = tcp_timer_create(&set, 5, set_int_variable_to_1, &resolved_2); + + assert(t1); + assert(t2); + assert(resolved_1 == 0); + assert(resolved_2 == 0); + + tcp_timerset_step(&set, 1); + assert(resolved_1 == 0); + assert(resolved_2 == 0); + + tcp_timer_disable(t2); + + tcp_timerset_step(&set, 4); + assert(resolved_1 == 1); + assert(resolved_2 == 0); + + tcp_timerset_free(&set); +} + +static void test_out_of_timers(void) +{ + static_assert(TCP_MAX_TIMERS > 0); + + tcp_timerset_t set; + tcp_timerset_init(&set); + + int temp; + for (int i = 0; i < TCP_MAX_TIMERS; i++) { + tcp_timer_t *t = tcp_timer_create(&set, 5, set_int_variable_to_1, &temp); + assert(t != NULL); + } + tcp_timer_t *t = tcp_timer_create(&set, 5, set_int_variable_to_1, &temp); + assert(t == NULL); + + tcp_timerset_free(&set); +} + +void test_tcp_timer(void) +{ + test_timer(); + test_disabled_timer(); + test_disabled_timer_2(); + test_disabled_timer_3(); + test_disabled_timer_4(); + test_out_of_timers(); +} \ No newline at end of file