diff --git a/test/apps/tcp_socket_reuse/test_sockets.c b/test/apps/tcp_socket_reuse/test_sockets.c index 6523d9cb..cddc0209 100644 --- a/test/apps/tcp_socket_reuse/test_sockets.c +++ b/test/apps/tcp_socket_reuse/test_sockets.c @@ -27,20 +27,6 @@ test_sockets_get_used_count(void) return used; } -#if 0 -static int -wait_for_pcbs_to_cleanup(void) -{ - struct tcp_pcb *pcb = tcp_active_pcbs; - while (pcb != NULL) { - if (pcb->state == TIME_WAIT || pcb->state == LAST_ACK) { - return -1; - } - pcb = pcb->next; - } - return 0; -} -#endif /* Setups/teardown functions */ static void sockets_setup(void) @@ -75,12 +61,12 @@ START_TEST(test_tcp_active_socket_limit) } END_TEST -START_TEST(test_tcp_new_max_num) +static void create_tcp_pcbs_and_kill_state(u8_t recycle_test, enum tcp_state state) { struct tcp_pcb* pcb[MEMP_NUM_TCP_PCB + 1]; int i; + err_t err; mem_size_t prev_used, one_pcb_size; - LWIP_UNUSED_ARG(_i); prev_used = lwip_stats.mem.used; pcb[0] = tcp_new(); @@ -92,18 +78,76 @@ START_TEST(test_tcp_new_max_num) pcb[i] = tcp_new(); fail_unless(pcb[i] != NULL); fail_unless(one_pcb_size == lwip_stats.mem.used - prev_used); + /* bind the pcb, so lwip expects they're active */ + err = tcp_bind(pcb[i], &test_local_ip, 3333+i); + fail_unless(err == ERR_OK); } - /* Trying to remove the oldest pcb in TIME_WAIT,LAST_ACK,CLOSING state when pcb full */ pcb[MEMP_NUM_TCP_PCB] = tcp_new(); fail_unless(pcb[MEMP_NUM_TCP_PCB] == NULL); - tcp_set_state(pcb[0], TIME_WAIT, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT); - pcb[MEMP_NUM_TCP_PCB] = tcp_new(); - fail_unless(pcb[MEMP_NUM_TCP_PCB] != NULL); - for (i = 1; i <= MEMP_NUM_TCP_PCB; i++) - { - tcp_abort(pcb[i]); + if (recycle_test) { + /* Trying to remove the oldest pcb in TIME_WAIT,LAST_ACK,CLOSING state when pcb full */ + if (state == TIME_WAIT) { + tcp_set_state(pcb[0], TIME_WAIT, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT); + } else { + tcp_set_state(pcb[0], ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT); + pcb[0]->state = state; + } + fail_unless(pcb[0]->state == state); + + pcb[MEMP_NUM_TCP_PCB] = tcp_new(); + fail_unless(pcb[MEMP_NUM_TCP_PCB] != NULL); + pcb[0] = tcp_new(); + fail_unless(pcb[0] == NULL); } + + for (i = 0; i <= MEMP_NUM_TCP_PCB; i++) + { + if (pcb[i]) { + tcp_abort(pcb[i]); + } + } +} + +START_TEST(test_tcp_new_max_num) +{ + LWIP_UNUSED_ARG(_i); + create_tcp_pcbs_and_kill_state(0, /* N/A */ CLOSED); +} +END_TEST + +START_TEST(test_tcp_pcb_recycle_TIME_WAIT) +{ + LWIP_UNUSED_ARG(_i); + create_tcp_pcbs_and_kill_state(1, TIME_WAIT); +} +END_TEST + +START_TEST(test_tcp_pcb_recycle_LAST_ACK) +{ + LWIP_UNUSED_ARG(_i); + create_tcp_pcbs_and_kill_state(1, LAST_ACK); +} +END_TEST + +START_TEST(test_tcp_pcb_recycle_CLOSING) +{ + LWIP_UNUSED_ARG(_i); + create_tcp_pcbs_and_kill_state(1, CLOSING); +} +END_TEST + +START_TEST(test_tcp_pcb_recycle_FIN_WAIT_1) +{ + LWIP_UNUSED_ARG(_i); + create_tcp_pcbs_and_kill_state(1, FIN_WAIT_1); +} +END_TEST + +START_TEST(test_tcp_pcb_recycle_FIN_WAIT_2) +{ + LWIP_UNUSED_ARG(_i); + create_tcp_pcbs_and_kill_state(1, FIN_WAIT_2); } END_TEST @@ -114,6 +158,11 @@ sockets_suite(void) testfunc tests[] = { TESTFUNC(test_tcp_active_socket_limit), TESTFUNC(test_tcp_new_max_num), + TESTFUNC(test_tcp_pcb_recycle_TIME_WAIT), + TESTFUNC(test_tcp_pcb_recycle_LAST_ACK), + TESTFUNC(test_tcp_pcb_recycle_CLOSING), + TESTFUNC(test_tcp_pcb_recycle_FIN_WAIT_1), + TESTFUNC(test_tcp_pcb_recycle_FIN_WAIT_2), }; return create_suite("TCP_ACTIVE_SOCKETS", tests, sizeof(tests)/sizeof(testfunc), sockets_setup, sockets_teardown); } diff --git a/test/ci/test_apps.sh b/test/ci/test_apps.sh index abd18e20..a97f8b44 100755 --- a/test/ci/test_apps.sh +++ b/test/ci/test_apps.sh @@ -14,10 +14,11 @@ for app in $TEST_APPS; do cmake -DCI_BUILD=1 -DTEST_APP=${app} -B ${app} -G Ninja . cmake --build ${app}/ timeout 10 ./${app}/lwip_test_apps - [ -f check2junit.py ] && + [ -f ${LWIP_DIR}/check2junit.py ] && python ${LWIP_DIR}/check2junit.py lwip_test_apps.xml > ${LWIP_DIR}/${app}.xml done -# Run the lingering test multiple times + +# Run the stress test(s) multiple times for stress_cfg in $STRESS_TEST_APPS; do for run in {1..1000}; do ( timeout 10 ./$stress_cfg/lwip_test_apps ) || exit 1 ; done; done diff --git a/test/unit/tcp/test_tcp_state.c b/test/unit/tcp/test_tcp_state.c index afd21fce..583b28bd 100644 --- a/test/unit/tcp/test_tcp_state.c +++ b/test/unit/tcp/test_tcp_state.c @@ -198,6 +198,56 @@ START_TEST(test_tcp_new_max_num_remove_TIME_WAIT) } END_TEST +#if ESP_LWIP +/* + * ESP_LWIP: + * If pcb lists are full when allocating a new pcb, + * try to remove one pcb in TIME_WAIT,LAST_ACK, FIN_WAIT_1,CLOSING,FIN_WAIT_1 state. + */ +START_TEST(test_tcp_new_max_num_remove_FIN_WAIT_1) + { + struct tcp_pcb* pcb; + struct tcp_pcb* pcb_list[MEMP_NUM_TCP_PCB + 1]; + err_t err; + int i; + uint16_t base_bind_port = 2222; + LWIP_UNUSED_ARG(_i); + + /* create a pcb in FIN_WAIT_1 state */ + pcb = tcp_new(); + EXPECT_RET(pcb != NULL); + tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT); + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + err = tcp_close(pcb); + EXPECT_RET(err == ERR_OK); + EXPECT_RET(pcb->state == FIN_WAIT_1); + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1); + + /* Create max number pcbs */ + for(i = 0;i < MEMP_NUM_TCP_PCB-1; i++) { + pcb_list[i] = tcp_new(); + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == (i + 2)); + /* must bind pcb, otherwise, it will not be calculated in tcp_active_pcbs */ + err = tcp_bind(pcb_list[i], &test_netif.ip_addr, base_bind_port+i); + EXPECT(err == ERR_OK); + } + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == MEMP_NUM_TCP_PCB); + /* Create one more pcb */ + pcb_list[MEMP_NUM_TCP_PCB-1] = tcp_new(); + + /* the FIN_WAIT_1 pcb was removed */ + EXPECT_RET(pcb_list[MEMP_NUM_TCP_PCB-1] != NULL); + EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == MEMP_NUM_TCP_PCB); + + for (i = 0; i <= MEMP_NUM_TCP_PCB-1; i++) + { + tcp_abort(pcb_list[i]); + } + EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0); + + } +END_TEST +#endif /* ESP_LWIP */ /* Call tcp_connect to check active open */ START_TEST(test_tcp_connect_active_open) @@ -649,6 +699,9 @@ tcp_state_suite(void) testfunc tests[] = { TESTFUNC(test_tcp_new_max_num), TESTFUNC(test_tcp_new_max_num_remove_TIME_WAIT), +#if ESP_LWIP + TESTFUNC(test_tcp_new_max_num_remove_FIN_WAIT_1), +#endif TESTFUNC(test_tcp_connect_active_open), TESTFUNC(test_tcp_active_close), TESTFUNC(test_tcp_imultaneous_close),