初始化版本
This commit is contained in:
38
lwip/lwip-2.2.1/test/unit/Filelists.cmake
Normal file
38
lwip/lwip-2.2.1/test/unit/Filelists.cmake
Normal file
@ -0,0 +1,38 @@
|
||||
# This file is indended to be included in end-user CMakeLists.txt
|
||||
# include(/path/to/Filelists.cmake)
|
||||
# It assumes the variable LWIP_DIR is defined pointing to the
|
||||
# root path of lwIP sources.
|
||||
#
|
||||
# This file is NOT designed (on purpose) to be used as cmake
|
||||
# subdir via add_subdirectory()
|
||||
# The intention is to provide greater flexibility to users to
|
||||
# create their own targets using the *_SRCS variables.
|
||||
|
||||
if(NOT ${CMAKE_VERSION} VERSION_LESS "3.10.0")
|
||||
include_guard(GLOBAL)
|
||||
endif()
|
||||
|
||||
set(LWIP_TESTDIR ${LWIP_DIR}/test/unit)
|
||||
set(LWIP_TESTFILES
|
||||
${LWIP_TESTDIR}/lwip_unittests.c
|
||||
${LWIP_TESTDIR}/api/test_sockets.c
|
||||
${LWIP_TESTDIR}/arch/sys_arch.c
|
||||
${LWIP_TESTDIR}/core/test_def.c
|
||||
${LWIP_TESTDIR}/core/test_dns.c
|
||||
${LWIP_TESTDIR}/core/test_mem.c
|
||||
${LWIP_TESTDIR}/core/test_netif.c
|
||||
${LWIP_TESTDIR}/core/test_pbuf.c
|
||||
${LWIP_TESTDIR}/core/test_timers.c
|
||||
${LWIP_TESTDIR}/dhcp/test_dhcp.c
|
||||
${LWIP_TESTDIR}/etharp/test_etharp.c
|
||||
${LWIP_TESTDIR}/ip4/test_ip4.c
|
||||
${LWIP_TESTDIR}/ip6/test_ip6.c
|
||||
${LWIP_TESTDIR}/mdns/test_mdns.c
|
||||
${LWIP_TESTDIR}/mqtt/test_mqtt.c
|
||||
${LWIP_TESTDIR}/tcp/tcp_helper.c
|
||||
${LWIP_TESTDIR}/tcp/test_tcp_oos.c
|
||||
${LWIP_TESTDIR}/tcp/test_tcp_state.c
|
||||
${LWIP_TESTDIR}/tcp/test_tcp.c
|
||||
${LWIP_TESTDIR}/udp/test_udp.c
|
||||
${LWIP_TESTDIR}/ppp/test_pppos.c
|
||||
)
|
||||
54
lwip/lwip-2.2.1/test/unit/Filelists.mk
Normal file
54
lwip/lwip-2.2.1/test/unit/Filelists.mk
Normal file
@ -0,0 +1,54 @@
|
||||
#
|
||||
# Copyright (c) 2001, 2002 Swedish Institute of Computer Science.
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without modification,
|
||||
# are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
# this list of conditions and the following disclaimer in the documentation
|
||||
# and/or other materials provided with the distribution.
|
||||
# 3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
# SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
# IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
# OF SUCH DAMAGE.
|
||||
#
|
||||
# This file is part of the lwIP TCP/IP stack.
|
||||
#
|
||||
# Author: Adam Dunkels <adam@sics.se>
|
||||
#
|
||||
|
||||
TESTDIR=$(LWIPDIR)/../test/unit
|
||||
TESTFILES=$(TESTDIR)/lwip_unittests.c \
|
||||
$(TESTDIR)/api/test_sockets.c \
|
||||
$(TESTDIR)/arch/sys_arch.c \
|
||||
$(TESTDIR)/core/test_def.c \
|
||||
$(TESTDIR)/core/test_dns.c \
|
||||
$(TESTDIR)/core/test_mem.c \
|
||||
$(TESTDIR)/core/test_netif.c \
|
||||
$(TESTDIR)/core/test_pbuf.c \
|
||||
$(TESTDIR)/core/test_timers.c \
|
||||
$(TESTDIR)/dhcp/test_dhcp.c \
|
||||
$(TESTDIR)/etharp/test_etharp.c \
|
||||
$(TESTDIR)/ip4/test_ip4.c \
|
||||
$(TESTDIR)/ip6/test_ip6.c \
|
||||
$(TESTDIR)/mdns/test_mdns.c \
|
||||
$(TESTDIR)/mqtt/test_mqtt.c \
|
||||
$(TESTDIR)/tcp/tcp_helper.c \
|
||||
$(TESTDIR)/tcp/test_tcp_oos.c \
|
||||
$(TESTDIR)/tcp/test_tcp_state.c \
|
||||
$(TESTDIR)/tcp/test_tcp.c \
|
||||
$(TESTDIR)/udp/test_udp.c \
|
||||
$(TESTDIR)/ppp/test_pppos.c
|
||||
|
||||
11
lwip/lwip-2.2.1/test/unit/Makefile
Normal file
11
lwip/lwip-2.2.1/test/unit/Makefile
Normal file
@ -0,0 +1,11 @@
|
||||
# Shortcuts to building and running tests on unix platforms.
|
||||
# Output files will be written to the directory listed below.
|
||||
|
||||
all:
|
||||
cd ../../contrib/ports/unix/check/ && $(MAKE)
|
||||
|
||||
check:
|
||||
cd ../../contrib/ports/unix/check/ && $(MAKE) check
|
||||
|
||||
clean:
|
||||
cd ../../contrib/ports/unix/check/ && $(MAKE) clean
|
||||
852
lwip/lwip-2.2.1/test/unit/api/test_sockets.c
Normal file
852
lwip/lwip-2.2.1/test/unit/api/test_sockets.c
Normal file
@ -0,0 +1,852 @@
|
||||
#include "test_sockets.h"
|
||||
|
||||
#include "lwip/mem.h"
|
||||
#include "lwip/opt.h"
|
||||
#include "lwip/sockets.h"
|
||||
#include "lwip/priv/sockets_priv.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#include "lwip/tcpip.h"
|
||||
#include "lwip/priv/tcp_priv.h"
|
||||
#include "lwip/api.h"
|
||||
|
||||
|
||||
static int
|
||||
test_sockets_get_used_count(void)
|
||||
{
|
||||
int used = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NUM_SOCKETS; i++) {
|
||||
struct lwip_sock* s = lwip_socket_dbg_get_socket(i);
|
||||
if (s != NULL) {
|
||||
if (s->fd_used) {
|
||||
used++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return used;
|
||||
}
|
||||
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
sockets_setup(void)
|
||||
{
|
||||
/* expect full free heap */
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void
|
||||
sockets_teardown(void)
|
||||
{
|
||||
fail_unless(test_sockets_get_used_count() == 0);
|
||||
/* poll until all memory is released... */
|
||||
tcpip_thread_poll_one();
|
||||
while (tcp_tw_pcbs) {
|
||||
tcp_abort(tcp_tw_pcbs);
|
||||
tcpip_thread_poll_one();
|
||||
}
|
||||
tcpip_thread_poll_one();
|
||||
/* ensure full free heap */
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
#ifndef NUM_SOCKETS
|
||||
#define NUM_SOCKETS MEMP_NUM_NETCONN
|
||||
#endif
|
||||
|
||||
#if LWIP_SOCKET
|
||||
static int
|
||||
test_sockets_alloc_socket_nonblocking(int domain, int type)
|
||||
{
|
||||
int s = lwip_socket(domain, type, 0);
|
||||
if (s >= 0) {
|
||||
int ret = lwip_fcntl(s, F_SETFL, O_NONBLOCK);
|
||||
fail_unless(ret == 0);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
/* Verify basic sockets functionality
|
||||
*/
|
||||
START_TEST(test_sockets_basics)
|
||||
{
|
||||
int s, i, ret;
|
||||
int s2[NUM_SOCKETS];
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
s = lwip_socket(AF_INET, SOCK_STREAM, 0);
|
||||
fail_unless(s >= 0);
|
||||
lwip_close(s);
|
||||
|
||||
for (i = 0; i < NUM_SOCKETS; i++) {
|
||||
s2[i] = lwip_socket(AF_INET, SOCK_STREAM, 0);
|
||||
fail_unless(s2[i] >= 0);
|
||||
}
|
||||
|
||||
/* all sockets used, now it should fail */
|
||||
s = lwip_socket(AF_INET, SOCK_STREAM, 0);
|
||||
fail_unless(s == -1);
|
||||
/* close one socket */
|
||||
ret = lwip_close(s2[0]);
|
||||
fail_unless(ret == 0);
|
||||
/* now it should succeed */
|
||||
s2[0] = lwip_socket(AF_INET, SOCK_STREAM, 0);
|
||||
fail_unless(s2[0] >= 0);
|
||||
|
||||
/* close all sockets */
|
||||
for (i = 0; i < NUM_SOCKETS; i++) {
|
||||
ret = lwip_close(s2[i]);
|
||||
fail_unless(ret == 0);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void test_sockets_allfunctions_basic_domain(int domain)
|
||||
{
|
||||
int s, s2, s3, ret;
|
||||
struct sockaddr_storage addr, addr2;
|
||||
socklen_t addrlen, addr2len;
|
||||
char buf[4];
|
||||
/* listen socket */
|
||||
s = lwip_socket(domain, SOCK_STREAM, 0);
|
||||
fail_unless(s >= 0);
|
||||
|
||||
ret = lwip_listen(s, 0);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
addrlen = sizeof(addr);
|
||||
ret = lwip_getsockname(s, (struct sockaddr*)&addr, &addrlen);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
s2 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM);
|
||||
fail_unless(s2 >= 0);
|
||||
/* nonblocking connect s2 to s (but use loopback address) */
|
||||
if (domain == AF_INET) {
|
||||
#if LWIP_IPV4
|
||||
struct sockaddr_in *addr4 = (struct sockaddr_in *)&addr;
|
||||
addr4->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK);
|
||||
#endif
|
||||
} else {
|
||||
#if LWIP_IPV6
|
||||
struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)&addr;
|
||||
struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT;
|
||||
addr6->sin6_addr = lo6;
|
||||
#endif
|
||||
}
|
||||
ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen);
|
||||
fail_unless(ret == -1);
|
||||
fail_unless(errno == EINPROGRESS);
|
||||
ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen);
|
||||
fail_unless(ret == -1);
|
||||
fail_unless(errno == EALREADY);
|
||||
|
||||
while(tcpip_thread_poll_one());
|
||||
|
||||
s3 = lwip_accept(s, (struct sockaddr*)&addr2, &addr2len);
|
||||
fail_unless(s3 >= 0);
|
||||
|
||||
ret = lwip_connect(s2, (struct sockaddr*)&addr, addrlen);
|
||||
fail_unless(ret == -1);
|
||||
fail_unless(errno == EISCONN);
|
||||
|
||||
/* write from server to client */
|
||||
ret = lwip_write(s3, "test", 4);
|
||||
fail_unless(ret == 4);
|
||||
|
||||
ret = lwip_shutdown(s3, SHUT_WR);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
while(tcpip_thread_poll_one());
|
||||
|
||||
ret = lwip_recv(s2, buf, 3, MSG_PEEK);
|
||||
fail_unless(ret == 3);
|
||||
|
||||
ret = lwip_recv(s2, buf, 3, MSG_PEEK);
|
||||
fail_unless(ret == 3);
|
||||
|
||||
ret = lwip_read(s2, buf, 4);
|
||||
fail_unless(ret == 4);
|
||||
|
||||
ret = lwip_read(s2, buf, 1);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
ret = lwip_read(s2, buf, 1);
|
||||
fail_unless(ret == -1);
|
||||
|
||||
ret = lwip_write(s2, "foo", 3);
|
||||
fail_unless(ret == 3);
|
||||
|
||||
ret = lwip_close(s2);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
while(tcpip_thread_poll_one());
|
||||
|
||||
/* read one byte more than available to check handling FIN */
|
||||
ret = lwip_read(s3, buf, 4);
|
||||
fail_unless(ret == 3);
|
||||
|
||||
ret = lwip_read(s3, buf, 1);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
ret = lwip_read(s3, buf, 1);
|
||||
fail_unless(ret == -1);
|
||||
|
||||
while(tcpip_thread_poll_one());
|
||||
|
||||
ret = lwip_close(s);
|
||||
fail_unless(ret == 0);
|
||||
ret = lwip_close(s3);
|
||||
fail_unless(ret == 0);
|
||||
}
|
||||
|
||||
/* Try to step through all sockets functions once...
|
||||
*/
|
||||
START_TEST(test_sockets_allfunctions_basic)
|
||||
{
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
#if LWIP_IPV4
|
||||
test_sockets_allfunctions_basic_domain(AF_INET);
|
||||
#endif
|
||||
#if LWIP_IPV6
|
||||
test_sockets_allfunctions_basic_domain(AF_INET6);
|
||||
#endif
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void test_sockets_init_loopback_addr(int domain, struct sockaddr_storage *addr_st, socklen_t *sz)
|
||||
{
|
||||
memset(addr_st, 0, sizeof(*addr_st));
|
||||
switch(domain) {
|
||||
#if LWIP_IPV6
|
||||
case AF_INET6: {
|
||||
struct sockaddr_in6 *addr = (struct sockaddr_in6*)addr_st;
|
||||
struct in6_addr lo6 = IN6ADDR_LOOPBACK_INIT;
|
||||
addr->sin6_family = AF_INET6;
|
||||
addr->sin6_port = 0; /* use ephemeral port */
|
||||
addr->sin6_addr = lo6;
|
||||
*sz = sizeof(*addr);
|
||||
}
|
||||
break;
|
||||
#endif /* LWIP_IPV6 */
|
||||
#if LWIP_IPV4
|
||||
case AF_INET: {
|
||||
struct sockaddr_in *addr = (struct sockaddr_in*)addr_st;
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_port = 0; /* use ephemeral port */
|
||||
addr->sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK);
|
||||
*sz = sizeof(*addr);
|
||||
}
|
||||
break;
|
||||
#endif /* LWIP_IPV4 */
|
||||
default:
|
||||
*sz = 0;
|
||||
fail();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_sockets_msgapi_update_iovs(struct msghdr *msg, size_t bytes)
|
||||
{
|
||||
msg_iovlen_t i;
|
||||
|
||||
/* note: this modifies the underlying iov_base and iov_len for a partial
|
||||
read for an individual vector. This updates the msg->msg_iov pointer
|
||||
to skip fully consumed vectors */
|
||||
|
||||
/* process fully consumed vectors */
|
||||
for (i = 0; i < msg->msg_iovlen; i++) {
|
||||
if (msg->msg_iov[i].iov_len <= bytes) {
|
||||
/* reduce bytes by amount of this vector */
|
||||
bytes -= msg->msg_iov[i].iov_len;
|
||||
} else {
|
||||
break; /* iov not fully consumed */
|
||||
}
|
||||
}
|
||||
|
||||
/* slide down over fully consumed vectors */
|
||||
msg->msg_iov = &msg->msg_iov[i];
|
||||
msg->msg_iovlen -= i;
|
||||
|
||||
/* update new first vector with any remaining amount */
|
||||
msg->msg_iov[0].iov_base = ((u8_t *)msg->msg_iov[0].iov_base + bytes);
|
||||
msg->msg_iov[0].iov_len -= bytes;
|
||||
}
|
||||
|
||||
static void test_sockets_msgapi_tcp(int domain)
|
||||
{
|
||||
#define BUF_SZ (TCP_SND_BUF/4)
|
||||
#define TOTAL_DATA_SZ (BUF_SZ*8) /* ~(TCP_SND_BUF*2) that accounts for integer rounding */
|
||||
#define NEED_TRAILER (BUF_SZ % 4 != 0)
|
||||
int listnr, s1, s2, i, ret, opt;
|
||||
int bytes_written, bytes_read;
|
||||
struct sockaddr_storage addr_storage;
|
||||
socklen_t addr_size;
|
||||
struct iovec siovs[8];
|
||||
struct msghdr smsg;
|
||||
u8_t * snd_buf;
|
||||
struct iovec riovs[5];
|
||||
struct iovec riovs_tmp[5];
|
||||
struct msghdr rmsg;
|
||||
u8_t * rcv_buf;
|
||||
int rcv_off;
|
||||
int rcv_trailer = 0;
|
||||
u8_t val;
|
||||
|
||||
test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
|
||||
|
||||
listnr = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM);
|
||||
fail_unless(listnr >= 0);
|
||||
s1 = test_sockets_alloc_socket_nonblocking(domain, SOCK_STREAM);
|
||||
fail_unless(s1 >= 0);
|
||||
|
||||
/* setup a listener socket on loopback with ephemeral port */
|
||||
ret = lwip_bind(listnr, (struct sockaddr*)&addr_storage, addr_size);
|
||||
fail_unless(ret == 0);
|
||||
ret = lwip_listen(listnr, 0);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
/* update address with ephemeral port */
|
||||
ret = lwip_getsockname(listnr, (struct sockaddr*)&addr_storage, &addr_size);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
/* connect, won't complete until we accept it */
|
||||
ret = lwip_connect(s1, (struct sockaddr*)&addr_storage, addr_size);
|
||||
fail_unless(ret == -1);
|
||||
fail_unless(errno == EINPROGRESS);
|
||||
|
||||
while (tcpip_thread_poll_one());
|
||||
|
||||
/* accept, creating the other side of the connection */
|
||||
s2 = lwip_accept(listnr, NULL, NULL);
|
||||
fail_unless(s2 >= 0);
|
||||
|
||||
/* double check s1 is connected */
|
||||
ret = lwip_connect(s1, (struct sockaddr*)&addr_storage, addr_size);
|
||||
fail_unless(ret == -1);
|
||||
fail_unless(errno == EISCONN);
|
||||
|
||||
/* set s2 to non-blocking, not inherited from listener */
|
||||
opt = lwip_fcntl(s2, F_GETFL, 0);
|
||||
fail_unless(opt == O_RDWR);
|
||||
opt = O_NONBLOCK;
|
||||
ret = lwip_fcntl(s2, F_SETFL, opt);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
/* we are done with listener, close it */
|
||||
ret = lwip_close(listnr);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
/* allocate a buffer for a stream of incrementing hex (0x00..0xFF) which we will use
|
||||
to create an input vector set that is larger than the TCP's send buffer. This will
|
||||
force execution of the partial IO vector send case */
|
||||
snd_buf = (u8_t*)mem_malloc(BUF_SZ);
|
||||
val = 0x00;
|
||||
fail_unless(snd_buf != NULL);
|
||||
for (i = 0; i < BUF_SZ; i++,val++) {
|
||||
snd_buf[i] = val;
|
||||
}
|
||||
|
||||
/* send the buffer 8 times in one message, equating to TOTAL_DATA_SZ */
|
||||
for (i = 0; i < 8; i++) {
|
||||
siovs[i].iov_base = snd_buf;
|
||||
siovs[i].iov_len = BUF_SZ;
|
||||
}
|
||||
|
||||
/* allocate a receive buffer, same size as snd_buf for easy verification */
|
||||
rcv_buf = (u8_t*)mem_calloc(1, BUF_SZ);
|
||||
fail_unless(rcv_buf != NULL);
|
||||
/* split across iovs */
|
||||
for (i = 0; i < 4; i++) {
|
||||
riovs[i].iov_base = &rcv_buf[i*(BUF_SZ/4)];
|
||||
riovs[i].iov_len = BUF_SZ/4;
|
||||
}
|
||||
/* handling trailing bytes if buffer doesn't evenly divide by 4 */
|
||||
#if NEED_TRAILER
|
||||
if ((BUF_SZ % 4) != 0) {
|
||||
riovs[5].iov_base = &rcv_buf[4*(BUF_SZ/4)];
|
||||
riovs[5].iov_len = BUF_SZ - (4*(BUF_SZ/4));
|
||||
rcv_trailer = 1;
|
||||
}
|
||||
#endif /* NEED_TRAILER */
|
||||
|
||||
/* we use a copy of riovs since we'll be modifying base and len during
|
||||
receiving. This gives us an easy way to reset the iovs for next recvmsg */
|
||||
memcpy(riovs_tmp, riovs, sizeof(riovs));
|
||||
|
||||
memset(&smsg, 0, sizeof(smsg));
|
||||
smsg.msg_iov = siovs;
|
||||
smsg.msg_iovlen = 8;
|
||||
|
||||
memset(&rmsg, 0, sizeof(rmsg));
|
||||
rmsg.msg_iov = riovs_tmp;
|
||||
rmsg.msg_iovlen = (rcv_trailer ? 5 : 4);
|
||||
|
||||
bytes_written = 0;
|
||||
bytes_read = 0;
|
||||
rcv_off = 0;
|
||||
|
||||
while (bytes_written < TOTAL_DATA_SZ && (bytes_read < TOTAL_DATA_SZ)) {
|
||||
/* send data */
|
||||
if (bytes_written < TOTAL_DATA_SZ) {
|
||||
ret = lwip_sendmsg(s1, &smsg, 0);
|
||||
/* note: since we always receive after sending, there will be open
|
||||
space in the send buffer */
|
||||
fail_unless(ret > 0);
|
||||
|
||||
bytes_written += ret;
|
||||
if (bytes_written < TOTAL_DATA_SZ) {
|
||||
test_sockets_msgapi_update_iovs(&smsg, (size_t)ret);
|
||||
}
|
||||
}
|
||||
|
||||
while (tcpip_thread_poll_one());
|
||||
|
||||
/* receive and verify data */
|
||||
do {
|
||||
if (bytes_read < TOTAL_DATA_SZ) {
|
||||
ret = lwip_recvmsg(s2, &rmsg, 0);
|
||||
fail_unless(ret > 0 || (ret == -1 && errno == EWOULDBLOCK));
|
||||
|
||||
if (ret > 0) {
|
||||
rcv_off += ret;
|
||||
/* we have received a full buffer */
|
||||
if (rcv_off == BUF_SZ) {
|
||||
/* note: since iovs are just pointers, compare underlying buf */
|
||||
fail_unless(!memcmp(snd_buf, rcv_buf, BUF_SZ));
|
||||
bytes_read += BUF_SZ;
|
||||
/* reset receive state for next buffer */
|
||||
rcv_off = 0;
|
||||
memset(rcv_buf, 0, BUF_SZ);
|
||||
memcpy(riovs_tmp, riovs, sizeof(riovs));
|
||||
rmsg.msg_iov = riovs_tmp;
|
||||
rmsg.msg_iovlen = (rcv_trailer ? 5 : 4);
|
||||
} else { /* partial read */
|
||||
test_sockets_msgapi_update_iovs(&rmsg, (size_t)ret);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while(ret > 0);
|
||||
}
|
||||
|
||||
ret = lwip_close(s1);
|
||||
fail_unless(ret == 0);
|
||||
ret = lwip_close(s2);
|
||||
fail_unless(ret == 0);
|
||||
mem_free(snd_buf);
|
||||
mem_free(rcv_buf);
|
||||
}
|
||||
|
||||
static void test_sockets_msgapi_udp_send_recv_loop(int s, struct msghdr *smsg, struct msghdr *rmsg)
|
||||
{
|
||||
int i, ret;
|
||||
|
||||
/* send/receive our datagram of IO vectors 10 times */
|
||||
for (i = 0; i < 10; i++) {
|
||||
ret = lwip_sendmsg(s, smsg, 0);
|
||||
fail_unless(ret == 4);
|
||||
|
||||
while (tcpip_thread_poll_one());
|
||||
|
||||
/* receive the datagram split across 4 buffers */
|
||||
ret = lwip_recvmsg(s, rmsg, 0);
|
||||
fail_unless(ret == 4);
|
||||
|
||||
/* verify data */
|
||||
fail_unless(*((u8_t*)rmsg->msg_iov[0].iov_base) == 0xDE);
|
||||
fail_unless(*((u8_t*)rmsg->msg_iov[1].iov_base) == 0xAD);
|
||||
fail_unless(*((u8_t*)rmsg->msg_iov[2].iov_base) == 0xBE);
|
||||
fail_unless(*((u8_t*)rmsg->msg_iov[3].iov_base) == 0xEF);
|
||||
|
||||
/* clear rcv_buf to ensure no data is being skipped */
|
||||
*((u8_t*)rmsg->msg_iov[0].iov_base) = 0x00;
|
||||
*((u8_t*)rmsg->msg_iov[1].iov_base) = 0x00;
|
||||
*((u8_t*)rmsg->msg_iov[2].iov_base) = 0x00;
|
||||
*((u8_t*)rmsg->msg_iov[3].iov_base) = 0x00;
|
||||
}
|
||||
}
|
||||
|
||||
static void test_sockets_msgapi_udp(int domain)
|
||||
{
|
||||
int s, i, ret;
|
||||
struct sockaddr_storage addr_storage;
|
||||
socklen_t addr_size;
|
||||
struct iovec riovs[4];
|
||||
struct msghdr rmsg;
|
||||
u8_t rcv_buf[4];
|
||||
struct iovec siovs[4];
|
||||
struct msghdr smsg;
|
||||
u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
|
||||
/* initialize IO vectors with data */
|
||||
for (i = 0; i < 4; i++) {
|
||||
siovs[i].iov_base = &snd_buf[i];
|
||||
siovs[i].iov_len = sizeof(u8_t);
|
||||
riovs[i].iov_base = &rcv_buf[i];
|
||||
riovs[i].iov_len = sizeof(u8_t);
|
||||
}
|
||||
|
||||
test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
|
||||
|
||||
s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM);
|
||||
fail_unless(s >= 0);
|
||||
|
||||
ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
/* Update addr with epehermal port */
|
||||
ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size);
|
||||
fail_unless(ret == 0);
|
||||
switch(domain) {
|
||||
#if LWIP_IPV6
|
||||
case AF_INET6:
|
||||
fail_unless(addr_size == sizeof(struct sockaddr_in6));
|
||||
break;
|
||||
#endif /* LWIP_IPV6 */
|
||||
#if LWIP_IPV4
|
||||
case AF_INET:
|
||||
fail_unless(addr_size == sizeof(struct sockaddr_in));
|
||||
break;
|
||||
#endif /* LWIP_IPV6 */
|
||||
default:
|
||||
fail();
|
||||
break;
|
||||
}
|
||||
|
||||
/* send and receive the datagram in 4 pieces */
|
||||
memset(&smsg, 0, sizeof(smsg));
|
||||
smsg.msg_iov = siovs;
|
||||
smsg.msg_iovlen = 4;
|
||||
memset(&rmsg, 0, sizeof(rmsg));
|
||||
rmsg.msg_iov = riovs;
|
||||
rmsg.msg_iovlen = 4;
|
||||
|
||||
/* perform a sendmsg with remote host (self) */
|
||||
smsg.msg_name = &addr_storage;
|
||||
smsg.msg_namelen = addr_size;
|
||||
|
||||
test_sockets_msgapi_udp_send_recv_loop(s, &smsg, &rmsg);
|
||||
|
||||
/* Connect to self, allowing us to not pass message name */
|
||||
ret = lwip_connect(s, (struct sockaddr*)&addr_storage, addr_size);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
smsg.msg_name = NULL;
|
||||
smsg.msg_namelen = 0;
|
||||
|
||||
test_sockets_msgapi_udp_send_recv_loop(s, &smsg, &rmsg);
|
||||
|
||||
ret = lwip_close(s);
|
||||
fail_unless(ret == 0);
|
||||
}
|
||||
|
||||
#if LWIP_IPV4
|
||||
static void test_sockets_msgapi_cmsg(int domain)
|
||||
{
|
||||
int s, ret, enable;
|
||||
struct sockaddr_storage addr_storage;
|
||||
socklen_t addr_size;
|
||||
struct iovec iov;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmsg;
|
||||
struct in_pktinfo *pktinfo;
|
||||
u8_t rcv_buf[4];
|
||||
u8_t snd_buf[4] = {0xDE, 0xAD, 0xBE, 0xEF};
|
||||
u8_t cmsg_buf[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
|
||||
test_sockets_init_loopback_addr(domain, &addr_storage, &addr_size);
|
||||
|
||||
s = test_sockets_alloc_socket_nonblocking(domain, SOCK_DGRAM);
|
||||
fail_unless(s >= 0);
|
||||
|
||||
ret = lwip_bind(s, (struct sockaddr*)&addr_storage, addr_size);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
/* Update addr with epehermal port */
|
||||
ret = lwip_getsockname(s, (struct sockaddr*)&addr_storage, &addr_size);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
enable = 1;
|
||||
ret = lwip_setsockopt(s, IPPROTO_IP, IP_PKTINFO, &enable, sizeof(enable));
|
||||
fail_unless(ret == 0);
|
||||
|
||||
/* Receive full message, including control message */
|
||||
iov.iov_base = rcv_buf;
|
||||
iov.iov_len = sizeof(rcv_buf);
|
||||
msg.msg_control = cmsg_buf;
|
||||
msg.msg_controllen = sizeof(cmsg_buf);
|
||||
msg.msg_flags = 0;
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
msg.msg_name = NULL;
|
||||
msg.msg_namelen = 0;
|
||||
|
||||
memset(rcv_buf, 0, sizeof(rcv_buf));
|
||||
ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size);
|
||||
fail_unless(ret == sizeof(snd_buf));
|
||||
|
||||
tcpip_thread_poll_one();
|
||||
|
||||
ret = lwip_recvmsg(s, &msg, 0);
|
||||
fail_unless(ret == sizeof(rcv_buf));
|
||||
fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf)));
|
||||
|
||||
/* Verify message header */
|
||||
cmsg = CMSG_FIRSTHDR(&msg);
|
||||
fail_unless(cmsg != NULL);
|
||||
fail_unless(cmsg->cmsg_len > 0);
|
||||
fail_unless(cmsg->cmsg_level == IPPROTO_IP);
|
||||
fail_unless(cmsg->cmsg_type == IP_PKTINFO);
|
||||
|
||||
/* Verify message data */
|
||||
pktinfo = (struct in_pktinfo*)CMSG_DATA(cmsg);
|
||||
/* We only have loopback interface enabled */
|
||||
fail_unless(pktinfo->ipi_ifindex == 1);
|
||||
fail_unless(pktinfo->ipi_addr.s_addr == PP_HTONL(INADDR_LOOPBACK));
|
||||
|
||||
/* Verify there are no additional messages */
|
||||
cmsg = CMSG_NXTHDR(&msg, cmsg);
|
||||
fail_unless(cmsg == NULL);
|
||||
|
||||
/* Send datagram again, testing truncation */
|
||||
memset(rcv_buf, 0, sizeof(rcv_buf));
|
||||
ret = lwip_sendto(s, snd_buf, sizeof(snd_buf), 0, (struct sockaddr*)&addr_storage, addr_size);
|
||||
fail_unless(ret == sizeof(snd_buf));
|
||||
|
||||
tcpip_thread_poll_one();
|
||||
|
||||
msg.msg_controllen = 1;
|
||||
msg.msg_flags = 0;
|
||||
ret = lwip_recvmsg(s, &msg, 0);
|
||||
fail_unless(ret == sizeof(rcv_buf));
|
||||
fail_unless(!memcmp(rcv_buf, snd_buf, sizeof(rcv_buf)));
|
||||
/* Ensure truncation was returned */
|
||||
fail_unless(msg.msg_flags & MSG_CTRUNC);
|
||||
/* Ensure no control messages were returned */
|
||||
fail_unless(msg.msg_controllen == 0);
|
||||
|
||||
ret = lwip_close(s);
|
||||
fail_unless(ret == 0);
|
||||
}
|
||||
#endif /* LWIP_IPV4 */
|
||||
|
||||
START_TEST(test_sockets_msgapis)
|
||||
{
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
#if LWIP_IPV4
|
||||
test_sockets_msgapi_udp(AF_INET);
|
||||
test_sockets_msgapi_tcp(AF_INET);
|
||||
test_sockets_msgapi_cmsg(AF_INET);
|
||||
#endif
|
||||
#if LWIP_IPV6
|
||||
test_sockets_msgapi_udp(AF_INET6);
|
||||
test_sockets_msgapi_tcp(AF_INET6);
|
||||
#endif
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_sockets_select)
|
||||
{
|
||||
#if LWIP_SOCKET_SELECT
|
||||
int s;
|
||||
int ret;
|
||||
fd_set readset;
|
||||
fd_set writeset;
|
||||
fd_set errset;
|
||||
struct timeval tv;
|
||||
|
||||
fail_unless(test_sockets_get_used_count() == 0);
|
||||
|
||||
s = lwip_socket(AF_INET, SOCK_STREAM, 0);
|
||||
fail_unless(s >= 0);
|
||||
fail_unless(test_sockets_get_used_count() == 0);
|
||||
|
||||
FD_ZERO(&readset);
|
||||
FD_SET(s, &readset);
|
||||
FD_ZERO(&writeset);
|
||||
FD_SET(s, &writeset);
|
||||
FD_ZERO(&errset);
|
||||
FD_SET(s, &errset);
|
||||
|
||||
tv.tv_sec = tv.tv_usec = 0;
|
||||
ret = lwip_select(s + 1, &readset, &writeset, &errset, &tv);
|
||||
fail_unless(ret == 0);
|
||||
fail_unless(test_sockets_get_used_count() == 0);
|
||||
|
||||
ret = lwip_close(s);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
#endif
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_sockets_recv_after_rst)
|
||||
{
|
||||
int sl, sact;
|
||||
int spass = -1;
|
||||
int ret;
|
||||
struct sockaddr_in sa_listen;
|
||||
const u16_t port = 1234;
|
||||
int arg;
|
||||
const char txbuf[] = "something";
|
||||
char rxbuf[16];
|
||||
struct lwip_sock *sact_sock;
|
||||
int err;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
fail_unless(test_sockets_get_used_count() == 0);
|
||||
|
||||
memset(&sa_listen, 0, sizeof(sa_listen));
|
||||
sa_listen.sin_family = AF_INET;
|
||||
sa_listen.sin_port = PP_HTONS(port);
|
||||
sa_listen.sin_addr.s_addr = PP_HTONL(INADDR_LOOPBACK);
|
||||
|
||||
/* set up the listener */
|
||||
sl = lwip_socket(AF_INET, SOCK_STREAM, 0);
|
||||
fail_unless(sl >= 0);
|
||||
fail_unless(test_sockets_get_used_count() == 0);
|
||||
|
||||
ret = lwip_bind(sl, (struct sockaddr *)&sa_listen, sizeof(sa_listen));
|
||||
fail_unless(ret == 0);
|
||||
ret = lwip_listen(sl, 0);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
/* set up the client */
|
||||
sact = lwip_socket(AF_INET, SOCK_STREAM, 0);
|
||||
fail_unless(sact >= 0);
|
||||
fail_unless(test_sockets_get_used_count() == 0);
|
||||
/* set the client to nonblocking to simplify this test */
|
||||
arg = 1;
|
||||
ret = lwip_ioctl(sact, FIONBIO, &arg);
|
||||
fail_unless(ret == 0);
|
||||
/* connect */
|
||||
do {
|
||||
ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen));
|
||||
err = errno;
|
||||
fail_unless((ret == 0) || (ret == -1));
|
||||
if (ret != 0) {
|
||||
if (err == EISCONN) {
|
||||
/* Although this is not valid, use EISCONN as an indicator for successful connection.
|
||||
This marks us as "connect phase is done". On error, we would either have a different
|
||||
errno code or "send" fails later... -> good enough for this test. */
|
||||
ret = 0;
|
||||
} else {
|
||||
fail_unless(err == EINPROGRESS);
|
||||
if (err != EINPROGRESS) {
|
||||
goto cleanup;
|
||||
}
|
||||
/* we're in progress: little side check: test for EALREADY */
|
||||
ret = lwip_connect(sact, (struct sockaddr *)&sa_listen, sizeof(sa_listen));
|
||||
err = errno;
|
||||
fail_unless(ret == -1);
|
||||
fail_unless(err == EALREADY);
|
||||
if ((ret != -1) || (err != EALREADY)) {
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
tcpip_thread_poll_one();
|
||||
tcpip_thread_poll_one();
|
||||
tcpip_thread_poll_one();
|
||||
tcpip_thread_poll_one();
|
||||
}
|
||||
} while (ret != 0);
|
||||
fail_unless(ret == 0);
|
||||
|
||||
/* accept the server connection part */
|
||||
spass = lwip_accept(sl, NULL, NULL);
|
||||
fail_unless(spass >= 0);
|
||||
|
||||
/* write data from client */
|
||||
ret = lwip_send(sact, txbuf, sizeof(txbuf), 0);
|
||||
fail_unless(ret == sizeof(txbuf));
|
||||
|
||||
tcpip_thread_poll_one();
|
||||
tcpip_thread_poll_one();
|
||||
|
||||
/* issue RST (This is a HACK, don't try this in your own app!) */
|
||||
sact_sock = lwip_socket_dbg_get_socket(sact);
|
||||
fail_unless(sact_sock != NULL);
|
||||
if (sact_sock != NULL) {
|
||||
struct netconn *sact_conn = sact_sock->conn;
|
||||
fail_unless(sact_conn != NULL);
|
||||
if (sact_conn != NULL) {
|
||||
struct tcp_pcb *pcb = sact_conn->pcb.tcp;
|
||||
fail_unless(pcb != NULL);
|
||||
if (pcb != NULL) {
|
||||
tcp_rst(pcb, pcb->snd_nxt, pcb->rcv_nxt, &pcb->local_ip, &pcb->remote_ip,
|
||||
pcb->local_port, pcb->remote_port);
|
||||
}
|
||||
}
|
||||
}
|
||||
tcpip_thread_poll_one();
|
||||
tcpip_thread_poll_one();
|
||||
|
||||
/* expect to receive data first */
|
||||
ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
|
||||
fail_unless(ret > 0);
|
||||
tcpip_thread_poll_one();
|
||||
tcpip_thread_poll_one();
|
||||
|
||||
/* expect to receive RST indication */
|
||||
ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
|
||||
fail_unless(ret == -1);
|
||||
err = errno;
|
||||
fail_unless(err == ECONNRESET);
|
||||
tcpip_thread_poll_one();
|
||||
tcpip_thread_poll_one();
|
||||
|
||||
/* expect to receive ENOTCONN indication */
|
||||
ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
|
||||
fail_unless(ret == -1);
|
||||
err = errno;
|
||||
fail_unless(err == ENOTCONN);
|
||||
tcpip_thread_poll_one();
|
||||
tcpip_thread_poll_one();
|
||||
|
||||
/* expect to receive ENOTCONN indication */
|
||||
ret = lwip_recv(spass, rxbuf, sizeof(rxbuf), 0);
|
||||
fail_unless(ret == -1);
|
||||
err = errno;
|
||||
fail_unless(err == ENOTCONN);
|
||||
tcpip_thread_poll_one();
|
||||
tcpip_thread_poll_one();
|
||||
|
||||
cleanup:
|
||||
ret = lwip_close(sl);
|
||||
fail_unless(ret == 0);
|
||||
ret = lwip_close(sact);
|
||||
fail_unless(ret == 0);
|
||||
if (spass >= 0) {
|
||||
ret = lwip_close(spass);
|
||||
fail_unless(ret == 0);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
sockets_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_sockets_basics),
|
||||
TESTFUNC(test_sockets_allfunctions_basic),
|
||||
TESTFUNC(test_sockets_msgapis),
|
||||
TESTFUNC(test_sockets_select),
|
||||
TESTFUNC(test_sockets_recv_after_rst),
|
||||
};
|
||||
return create_suite("SOCKETS", tests, sizeof(tests)/sizeof(testfunc), sockets_setup, sockets_teardown);
|
||||
}
|
||||
|
||||
#else /* LWIP_SOCKET */
|
||||
|
||||
Suite *
|
||||
sockets_suite(void)
|
||||
{
|
||||
return create_suite("SOCKETS", NULL, 0, NULL, NULL);
|
||||
}
|
||||
#endif /* LWIP_SOCKET */
|
||||
8
lwip/lwip-2.2.1/test/unit/api/test_sockets.h
Normal file
8
lwip/lwip-2.2.1/test/unit/api/test_sockets.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_SOCKETS_H
|
||||
#define LWIP_HDR_TEST_SOCKETS_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *sockets_suite(void);
|
||||
|
||||
#endif
|
||||
387
lwip/lwip-2.2.1/test/unit/arch/sys_arch.c
Normal file
387
lwip/lwip-2.2.1/test/unit/arch/sys_arch.c
Normal file
@ -0,0 +1,387 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Simon Goldschmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Simon Goldschmidt
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <lwip/opt.h>
|
||||
#include <lwip/arch.h>
|
||||
#if !NO_SYS
|
||||
#include "sys_arch.h"
|
||||
#endif
|
||||
#include <lwip/stats.h>
|
||||
#include <lwip/debug.h>
|
||||
#include <lwip/sys.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
u32_t lwip_sys_now;
|
||||
|
||||
u32_t
|
||||
sys_jiffies(void)
|
||||
{
|
||||
return lwip_sys_now;
|
||||
}
|
||||
|
||||
u32_t
|
||||
sys_now(void)
|
||||
{
|
||||
return lwip_sys_now;
|
||||
}
|
||||
|
||||
void
|
||||
sys_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
#if !NO_SYS
|
||||
|
||||
test_sys_arch_waiting_fn the_waiting_fn;
|
||||
|
||||
void
|
||||
test_sys_arch_wait_callback(test_sys_arch_waiting_fn waiting_fn)
|
||||
{
|
||||
the_waiting_fn = waiting_fn;
|
||||
}
|
||||
|
||||
err_t
|
||||
sys_sem_new(sys_sem_t *sem, u8_t count)
|
||||
{
|
||||
LWIP_ASSERT("sem != NULL", sem != NULL);
|
||||
*sem = count + 1;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
sys_sem_free(sys_sem_t *sem)
|
||||
{
|
||||
LWIP_ASSERT("sem != NULL", sem != NULL);
|
||||
*sem = 0;
|
||||
}
|
||||
|
||||
void
|
||||
sys_sem_set_invalid(sys_sem_t *sem)
|
||||
{
|
||||
LWIP_ASSERT("sem != NULL", sem != NULL);
|
||||
*sem = 0;
|
||||
}
|
||||
|
||||
/* semaphores are 1-based because RAM is initialized as 0, which would be valid */
|
||||
u32_t
|
||||
sys_arch_sem_wait(sys_sem_t *sem, u32_t timeout)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
LWIP_ASSERT("sem != NULL", sem != NULL);
|
||||
LWIP_ASSERT("*sem > 0", *sem > 0);
|
||||
if (*sem == 1) {
|
||||
/* need to wait */
|
||||
if(!timeout)
|
||||
{
|
||||
/* wait infinite */
|
||||
LWIP_ASSERT("cannot wait without waiting callback", the_waiting_fn != NULL);
|
||||
do {
|
||||
int expectSomething = the_waiting_fn(sem, NULL);
|
||||
LWIP_ASSERT("*sem > 0", *sem > 0);
|
||||
LWIP_ASSERT("expecting a semaphore count but it's 0", !expectSomething || (*sem > 1));
|
||||
ret++;
|
||||
if (ret == SYS_ARCH_TIMEOUT) {
|
||||
ret--;
|
||||
}
|
||||
} while(*sem == 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (the_waiting_fn) {
|
||||
int expectSomething = the_waiting_fn(sem, NULL);
|
||||
LWIP_ASSERT("expecting a semaphore count but it's 0", !expectSomething || (*sem > 1));
|
||||
}
|
||||
LWIP_ASSERT("*sem > 0", *sem > 0);
|
||||
if (*sem == 1) {
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
LWIP_ASSERT("*sem > 0", *sem > 0);
|
||||
(*sem)--;
|
||||
LWIP_ASSERT("*sem > 0", *sem > 0);
|
||||
/* return the time we waited for the sem */
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
sys_sem_signal(sys_sem_t *sem)
|
||||
{
|
||||
LWIP_ASSERT("sem != NULL", sem != NULL);
|
||||
LWIP_ASSERT("*sem > 0", *sem > 0);
|
||||
(*sem)++;
|
||||
LWIP_ASSERT("*sem > 0", *sem > 0);
|
||||
}
|
||||
|
||||
err_t
|
||||
sys_mutex_new(sys_mutex_t *mutex)
|
||||
{
|
||||
LWIP_ASSERT("mutex != NULL", mutex != NULL);
|
||||
*mutex = 1; /* 1 allocated */
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
sys_mutex_free(sys_mutex_t *mutex)
|
||||
{
|
||||
/* parameter check */
|
||||
LWIP_ASSERT("mutex != NULL", mutex != NULL);
|
||||
LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
|
||||
*mutex = 0;
|
||||
}
|
||||
|
||||
void
|
||||
sys_mutex_set_invalid(sys_mutex_t *mutex)
|
||||
{
|
||||
LWIP_ASSERT("mutex != NULL", mutex != NULL);
|
||||
*mutex = 0;
|
||||
}
|
||||
|
||||
void
|
||||
sys_mutex_lock(sys_mutex_t *mutex)
|
||||
{
|
||||
/* nothing to do, no multithreading supported */
|
||||
LWIP_ASSERT("mutex != NULL", mutex != NULL);
|
||||
/* check that the mutext is valid and unlocked (no nested locking) */
|
||||
LWIP_ASSERT("*mutex >= 1", *mutex == 1);
|
||||
/* we count up just to check the correct pairing of lock/unlock */
|
||||
(*mutex)++;
|
||||
LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
|
||||
}
|
||||
|
||||
void
|
||||
sys_mutex_unlock(sys_mutex_t *mutex)
|
||||
{
|
||||
/* nothing to do, no multithreading supported */
|
||||
LWIP_ASSERT("mutex != NULL", mutex != NULL);
|
||||
LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
|
||||
/* we count down just to check the correct pairing of lock/unlock */
|
||||
(*mutex)--;
|
||||
LWIP_ASSERT("*mutex >= 1", *mutex >= 1);
|
||||
}
|
||||
|
||||
|
||||
sys_thread_t
|
||||
sys_thread_new(const char *name, lwip_thread_fn function, void *arg, int stacksize, int prio)
|
||||
{
|
||||
LWIP_UNUSED_ARG(name);
|
||||
LWIP_UNUSED_ARG(function);
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_UNUSED_ARG(stacksize);
|
||||
LWIP_UNUSED_ARG(prio);
|
||||
/* threads not supported */
|
||||
return 0;
|
||||
}
|
||||
|
||||
err_t
|
||||
sys_mbox_new(sys_mbox_t *mbox, int size)
|
||||
{
|
||||
int mboxsize = size;
|
||||
LWIP_ASSERT("mbox != NULL", mbox != NULL);
|
||||
LWIP_ASSERT("size >= 0", size >= 0);
|
||||
if (size == 0) {
|
||||
mboxsize = 1024;
|
||||
}
|
||||
mbox->head = mbox->tail = 0;
|
||||
mbox->sem = mbox; /* just point to something for sys_mbox_valid() */
|
||||
mbox->q_mem = (void**)malloc(sizeof(void*)*mboxsize);
|
||||
mbox->size = mboxsize;
|
||||
mbox->used = 0;
|
||||
|
||||
memset(mbox->q_mem, 0, sizeof(void*)*mboxsize);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void
|
||||
sys_mbox_free(sys_mbox_t *mbox)
|
||||
{
|
||||
/* parameter check */
|
||||
LWIP_ASSERT("mbox != NULL", mbox != NULL);
|
||||
LWIP_ASSERT("mbox->sem != NULL", mbox->sem != NULL);
|
||||
LWIP_ASSERT("mbox->sem == mbox", mbox->sem == mbox);
|
||||
LWIP_ASSERT("mbox->q_mem != NULL", mbox->q_mem != NULL);
|
||||
mbox->sem = NULL;
|
||||
free(mbox->q_mem);
|
||||
mbox->q_mem = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
sys_mbox_set_invalid(sys_mbox_t *mbox)
|
||||
{
|
||||
LWIP_ASSERT("mbox != NULL", mbox != NULL);
|
||||
LWIP_ASSERT("mbox->q_mem == NULL", mbox->q_mem == NULL);
|
||||
mbox->sem = NULL;
|
||||
mbox->q_mem = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
sys_mbox_post(sys_mbox_t *q, void *msg)
|
||||
{
|
||||
LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
|
||||
LWIP_ASSERT("q->sem == q", q->sem == q);
|
||||
LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
|
||||
LWIP_ASSERT("q->used >= 0", q->used >= 0);
|
||||
LWIP_ASSERT("q->size > 0", q->size > 0);
|
||||
|
||||
LWIP_ASSERT("mbox already full", q->used < q->size);
|
||||
|
||||
q->q_mem[q->head] = msg;
|
||||
q->head++;
|
||||
if (q->head >= (unsigned int)q->size) {
|
||||
q->head = 0;
|
||||
}
|
||||
LWIP_ASSERT("mbox is full!", q->head != q->tail);
|
||||
q->used++;
|
||||
}
|
||||
|
||||
err_t
|
||||
sys_mbox_trypost(sys_mbox_t *q, void *msg)
|
||||
{
|
||||
LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
|
||||
LWIP_ASSERT("q->sem == q", q->sem == q);
|
||||
LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
|
||||
LWIP_ASSERT("q->used >= 0", q->used >= 0);
|
||||
LWIP_ASSERT("q->size > 0", q->size > 0);
|
||||
LWIP_ASSERT("q->used <= q->size", q->used <= q->size);
|
||||
|
||||
if (q->used == q->size) {
|
||||
return ERR_MEM;
|
||||
}
|
||||
sys_mbox_post(q, msg);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
err_t
|
||||
sys_mbox_trypost_fromisr(sys_mbox_t *q, void *msg)
|
||||
{
|
||||
return sys_mbox_trypost(q, msg);
|
||||
}
|
||||
|
||||
u32_t
|
||||
sys_arch_mbox_fetch(sys_mbox_t *q, void **msg, u32_t timeout)
|
||||
{
|
||||
u32_t ret = 0;
|
||||
u32_t ret2;
|
||||
LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
|
||||
LWIP_ASSERT("q->sem == q", q->sem == q);
|
||||
LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
|
||||
LWIP_ASSERT("q->used >= 0", q->used >= 0);
|
||||
LWIP_ASSERT("q->size > 0", q->size > 0);
|
||||
|
||||
if (q->used == 0) {
|
||||
/* need to wait */
|
||||
/* need to wait */
|
||||
if(!timeout)
|
||||
{
|
||||
/* wait infinite */
|
||||
LWIP_ASSERT("cannot wait without waiting callback", the_waiting_fn != NULL);
|
||||
do {
|
||||
int expectSomething = the_waiting_fn(NULL, q);
|
||||
LWIP_ASSERT("q->used >= 0", q->used >= 0);
|
||||
LWIP_ASSERT("expecting item available but it's 0", !expectSomething || (q->used > 0));
|
||||
ret++;
|
||||
if (ret == SYS_ARCH_TIMEOUT) {
|
||||
ret--;
|
||||
}
|
||||
} while(q->used == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (the_waiting_fn) {
|
||||
int expectSomething = the_waiting_fn(NULL, q);
|
||||
LWIP_ASSERT("expecting item available count but it's 0", !expectSomething || (q->used > 0));
|
||||
}
|
||||
LWIP_ASSERT("q->used >= 0", q->used >= 0);
|
||||
if (q->used == 0) {
|
||||
if(msg) {
|
||||
*msg = NULL;
|
||||
}
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
LWIP_ASSERT("q->used > 0", q->used > 0);
|
||||
ret2 = sys_arch_mbox_tryfetch(q, msg);
|
||||
LWIP_ASSERT("got no message", ret2 == 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32_t
|
||||
sys_arch_mbox_tryfetch(sys_mbox_t *q, void **msg)
|
||||
{
|
||||
LWIP_ASSERT("q != SYS_MBOX_NULL", q != SYS_MBOX_NULL);
|
||||
LWIP_ASSERT("q->sem == q", q->sem == q);
|
||||
LWIP_ASSERT("q->q_mem != NULL", q->q_mem != NULL);
|
||||
LWIP_ASSERT("q->used >= 0", q->used >= 0);
|
||||
LWIP_ASSERT("q->size > 0", q->size > 0);
|
||||
|
||||
if (!q->used) {
|
||||
return SYS_ARCH_TIMEOUT;
|
||||
}
|
||||
if(msg) {
|
||||
*msg = q->q_mem[q->tail];
|
||||
}
|
||||
|
||||
q->tail++;
|
||||
if (q->tail >= (unsigned int)q->size) {
|
||||
q->tail = 0;
|
||||
}
|
||||
q->used--;
|
||||
LWIP_ASSERT("q->used >= 0", q->used >= 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if LWIP_NETCONN_SEM_PER_THREAD
|
||||
/* Simple implementation of this: unit tests only support one thread */
|
||||
static sys_sem_t global_netconn_sem;
|
||||
|
||||
sys_sem_t* sys_arch_netconn_sem_get(void)
|
||||
{
|
||||
return &global_netconn_sem;
|
||||
}
|
||||
|
||||
void sys_arch_netconn_sem_alloc(void)
|
||||
{
|
||||
sys_sem_new(&global_netconn_sem, 0);
|
||||
}
|
||||
|
||||
void sys_arch_netconn_sem_free(void)
|
||||
{
|
||||
sys_sem_free(&global_netconn_sem);
|
||||
}
|
||||
#endif /* LWIP_NETCONN_SEM_PER_THREAD */
|
||||
|
||||
#endif /* !NO_SYS */
|
||||
79
lwip/lwip-2.2.1/test/unit/arch/sys_arch.h
Normal file
79
lwip/lwip-2.2.1/test/unit/arch/sys_arch.h
Normal file
@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright (c) 2017 Simon Goldschmidt
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Simon Goldschmidt
|
||||
*
|
||||
*/
|
||||
#ifndef LWIP_HDR_TEST_SYS_ARCH_H
|
||||
#define LWIP_HDR_TEST_SYS_ARCH_H
|
||||
|
||||
typedef int sys_sem_t;
|
||||
#define sys_sem_valid(sema) ((sema) != NULL)
|
||||
|
||||
typedef int sys_mutex_t;
|
||||
#define sys_mutex_valid(mutex) (((mutex) != NULL)
|
||||
|
||||
struct lwip_mbox {
|
||||
void* sem;
|
||||
void** q_mem;
|
||||
unsigned int head, tail;
|
||||
int size;
|
||||
int used;
|
||||
};
|
||||
typedef struct lwip_mbox sys_mbox_t;
|
||||
#define SYS_MBOX_NULL NULL
|
||||
#define sys_mbox_valid(mbox) ((mbox != NULL) && ((mbox)->sem != NULL) && ((mbox)->sem != (void*)-1))
|
||||
#define sys_mbox_valid_val(mbox) (((mbox).sem != NULL) && ((mbox).sem != (void*)-1))
|
||||
|
||||
/* DWORD (thread id) is used for sys_thread_t but we won't include windows.h */
|
||||
typedef u32_t sys_thread_t;
|
||||
|
||||
#define SYS_ARCH_DECL_PROTECT(lev)
|
||||
#define SYS_ARCH_PROTECT(lev)
|
||||
#define SYS_ARCH_UNPROTECT(lev)
|
||||
|
||||
/* to implement doing something while blocking on an mbox or semaphore:
|
||||
* pass a function to test_sys_arch_wait_callback() that returns
|
||||
* '0' if waiting again and
|
||||
* '1' if now there should be something to do (used for asserting)
|
||||
*/
|
||||
typedef int (*test_sys_arch_waiting_fn)(sys_sem_t* wait_sem, sys_mbox_t* wait_mbox);
|
||||
void test_sys_arch_wait_callback(test_sys_arch_waiting_fn waiting_fn);
|
||||
|
||||
/* current time */
|
||||
extern u32_t lwip_sys_now;
|
||||
|
||||
sys_sem_t* sys_arch_netconn_sem_get(void);
|
||||
void sys_arch_netconn_sem_alloc(void);
|
||||
void sys_arch_netconn_sem_free(void);
|
||||
#define LWIP_NETCONN_THREAD_SEM_GET() sys_arch_netconn_sem_get()
|
||||
#define LWIP_NETCONN_THREAD_SEM_ALLOC() sys_arch_netconn_sem_alloc()
|
||||
#define LWIP_NETCONN_THREAD_SEM_FREE() sys_arch_netconn_sem_free()
|
||||
|
||||
#endif /* LWIP_HDR_TEST_SYS_ARCH_H */
|
||||
|
||||
84
lwip/lwip-2.2.1/test/unit/core/test_def.c
Normal file
84
lwip/lwip-2.2.1/test/unit/core/test_def.c
Normal file
@ -0,0 +1,84 @@
|
||||
#include "test_def.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
|
||||
#define MAGIC_UNTOUCHED_BYTE 0x7a
|
||||
#define TEST_BUFSIZE 32
|
||||
#define GUARD_SIZE 4
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
def_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
def_teardown(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
def_check_range_untouched(const char *buf, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
fail_unless(buf[i] == (char)MAGIC_UNTOUCHED_BYTE);
|
||||
}
|
||||
}
|
||||
|
||||
static void test_def_itoa(int number, const char *expected)
|
||||
{
|
||||
char buf[TEST_BUFSIZE];
|
||||
char *test_buf = &buf[GUARD_SIZE];
|
||||
|
||||
size_t exp_len = strlen(expected);
|
||||
fail_unless(exp_len + 4 < (TEST_BUFSIZE - (2 * GUARD_SIZE)));
|
||||
|
||||
memset(buf, MAGIC_UNTOUCHED_BYTE, sizeof(buf));
|
||||
lwip_itoa(test_buf, exp_len + 1, number);
|
||||
def_check_range_untouched(buf, GUARD_SIZE);
|
||||
fail_unless(test_buf[exp_len] == 0);
|
||||
fail_unless(!memcmp(test_buf, expected, exp_len));
|
||||
def_check_range_untouched(&test_buf[exp_len + 1], TEST_BUFSIZE - GUARD_SIZE - exp_len - 1);
|
||||
|
||||
/* check with too small buffer */
|
||||
memset(buf, MAGIC_UNTOUCHED_BYTE, sizeof(buf));
|
||||
lwip_itoa(test_buf, exp_len, number);
|
||||
def_check_range_untouched(buf, GUARD_SIZE);
|
||||
def_check_range_untouched(&test_buf[exp_len + 1], TEST_BUFSIZE - GUARD_SIZE - exp_len - 1);
|
||||
|
||||
/* check with too large buffer */
|
||||
memset(buf, MAGIC_UNTOUCHED_BYTE, sizeof(buf));
|
||||
lwip_itoa(test_buf, exp_len + 4, number);
|
||||
def_check_range_untouched(buf, GUARD_SIZE);
|
||||
fail_unless(test_buf[exp_len] == 0);
|
||||
fail_unless(!memcmp(test_buf, expected, exp_len));
|
||||
def_check_range_untouched(&test_buf[exp_len + 4], TEST_BUFSIZE - GUARD_SIZE - exp_len - 4);
|
||||
}
|
||||
|
||||
START_TEST(test_def_lwip_itoa)
|
||||
{
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
test_def_itoa(0, "0");
|
||||
test_def_itoa(1, "1");
|
||||
test_def_itoa(-1, "-1");
|
||||
test_def_itoa(15, "15");
|
||||
test_def_itoa(-15, "-15");
|
||||
test_def_itoa(156, "156");
|
||||
test_def_itoa(1192, "1192");
|
||||
test_def_itoa(-156, "-156");
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
def_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_def_lwip_itoa)
|
||||
};
|
||||
return create_suite("DEF", tests, sizeof(tests)/sizeof(testfunc), def_setup, def_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/core/test_def.h
Normal file
8
lwip/lwip-2.2.1/test/unit/core/test_def.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_DEF_H
|
||||
#define LWIP_HDR_TEST_DEF_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *def_suite(void);
|
||||
|
||||
#endif
|
||||
52
lwip/lwip-2.2.1/test/unit/core/test_dns.c
Normal file
52
lwip/lwip-2.2.1/test/unit/core/test_dns.c
Normal file
@ -0,0 +1,52 @@
|
||||
#include "test_dns.h"
|
||||
|
||||
#include "lwip/dns.h"
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
dns_setup(void)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
dns_teardown(void)
|
||||
{
|
||||
}
|
||||
|
||||
/* Test functions */
|
||||
|
||||
START_TEST(test_dns_set_get_server)
|
||||
{
|
||||
int n;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
for (n = 0; n < 256; n++) {
|
||||
u8_t i = (u8_t)n;
|
||||
ip_addr_t server;
|
||||
/* Should return a zeroed address for any index */
|
||||
fail_unless(dns_getserver(i));
|
||||
fail_unless(ip_addr_isany(dns_getserver(i)));
|
||||
|
||||
/* Should accept setting address for any index, and ignore if out of range */
|
||||
IP_ADDR4(&server, 10, 0, 0, i);
|
||||
dns_setserver(i, &server);
|
||||
fail_unless(dns_getserver(i));
|
||||
if (i < DNS_MAX_SERVERS) {
|
||||
fail_unless(ip_addr_eq(dns_getserver(i), &server) == 1);
|
||||
} else {
|
||||
fail_unless(ip_addr_isany(dns_getserver(i)));
|
||||
}
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
dns_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_dns_set_get_server)
|
||||
};
|
||||
return create_suite("DNS", tests, sizeof(tests)/sizeof(testfunc), dns_setup, dns_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/core/test_dns.h
Normal file
8
lwip/lwip-2.2.1/test/unit/core/test_dns.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_DNS_H
|
||||
#define LWIP_HDR_TEST_DNS_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *dns_suite(void);
|
||||
|
||||
#endif
|
||||
221
lwip/lwip-2.2.1/test/unit/core/test_mem.c
Normal file
221
lwip/lwip-2.2.1/test/unit/core/test_mem.c
Normal file
@ -0,0 +1,221 @@
|
||||
#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
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
mem_setup(void)
|
||||
{
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void
|
||||
mem_teardown(void)
|
||||
{
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
|
||||
/* 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);
|
||||
|
||||
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
|
||||
|
||||
static void malloc_keep_x(int x, int num, int size, int freestep)
|
||||
{
|
||||
int i;
|
||||
void* p[16];
|
||||
LWIP_ASSERT("invalid size", size >= 0 && size < (mem_size_t)-1);
|
||||
memset(p, 0, sizeof(p));
|
||||
for(i = 0; i < num && i < 16; i++) {
|
||||
p[i] = mem_malloc((mem_size_t)size);
|
||||
fail_unless(p[i] != NULL);
|
||||
}
|
||||
for(i = 0; i < num && i < 16; i += freestep) {
|
||||
if (i == x) {
|
||||
continue;
|
||||
}
|
||||
mem_free(p[i]);
|
||||
p[i] = NULL;
|
||||
}
|
||||
for(i = 0; i < num && i < 16; i++) {
|
||||
if (i == x) {
|
||||
continue;
|
||||
}
|
||||
if (p[i] != NULL) {
|
||||
mem_free(p[i]);
|
||||
p[i] = NULL;
|
||||
}
|
||||
}
|
||||
fail_unless(p[x] != NULL);
|
||||
mem_free(p[x]);
|
||||
}
|
||||
|
||||
START_TEST(test_mem_random)
|
||||
{
|
||||
const int num = 16;
|
||||
int x;
|
||||
int size;
|
||||
int freestep;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
fail_unless(lwip_stats.mem.used == 0);
|
||||
|
||||
for (x = 0; x < num; x++) {
|
||||
for (size = 1; size < 32; size++) {
|
||||
for (freestep = 1; freestep <= 3; freestep++) {
|
||||
fail_unless(lwip_stats.mem.used == 0);
|
||||
malloc_keep_x(x, num, size, freestep);
|
||||
fail_unless(lwip_stats.mem.used == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_mem_invalid_free)
|
||||
{
|
||||
u8_t *ptr, *ptr_low, *ptr_high;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
fail_unless(lwip_stats.mem.used == 0);
|
||||
fail_unless(lwip_stats.mem.illegal == 0);
|
||||
|
||||
ptr = (u8_t *)mem_malloc(1);
|
||||
fail_unless(ptr != NULL);
|
||||
fail_unless(lwip_stats.mem.used != 0);
|
||||
|
||||
ptr_low = ptr - 0x10;
|
||||
mem_free(ptr_low);
|
||||
fail_unless(lwip_stats.mem.illegal == 1);
|
||||
lwip_stats.mem.illegal = 0;
|
||||
|
||||
ptr_high = ptr + (MEM_SIZE * 2);
|
||||
mem_free(ptr_high);
|
||||
fail_unless(lwip_stats.mem.illegal == 1);
|
||||
lwip_stats.mem.illegal = 0;
|
||||
|
||||
mem_free(ptr);
|
||||
fail_unless(lwip_stats.mem.illegal == 0);
|
||||
fail_unless(lwip_stats.mem.used == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_mem_double_free)
|
||||
{
|
||||
u8_t *ptr1b, *ptr1, *ptr2, *ptr3;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
fail_unless(lwip_stats.mem.used == 0);
|
||||
fail_unless(lwip_stats.mem.illegal == 0);
|
||||
|
||||
ptr1 = (u8_t *)mem_malloc(1);
|
||||
fail_unless(ptr1 != NULL);
|
||||
fail_unless(lwip_stats.mem.used != 0);
|
||||
|
||||
ptr2 = (u8_t *)mem_malloc(1);
|
||||
fail_unless(ptr2 != NULL);
|
||||
fail_unless(lwip_stats.mem.used != 0);
|
||||
|
||||
ptr3 = (u8_t *)mem_malloc(1);
|
||||
fail_unless(ptr3 != NULL);
|
||||
fail_unless(lwip_stats.mem.used != 0);
|
||||
|
||||
/* free the middle mem */
|
||||
mem_free(ptr2);
|
||||
fail_unless(lwip_stats.mem.illegal == 0);
|
||||
|
||||
/* double-free of middle mem: should fail */
|
||||
mem_free(ptr2);
|
||||
fail_unless(lwip_stats.mem.illegal == 1);
|
||||
lwip_stats.mem.illegal = 0;
|
||||
|
||||
/* free upper memory and try again */
|
||||
mem_free(ptr3);
|
||||
fail_unless(lwip_stats.mem.illegal == 0);
|
||||
|
||||
mem_free(ptr2);
|
||||
fail_unless(lwip_stats.mem.illegal == 1);
|
||||
lwip_stats.mem.illegal = 0;
|
||||
|
||||
/* free lower memory and try again */
|
||||
mem_free(ptr1);
|
||||
fail_unless(lwip_stats.mem.illegal == 0);
|
||||
fail_unless(lwip_stats.mem.used == 0);
|
||||
|
||||
mem_free(ptr2);
|
||||
fail_unless(lwip_stats.mem.illegal == 1);
|
||||
fail_unless(lwip_stats.mem.used == 0);
|
||||
lwip_stats.mem.illegal = 0;
|
||||
|
||||
/* reallocate lowest memory, now overlapping already freed ptr2 */
|
||||
#ifndef MIN_SIZE
|
||||
#define MIN_SIZE 12
|
||||
#endif
|
||||
ptr1b = (u8_t *)mem_malloc(MIN_SIZE * 2);
|
||||
fail_unless(ptr1b != NULL);
|
||||
fail_unless(lwip_stats.mem.used != 0);
|
||||
|
||||
mem_free(ptr2);
|
||||
fail_unless(lwip_stats.mem.illegal == 1);
|
||||
lwip_stats.mem.illegal = 0;
|
||||
|
||||
memset(ptr1b, 1, MIN_SIZE * 2);
|
||||
|
||||
mem_free(ptr2);
|
||||
fail_unless(lwip_stats.mem.illegal == 1);
|
||||
lwip_stats.mem.illegal = 0;
|
||||
|
||||
mem_free(ptr1b);
|
||||
fail_unless(lwip_stats.mem.illegal == 0);
|
||||
fail_unless(lwip_stats.mem.used == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
mem_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_mem_one),
|
||||
TESTFUNC(test_mem_random),
|
||||
TESTFUNC(test_mem_invalid_free),
|
||||
TESTFUNC(test_mem_double_free)
|
||||
};
|
||||
return create_suite("MEM", tests, sizeof(tests)/sizeof(testfunc), mem_setup, mem_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/core/test_mem.h
Normal file
8
lwip/lwip-2.2.1/test/unit/core/test_mem.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_MEM_H
|
||||
#define LWIP_HDR_TEST_MEM_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *mem_suite(void);
|
||||
|
||||
#endif
|
||||
285
lwip/lwip-2.2.1/test/unit/core/test_netif.c
Normal file
285
lwip/lwip-2.2.1/test/unit/core/test_netif.c
Normal file
@ -0,0 +1,285 @@
|
||||
#include "test_netif.h"
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "netif/ethernet.h"
|
||||
|
||||
#if !LWIP_NETIF_EXT_STATUS_CALLBACK
|
||||
#error "This tests needs LWIP_NETIF_EXT_STATUS_CALLBACK enabled"
|
||||
#endif
|
||||
|
||||
static struct netif net_test;
|
||||
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
netif_setup(void)
|
||||
{
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void
|
||||
netif_teardown(void)
|
||||
{
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
/* test helper functions */
|
||||
|
||||
static err_t
|
||||
testif_tx_func(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
LWIP_UNUSED_ARG(netif);
|
||||
LWIP_UNUSED_ARG(p);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t
|
||||
testif_init(struct netif *netif)
|
||||
{
|
||||
netif->name[0] = 'c';
|
||||
netif->name[1] = 'h';
|
||||
netif->output = etharp_output;
|
||||
netif->linkoutput = testif_tx_func;
|
||||
netif->mtu = 1500;
|
||||
netif->hwaddr_len = 6;
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_ETHERNET | NETIF_FLAG_IGMP | NETIF_FLAG_MLD6;
|
||||
|
||||
netif->hwaddr[0] = 0x02;
|
||||
netif->hwaddr[1] = 0x03;
|
||||
netif->hwaddr[2] = 0x04;
|
||||
netif->hwaddr[3] = 0x05;
|
||||
netif->hwaddr[4] = 0x06;
|
||||
netif->hwaddr[5] = 0x07;
|
||||
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
#define MAX_NSC_REASON_IDX 10
|
||||
static netif_nsc_reason_t expected_reasons;
|
||||
static int callback_ctr;
|
||||
|
||||
static int dummy_active;
|
||||
|
||||
static void
|
||||
test_netif_ext_callback_dummy(struct netif* netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t* args)
|
||||
{
|
||||
LWIP_UNUSED_ARG(netif);
|
||||
LWIP_UNUSED_ARG(reason);
|
||||
LWIP_UNUSED_ARG(args);
|
||||
|
||||
fail_unless(dummy_active);
|
||||
}
|
||||
|
||||
static void
|
||||
test_netif_ext_callback(struct netif* netif, netif_nsc_reason_t reason, const netif_ext_callback_args_t* args)
|
||||
{
|
||||
LWIP_UNUSED_ARG(args); /* @todo */
|
||||
callback_ctr++;
|
||||
|
||||
fail_unless(netif == &net_test);
|
||||
|
||||
fail_unless(expected_reasons == reason);
|
||||
}
|
||||
|
||||
/* Test functions */
|
||||
|
||||
NETIF_DECLARE_EXT_CALLBACK(netif_callback_1)
|
||||
NETIF_DECLARE_EXT_CALLBACK(netif_callback_2)
|
||||
NETIF_DECLARE_EXT_CALLBACK(netif_callback_3)
|
||||
|
||||
START_TEST(test_netif_extcallbacks)
|
||||
{
|
||||
ip4_addr_t addr;
|
||||
ip4_addr_t netmask;
|
||||
ip4_addr_t gw;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
IP4_ADDR(&addr, 0, 0, 0, 0);
|
||||
IP4_ADDR(&netmask, 0, 0, 0, 0);
|
||||
IP4_ADDR(&gw, 0, 0, 0, 0);
|
||||
|
||||
netif_add_ext_callback(&netif_callback_3, test_netif_ext_callback_dummy);
|
||||
netif_add_ext_callback(&netif_callback_2, test_netif_ext_callback);
|
||||
netif_add_ext_callback(&netif_callback_1, test_netif_ext_callback_dummy);
|
||||
|
||||
dummy_active = 1;
|
||||
|
||||
/* positive tests: check that single events come as expected */
|
||||
|
||||
expected_reasons = LWIP_NSC_NETIF_ADDED;
|
||||
callback_ctr = 0;
|
||||
netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
expected_reasons = LWIP_NSC_LINK_CHANGED;
|
||||
callback_ctr = 0;
|
||||
netif_set_link_up(&net_test);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
expected_reasons = LWIP_NSC_STATUS_CHANGED;
|
||||
callback_ctr = 0;
|
||||
netif_set_up(&net_test);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
IP4_ADDR(&addr, 1, 2, 3, 4);
|
||||
expected_reasons = LWIP_NSC_IPV4_ADDRESS_CHANGED;
|
||||
callback_ctr = 0;
|
||||
netif_set_ipaddr(&net_test, &addr);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
IP4_ADDR(&netmask, 255, 255, 255, 0);
|
||||
expected_reasons = LWIP_NSC_IPV4_NETMASK_CHANGED;
|
||||
callback_ctr = 0;
|
||||
netif_set_netmask(&net_test, &netmask);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
IP4_ADDR(&gw, 1, 2, 3, 254);
|
||||
expected_reasons = LWIP_NSC_IPV4_GATEWAY_CHANGED;
|
||||
callback_ctr = 0;
|
||||
netif_set_gw(&net_test, &gw);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
IP4_ADDR(&addr, 0, 0, 0, 0);
|
||||
expected_reasons = LWIP_NSC_IPV4_ADDRESS_CHANGED;
|
||||
callback_ctr = 0;
|
||||
netif_set_ipaddr(&net_test, &addr);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
IP4_ADDR(&netmask, 0, 0, 0, 0);
|
||||
expected_reasons = LWIP_NSC_IPV4_NETMASK_CHANGED;
|
||||
callback_ctr = 0;
|
||||
netif_set_netmask(&net_test, &netmask);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
IP4_ADDR(&gw, 0, 0, 0, 0);
|
||||
expected_reasons = LWIP_NSC_IPV4_GATEWAY_CHANGED;
|
||||
callback_ctr = 0;
|
||||
netif_set_gw(&net_test, &gw);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
/* check for multi-events (only one combined callback expected) */
|
||||
|
||||
IP4_ADDR(&addr, 1, 2, 3, 4);
|
||||
IP4_ADDR(&netmask, 255, 255, 255, 0);
|
||||
IP4_ADDR(&gw, 1, 2, 3, 254);
|
||||
expected_reasons = (netif_nsc_reason_t)(LWIP_NSC_IPV4_ADDRESS_CHANGED | LWIP_NSC_IPV4_NETMASK_CHANGED |
|
||||
LWIP_NSC_IPV4_GATEWAY_CHANGED | LWIP_NSC_IPV4_SETTINGS_CHANGED |
|
||||
LWIP_NSC_IPV4_ADDR_VALID);
|
||||
callback_ctr = 0;
|
||||
netif_set_addr(&net_test, &addr, &netmask, &gw);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
/* check that for no-change, no callback is expected */
|
||||
expected_reasons = LWIP_NSC_NONE;
|
||||
callback_ctr = 0;
|
||||
netif_set_ipaddr(&net_test, &addr);
|
||||
fail_unless(callback_ctr == 0);
|
||||
|
||||
netif_set_netmask(&net_test, &netmask);
|
||||
callback_ctr = 0;
|
||||
fail_unless(callback_ctr == 0);
|
||||
|
||||
callback_ctr = 0;
|
||||
netif_set_gw(&net_test, &gw);
|
||||
fail_unless(callback_ctr == 0);
|
||||
|
||||
/* netif_set_addr() always issues at least LWIP_NSC_IPV4_ADDR_VALID */
|
||||
expected_reasons = LWIP_NSC_IPV4_ADDR_VALID;
|
||||
callback_ctr = 0;
|
||||
netif_set_addr(&net_test, &addr, &netmask, &gw);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
/* check for single-events */
|
||||
IP4_ADDR(&addr, 1, 2, 3, 5);
|
||||
expected_reasons = (netif_nsc_reason_t)(LWIP_NSC_IPV4_ADDRESS_CHANGED | LWIP_NSC_IPV4_SETTINGS_CHANGED |
|
||||
LWIP_NSC_IPV4_ADDR_VALID);
|
||||
callback_ctr = 0;
|
||||
netif_set_addr(&net_test, &addr, &netmask, &gw);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
expected_reasons = LWIP_NSC_STATUS_CHANGED;
|
||||
callback_ctr = 0;
|
||||
netif_set_down(&net_test);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
expected_reasons = LWIP_NSC_NETIF_REMOVED;
|
||||
callback_ctr = 0;
|
||||
netif_remove(&net_test);
|
||||
fail_unless(callback_ctr == 1);
|
||||
|
||||
expected_reasons = LWIP_NSC_NONE;
|
||||
|
||||
netif_remove_ext_callback(&netif_callback_2);
|
||||
netif_remove_ext_callback(&netif_callback_3);
|
||||
netif_remove_ext_callback(&netif_callback_1);
|
||||
dummy_active = 0;
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_netif_flag_set)
|
||||
{
|
||||
ip4_addr_t addr;
|
||||
ip4_addr_t netmask;
|
||||
ip4_addr_t gw;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
IP4_ADDR(&addr, 0, 0, 0, 0);
|
||||
IP4_ADDR(&netmask, 0, 0, 0, 0);
|
||||
IP4_ADDR(&gw, 0, 0, 0, 0);
|
||||
|
||||
netif_add(&net_test, &addr, &netmask, &gw, &net_test, testif_init, ethernet_input);
|
||||
|
||||
fail_if(netif_is_flag_set(&net_test, NETIF_FLAG_UP));
|
||||
fail_unless(netif_is_flag_set(&net_test, NETIF_FLAG_BROADCAST));
|
||||
fail_if(netif_is_flag_set(&net_test, NETIF_FLAG_LINK_UP));
|
||||
fail_unless(netif_is_flag_set(&net_test, NETIF_FLAG_ETHARP));
|
||||
fail_unless(netif_is_flag_set(&net_test, NETIF_FLAG_ETHERNET));
|
||||
fail_unless(netif_is_flag_set(&net_test, NETIF_FLAG_IGMP));
|
||||
fail_unless(netif_is_flag_set(&net_test, NETIF_FLAG_MLD6));
|
||||
|
||||
netif_remove(&net_test);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_netif_find)
|
||||
{
|
||||
struct netif net0;
|
||||
struct netif net1;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* No netifs available */
|
||||
fail_unless(netif_find("ch0") == NULL);
|
||||
|
||||
/* Add netifs with known names */
|
||||
fail_unless(netif_add_noaddr(&net0, NULL, testif_init, ethernet_input) == &net0);
|
||||
net0.num = 0;
|
||||
fail_unless(netif_add_noaddr(&net1, NULL, testif_init, ethernet_input) == &net1);
|
||||
net1.num = 1;
|
||||
|
||||
fail_unless(netif_find("ch0") == &net0);
|
||||
fail_unless(netif_find("CH0") == NULL);
|
||||
fail_unless(netif_find("ch1") == &net1);
|
||||
fail_unless(netif_find("ch3") == NULL);
|
||||
/* atoi failure is not treated as zero */
|
||||
fail_unless(netif_find("chX") == NULL);
|
||||
fail_unless(netif_find("ab0") == NULL);
|
||||
|
||||
netif_remove(&net0);
|
||||
netif_remove(&net1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
netif_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_netif_extcallbacks),
|
||||
TESTFUNC(test_netif_flag_set),
|
||||
TESTFUNC(test_netif_find)
|
||||
};
|
||||
return create_suite("NETIF", tests, sizeof(tests)/sizeof(testfunc), netif_setup, netif_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/core/test_netif.h
Normal file
8
lwip/lwip-2.2.1/test/unit/core/test_netif.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_NETIF_H
|
||||
#define LWIP_HDR_TEST_NETIF_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *netif_suite(void);
|
||||
|
||||
#endif
|
||||
371
lwip/lwip-2.2.1/test/unit/core/test_pbuf.c
Normal file
371
lwip/lwip-2.2.1/test/unit/core/test_pbuf.c
Normal file
@ -0,0 +1,371 @@
|
||||
#include "test_pbuf.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/stats.h"
|
||||
|
||||
#if !LWIP_STATS || !MEM_STATS ||!MEMP_STATS
|
||||
#error "This tests needs MEM- and MEMP-statistics enabled"
|
||||
#endif
|
||||
#if !LWIP_TCP || !TCP_QUEUE_OOSEQ || !LWIP_WND_SCALE
|
||||
#error "This test needs TCP OOSEQ queueing and window scaling enabled"
|
||||
#endif
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
pbuf_setup(void)
|
||||
{
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void
|
||||
pbuf_teardown(void)
|
||||
{
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
|
||||
#define TESTBUFSIZE_1 65535
|
||||
#define TESTBUFSIZE_2 65530
|
||||
#define TESTBUFSIZE_3 50050
|
||||
static u8_t testbuf_1[TESTBUFSIZE_1];
|
||||
static u8_t testbuf_1a[TESTBUFSIZE_1];
|
||||
static u8_t testbuf_2[TESTBUFSIZE_2];
|
||||
static u8_t testbuf_2a[TESTBUFSIZE_2];
|
||||
static u8_t testbuf_3[TESTBUFSIZE_3];
|
||||
static u8_t testbuf_3a[TESTBUFSIZE_3];
|
||||
|
||||
/* Test functions */
|
||||
START_TEST(test_pbuf_alloc_zero_pbufs)
|
||||
{
|
||||
struct pbuf *p;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, 0, PBUF_ROM);
|
||||
fail_unless(p != NULL);
|
||||
if (p != NULL) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, 0, PBUF_RAM);
|
||||
fail_unless(p != NULL);
|
||||
if (p != NULL) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, 0, PBUF_REF);
|
||||
fail_unless(p != NULL);
|
||||
if (p != NULL) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, 0, PBUF_POOL);
|
||||
fail_unless(p != NULL);
|
||||
if (p != NULL) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Call pbuf_copy on a pbuf with zero length */
|
||||
START_TEST(test_pbuf_copy_zero_pbuf)
|
||||
{
|
||||
struct pbuf *p1, *p2, *p3;
|
||||
err_t err;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p1 = pbuf_alloc(PBUF_RAW, 1024, PBUF_RAM);
|
||||
fail_unless(p1 != NULL);
|
||||
fail_unless(p1->ref == 1);
|
||||
|
||||
p2 = pbuf_alloc(PBUF_RAW, 2, PBUF_POOL);
|
||||
fail_unless(p2 != NULL);
|
||||
fail_unless(p2->ref == 1);
|
||||
p2->len = p2->tot_len = 0;
|
||||
|
||||
pbuf_cat(p1, p2);
|
||||
fail_unless(p1->ref == 1);
|
||||
fail_unless(p2->ref == 1);
|
||||
|
||||
p3 = pbuf_alloc(PBUF_RAW, p1->tot_len, PBUF_POOL);
|
||||
fail_unless(p3 != NULL);
|
||||
err = pbuf_copy(p3, p1);
|
||||
fail_unless(err == ERR_VAL);
|
||||
|
||||
pbuf_free(p1);
|
||||
pbuf_free(p3);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Call pbuf_copy on pbufs with chains of different sizes */
|
||||
START_TEST(test_pbuf_copy_unmatched_chains)
|
||||
{
|
||||
uint16_t i, j;
|
||||
err_t err;
|
||||
struct pbuf *source, *dest, *p;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
source = NULL;
|
||||
/* Build source pbuf from linked 16 byte parts,
|
||||
* with payload bytes containing their offset */
|
||||
for (i = 0; i < 8; i++) {
|
||||
p = pbuf_alloc(PBUF_RAW, 16, PBUF_RAM);
|
||||
fail_unless(p != NULL);
|
||||
for (j = 0; j < p->len; j++) {
|
||||
((u8_t*)p->payload)[j] = (u8_t)((i << 4) | j);
|
||||
}
|
||||
if (source) {
|
||||
pbuf_cat(source, p);
|
||||
} else {
|
||||
source = p;
|
||||
}
|
||||
}
|
||||
for (i = 0; i < source->tot_len; i++) {
|
||||
fail_unless(pbuf_get_at(source, i) == i);
|
||||
}
|
||||
|
||||
/* Build dest pbuf from other lengths */
|
||||
dest = pbuf_alloc(PBUF_RAW, 35, PBUF_RAM);
|
||||
fail_unless(dest != NULL);
|
||||
p = pbuf_alloc(PBUF_RAW, 81, PBUF_RAM);
|
||||
fail_unless(p != NULL);
|
||||
pbuf_cat(dest, p);
|
||||
p = pbuf_alloc(PBUF_RAW, 27, PBUF_RAM);
|
||||
fail_unless(p != NULL);
|
||||
pbuf_cat(dest, p);
|
||||
|
||||
/* Copy contents and verify data */
|
||||
err = pbuf_copy(dest, source);
|
||||
fail_unless(err == ERR_OK);
|
||||
for (i = 0; i < source->tot_len; i++) {
|
||||
fail_unless(pbuf_get_at(dest, i) == i);
|
||||
}
|
||||
|
||||
pbuf_free(source);
|
||||
pbuf_free(dest);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_pbuf_copy_partial_pbuf)
|
||||
{
|
||||
struct pbuf *a, *b, *dest;
|
||||
char lwip[] = "lwip ";
|
||||
char packet[] = "packet";
|
||||
err_t err;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
a = pbuf_alloc(PBUF_RAW, 5, PBUF_REF);
|
||||
fail_unless(a != NULL);
|
||||
a->payload = lwip;
|
||||
b = pbuf_alloc(PBUF_RAW, 7, PBUF_REF);
|
||||
fail_unless(b != NULL);
|
||||
b->payload = packet;
|
||||
pbuf_cat(a, b);
|
||||
dest = pbuf_alloc(PBUF_RAW, 14, PBUF_RAM);
|
||||
fail_unless(dest != NULL);
|
||||
memset(dest->payload, 0, dest->len);
|
||||
|
||||
/* Don't copy if data will not fit */
|
||||
err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 4);
|
||||
fail_unless(err == ERR_ARG);
|
||||
/* Don't copy if length is longer than source */
|
||||
err = pbuf_copy_partial_pbuf(dest, a, a->tot_len + 1, 0);
|
||||
fail_unless(err == ERR_ARG);
|
||||
/* Normal copy */
|
||||
err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 0);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(strcmp("lwip packet", (char*)dest->payload) == 0);
|
||||
/* Copy at offset */
|
||||
err = pbuf_copy_partial_pbuf(dest, a, a->tot_len, 1);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(strcmp("llwip packet", (char*)dest->payload) == 0);
|
||||
/* Copy at offset with shorter length */
|
||||
err = pbuf_copy_partial_pbuf(dest, a, 6, 6);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(strcmp("llwip lwip p", (char*)dest->payload) == 0);
|
||||
/* Copy with shorter length */
|
||||
err = pbuf_copy_partial_pbuf(dest, a, 5, 0);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(strcmp("lwip lwip p", (char*)dest->payload) == 0);
|
||||
|
||||
pbuf_free(dest);
|
||||
pbuf_free(a);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_pbuf_split_64k_on_small_pbufs)
|
||||
{
|
||||
struct pbuf *p, *rest=NULL;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, 1, PBUF_POOL);
|
||||
fail_unless(p != NULL);
|
||||
pbuf_split_64k(p, &rest);
|
||||
fail_unless(p->tot_len == 1);
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_pbuf_queueing_bigger_than_64k)
|
||||
{
|
||||
int i;
|
||||
err_t err;
|
||||
struct pbuf *p1, *p2, *p3, *rest2=NULL, *rest3=NULL;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
for(i = 0; i < TESTBUFSIZE_1; i++) {
|
||||
testbuf_1[i] = (u8_t)rand();
|
||||
}
|
||||
for(i = 0; i < TESTBUFSIZE_2; i++) {
|
||||
testbuf_2[i] = (u8_t)rand();
|
||||
}
|
||||
for(i = 0; i < TESTBUFSIZE_3; i++) {
|
||||
testbuf_3[i] = (u8_t)rand();
|
||||
}
|
||||
|
||||
p1 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_1, PBUF_POOL);
|
||||
fail_unless(p1 != NULL);
|
||||
p2 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_2, PBUF_POOL);
|
||||
fail_unless(p2 != NULL);
|
||||
p3 = pbuf_alloc(PBUF_RAW, TESTBUFSIZE_3, PBUF_POOL);
|
||||
fail_unless(p3 != NULL);
|
||||
err = pbuf_take(p1, testbuf_1, TESTBUFSIZE_1);
|
||||
fail_unless(err == ERR_OK);
|
||||
err = pbuf_take(p2, testbuf_2, TESTBUFSIZE_2);
|
||||
fail_unless(err == ERR_OK);
|
||||
err = pbuf_take(p3, testbuf_3, TESTBUFSIZE_3);
|
||||
fail_unless(err == ERR_OK);
|
||||
|
||||
pbuf_cat(p1, p2);
|
||||
pbuf_cat(p1, p3);
|
||||
|
||||
pbuf_split_64k(p1, &rest2);
|
||||
fail_unless(p1->tot_len == TESTBUFSIZE_1);
|
||||
fail_unless(rest2->tot_len == (u16_t)((TESTBUFSIZE_2+TESTBUFSIZE_3) & 0xFFFF));
|
||||
pbuf_split_64k(rest2, &rest3);
|
||||
fail_unless(rest2->tot_len == TESTBUFSIZE_2);
|
||||
fail_unless(rest3->tot_len == TESTBUFSIZE_3);
|
||||
|
||||
pbuf_copy_partial(p1, testbuf_1a, TESTBUFSIZE_1, 0);
|
||||
pbuf_copy_partial(rest2, testbuf_2a, TESTBUFSIZE_2, 0);
|
||||
pbuf_copy_partial(rest3, testbuf_3a, TESTBUFSIZE_3, 0);
|
||||
fail_if(memcmp(testbuf_1, testbuf_1a, TESTBUFSIZE_1));
|
||||
fail_if(memcmp(testbuf_2, testbuf_2a, TESTBUFSIZE_2));
|
||||
fail_if(memcmp(testbuf_3, testbuf_3a, TESTBUFSIZE_3));
|
||||
|
||||
pbuf_free(p1);
|
||||
pbuf_free(rest2);
|
||||
pbuf_free(rest3);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Test for bug that writing with pbuf_take_at() did nothing
|
||||
* and returned ERR_OK when writing at beginning of a pbuf
|
||||
* in the chain.
|
||||
*/
|
||||
START_TEST(test_pbuf_take_at_edge)
|
||||
{
|
||||
err_t res;
|
||||
u8_t *out;
|
||||
int i;
|
||||
u8_t testdata[] = { 0x01, 0x08, 0x82, 0x02 };
|
||||
struct pbuf *p;
|
||||
struct pbuf *q;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL);
|
||||
fail_unless(p != NULL);
|
||||
q = p->next;
|
||||
|
||||
/* alloc big enough to get a chain of pbufs */
|
||||
fail_if(p->tot_len == p->len);
|
||||
memset(p->payload, 0, p->len);
|
||||
memset(q->payload, 0, q->len);
|
||||
|
||||
/* copy data to the beginning of first pbuf */
|
||||
res = pbuf_take_at(p, &testdata, sizeof(testdata), 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
out = (u8_t*)p->payload;
|
||||
for (i = 0; i < (int)sizeof(testdata); i++) {
|
||||
fail_unless(out[i] == testdata[i],
|
||||
"Bad data at pos %d, was %02X, expected %02X", i, out[i], testdata[i]);
|
||||
}
|
||||
|
||||
/* copy data to the just before end of first pbuf */
|
||||
res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len - 1);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
out = (u8_t*)p->payload;
|
||||
fail_unless(out[p->len - 1] == testdata[0],
|
||||
"Bad data at pos %d, was %02X, expected %02X", p->len - 1, out[p->len - 1], testdata[0]);
|
||||
out = (u8_t*)q->payload;
|
||||
for (i = 1; i < (int)sizeof(testdata); i++) {
|
||||
fail_unless(out[i-1] == testdata[i],
|
||||
"Bad data at pos %d, was %02X, expected %02X", p->len - 1 + i, out[i-1], testdata[i]);
|
||||
}
|
||||
|
||||
/* copy data to the beginning of second pbuf */
|
||||
res = pbuf_take_at(p, &testdata, sizeof(testdata), p->len);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
out = (u8_t*)p->payload;
|
||||
for (i = 0; i < (int)sizeof(testdata); i++) {
|
||||
fail_unless(out[i] == testdata[i],
|
||||
"Bad data at pos %d, was %02X, expected %02X", p->len+i, out[i], testdata[i]);
|
||||
}
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Verify pbuf_put_at()/pbuf_get_at() when using
|
||||
* offsets equal to beginning of new pbuf in chain
|
||||
*/
|
||||
START_TEST(test_pbuf_get_put_at_edge)
|
||||
{
|
||||
u8_t *out;
|
||||
u8_t testdata = 0x01;
|
||||
u8_t getdata;
|
||||
struct pbuf *p;
|
||||
struct pbuf *q;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, 1024, PBUF_POOL);
|
||||
fail_unless(p != NULL);
|
||||
q = p->next;
|
||||
|
||||
/* alloc big enough to get a chain of pbufs */
|
||||
fail_if(p->tot_len == p->len);
|
||||
memset(p->payload, 0, p->len);
|
||||
memset(q->payload, 0, q->len);
|
||||
|
||||
/* put byte at the beginning of second pbuf */
|
||||
pbuf_put_at(p, p->len, testdata);
|
||||
|
||||
out = (u8_t*)q->payload;
|
||||
fail_unless(*out == testdata,
|
||||
"Bad data at pos %d, was %02X, expected %02X", p->len, *out, testdata);
|
||||
|
||||
getdata = pbuf_get_at(p, p->len);
|
||||
fail_unless(*out == getdata,
|
||||
"pbuf_get_at() returned bad data at pos %d, was %02X, expected %02X", p->len, getdata, *out);
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
pbuf_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_pbuf_alloc_zero_pbufs),
|
||||
TESTFUNC(test_pbuf_copy_zero_pbuf),
|
||||
TESTFUNC(test_pbuf_copy_unmatched_chains),
|
||||
TESTFUNC(test_pbuf_copy_partial_pbuf),
|
||||
TESTFUNC(test_pbuf_split_64k_on_small_pbufs),
|
||||
TESTFUNC(test_pbuf_queueing_bigger_than_64k),
|
||||
TESTFUNC(test_pbuf_take_at_edge),
|
||||
TESTFUNC(test_pbuf_get_put_at_edge)
|
||||
};
|
||||
return create_suite("PBUF", tests, sizeof(tests)/sizeof(testfunc), pbuf_setup, pbuf_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/core/test_pbuf.h
Normal file
8
lwip/lwip-2.2.1/test/unit/core/test_pbuf.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_PBUF_H
|
||||
#define LWIP_HDR_TEST_PBUF_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *pbuf_suite(void);
|
||||
|
||||
#endif
|
||||
233
lwip/lwip-2.2.1/test/unit/core/test_timers.c
Normal file
233
lwip/lwip-2.2.1/test/unit/core/test_timers.c
Normal file
@ -0,0 +1,233 @@
|
||||
#include "test_timers.h"
|
||||
|
||||
#include "lwip/def.h"
|
||||
#include "lwip/timeouts.h"
|
||||
#include "arch/sys_arch.h"
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static struct sys_timeo* old_list_head;
|
||||
|
||||
static void
|
||||
timers_setup(void)
|
||||
{
|
||||
struct sys_timeo** list_head = sys_timeouts_get_next_timeout();
|
||||
old_list_head = *list_head;
|
||||
*list_head = NULL;
|
||||
}
|
||||
|
||||
static void
|
||||
timers_teardown(void)
|
||||
{
|
||||
struct sys_timeo** list_head = sys_timeouts_get_next_timeout();
|
||||
*list_head = old_list_head;
|
||||
lwip_sys_now = 0;
|
||||
}
|
||||
|
||||
static int fired[3];
|
||||
static void
|
||||
dummy_handler(void* arg)
|
||||
{
|
||||
int index = LWIP_PTR_NUMERIC_CAST(int, arg);
|
||||
fired[index] = 1;
|
||||
}
|
||||
|
||||
#define HANDLER_EXECUTION_TIME 5
|
||||
static int cyclic_fired;
|
||||
static void
|
||||
dummy_cyclic_handler(void)
|
||||
{
|
||||
cyclic_fired = 1;
|
||||
lwip_sys_now += HANDLER_EXECUTION_TIME;
|
||||
}
|
||||
|
||||
struct lwip_cyclic_timer test_cyclic = {10, dummy_cyclic_handler};
|
||||
|
||||
static void
|
||||
do_test_cyclic_timers(u32_t offset)
|
||||
{
|
||||
struct sys_timeo** list_head = sys_timeouts_get_next_timeout();
|
||||
|
||||
/* verify normal timer expiration */
|
||||
lwip_sys_now = offset + 0;
|
||||
sys_timeout(test_cyclic.interval_ms, lwip_cyclic_timer, &test_cyclic);
|
||||
|
||||
cyclic_fired = 0;
|
||||
sys_check_timeouts();
|
||||
fail_unless(cyclic_fired == 0);
|
||||
|
||||
lwip_sys_now = offset + test_cyclic.interval_ms;
|
||||
sys_check_timeouts();
|
||||
fail_unless(cyclic_fired == 1);
|
||||
|
||||
fail_unless((*list_head)->time == (u32_t)(lwip_sys_now + test_cyclic.interval_ms - HANDLER_EXECUTION_TIME));
|
||||
|
||||
sys_untimeout(lwip_cyclic_timer, &test_cyclic);
|
||||
|
||||
|
||||
/* verify "overload" - next cyclic timer execution is already overdue twice */
|
||||
lwip_sys_now = offset + 0;
|
||||
sys_timeout(test_cyclic.interval_ms, lwip_cyclic_timer, &test_cyclic);
|
||||
|
||||
cyclic_fired = 0;
|
||||
sys_check_timeouts();
|
||||
fail_unless(cyclic_fired == 0);
|
||||
|
||||
lwip_sys_now = offset + 2*test_cyclic.interval_ms;
|
||||
sys_check_timeouts();
|
||||
fail_unless(cyclic_fired == 1);
|
||||
|
||||
fail_unless((*list_head)->time == (u32_t)(lwip_sys_now + test_cyclic.interval_ms));
|
||||
}
|
||||
|
||||
START_TEST(test_cyclic_timers)
|
||||
{
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* check without u32_t wraparound */
|
||||
do_test_cyclic_timers(0);
|
||||
|
||||
/* check with u32_t wraparound */
|
||||
do_test_cyclic_timers(0xfffffff0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* reproduce bug #52748: the bug in timeouts.c */
|
||||
START_TEST(test_bug52748)
|
||||
{
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&fired, 0, sizeof(fired));
|
||||
|
||||
lwip_sys_now = 50;
|
||||
sys_timeout(20, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0));
|
||||
sys_timeout( 5, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 2));
|
||||
|
||||
lwip_sys_now = 55;
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[0] == 0);
|
||||
fail_unless(fired[1] == 0);
|
||||
fail_unless(fired[2] == 1);
|
||||
|
||||
lwip_sys_now = 60;
|
||||
sys_timeout(10, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 1));
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[0] == 0);
|
||||
fail_unless(fired[1] == 0);
|
||||
fail_unless(fired[2] == 1);
|
||||
|
||||
lwip_sys_now = 70;
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[0] == 1);
|
||||
fail_unless(fired[1] == 1);
|
||||
fail_unless(fired[2] == 1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void
|
||||
do_test_timers(u32_t offset)
|
||||
{
|
||||
struct sys_timeo** list_head = sys_timeouts_get_next_timeout();
|
||||
|
||||
lwip_sys_now = offset + 0;
|
||||
|
||||
sys_timeout(10, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0));
|
||||
fail_unless(sys_timeouts_sleeptime() == 10);
|
||||
sys_timeout(20, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 1));
|
||||
fail_unless(sys_timeouts_sleeptime() == 10);
|
||||
sys_timeout( 5, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 2));
|
||||
fail_unless(sys_timeouts_sleeptime() == 5);
|
||||
|
||||
/* linked list correctly sorted? */
|
||||
fail_unless((*list_head)->time == (u32_t)(lwip_sys_now + 5));
|
||||
fail_unless((*list_head)->next->time == (u32_t)(lwip_sys_now + 10));
|
||||
fail_unless((*list_head)->next->next->time == (u32_t)(lwip_sys_now + 20));
|
||||
|
||||
/* check timers expire in correct order */
|
||||
memset(&fired, 0, sizeof(fired));
|
||||
|
||||
lwip_sys_now += 4;
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[2] == 0);
|
||||
|
||||
lwip_sys_now += 1;
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[2] == 1);
|
||||
|
||||
lwip_sys_now += 4;
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[0] == 0);
|
||||
|
||||
lwip_sys_now += 1;
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[0] == 1);
|
||||
|
||||
lwip_sys_now += 9;
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[1] == 0);
|
||||
|
||||
lwip_sys_now += 1;
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[1] == 1);
|
||||
|
||||
sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0));
|
||||
sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 1));
|
||||
sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 2));
|
||||
}
|
||||
|
||||
START_TEST(test_timers)
|
||||
{
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* check without u32_t wraparound */
|
||||
do_test_timers(0);
|
||||
|
||||
/* check with u32_t wraparound */
|
||||
do_test_timers(0xfffffff0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_long_timer)
|
||||
{
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&fired, 0, sizeof(fired));
|
||||
lwip_sys_now = 0;
|
||||
|
||||
sys_timeout(LWIP_UINT32_MAX / 4, dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0));
|
||||
fail_unless(sys_timeouts_sleeptime() == LWIP_UINT32_MAX / 4);
|
||||
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[0] == 0);
|
||||
|
||||
lwip_sys_now += LWIP_UINT32_MAX / 8;
|
||||
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[0] == 0);
|
||||
|
||||
lwip_sys_now += LWIP_UINT32_MAX / 8;
|
||||
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[0] == 0);
|
||||
|
||||
lwip_sys_now += 1;
|
||||
|
||||
sys_check_timeouts();
|
||||
fail_unless(fired[0] == 1);
|
||||
|
||||
sys_untimeout(dummy_handler, LWIP_PTR_NUMERIC_CAST(void*, 0));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
timers_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_bug52748),
|
||||
TESTFUNC(test_cyclic_timers),
|
||||
TESTFUNC(test_timers),
|
||||
TESTFUNC(test_long_timer),
|
||||
};
|
||||
return create_suite("TIMERS", tests, LWIP_ARRAYSIZE(tests), timers_setup, timers_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/core/test_timers.h
Normal file
8
lwip/lwip-2.2.1/test/unit/core/test_timers.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_TIMERS_H
|
||||
#define LWIP_HDR_TEST_TIMERS_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *timers_suite(void);
|
||||
|
||||
#endif
|
||||
1108
lwip/lwip-2.2.1/test/unit/dhcp/test_dhcp.c
Normal file
1108
lwip/lwip-2.2.1/test/unit/dhcp/test_dhcp.c
Normal file
File diff suppressed because it is too large
Load Diff
8
lwip/lwip-2.2.1/test/unit/dhcp/test_dhcp.h
Normal file
8
lwip/lwip-2.2.1/test/unit/dhcp/test_dhcp.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_DHCP_H
|
||||
#define LWIP_HDR_TEST_DHCP_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite* dhcp_suite(void);
|
||||
|
||||
#endif
|
||||
273
lwip/lwip-2.2.1/test/unit/etharp/test_etharp.c
Normal file
273
lwip/lwip-2.2.1/test/unit/etharp/test_etharp.c
Normal file
@ -0,0 +1,273 @@
|
||||
#include "test_etharp.h"
|
||||
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "netif/ethernet.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/prot/iana.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 ip4_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(ip4_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(LWIP_IANA_HWTYPE_ETHERNET);
|
||||
etharphdr->proto = htons(ETHTYPE_IP);
|
||||
etharphdr->hwlen = ETHARP_HWADDR_LEN;
|
||||
etharphdr->protolen = sizeof(ip4_addr_t);
|
||||
etharphdr->opcode = htons(ARP_REPLY);
|
||||
|
||||
SMEMCPY(ðarphdr->sipaddr, adr, sizeof(ip4_addr_t));
|
||||
SMEMCPY(ðarphdr->dipaddr, &test_ipaddr, sizeof(ip4_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();
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void
|
||||
etharp_teardown(void)
|
||||
{
|
||||
etharp_remove_all();
|
||||
default_netif_remove();
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
|
||||
/* Test functions */
|
||||
|
||||
START_TEST(test_etharp_table)
|
||||
{
|
||||
#if ETHARP_SUPPORT_STATIC_ENTRIES
|
||||
err_t err;
|
||||
#endif /* ETHARP_SUPPORT_STATIC_ENTRIES */
|
||||
ssize_t idx;
|
||||
const ip4_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) {
|
||||
ip4_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 err2;
|
||||
ip_addr_t dst;
|
||||
ip_addr_copy_from_ip4(dst, adrs[i]);
|
||||
err2 = udp_sendto(pcb, p, &dst, 123);
|
||||
fail_unless(err2 == 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 err2;
|
||||
ip_addr_t dst;
|
||||
ip_addr_copy_from_ip4(dst, adrs[i]);
|
||||
err2 = udp_sendto(pcb, p, &dst, 123);
|
||||
fail_unless(err2 == 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)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_etharp_table)
|
||||
};
|
||||
return create_suite("ETHARP", tests, sizeof(tests)/sizeof(testfunc), etharp_setup, etharp_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/etharp/test_etharp.h
Normal file
8
lwip/lwip-2.2.1/test/unit/etharp/test_etharp.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_ETHARP_H
|
||||
#define LWIP_HDR_TEST_ETHARP_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite* etharp_suite(void);
|
||||
|
||||
#endif
|
||||
343
lwip/lwip-2.2.1/test/unit/ip4/test_ip4.c
Normal file
343
lwip/lwip-2.2.1/test/unit/ip4/test_ip4.c
Normal file
@ -0,0 +1,343 @@
|
||||
#include "test_ip4.h"
|
||||
|
||||
#include "lwip/icmp.h"
|
||||
#include "lwip/ip4.h"
|
||||
#include "lwip/etharp.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/prot/ip.h"
|
||||
#include "lwip/prot/ip4.h"
|
||||
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#if !LWIP_IPV4 || !IP_REASSEMBLY || !MIB2_STATS || !IPFRAG_STATS
|
||||
#error "This tests needs LWIP_IPV4, IP_REASSEMBLY; MIB2- and IPFRAG-statistics enabled"
|
||||
#endif
|
||||
|
||||
static struct netif test_netif;
|
||||
static ip4_addr_t test_ipaddr, test_netmask, test_gw;
|
||||
static int linkoutput_ctr;
|
||||
static int linkoutput_byte_ctr;
|
||||
static u16_t linkoutput_pkt_len;
|
||||
static u8_t linkoutput_pkt[100];
|
||||
|
||||
/* reference internal lwip variable in netif.c */
|
||||
|
||||
static err_t
|
||||
test_netif_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
fail_unless(netif == &test_netif);
|
||||
fail_unless(p != NULL);
|
||||
linkoutput_ctr++;
|
||||
linkoutput_byte_ctr += p->tot_len;
|
||||
/* Copy start of packet into buffer */
|
||||
linkoutput_pkt_len = pbuf_copy_partial(p, linkoutput_pkt, sizeof(linkoutput_pkt), 0);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t
|
||||
test_netif_init(struct netif *netif)
|
||||
{
|
||||
fail_unless(netif != NULL);
|
||||
netif->linkoutput = test_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
|
||||
test_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_add(&test_netif, &test_ipaddr, &test_netmask, &test_gw,
|
||||
NULL, test_netif_init, NULL);
|
||||
netif_set_default(&test_netif);
|
||||
netif_set_up(&test_netif);
|
||||
}
|
||||
|
||||
static void
|
||||
test_netif_remove(void)
|
||||
{
|
||||
if (netif_default == &test_netif) {
|
||||
netif_remove(&test_netif);
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper functions */
|
||||
static void
|
||||
create_ip4_input_fragment(u16_t ip_id, u16_t start, u16_t len, int last)
|
||||
{
|
||||
struct pbuf *p;
|
||||
struct netif *input_netif = netif_list; /* just use any netif */
|
||||
fail_unless((start & 7) == 0);
|
||||
fail_unless(((len & 7) == 0) || last);
|
||||
fail_unless(input_netif != NULL);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, len + sizeof(struct ip_hdr), PBUF_RAM);
|
||||
fail_unless(p != NULL);
|
||||
if (p != NULL) {
|
||||
err_t err;
|
||||
struct ip_hdr *iphdr = (struct ip_hdr *)p->payload;
|
||||
IPH_VHL_SET(iphdr, 4, sizeof(struct ip_hdr) / 4);
|
||||
IPH_TOS_SET(iphdr, 0);
|
||||
IPH_LEN_SET(iphdr, lwip_htons(p->tot_len));
|
||||
IPH_ID_SET(iphdr, lwip_htons(ip_id));
|
||||
if (last) {
|
||||
IPH_OFFSET_SET(iphdr, lwip_htons(start / 8));
|
||||
} else {
|
||||
IPH_OFFSET_SET(iphdr, lwip_htons((start / 8) | IP_MF));
|
||||
}
|
||||
IPH_TTL_SET(iphdr, 5);
|
||||
IPH_PROTO_SET(iphdr, IP_PROTO_UDP);
|
||||
IPH_CHKSUM_SET(iphdr, 0);
|
||||
ip4_addr_copy(iphdr->src, *netif_ip4_addr(input_netif));
|
||||
iphdr->src.addr = lwip_htonl(lwip_htonl(iphdr->src.addr) + 1);
|
||||
ip4_addr_copy(iphdr->dest, *netif_ip4_addr(input_netif));
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, sizeof(struct ip_hdr)));
|
||||
|
||||
err = ip4_input(p, input_netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
fail_unless(err == ERR_OK);
|
||||
}
|
||||
}
|
||||
|
||||
static err_t arpless_output(struct netif *netif, struct pbuf *p,
|
||||
const ip4_addr_t *ipaddr) {
|
||||
LWIP_UNUSED_ARG(ipaddr);
|
||||
return netif->linkoutput(netif, p);
|
||||
}
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
ip4_setup(void)
|
||||
{
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void
|
||||
ip4_teardown(void)
|
||||
{
|
||||
if (netif_list->loop_first != NULL) {
|
||||
pbuf_free(netif_list->loop_first);
|
||||
netif_list->loop_first = NULL;
|
||||
}
|
||||
netif_list->loop_last = NULL;
|
||||
/* poll until all memory is released... */
|
||||
tcpip_thread_poll_one();
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
test_netif_remove();
|
||||
netif_set_up(netif_get_loopif());
|
||||
}
|
||||
|
||||
/* Test functions */
|
||||
START_TEST(test_ip4_frag)
|
||||
{
|
||||
struct pbuf *data = pbuf_alloc(PBUF_IP, 8000, PBUF_RAM);
|
||||
ip_addr_t peer_ip = IPADDR4_INIT_BYTES(192,168,0,5);
|
||||
err_t err;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
linkoutput_ctr = 0;
|
||||
linkoutput_byte_ctr = 0;
|
||||
|
||||
/* Verify that 8000 byte payload is split into six packets */
|
||||
fail_unless(data != NULL);
|
||||
test_netif_add();
|
||||
test_netif.output = arpless_output;
|
||||
err = ip4_output_if_src(data, &test_ipaddr, ip_2_ip4(&peer_ip),
|
||||
16, 0, IP_PROTO_UDP, &test_netif);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(linkoutput_ctr == 6);
|
||||
fail_unless(linkoutput_byte_ctr == (8000 + (6 * IP_HLEN)));
|
||||
pbuf_free(data);
|
||||
test_netif_remove();
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_ip4_reass)
|
||||
{
|
||||
const u16_t ip_id = 128;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2));
|
||||
|
||||
create_ip4_input_fragment(ip_id, 8*200, 200, 1);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 1);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 0*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 2);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 1*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 3);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 2*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 4);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 3*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 5);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 4*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 6);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 7*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 7);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 6*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 8);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 0);
|
||||
|
||||
create_ip4_input_fragment(ip_id, 5*200, 200, 0);
|
||||
fail_unless(lwip_stats.ip_frag.recv == 9);
|
||||
fail_unless(lwip_stats.ip_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip_frag.drop == 0);
|
||||
fail_unless(lwip_stats.mib2.ipreasmoks == 1);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* packets to 127.0.0.1 shall not be sent out to netif_default */
|
||||
START_TEST(test_127_0_0_1)
|
||||
{
|
||||
ip4_addr_t localhost;
|
||||
struct pbuf* p;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
linkoutput_ctr = 0;
|
||||
|
||||
test_netif_add();
|
||||
netif_set_down(netif_get_loopif());
|
||||
|
||||
IP4_ADDR(&localhost, 127, 0, 0, 1);
|
||||
p = pbuf_alloc(PBUF_IP, 10, PBUF_POOL);
|
||||
|
||||
if(ip4_output(p, netif_ip4_addr(netif_default), &localhost, 0, 0, IP_PROTO_UDP) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
fail_unless(linkoutput_ctr == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_ip4addr_aton)
|
||||
{
|
||||
ip4_addr_t ip_addr;
|
||||
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
fail_unless(ip4addr_aton("192.168.0.1", &ip_addr) == 1);
|
||||
fail_unless(ip4addr_aton("192.168.0.0001", &ip_addr) == 1);
|
||||
fail_unless(ip4addr_aton("192.168.0.zzz", &ip_addr) == 0);
|
||||
fail_unless(ip4addr_aton("192.168.1", &ip_addr) == 1);
|
||||
fail_unless(ip4addr_aton("192.168.0xd3", &ip_addr) == 1);
|
||||
fail_unless(ip4addr_aton("192.168.0xz5", &ip_addr) == 0);
|
||||
fail_unless(ip4addr_aton("192.168.095", &ip_addr) == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Test for bug #59364 */
|
||||
START_TEST(test_ip4_icmp_replylen_short)
|
||||
{
|
||||
/* IP packet to 192.168.0.1 using proto 0x22 and 1 byte payload */
|
||||
const u8_t unknown_proto[] = {
|
||||
0x45, 0x00, 0x00, 0x15, 0xd4, 0x31, 0x00, 0x00, 0xff, 0x22,
|
||||
0x66, 0x41, 0xc0, 0xa8, 0x00, 0x02, 0xc0, 0xa8, 0x00, 0x01,
|
||||
0xaa };
|
||||
struct pbuf *p;
|
||||
const int icmp_len = IP_HLEN + sizeof(struct icmp_hdr);
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
linkoutput_ctr = 0;
|
||||
|
||||
test_netif_add();
|
||||
test_netif.output = arpless_output;
|
||||
p = pbuf_alloc(PBUF_IP, sizeof(unknown_proto), PBUF_RAM);
|
||||
pbuf_take(p, unknown_proto, sizeof(unknown_proto));
|
||||
fail_unless(ip4_input(p, &test_netif) == ERR_OK);
|
||||
|
||||
fail_unless(linkoutput_ctr == 1);
|
||||
/* Verify outgoing ICMP packet has no extra data */
|
||||
fail_unless(linkoutput_pkt_len == icmp_len + sizeof(unknown_proto));
|
||||
fail_if(memcmp(&linkoutput_pkt[icmp_len], unknown_proto, sizeof(unknown_proto)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_ip4_icmp_replylen_first_8)
|
||||
{
|
||||
/* IP packet to 192.168.0.1 using proto 0x22 and 11 bytes payload */
|
||||
const u8_t unknown_proto[] = {
|
||||
0x45, 0x00, 0x00, 0x1f, 0xd4, 0x31, 0x00, 0x00, 0xff, 0x22,
|
||||
0x66, 0x37, 0xc0, 0xa8, 0x00, 0x02, 0xc0, 0xa8, 0x00, 0x01,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
|
||||
0xaa };
|
||||
struct pbuf *p;
|
||||
const int icmp_len = IP_HLEN + sizeof(struct icmp_hdr);
|
||||
const int unreach_len = IP_HLEN + 8;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
linkoutput_ctr = 0;
|
||||
|
||||
test_netif_add();
|
||||
test_netif.output = arpless_output;
|
||||
p = pbuf_alloc(PBUF_IP, sizeof(unknown_proto), PBUF_RAM);
|
||||
pbuf_take(p, unknown_proto, sizeof(unknown_proto));
|
||||
fail_unless(ip4_input(p, &test_netif) == ERR_OK);
|
||||
|
||||
fail_unless(linkoutput_ctr == 1);
|
||||
fail_unless(linkoutput_pkt_len == icmp_len + unreach_len);
|
||||
fail_if(memcmp(&linkoutput_pkt[icmp_len], unknown_proto, unreach_len));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
ip4_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_ip4_frag),
|
||||
TESTFUNC(test_ip4_reass),
|
||||
TESTFUNC(test_127_0_0_1),
|
||||
TESTFUNC(test_ip4addr_aton),
|
||||
TESTFUNC(test_ip4_icmp_replylen_short),
|
||||
TESTFUNC(test_ip4_icmp_replylen_first_8),
|
||||
};
|
||||
return create_suite("IPv4", tests, sizeof(tests)/sizeof(testfunc), ip4_setup, ip4_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/ip4/test_ip4.h
Normal file
8
lwip/lwip-2.2.1/test/unit/ip4/test_ip4.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_IP4_H
|
||||
#define LWIP_HDR_TEST_IP4_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite* ip4_suite(void);
|
||||
|
||||
#endif
|
||||
558
lwip/lwip-2.2.1/test/unit/ip6/test_ip6.c
Normal file
558
lwip/lwip-2.2.1/test/unit/ip6/test_ip6.c
Normal file
@ -0,0 +1,558 @@
|
||||
#include "test_ip6.h"
|
||||
|
||||
#include "lwip/ethip6.h"
|
||||
#include "lwip/ip6.h"
|
||||
#include "lwip/icmp6.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/nd6.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/prot/ethernet.h"
|
||||
#include "lwip/prot/ip.h"
|
||||
#include "lwip/prot/ip6.h"
|
||||
|
||||
#include "lwip/tcpip.h"
|
||||
|
||||
#if LWIP_IPV6 /* allow to build the unit tests without IPv6 support */
|
||||
|
||||
static struct netif test_netif6;
|
||||
static int linkoutput_ctr;
|
||||
static int linkoutput_byte_ctr;
|
||||
|
||||
static err_t
|
||||
default_netif_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
fail_unless(netif == &test_netif6);
|
||||
fail_unless(p != NULL);
|
||||
linkoutput_ctr++;
|
||||
linkoutput_byte_ctr += p->tot_len;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t
|
||||
default_netif_init(struct netif *netif)
|
||||
{
|
||||
fail_unless(netif != NULL);
|
||||
netif->linkoutput = default_netif_linkoutput;
|
||||
netif->output_ip6 = ethip6_output;
|
||||
netif->mtu = 1500;
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHERNET | NETIF_FLAG_MLD6;
|
||||
netif->hwaddr_len = ETH_HWADDR_LEN;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
default_netif_add(void)
|
||||
{
|
||||
struct netif *n;
|
||||
fail_unless(netif_default == NULL);
|
||||
n = netif_add_noaddr(&test_netif6, NULL, default_netif_init, NULL);
|
||||
fail_unless(n == &test_netif6);
|
||||
netif_set_default(&test_netif6);
|
||||
}
|
||||
|
||||
static void
|
||||
default_netif_remove(void)
|
||||
{
|
||||
fail_unless(netif_default == &test_netif6);
|
||||
netif_remove(&test_netif6);
|
||||
}
|
||||
|
||||
static void
|
||||
ip6_test_handle_timers(int count)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < count; i++) {
|
||||
nd6_tmr();
|
||||
}
|
||||
}
|
||||
|
||||
/* Helper functions */
|
||||
static void
|
||||
create_ip6_input_fragment(u32_t ip_id, u16_t start, u16_t len, int last, u8_t next_hdr)
|
||||
{
|
||||
struct pbuf* p;
|
||||
struct netif* input_netif = netif_list; /* just use any netif */
|
||||
fail_unless((start & 7) == 0);
|
||||
fail_unless(((len & 7) == 0) || last);
|
||||
fail_unless(input_netif != NULL);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, len + sizeof(struct ip6_frag_hdr) +
|
||||
sizeof(struct ip6_hdr), PBUF_RAM);
|
||||
fail_unless(p != NULL);
|
||||
if (p != NULL) {
|
||||
err_t err;
|
||||
struct ip6_frag_hdr* fraghdr;
|
||||
|
||||
struct ip6_hdr* ip6hdr = (struct ip6_hdr*)p->payload;
|
||||
IP6H_VTCFL_SET(ip6hdr, 6, 0, 0);
|
||||
IP6H_PLEN_SET(ip6hdr, len + sizeof(struct ip6_frag_hdr));
|
||||
IP6H_NEXTH_SET(ip6hdr, IP6_NEXTH_FRAGMENT);
|
||||
IP6H_HOPLIM_SET(ip6hdr, 64);
|
||||
ip6_addr_copy_to_packed(ip6hdr->src, *netif_ip6_addr(input_netif, 0));
|
||||
ip6hdr->src.addr[3]++;
|
||||
ip6_addr_copy_to_packed(ip6hdr->dest, *netif_ip6_addr(input_netif, 0));
|
||||
|
||||
fraghdr = (struct ip6_frag_hdr*)(ip6hdr + 1);
|
||||
fraghdr->_nexth = next_hdr;
|
||||
fraghdr->reserved = 0;
|
||||
if (last) {
|
||||
fraghdr->_fragment_offset = htons(start & ~7);
|
||||
} else {
|
||||
fraghdr->_fragment_offset = htons((start & ~7) | 1);
|
||||
}
|
||||
fraghdr->_identification = htonl(ip_id);
|
||||
|
||||
err = ip6_input(p, input_netif);
|
||||
if (err != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
fail_unless(err == ERR_OK);
|
||||
}
|
||||
}
|
||||
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
ip6_setup(void)
|
||||
{
|
||||
default_netif_add();
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void
|
||||
ip6_teardown(void)
|
||||
{
|
||||
if (netif_list->loop_first != NULL) {
|
||||
pbuf_free(netif_list->loop_first);
|
||||
netif_list->loop_first = NULL;
|
||||
}
|
||||
netif_list->loop_last = NULL;
|
||||
/* poll until all memory is released... */
|
||||
tcpip_thread_poll_one();
|
||||
default_netif_remove();
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
|
||||
/* Test functions */
|
||||
|
||||
static void
|
||||
test_ip6_ll_addr_iter(int expected_ctr1, int expected_ctr2)
|
||||
{
|
||||
fail_unless(linkoutput_ctr == 0);
|
||||
|
||||
/* test that nothing is sent with link uo but netif down */
|
||||
netif_set_link_up(&test_netif6);
|
||||
ip6_test_handle_timers(500);
|
||||
fail_unless(linkoutput_ctr == 0);
|
||||
netif_set_link_down(&test_netif6);
|
||||
fail_unless(linkoutput_ctr == 0);
|
||||
|
||||
/* test that nothing is sent with link down but netif up */
|
||||
netif_set_up(&test_netif6);
|
||||
ip6_test_handle_timers(500);
|
||||
fail_unless(linkoutput_ctr == 0);
|
||||
netif_set_down(&test_netif6);
|
||||
fail_unless(linkoutput_ctr == 0);
|
||||
|
||||
/* test what is sent with link up + netif up */
|
||||
netif_set_link_up(&test_netif6);
|
||||
netif_set_up(&test_netif6);
|
||||
ip6_test_handle_timers(500);
|
||||
fail_unless(linkoutput_ctr == expected_ctr1);
|
||||
netif_set_down(&test_netif6);
|
||||
netif_set_link_down(&test_netif6);
|
||||
fail_unless(linkoutput_ctr == expected_ctr1);
|
||||
linkoutput_ctr = 0;
|
||||
|
||||
netif_set_up(&test_netif6);
|
||||
netif_set_link_up(&test_netif6);
|
||||
ip6_test_handle_timers(500);
|
||||
fail_unless(linkoutput_ctr == expected_ctr2);
|
||||
netif_set_link_down(&test_netif6);
|
||||
netif_set_down(&test_netif6);
|
||||
fail_unless(linkoutput_ctr == expected_ctr2);
|
||||
linkoutput_ctr = 0;
|
||||
}
|
||||
|
||||
START_TEST(test_ip6_ll_addr)
|
||||
{
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
linkoutput_ctr = 0;
|
||||
|
||||
/* test without link-local address */
|
||||
test_ip6_ll_addr_iter(0, 0);
|
||||
|
||||
/* test with link-local address */
|
||||
netif_create_ip6_linklocal_address(&test_netif6, 1);
|
||||
test_ip6_ll_addr_iter(3 + LWIP_IPV6_DUP_DETECT_ATTEMPTS + LWIP_IPV6_MLD, 3);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_ip6_aton_ipv4mapped)
|
||||
{
|
||||
int ret;
|
||||
ip_addr_t addr;
|
||||
ip6_addr_t addr6;
|
||||
const ip_addr_t addr_expected = IPADDR6_INIT_HOST(0, 0, 0xFFFF, 0xD4CC65D2);
|
||||
const char *full_ipv6_addr = "0:0:0:0:0:FFFF:D4CC:65D2";
|
||||
const char *shortened_ipv6_addr = "::FFFF:D4CC:65D2";
|
||||
const char *full_ipv4_mapped_addr = "0:0:0:0:0:FFFF:212.204.101.210";
|
||||
const char *shortened_ipv4_mapped_addr = "::FFFF:212.204.101.210";
|
||||
const char *bogus_ipv4_mapped_addr = "::FFFF:212.204.101.2101";
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* check IPv6 representation */
|
||||
memset(&addr6, 0, sizeof(addr6));
|
||||
ret = ip6addr_aton(full_ipv6_addr, &addr6);
|
||||
fail_unless(ret == 1);
|
||||
fail_unless(memcmp(&addr6, &addr_expected, 16) == 0);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
ret = ipaddr_aton(full_ipv6_addr, &addr);
|
||||
fail_unless(ret == 1);
|
||||
fail_unless(memcmp(&addr, &addr_expected, 16) == 0);
|
||||
|
||||
/* check shortened IPv6 representation */
|
||||
memset(&addr6, 0, sizeof(addr6));
|
||||
ret = ip6addr_aton(shortened_ipv6_addr, &addr6);
|
||||
fail_unless(ret == 1);
|
||||
fail_unless(memcmp(&addr6, &addr_expected, 16) == 0);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
ret = ipaddr_aton(shortened_ipv6_addr, &addr);
|
||||
fail_unless(ret == 1);
|
||||
fail_unless(memcmp(&addr, &addr_expected, 16) == 0);
|
||||
|
||||
/* checked shortened mixed representation */
|
||||
memset(&addr6, 0, sizeof(addr6));
|
||||
ret = ip6addr_aton(shortened_ipv4_mapped_addr, &addr6);
|
||||
fail_unless(ret == 1);
|
||||
fail_unless(memcmp(&addr6, &addr_expected, 16) == 0);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
ret = ipaddr_aton(shortened_ipv4_mapped_addr, &addr);
|
||||
fail_unless(ret == 1);
|
||||
fail_unless(memcmp(&addr, &addr_expected, 16) == 0);
|
||||
|
||||
/* checked mixed representation */
|
||||
memset(&addr6, 0, sizeof(addr6));
|
||||
ret = ip6addr_aton(full_ipv4_mapped_addr, &addr6);
|
||||
fail_unless(ret == 1);
|
||||
fail_unless(memcmp(&addr6, &addr_expected, 16) == 0);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
ret = ipaddr_aton(full_ipv4_mapped_addr, &addr);
|
||||
fail_unless(ret == 1);
|
||||
fail_unless(memcmp(&addr, &addr_expected, 16) == 0);
|
||||
|
||||
/* checked bogus mixed representation */
|
||||
memset(&addr6, 0, sizeof(addr6));
|
||||
ret = ip6addr_aton(bogus_ipv4_mapped_addr, &addr6);
|
||||
fail_unless(ret == 0);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
ret = ipaddr_aton(bogus_ipv4_mapped_addr, &addr);
|
||||
fail_unless(ret == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_ip6_ntoa_ipv4mapped)
|
||||
{
|
||||
const ip_addr_t addr = IPADDR6_INIT_HOST(0, 0, 0xFFFF, 0xD4CC65D2);
|
||||
char buf[128];
|
||||
char *str;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
str = ip6addr_ntoa_r(ip_2_ip6(&addr), buf, sizeof(buf));
|
||||
fail_unless(str == buf);
|
||||
fail_unless(!strcmp(str, "::FFFF:212.204.101.210"));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
struct test_addr_and_str {
|
||||
ip_addr_t addr;
|
||||
const char *str;
|
||||
};
|
||||
|
||||
START_TEST(test_ip6_ntoa)
|
||||
{
|
||||
struct test_addr_and_str tests[] = {
|
||||
{IPADDR6_INIT_HOST(0xfe800000, 0x00000000, 0xb2a1a2ff, 0xfea3a4a5), "FE80::B2A1:A2FF:FEA3:A4A5"}, /* test shortened zeros */
|
||||
{IPADDR6_INIT_HOST(0xfe800000, 0xff000000, 0xb2a1a2ff, 0xfea3a4a5), "FE80:0:FF00:0:B2A1:A2FF:FEA3:A4A5"}, /* don't omit single zero blocks */
|
||||
{IPADDR6_INIT_HOST(0xfe800000, 0xff000000, 0xb2000000, 0x0000a4a5), "FE80:0:FF00:0:B200::A4A5"}, /* omit longest zero block */
|
||||
};
|
||||
char buf[128];
|
||||
char *str;
|
||||
size_t i;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
for (i = 0; i < LWIP_ARRAYSIZE(tests); i++) {
|
||||
str = ip6addr_ntoa_r(ip_2_ip6(&tests[i].addr), buf, sizeof(buf));
|
||||
fail_unless(str == buf);
|
||||
fail_unless(!strcmp(str, tests[i].str));
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_ip6_lladdr)
|
||||
{
|
||||
u8_t zeros[128];
|
||||
const u8_t test_mac_addr[6] = {0xb0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5};
|
||||
const u32_t expected_ip6_addr_1[4] = {PP_HTONL(0xfe800000), 0, PP_HTONL(0xb2a1a2ff), PP_HTONL(0xfea3a4a5)};
|
||||
const u32_t expected_ip6_addr_2[4] = {PP_HTONL(0xfe800000), 0, PP_HTONL(0x0000b0a1), PP_HTONL(0xa2a3a4a5)};
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
memset(zeros, 0, sizeof(zeros));
|
||||
|
||||
fail_unless(test_netif6.hwaddr_len == 6);
|
||||
fail_unless(!memcmp(test_netif6.hwaddr, zeros, 6));
|
||||
|
||||
fail_unless(test_netif6.ip6_addr_state[0] == 0);
|
||||
fail_unless(!memcmp(netif_ip6_addr(&test_netif6, 0), zeros, sizeof(ip6_addr_t)));
|
||||
|
||||
/* set specific mac addr */
|
||||
memcpy(test_netif6.hwaddr, test_mac_addr, 6);
|
||||
|
||||
/* create link-local addr based on mac (EUI-48) */
|
||||
netif_create_ip6_linklocal_address(&test_netif6, 1);
|
||||
fail_unless(IP_IS_V6(&test_netif6.ip6_addr[0]));
|
||||
fail_unless(!memcmp(&netif_ip6_addr(&test_netif6, 0)->addr, expected_ip6_addr_1, 16));
|
||||
#if LWIP_IPV6_SCOPES
|
||||
fail_unless(netif_ip6_addr(&test_netif6, 0)->zone == (test_netif6.num + 1));
|
||||
#endif
|
||||
/* reset address */
|
||||
memset(&test_netif6.ip6_addr[0], 0, sizeof(ip6_addr_t));
|
||||
test_netif6.ip6_addr_state[0] = 0;
|
||||
|
||||
/* create link-local addr based interface ID */
|
||||
netif_create_ip6_linklocal_address(&test_netif6, 0);
|
||||
fail_unless(IP_IS_V6(&test_netif6.ip6_addr[0]));
|
||||
fail_unless(!memcmp(&netif_ip6_addr(&test_netif6, 0)->addr, expected_ip6_addr_2, 16));
|
||||
#if LWIP_IPV6_SCOPES
|
||||
fail_unless(netif_ip6_addr(&test_netif6, 0)->zone == (test_netif6.num + 1));
|
||||
#endif
|
||||
/* reset address */
|
||||
memset(&test_netif6.ip6_addr[0], 0, sizeof(ip6_addr_t));
|
||||
test_netif6.ip6_addr_state[0] = 0;
|
||||
|
||||
/* reset mac address */
|
||||
memset(&test_netif6.hwaddr, 0, sizeof(test_netif6.hwaddr));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static struct pbuf *cloned_pbuf = NULL;
|
||||
static err_t clone_output(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) {
|
||||
LWIP_UNUSED_ARG(netif);
|
||||
LWIP_UNUSED_ARG(addr);
|
||||
cloned_pbuf = pbuf_clone(PBUF_RAW, PBUF_RAM, p);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
/* Reproduces bug #58553 */
|
||||
START_TEST(test_ip6_dest_unreachable_chained_pbuf)
|
||||
{
|
||||
|
||||
ip_addr_t my_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x1);
|
||||
ip_addr_t peer_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x4);
|
||||
/* Create chained pbuf with UDP data that will get destination unreachable */
|
||||
u8_t udp_hdr[] = {
|
||||
0x60, 0x00, 0x27, 0x03, 0x00, 0x2d, 0x11, 0x40,
|
||||
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
|
||||
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0x01, 0xff, 0x03, 0xff, 0x00, 0x2d, 0x00, 0x00,
|
||||
};
|
||||
struct pbuf *header = pbuf_alloc(PBUF_RAW, sizeof(udp_hdr), PBUF_ROM);
|
||||
u8_t udp_payload[] = "abcdefghijklmnopqrstuvwxyz0123456789";
|
||||
struct pbuf *data = pbuf_alloc(PBUF_RAW, sizeof(udp_payload), PBUF_ROM);
|
||||
u8_t *icmpptr;
|
||||
struct ip6_hdr *outhdr;
|
||||
struct icmp6_hdr *icmp6hdr;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
fail_unless(header);
|
||||
header->payload = udp_hdr;
|
||||
fail_unless(data);
|
||||
data->payload = udp_payload;
|
||||
pbuf_cat(header, data);
|
||||
data = NULL;
|
||||
|
||||
/* Configure and enable local address */
|
||||
netif_set_up(&test_netif6);
|
||||
netif_ip6_addr_set(&test_netif6, 0, ip_2_ip6(&my_addr));
|
||||
netif_ip6_addr_set_state(&test_netif6, 0, IP6_ADDR_VALID);
|
||||
test_netif6.output_ip6 = clone_output;
|
||||
|
||||
/* Process packet and send ICMPv6 reply for unreachable UDP port */
|
||||
ip6_input(header, &test_netif6);
|
||||
header = NULL;
|
||||
|
||||
/* Verify ICMP reply packet contents */
|
||||
fail_unless(cloned_pbuf);
|
||||
fail_unless(cloned_pbuf->len == IP6_HLEN + ICMP6_HLEN + sizeof(udp_hdr) + sizeof(udp_payload));
|
||||
outhdr = (struct ip6_hdr*) cloned_pbuf->payload;
|
||||
fail_unless(ip6_addr_packed_eq(ip_2_ip6(&my_addr), &outhdr->src, IP6_NO_ZONE));
|
||||
fail_unless(ip6_addr_packed_eq(ip_2_ip6(&peer_addr), &outhdr->dest, IP6_NO_ZONE));
|
||||
icmpptr = &((u8_t*)cloned_pbuf->payload)[IP6_HLEN];
|
||||
icmp6hdr = (struct icmp6_hdr*) icmpptr;
|
||||
fail_unless(icmp6hdr->type == ICMP6_TYPE_DUR);
|
||||
fail_unless(icmp6hdr->code == ICMP6_DUR_PORT);
|
||||
fail_unless(icmp6hdr->data == lwip_htonl(0));
|
||||
icmpptr += ICMP6_HLEN;
|
||||
fail_unless(memcmp(icmpptr, udp_hdr, sizeof(udp_hdr)) == 0, "mismatch in copied ip6/udp header");
|
||||
icmpptr += sizeof(udp_hdr);
|
||||
fail_unless(memcmp(icmpptr, udp_payload, sizeof(udp_payload)) == 0, "mismatch in copied udp payload");
|
||||
pbuf_free(cloned_pbuf);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* Reproduces bug #57374 */
|
||||
START_TEST(test_ip6_frag_pbuf_len_assert)
|
||||
{
|
||||
ip_addr_t my_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x1);
|
||||
ip_addr_t peer_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x4);
|
||||
struct pbuf *payload, *hdr;
|
||||
err_t err;
|
||||
int i;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* Configure and enable local address */
|
||||
test_netif6.mtu = 1500;
|
||||
netif_set_up(&test_netif6);
|
||||
netif_ip6_addr_set(&test_netif6, 0, ip_2_ip6(&my_addr));
|
||||
netif_ip6_addr_set_state(&test_netif6, 0, IP6_ADDR_VALID);
|
||||
|
||||
/* Create packet with lots of small pbufs around mtu limit */
|
||||
payload = pbuf_alloc(PBUF_RAW, 1400, PBUF_POOL);
|
||||
fail_unless(payload != NULL);
|
||||
for (i = 0; i < 16; i++) {
|
||||
struct pbuf *p = pbuf_alloc(PBUF_RAW, 32, PBUF_RAM);
|
||||
fail_unless(p != NULL);
|
||||
pbuf_cat(payload, p);
|
||||
}
|
||||
/* Prefix with header like UDP would */
|
||||
hdr = pbuf_alloc(PBUF_IP, 8, PBUF_RAM);
|
||||
fail_unless(hdr != NULL);
|
||||
pbuf_chain(hdr, payload);
|
||||
|
||||
/* Send it and don't crash while fragmenting */
|
||||
err = ip6_output_if_src(hdr, ip_2_ip6(&my_addr), ip_2_ip6(&peer_addr), 15, 0, IP_PROTO_UDP, &test_netif6);
|
||||
fail_unless(err == ERR_OK);
|
||||
|
||||
pbuf_free(hdr);
|
||||
pbuf_free(payload);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static err_t direct_output(struct netif *netif, struct pbuf *p, const ip6_addr_t *addr) {
|
||||
LWIP_UNUSED_ARG(addr);
|
||||
return netif->linkoutput(netif, p);
|
||||
}
|
||||
|
||||
START_TEST(test_ip6_frag)
|
||||
{
|
||||
ip_addr_t my_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x1);
|
||||
ip_addr_t peer_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x4);
|
||||
struct pbuf *data;
|
||||
err_t err;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* Configure and enable local address */
|
||||
test_netif6.mtu = 1500;
|
||||
netif_set_up(&test_netif6);
|
||||
netif_ip6_addr_set(&test_netif6, 0, ip_2_ip6(&my_addr));
|
||||
netif_ip6_addr_set_state(&test_netif6, 0, IP6_ADDR_VALID);
|
||||
test_netif6.output_ip6 = direct_output;
|
||||
/* Reset counters after multicast traffic */
|
||||
linkoutput_ctr = 0;
|
||||
linkoutput_byte_ctr = 0;
|
||||
|
||||
/* Verify that 8000 byte payload is split into six packets */
|
||||
data = pbuf_alloc(PBUF_IP, 8000, PBUF_RAM);
|
||||
fail_unless(data != NULL);
|
||||
err = ip6_output_if_src(data, ip_2_ip6(&my_addr), ip_2_ip6(&peer_addr),
|
||||
15, 0, IP_PROTO_UDP, &test_netif6);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(linkoutput_ctr == 6);
|
||||
fail_unless(linkoutput_byte_ctr == (8000 + (6 * (IP6_HLEN + IP6_FRAG_HLEN))));
|
||||
pbuf_free(data);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void test_ip6_reass_helper(u32_t ip_id, const u16_t *segments, size_t num_segs, u16_t seglen)
|
||||
{
|
||||
ip_addr_t my_addr = IPADDR6_INIT_HOST(0x20010db8, 0x0, 0x0, 0x1);
|
||||
size_t i;
|
||||
|
||||
memset(&lwip_stats.mib2, 0, sizeof(lwip_stats.mib2));
|
||||
memset(&lwip_stats.ip6_frag, 0, sizeof(lwip_stats.ip6_frag));
|
||||
|
||||
netif_set_up(&test_netif6);
|
||||
netif_ip6_addr_set(&test_netif6, 0, ip_2_ip6(&my_addr));
|
||||
netif_ip6_addr_set_state(&test_netif6, 0, IP6_ADDR_VALID);
|
||||
|
||||
for (i = 0; i < num_segs; i++) {
|
||||
u16_t seg = segments[i];
|
||||
int last = seg + 1U == num_segs;
|
||||
create_ip6_input_fragment(ip_id, seg * seglen, seglen, last, IP6_NEXTH_UDP);
|
||||
fail_unless(lwip_stats.ip6_frag.recv == i + 1);
|
||||
fail_unless(lwip_stats.ip6_frag.err == 0);
|
||||
fail_unless(lwip_stats.ip6_frag.memerr == 0);
|
||||
fail_unless(lwip_stats.ip6_frag.drop == 0);
|
||||
if (i + 1 == num_segs) {
|
||||
fail_unless(lwip_stats.mib2.ip6reasmoks == 1);
|
||||
}
|
||||
else {
|
||||
fail_unless(lwip_stats.mib2.ip6reasmoks == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
START_TEST(test_ip6_reass)
|
||||
{
|
||||
#define NUM_SEGS 9
|
||||
const u16_t t1[NUM_SEGS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
|
||||
const u16_t t2[NUM_SEGS] = { 8, 0, 1, 2, 3, 4, 7, 6, 5 };
|
||||
const u16_t t3[NUM_SEGS] = { 1, 2, 3, 4, 5, 6, 7, 8, 0 };
|
||||
const u16_t t4[NUM_SEGS] = { 8, 2, 4, 6, 7, 5, 3, 1, 0 };
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
test_ip6_reass_helper(128, t1, NUM_SEGS, 200);
|
||||
test_ip6_reass_helper(129, t2, NUM_SEGS, 208);
|
||||
test_ip6_reass_helper(130, t3, NUM_SEGS, 8);
|
||||
test_ip6_reass_helper(130, t4, NUM_SEGS, 1448);
|
||||
}
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
ip6_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_ip6_ll_addr),
|
||||
TESTFUNC(test_ip6_aton_ipv4mapped),
|
||||
TESTFUNC(test_ip6_ntoa_ipv4mapped),
|
||||
TESTFUNC(test_ip6_ntoa),
|
||||
TESTFUNC(test_ip6_lladdr),
|
||||
TESTFUNC(test_ip6_dest_unreachable_chained_pbuf),
|
||||
TESTFUNC(test_ip6_frag_pbuf_len_assert),
|
||||
TESTFUNC(test_ip6_frag),
|
||||
TESTFUNC(test_ip6_reass)
|
||||
};
|
||||
return create_suite("IPv6", tests, sizeof(tests)/sizeof(testfunc), ip6_setup, ip6_teardown);
|
||||
}
|
||||
|
||||
#else /* LWIP_IPV6 */
|
||||
|
||||
/* allow to build the unit tests without IPv6 support */
|
||||
START_TEST(test_ip6_dummy)
|
||||
{
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite *
|
||||
ip6_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_ip6_dummy),
|
||||
};
|
||||
return create_suite("IPv6", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL);
|
||||
}
|
||||
#endif /* LWIP_IPV6 */
|
||||
8
lwip/lwip-2.2.1/test/unit/ip6/test_ip6.h
Normal file
8
lwip/lwip-2.2.1/test/unit/ip6/test_ip6.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_IP6_H
|
||||
#define LWIP_HDR_TEST_IP6_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite* ip6_suite(void);
|
||||
|
||||
#endif
|
||||
52
lwip/lwip-2.2.1/test/unit/lwip_check.h
Normal file
52
lwip/lwip-2.2.1/test/unit/lwip_check.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef LWIP_HDR_LWIP_CHECK_H
|
||||
#define LWIP_HDR_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)
|
||||
|
||||
#if (CHECK_MAJOR_VERSION == 0 && CHECK_MINOR_VERSION < 13)
|
||||
typedef struct {
|
||||
TFun func;
|
||||
const char *name;
|
||||
} testfunc;
|
||||
|
||||
#define TESTFUNC(x) {(x), "" # x "" }
|
||||
|
||||
/* Modified function from check.h, supplying function name */
|
||||
#define tcase_add_named_test(tc,tf) \
|
||||
_tcase_add_test((tc),(tf).func,(tf).name,0, 0, 0, 1)
|
||||
|
||||
#else
|
||||
/* From 0.13.0 check keeps track of the method name internally */
|
||||
typedef const TTest * testfunc;
|
||||
|
||||
#define TESTFUNC(x) x
|
||||
|
||||
#define tcase_add_named_test(tc,tf) tcase_add_test(tc,tf)
|
||||
#endif
|
||||
|
||||
/** typedef for a function returning a test suite */
|
||||
typedef Suite* (suite_getter_fn)(void);
|
||||
|
||||
/** Create a test suite */
|
||||
Suite* create_suite(const char* name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown);
|
||||
|
||||
#ifdef LWIP_UNITTESTS_LIB
|
||||
int lwip_unittests_run(void)
|
||||
#endif
|
||||
|
||||
/* helper functions */
|
||||
#define SKIP_POOL(x) (1 << x)
|
||||
#define SKIP_HEAP (1 << MEMP_MAX)
|
||||
void lwip_check_ensure_no_alloc(unsigned int skip);
|
||||
|
||||
#endif /* LWIP_HDR_LWIP_CHECK_H */
|
||||
131
lwip/lwip-2.2.1/test/unit/lwip_unittests.c
Normal file
131
lwip/lwip-2.2.1/test/unit/lwip_unittests.c
Normal file
@ -0,0 +1,131 @@
|
||||
#include "lwip_check.h"
|
||||
|
||||
#include "ip4/test_ip4.h"
|
||||
#include "ip6/test_ip6.h"
|
||||
#include "udp/test_udp.h"
|
||||
#include "tcp/test_tcp.h"
|
||||
#include "tcp/test_tcp_oos.h"
|
||||
#include "tcp/test_tcp_state.h"
|
||||
#include "core/test_def.h"
|
||||
#include "core/test_dns.h"
|
||||
#include "core/test_mem.h"
|
||||
#include "core/test_netif.h"
|
||||
#include "core/test_pbuf.h"
|
||||
#include "core/test_timers.h"
|
||||
#include "etharp/test_etharp.h"
|
||||
#include "dhcp/test_dhcp.h"
|
||||
#include "mdns/test_mdns.h"
|
||||
#include "mqtt/test_mqtt.h"
|
||||
#include "api/test_sockets.h"
|
||||
#include "ppp/test_pppos.h"
|
||||
|
||||
#include "lwip/init.h"
|
||||
#if !NO_SYS
|
||||
#include "lwip/tcpip.h"
|
||||
#endif
|
||||
|
||||
/* This function is used for LWIP_RAND by some ports... */
|
||||
unsigned int
|
||||
lwip_port_rand(void)
|
||||
{
|
||||
return (unsigned int)rand();
|
||||
}
|
||||
|
||||
Suite* create_suite(const char* name, testfunc *tests, size_t num_tests, SFun setup, SFun teardown)
|
||||
{
|
||||
size_t i;
|
||||
Suite *s = suite_create(name);
|
||||
|
||||
for(i = 0; i < num_tests; i++) {
|
||||
TCase *tc_core = tcase_create(name);
|
||||
if ((setup != NULL) || (teardown != NULL)) {
|
||||
tcase_add_checked_fixture(tc_core, setup, teardown);
|
||||
}
|
||||
tcase_add_named_test(tc_core, tests[i]);
|
||||
suite_add_tcase(s, tc_core);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
void lwip_check_ensure_no_alloc(unsigned int skip)
|
||||
{
|
||||
int i;
|
||||
unsigned int mask;
|
||||
|
||||
if (!(skip & SKIP_HEAP)) {
|
||||
fail_unless(lwip_stats.mem.used == 0,
|
||||
"mem heap still has %d bytes allocated", lwip_stats.mem.used);
|
||||
}
|
||||
for (i = 0, mask = 1; i < MEMP_MAX; i++, mask <<= 1) {
|
||||
if (!(skip & mask)) {
|
||||
#if defined(LWIP_DEBUG) || LWIP_STATS_DISPLAY
|
||||
fail_unless(lwip_stats.memp[i]->used == 0,
|
||||
"memp pool '%s' still has %d entries allocated",
|
||||
lwip_stats.memp[i]->name, lwip_stats.memp[i]->used);
|
||||
#else
|
||||
fail_unless(lwip_stats.memp[i]->used == 0,
|
||||
"memp pool %d still has %d entries allocated",
|
||||
i, lwip_stats.memp[i]->used);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef LWIP_UNITTESTS_LIB
|
||||
int lwip_unittests_run(void)
|
||||
#else
|
||||
int main(void)
|
||||
#endif
|
||||
{
|
||||
int number_failed;
|
||||
SRunner *sr;
|
||||
size_t i;
|
||||
suite_getter_fn* suites[] = {
|
||||
ip4_suite,
|
||||
ip6_suite,
|
||||
udp_suite,
|
||||
tcp_suite,
|
||||
tcp_oos_suite,
|
||||
tcp_state_suite,
|
||||
def_suite,
|
||||
dns_suite,
|
||||
mem_suite,
|
||||
netif_suite,
|
||||
pbuf_suite,
|
||||
timers_suite,
|
||||
etharp_suite,
|
||||
dhcp_suite,
|
||||
mdns_suite,
|
||||
mqtt_suite,
|
||||
sockets_suite
|
||||
#if PPP_SUPPORT && PPPOS_SUPPORT
|
||||
, pppos_suite
|
||||
#endif /* PPP_SUPPORT && PPPOS_SUPPORT */
|
||||
};
|
||||
size_t num = sizeof(suites)/sizeof(void*);
|
||||
LWIP_ASSERT("No suites defined", num > 0);
|
||||
|
||||
#if NO_SYS
|
||||
lwip_init();
|
||||
#else
|
||||
tcpip_init(NULL, NULL);
|
||||
#endif
|
||||
|
||||
sr = srunner_create((suites[0])());
|
||||
srunner_set_xml(sr, "lwip_unittests.xml");
|
||||
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;
|
||||
}
|
||||
117
lwip/lwip-2.2.1/test/unit/lwipopts.h
Normal file
117
lwip/lwip-2.2.1/test/unit/lwipopts.h
Normal file
@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2001-2003 Swedish Institute of Computer Science.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Simon Goldschmidt
|
||||
*
|
||||
*/
|
||||
#ifndef LWIP_HDR_LWIPOPTS_H
|
||||
#define LWIP_HDR_LWIPOPTS_H
|
||||
|
||||
#define LWIP_TESTMODE 1
|
||||
|
||||
#define LWIP_IPV6 1
|
||||
|
||||
#define LWIP_CHECKSUM_ON_COPY 1
|
||||
#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK 1
|
||||
#define TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL(printfmsg) LWIP_ASSERT("TCP_CHECKSUM_ON_COPY_SANITY_CHECK_FAIL", 0)
|
||||
|
||||
/* We link to special sys_arch.c (for basic non-waiting API layers unit tests) */
|
||||
#define NO_SYS 0
|
||||
#define SYS_LIGHTWEIGHT_PROT 0
|
||||
#define LWIP_NETCONN !NO_SYS
|
||||
#define LWIP_SOCKET !NO_SYS
|
||||
#define LWIP_NETCONN_FULLDUPLEX LWIP_SOCKET
|
||||
#define LWIP_NETCONN_SEM_PER_THREAD 1
|
||||
#define LWIP_NETBUF_RECVINFO 1
|
||||
#define LWIP_HAVE_LOOPIF 1
|
||||
#define TCPIP_THREAD_TEST
|
||||
|
||||
/* Enable DHCP to test it */
|
||||
#define LWIP_DHCP 1
|
||||
|
||||
/* Enable DNS, with random source port to avoid alloc in dns_init */
|
||||
#define LWIP_DNS 1
|
||||
#define LWIP_DNS_SECURE (LWIP_DNS_SECURE_RAND_XID | LWIP_DNS_SECURE_RAND_SRC_PORT)
|
||||
|
||||
/* Minimal changes to opt.h required for tcp unit tests: */
|
||||
#define MEM_SIZE 17000
|
||||
#define TCP_SND_QUEUELEN 40
|
||||
#define MEMP_NUM_TCP_SEG TCP_SND_QUEUELEN
|
||||
#define TCP_SND_BUF (12 * TCP_MSS)
|
||||
#define TCP_WND (10 * TCP_MSS)
|
||||
#define LWIP_WND_SCALE 1
|
||||
#define TCP_RCV_SCALE 0
|
||||
#define PBUF_POOL_SIZE 400 /* pbuf tests need ~200KByte */
|
||||
|
||||
/* Enable IGMP and MDNS for MDNS tests */
|
||||
#define LWIP_IGMP 1
|
||||
#define LWIP_MDNS_RESPONDER 1
|
||||
#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER)
|
||||
|
||||
/* Enable PPP and PPPOS support for PPPOS test suites */
|
||||
#define PPP_SUPPORT 1
|
||||
#define PPPOS_SUPPORT 1
|
||||
|
||||
/* Minimal changes to opt.h required for etharp unit tests: */
|
||||
#define ETHARP_SUPPORT_STATIC_ENTRIES 1
|
||||
|
||||
#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL + 8)
|
||||
|
||||
/* MIB2 stats are required to check IPv4 reassembly results */
|
||||
#define MIB2_STATS 1
|
||||
|
||||
/* netif tests want to test this, so enable: */
|
||||
#define LWIP_NETIF_EXT_STATUS_CALLBACK 1
|
||||
|
||||
/* Check lwip_stats.mem.illegal instead of asserting */
|
||||
#define LWIP_MEM_ILLEGAL_FREE(msg) /* to nothing */
|
||||
|
||||
/* autodetect if we are running the tests on 32-bit or 64-bit */
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
#if defined(_WIN64)
|
||||
#define PTR64
|
||||
#else
|
||||
#define PTR32
|
||||
#endif
|
||||
#elif defined(__GNUC__)
|
||||
#if defined(__x86_64__) || defined(__ppc64__)
|
||||
#define PTR64
|
||||
#else
|
||||
#define PTR32
|
||||
#endif
|
||||
#elif UINTPTR_MAX > UINT_MAX
|
||||
#define PTR64
|
||||
#else
|
||||
#define PTR32
|
||||
#endif
|
||||
|
||||
#ifdef PTR64
|
||||
#define IPV6_FRAG_COPYHEADER 1
|
||||
#endif
|
||||
|
||||
#endif /* LWIP_HDR_LWIPOPTS_H */
|
||||
916
lwip/lwip-2.2.1/test/unit/mdns/test_mdns.c
Normal file
916
lwip/lwip-2.2.1/test/unit/mdns/test_mdns.c
Normal file
@ -0,0 +1,916 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Verisure Innovation AB
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
||||
* OF SUCH DAMAGE.
|
||||
*
|
||||
* This file is part of the lwIP TCP/IP stack.
|
||||
*
|
||||
* Author: Erik Ekman <erik@kryo.se>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "test_mdns.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/apps/mdns.h"
|
||||
#include "lwip/apps/mdns_domain.h"
|
||||
#include "lwip/apps/mdns_priv.h"
|
||||
|
||||
START_TEST(readname_basic)
|
||||
{
|
||||
static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 };
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == sizeof(data));
|
||||
fail_unless(domain.length == sizeof(data));
|
||||
fail_if(memcmp(&domain.name, data, sizeof(data)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_anydata)
|
||||
{
|
||||
static const u8_t data[] = { 0x05, 0x00, 0xFF, 0x08, 0xc0, 0x0f, 0x04, 0x7f, 0x80, 0x82, 0x88, 0x00 };
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == sizeof(data));
|
||||
fail_unless(domain.length == sizeof(data));
|
||||
fail_if(memcmp(&domain.name, data, sizeof(data)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_short_buf)
|
||||
{
|
||||
static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a' };
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_long_label)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i',
|
||||
0x52, 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a',
|
||||
'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_overflow)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_earlier)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* Some padding needed, not supported to jump to bytes containing dns header */
|
||||
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 10 */ 0x0f, 0x0e, 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab,
|
||||
/* 20 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x0c
|
||||
};
|
||||
static const u8_t fullname[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 20, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == sizeof(data));
|
||||
fail_unless(domain.length == sizeof(fullname));
|
||||
|
||||
fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_earlier_jump)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* Some padding needed, not supported to jump to bytes containing dns header */
|
||||
/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2,
|
||||
/* 0x10 */ 0x04, 'c', 'a', 's', 't', 0x00, 0xc0, 0x10,
|
||||
/* 0x18 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x16
|
||||
};
|
||||
static const u8_t fullname[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 0x18, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == sizeof(data));
|
||||
fail_unless(domain.length == sizeof(fullname));
|
||||
|
||||
fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_maxdepth)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* Some padding needed, not supported to jump to bytes containing dns header */
|
||||
/* 0x00 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 0x08 */ 0x00, 0x00, 0x00, 0x00, 0x03, 0x0b, 0x0a, 0xf2,
|
||||
/* 0x10 */ 0x04, 'n', 'a', 'm', 'e', 0xc0, 0x27, 0x03,
|
||||
/* 0x18 */ 0x03, 'd', 'n', 's', 0xc0, 0x10, 0xc0, 0x10,
|
||||
/* 0x20 */ 0x04, 'd', 'e', 'e', 'p', 0xc0, 0x18, 0x00,
|
||||
/* 0x28 */ 0x04, 'c', 'a', 's', 't', 0xc0, 0x20, 0xb0,
|
||||
/* 0x30 */ 0x05, 'm', 'u', 'l', 't', 'i', 0xc0, 0x28
|
||||
};
|
||||
static const u8_t fullname[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't',
|
||||
0x04, 'd', 'e', 'e', 'p', 0x03, 'd', 'n', 's',
|
||||
0x04, 'n', 'a', 'm', 'e', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 0x30, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == sizeof(data));
|
||||
fail_unless(domain.length == sizeof(fullname));
|
||||
|
||||
fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_later)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* 0x00 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10, 0x00, 0x01, 0x40,
|
||||
/* 0x10 */ 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xab
|
||||
};
|
||||
static const u8_t fullname[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == 13);
|
||||
fail_unless(domain.length == sizeof(fullname));
|
||||
|
||||
fail_if(memcmp(&domain.name, fullname, sizeof(fullname)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_half_jump)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_toolong)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc2, 0x10, 0x00, 0x01, 0x40
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 0, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_loop_label)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x10
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 10, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(readname_jump_loop_jump)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
/* 10 */ 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0xc0, 0x15
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
offset = mdns_readname(p, 10, &domain);
|
||||
pbuf_free(p);
|
||||
fail_unless(offset == MDNS_READNAME_ERROR);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(add_label_basic)
|
||||
{
|
||||
static const u8_t data[] = { 0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00 };
|
||||
struct mdns_domain domain;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == sizeof(data));
|
||||
fail_if(memcmp(&domain.name, data, sizeof(data)));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(add_label_long_label)
|
||||
{
|
||||
static const char *toolong = "abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-abcdefghijklmnopqrstuvwxyz0123456789-";
|
||||
struct mdns_domain domain;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, toolong, (u8_t)strlen(toolong));
|
||||
fail_unless(res == ERR_VAL);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(add_label_full)
|
||||
{
|
||||
static const char *label = "0123456789abcdef0123456789abcdef";
|
||||
struct mdns_domain domain;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 33);
|
||||
res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 66);
|
||||
res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 99);
|
||||
res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 132);
|
||||
res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 165);
|
||||
res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 198);
|
||||
res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 231);
|
||||
res = mdns_domain_add_label(&domain, label, (u8_t)strlen(label));
|
||||
fail_unless(res == ERR_VAL);
|
||||
fail_unless(domain.length == 231);
|
||||
res = mdns_domain_add_label(&domain, label, 25);
|
||||
fail_unless(res == ERR_VAL);
|
||||
fail_unless(domain.length == 231);
|
||||
res = mdns_domain_add_label(&domain, label, 24);
|
||||
fail_unless(res == ERR_VAL);
|
||||
fail_unless(domain.length == 231);
|
||||
res = mdns_domain_add_label(&domain, label, 23);
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 255);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain.length == 256);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_VAL);
|
||||
fail_unless(domain.length == 256);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(domain_eq_basic)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x05, 'm', 'u', 'l', 't', 'i', 0x04, 'c', 'a', 's', 't', 0x00
|
||||
};
|
||||
struct mdns_domain domain1, domain2;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&domain1, 0, sizeof(domain1));
|
||||
res = mdns_domain_add_label(&domain1, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
fail_unless(domain1.length == sizeof(data));
|
||||
|
||||
memset(&domain2, 0, sizeof(domain2));
|
||||
res = mdns_domain_add_label(&domain2, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(mdns_domain_eq(&domain1, &domain2));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(domain_eq_diff)
|
||||
{
|
||||
struct mdns_domain domain1, domain2;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&domain1, 0, sizeof(domain1));
|
||||
res = mdns_domain_add_label(&domain1, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, "base", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
memset(&domain2, 0, sizeof(domain2));
|
||||
res = mdns_domain_add_label(&domain2, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_if(mdns_domain_eq(&domain1, &domain2));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(domain_eq_case)
|
||||
{
|
||||
struct mdns_domain domain1, domain2;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&domain1, 0, sizeof(domain1));
|
||||
res = mdns_domain_add_label(&domain1, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
memset(&domain2, 0, sizeof(domain2));
|
||||
res = mdns_domain_add_label(&domain2, "MulTI", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, "casT", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(mdns_domain_eq(&domain1, &domain2));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(domain_eq_anydata)
|
||||
{
|
||||
static const u8_t data1[] = { 0x05, 0xcc, 0xdc, 0x00, 0xa0 };
|
||||
static const u8_t data2[] = { 0x7f, 0x8c, 0x01, 0xff, 0xcf };
|
||||
struct mdns_domain domain1, domain2;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&domain1, 0, sizeof(domain1));
|
||||
res = mdns_domain_add_label(&domain1, (const char*)data1, sizeof(data1));
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, (const char*)data2, sizeof(data2));
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
memset(&domain2, 0, sizeof(domain2));
|
||||
res = mdns_domain_add_label(&domain2, (const char*)data1, sizeof(data1));
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, "casT", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, (const char*)data2, sizeof(data2));
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(mdns_domain_eq(&domain1, &domain2));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(domain_eq_length)
|
||||
{
|
||||
struct mdns_domain domain1, domain2;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
memset(&domain1, 0, sizeof(domain1));
|
||||
memset(domain1.name, 0xAA, sizeof(MDNS_DOMAIN_MAXLEN));
|
||||
res = mdns_domain_add_label(&domain1, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain1, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
memset(&domain2, 0, sizeof(domain2));
|
||||
memset(domain2.name, 0xBB, sizeof(MDNS_DOMAIN_MAXLEN));
|
||||
res = mdns_domain_add_label(&domain2, "multi", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain2, "cast", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
fail_unless(mdns_domain_eq(&domain1, &domain2));
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_full_match)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u16_t length;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 0 bytes, then a jump to addr 2 */
|
||||
fail_unless(length == 0);
|
||||
fail_unless(offset == 2);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_full_match_subset)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x02, 'g', 'o', 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u16_t length;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 0 bytes, then a jump to addr 5 */
|
||||
fail_unless(length == 0);
|
||||
fail_unless(offset == 5);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_full_match_jump)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
/* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00,
|
||||
/* 0x20 */ 0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0xc0, 0x15
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u16_t length;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 0x20;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 0 bytes, then a jump to addr 0x20 */
|
||||
fail_unless(length == 0);
|
||||
fail_unless(offset == 0x20);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_no_match)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x04, 'l', 'w', 'i', 'p', 0x05, 'w', 'i', 'k', 'i', 'a', 0x03, 'c', 'o', 'm', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u16_t length;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write all bytes, no jump */
|
||||
fail_unless(length == domain.length);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_2nd_label)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u16_t length;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "lwip", 4);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 5 bytes, then a jump to addr 9 */
|
||||
fail_unless(length == 5);
|
||||
fail_unless(offset == 9);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_2nd_label_short)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u16_t length;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 5 bytes, then a jump to addr 7 */
|
||||
fail_unless(length == 7);
|
||||
fail_unless(offset == 7);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_jump_to_jump)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
/* 0x00 */ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
||||
/* 0x10 */ 0x04, 'l', 'w', 'i', 'p', 0x05, 'l', 'o', 'c', 'a', 'l', 0x00, 0xc0, 0x00, 0x02, 0x00,
|
||||
/* 0x20 */ 0x07, 'b', 'a', 'n', 'a', 'n', 'a', 's', 0xc0, 0x15
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u16_t length;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 0x20;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Don't compress if jump would be to a jump */
|
||||
fail_unless(length == domain.length);
|
||||
|
||||
offset = 0x10;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
/* Write 7 bytes, then a jump to addr 0x15 */
|
||||
fail_unless(length == 7);
|
||||
fail_unless(offset == 0x15);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(compress_long_match)
|
||||
{
|
||||
static const u8_t data[] = {
|
||||
0x00, 0x00,
|
||||
0x06, 'f', 'o', 'o', 'b', 'a', 'r', 0x05, 'l', 'o', 'c', 'a', 'l', 0x03, 'c', 'o', 'm', 0x00
|
||||
};
|
||||
struct pbuf *p;
|
||||
struct mdns_domain domain;
|
||||
u16_t offset;
|
||||
u16_t length;
|
||||
err_t res;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(data), PBUF_ROM);
|
||||
fail_if(p == NULL);
|
||||
p->payload = (void *)(size_t)data;
|
||||
|
||||
memset(&domain, 0, sizeof(domain));
|
||||
res = mdns_domain_add_label(&domain, "foobar", 6);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, "local", 5);
|
||||
fail_unless(res == ERR_OK);
|
||||
res = mdns_domain_add_label(&domain, NULL, 0);
|
||||
fail_unless(res == ERR_OK);
|
||||
|
||||
offset = 2;
|
||||
length = mdns_compress_domain(p, &offset, &domain);
|
||||
fail_unless(length == domain.length);
|
||||
|
||||
pbuf_free(p);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite* mdns_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(readname_basic),
|
||||
TESTFUNC(readname_anydata),
|
||||
TESTFUNC(readname_short_buf),
|
||||
TESTFUNC(readname_long_label),
|
||||
TESTFUNC(readname_overflow),
|
||||
TESTFUNC(readname_jump_earlier),
|
||||
TESTFUNC(readname_jump_earlier_jump),
|
||||
TESTFUNC(readname_jump_maxdepth),
|
||||
TESTFUNC(readname_jump_later),
|
||||
TESTFUNC(readname_half_jump),
|
||||
TESTFUNC(readname_jump_toolong),
|
||||
TESTFUNC(readname_jump_loop_label),
|
||||
TESTFUNC(readname_jump_loop_jump),
|
||||
|
||||
TESTFUNC(add_label_basic),
|
||||
TESTFUNC(add_label_long_label),
|
||||
TESTFUNC(add_label_full),
|
||||
|
||||
TESTFUNC(domain_eq_basic),
|
||||
TESTFUNC(domain_eq_diff),
|
||||
TESTFUNC(domain_eq_case),
|
||||
TESTFUNC(domain_eq_anydata),
|
||||
TESTFUNC(domain_eq_length),
|
||||
|
||||
TESTFUNC(compress_full_match),
|
||||
TESTFUNC(compress_full_match_subset),
|
||||
TESTFUNC(compress_full_match_jump),
|
||||
TESTFUNC(compress_no_match),
|
||||
TESTFUNC(compress_2nd_label),
|
||||
TESTFUNC(compress_2nd_label_short),
|
||||
TESTFUNC(compress_jump_to_jump),
|
||||
TESTFUNC(compress_long_match),
|
||||
};
|
||||
return create_suite("MDNS", tests, sizeof(tests)/sizeof(testfunc), NULL, NULL);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/mdns/test_mdns.h
Normal file
8
lwip/lwip-2.2.1/test/unit/mdns/test_mdns.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_MDNS_H__
|
||||
#define LWIP_HDR_TEST_MDNS_H__
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite* mdns_suite(void);
|
||||
|
||||
#endif
|
||||
115
lwip/lwip-2.2.1/test/unit/mqtt/test_mqtt.c
Normal file
115
lwip/lwip-2.2.1/test/unit/mqtt/test_mqtt.c
Normal file
@ -0,0 +1,115 @@
|
||||
#include "test_mqtt.h"
|
||||
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/apps/mqtt.h"
|
||||
#include "lwip/apps/mqtt_priv.h"
|
||||
#include "lwip/netif.h"
|
||||
|
||||
const ip_addr_t test_mqtt_local_ip = IPADDR4_INIT_BYTES(192, 168, 1, 1);
|
||||
const ip_addr_t test_mqtt_remote_ip = IPADDR4_INIT_BYTES(192, 168, 1, 2);
|
||||
const ip_addr_t test_mqtt_netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0);
|
||||
|
||||
static err_t test_mqtt_netif_output(struct netif *netif, struct pbuf *p,
|
||||
const ip4_addr_t *ipaddr)
|
||||
{
|
||||
LWIP_UNUSED_ARG(netif);
|
||||
LWIP_UNUSED_ARG(ipaddr);
|
||||
LWIP_UNUSED_ARG(p);
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
test_mqtt_init_netif(struct netif *netif, const ip_addr_t *ip_addr, const ip_addr_t *netmask)
|
||||
{
|
||||
struct netif *n;
|
||||
memset(netif, 0, sizeof(struct netif));
|
||||
netif->output = test_mqtt_netif_output;
|
||||
netif->flags |= NETIF_FLAG_UP | NETIF_FLAG_LINK_UP;
|
||||
ip_addr_copy_from_ip4(netif->netmask, *ip_2_ip4(netmask));
|
||||
ip_addr_copy_from_ip4(netif->ip_addr, *ip_2_ip4(ip_addr));
|
||||
for (n = netif_list; n != NULL; n = n->next) {
|
||||
if (n == netif) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
netif->next = NULL;
|
||||
netif_list = netif;
|
||||
}
|
||||
|
||||
/* Setups/teardown functions */
|
||||
static struct netif *old_netif_list;
|
||||
static struct netif *old_netif_default;
|
||||
|
||||
static void
|
||||
mqtt_setup(void)
|
||||
{
|
||||
old_netif_list = netif_list;
|
||||
old_netif_default = netif_default;
|
||||
netif_list = NULL;
|
||||
netif_default = NULL;
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void
|
||||
mqtt_teardown(void)
|
||||
{
|
||||
netif_list = NULL;
|
||||
netif_default = NULL;
|
||||
/* restore netif_list for next tests (e.g. loopif) */
|
||||
netif_list = old_netif_list;
|
||||
netif_default = old_netif_default;
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void test_mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status)
|
||||
{
|
||||
LWIP_UNUSED_ARG(client);
|
||||
LWIP_UNUSED_ARG(arg);
|
||||
LWIP_UNUSED_ARG(status);
|
||||
}
|
||||
|
||||
START_TEST(basic_connect)
|
||||
{
|
||||
mqtt_client_t* client;
|
||||
struct netif netif;
|
||||
err_t err;
|
||||
struct mqtt_connect_client_info_t client_info = {
|
||||
"dumm",
|
||||
NULL, NULL,
|
||||
10,
|
||||
NULL, NULL, 0, 0, 0
|
||||
};
|
||||
struct pbuf *p;
|
||||
unsigned char rxbuf[] = {0x20, 0x02, 0x00, 0x00};
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
test_mqtt_init_netif(&netif, &test_mqtt_local_ip, &test_mqtt_netmask);
|
||||
|
||||
client = mqtt_client_new();
|
||||
fail_unless(client != NULL);
|
||||
err = mqtt_client_connect(client, &test_mqtt_remote_ip, 1234, test_mqtt_connection_cb, NULL, &client_info);
|
||||
fail_unless(err == ERR_OK);
|
||||
|
||||
client->conn->connected(client->conn->callback_arg, client->conn, ERR_OK);
|
||||
p = pbuf_alloc(PBUF_RAW, sizeof(rxbuf), PBUF_REF);
|
||||
fail_unless(p != NULL);
|
||||
p->payload = rxbuf;
|
||||
/* since we hack the rx path, we have to hack the rx window, too: */
|
||||
client->conn->rcv_wnd -= p->tot_len;
|
||||
if (client->conn->recv(client->conn->callback_arg, client->conn, p, ERR_OK) != ERR_OK) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
|
||||
mqtt_disconnect(client);
|
||||
/* fixme: mqtt_client_fre() is missing... */
|
||||
mem_free(client);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
Suite* mqtt_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(basic_connect),
|
||||
};
|
||||
return create_suite("MQTT", tests, sizeof(tests)/sizeof(testfunc), mqtt_setup, mqtt_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/mqtt/test_mqtt.h
Normal file
8
lwip/lwip-2.2.1/test/unit/mqtt/test_mqtt.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_MQTT_H__
|
||||
#define LWIP_HDR_TEST_MQTT_H__
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite* mqtt_suite(void);
|
||||
|
||||
#endif
|
||||
67
lwip/lwip-2.2.1/test/unit/ppp/test_pppos.c
Normal file
67
lwip/lwip-2.2.1/test/unit/ppp/test_pppos.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include "test_pppos.h"
|
||||
|
||||
#include "lwip/netif.h"
|
||||
#include "netif/ppp/pppos.h"
|
||||
#include "netif/ppp/ppp.h"
|
||||
|
||||
#if PPP_SUPPORT && PPPOS_SUPPORT
|
||||
static struct netif pppos_netif;
|
||||
static ppp_pcb *ppp;
|
||||
|
||||
static u32_t ppp_output_cb(ppp_pcb *pcb, const void *data, u32_t len, void *ctx)
|
||||
{
|
||||
LWIP_UNUSED_ARG(pcb);
|
||||
LWIP_UNUSED_ARG(data);
|
||||
LWIP_UNUSED_ARG(len);
|
||||
LWIP_UNUSED_ARG(ctx);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ppp_link_status_cb(ppp_pcb *pcb, int err_code, void *ctx)
|
||||
{
|
||||
LWIP_UNUSED_ARG(pcb);
|
||||
LWIP_UNUSED_ARG(err_code);
|
||||
LWIP_UNUSED_ARG(ctx);
|
||||
}
|
||||
|
||||
static void pppos_setup(void)
|
||||
{
|
||||
ppp = pppos_create(&pppos_netif, ppp_output_cb, ppp_link_status_cb, NULL);
|
||||
fail_if(ppp == NULL);
|
||||
ppp_connect(ppp, 0);
|
||||
}
|
||||
|
||||
static void pppos_teardown(void)
|
||||
{
|
||||
}
|
||||
|
||||
START_TEST(test_pppos_empty_packet_with_valid_fcs)
|
||||
{
|
||||
u8_t two_breaks[] = { 0x7e, 0, 0, 0x7e };
|
||||
u8_t other_packet[] = { 0x7e, 0x7d, 0x20, 0x00, 0x7e };
|
||||
/* Set internal states of the underlying pcb */
|
||||
pppos_pcb *pppos = (pppos_pcb *)ppp->link_ctx_cb;
|
||||
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
pppos->open = 1; /* Pretend the connection is open already */
|
||||
pppos->in_accm[0] = 0xf0; /* Make sure 0x0's are not escaped chars */
|
||||
|
||||
pppos_input(ppp, two_breaks, sizeof(two_breaks));
|
||||
pppos_input(ppp, other_packet, sizeof(other_packet));
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
pppos_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_pppos_empty_packet_with_valid_fcs)
|
||||
};
|
||||
return create_suite("PPPOS", tests, sizeof(tests)/sizeof(testfunc), pppos_setup, pppos_teardown);
|
||||
}
|
||||
|
||||
#endif /* PPP_SUPPORT && PPPOS_SUPPORT */
|
||||
13
lwip/lwip-2.2.1/test/unit/ppp/test_pppos.h
Normal file
13
lwip/lwip-2.2.1/test/unit/ppp/test_pppos.h
Normal file
@ -0,0 +1,13 @@
|
||||
#ifndef LWIP_HDR_TEST_PPPOS_H
|
||||
#define LWIP_HDR_TEST_PPPOS_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
#include "netif/ppp/ppp.h"
|
||||
|
||||
#if PPP_SUPPORT && PPPOS_SUPPORT
|
||||
|
||||
Suite* pppos_suite(void);
|
||||
|
||||
#endif /* PPP_SUPPORT && PPPOS_SUPPORT */
|
||||
|
||||
#endif /* LWIP_HDR_TEST_PPPOS_H */
|
||||
325
lwip/lwip-2.2.1/test/unit/tcp/tcp_helper.c
Normal file
325
lwip/lwip-2.2.1/test/unit/tcp/tcp_helper.c
Normal file
@ -0,0 +1,325 @@
|
||||
#include "tcp_helper.h"
|
||||
|
||||
#include "lwip/priv/tcp_priv.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/pbuf.h"
|
||||
#include "lwip/inet.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
#include "lwip/ip_addr.h"
|
||||
|
||||
#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
|
||||
#error "This tests needs TCP- and MEMP-statistics enabled"
|
||||
#endif
|
||||
|
||||
const ip_addr_t test_local_ip = IPADDR4_INIT_BYTES(192, 168, 1, 1);
|
||||
const ip_addr_t test_remote_ip = IPADDR4_INIT_BYTES(192, 168, 1, 2);
|
||||
const ip_addr_t test_netmask = IPADDR4_INIT_BYTES(255, 255, 255, 0);
|
||||
|
||||
/** 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;
|
||||
if (pcb2->state == LISTEN) {
|
||||
tcp_close(pcb2);
|
||||
} else {
|
||||
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_bound_pcbs);
|
||||
tcp_remove(tcp_active_pcbs);
|
||||
tcp_remove(tcp_tw_pcbs);
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) == 0);
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_TCP_SEG) == 0);
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_PBUF_POOL) == 0);
|
||||
}
|
||||
|
||||
/** Create a TCP segment usable for passing to tcp_input */
|
||||
static struct pbuf*
|
||||
tcp_create_segment_wnd(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, u16_t wnd)
|
||||
{
|
||||
struct pbuf *p, *q;
|
||||
struct ip_hdr* iphdr;
|
||||
struct tcp_hdr* tcphdr;
|
||||
u16_t pbuf_len = (u16_t)(sizeof(struct ip_hdr) + sizeof(struct tcp_hdr) + data_len);
|
||||
LWIP_ASSERT("data_len too big", data_len <= 0xFFFF);
|
||||
|
||||
p = pbuf_alloc(PBUF_RAW, pbuf_len, PBUF_POOL);
|
||||
EXPECT_RETNULL(p != NULL);
|
||||
/* first pbuf must be big enough to hold the headers */
|
||||
EXPECT_RETNULL(p->len >= (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr)));
|
||||
if (data_len > 0) {
|
||||
/* first pbuf must be big enough to hold at least 1 data byte, too */
|
||||
EXPECT_RETNULL(p->len > (sizeof(struct ip_hdr) + sizeof(struct tcp_hdr)));
|
||||
}
|
||||
|
||||
for(q = p; q != NULL; q = q->next) {
|
||||
memset(q->payload, 0, q->len);
|
||||
}
|
||||
|
||||
iphdr = (struct ip_hdr*)p->payload;
|
||||
/* fill IP header */
|
||||
iphdr->dest.addr = ip_2_ip4(dst_ip)->addr;
|
||||
iphdr->src.addr = ip_2_ip4(src_ip)->addr;
|
||||
IPH_VHL_SET(iphdr, 4, IP_HLEN / 4);
|
||||
IPH_TOS_SET(iphdr, 0);
|
||||
IPH_LEN_SET(iphdr, htons(p->tot_len));
|
||||
IPH_CHKSUM_SET(iphdr, inet_chksum(iphdr, IP_HLEN));
|
||||
|
||||
/* let p point to TCP header */
|
||||
pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
|
||||
|
||||
tcphdr = (struct tcp_hdr*)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(wnd);
|
||||
|
||||
if (data_len > 0) {
|
||||
/* let p point to TCP data */
|
||||
pbuf_header(p, -(s16_t)sizeof(struct tcp_hdr));
|
||||
/* copy data */
|
||||
pbuf_take(p, data, (u16_t)data_len);
|
||||
/* let p point to TCP header again */
|
||||
pbuf_header(p, sizeof(struct tcp_hdr));
|
||||
}
|
||||
|
||||
/* calculate checksum */
|
||||
|
||||
tcphdr->chksum = ip_chksum_pseudo(p,
|
||||
IP_PROTO_TCP, p->tot_len, src_ip, dst_ip);
|
||||
|
||||
pbuf_header(p, sizeof(struct ip_hdr));
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/** 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)
|
||||
{
|
||||
return tcp_create_segment_wnd(src_ip, dst_ip, src_port, dst_port, data,
|
||||
data_len, seqno, ackno, headerflags, TCP_WND);
|
||||
}
|
||||
|
||||
/** 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->lastack + ackno_offset, headerflags);
|
||||
}
|
||||
|
||||
/** 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
|
||||
* - TCP window can be adjusted
|
||||
*/
|
||||
struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len,
|
||||
u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd)
|
||||
{
|
||||
return tcp_create_segment_wnd(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port, pcb->local_port,
|
||||
data, data_len, pcb->rcv_nxt + seqno_offset, pcb->lastack + ackno_offset, headerflags, wnd);
|
||||
}
|
||||
|
||||
/** Safely bring a tcp_pcb into the requested state */
|
||||
void
|
||||
tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, const ip_addr_t* local_ip,
|
||||
const ip_addr_t* remote_ip, u16_t local_port, u16_t remote_port)
|
||||
{
|
||||
u32_t iss;
|
||||
|
||||
/* @todo: are these all states? */
|
||||
/* @todo: remove from previous list */
|
||||
pcb->state = state;
|
||||
|
||||
iss = tcp_next_iss(pcb);
|
||||
pcb->snd_wl2 = iss;
|
||||
pcb->snd_nxt = iss;
|
||||
pcb->lastack = iss;
|
||||
pcb->snd_lbb = iss;
|
||||
|
||||
if (state == ESTABLISHED) {
|
||||
TCP_REG(&tcp_active_pcbs, pcb);
|
||||
ip_addr_copy(pcb->local_ip, *local_ip);
|
||||
pcb->local_port = local_port;
|
||||
ip_addr_copy(pcb->remote_ip, *remote_ip);
|
||||
pcb->remote_port = remote_port;
|
||||
} else if(state == LISTEN) {
|
||||
TCP_REG(&tcp_listen_pcbs.pcbs, pcb);
|
||||
ip_addr_copy(pcb->local_ip, *local_ip);
|
||||
pcb->local_port = local_port;
|
||||
} else if(state == TIME_WAIT) {
|
||||
TCP_REG(&tcp_tw_pcbs, pcb);
|
||||
ip_addr_copy(pcb->local_ip, *local_ip);
|
||||
pcb->local_port = local_port;
|
||||
ip_addr_copy(pcb->remote_ip, *remote_ip);
|
||||
pcb->remote_port = remote_port;
|
||||
} else {
|
||||
fail();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
test_tcp_counters_err(void* arg, err_t err)
|
||||
{
|
||||
struct test_tcp_counters* counters = (struct test_tcp_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 = (char*)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 = (struct test_tcp_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);
|
||||
pcb->snd_wnd = TCP_WND;
|
||||
pcb->snd_wnd_max = TCP_WND;
|
||||
}
|
||||
return pcb;
|
||||
}
|
||||
|
||||
/** Calls tcp_input() after adjusting current_iphdr_dest */
|
||||
void test_tcp_input(struct pbuf *p, struct netif *inp)
|
||||
{
|
||||
struct ip_hdr *iphdr = (struct ip_hdr*)p->payload;
|
||||
/* these lines are a hack, don't use them as an example :-) */
|
||||
ip_addr_copy_from_ip4(*ip_current_dest_addr(), iphdr->dest);
|
||||
ip_addr_copy_from_ip4(*ip_current_src_addr(), iphdr->src);
|
||||
ip_current_netif() = inp;
|
||||
ip_data.current_ip4_header = iphdr;
|
||||
ip_data.current_input_netif = inp;
|
||||
|
||||
/* since adding IPv6, p->payload must point to tcp header, not ip header */
|
||||
pbuf_header(p, -(s16_t)sizeof(struct ip_hdr));
|
||||
|
||||
tcp_input(p, inp);
|
||||
|
||||
ip_addr_set_zero(ip_current_dest_addr());
|
||||
ip_addr_set_zero(ip_current_src_addr());
|
||||
ip_current_netif() = NULL;
|
||||
ip_data.current_ip4_header = NULL;
|
||||
}
|
||||
|
||||
static err_t test_tcp_netif_output(struct netif *netif, struct pbuf *p,
|
||||
const ip4_addr_t *ipaddr)
|
||||
{
|
||||
struct test_tcp_txcounters *txcounters = (struct test_tcp_txcounters*)netif->state;
|
||||
LWIP_UNUSED_ARG(ipaddr);
|
||||
if (txcounters != NULL)
|
||||
{
|
||||
txcounters->num_tx_calls++;
|
||||
txcounters->num_tx_bytes += p->tot_len;
|
||||
if (txcounters->copy_tx_packets) {
|
||||
struct pbuf *p_copy = pbuf_alloc(PBUF_LINK, p->tot_len, PBUF_RAM);
|
||||
err_t err;
|
||||
EXPECT(p_copy != NULL);
|
||||
err = pbuf_copy(p_copy, p);
|
||||
EXPECT(err == ERR_OK);
|
||||
if (txcounters->tx_packets == NULL) {
|
||||
txcounters->tx_packets = p_copy;
|
||||
} else {
|
||||
pbuf_cat(txcounters->tx_packets, p_copy);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters,
|
||||
const ip_addr_t *ip_addr, const ip_addr_t *netmask)
|
||||
{
|
||||
struct netif *n;
|
||||
memset(netif, 0, sizeof(struct netif));
|
||||
if (txcounters != NULL) {
|
||||
memset(txcounters, 0, sizeof(struct test_tcp_txcounters));
|
||||
netif->state = txcounters;
|
||||
}
|
||||
netif->output = test_tcp_netif_output;
|
||||
netif->flags |= NETIF_FLAG_UP | NETIF_FLAG_LINK_UP;
|
||||
ip_addr_copy_from_ip4(netif->netmask, *ip_2_ip4(netmask));
|
||||
ip_addr_copy_from_ip4(netif->ip_addr, *ip_2_ip4(ip_addr));
|
||||
for (n = netif_list; n != NULL; n = n->next) {
|
||||
if (n == netif) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
netif->next = NULL;
|
||||
netif_list = netif;
|
||||
}
|
||||
58
lwip/lwip-2.2.1/test/unit/tcp/tcp_helper.h
Normal file
58
lwip/lwip-2.2.1/test/unit/tcp/tcp_helper.h
Normal file
@ -0,0 +1,58 @@
|
||||
#ifndef LWIP_HDR_TCP_HELPER_H
|
||||
#define LWIP_HDR_TCP_HELPER_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
#include "lwip/arch.h"
|
||||
#include "lwip/tcp.h"
|
||||
#include "lwip/netif.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;
|
||||
};
|
||||
|
||||
struct test_tcp_txcounters {
|
||||
u32_t num_tx_calls;
|
||||
u32_t num_tx_bytes;
|
||||
u8_t copy_tx_packets;
|
||||
struct pbuf *tx_packets;
|
||||
};
|
||||
|
||||
extern const ip_addr_t test_local_ip;
|
||||
extern const ip_addr_t test_remote_ip;
|
||||
extern const ip_addr_t test_netmask;
|
||||
#define TEST_REMOTE_PORT 0x100
|
||||
#define TEST_LOCAL_PORT 0x101
|
||||
|
||||
/* 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);
|
||||
struct pbuf* tcp_create_rx_segment_wnd(struct tcp_pcb* pcb, void* data, size_t data_len,
|
||||
u32_t seqno_offset, u32_t ackno_offset, u8_t headerflags, u16_t wnd);
|
||||
void tcp_set_state(struct tcp_pcb* pcb, enum tcp_state state, const ip_addr_t* local_ip,
|
||||
const 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);
|
||||
|
||||
void test_tcp_input(struct pbuf *p, struct netif *inp);
|
||||
|
||||
void test_tcp_init_netif(struct netif *netif, struct test_tcp_txcounters *txcounters,
|
||||
const ip_addr_t *ip_addr, const ip_addr_t *netmask);
|
||||
|
||||
|
||||
#endif
|
||||
1700
lwip/lwip-2.2.1/test/unit/tcp/test_tcp.c
Normal file
1700
lwip/lwip-2.2.1/test/unit/tcp/test_tcp.c
Normal file
File diff suppressed because it is too large
Load Diff
8
lwip/lwip-2.2.1/test/unit/tcp/test_tcp.h
Normal file
8
lwip/lwip-2.2.1/test/unit/tcp/test_tcp.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_TCP_H
|
||||
#define LWIP_HDR_TEST_TCP_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *tcp_suite(void);
|
||||
|
||||
#endif
|
||||
1018
lwip/lwip-2.2.1/test/unit/tcp/test_tcp_oos.c
Normal file
1018
lwip/lwip-2.2.1/test/unit/tcp/test_tcp_oos.c
Normal file
File diff suppressed because it is too large
Load Diff
8
lwip/lwip-2.2.1/test/unit/tcp/test_tcp_oos.h
Normal file
8
lwip/lwip-2.2.1/test/unit/tcp/test_tcp_oos.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_TCP_OOS_H
|
||||
#define LWIP_HDR_TEST_TCP_OOS_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *tcp_oos_suite(void);
|
||||
|
||||
#endif
|
||||
665
lwip/lwip-2.2.1/test/unit/tcp/test_tcp_state.c
Normal file
665
lwip/lwip-2.2.1/test/unit/tcp/test_tcp_state.c
Normal file
@ -0,0 +1,665 @@
|
||||
#include "test_tcp_state.h"
|
||||
|
||||
#include "lwip/priv/tcp_priv.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "tcp_helper.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable: 4307) /* we explicitly wrap around TCP seqnos */
|
||||
#endif
|
||||
|
||||
#if !LWIP_STATS || !TCP_STATS || !MEMP_STATS
|
||||
#error "This tests needs TCP- and MEMP-statistics enabled"
|
||||
#endif
|
||||
|
||||
static struct netif test_netif = {0};
|
||||
static struct test_tcp_txcounters test_txcounters = {0};
|
||||
|
||||
#define SEQNO1 (0xFFFFFF00 - TCP_MSS)
|
||||
#define ISS 6510
|
||||
static u8_t test_tcp_timer;
|
||||
|
||||
/* our own version of tcp_tmr so we can reset fast/slow timer state */
|
||||
static void
|
||||
test_tcp_tmr(void)
|
||||
{
|
||||
tcp_fasttmr();
|
||||
if (++test_tcp_timer & 1) {
|
||||
tcp_slowtmr();
|
||||
}
|
||||
}
|
||||
|
||||
/* Get TCP flags from packets */
|
||||
static u8_t
|
||||
get_tcp_flags_from_packet(struct pbuf *p, u16_t tcp_hdr_offset)
|
||||
{
|
||||
struct tcp_hdr tcphdr;
|
||||
u16_t ret;
|
||||
EXPECT_RETX(p != NULL, 0);
|
||||
EXPECT_RETX(p->len >= tcp_hdr_offset + sizeof(struct tcp_hdr), 0);
|
||||
ret = pbuf_copy_partial(p, &tcphdr, sizeof(struct tcp_hdr), tcp_hdr_offset);
|
||||
EXPECT(ret == sizeof(struct tcp_hdr));
|
||||
return TCPH_FLAGS(&tcphdr);
|
||||
}
|
||||
|
||||
/* Create listening tcp_pcb */
|
||||
static struct tcp_pcb_listen *
|
||||
create_listening_pcb(u16_t local_port, struct test_tcp_counters *counters)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
struct tcp_pcb_listen *lpcb=NULL;
|
||||
err_t err;
|
||||
u16_t port = local_port?local_port:1234;
|
||||
|
||||
if (counters) {
|
||||
pcb = test_tcp_new_counters_pcb(counters);
|
||||
} else {
|
||||
pcb = tcp_new();
|
||||
}
|
||||
EXPECT(pcb != NULL);
|
||||
|
||||
if (pcb) {
|
||||
err = tcp_bind(pcb, &test_netif.ip_addr, port);
|
||||
EXPECT(err == ERR_OK);
|
||||
lpcb = (struct tcp_pcb_listen *)tcp_listen(pcb);
|
||||
}
|
||||
|
||||
return lpcb;
|
||||
}
|
||||
|
||||
/* Setup/teardown functions */
|
||||
static struct netif* old_netif_list;
|
||||
static struct netif* old_netif_default;
|
||||
|
||||
static void
|
||||
tcp_state_setup(void)
|
||||
{
|
||||
struct tcp_pcb dummy_pcb; /* we need this for tcp_next_iss() only */
|
||||
|
||||
/* reset iss to default (6510) */
|
||||
tcp_ticks = 0;
|
||||
tcp_ticks = 0 - (tcp_next_iss(&dummy_pcb) - 6510);
|
||||
tcp_next_iss(&dummy_pcb);
|
||||
tcp_ticks = 0;
|
||||
|
||||
test_tcp_timer = 0;
|
||||
|
||||
old_netif_list = netif_list;
|
||||
old_netif_default = netif_default;
|
||||
netif_list = NULL;
|
||||
netif_default = NULL;
|
||||
tcp_remove_all();
|
||||
test_tcp_init_netif(&test_netif, &test_txcounters, &test_local_ip, &test_netmask);
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void
|
||||
tcp_state_teardown(void)
|
||||
{
|
||||
netif_list = NULL;
|
||||
netif_default = NULL;
|
||||
tcp_remove_all();
|
||||
/* restore netif_list for next tests (e.g. loopif) */
|
||||
netif_list = old_netif_list;
|
||||
netif_default = old_netif_default;
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
/* helper functions */
|
||||
|
||||
static void
|
||||
test_rst_generation_with_incoming_packet(struct pbuf *p,
|
||||
struct netif *netif, struct test_tcp_txcounters *tx_counters)
|
||||
{
|
||||
u16_t tcp_flags;
|
||||
EXPECT_RET(p != NULL);
|
||||
memset(tx_counters, 0, sizeof(struct test_tcp_txcounters));
|
||||
/* pass the segment to tcp_input */
|
||||
tx_counters->copy_tx_packets = 1;
|
||||
test_tcp_input(p, netif);
|
||||
tx_counters->copy_tx_packets = 0;
|
||||
/* check if packets are as expected */
|
||||
EXPECT(tx_counters->tx_packets != NULL);
|
||||
if (tx_counters->tx_packets) {
|
||||
tcp_flags = get_tcp_flags_from_packet(tx_counters->tx_packets, 20);
|
||||
EXPECT(tcp_flags & TCP_RST);
|
||||
pbuf_free(tx_counters->tx_packets);
|
||||
tx_counters->tx_packets = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Test functions */
|
||||
|
||||
/* Call tcp_new() and test memp stats (max number) */
|
||||
START_TEST(test_tcp_new_max_num)
|
||||
{
|
||||
struct tcp_pcb* pcb[MEMP_NUM_TCP_PCB + 1];
|
||||
int i;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
|
||||
for(i = 0;i < MEMP_NUM_TCP_PCB; i++) {
|
||||
pcb[i] = tcp_new();
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == (i + 1));
|
||||
}
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == MEMP_NUM_TCP_PCB);
|
||||
/* 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);
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == MEMP_NUM_TCP_PCB);
|
||||
|
||||
for (i = 1; i <= MEMP_NUM_TCP_PCB; i++)
|
||||
{
|
||||
tcp_abort(pcb[i]);
|
||||
}
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
/* pcbs in TIME_WAIT state will be deleted when creating new pcb reach the max number */
|
||||
START_TEST(test_tcp_new_max_num_remove_TIME_WAIT)
|
||||
{
|
||||
struct tcp_pcb* pcb;
|
||||
struct tcp_pcb* pcb_list[MEMP_NUM_TCP_PCB + 1];
|
||||
int i;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* create a pcb in TIME_WAIT state */
|
||||
pcb = tcp_new();
|
||||
EXPECT_RET(pcb != NULL);
|
||||
tcp_set_state(pcb, TIME_WAIT, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
|
||||
EXPECT_RET(pcb->state == TIME_WAIT);
|
||||
|
||||
/* 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));
|
||||
}
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == MEMP_NUM_TCP_PCB);
|
||||
|
||||
/* Create one more pcb, and expect that the pcb in the TIME_WAIT state is deleted */
|
||||
pcb_list[MEMP_NUM_TCP_PCB-1] = tcp_new();
|
||||
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
|
||||
|
||||
|
||||
/* Call tcp_connect to check active open */
|
||||
START_TEST(test_tcp_connect_active_open)
|
||||
{
|
||||
struct test_tcp_counters counters;
|
||||
struct tcp_pcb *pcb;
|
||||
struct pbuf *p;
|
||||
err_t err;
|
||||
u16_t test_port = 1234;
|
||||
u32_t seqno = 0;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* create and initialize the pcb */
|
||||
tcp_ticks = SEQNO1 - ISS;
|
||||
pcb = test_tcp_new_counters_pcb(&counters);
|
||||
EXPECT_RET(pcb != NULL);
|
||||
|
||||
/* Get seqno from SYN packet */
|
||||
test_txcounters.copy_tx_packets = 1;
|
||||
err = tcp_connect(pcb, &test_remote_ip, test_port, NULL);
|
||||
test_txcounters.copy_tx_packets = 0;
|
||||
EXPECT(err == ERR_OK);
|
||||
EXPECT(pcb->state == SYN_SENT);
|
||||
EXPECT(test_txcounters.num_tx_calls == 1);
|
||||
EXPECT_RET(test_txcounters.tx_packets != NULL);
|
||||
if (test_txcounters.tx_packets != NULL) {
|
||||
struct tcp_hdr tcphdr;
|
||||
u16_t ret;
|
||||
ret = pbuf_copy_partial(test_txcounters.tx_packets, &tcphdr, 20, 20);
|
||||
EXPECT(ret == 20);
|
||||
EXPECT(TCPH_FLAGS(&tcphdr) & TCP_SYN);
|
||||
pbuf_free(test_txcounters.tx_packets);
|
||||
test_txcounters.tx_packets = NULL;
|
||||
seqno = lwip_htonl(tcphdr.seqno);
|
||||
EXPECT(seqno == pcb->lastack);
|
||||
}
|
||||
|
||||
/* check correct syn packet */
|
||||
p = tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, test_port,
|
||||
pcb->local_port, NULL, 0, 12345, seqno + 1, TCP_SYN|TCP_ACK);
|
||||
EXPECT_RET(p != NULL);
|
||||
test_tcp_input(p, &test_netif);
|
||||
EXPECT_RET(pcb->state == ESTABLISHED);
|
||||
EXPECT_RET(test_txcounters.num_tx_calls == 2);
|
||||
|
||||
/* make sure the pcb is freed */
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
|
||||
tcp_abort(pcb);
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_tcp_active_close)
|
||||
{
|
||||
struct tcp_pcb *pcb, *pcbl;
|
||||
struct test_tcp_counters counters;
|
||||
struct pbuf *p;
|
||||
err_t err;
|
||||
u32_t i;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* create TCP in LISTEN state */
|
||||
memset(&counters, 0, sizeof(counters));
|
||||
pcb = test_tcp_new_counters_pcb(&counters);
|
||||
EXPECT_RET(pcb != NULL);
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
|
||||
err = tcp_bind(pcb, &test_netif.ip_addr, 1234);
|
||||
EXPECT_RET(err == ERR_OK);
|
||||
pcbl = tcp_listen(pcb);
|
||||
EXPECT_RET(pcbl != NULL);
|
||||
EXPECT_RET(pcbl->state == LISTEN);
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) == 1);
|
||||
|
||||
memset(&test_txcounters, 0, sizeof(test_txcounters));
|
||||
err = tcp_close(pcbl);
|
||||
EXPECT_RET(err == ERR_OK);
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) == 0);
|
||||
EXPECT(test_txcounters.num_tx_calls == 0);
|
||||
|
||||
/* close TCP in SYN_SENT state */
|
||||
memset(&counters, 0, sizeof(counters));
|
||||
pcb = test_tcp_new_counters_pcb(&counters);
|
||||
EXPECT_RET(pcb != NULL);
|
||||
err = tcp_connect(pcb, &test_netif.gw, 1234, NULL);
|
||||
EXPECT_RET(err == ERR_OK);
|
||||
EXPECT_RET(pcb->state == SYN_SENT);
|
||||
EXPECT(test_txcounters.num_tx_calls == 1);
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
|
||||
|
||||
memset(&test_txcounters, 0, sizeof(test_txcounters));
|
||||
err = tcp_close(pcb);
|
||||
EXPECT_RET(err == ERR_OK);
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
EXPECT(test_txcounters.num_tx_calls == 0);
|
||||
|
||||
/* close TCP in ESTABLISHED state */
|
||||
memset(&counters, 0, sizeof(counters));
|
||||
pcb = test_tcp_new_counters_pcb(&counters);
|
||||
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);
|
||||
|
||||
memset(&test_txcounters, 0, sizeof(test_txcounters));
|
||||
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);
|
||||
/* test_tcp_tmr(); */
|
||||
EXPECT(test_txcounters.num_tx_calls == 1);
|
||||
/* create a segment ACK and pass it to tcp_input */
|
||||
p = tcp_create_rx_segment(pcb, NULL, 0, 0, 1, TCP_ACK);
|
||||
EXPECT_RET(p != NULL);
|
||||
test_tcp_input(p, &test_netif);
|
||||
EXPECT_RET(pcb->state == FIN_WAIT_2);
|
||||
/* create a segment FIN and pass it to tcp_input */
|
||||
p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_FIN);
|
||||
EXPECT_RET(p != NULL);
|
||||
test_tcp_input(p, &test_netif);
|
||||
EXPECT_RET(pcb->state == TIME_WAIT);
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
|
||||
for (i = 0; i < 2 * TCP_MSL / TCP_TMR_INTERVAL + 1; i++) {
|
||||
test_tcp_tmr();
|
||||
}
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_tcp_imultaneous_close)
|
||||
{
|
||||
struct test_tcp_counters counters;
|
||||
struct tcp_pcb* pcb;
|
||||
struct pbuf* p;
|
||||
char data = 0x0f;
|
||||
err_t err;
|
||||
u32_t i;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* initialize counter struct */
|
||||
memset(&counters, 0, sizeof(counters));
|
||||
counters.expected_data_len = 1;
|
||||
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, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
|
||||
err = tcp_close(pcb);
|
||||
EXPECT_RET(err == ERR_OK);
|
||||
EXPECT_RET(pcb->state == FIN_WAIT_1);
|
||||
/* create a FIN segment */
|
||||
p = tcp_create_rx_segment(pcb, &data, 0, 0, 0, TCP_FIN);
|
||||
EXPECT(p != NULL);
|
||||
if (p != NULL) {
|
||||
test_tcp_input(p, &test_netif);
|
||||
}
|
||||
EXPECT_RET(pcb->state == CLOSING);
|
||||
/* create an ACK segment */
|
||||
p = tcp_create_rx_segment(pcb, &data, 0, 0, 1, TCP_ACK);
|
||||
EXPECT(p != NULL);
|
||||
if (p != NULL) {
|
||||
test_tcp_input(p, &test_netif);
|
||||
}
|
||||
EXPECT_RET(pcb->state == TIME_WAIT);
|
||||
for (i = 0; i < 2 * TCP_MSL / TCP_TMR_INTERVAL + 1; i++) {
|
||||
test_tcp_tmr();
|
||||
}
|
||||
EXPECT_RET(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
/* RST was generated when receive any incoming segment in CLOSED state */
|
||||
START_TEST(test_tcp_gen_rst_in_CLOSED)
|
||||
{
|
||||
struct pbuf *p;
|
||||
ip_addr_t src_addr = test_remote_ip;
|
||||
ip_addr_t dst_addr = test_local_ip;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* Do not create any pcb */
|
||||
|
||||
/* create a segment */
|
||||
p = tcp_create_segment(&src_addr, &dst_addr, TEST_REMOTE_PORT,
|
||||
TEST_LOCAL_PORT, NULL, 0, 12345, 54321, TCP_ACK);
|
||||
EXPECT(p != NULL);
|
||||
test_rst_generation_with_incoming_packet(p, &test_netif, &test_txcounters);
|
||||
EXPECT(test_txcounters.num_tx_calls == 1);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* RST was generated when receive ACK in LISTEN state */
|
||||
START_TEST(test_tcp_gen_rst_in_LISTEN)
|
||||
{
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
struct pbuf *p;
|
||||
ip_addr_t src_addr = test_remote_ip;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* create a pcb in LISTEN state */
|
||||
lpcb = create_listening_pcb(TEST_LOCAL_PORT, NULL);
|
||||
EXPECT_RET(lpcb != NULL);
|
||||
|
||||
/* create a segment */
|
||||
p = tcp_create_segment(&src_addr,&lpcb->local_ip, TEST_REMOTE_PORT,
|
||||
lpcb->local_port, NULL, 0, 12345, 54321, TCP_ACK);
|
||||
EXPECT(p != NULL);
|
||||
test_rst_generation_with_incoming_packet(p, &test_netif, &test_txcounters);
|
||||
EXPECT(test_txcounters.num_tx_calls == 1);
|
||||
|
||||
/* the PCB still in LISTEN state */
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) == 1);
|
||||
if (MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) != 0) {
|
||||
/* can not use tcp_abort() */
|
||||
tcp_close((struct tcp_pcb *)lpcb);
|
||||
}
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
||||
/* RST was generated when receive an SYN in TIME_WAIT state */
|
||||
START_TEST(test_tcp_gen_rst_in_TIME_WAIT)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
struct pbuf *p;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* create a pcb in LISTEN state */
|
||||
pcb = tcp_new();
|
||||
EXPECT_RET(pcb != NULL);
|
||||
tcp_set_state(pcb, TIME_WAIT, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
|
||||
|
||||
/* create a segment */
|
||||
p = tcp_create_rx_segment(pcb, NULL, 0, 0, 0, TCP_SYN);
|
||||
EXPECT(p != NULL);
|
||||
test_rst_generation_with_incoming_packet(p, &test_netif, &test_txcounters);
|
||||
EXPECT(test_txcounters.num_tx_calls == 1);
|
||||
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
|
||||
EXPECT(pcb->state == TIME_WAIT);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* receive TCP_RST with different seqno */
|
||||
START_TEST(test_tcp_process_rst_seqno)
|
||||
{
|
||||
struct test_tcp_counters counters;
|
||||
struct tcp_pcb *pcb;
|
||||
struct pbuf *p;
|
||||
err_t err;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* create and initialize a pcb in SYN_SENT state */
|
||||
memset(&counters, 0, sizeof(counters));
|
||||
pcb = test_tcp_new_counters_pcb(&counters);
|
||||
EXPECT_RET(pcb != NULL);
|
||||
err = tcp_connect(pcb, &test_remote_ip, TEST_REMOTE_PORT, NULL);
|
||||
EXPECT_RET(err == ERR_OK);
|
||||
|
||||
/* a RST segment with incorrect seqno will not be accepted */
|
||||
p = tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, TEST_REMOTE_PORT,
|
||||
pcb->local_port, NULL, 0, 12345, pcb->snd_nxt-10, TCP_RST);
|
||||
EXPECT(p != NULL);
|
||||
test_tcp_input(p, &test_netif);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
|
||||
/* a RST segment with correct seqno will be accepted */
|
||||
p = tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, TEST_REMOTE_PORT,
|
||||
pcb->local_port, NULL, 0, 12345, pcb->snd_nxt, TCP_RST);
|
||||
EXPECT(p != NULL);
|
||||
test_tcp_input(p, &test_netif);
|
||||
EXPECT(counters.err_calls == 1);
|
||||
counters.err_calls = 0;
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
|
||||
/* create another pcb in ESTABLISHED state */
|
||||
memset(&counters, 0, sizeof(counters));
|
||||
pcb = test_tcp_new_counters_pcb(&counters);
|
||||
EXPECT_RET(pcb != NULL);
|
||||
tcp_set_state(pcb, ESTABLISHED, &test_local_ip, &test_remote_ip, TEST_LOCAL_PORT, TEST_REMOTE_PORT);
|
||||
|
||||
/* a RST segment with incorrect seqno will not be accepted */
|
||||
p = tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port,
|
||||
pcb->local_port, NULL, 0, pcb->rcv_nxt-10, 54321, TCP_RST);
|
||||
EXPECT(p != NULL);
|
||||
test_tcp_input(p, &test_netif);
|
||||
EXPECT(counters.err_calls == 0);
|
||||
|
||||
/* a RST segment with correct seqno will be accepted */
|
||||
p = tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, TEST_REMOTE_PORT,
|
||||
pcb->local_port, NULL, 0, pcb->rcv_nxt, 54321, TCP_RST);
|
||||
EXPECT(p != NULL);
|
||||
test_tcp_input(p, &test_netif);
|
||||
EXPECT(counters.err_calls == 1);
|
||||
counters.err_calls = 0;
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* RST was generated when receive an SYN+ACK with incorrect ACK number in SYN_SENT state */
|
||||
START_TEST(test_tcp_gen_rst_in_SYN_SENT_ackseq)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
struct pbuf *p;
|
||||
u16_t test_port = 1234;
|
||||
err_t err;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* create and initialize a pcb in listen state */
|
||||
pcb = tcp_new();
|
||||
EXPECT_RET(pcb != NULL);
|
||||
err = tcp_connect(pcb, &test_remote_ip, test_port, NULL);
|
||||
EXPECT_RET(err == ERR_OK);
|
||||
|
||||
/* create a SYN+ACK segment with incorrect seqno */
|
||||
p = tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port,
|
||||
pcb->local_port, NULL, 0, 12345, pcb->lastack-10, TCP_SYN|TCP_ACK);
|
||||
EXPECT(p != NULL);
|
||||
test_rst_generation_with_incoming_packet(p, &test_netif, &test_txcounters);
|
||||
|
||||
/* LWIP: send RST then re-send SYN immediately */
|
||||
EXPECT(test_txcounters.num_tx_calls == 2);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* RST was generated when receive an ACK without SYN in SYN_SENT state */
|
||||
START_TEST(test_tcp_gen_rst_in_SYN_SENT_non_syn_ack)
|
||||
{
|
||||
struct tcp_pcb *pcb;
|
||||
struct pbuf *p;
|
||||
u16_t test_port = 1234;
|
||||
err_t err;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* create and initialize a pcb in listen state */
|
||||
pcb = tcp_new();
|
||||
EXPECT_RET(pcb != NULL);
|
||||
err = tcp_connect(pcb, &test_remote_ip, test_port, NULL);
|
||||
EXPECT_RET(err == ERR_OK);
|
||||
|
||||
/* create a SYN+ACK segment with incorrect seqno */
|
||||
p = tcp_create_segment(&pcb->remote_ip, &pcb->local_ip, pcb->remote_port,
|
||||
pcb->local_port, NULL, 0, 12345, pcb->lastack, TCP_ACK);
|
||||
EXPECT(p != NULL);
|
||||
test_rst_generation_with_incoming_packet(p, &test_netif, &test_txcounters);
|
||||
|
||||
/* LWIP: send RST then re-send SYN immediately */
|
||||
EXPECT(test_txcounters.num_tx_calls == 2);
|
||||
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* RST was generated when receive an ACK with incorrect seqno in SYN_RCVD state */
|
||||
START_TEST(test_tcp_gen_rst_in_SYN_RCVD)
|
||||
{
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
struct pbuf *p;
|
||||
u32_t ack_seqno = 0;
|
||||
ip_addr_t src_addr = test_remote_ip;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* create and initialize a pcb in listen state */
|
||||
lpcb = create_listening_pcb(TEST_LOCAL_PORT, NULL);
|
||||
EXPECT_RET(lpcb != NULL);
|
||||
|
||||
/* LISTEN -> SYN_RCVD */
|
||||
p = tcp_create_segment(&src_addr, &lpcb->local_ip, TEST_REMOTE_PORT,
|
||||
lpcb->local_port, NULL, 0, 1000, 54321, TCP_SYN);
|
||||
EXPECT(p != NULL);
|
||||
memset(&test_txcounters, 0, sizeof(struct test_tcp_txcounters));
|
||||
test_tcp_input(p, &test_netif);
|
||||
EXPECT(test_txcounters.num_tx_calls == 1);
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
|
||||
if (MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1) {
|
||||
ack_seqno = tcp_active_pcbs[0].lastack;
|
||||
}
|
||||
|
||||
/* create a ACK segment with incorrect seqno */
|
||||
p = tcp_create_segment(&src_addr, &lpcb->local_ip, TEST_REMOTE_PORT,
|
||||
lpcb->local_port, NULL, 0, 1001, ack_seqno+1111, TCP_ACK);
|
||||
EXPECT(p != NULL);
|
||||
test_rst_generation_with_incoming_packet(p, &test_netif, &test_txcounters);
|
||||
EXPECT(test_txcounters.num_tx_calls == 1);
|
||||
|
||||
/* the active pcb still exists */
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) == 1);
|
||||
if (MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) != 0) {
|
||||
/* can not use tcp_abort() */
|
||||
tcp_close((struct tcp_pcb *)lpcb);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/* a listen pcb returns to LISTEN from SYN_RCVD when RST received */
|
||||
START_TEST(test_tcp_receive_rst_SYN_RCVD_to_LISTEN)
|
||||
{
|
||||
struct tcp_pcb_listen *lpcb;
|
||||
struct pbuf *p;
|
||||
u16_t tcp_flags;
|
||||
ip_addr_t src_addr = test_remote_ip;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* create and initialize a pcb in listen state */
|
||||
lpcb = create_listening_pcb(TEST_LOCAL_PORT, NULL);
|
||||
EXPECT_RET(lpcb != NULL);
|
||||
|
||||
/* create a SYN segment */
|
||||
p = tcp_create_segment(&src_addr, &lpcb->local_ip, TEST_REMOTE_PORT,
|
||||
lpcb->local_port, NULL, 0, 1000, 54321, TCP_SYN);
|
||||
EXPECT(p != NULL);
|
||||
/* pass the segment to tcp_input */
|
||||
memset(&test_txcounters, 0, sizeof(struct test_tcp_txcounters));
|
||||
test_txcounters.copy_tx_packets = 1;
|
||||
test_tcp_input(p, &test_netif);
|
||||
test_txcounters.copy_tx_packets = 0;
|
||||
/* check if packets are as expected */
|
||||
EXPECT(test_txcounters.num_tx_calls == 1);
|
||||
tcp_flags = get_tcp_flags_from_packet(test_txcounters.tx_packets, 20);
|
||||
pbuf_free(test_txcounters.tx_packets);
|
||||
test_txcounters.tx_packets = NULL;
|
||||
EXPECT((tcp_flags & TCP_SYN) && (tcp_flags & TCP_ACK));
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 1);
|
||||
|
||||
/* create a RST segment */
|
||||
p = tcp_create_segment(&src_addr, &lpcb->local_ip, TEST_REMOTE_PORT,
|
||||
lpcb->local_port, NULL, 0, 1001, 54321, TCP_RST);
|
||||
EXPECT(p != NULL);
|
||||
test_tcp_input(p, &test_netif);
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB) == 0);
|
||||
EXPECT(MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) == 1);
|
||||
|
||||
if (MEMP_STATS_GET(used, MEMP_TCP_PCB_LISTEN) != 0) {
|
||||
/* can not use tcp_abort() */
|
||||
tcp_close((struct tcp_pcb *)lpcb);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
tcp_state_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_tcp_new_max_num),
|
||||
TESTFUNC(test_tcp_new_max_num_remove_TIME_WAIT),
|
||||
TESTFUNC(test_tcp_connect_active_open),
|
||||
TESTFUNC(test_tcp_active_close),
|
||||
TESTFUNC(test_tcp_imultaneous_close),
|
||||
TESTFUNC(test_tcp_gen_rst_in_CLOSED),
|
||||
TESTFUNC(test_tcp_gen_rst_in_LISTEN),
|
||||
TESTFUNC(test_tcp_gen_rst_in_TIME_WAIT),
|
||||
TESTFUNC(test_tcp_process_rst_seqno),
|
||||
TESTFUNC(test_tcp_gen_rst_in_SYN_SENT_ackseq),
|
||||
TESTFUNC(test_tcp_gen_rst_in_SYN_SENT_non_syn_ack),
|
||||
TESTFUNC(test_tcp_gen_rst_in_SYN_RCVD),
|
||||
TESTFUNC(test_tcp_receive_rst_SYN_RCVD_to_LISTEN),
|
||||
};
|
||||
return create_suite("TCP_STATE", tests, sizeof(tests) / sizeof(testfunc), tcp_state_setup, tcp_state_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/tcp/test_tcp_state.h
Normal file
8
lwip/lwip-2.2.1/test/unit/tcp/test_tcp_state.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_TCP_STATE_H
|
||||
#define LWIP_HDR_TEST_TCP_STATE_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite *tcp_state_suite(void);
|
||||
|
||||
#endif
|
||||
472
lwip/lwip-2.2.1/test/unit/udp/test_udp.c
Normal file
472
lwip/lwip-2.2.1/test/unit/udp/test_udp.c
Normal file
@ -0,0 +1,472 @@
|
||||
#include "test_udp.h"
|
||||
|
||||
#include "lwip/udp.h"
|
||||
#include "lwip/stats.h"
|
||||
#include "lwip/inet_chksum.h"
|
||||
|
||||
#if !LWIP_STATS || !UDP_STATS || !MEMP_STATS
|
||||
#error "This tests needs UDP- and MEMP-statistics enabled"
|
||||
#endif
|
||||
|
||||
struct test_udp_rxdata {
|
||||
u32_t rx_cnt;
|
||||
u32_t rx_bytes;
|
||||
struct udp_pcb *pcb;
|
||||
};
|
||||
|
||||
static struct netif test_netif1, test_netif2;
|
||||
static ip4_addr_t test_gw1, test_ipaddr1, test_netmask1;
|
||||
static ip4_addr_t test_gw2, test_ipaddr2, test_netmask2;
|
||||
static int output_ctr, linkoutput_ctr;
|
||||
|
||||
/* 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(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0);
|
||||
}
|
||||
|
||||
static err_t
|
||||
default_netif_output(struct netif *netif, struct pbuf *p, const ip4_addr_t *ipaddr)
|
||||
{
|
||||
fail_unless((netif == &test_netif1) || (netif == &test_netif2));
|
||||
fail_unless(p != NULL);
|
||||
fail_unless(ipaddr != NULL);
|
||||
output_ctr++;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t
|
||||
default_netif_linkoutput(struct netif *netif, struct pbuf *p)
|
||||
{
|
||||
fail_unless((netif == &test_netif1) || (netif == &test_netif2));
|
||||
fail_unless(p != NULL);
|
||||
linkoutput_ctr++;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static err_t
|
||||
default_netif_init(struct netif *netif)
|
||||
{
|
||||
fail_unless(netif != NULL);
|
||||
netif->output = default_netif_output;
|
||||
netif->linkoutput = default_netif_linkoutput;
|
||||
netif->mtu = 1500;
|
||||
netif->flags = NETIF_FLAG_BROADCAST | NETIF_FLAG_ETHARP | NETIF_FLAG_LINK_UP;
|
||||
netif->hwaddr_len = 6;
|
||||
return ERR_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
default_netif_add(void)
|
||||
{
|
||||
struct netif *n;
|
||||
|
||||
#if LWIP_HAVE_LOOPIF
|
||||
fail_unless(netif_list != NULL); /* the loopif */
|
||||
fail_unless(netif_list->next == NULL);
|
||||
#else
|
||||
fail_unless(netif_list == NULL);
|
||||
#endif
|
||||
fail_unless(netif_default == NULL);
|
||||
|
||||
IP4_ADDR(&test_ipaddr1, 192,168,0,1);
|
||||
IP4_ADDR(&test_netmask1, 255,255,255,0);
|
||||
IP4_ADDR(&test_gw1, 192,168,0,254);
|
||||
n = netif_add(&test_netif1, &test_ipaddr1, &test_netmask1,
|
||||
&test_gw1, NULL, default_netif_init, NULL);
|
||||
fail_unless(n == &test_netif1);
|
||||
|
||||
IP4_ADDR(&test_ipaddr2, 192,168,1,1);
|
||||
IP4_ADDR(&test_netmask2, 255,255,255,0);
|
||||
IP4_ADDR(&test_gw2, 192,168,1,254);
|
||||
n = netif_add(&test_netif2, &test_ipaddr2, &test_netmask2,
|
||||
&test_gw2, NULL, default_netif_init, NULL);
|
||||
fail_unless(n == &test_netif2);
|
||||
|
||||
netif_set_default(&test_netif1);
|
||||
netif_set_up(&test_netif1);
|
||||
netif_set_up(&test_netif2);
|
||||
}
|
||||
|
||||
static void
|
||||
default_netif_remove(void)
|
||||
{
|
||||
fail_unless(netif_default == &test_netif1);
|
||||
netif_remove(&test_netif1);
|
||||
netif_remove(&test_netif2);
|
||||
fail_unless(netif_default == NULL);
|
||||
#if LWIP_HAVE_LOOPIF
|
||||
fail_unless(netif_list != NULL); /* the loopif */
|
||||
fail_unless(netif_list->next == NULL);
|
||||
#else
|
||||
fail_unless(netif_list == NULL);
|
||||
#endif
|
||||
}
|
||||
/* Setups/teardown functions */
|
||||
|
||||
static void
|
||||
udp_setup(void)
|
||||
{
|
||||
udp_remove_all();
|
||||
default_netif_add();
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
static void
|
||||
udp_teardown(void)
|
||||
{
|
||||
udp_remove_all();
|
||||
default_netif_remove();
|
||||
lwip_check_ensure_no_alloc(SKIP_POOL(MEMP_SYS_TIMEOUT));
|
||||
}
|
||||
|
||||
|
||||
/* Test functions */
|
||||
|
||||
START_TEST(test_udp_new_remove)
|
||||
{
|
||||
struct udp_pcb* pcb;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0);
|
||||
|
||||
pcb = udp_new();
|
||||
fail_unless(pcb != NULL);
|
||||
if (pcb != NULL) {
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 1);
|
||||
udp_remove(pcb);
|
||||
fail_unless(MEMP_STATS_GET(used, MEMP_UDP_PCB) == 0);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
static void test_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p,
|
||||
const ip_addr_t *addr, u16_t port)
|
||||
{
|
||||
struct test_udp_rxdata *ctr = (struct test_udp_rxdata *)arg;
|
||||
|
||||
LWIP_UNUSED_ARG(addr);
|
||||
LWIP_UNUSED_ARG(port);
|
||||
|
||||
fail_unless(arg != NULL);
|
||||
fail_unless(ctr->pcb == pcb);
|
||||
|
||||
ctr->rx_cnt++;
|
||||
ctr->rx_bytes += p->tot_len;
|
||||
|
||||
if (p != NULL) {
|
||||
pbuf_free(p);
|
||||
}
|
||||
}
|
||||
|
||||
static struct pbuf *
|
||||
test_udp_create_test_packet(u16_t length, u16_t port, u32_t dst_addr)
|
||||
{
|
||||
err_t err;
|
||||
u8_t ret;
|
||||
struct udp_hdr *uh;
|
||||
struct ip_hdr *ih;
|
||||
struct pbuf *p;
|
||||
const u8_t test_data[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf};
|
||||
|
||||
p = pbuf_alloc(PBUF_TRANSPORT, length, PBUF_POOL);
|
||||
fail_unless(p != NULL);
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
fail_unless(p->next == NULL);
|
||||
err = pbuf_take(p, test_data, length);
|
||||
fail_unless(err == ERR_OK);
|
||||
|
||||
/* add UDP header */
|
||||
ret = pbuf_add_header(p, sizeof(struct udp_hdr));
|
||||
fail_unless(!ret);
|
||||
uh = (struct udp_hdr *)p->payload;
|
||||
uh->chksum = 0;
|
||||
uh->dest = uh->src = lwip_htons(port);
|
||||
uh->len = lwip_htons(p->tot_len);
|
||||
/* add IPv4 header */
|
||||
ret = pbuf_add_header(p, sizeof(struct ip_hdr));
|
||||
fail_unless(!ret);
|
||||
ih = (struct ip_hdr *)p->payload;
|
||||
memset(ih, 0, sizeof(*ih));
|
||||
ih->dest.addr = dst_addr;
|
||||
ih->_len = lwip_htons(p->tot_len);
|
||||
ih->_ttl = 32;
|
||||
ih->_proto = IP_PROTO_UDP;
|
||||
IPH_VHL_SET(ih, 4, sizeof(struct ip_hdr) / 4);
|
||||
IPH_CHKSUM_SET(ih, inet_chksum(ih, sizeof(struct ip_hdr)));
|
||||
return p;
|
||||
}
|
||||
|
||||
/* bind 2 pcbs to specific netif IP and test which one gets broadcasts */
|
||||
START_TEST(test_udp_broadcast_rx_with_2_netifs)
|
||||
{
|
||||
err_t err;
|
||||
struct udp_pcb *pcb1, *pcb2;
|
||||
const u16_t port = 12345;
|
||||
struct test_udp_rxdata ctr1, ctr2;
|
||||
struct pbuf *p;
|
||||
#if SO_REUSE
|
||||
struct udp_pcb *pcb_any;
|
||||
struct test_udp_rxdata ctr_any;
|
||||
#endif
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
pcb1 = udp_new();
|
||||
fail_unless(pcb1 != NULL);
|
||||
pcb2 = udp_new();
|
||||
fail_unless(pcb2 != NULL);
|
||||
|
||||
#if SO_REUSE
|
||||
pcb_any = udp_new();
|
||||
fail_unless(pcb_any != NULL);
|
||||
|
||||
ip_set_option(pcb1, SOF_REUSEADDR);
|
||||
ip_set_option(pcb2, SOF_REUSEADDR);
|
||||
ip_set_option(pcb_any, SOF_REUSEADDR);
|
||||
|
||||
err = udp_bind(pcb_any, NULL, port);
|
||||
fail_unless(err == ERR_OK);
|
||||
memset(&ctr_any, 0, sizeof(ctr_any));
|
||||
ctr_any.pcb = pcb_any;
|
||||
udp_recv(pcb_any, test_recv, &ctr_any);
|
||||
#endif
|
||||
|
||||
err = udp_bind(pcb1, &test_netif1.ip_addr, port);
|
||||
fail_unless(err == ERR_OK);
|
||||
err = udp_bind(pcb2, &test_netif2.ip_addr, port);
|
||||
fail_unless(err == ERR_OK);
|
||||
|
||||
memset(&ctr1, 0, sizeof(ctr1));
|
||||
ctr1.pcb = pcb1;
|
||||
memset(&ctr2, 0, sizeof(ctr2));
|
||||
ctr2.pcb = pcb2;
|
||||
|
||||
udp_recv(pcb1, test_recv, &ctr1);
|
||||
udp_recv(pcb2, test_recv, &ctr2);
|
||||
|
||||
/* unicast to netif1 */
|
||||
p = test_udp_create_test_packet(16, port, test_ipaddr1.addr);
|
||||
EXPECT_RET(p != NULL);
|
||||
err = ip4_input(p, &test_netif1);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(ctr1.rx_cnt == 1);
|
||||
fail_unless(ctr1.rx_bytes == 16);
|
||||
fail_unless(ctr2.rx_cnt == 0);
|
||||
#if SO_REUSE
|
||||
fail_unless(ctr_any.rx_cnt == 0);
|
||||
#endif
|
||||
ctr1.rx_cnt = ctr1.rx_bytes = 0;
|
||||
|
||||
/* unicast to netif2 */
|
||||
p = test_udp_create_test_packet(16, port, test_ipaddr2.addr);
|
||||
EXPECT_RET(p != NULL);
|
||||
err = ip4_input(p, &test_netif2);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(ctr2.rx_cnt == 1);
|
||||
fail_unless(ctr2.rx_bytes == 16);
|
||||
fail_unless(ctr1.rx_cnt == 0);
|
||||
#if SO_REUSE
|
||||
fail_unless(ctr_any.rx_cnt == 0);
|
||||
#endif
|
||||
ctr2.rx_cnt = ctr2.rx_bytes = 0;
|
||||
|
||||
/* broadcast to netif1-broadcast, input to netif2 */
|
||||
p = test_udp_create_test_packet(16, port, test_ipaddr1.addr | ~test_netmask1.addr);
|
||||
EXPECT_RET(p != NULL);
|
||||
err = ip4_input(p, &test_netif2);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(ctr1.rx_cnt == 1);
|
||||
fail_unless(ctr1.rx_bytes == 16);
|
||||
fail_unless(ctr2.rx_cnt == 0);
|
||||
#if SO_REUSE
|
||||
fail_unless(ctr_any.rx_cnt == 0);
|
||||
#endif
|
||||
ctr1.rx_cnt = ctr1.rx_bytes = 0;
|
||||
|
||||
/* broadcast to netif2-broadcast, input to netif1 */
|
||||
p = test_udp_create_test_packet(16, port, test_ipaddr2.addr | ~test_netmask2.addr);
|
||||
EXPECT_RET(p != NULL);
|
||||
err = ip4_input(p, &test_netif1);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(ctr2.rx_cnt == 1);
|
||||
fail_unless(ctr2.rx_bytes == 16);
|
||||
fail_unless(ctr1.rx_cnt == 0);
|
||||
#if SO_REUSE
|
||||
fail_unless(ctr_any.rx_cnt == 0);
|
||||
#endif
|
||||
ctr2.rx_cnt = ctr2.rx_bytes = 0;
|
||||
|
||||
/* broadcast to global-broadcast, input to netif1 */
|
||||
p = test_udp_create_test_packet(16, port, 0xffffffff);
|
||||
EXPECT_RET(p != NULL);
|
||||
err = ip4_input(p, &test_netif1);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(ctr1.rx_cnt == 1);
|
||||
fail_unless(ctr1.rx_bytes == 16);
|
||||
fail_unless(ctr2.rx_cnt == 0);
|
||||
#if SO_REUSE
|
||||
fail_unless(ctr_any.rx_cnt == 0);
|
||||
#endif
|
||||
ctr1.rx_cnt = ctr1.rx_bytes = 0;
|
||||
|
||||
/* broadcast to global-broadcast, input to netif2 */
|
||||
p = test_udp_create_test_packet(16, port, 0xffffffff);
|
||||
EXPECT_RET(p != NULL);
|
||||
err = ip4_input(p, &test_netif2);
|
||||
fail_unless(err == ERR_OK);
|
||||
fail_unless(ctr2.rx_cnt == 1);
|
||||
fail_unless(ctr2.rx_bytes == 16);
|
||||
fail_unless(ctr1.rx_cnt == 0);
|
||||
#if SO_REUSE
|
||||
fail_unless(ctr_any.rx_cnt == 0);
|
||||
#endif
|
||||
ctr2.rx_cnt = ctr2.rx_bytes = 0;
|
||||
}
|
||||
END_TEST
|
||||
|
||||
START_TEST(test_udp_bind)
|
||||
{
|
||||
struct udp_pcb* pcb1;
|
||||
struct udp_pcb* pcb2;
|
||||
ip_addr_t ip1;
|
||||
ip_addr_t ip2;
|
||||
err_t err1;
|
||||
err_t err2;
|
||||
LWIP_UNUSED_ARG(_i);
|
||||
|
||||
/* bind on same port using different IP address types */
|
||||
ip_addr_set_any_val(0, ip1);
|
||||
ip_addr_set_any_val(1, ip2);
|
||||
|
||||
pcb1 = udp_new_ip_type(IPADDR_TYPE_V4);
|
||||
pcb2 = udp_new_ip_type(IPADDR_TYPE_V6);
|
||||
|
||||
err1 = udp_bind(pcb1, &ip1, 2105);
|
||||
err2 = udp_bind(pcb2, &ip2, 2105);
|
||||
|
||||
fail_unless(err1 == ERR_OK);
|
||||
fail_unless(err2 == ERR_OK);
|
||||
|
||||
udp_remove(pcb1);
|
||||
udp_remove(pcb2);
|
||||
|
||||
/* bind on same port using SAME IPv4 address type */
|
||||
ip_addr_set_any_val(0, ip1);
|
||||
ip_addr_set_any_val(0, ip2);
|
||||
|
||||
pcb1 = udp_new_ip_type(IPADDR_TYPE_V4);
|
||||
pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
|
||||
|
||||
err1 = udp_bind(pcb1, &ip1, 2105);
|
||||
err2 = udp_bind(pcb2, &ip2, 2105);
|
||||
|
||||
fail_unless(err1 == ERR_OK);
|
||||
fail_unless(err2 == ERR_USE);
|
||||
|
||||
udp_remove(pcb1);
|
||||
udp_remove(pcb2);
|
||||
|
||||
/* bind on same port using SAME IPv6 address type */
|
||||
ip_addr_set_any_val(1, ip1);
|
||||
ip_addr_set_any_val(1, ip2);
|
||||
|
||||
pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
|
||||
pcb2 = udp_new_ip_type(IPADDR_TYPE_V6);
|
||||
|
||||
err1 = udp_bind(pcb1, &ip1, 2105);
|
||||
err2 = udp_bind(pcb2, &ip2, 2105);
|
||||
|
||||
fail_unless(err1 == ERR_OK);
|
||||
fail_unless(err2 == ERR_USE);
|
||||
|
||||
udp_remove(pcb1);
|
||||
udp_remove(pcb2);
|
||||
|
||||
/* Bind with different IP address type */
|
||||
ip_addr_set_any_val(0, ip1);
|
||||
ip_addr_set_any_val(1, ip2);
|
||||
|
||||
pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
|
||||
pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
|
||||
|
||||
err1 = udp_bind(pcb1, &ip1, 2105);
|
||||
err2 = udp_bind(pcb2, &ip2, 2105);
|
||||
|
||||
fail_unless(err1 == ERR_OK);
|
||||
fail_unless(err2 == ERR_OK);
|
||||
|
||||
udp_remove(pcb1);
|
||||
udp_remove(pcb2);
|
||||
|
||||
/* Bind with different IP numbers */
|
||||
IP_ADDR4(&ip1, 1, 2, 3, 4);
|
||||
IP_ADDR4(&ip2, 4, 3, 2, 1);
|
||||
|
||||
pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
|
||||
pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
|
||||
|
||||
err1 = udp_bind(pcb1, &ip1, 2105);
|
||||
err2 = udp_bind(pcb2, &ip2, 2105);
|
||||
|
||||
fail_unless(err1 == ERR_OK);
|
||||
fail_unless(err2 == ERR_OK);
|
||||
|
||||
udp_remove(pcb1);
|
||||
udp_remove(pcb2);
|
||||
|
||||
/* Bind with same IP numbers */
|
||||
IP_ADDR4(&ip1, 1, 2, 3, 4);
|
||||
IP_ADDR4(&ip2, 1, 2, 3, 4);
|
||||
|
||||
pcb1 = udp_new_ip_type(IPADDR_TYPE_V6);
|
||||
pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
|
||||
|
||||
err1 = udp_bind(pcb1, &ip1, 2105);
|
||||
err2 = udp_bind(pcb2, &ip2, 2105);
|
||||
|
||||
fail_unless(err1 == ERR_OK);
|
||||
fail_unless(err2 == ERR_USE);
|
||||
|
||||
udp_remove(pcb1);
|
||||
udp_remove(pcb2);
|
||||
|
||||
/* bind on same port using ANY + IPv4 */
|
||||
ip1 = *IP_ANY_TYPE;
|
||||
IP_ADDR4(&ip2, 1, 2, 3, 4);
|
||||
|
||||
pcb1 = udp_new_ip_type(IPADDR_TYPE_ANY);
|
||||
pcb2 = udp_new_ip_type(IPADDR_TYPE_V4);
|
||||
|
||||
err1 = udp_bind(pcb1, &ip1, 2105);
|
||||
err2 = udp_bind(pcb2, &ip2, 2105);
|
||||
|
||||
fail_unless(err1 == ERR_OK);
|
||||
fail_unless(err2 == ERR_USE);
|
||||
|
||||
udp_remove(pcb1);
|
||||
udp_remove(pcb2);
|
||||
}
|
||||
END_TEST
|
||||
|
||||
/** Create the suite including all tests for this module */
|
||||
Suite *
|
||||
udp_suite(void)
|
||||
{
|
||||
testfunc tests[] = {
|
||||
TESTFUNC(test_udp_new_remove),
|
||||
TESTFUNC(test_udp_broadcast_rx_with_2_netifs),
|
||||
TESTFUNC(test_udp_bind)
|
||||
};
|
||||
return create_suite("UDP", tests, sizeof(tests)/sizeof(testfunc), udp_setup, udp_teardown);
|
||||
}
|
||||
8
lwip/lwip-2.2.1/test/unit/udp/test_udp.h
Normal file
8
lwip/lwip-2.2.1/test/unit/udp/test_udp.h
Normal file
@ -0,0 +1,8 @@
|
||||
#ifndef LWIP_HDR_TEST_UDP_H
|
||||
#define LWIP_HDR_TEST_UDP_H
|
||||
|
||||
#include "../lwip_check.h"
|
||||
|
||||
Suite* udp_suite(void);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user