修改了Web后台的部分界面,增加了HAmqtt中的总电量传感器,后台新增mqtt上报频率设置

This commit is contained in:
OOP
2025-03-03 21:49:41 +08:00
parent e1e00b60ce
commit 9f9d4c7a56
4468 changed files with 1473046 additions and 10728 deletions

View File

@@ -0,0 +1,73 @@
#include "test_mem.h"
#include "lwip/mem.h"
#include "lwip/stats.h"
#if !LWIP_STATS || !MEM_STATS
#error "This tests needs MEM-statistics enabled"
#endif
#if LWIP_DNS
/*#error "This test needs DNS turned off (as it mallocs on init)"*/
#endif
/* Setups/teardown functions */
static void
mem_setup(void)
{
}
static void
mem_teardown(void)
{
}
/* Test functions */
/** Call mem_malloc, mem_free and mem_trim and check stats */
START_TEST(test_mem_one)
{
#define SIZE1 16
#define SIZE1_2 12
#define SIZE2 16
void *p1, *p2;
mem_size_t s1, s2;
LWIP_UNUSED_ARG(_i);
#if LWIP_DNS
fail("This test needs DNS turned off (as it mallocs on init)");
#endif
fail_unless(lwip_stats.mem.used == 0);
p1 = mem_malloc(SIZE1);
fail_unless(p1 != NULL);
fail_unless(lwip_stats.mem.used >= SIZE1);
s1 = lwip_stats.mem.used;
p2 = mem_malloc(SIZE2);
fail_unless(p2 != NULL);
fail_unless(lwip_stats.mem.used >= SIZE2 + s1);
s2 = lwip_stats.mem.used;
mem_trim(p1, SIZE1_2);
mem_free(p2);
fail_unless(lwip_stats.mem.used <= s2 - SIZE2);
mem_free(p1);
fail_unless(lwip_stats.mem.used == 0);
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
mem_suite(void)
{
TFun tests[] = {
test_mem_one,
};
return create_suite("MEM", tests, sizeof(tests)/sizeof(TFun), mem_setup, mem_teardown);
}

View File

@@ -0,0 +1,8 @@
#ifndef __TEST_MEM_H__
#define __TEST_MEM_H__
#include "../lwip_check.h"
Suite *mem_suite(void);
#endif

View File

@@ -0,0 +1,261 @@
#include "test_etharp.h"
#include "lwip/udp.h"
#include "netif/etharp.h"
#include "lwip/stats.h"
#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS || !ETHARP_STATS
#error "This tests needs UDP-, MEMP- and ETHARP-statistics enabled"
#endif
#if !ETHARP_SUPPORT_STATIC_ENTRIES
#error "This test needs ETHARP_SUPPORT_STATIC_ENTRIES enabled"
#endif
static struct netif test_netif;
static ip_addr_t test_ipaddr, test_netmask, test_gw;
struct eth_addr test_ethaddr = {1,1,1,1,1,1};
struct eth_addr test_ethaddr2 = {1,1,1,1,1,2};
struct eth_addr test_ethaddr3 = {1,1,1,1,1,3};
struct eth_addr test_ethaddr4 = {1,1,1,1,1,4};
static int linkoutput_ctr;
/* Helper functions */
static void
etharp_remove_all(void)
{
int i;
/* call etharp_tmr often enough to have all entries cleaned */
for(i = 0; i < 0xff; i++) {
etharp_tmr();
}
}
static err_t
default_netif_linkoutput(struct netif *netif, struct pbuf *p)
{
fail_unless(netif == &test_netif);
fail_unless(p != NULL);
linkoutput_ctr++;
return ERR_OK;
}
static err_t
default_netif_init(struct netif *netif)
{
fail_unless(netif != NULL);
netif->linkoutput = default_netif_linkoutput;
netif->output = etharp_output;
netif->mtu = 1500;
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
netif->hwaddr_len = ETHARP_HWADDR_LEN;
return ERR_OK;
}
static void
default_netif_add(void)
{
IP4_ADDR(&test_gw, 192,168,0,1);
IP4_ADDR(&test_ipaddr, 192,168,0,1);
IP4_ADDR(&test_netmask, 255,255,0,0);
fail_unless(netif_default == NULL);
netif_set_default(netif_add(&test_netif, &test_ipaddr, &test_netmask,
&test_gw, NULL, default_netif_init, NULL));
netif_set_up(&test_netif);
}
static void
default_netif_remove(void)
{
fail_unless(netif_default == &test_netif);
netif_remove(&test_netif);
}
static void
create_arp_response(ip_addr_t *adr)
{
int k;
struct eth_hdr *ethhdr;
struct etharp_hdr *etharphdr;
struct pbuf *p = pbuf_alloc(PBUF_RAW, sizeof(struct eth_hdr) + sizeof(struct etharp_hdr), PBUF_RAM);
if(p == NULL) {
FAIL_RET();
}
ethhdr = (struct eth_hdr*)p->payload;
etharphdr = (struct etharp_hdr*)(ethhdr + 1);
ethhdr->dest = test_ethaddr;
ethhdr->src = test_ethaddr2;
ethhdr->type = htons(ETHTYPE_ARP);
etharphdr->hwtype = htons(/*HWTYPE_ETHERNET*/ 1);
etharphdr->proto = htons(ETHTYPE_IP);
etharphdr->_hwlen_protolen = htons((ETHARP_HWADDR_LEN << 8) | sizeof(ip_addr_t));
etharphdr->opcode = htons(ARP_REPLY);
SMEMCPY(&etharphdr->sipaddr, adr, sizeof(ip_addr_t));
SMEMCPY(&etharphdr->dipaddr, &test_ipaddr, sizeof(ip_addr_t));
k = 6;
while(k > 0) {
k--;
/* Write the ARP MAC-Addresses */
etharphdr->shwaddr.addr[k] = test_ethaddr2.addr[k];
etharphdr->dhwaddr.addr[k] = test_ethaddr.addr[k];
/* Write the Ethernet MAC-Addresses */
ethhdr->dest.addr[k] = test_ethaddr.addr[k];
ethhdr->src.addr[k] = test_ethaddr2.addr[k];
}
ethernet_input(p, &test_netif);
}
/* Setups/teardown functions */
static void
etharp_setup(void)
{
etharp_remove_all();
default_netif_add();
}
static void
etharp_teardown(void)
{
etharp_remove_all();
default_netif_remove();
}
/* Test functions */
START_TEST(test_etharp_table)
{
#if ETHARP_SUPPORT_STATIC_ENTRIES
err_t err;
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
s8_t idx;
ip_addr_t *unused_ipaddr;
struct eth_addr *unused_ethaddr;
struct udp_pcb* pcb;
LWIP_UNUSED_ARG(_i);
if (netif_default != &test_netif) {
fail("This test needs a default netif");
}
linkoutput_ctr = 0;
pcb = udp_new();
fail_unless(pcb != NULL);
if (pcb != NULL) {
ip_addr_t adrs[ARP_TABLE_SIZE + 2];
int i;
for(i = 0; i < ARP_TABLE_SIZE + 2; i++) {
IP4_ADDR(&adrs[i], 192,168,0,i+2);
}
/* fill ARP-table with dynamic entries */
for(i = 0; i < ARP_TABLE_SIZE; i++) {
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM);
fail_unless(p != NULL);
if (p != NULL) {
err_t err = udp_sendto(pcb, p, &adrs[i], 123);
fail_unless(err == ERR_OK);
/* etharp request sent? */
fail_unless(linkoutput_ctr == (2*i) + 1);
pbuf_free(p);
/* create an ARP response */
create_arp_response(&adrs[i]);
/* queued UDP packet sent? */
fail_unless(linkoutput_ctr == (2*i) + 2);
idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr);
fail_unless(idx == i);
etharp_tmr();
}
}
linkoutput_ctr = 0;
#if ETHARP_SUPPORT_STATIC_ENTRIES
/* create one static entry */
err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE], &test_ethaddr3);
fail_unless(err == ERR_OK);
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr);
fail_unless(idx == 0);
fail_unless(linkoutput_ctr == 0);
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
linkoutput_ctr = 0;
/* fill ARP-table with dynamic entries */
for(i = 0; i < ARP_TABLE_SIZE; i++) {
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 10, PBUF_RAM);
fail_unless(p != NULL);
if (p != NULL) {
err_t err = udp_sendto(pcb, p, &adrs[i], 123);
fail_unless(err == ERR_OK);
/* etharp request sent? */
fail_unless(linkoutput_ctr == (2*i) + 1);
pbuf_free(p);
/* create an ARP response */
create_arp_response(&adrs[i]);
/* queued UDP packet sent? */
fail_unless(linkoutput_ctr == (2*i) + 2);
idx = etharp_find_addr(NULL, &adrs[i], &unused_ethaddr, &unused_ipaddr);
if (i < ARP_TABLE_SIZE - 1) {
fail_unless(idx == i+1);
} else {
/* the last entry must not overwrite the static entry! */
fail_unless(idx == 1);
}
etharp_tmr();
}
}
#if ETHARP_SUPPORT_STATIC_ENTRIES
/* create a second static entry */
err = etharp_add_static_entry(&adrs[ARP_TABLE_SIZE+1], &test_ethaddr4);
fail_unless(err == ERR_OK);
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr);
fail_unless(idx == 0);
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr);
fail_unless(idx == 2);
/* and remove it again */
err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE+1]);
fail_unless(err == ERR_OK);
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr);
fail_unless(idx == 0);
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr);
fail_unless(idx == -1);
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
/* check that static entries don't time out */
etharp_remove_all();
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr);
fail_unless(idx == 0);
#if ETHARP_SUPPORT_STATIC_ENTRIES
/* remove the first static entry */
err = etharp_remove_static_entry(&adrs[ARP_TABLE_SIZE]);
fail_unless(err == ERR_OK);
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE], &unused_ethaddr, &unused_ipaddr);
fail_unless(idx == -1);
idx = etharp_find_addr(NULL, &adrs[ARP_TABLE_SIZE+1], &unused_ethaddr, &unused_ipaddr);
fail_unless(idx == -1);
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
udp_remove(pcb);
}
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
etharp_suite(void)
{
TFun tests[] = {
test_etharp_table,
};
return create_suite("ETHARP", tests, sizeof(tests)/sizeof(TFun), etharp_setup, etharp_teardown);
}

View File

@@ -0,0 +1,8 @@
#ifndef __TEST_ETHARP_H__
#define __TEST_ETHARP_H__
#include "../lwip_check.h"
Suite* etharp_suite(void);
#endif

View File

@@ -0,0 +1,37 @@
#ifndef __LWIP_CHECK_H__
#define __LWIP_CHECK_H__
/* Common header file for lwIP unit tests using the check framework */
#include <config.h>
#include <check.h>
#include <stdlib.h>
#define FAIL_RET() do { fail(); return; } while(0)
#define EXPECT(x) fail_unless(x)
#define EXPECT_RET(x) do { fail_unless(x); if(!(x)) { return; }} while(0)
#define EXPECT_RETX(x, y) do { fail_unless(x); if(!(x)) { return y; }} while(0)
#define EXPECT_RETNULL(x) EXPECT_RETX(x, NULL)
/** typedef for a function returning a test suite */
typedef Suite* (suite_getter_fn)(void);
/** Create a test suite */
static Suite* create_suite(const char* name, TFun *tests, size_t num_tests, SFun setup, SFun teardown)
{
size_t i;
Suite *s = suite_create(name);
for(i = 0; i < num_tests; i++) {
/* Core test case */
TCase *tc_core = tcase_create("Core");
if ((setup != NULL) || (teardown != NULL)) {
tcase_add_checked_fixture(tc_core, setup, teardown);
}
tcase_add_test(tc_core, tests[i]);
suite_add_tcase(s, tc_core);
}
return s;
}
#endif /* __LWIP_CHECK_H__ */

View File

@@ -0,0 +1,46 @@
#include "lwip_check.h"
#include "udp/test_udp.h"
#include "tcp/test_tcp.h"
#include "tcp/test_tcp_oos.h"
#include "core/test_mem.h"
#include "etharp/test_etharp.h"
#include "lwip/init.h"
int main()
{
int number_failed;
SRunner *sr;
size_t i;
suite_getter_fn* suites[] = {
udp_suite,
tcp_suite,
tcp_oos_suite,
mem_suite,
etharp_suite,
};
size_t num = sizeof(suites)/sizeof(void*);
LWIP_ASSERT("No suites defined", num > 0);
lwip_init();
sr = srunner_create((suites[0])());
for(i = 1; i < num; i++) {
srunner_add_suite(sr, ((suite_getter_fn*)suites[i])());
}
#ifdef LWIP_UNITTESTS_NOFORK
srunner_set_fork_status(sr, CK_NOFORK);
#endif
#ifdef LWIP_UNITTESTS_FORK
srunner_set_fork_status(sr, CK_FORK);
#endif
srunner_run_all(sr, CK_NORMAL);
number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@@ -0,0 +1,195 @@
#include "tcp_helper.h"
#include "lwip/tcp_impl.h"
#include "lwip/stats.h"
#include "lwip/pbuf.h"
#include "lwip/inet_chksum.h"
#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
#error "This tests needs TCP- and MEMP-statistics enabled"
#endif
/** Remove all pcbs on the given list. */
static void
tcp_remove(struct tcp_pcb* pcb_list)
{
struct tcp_pcb *pcb = pcb_list;
struct tcp_pcb *pcb2;
while(pcb != NULL) {
pcb2 = pcb;
pcb = pcb->next;
tcp_abort(pcb2);
}
}
/** Remove all pcbs on listen-, active- and time-wait-list (bound- isn't exported). */
void
tcp_remove_all(void)
{
tcp_remove(tcp_listen_pcbs.pcbs);
tcp_remove(tcp_active_pcbs);
tcp_remove(tcp_tw_pcbs);
fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
fail_unless(lwip_stats.memp[MEMP_TCP_PCB_LISTEN].used == 0);
fail_unless(lwip_stats.memp[MEMP_TCP_SEG].used == 0);
fail_unless(lwip_stats.memp[MEMP_PBUF_POOL].used == 0);
}
/** Create a TCP segment usable for passing to tcp_input
* - IP-addresses, ports, seqno and ackno are taken from pcb
* - seqno and ackno can be altered with an offset
*/
struct pbuf*
tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len, u32_t seqno_offset,
u32_t ackno_offset, u8_t headerflags)
{
return tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port,
data, data_len, pcb->rcv_nxt + seqno_offset, pcb->snd_nxt + ackno_offset, headerflags);
}
/** Create a TCP segment usable for passing to tcp_input */
struct pbuf*
tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip,
u16_t src_port, u16_t dst_port, void* data, size_t data_len,
u32_t seqno, u32_t ackno, u8_t headerflags)
{
struct pbuf* p;
struct ip_hdr* iphdr;
struct tcp_hdr* tcphdr;
u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len);
p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL);
EXPECT_RETNULL(p != NULL);
EXPECT_RETNULL(p->next == NULL);
memset(p->payload, 0, p->len);
iphdr = p->payload;
/* fill IP header */
iphdr->dest.addr = dst_ip->addr;
iphdr->src.addr = src_ip->addr;
IPH_VHLTOS_SET(iphdr, 4, IP_HLEN / 4, 0);
IPH_LEN_SET(iphdr, htons(p->tot_len));
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
tcphdr = p->payload;
tcphdr->src = htons(src_port);
tcphdr->dest = htons(dst_port);
tcphdr->seqno = htonl(seqno);
tcphdr->ackno = htonl(ackno);
TCPH_HDRLEN_SET(tcphdr, sizeof(struct tcp_hdr)/4);
TCPH_FLAGS_SET(tcphdr, headerflags);
tcphdr->wnd = htons(TCP_WND);
/* copy data */
memcpy((char*)tcphdr + sizeof(struct tcp_hdr), data, data_len);
/* calculate checksum */
tcphdr->chksum = inet_chksum_pseudo(p, &(iphdr->src), &(iphdr->dest),
IP_PROTO_TCP, p->tot_len);
pbuf_header(p, sizeof(struct ip_hdr));
return p;
}
/** Safely bring a tcp_pcb into the requested state */
void
tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip,
ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port)
{
/* @todo: are these all states? */
/* @todo: remove from previous list */
pcb->state = state;
if (state == ESTABLISHED) {
TCP_REG(&tcp_active_pcbs, pcb);
pcb->local_ip.addr = local_ip->addr;
pcb->local_port = local_port;
pcb->remote_ip.addr = remote_ip->addr;
pcb->remote_port = remote_port;
} else if(state == LISTEN) {
TCP_REG(&tcp_listen_pcbs.pcbs, pcb);
pcb->local_ip.addr = local_ip->addr;
pcb->local_port = local_port;
} else if(state == TIME_WAIT) {
TCP_REG(&tcp_tw_pcbs, pcb);
pcb->local_ip.addr = local_ip->addr;
pcb->local_port = local_port;
pcb->remote_ip.addr = remote_ip->addr;
pcb->remote_port = remote_port;
} else {
fail();
}
}
void
test_tcp_counters_err(void* arg, err_t err)
{
struct test_tcp_counters* counters = arg;
EXPECT_RET(arg != NULL);
counters->err_calls++;
counters->last_err = err;
}
static void
test_tcp_counters_check_rxdata(struct test_tcp_counters* counters, struct pbuf* p)
{
struct pbuf* q;
u32_t i, received;
if(counters->expected_data == NULL) {
/* no data to compare */
return;
}
EXPECT_RET(counters->recved_bytes + p->tot_len <= counters->expected_data_len);
received = counters->recved_bytes;
for(q = p; q != NULL; q = q->next) {
char *data = q->payload;
for(i = 0; i < q->len; i++) {
EXPECT_RET(data[i] == counters->expected_data[received]);
received++;
}
}
EXPECT(received == counters->recved_bytes + p->tot_len);
}
err_t
test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err)
{
struct test_tcp_counters* counters = arg;
EXPECT_RETX(arg != NULL, ERR_OK);
EXPECT_RETX(pcb != NULL, ERR_OK);
EXPECT_RETX(err == ERR_OK, ERR_OK);
if (p != NULL) {
if (counters->close_calls == 0) {
counters->recv_calls++;
test_tcp_counters_check_rxdata(counters, p);
counters->recved_bytes += p->tot_len;
} else {
counters->recv_calls_after_close++;
counters->recved_bytes_after_close += p->tot_len;
}
pbuf_free(p);
} else {
counters->close_calls++;
}
EXPECT(counters->recv_calls_after_close == 0 && counters->recved_bytes_after_close == 0);
return ERR_OK;
}
/** Allocate a pcb and set up the test_tcp_counters_* callbacks */
struct tcp_pcb*
test_tcp_new_counters_pcb(struct test_tcp_counters* counters)
{
struct tcp_pcb* pcb = tcp_new();
if (pcb != NULL) {
/* set up args and callbacks */
tcp_arg(pcb, counters);
tcp_recv(pcb, test_tcp_counters_recv);
tcp_err(pcb, test_tcp_counters_err);
}
return pcb;
}

View File

@@ -0,0 +1,36 @@
#ifndef __TCP_HELPER_H__
#define __TCP_HELPER_H__
#include "../lwip_check.h"
#include "lwip/arch.h"
#include "lwip/tcp.h"
/* counters used for test_tcp_counters_* callback functions */
struct test_tcp_counters {
u32_t recv_calls;
u32_t recved_bytes;
u32_t recv_calls_after_close;
u32_t recved_bytes_after_close;
u32_t close_calls;
u32_t err_calls;
err_t last_err;
char* expected_data;
u32_t expected_data_len;
};
/* Helper functions */
void tcp_remove_all(void);
struct pbuf* tcp_create_segment(ip_addr_t* src_ip, ip_addr_t* dst_ip,
u16_t src_port, u16_t dst_port, void* data, size_t data_len,
u32_t seqno, u32_t ackno, u8_t headerflags);
struct pbuf* tcp_create_rx_segment(struct tcp_pcb* pcb, void* data, size_t data_len,
u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags);
void tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, ip_addr_t* local_ip,
ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port);
void test_tcp_counters_err(void* arg, err_t err);
err_t test_tcp_counters_recv(void* arg, struct tcp_pcb* pcb, struct pbuf* p, err_t err);
struct tcp_pcb* test_tcp_new_counters_pcb(struct test_tcp_counters* counters);
#endif

View File

@@ -0,0 +1,104 @@
#include "test_tcp.h"
#include "lwip/tcp_impl.h"
#include "lwip/stats.h"
#include "tcp_helper.h"
#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
#error "This tests needs TCP- and MEMP-statistics enabled"
#endif
/* Setups/teardown functions */
static void
tcp_setup(void)
{
tcp_remove_all();
}
static void
tcp_teardown(void)
{
tcp_remove_all();
}
/* Test functions */
/** Call tcp_new() and tcp_abort() and test memp stats */
START_TEST(test_tcp_new_abort)
{
struct tcp_pcb* pcb;
LWIP_UNUSED_ARG(_i);
fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
pcb = tcp_new();
fail_unless(pcb != NULL);
if (pcb != NULL) {
fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
tcp_abort(pcb);
fail_unless(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
}
}
END_TEST
/** Create an ESTABLISHED pcb and check if receive callback is called */
START_TEST(test_tcp_recv_inseq)
{
struct test_tcp_counters counters;
struct tcp_pcb* pcb;
struct pbuf* p;
char data[] = {1, 2, 3, 4};
ip_addr_t remote_ip, local_ip;
u16_t data_len;
u16_t remote_port = 0x100, local_port = 0x101;
struct netif netif;
LWIP_UNUSED_ARG(_i);
/* initialize local vars */
memset(&netif, 0, sizeof(netif));
IP4_ADDR(&local_ip, 192, 168, 1, 1);
IP4_ADDR(&remote_ip, 192, 168, 1, 2);
data_len = sizeof(data);
/* initialize counter struct */
memset(&counters, 0, sizeof(counters));
counters.expected_data_len = data_len;
counters.expected_data = data;
/* create and initialize the pcb */
pcb = test_tcp_new_counters_pcb(&counters);
EXPECT_RET(pcb != NULL);
tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
/* create a segment */
p = tcp_create_rx_segment(pcb, counters.expected_data, data_len, 0, 0, 0);
EXPECT(p != NULL);
if (p != NULL) {
/* pass the segment to tcp_input */
tcp_input(p, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 1);
EXPECT(counters.recved_bytes == data_len);
EXPECT(counters.err_calls == 0);
}
/* make sure the pcb is freed */
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
tcp_abort(pcb);
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
tcp_suite(void)
{
TFun tests[] = {
test_tcp_new_abort,
test_tcp_recv_inseq,
};
return create_suite("TCP", tests, sizeof(tests)/sizeof(TFun), tcp_setup, tcp_teardown);
}

View File

@@ -0,0 +1,8 @@
#ifndef __TEST_TCP_H__
#define __TEST_TCP_H__
#include "../lwip_check.h"
Suite *tcp_suite(void);
#endif

View File

@@ -0,0 +1,540 @@
#include "test_tcp_oos.h"
#include "lwip/tcp_impl.h"
#include "lwip/stats.h"
#include "tcp_helper.h"
#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
#error "This tests needs TCP- and MEMP-statistics enabled"
#endif
#if !TCP_QUEUE_OOSEQ
#error "This tests needs TCP_QUEUE_OOSEQ enabled"
#endif
/** CHECK_SEGMENTS_ON_OOSEQ:
* 1: check count, seqno and len of segments on pcb->ooseq (strict)
* 0: only check that bytes are received in correct order (less strict) */
#define CHECK_SEGMENTS_ON_OOSEQ 1
#if CHECK_SEGMENTS_ON_OOSEQ
#define EXPECT_OOSEQ(x) EXPECT(x)
#else
#define EXPECT_OOSEQ(x)
#endif
/* helper functions */
/** Get the numbers of segments on the ooseq list */
static int tcp_oos_count(struct tcp_pcb* pcb)
{
int num = 0;
struct tcp_seg* seg = pcb->ooseq;
while(seg != NULL) {
num++;
seg = seg->next;
}
return num;
}
/** Get the seqno of a segment (by index) on the ooseq list
*
* @param pcb the pcb to check for ooseq segments
* @param seg_index index of the segment on the ooseq list
* @return seqno of the segment
*/
static u32_t
tcp_oos_seg_seqno(struct tcp_pcb* pcb, int seg_index)
{
int num = 0;
struct tcp_seg* seg = pcb->ooseq;
/* then check the actual segment */
while(seg != NULL) {
if(num == seg_index) {
return seg->tcphdr->seqno;
}
num++;
seg = seg->next;
}
fail();
return 0;
}
/** Get the tcplen (datalen + SYN/FIN) of a segment (by index) on the ooseq list
*
* @param pcb the pcb to check for ooseq segments
* @param seg_index index of the segment on the ooseq list
* @return tcplen of the segment
*/
static int
tcp_oos_seg_tcplen(struct tcp_pcb* pcb, int seg_index)
{
int num = 0;
struct tcp_seg* seg = pcb->ooseq;
/* then check the actual segment */
while(seg != NULL) {
if(num == seg_index) {
return TCP_TCPLEN(seg);
}
num++;
seg = seg->next;
}
fail();
return -1;
}
/** Get the tcplen (datalen + SYN/FIN) of all segments on the ooseq list
*
* @param pcb the pcb to check for ooseq segments
* @return tcplen of all segment
*/
static int
tcp_oos_tcplen(struct tcp_pcb* pcb)
{
int len = 0;
struct tcp_seg* seg = pcb->ooseq;
/* then check the actual segment */
while(seg != NULL) {
len += TCP_TCPLEN(seg);
seg = seg->next;
}
return len;
}
/* Setup/teardown functions */
static void
tcp_oos_setup(void)
{
tcp_remove_all();
}
static void
tcp_oos_teardown(void)
{
tcp_remove_all();
}
/* Test functions */
/** create multiple segments and pass them to tcp_input in a wrong
* order to see if ooseq-caching works correctly
* FIN is received in out-of-sequence segments only */
START_TEST(test_tcp_recv_ooseq_FIN_OOSEQ)
{
struct test_tcp_counters counters;
struct tcp_pcb* pcb;
struct pbuf *p_8_9, *p_4_8, *p_4_10, *p_2_14, *p_fin, *pinseq;
char data[] = {
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16};
ip_addr_t remote_ip, local_ip;
u16_t data_len;
u16_t remote_port = 0x100, local_port = 0x101;
struct netif netif;
LWIP_UNUSED_ARG(_i);
/* initialize local vars */
memset(&netif, 0, sizeof(netif));
IP4_ADDR(&local_ip, 192, 168, 1, 1);
IP4_ADDR(&remote_ip, 192, 168, 1, 2);
data_len = sizeof(data);
/* initialize counter struct */
memset(&counters, 0, sizeof(counters));
counters.expected_data_len = data_len;
counters.expected_data = data;
/* create and initialize the pcb */
pcb = test_tcp_new_counters_pcb(&counters);
EXPECT_RET(pcb != NULL);
tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
/* create segments */
/* pinseq is sent as last segment! */
pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK);
/* p1: 8 bytes before FIN */
/* seqno: 8..16 */
p_8_9 = tcp_create_rx_segment(pcb, &data[8], 8, 8, 0, TCP_ACK|TCP_FIN);
/* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
/* seqno: 4..11 */
p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK);
/* p3: same as p2 but 2 bytes longer */
/* seqno: 4..13 */
p_4_10 = tcp_create_rx_segment(pcb, &data[4], 10, 4, 0, TCP_ACK);
/* p4: 14 bytes before FIN, includes data from p1 and p2, plus partly from pinseq */
/* seqno: 2..15 */
p_2_14 = tcp_create_rx_segment(pcb, &data[2], 14, 2, 0, TCP_ACK);
/* FIN, seqno 16 */
p_fin = tcp_create_rx_segment(pcb, NULL, 0,16, 0, TCP_ACK|TCP_FIN);
EXPECT(pinseq != NULL);
EXPECT(p_8_9 != NULL);
EXPECT(p_4_8 != NULL);
EXPECT(p_4_10 != NULL);
EXPECT(p_2_14 != NULL);
EXPECT(p_fin != NULL);
if ((pinseq != NULL) && (p_8_9 != NULL) && (p_4_8 != NULL) && (p_4_10 != NULL) && (p_2_14 != NULL) && (p_fin != NULL)) {
/* pass the segment to tcp_input */
tcp_input(p_8_9, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 8);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 9); /* includes FIN */
/* pass the segment to tcp_input */
tcp_input(p_4_8, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
/* pass the segment to tcp_input */
tcp_input(p_4_10, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* ooseq queue: unchanged */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 4);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 4);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 8);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 9); /* includes FIN */
/* pass the segment to tcp_input */
tcp_input(p_2_14, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
/* pass the segment to tcp_input */
tcp_input(p_fin, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* ooseq queue: unchanged */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 2);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 15); /* includes FIN */
/* pass the segment to tcp_input */
tcp_input(pinseq, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 1);
EXPECT(counters.recv_calls == 1);
EXPECT(counters.recved_bytes == data_len);
EXPECT(counters.err_calls == 0);
EXPECT(pcb->ooseq == NULL);
}
/* make sure the pcb is freed */
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
tcp_abort(pcb);
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
}
END_TEST
/** create multiple segments and pass them to tcp_input in a wrong
* order to see if ooseq-caching works correctly
* FIN is received IN-SEQUENCE at the end */
START_TEST(test_tcp_recv_ooseq_FIN_INSEQ)
{
struct test_tcp_counters counters;
struct tcp_pcb* pcb;
struct pbuf *p_1_2, *p_4_8, *p_3_11, *p_2_12, *p_15_1, *p_15_1a, *pinseq, *pinseqFIN;
char data[] = {
1, 2, 3, 4,
5, 6, 7, 8,
9, 10, 11, 12,
13, 14, 15, 16};
ip_addr_t remote_ip, local_ip;
u16_t data_len;
u16_t remote_port = 0x100, local_port = 0x101;
struct netif netif;
LWIP_UNUSED_ARG(_i);
/* initialize local vars */
memset(&netif, 0, sizeof(netif));
IP4_ADDR(&local_ip, 192, 168, 1, 1);
IP4_ADDR(&remote_ip, 192, 168, 1, 2);
data_len = sizeof(data);
/* initialize counter struct */
memset(&counters, 0, sizeof(counters));
counters.expected_data_len = data_len;
counters.expected_data = data;
/* create and initialize the pcb */
pcb = test_tcp_new_counters_pcb(&counters);
EXPECT_RET(pcb != NULL);
tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
/* create segments */
/* p1: 7 bytes - 2 before FIN */
/* seqno: 1..2 */
p_1_2 = tcp_create_rx_segment(pcb, &data[1], 2, 1, 0, TCP_ACK);
/* p2: 4 bytes before p1, including the first 4 bytes of p1 (partly duplicate) */
/* seqno: 4..11 */
p_4_8 = tcp_create_rx_segment(pcb, &data[4], 8, 4, 0, TCP_ACK);
/* p3: same as p2 but 2 bytes longer and one byte more at the front */
/* seqno: 3..13 */
p_3_11 = tcp_create_rx_segment(pcb, &data[3], 11, 3, 0, TCP_ACK);
/* p4: 13 bytes - 2 before FIN - should be ignored as contained in p1 and p3 */
/* seqno: 2..13 */
p_2_12 = tcp_create_rx_segment(pcb, &data[2], 12, 2, 0, TCP_ACK);
/* pinseq is the first segment that is held back to create ooseq! */
/* seqno: 0..3 */
pinseq = tcp_create_rx_segment(pcb, &data[0], 4, 0, 0, TCP_ACK);
/* p5: last byte before FIN */
/* seqno: 15 */
p_15_1 = tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
/* p6: same as p5, should be ignored */
p_15_1a= tcp_create_rx_segment(pcb, &data[15], 1, 15, 0, TCP_ACK);
/* pinseqFIN: last 2 bytes plus FIN */
/* only segment containing seqno 14 and FIN */
pinseqFIN = tcp_create_rx_segment(pcb, &data[14], 2, 14, 0, TCP_ACK|TCP_FIN);
EXPECT(pinseq != NULL);
EXPECT(p_1_2 != NULL);
EXPECT(p_4_8 != NULL);
EXPECT(p_3_11 != NULL);
EXPECT(p_2_12 != NULL);
EXPECT(p_15_1 != NULL);
EXPECT(p_15_1a != NULL);
EXPECT(pinseqFIN != NULL);
if ((pinseq != NULL) && (p_1_2 != NULL) && (p_4_8 != NULL) && (p_3_11 != NULL) && (p_2_12 != NULL)
&& (p_15_1 != NULL) && (p_15_1a != NULL) && (pinseqFIN != NULL)) {
/* pass the segment to tcp_input */
tcp_input(p_1_2, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
/* pass the segment to tcp_input */
tcp_input(p_4_8, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 4);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 8);
/* pass the segment to tcp_input */
tcp_input(p_3_11, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 2);
/* p_3_11 has removed p_4_8 from ooseq */
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 3);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 11);
/* pass the segment to tcp_input */
tcp_input(p_2_12, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 2);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 1);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 1) == 2);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 1) == 12);
/* pass the segment to tcp_input */
tcp_input(pinseq, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 1);
EXPECT(counters.recved_bytes == 14);
EXPECT(counters.err_calls == 0);
EXPECT(pcb->ooseq == NULL);
/* pass the segment to tcp_input */
tcp_input(p_15_1, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 1);
EXPECT(counters.recved_bytes == 14);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
/* pass the segment to tcp_input */
tcp_input(p_15_1a, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 1);
EXPECT(counters.recved_bytes == 14);
EXPECT(counters.err_calls == 0);
/* check ooseq queue: unchanged */
EXPECT_OOSEQ(tcp_oos_count(pcb) == 1);
EXPECT_OOSEQ(tcp_oos_seg_seqno(pcb, 0) == 15);
EXPECT_OOSEQ(tcp_oos_seg_tcplen(pcb, 0) == 1);
/* pass the segment to tcp_input */
tcp_input(pinseqFIN, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 1);
EXPECT(counters.recv_calls == 2);
EXPECT(counters.recved_bytes == data_len);
EXPECT(counters.err_calls == 0);
EXPECT(pcb->ooseq == NULL);
}
/* make sure the pcb is freed */
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
tcp_abort(pcb);
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
}
END_TEST
static char data_full_wnd[TCP_WND];
/** create multiple segments and pass them to tcp_input with the first segment missing
* to simulate overruning the rxwin with ooseq queueing enabled */
START_TEST(test_tcp_recv_ooseq_overrun_rxwin)
{
int i, k;
struct test_tcp_counters counters;
struct tcp_pcb* pcb;
struct pbuf *pinseq, *p_ovr;
ip_addr_t remote_ip, local_ip;
u16_t remote_port = 0x100, local_port = 0x101;
struct netif netif;
int datalen = 0;
int datalen2;
LWIP_UNUSED_ARG(_i);
for(i = 0; i < sizeof(data_full_wnd); i++) {
data_full_wnd[i] = (char)i;
}
/* initialize local vars */
memset(&netif, 0, sizeof(netif));
IP4_ADDR(&local_ip, 192, 168, 1, 1);
IP4_ADDR(&remote_ip, 192, 168, 1, 2);
/* initialize counter struct */
memset(&counters, 0, sizeof(counters));
counters.expected_data_len = TCP_WND;
counters.expected_data = data_full_wnd;
/* create and initialize the pcb */
pcb = test_tcp_new_counters_pcb(&counters);
EXPECT_RET(pcb != NULL);
tcp_set_state(pcb, ESTABLISHED, &local_ip, &remote_ip, local_port, remote_port);
pcb->rcv_nxt = 0x8000;
/* create segments */
/* pinseq is sent as last segment! */
pinseq = tcp_create_rx_segment(pcb, &data_full_wnd[0], TCP_MSS, 0, 0, TCP_ACK);
for(i = TCP_MSS, k = 0; i < TCP_WND; i += TCP_MSS, k++) {
int count, expected_datalen;
struct pbuf *p = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)],
TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK);
EXPECT(p != NULL);
/* pass the segment to tcp_input */
tcp_input(p, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
count = tcp_oos_count(pcb);
EXPECT_OOSEQ(count == k+1);
datalen = tcp_oos_tcplen(pcb);
if (i + TCP_MSS < TCP_WND) {
expected_datalen = (k+1)*TCP_MSS;
} else {
expected_datalen = TCP_WND - TCP_MSS;
}
if (datalen != expected_datalen) {
EXPECT_OOSEQ(datalen == expected_datalen);
}
}
/* pass in one more segment, cleary overrunning the rxwin */
p_ovr = tcp_create_rx_segment(pcb, &data_full_wnd[TCP_MSS*(k+1)], TCP_MSS, TCP_MSS*(k+1), 0, TCP_ACK);
EXPECT(p_ovr != NULL);
/* pass the segment to tcp_input */
tcp_input(p_ovr, &netif);
/* check if counters are as expected */
EXPECT(counters.close_calls == 0);
EXPECT(counters.recv_calls == 0);
EXPECT(counters.recved_bytes == 0);
EXPECT(counters.err_calls == 0);
/* check ooseq queue */
EXPECT_OOSEQ(tcp_oos_count(pcb) == k);
datalen2 = tcp_oos_tcplen(pcb);
EXPECT_OOSEQ(datalen == datalen2);
/* now pass inseq */
tcp_input(pinseq, &netif);
EXPECT(pcb->ooseq == NULL);
/* make sure the pcb is freed */
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 1);
tcp_abort(pcb);
EXPECT(lwip_stats.memp[MEMP_TCP_PCB].used == 0);
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
tcp_oos_suite(void)
{
TFun tests[] = {
test_tcp_recv_ooseq_FIN_OOSEQ,
test_tcp_recv_ooseq_FIN_INSEQ,
test_tcp_recv_ooseq_overrun_rxwin,
};
return create_suite("TCP_OOS", tests, sizeof(tests)/sizeof(TFun), tcp_oos_setup, tcp_oos_teardown);
}

View File

@@ -0,0 +1,8 @@
#ifndef __TEST_TCP_OOS_H__
#define __TEST_TCP_OOS_H__
#include "../lwip_check.h"
Suite *tcp_oos_suite(void);
#endif

View File

@@ -0,0 +1,68 @@
#include "test_udp.h"
#include "lwip/udp.h"
#include "lwip/stats.h"
#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS
#error "This tests needs UDP- and MEMP-statistics enabled"
#endif
/* Helper functions */
static void
udp_remove_all(void)
{
struct udp_pcb *pcb = udp_pcbs;
struct udp_pcb *pcb2;
while(pcb != NULL) {
pcb2 = pcb;
pcb = pcb->next;
udp_remove(pcb2);
}
fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0);
}
/* Setups/teardown functions */
static void
udp_setup(void)
{
udp_remove_all();
}
static void
udp_teardown(void)
{
udp_remove_all();
}
/* Test functions */
START_TEST(test_udp_new_remove)
{
struct udp_pcb* pcb;
LWIP_UNUSED_ARG(_i);
fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0);
pcb = udp_new();
fail_unless(pcb != NULL);
if (pcb != NULL) {
fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 1);
udp_remove(pcb);
fail_unless(lwip_stats.memp[MEMP_UDP_PCB].used == 0);
}
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
udp_suite(void)
{
TFun tests[] = {
test_udp_new_remove,
};
return create_suite("UDP", tests, sizeof(tests)/sizeof(TFun), udp_setup, udp_teardown);
}

View File

@@ -0,0 +1,8 @@
#ifndef __TEST_UDP_H__
#define __TEST_UDP_H__
#include "../lwip_check.h"
Suite* udp_suite(void);
#endif