ci: Add simple CI test

with relaxed criteria on the lingering test, as the fix is not added yet
This commit is contained in:
David Cermak
2024-04-15 15:46:10 +02:00
parent 531e7999e8
commit f49974d881
22 changed files with 999 additions and 21 deletions
+38 -16
View File
@@ -1,32 +1,31 @@
name: CI
on:
push:
branches: [master]
on: [push, pull_request]
jobs:
build:
build-and-test:
strategy:
matrix:
compiler: [gcc, clang]
env:
CC: ${{ matrix.compiler }}
LSAN_OPTIONS: verbosity=1:log_threads=1
WGET_CHECK2JUNIT_PY: https://raw.githubusercontent.com/gsauthof/utility/42792030/check2junit.py
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Install deps
run: sudo apt-get install check ninja-build doxygen
run: |
sudo apt-get install check ninja-build doxygen
python -m pip install lxml junit-xml
wget --no-verbose ${WGET_CHECK2JUNIT_PY}
- name: Build and Run unit tests with make and cmake
run: ./test/ci/unit_tests.sh
- name: Copy lwipcfg.h for example app
run: cp contrib/examples/example_app/lwipcfg.h.ci contrib/examples/example_app/lwipcfg.h
- name: Build unit tests with make
run: make -C contrib/ports/unix/check
- name: Run unit tests
run: make -C contrib/ports/unix/check check
- name: Run cmake
run: mkdir build && cd build && cmake .. -G Ninja
- name: Build with cmake
@@ -35,9 +34,32 @@ jobs:
run: cd build && cmake --build . --target lwipdocs
- name: Validate combinations of options
run: cd contrib/ports/unix/example_app && ./iteropts.sh
run: ./test/ci/validate_opts.sh
- name: Build the default example app
run: |
cp contrib/examples/example_app/lwipcfg.h.example contrib/examples/example_app/lwipcfg.h
make -C contrib/ports/unix/example_app TESTFLAGS="-Wno-documentation" -j 4
- name: Build and run test apps
run: ./test/ci/test_apps.sh
- name: Upload Test Results
if: always()
uses: actions/upload-artifact@v2
with:
name: Test Results ${{ matrix.compiler }}
path: "*.xml"
publish-test-results:
name: "Publish Tests Results"
needs: build-and-test
runs-on: ubuntu-latest
permissions:
checks: write
if: always()
steps:
- name: Download Artifacts
uses: actions/download-artifact@v2
with:
path: artifacts
- name: Publish Test Results
uses: EnricoMi/publish-unit-test-result-action@v2
with:
junit_files: "artifacts/**/*.xml"
+75
View File
@@ -0,0 +1,75 @@
stages:
- host_test
- deploy
image: ${CI_DOCKER_REGISTRY}/esp-env-v5.0:2
variables:
CMAKE_SH: cmake-3.22.3-linux-x86_64.sh
CC: cc
before_script:
# Use CI Tools
- curl -sSL ${CIT_LOADER_URL} | sh
- source citools/import_functions
.get_cmake: &get_cmake |
wget -q https://github.com/Kitware/CMake/releases/download/v3.22.3/${CMAKE_SH}
mkdir -p /opt/cmake && sh ${CMAKE_SH} --prefix=/opt/cmake --skip-license
export PATH=/opt/cmake/bin:$PATH
run_unittests:
stage: host_test
tags:
- host_test
dependencies: []
script:
- ./test/ci/unit_tests.sh
build_all:
stage: host_test
tags:
- host_test
script:
- cp contrib/examples/example_app/lwipcfg.h.ci contrib/examples/example_app/lwipcfg.h
- mkdir build && cd build && cmake .. -G Ninja
- cmake --build .
- cmake --build . --target lwipdocs
validate_opts:
stage: host_test
tags:
- host_test
script:
- ./test/ci/validate_opts.sh
run_test_apps:
stage: host_test
tags:
- host_test
script:
- *get_cmake
- ./test/ci/test_apps.sh
.add_gh_key_remote: &add_gh_key_remote |
command -v ssh-agent >/dev/null || exit 1
eval $(ssh-agent -s)
printf '%s\n' "${GH_PUSH_KEY}" | tr -d '\r' | ssh-add - > /dev/null
mkdir -p ~/.ssh && chmod 700 ~/.ssh
[[ -f /.dockerenv ]] && echo -e "Host *\n\tStrictHostKeyChecking no\n\n" > ~/.ssh/config || ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts
git remote remove github || true
git remote add github ${GH_PUSH_REPO}
push_master_to_github:
stage: deploy
only:
- 2.1.2-esp
- 2.1.3-esp
when: on_success
variables:
GIT_STRATEGY: clone
script:
- *add_gh_key_remote
- "[ -n \"${CI_COMMIT_TAG:-}\" ] && git push github ${CI_COMMIT_TAG}"
- "[ -z \"${CI_COMMIT_TAG:-}\" ] && git push github ${CI_COMMIT_SHA}:refs/heads/${CI_COMMIT_REF_NAME}"
+2
View File
@@ -76,6 +76,8 @@ if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
list(APPEND LWIP_COMPILER_FLAGS_GNU_CLANG
-Wlogical-op
-Wtrampolines
-fno-stack-clash-protection
-Wno-error=format-extra-args
)
if (NOT LWIP_HAVE_MBEDTLS)
+1 -1
View File
@@ -16,7 +16,7 @@ include(${LWIP_DIR}/contrib/ports/CMakeCommon.cmake)
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
# check.h causes 'error: token pasting of ',' and __VA_ARGS__ is a GNU extension' with clang 9.0.0
list(LWIP_COMPILER_FLAGS APPEND -Wno-gnu-zero-variadic-macro-arguments)
list(APPEND LWIP_COMPILER_FLAGS -Wno-gnu-zero-variadic-macro-arguments)
endif()
set (LWIP_DEFINITIONS -DLWIP_DEBUG -DLWIP_NOASSERT_ON_ERROR)
-1
View File
@@ -45,7 +45,6 @@
* leaking messages.
*/
#define _GNU_SOURCE /* pull in pthread_setname_np() on Linux */
#include "lwip/debug.h"
#include <string.h>
+1 -1
View File
@@ -38,7 +38,7 @@ PROJECT_NAME = "lwIP"
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER = "2.2.0.esp"
PROJECT_NUMBER = "2.2.0.dev"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
+1 -1
View File
@@ -983,7 +983,7 @@ lwip_netconn_do_close_internal(struct netconn *conn WRITE_DELAYED_PARAM)
err = ERR_OK;
/* linger enabled/required at all? (i.e. is there untransmitted data left?) */
if ((conn->linger >= 0) && (conn->pcb.tcp->unsent || conn->pcb.tcp->unacked)) {
if ((conn->linger == 0)) {
if (conn->linger == 0) {
/* data left but linger prevents waiting */
tcp_abort(tpcb);
tpcb = NULL;
+1 -1
View File
@@ -75,7 +75,7 @@ extern "C" {
#if LWIP_VERSION_IS_RELEASE
#define LWIP_VERSION_STRING_SUFFIX ""
#elif LWIP_VERSION_IS_DEVELOPMENT
#define LWIP_VERSION_STRING_SUFFIX "esp"
#define LWIP_VERSION_STRING_SUFFIX "d"
#else
#define LWIP_VERSION_STRING_SUFFIX "rc" LWIP_VERSTR(LWIP_VERSION_RC)
#endif
+66
View File
@@ -0,0 +1,66 @@
cmake_minimum_required(VERSION 3.8)
project(lwip_test_apps C)
if (NOT CMAKE_SYSTEM_NAME STREQUAL Linux AND NOT CMAKE_SYSTEM_NAME STREQUAL Darwin)
message(FATAL_ERROR "Unit test are currently only working on Linux or Darwin")
endif()
if (NOT LWIP_DIR OR NOT LWIP_CONTRIB_DIR)
set(LWIP_DIR "$ENV{LWIP_DIR}")
set(LWIP_CONTRIB_DIR "$ENV{LWIP_CONTRIB_DIR}")
endif()
if (NOT CI_BUILD)
set(LWIP_USE_SANITIZERS true)
endif()
include(${LWIP_CONTRIB_DIR}/ports/CMakeCommon.cmake)
if(CMAKE_C_COMPILER_ID STREQUAL Clang)
# check.h causes 'error: token pasting of ',' and __VA_ARGS__ is a GNU extension' with clang 9.0.0
endif()
set (LWIP_DEFINITIONS -DLWIP_DEBUG -DLWIP_NOASSERT_ON_ERROR -DLWIP_OPTTEST_FILE)
set (LWIP_INCLUDE_DIRS
"${LWIP_DIR}/test/apps"
"${LWIP_DIR}/test/unix"
"${LWIP_CONTRIB_DIR}/ports/unix/port/include"
"${LWIP_DIR}/test/unit"
"${LWIP_DIR}/src/include"
"${LWIP_CONTRIB_DIR}/"
"${CMAKE_CURRENT_SOURCE_DIR}/"
"${CMAKE_CURRENT_SOURCE_DIR}/${TEST_CONFIG}"
)
include(${LWIP_CONTRIB_DIR}/ports/unix/Filelists.cmake)
include(${LWIP_DIR}/src/Filelists.cmake)
include(${LWIP_DIR}/test/apps/Filelists.cmake)
add_executable(lwip_test_apps ${LWIP_TESTFILES})
target_include_directories(lwip_test_apps PRIVATE ${LWIP_INCLUDE_DIRS})
target_compile_options(lwip_test_apps PRIVATE ${LWIP_COMPILER_FLAGS})
target_compile_definitions(lwip_test_apps PRIVATE ${LWIP_DEFINITIONS} ${LWIP_MBEDTLS_DEFINITIONS})
find_library(LIBCHECK check)
find_library(LIBM m)
target_link_libraries(lwip_test_apps ${LWIP_SANITIZER_LIBS} lwipallapps lwipcore ${LIBCHECK} ${LIBM})
if (NOT CMAKE_SYSTEM_NAME STREQUAL Darwin)
# check installed via brew on Darwin doesn't have a separate subunit library (must be statically linked)
find_library(LIBSUBUNIT subunit)
target_link_libraries(lwip_test_apps ${LIBSUBUNIT})
endif()
if (CMAKE_SYSTEM_NAME STREQUAL Linux)
find_library(LIBUTIL util)
find_library(LIBPTHREAD pthread)
find_library(LIBRT rt)
target_link_libraries(lwip_test_apps ${LIBUTIL} ${LIBPTHREAD} ${LIBRT})
endif()
if (CMAKE_SYSTEM_NAME STREQUAL Darwin)
# Darwin doesn't have pthreads or POSIX real-time extensions libs
find_library(LIBUTIL util)
target_link_libraries(lwip_test_apps ${LIBUTIL})
endif()
+16
View File
@@ -0,0 +1,16 @@
# 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.
set(LWIP_TESTDIR ${LWIP_DIR}/test/apps)
set(LWIP_TESTFILES
${LWIP_TESTDIR}/test_apps.c
${LWIP_TESTDIR}/test_sockets.c
${LWIP_CONTRIB_DIR}/ports/unix/port/sys_arch.c
)
+4
View File
@@ -0,0 +1,4 @@
#ifndef LWIP_HDR_LWIP_CHECK_CONFIG_H
#define LWIP_HDR_LWIP_CHECK_CONFIG_H
#endif /* LWIP_TEST_APPS_CONFIG_H */
+37
View File
@@ -0,0 +1,37 @@
#ifndef LWIP_HDR_TEST_APPS_LWIPOPTS_TEST_H
#define LWIP_HDR_TEST_APPS_LWIPOPTS_TEST_H
#define LWIP_SO_LINGER 1
#ifdef LWIP_DEBUG
#define LWIP_DBG_MIN_LEVEL 0
#define PPP_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define DNS_DEBUG LWIP_DBG_OFF
#define AUTOIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define IGMP_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#endif
#endif /* LWIP_HDR_TEST_APPS_LWIPOPTS_TEST_H */
@@ -0,0 +1,7 @@
#ifndef LWIP_HDR_TEST_APPS_LWIPOPTS_TEST_H
#define LWIP_HDR_TEST_APPS_LWIPOPTS_TEST_H
#define LWIP_SO_LINGER 1
#define SO_REUSE 1
#endif /* LWIP_HDR_TEST_APPS_LWIPOPTS_TEST_H */
@@ -0,0 +1,37 @@
#ifndef LWIP_HDR_TEST_APPS_LWIPOPTS_TEST_H
#define LWIP_HDR_TEST_APPS_LWIPOPTS_TEST_H
#define LWIP_SO_LINGER 0
#ifdef LWIP_DEBUG
#define LWIP_DBG_MIN_LEVEL 0
#define PPP_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define DNS_DEBUG LWIP_DBG_OFF
#define AUTOIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define IGMP_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#endif
#endif /* LWIP_HDR_TEST_APPS_LWIPOPTS_TEST_H */
+310
View File
@@ -0,0 +1,310 @@
/*
* 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: Adam Dunkels <adam@sics.se>
*
*/
#ifndef LWIP_LWIPOPTS_H
#define LWIP_LWIPOPTS_H
#ifdef LWIP_OPTTEST_FILE
#include "lwipopts_test.h"
#endif /* LWIP_OPTTEST_FILE */
#define LWIP_IPV4 1
#define LWIP_IPV6 0
#define LWIP_ND6 0
#define LWIP_IPV6_REASS 0
#define NO_SYS 0
#define LWIP_SOCKET (NO_SYS==0)
#define LWIP_NETCONN (NO_SYS==0)
#define LWIP_NETIF_API (NO_SYS==0)
#define LWIP_IGMP LWIP_IPV4
#define LWIP_ICMP LWIP_IPV4
#define LWIP_SNMP LWIP_UDP
#define MIB2_STATS LWIP_SNMP
#ifdef LWIP_HAVE_MBEDTLS
#define LWIP_SNMP_V3 (LWIP_SNMP)
#endif
#define LWIP_DNS LWIP_UDP
#define LWIP_MDNS_RESPONDER LWIP_UDP
#define LWIP_NUM_NETIF_CLIENT_DATA (LWIP_MDNS_RESPONDER)
#define LWIP_HAVE_LOOPIF 1
#define LWIP_NETIF_LOOPBACK 1
#define LWIP_LOOPBACK_MAX_PBUFS 10
#define TCP_LISTEN_BACKLOG 1
#define LWIP_COMPAT_SOCKETS 1
#define LWIP_SO_RCVTIMEO 1
#define LWIP_SO_RCVBUF 1
#define LWIP_TCPIP_CORE_LOCKING 0
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_EXT_STATUS_CALLBACK 1
#define LWIP_DBG_TYPES_ON (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH|LWIP_DBG_HALT)
/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
byte alignment -> define MEM_ALIGNMENT to 2. */
/* MSVC port: intel processors don't need 4-byte alignment,
but are faster that way! */
#define MEM_ALIGNMENT 4U
/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE 16000
/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
sends a lot of data out of ROM (or other static memory), this
should be set high. */
#define MEMP_NUM_PBUF 16
/* MEMP_NUM_RAW_PCB: the number of UDP protocol control blocks. One
per active RAW "connection". */
#define MEMP_NUM_RAW_PCB 3
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
per active UDP "connection". */
#define MEMP_NUM_UDP_PCB 4
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
connections. */
#define MEMP_NUM_TCP_PCB 5
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 8
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
segments. */
#define MEMP_NUM_TCP_SEG 16
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
timeouts. */
#define MEMP_NUM_SYS_TIMEOUT (LWIP_NUM_SYS_TIMEOUT_INTERNAL + 8)
/* The following four are used only with the sequential API and can be
set to 0 if the application only will use the raw API. */
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
#define MEMP_NUM_NETBUF 2
/* MEMP_NUM_NETCONN: the number of struct netconns. */
#define MEMP_NUM_NETCONN 10
/* MEMP_NUM_TCPIP_MSG_*: the number of struct tcpip_msg, which is used
for sequential API communication and incoming packets. Used in
src/api/tcpip.c. */
#define MEMP_NUM_TCPIP_MSG_API 16
#define MEMP_NUM_TCPIP_MSG_INPKT 16
/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
#define PBUF_POOL_SIZE 120
/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE 256
/** SYS_LIGHTWEIGHT_PROT
* define SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection
* for certain critical regions during buffer allocation, deallocation and memory
* allocation and deallocation.
*/
#define SYS_LIGHTWEIGHT_PROT (NO_SYS==0)
/* ---------- TCP options ---------- */
#define LWIP_TCP 1
#define TCP_TTL 255
#define LWIP_ALTCP 0
/* Controls if TCP should queue segments that arrive out of
order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ 1
/* TCP Maximum segment size. */
#define TCP_MSS 1024
/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF 2048
/* TCP sender buffer space (pbufs). This must be at least = 2 *
TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN (4 * TCP_SND_BUF/TCP_MSS)
/* TCP writable space (bytes). This must be less than or equal
to TCP_SND_BUF. It is the amount of space which must be
available in the tcp snd_buf for select to return writable */
#define TCP_SNDLOWAT (TCP_SND_BUF/2)
/* TCP receive window. */
#define TCP_WND (20 * 1024)
/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX 12
/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX 4
/* ---------- ARP options ---------- */
#define LWIP_ARP 1
#define ARP_TABLE_SIZE 10
#define ARP_QUEUEING 1
/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
IP packets across network interfaces. If you are going to run lwIP
on a device with only one network interface, define this to 0. */
#define IP_FORWARD 0
/* IP reassembly and segmentation.These are orthogonal even
* if they both deal with IP fragments */
#define IP_REASSEMBLY 1
#define IP_REASS_MAX_PBUFS (10 * ((1500 + PBUF_POOL_BUFSIZE - 1) / PBUF_POOL_BUFSIZE))
#define MEMP_NUM_REASSDATA IP_REASS_MAX_PBUFS
#define IP_FRAG 1
#define IPV6_FRAG_COPYHEADER 1
/* ---------- ICMP options ---------- */
#define ICMP_TTL 255
/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
interfaces. */
#define LWIP_DHCP LWIP_UDP
/* 1 if you want to do an ARP check on the offered address
(recommended). */
#define DHCP_DOES_ARP_CHECK (LWIP_DHCP)
/* ---------- AUTOIP options ------- */
#define LWIP_AUTOIP (LWIP_DHCP)
#define LWIP_DHCP_AUTOIP_COOP (LWIP_DHCP && LWIP_AUTOIP)
/* ---------- UDP options ---------- */
#define LWIP_UDP 1
#define LWIP_UDPLITE LWIP_UDP
#define UDP_TTL 255
/* ---------- RAW options ---------- */
#define LWIP_RAW 1
/* ---------- Statistics options ---------- */
#define LWIP_STATS 1
#define LWIP_STATS_DISPLAY 1
#if LWIP_STATS
#define LINK_STATS 1
#define IP_STATS 1
#define ICMP_STATS 1
#define IGMP_STATS 1
#define IPFRAG_STATS 1
#define UDP_STATS 1
#define TCP_STATS 1
#define MEM_STATS 1
#define MEMP_STATS 1
#define PBUF_STATS 1
#define SYS_STATS 1
#endif /* LWIP_STATS */
/* ---------- NETBIOS options ---------- */
#define LWIP_NETBIOS_RESPOND_NAME_QUERY 1
/* ---------- PPP options ---------- */
#define PPP_SUPPORT 1 /* Set > 0 for PPP */
#if PPP_SUPPORT
#define NUM_PPP 1 /* Max PPP sessions. */
/* Select modules to enable. Ideally these would be set in the makefile but
* we're limited by the command line length so you need to modify the settings
* in this file.
*/
#define PPPOE_SUPPORT 1
#define PPPOS_SUPPORT 1
#define PAP_SUPPORT 1 /* Set > 0 for PAP. */
#define CHAP_SUPPORT 1 /* Set > 0 for CHAP. */
#define MSCHAP_SUPPORT 0 /* Set > 0 for MSCHAP */
#define CBCP_SUPPORT 0 /* Set > 0 for CBCP (NOT FUNCTIONAL!) */
#define CCP_SUPPORT 0 /* Set > 0 for CCP */
#define VJ_SUPPORT 1 /* Set > 0 for VJ header compression. */
#define MD5_SUPPORT 1 /* Set > 0 for MD5 (see also CHAP) */
#endif /* PPP_SUPPORT */
/* The following defines must be done even in OPTTEST mode: */
void sys_check_core_locking(void);
struct sys_sem;
typedef struct sys_sem * sys_sem_t;
sys_sem_t* sys_thread_sem_get(void);
void sys_thread_sem_init(void);
void sys_thread_sem_deinit(void);
#define ESP_LWIP 1
#define LWIP_NETCONN_FULLDUPLEX 1
#define LWIP_NETCONN_SEM_PER_THREAD 1
#define ESP_LWIP_IGMP_TIMERS_ONDEMAND 1
#define ESP_LWIP_DHCP_FINE_TIMERS_ONDEMAND 1
#define ESP_LWIP_DNS_TIMERS_ONDEMAND 1
#define ESP_LWIP_MLD6_TIMERS_ONDEMAND 1
#if IP_REASSEMBLY
#define ESP_LWIP_IP4_REASSEMBLY_TIMERS_ONDEMAND 1
#endif /* IP_REASSEMBLY */
#if LWIP_IPV6_REASS
#define ESP_LWIP_IP6_REASSEMBLY_TIMERS_ONDEMAND 1
#endif /* LWIP_IPV6_REASS */
#define ESP_DNS 1
#define ESP_LWIP_ARP 1
#define LWIP_AUTOIP_MAX_CONFLICTS 10
#define LWIP_AUTOIP_RATE_LIMIT_INTERVAL 60
#define DNS_FALLBACK_SERVER_INDEX (DNS_MAX_SERVERS - 1)
#endif /* LWIP_LWIPOPTS_H */
+11
View File
@@ -0,0 +1,11 @@
try:
import sys
from junit_xml import TestSuite as ts, TestCase as tc
t=tc("lingering close stress test")
if len(sys.argv) > 1 and sys.argv[1] == "failed":
t.add_failure_info("test got stuck when closing clients socket")
print(ts.to_xml_string([ts("SOCKET SO_LINGER stress test", [t])]))
except ImportError:
print()
+60
View File
@@ -0,0 +1,60 @@
#include "lwip_check.h"
#include "api/test_sockets.h"
#include "lwip/init.h"
#include "lwip/tcpip.h"
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;
for (i = 0, mask = 1; i < MEMP_MAX; i++, mask <<= 1) {
if (!(skip & mask)) {
fail_unless(lwip_stats.memp[i]->used == 0);
}
}
}
int main(void)
{
int number_failed;
SRunner *sr;
size_t i;
suite_getter_fn* suites[] = {
sockets_suite,
};
size_t num = sizeof(suites)/sizeof(void*);
LWIP_ASSERT("No suites defined", num > 0);
tcpip_init(NULL, NULL);
sr = srunner_create((suites[0])());
srunner_set_xml(sr, "lwip_test_apps.xml");
for(i = 1; i < num; i++) {
srunner_add_suite(sr, ((suite_getter_fn*)suites[i])());
}
srunner_set_fork_status(sr, CK_NOFORK);
srunner_run_all(sr, CK_NORMAL);
number_failed = srunner_ntests_failed(sr);
srunner_free(sr);
return (number_failed == 0) ? EXIT_SUCCESS : EXIT_FAILURE;
}
+249
View File
@@ -0,0 +1,249 @@
#include <pthread.h>
#include "lwip_check.h"
#include "lwip/mem.h"
#include "lwip/opt.h"
#include "lwip/sockets.h"
#include "lwip/priv/sockets_priv.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/api.h"
Suite *sockets_suite(void);
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;
}
#if !SO_REUSE
static int
wait_for_pcbs_to_cleanup(void)
{
struct tcp_pcb *pcb = tcp_active_pcbs;
while (pcb != NULL) {
if (pcb->state == TIME_WAIT || pcb->state == LAST_ACK) {
return -1;
}
pcb = pcb->next;
}
return 0;
}
#endif
/* Setups/teardown functions */
static void
sockets_setup(void)
{
fail_unless(test_sockets_get_used_count() == 0);
}
static void
sockets_teardown(void)
{
fail_unless(test_sockets_get_used_count() == 0);
/* poll until all memory is released... */
while (tcp_tw_pcbs) {
tcp_abort(tcp_tw_pcbs);
}
}
struct test_params {
int listener;
size_t tx_buffer_size;
struct linger so_linger;
};
static void *
server_thread(void *arg)
{
struct test_params *params = (struct test_params *)arg;
int srv;
int err;
int ret;
struct sockaddr_storage source_addr;
socklen_t addr_len = sizeof(source_addr);
char rxbuf[16];
/* accept the connection */
srv = lwip_accept(params->listener, (struct sockaddr *)&source_addr, &addr_len);
/* accepted, so won't need the listener socket anymore, close it */
ret = lwip_close(params->listener);
fail_unless(ret == 0);
#if LWIP_SO_LINGER
/* if we linger with timout=0, we might not be able to even accept */
if (params->so_linger.l_linger == 0 && srv < 0) {
return NULL;
}
fail_unless(srv >= 0);
#endif
#if !LWIP_SO_LINGER
/* check that we received exactly the amount of bytes that we sent */
ret = lwip_recv(srv, rxbuf, params->tx_buffer_size, 0);
err = errno;
fail_unless(ret == (int)params->tx_buffer_size);
/* check that we received exactly 0, i.e. EOF, connection closed cleanly */
ret = lwip_recv(srv, rxbuf, sizeof(rxbuf), 0);
err = errno;
fail_unless(ret == 0);
/* check that we could receive no longer */
ret = lwip_recv(srv, rxbuf, sizeof(rxbuf), 0);
err = errno;
fail_unless(ret == -1);
fail_unless(err == ENOTCONN || err == ECONNRESET);
#else
/* try to receive (could be data or EOF if the client lingers on closing) */
ret = lwip_recv(srv, rxbuf, sizeof(rxbuf), 0);
err = errno;
fail_unless(ret >= 0);
fail_unless(err == 0);
if (params->so_linger.l_onoff == 1 && params->so_linger.l_linger > 0) {
/* if lingering enabled with a non-zero timeout, let's just close
* (connection could be closed both cleanly and abruptly) */
ret = lwip_close(srv);
fail_unless(ret == 0);
return NULL;
}
/* otherwise, check that we could receive no longer */
ret = lwip_recv(srv, rxbuf, sizeof(rxbuf), 0);
err = errno;
if (params->so_linger.l_onoff == 0 || params->so_linger.l_linger > 0) {
/* if lingering disabled or timeout nonzero, we should get a clean exit */
fail_unless(ret == 0);
} else {
/* linger with timeout=0, expect an abrupt closure */
fail_unless(ret == -1);
fail_unless(err == ENOTCONN || err == ECONNRESET);
}
#endif
/* close server socket */
ret = lwip_close(srv);
fail_unless(ret == 0);
return NULL;
}
static void
test_socket_close_linger(int l_onoff, int l_linger)
{
int client;
int ret;
struct sockaddr_in sa_listen;
const u16_t port = 1234;
static const char txbuf[] = "something";
struct test_params params;
int err;
pthread_t srv_thread;
/* set test parameters */
params.so_linger.l_onoff = l_onoff;
params.so_linger.l_linger = l_linger;
params.tx_buffer_size = sizeof(txbuf);
fail_unless(test_sockets_get_used_count() == 0);
/* set up the listener */
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);
params.listener = lwip_socket(AF_INET, SOCK_STREAM, 0);
fail_unless(params.listener >= 0);
#if SO_REUSE
ret = 1;
fail_unless(setsockopt(params.listener, SOL_SOCKET, SO_REUSEADDR, &ret, sizeof(ret)) == 0);
#endif
ret = lwip_bind(params.listener, (struct sockaddr *)&sa_listen, sizeof(sa_listen));
fail_unless(ret == 0);
ret = lwip_listen(params.listener, 1);
fail_unless(ret == 0);
/* continue to serve connections in a separate thread*/
err = pthread_create(&srv_thread, NULL, server_thread, &params);
fail_unless(err == 0);
/* set up the client */
client = lwip_socket(AF_INET, SOCK_STREAM, 0);
/* connect */
ret = lwip_connect(client, (struct sockaddr *) &sa_listen, sizeof(sa_listen));
fail_unless(ret == 0);
/* set socket to enable SO_LINGER option */
ret = lwip_setsockopt(client, SOL_SOCKET, SO_LINGER, &params.so_linger, sizeof(params.so_linger));
#if LWIP_SO_LINGER
fail_unless(ret == 0);
#else
/* If not enabled, just expect No Such Option error */
err = errno;
fail_unless(ret == -1);
fail_unless(err == ENOPROTOOPT);
#endif /* LWIP_SO_LINGER */
ret = lwip_send(client, txbuf, sizeof(txbuf), 0);
fail_unless(ret == sizeof(txbuf));
/* close from client's side */
ret = lwip_close(client);
#if !LWIP_SO_LINGER
err = errno;
fail_unless(ret == 0);
#endif
pthread_join(srv_thread, NULL);
#if !SO_REUSE
while (wait_for_pcbs_to_cleanup() != 0) {
usleep(1000);
}
#endif
}
START_TEST(test_sockets_close_state_machine_linger_off)
{
LWIP_UNUSED_ARG(_i);
test_socket_close_linger(0, 0);
}
END_TEST
START_TEST(test_sockets_close_state_machine_linger_on)
{
LWIP_UNUSED_ARG(_i);
test_socket_close_linger(1, 1);
}
END_TEST
START_TEST(test_sockets_close_state_machine_linger_on_timeout_0)
{
LWIP_UNUSED_ARG(_i);
test_socket_close_linger(1, 0);
}
END_TEST
/** Create the suite including all tests for this module */
Suite *
sockets_suite(void)
{
testfunc tests[] = {
TESTFUNC(test_sockets_close_state_machine_linger_off),
TESTFUNC(test_sockets_close_state_machine_linger_on),
TESTFUNC(test_sockets_close_state_machine_linger_on_timeout_0),
};
return create_suite("SOCKETS", tests, sizeof(tests)/sizeof(testfunc), sockets_setup, sockets_teardown);
}
+20
View File
@@ -0,0 +1,20 @@
#!/bin/bash
set -e
export LWIP_DIR=`pwd`
export LWIP_CONTRIB_DIR=`pwd`/contrib
cd test/apps
# Prepare a failing report in case we get stuck (check in no-fork mode)
python socket_linger_stress_test.py failed > ${LWIP_DIR}/socket_linger_stress_test.xml
for cfg in config_no_linger config_linger config_linger_reuse; do
cmake -DCI_BUILD=1 -DTEST_CONFIG=${cfg} -B ${cfg} -G Ninja .
cmake --build ${cfg}/
timeout 10 ./${cfg}/lwip_test_apps
[ -f check2junit.py ] &&
python ${LWIP_DIR}/check2junit.py lwip_test_apps.xml > ${LWIP_DIR}/${cfg}.xml
done
# Run the lingering test multiple times
for run in {1..10}; do ( timeout 10 ./config_linger/lwip_test_apps ) || exit 1 ; done
# All good, regenerate the stress test-report, since the test succeeded
python socket_linger_stress_test.py > ${LWIP_DIR}/socket_linger_stress_test.xml
+43
View File
@@ -0,0 +1,43 @@
#!/bin/bash
set -e
export CI_ROOT_DIR=`pwd`
export LWIPDIR=../../../../src
export ORIG_CC=${CC}
pushd `pwd`
cd contrib/ports/unix/check
### with GNU Make
# build and run default lwip tests (ESP_LWIP=0!)
make clean
make -j 4 check
# retest with ESP_LWIP patches
make clean
export EXTRA_CFLAGS="-DESP_LWIP=1" && export CC="${ORIG_CC} ${EXTRA_CFLAGS}"
make -j 4 check
# retest with IP_FORWARD enabled
make clean
export EXTRA_CFLAGS="-DESP_LWIP=1 -DIP_FORWARD=1" && export CC="${ORIG_CC} ${EXTRA_CFLAGS}"
make -j 4 check
# retest with IP_FORWARD and IP_NAPT enabled
make clean
export EXTRA_CFLAGS="-DESP_LWIP=1 -DIP_FORWARD=1 -DIP_NAPT=1" && export CC="${ORIG_CC} ${EXTRA_CFLAGS}"
make -j 4 check
# Please uncomment the below to test IP_FORWARD/IP_NAPT tests with debug output (only ip4_route test suite will be executed)
make clean
export EXTRA_CFLAGS="-DESP_LWIP=1 -DIP_FORWARD=1 -DESP_TEST_DEBUG=1 -DIP_NAPT=1" && export CC="${ORIG_CC} ${EXTRA_CFLAGS}"
make -j 4 check
### with CMake
cd ${CI_ROOT_DIR}/contrib/ports/unix/check
rm -rf build
export EXTRA_CFLAGS=""
export CC="${ORIG_CC}"
mkdir build && cd build && cmake -DLWIP_DIR=`pwd`/../../../../.. .. -G Ninja
cmake --build . && ./lwip_unittests
[ -f ${CI_ROOT_DIR}/check2junit.py ] &&
python ${CI_ROOT_DIR}/check2junit.py lwip_unittests.xml > ${CI_ROOT_DIR}/unit_tests.xml
popd
+11
View File
@@ -0,0 +1,11 @@
#!/bin/bash
set -e
export CFLAGS="-I../../../../test/unix -include esp_lwipopts.h"
export LWIPDIR=../../../../src/
cp contrib/examples/example_app/lwipcfg.h.example contrib/examples/example_app/lwipcfg.h
cd contrib/ports/unix/example_app
make TESTFLAGS="-Wno-documentation" -j 4
chmod +x iteropts.sh
./iteropts.sh
+9
View File
@@ -0,0 +1,9 @@
#define ESP_LWIP LWIP_NETCONN_FULLDUPLEX
#define ESP_LWIP_IP4_REASSEMBLY_TIMERS_ONDEMAND ESP_LWIP
#define ESP_LWIP_IP6_REASSEMBLY_TIMERS_ONDEMAND ESP_LWIP
#define ESP_LWIP_DNS_TIMERS_ONDEMAND ESP_LWIP
#define ESP_LWIP_DHCP_FINE_TIMERS_ONDEMAND ESP_LWIP
#define ESP_LWIP_IGMP_TIMERS_ONDEMAND ESP_LWIP
#define ESP_LWIP_MLD6_TIMERS_ONDEMAND ESP_LWIP
#define ESP_DNS ESP_LWIP
#define ESP_LWIP_ARP ESP_LWIP