From 514de4155d6731b133b6e436aa53891732dceed4 Mon Sep 17 00:00:00 2001 From: Christian Spielberger Date: Sat, 1 Oct 2022 11:00:15 +0200 Subject: [PATCH] release v2.8.0 (#133) * async: add new tests (#107) * cmake: add path to windows build * mock: fix warning * dns/client: add async getaddrinfo usage (#112) * dns: refactor IP checks and add system test * use dnsc_getaddrinfo * fmt: workaround for windows compiler * sys: fix unlink and WIN32 * test: cast values to fix WIN32 warnings * trace: fix unlink and WIN32 * main: only run regular tests if GETOPT is missing * test: various fixes for WIN32 * async: fix multithreading tests (#115) * main: if GETOPT is missing run regular tests * cmake: add LINKLIBS variable * test cmake on Windows (#114) * test cmake on Windows * You have an error in your yaml syntax on line 14 * fix yaml syntax error * try to find re * try to find rem * mock: fix win32 warning * fix unlink warnings * fix warnings * fix write * fix size_t * write needs unsigned int * link to win32 libs * add qwave * execute retest.exe in build/debug * set verbose * set verbose * disable all * update flags * ci: fix compiler list and choco * LINKLIBS and flags * test: fix c11 err handling * cmake: use re config (#118) * base64: Encoding/Decoding with URL and Filename Safe Alphabet (#113) * cmake: bump minimum to 3.10 (#119) * Don't fail on compilation when there no OpenSSL on target platform (#120) * trice: fix win32 with explicit error tests (#121) * http: test http/https requests with large body * http: validate body of http requests for get method * http: add test for http conn requests * dns: test dnsc_getaddrinfo_enabled * rtp: Update tests for the changed rtp_send signature. This updates RTP tests for compatibility with this PR: https://github.com/baresip/re/pull/418 * crc32: add re wrapper * sipreg: use TEST_ERR and remove static port test Tests should run without interfere with each other. Looks like on Github Actions runners share the same port range sometimes? So for tests we have to use dynamic ports. * cmake: no need to link to libz * sa: init err * cmake: add optional zlib linking * cmake/FindREM: add rem-static target name * sys: remove old sys div test (#130) * aubuf: refactor aubuf_auframe test (#70) * rtcp: use udp_send() (#132) * rtcp: use udp_send() * rtcp: add workaround for OOM test Co-authored-by: Sebastian Reimers Co-authored-by: Alfred E. Heggestad Co-authored-by: Dmitry Ilyin Co-authored-by: Franz Auernigg Co-authored-by: Andrey Semashev --- .github/workflows/build.yml | 17 ++- CMakeLists.txt | 106 +++---------- cmake/FindRE.cmake | 3 +- cmake/FindREM.cmake | 5 +- src/async.c | 113 ++++++++++++++ src/aubuf.c | 176 ++++++++++++---------- src/base64.c | 99 +++++++++--- src/crc32.c | 4 +- src/dns.c | 45 ++++-- src/fmt.c | 6 +- src/http.c | 289 ++++++++++++++++++++++++++++++++---- src/main.c | 10 +- src/mock/turnsrv.c | 2 +- src/rtcp.c | 14 +- src/rtp.c | 6 +- src/sa.c | 2 +- src/sipreg.c | 9 +- src/sys.c | 30 +--- src/test.c | 40 +++-- src/test.h | 6 +- src/trace.c | 4 + src/trice.c | 29 ++-- 22 files changed, 717 insertions(+), 298 deletions(-) create mode 100644 src/async.c diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3424f93a..db109c91 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -17,10 +17,12 @@ jobs: strategy: matrix: compiler: [gcc, clang] - os: [ubuntu-latest, macos-latest] + os: [ubuntu-latest, macos-latest, windows-latest] exclude: - os: macos-latest compiler: gcc + - os: windows-latest + compiler: clang env: CC: ${{ matrix.compiler }} @@ -32,6 +34,11 @@ jobs: run: | echo "OPENSSL_ROOT_DIR=/usr/local/opt/openssl" >> $GITHUB_ENV + - name: install packages + if: ${{ runner.os == 'Windows' }} + run: | + choco install --no-progress openssl + - uses: sreimers/pr-dependency-action@v0.5 with: name: re @@ -45,6 +52,7 @@ jobs: secret: ${{ secrets.GITHUB_TOKEN }} - name: make re/rem + shell: bash run: | for p in re rem; do cmake -S $p -B $p/build @@ -69,3 +77,10 @@ jobs: run: | OPENSSL_ROOT_DIR=/usr/local/opt/openssl cmake -DCMAKE_C_FLAGS="-Werror" . && make ./retest -r + + - name: retest + if: ${{ runner.os == 'Windows' }} + run: | + cmake -B build -DCMAKE_C_FLAGS="/WX" + cmake --build build + build\Debug\retest.exe -v -r diff --git a/CMakeLists.txt b/CMakeLists.txt index 33747d32..86bc9a5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,7 +9,7 @@ # Versioning # -cmake_minimum_required(VERSION 3.7) +cmake_minimum_required(VERSION 3.10) project(retest C) @@ -21,21 +21,14 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) # Module/Package Includes # -include(CheckIncludeFile) -include(CheckFunctionExists) -include(CheckSymbolExists) find_package(RE REQUIRED) find_package(REM REQUIRED) -find_package(Threads REQUIRED) -find_package(OpenSSL) - ############################################################################## # # Compile options/definitions # -option(USE_OPENSSL "Enable OpenSSL" ${OPENSSL_FOUND}) option(USE_SANITIZER "Sanitizers like: address, thread, undefined, memory") include(sanitizer) @@ -66,86 +59,13 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang") add_compile_options(-Wshorten-64-to-32) endif() -check_include_file(unistd.h HAVE_UNISTD_H) -if(HAVE_UNISTD_H) - add_definitions(-DHAVE_UNISTD_H) -endif() - -check_function_exists(thrd_create HAVE_THREADS) -if(HAVE_THREADS) - add_definitions(-DHAVE_THREADS) -endif() - -if(CMAKE_USE_PTHREADS_INIT) - add_definitions(-DHAVE_PTHREAD) - set(HAVE_PTHREAD ON) -endif() - -check_symbol_exists("arc4random" "stdlib.h" HAVE_ARC4RANDOM) -if(HAVE_ARC4RANDOM) - add_definitions(-DHAVE_ARC4RANDOM) -endif() - - include_directories( src - ../re/include - ../rem/include ${RE_INCLUDE_DIRS} ${REM_INCLUDE_DIRS} ) -add_definitions( - -DHAVE_ATOMIC - -DHAVE_INET6 - -DHAVE_SELECT - ) - -if(UNIX) - add_definitions( - -DHAVE_GETOPT - -DHAVE_POLL - -DHAVE_PWD_H - -DHAVE_ROUTE_LIST - -DHAVE_SETRLIMIT - -DHAVE_STRERROR_R - -DHAVE_STRINGS_H - -DHAVE_SYS_TIME_H - -DHAVE_UNAME - -DHAVE_SELECT_H - -DHAVE_SIGNAL - ) - if(NOT ANDROID) - add_definitions(-DHAVE_GETIFADDRS) - endif() -endif() - - -if(MSVC) - add_definitions( - -DHAVE_IO_H - -D_CRT_SECURE_NO_WARNINGS - ) -endif() - -if(WIN32) - add_definitions( - -DWIN32 -D_WIN32_WINNT=0x0600 - ) -endif() - -if(USE_OPENSSL) - add_definitions( - -DUSE_DTLS - -DUSE_OPENSSL - -DUSE_OPENSSL_AES - -DUSE_OPENSSL_DTLS - -DUSE_OPENSSL_HMAC - -DUSE_OPENSSL_SRTP - -DUSE_TLS - ) -endif() - +find_package(re CONFIG REQUIRED HINTS ../re/cmake) ############################################################################## # @@ -158,6 +78,7 @@ set(SRCS src/aubuf.c src/aulevel.c src/auresamp.c + src/async.c src/av1.c src/base64.c src/bfcp.c @@ -241,10 +162,23 @@ endif() # Main target object # +set(LINKLIBS ${REM_LIBRARIES} ${RE_LIBRARIES} ${OPENSSL_LIBRARIES}) +if(WIN32) + list(APPEND LINKLIBS qwave iphlpapi wsock32 ws2_32) +else() + list(APPEND LINKLIBS -lpthread -lm) +endif() + +if(ZLIB_FOUND) + list(APPEND LINKLIBS ZLIB::ZLIB) +endif() + add_executable(${PROJECT_NAME} ${SRCS}) set_property(TARGET ${PROJECT_NAME} PROPERTY ENABLE_EXPORTS 1) -target_link_libraries(${PROJECT_NAME} - PRIVATE ${REM_LIBRARIES} ${RE_LIBRARIES} ${OPENSSL_LIBRARIES} - -lz -lpthread -lm) -target_include_directories(${PROJECT_NAME} PRIVATE ${OPENSSL_INCLUDE_DIR}) +target_link_libraries(${PROJECT_NAME} PRIVATE ${LINKLIBS}) +target_compile_definitions(${PROJECT_NAME} PRIVATE ${RE_DEFINITIONS}) + +if(USE_OPENSSL) + target_include_directories(${PROJECT_NAME} PRIVATE ${OPENSSL_INCLUDE_DIR}) +endif() diff --git a/cmake/FindRE.cmake b/cmake/FindRE.cmake index 2ddc5ff5..2e36c90a 100644 --- a/cmake/FindRE.cmake +++ b/cmake/FindRE.cmake @@ -5,7 +5,8 @@ find_path(RE_INCLUDE_DIR re.h HINTS ../re/include ${PC_LIBRE_INCLUDEDIR} ${PC_LIBRE_INCLUDE_DIRS}) find_library(RE_LIBRARY NAMES re libre re-static - HINTS ../re ../re/build ${PC_LIBRE_LIBDIR} ${PC_LIBRE_LIBRARY_DIRS}) + HINTS ../re ../re/build ../re/build/Debug + ${PC_LIBRE_LIBDIR} ${PC_LIBRE_LIBRARY_DIRS}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(RE DEFAULT_MSG RE_LIBRARY RE_INCLUDE_DIR) diff --git a/cmake/FindREM.cmake b/cmake/FindREM.cmake index 4a3502b0..45b99b2e 100644 --- a/cmake/FindREM.cmake +++ b/cmake/FindREM.cmake @@ -4,8 +4,9 @@ pkg_check_modules(PC_LIBREM QUIET librem) find_path(REM_INCLUDE_DIR rem.h HINTS ../rem/include ${PC_LIBREM_INCLUDEDIR} ${PC_LIBREM_INCLUDE_DIRS}) -find_library(REM_LIBRARY NAMES rem librem - HINTS ../rem ../rem/build ${PC_LIBREM_LIBDIR} ${PC_LIBREM_LIBRARY_DIRS}) +find_library(REM_LIBRARY NAMES rem librem rem-static + HINTS ../rem ../rem/build ../rem/build/Debug + ${PC_LIBREM_LIBDIR} ${PC_LIBREM_LIBRARY_DIRS}) include(FindPackageHandleStandardArgs) find_package_handle_standard_args(REM DEFAULT_MSG REM_LIBRARY REM_INCLUDE_DIR) diff --git a/src/async.c b/src/async.c new file mode 100644 index 00000000..8ee99687 --- /dev/null +++ b/src/async.c @@ -0,0 +1,113 @@ +/** + * @file async.c Testcode for re async + * + * Copyright (C) 2022 Sebastian Reimers + */ +#define _BSD_SOURCE 1 +#define _DEFAULT_SOURCE 1 + +#ifndef WIN32 +#include +#endif + +#include +#include +#include "test.h" + +#define DEBUG_MODULE "async" +#define DEBUG_LEVEL 5 +#include + +struct test_cnt { + int tests; + int done; +}; + +struct test { + char domain[128]; + struct sa sa; + int err; + int err_expected; + struct test_cnt *cnt; +}; + +static int blocking_getaddr(void *arg) +{ + int err; + struct test *test = arg; + struct addrinfo *res = NULL; + struct addrinfo hints; + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; + hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG; + + + /* Blocking */ + err = getaddrinfo(test->domain, NULL, &hints, &res); + if (err) + return EADDRNOTAVAIL; + + sa_set_sa(&test->sa, res->ai_addr); + freeaddrinfo(res); + + return 0; +} + + +static void completed(int err, void *arg) +{ + struct test *test = arg; + struct sa sa; + + if (err) + goto out; + + err = re_thread_check(); + TEST_ERR(err); + + sa_set_str(&sa, "127.0.0.1", 0); + if (!sa_cmp(&sa, &test->sa, SA_ADDR)) + err = EINVAL; + + TEST_ERR(err); + +out: + test->err = err; + if (++test->cnt->done >= test->cnt->tests) + re_cancel(); +} + + +int test_async(void) +{ + int err; + + struct test_cnt cnt = {0, 0}; + + struct test testv[] = { + {"localhost", {.len = 0}, -1, 0, &cnt}, + {"test.notfound", {.len = 0}, -1, EADDRNOTAVAIL, &cnt} + }; + + cnt.tests = ARRAY_SIZE(testv); + + err = re_thread_async_init(2); + TEST_ERR(err); + + for (size_t i = 0; i < ARRAY_SIZE(testv); i++) { + err = re_thread_async(blocking_getaddr, completed, &testv[i]); + TEST_ERR(err); + } + + err = re_main_timeout(200); + TEST_ERR(err); + + for (size_t i = 0; i < ARRAY_SIZE(testv); i++) { + TEST_EQUALS(testv[i].err_expected, testv[i].err); + } + +out: + re_thread_async_close(); + return err; +} diff --git a/src/aubuf.c b/src/aubuf.c index 90065590..096ed65f 100644 --- a/src/aubuf.c +++ b/src/aubuf.c @@ -15,17 +15,21 @@ #define AUDIO_TIMEBASE 1000000U +enum { + FRAMES = 80, +}; + static int test_aubuf_raw(void) { struct aubuf *ab = NULL; - int16_t sampv_in[160]; - int16_t sampv_out[160]; + int16_t sampv_in[2 * FRAMES]; + int16_t sampv_out[2 * FRAMES]; struct mbuf *mb; unsigned i; int err; - mb = mbuf_alloc(80 * sizeof(int16_t)); + mb = mbuf_alloc(FRAMES * sizeof(int16_t)); if (!mb) return ENOMEM; @@ -33,24 +37,24 @@ static int test_aubuf_raw(void) sampv_in[i] = i; memset(sampv_out, 0, sizeof(sampv_out)); - err = aubuf_alloc(&ab, 320, 0); + err = aubuf_alloc(&ab, 4 * FRAMES, 0); TEST_ERR(err); TEST_EQUALS(0, aubuf_cur_size(ab)); - err = aubuf_write(ab, (uint8_t *)sampv_in, 80 * sizeof(int16_t)); + err = aubuf_write(ab, (uint8_t *)sampv_in, FRAMES * sizeof(int16_t)); TEST_ERR(err); - TEST_EQUALS(160, aubuf_cur_size(ab)); + TEST_EQUALS(2 * FRAMES, aubuf_cur_size(ab)); - (void)mbuf_write_mem(mb, (uint8_t *)&sampv_in[80], - 80 * sizeof(int16_t)); + (void)mbuf_write_mem(mb, (uint8_t *)&sampv_in[FRAMES], + FRAMES * sizeof(int16_t)); mb->pos = 0; err = aubuf_append(ab, mb); TEST_ERR(err); - TEST_EQUALS(320, aubuf_cur_size(ab)); + TEST_EQUALS(4 * FRAMES, aubuf_cur_size(ab)); memset(sampv_out, 0, sizeof(sampv_out)); - aubuf_read(ab, (uint8_t *)sampv_out, 160 * sizeof(int16_t)); + aubuf_read(ab, (uint8_t *)sampv_out, 2 * FRAMES * sizeof(int16_t)); TEST_MEMCMP(sampv_in, sizeof(sampv_in), sampv_out, sizeof(sampv_out)); TEST_EQUALS(0, aubuf_cur_size(ab)); @@ -64,8 +68,8 @@ static int test_aubuf_raw(void) static int test_aubuf_samp(void) { struct aubuf *ab = NULL; - int16_t sampv_in[160]; - int16_t sampv_out[160]; + int16_t sampv_in[2 * FRAMES]; + int16_t sampv_out[2 * FRAMES]; unsigned i; int err; @@ -73,16 +77,16 @@ static int test_aubuf_samp(void) sampv_in[i] = i; memset(sampv_out, 0, sizeof(sampv_out)); - err = aubuf_alloc(&ab, 320, 0); + err = aubuf_alloc(&ab, 4 * FRAMES, 0); TEST_ERR(err); TEST_EQUALS(0, aubuf_cur_size(ab)); - err |= aubuf_write_samp(ab, sampv_in, 80); - err |= aubuf_write_samp(ab, &sampv_in[80], 80); + err |= aubuf_write_samp(ab, sampv_in, FRAMES); + err |= aubuf_write_samp(ab, &sampv_in[FRAMES], FRAMES); TEST_ERR(err); - TEST_EQUALS(320, aubuf_cur_size(ab)); + TEST_EQUALS(4 * FRAMES, aubuf_cur_size(ab)); aubuf_read_samp(ab, sampv_out, ARRAY_SIZE(sampv_out)); TEST_MEMCMP(sampv_in, sizeof(sampv_in), sampv_out, sizeof(sampv_out)); @@ -97,74 +101,96 @@ static int test_aubuf_samp(void) static int test_aubuf_auframe(void) { struct aubuf *ab = NULL; - float sampv_in[160]; - float sampv_out[160]; + float sampv_in[3 * FRAMES + (FRAMES / 2)]; + float sampv_out[3 * FRAMES + (FRAMES / 2)]; uint64_t dt; struct auframe af_in; struct auframe af_out; - unsigned i; int err; - for (i=0; ip, pl->l, buf, &olen); - if (err) - break; + TEST_ERR(err); if (olen != testv[i].b64.l) { DEBUG_WARNING("b64_encode %u failed: l=%u olen=%u\n", i, testv[i].b64.l, olen); err = EINVAL; - break; + TEST_ERR(err); } if (0 != memcmp(testv[i].b64.p, buf, olen)) { DEBUG_WARNING("b64_encode %u failed: ref=%r, enc=%b\n", i, &testv[i].b64, buf, olen); err = EINVAL; - break; + TEST_ERR(err); + } + + /* Encode URL */ + olen = sizeof(buf); + err = base64url_encode((uint8_t *)pl->p, pl->l, buf, &olen); + TEST_ERR(err); + + if (olen != testv[i].b64url.l) { + DEBUG_WARNING("b64_encode %u failed: l=%u olen=%u\n", + i, testv[i].b64url.l, olen); + err = EINVAL; + TEST_ERR(err); + } + if (0 != memcmp(testv[i].b64url.p, buf, olen)) { + DEBUG_WARNING("b64_encode %u failed: ref=%r, enc=%b\n", + i, &testv[i].b64url, buf, olen); + err = EINVAL; + TEST_ERR(err); } /* Decode */ b = &testv[i].b64; olen = sizeof(b64_buf); err = base64_decode(b->p, b->l, b64_buf, &olen); - if (err) - break; + TEST_ERR(err); if (olen != testv[i].pl.l) { DEBUG_WARNING("b64_decode %u failed: l=%u olen=%u\n", i, testv[i].pl.l, olen); err = EINVAL; - break; + TEST_ERR(err); } if (0 != memcmp(testv[i].pl.p, b64_buf, olen)) { DEBUG_WARNING("b64_decode %u failed: ref=%r, enc=%b\n", i, &testv[i].pl, b64_buf, olen); err = EINVAL; - break; + TEST_ERR(err); + } + + /* Decode Url */ + b = &testv[i].b64url; + olen = sizeof(b64_buf); + err = base64_decode(b->p, b->l, b64_buf, &olen); + TEST_ERR(err); + + if (olen != testv[i].pl.l) { + DEBUG_WARNING( + "b64_decode url %u failed: l=%u olen=%u\n", i, + testv[i].pl.l, olen); + err = EINVAL; + TEST_ERR(err); + } + if (0 != memcmp(testv[i].pl.p, b64_buf, olen)) { + DEBUG_WARNING( + "b64_decode url %u failed: ref=%r, enc=%b\n", + i, &testv[i].pl, b64_buf, olen); + err = EINVAL; + TEST_ERR(err); } } + /* Invalid checks */ + char c = 'A'; + olen = sizeof(b64_buf); + err = base64_decode(&c, sizeof(c), b64_buf, &olen); + TEST_ERR(err); + + struct pl inv; + pl_set_str(&inv, "Zm8="); + olen = 1; + err = base64_decode(inv.p, inv.l, b64_buf, &olen); + TEST_EQUALS(EOVERFLOW, err); + + err = 0; +out: return err; } diff --git a/src/crc32.c b/src/crc32.c index 27592fc8..755d227d 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -28,8 +28,8 @@ int test_crc32(void) for (i=0; i -enum {NUM_TESTS = 32}; +enum { + NUM_TESTS = 32, + IP_127_0_0_1 = 0x7f000001, + IP_127_0_0_2 = 0x7f000002, + IP_127_0_0_3 = 0x7f000003, + IP_127_0_0_4 = 0x7f000004, + IP_127_0_0_5 = 0x7f000005, +}; static int mkstr(char **strp) @@ -371,57 +378,65 @@ int test_dns_integration(void) err = dns_server_alloc(&srv, false); TEST_ERR(err); - err = dns_server_add_a(srv, "test1.example.net", 0x7f000001, 1); + err = dns_server_add_a(srv, "test1.example.net", IP_127_0_0_1, 1); TEST_ERR(err); err = dnsc_alloc(&data.dnsc, NULL, &srv->addr, 1); TEST_ERR(err); - err = check_dns(&data, "test1.example.net", 0x7f000001, true); + /* Test system getaddrinfo */ + dnsc_getaddrinfo(data.dnsc, true); + err = check_dns(&data, "localhost", IP_127_0_0_1, true); + TEST_EQUALS(dnsc_getaddrinfo_enabled(data.dnsc), true); + TEST_ERR(err); + dnsc_getaddrinfo(data.dnsc, false); + TEST_EQUALS(dnsc_getaddrinfo_enabled(data.dnsc), false); + + err = check_dns(&data, "test1.example.net", IP_127_0_0_1, true); TEST_ERR(err); /* Test does not exist */ - err = check_dns(&data, "test2.example.net", 0x7f000001, true); + err = check_dns(&data, "test2.example.net", IP_127_0_0_1, true); TEST_EQUALS(ENODATA, err); dns_server_flush(srv); - err = dns_server_add_a(srv, "test1.example.net", 0x7f000002, 1); + err = dns_server_add_a(srv, "test1.example.net", IP_127_0_0_2, 1); TEST_ERR(err); - err = dns_server_add_a(srv, "test2.example.net", 0x7f000003, 1); + err = dns_server_add_a(srv, "test2.example.net", IP_127_0_0_3, 1); TEST_ERR(err); - err = dns_server_add_a(srv, "test3.example.net", 0x7f000004, 1); + err = dns_server_add_a(srv, "test3.example.net", IP_127_0_0_4, 1); TEST_ERR(err); /* --- Test DNS Cache --- */ - err = check_dns(&data, "test1.example.net", 0x7f000001, true); + err = check_dns(&data, "test1.example.net", IP_127_0_0_1, true); TEST_ERR(err); - err = check_dns(&data, "test2.example.net", 0x7f000003, true); + err = check_dns(&data, "test2.example.net", IP_127_0_0_3, true); TEST_ERR(err); - err = check_dns(&data, "test2.example.net", 0x7f000003, true); + err = check_dns(&data, "test2.example.net", IP_127_0_0_3, true); TEST_ERR(err); /* Check another resource record afterwards */ - err = check_dns(&data, "test3.example.net", 0x7f000004, true); + err = check_dns(&data, "test3.example.net", IP_127_0_0_4, true); TEST_ERR(err); sys_msleep(100); /* wait until TTL timer expires */ re_main_timeout(1); /* execute tmr callbacks */ /* --- Check expired TTL --- */ - err = check_dns(&data, "test1.example.net", 0x7f000002, true); + err = check_dns(&data, "test1.example.net", IP_127_0_0_2, true); TEST_ERR(err); /* --- Test explicit DNS cache flush --- */ dns_server_flush(srv); - err = dns_server_add_a(srv, "test1.example.net", 0x7f000005, 1); + err = dns_server_add_a(srv, "test1.example.net", IP_127_0_0_5, 1); TEST_ERR(err); dnsc_cache_flush(data.dnsc); - err = check_dns(&data, "test1.example.net", 0x7f000005, true); + err = check_dns(&data, "test1.example.net", IP_127_0_0_5, true); TEST_ERR(err); /* --- Test early query cancellation --- */ @@ -430,7 +445,7 @@ int test_dns_integration(void) TEST_ERR(err); mem_deref(q); - err = check_dns(&data, "test1.example.net", 0x7f000005, true); + err = check_dns(&data, "test1.example.net", IP_127_0_0_5, true); TEST_ERR(err); /* --- Leave query open for cleanup test --- */ diff --git a/src/fmt.c b/src/fmt.c index 56ab035e..e1ddc076 100644 --- a/src/fmt.c +++ b/src/fmt.c @@ -133,7 +133,7 @@ int test_fmt_pl_i32(void) {PL(""), 0}, {{NULL, 2}, 0}, {{"fo", 0}, 0}, - {PL("2147483648"), -2147483648}, + {PL("2147483648"), -2147483647 - 1}, {PL("9223372036854775808"), 0}, /* Working cases */ @@ -147,7 +147,7 @@ int test_fmt_pl_i32(void) {PL("-5467"), -5467}, {PL("2147483647"), 2147483647}, {PL("+2147483647"), 2147483647}, - {PL("-2147483648"), -2147483648}, + {PL("-2147483648"), -2147483647 - 1}, }; uint32_t i; int err = 0; @@ -192,7 +192,7 @@ int test_fmt_pl_i64(void) {PL("-5467"), -5467}, {PL("2147483647"), 2147483647}, {PL("2147483648"), 2147483648L}, - {PL("-2147483648"), -2147483648L}, + {PL("-2147483648"), -2147483647L - 1L}, {PL("9223372036854775807"), 9223372036854775807L}, {PL("+9223372036854775807"), 9223372036854775807L}, {PL("-9223372036854775808"), -9223372036854775807L - 1L}, diff --git a/src/http.c b/src/http.c index 98690422..597730e5 100644 --- a/src/http.c +++ b/src/http.c @@ -12,6 +12,12 @@ #define DEBUG_LEVEL 5 #include +enum large_body_test { + REQ_BODY_CHUNK_SIZE = 26 * 42, + REQ_BODY_SIZE = REQ_BODY_CHUNK_SIZE * 480 - 26, + REQ_HTTP_REQUESTS = 2 +}; + static int test_http_response_no_reasonphrase(void) { @@ -122,6 +128,7 @@ struct test { size_t clen; uint32_t n_request; uint32_t n_response; + size_t i_req_body; bool secure; int err; }; @@ -160,7 +167,88 @@ static void http_req_handler(struct http_conn *conn, TEST_STRCMP("GET", 3, msg->met.p, msg->met.l); TEST_STRCMP("/index.html", 11, msg->path.p, msg->path.l); TEST_STRCMP("", 0, msg->prm.p, msg->prm.l); - TEST_EQUALS(0, msg->clen); + TEST_EQUALS(t->clen, msg->clen); + TEST_STRCMP("abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz", 52, + mbuf_buf(msg->mb), mbuf_get_left(msg->mb)); + + /* Create a chunked response body */ + err = mbuf_write_str(mb_body, + "2\r\n" + "ab\r\n" + + "4\r\n" + "cdef\r\n" + + "8\r\n" + "ghijklmn\r\n" + + "c\r\n" + "opqrstuvwxyz\r\n" + + "0\r\n" + "\r\n" + ); + if (err) + goto out; + + t->clen = mb_body->end; + + err = http_reply(conn, 200, "OK", + "Transfer-Encoding: chunked\r\n" + "Content-Type: text/plain\r\n" + "Content-Length: %zu\r\n" + "\r\n" + "%b", + mb_body->end, + mb_body->buf, mb_body->end + ); + + out: + mem_deref(mb_body); + if (err) + abort_test(t, err); +} + + +static void http_put_req_handler(struct http_conn *conn, + const struct http_msg *msg, void *arg) +{ + struct test *t = arg; + struct mbuf *mb_body = mbuf_alloc(1024); + int err = 0; + size_t l = 0; + size_t cmp_len; + + if (!mb_body) { + err = ENOMEM; + goto out; + } + + ++t->n_request; + + if (t->secure) { + TEST_ASSERT(http_conn_tls(conn) != NULL); + } + else { + TEST_ASSERT(http_conn_tls(conn) == NULL); + } + + /* verify HTTP request */ + TEST_STRCMP("1.1", 3, msg->ver.p, msg->ver.l); + TEST_STRCMP("PUT", 3, msg->met.p, msg->met.l); + TEST_STRCMP("/index.html", 11, msg->path.p, msg->path.l); + TEST_STRCMP("", 0, msg->prm.p, msg->prm.l); + TEST_EQUALS(t->clen, msg->clen); + + l = mbuf_get_left(msg->mb); + + while (l > 0) { + cmp_len = min(l, 26); + TEST_STRCMP("abcdefghijklmnopqrstuvwxyz", cmp_len, + mbuf_buf(msg->mb), cmp_len); + mbuf_advance(msg->mb, cmp_len); + l -= cmp_len; + } /* Create a chunked response body */ err = mbuf_write_str(mb_body, @@ -249,28 +337,80 @@ static int http_data_handler(const uint8_t *buf, size_t size, struct test *t = arg; (void)msg; - if (!t->mb_body) { - + if (!t->mb_body) t->mb_body = mbuf_alloc(256); - if (!t->mb_body) - return ENOMEM; - } + if (!t->mb_body) + return 0; return mbuf_write_mem(t->mb_body, buf, size); } -static int test_http_loop_base(bool secure) +static size_t http_req_body_handler(struct mbuf *mb, void *arg) +{ + struct test *t = arg; + + if (t->i_req_body >= t->clen) + return 0; + + if (mbuf_write_mem(mb, + (const uint8_t*) "abcdefghijklmnopqrstuvwxyz", + strlen("abcdefghijklmnopqrstuvwxyz"))) { + mbuf_reset(mb); + return 0; + } + + t->i_req_body += strlen("abcdefghijklmnopqrstuvwxyz"); + return strlen("abcdefghijklmnopqrstuvwxyz"); +} + + +static size_t http_req_long_body_handler(struct mbuf *mb, void *arg) +{ + struct test *t = arg; + size_t l = 0; + size_t wlen; + + /* Create a chunked response body */ + while ( l < REQ_BODY_CHUNK_SIZE && t->i_req_body < t->clen) { + wlen = min(min(26, REQ_BODY_CHUNK_SIZE - l), + t->clen - t->i_req_body); + if (wlen <= 0) + return l; + + if (mbuf_write_mem(mb, + (const uint8_t*) "abcdefghijklmnopqrstuvwxyz", + wlen)) { + mbuf_reset(mb); + return 0; + } + l += wlen; + t->i_req_body += (uint32_t)wlen; + } + + return l; +} + + +static int test_http_loop_base(bool secure, const char *met, bool http_conn) { struct http_sock *sock = NULL; struct http_cli *cli = NULL; struct http_req *req = NULL; + struct http_reqconn *conn = NULL; struct dnsc *dnsc = NULL; struct sa srv, dns; struct test t; char url[256]; char path[256]; int err = 0; + unsigned int i; + bool put = false; + struct mbuf *mb_body = NULL; + struct pl pl; + + if (!strcmp(met, "PUT")) + put = true; memset(&t, 0, sizeof(t)); @@ -287,10 +427,11 @@ static int test_http_loop_base(bool secure) test_datapath()); err = https_listen(&sock, &srv, path, - http_req_handler, &t); + put ? http_put_req_handler : http_req_handler, &t); } else { - err = http_listen(&sock, &srv, http_req_handler, &t); + err = http_listen(&sock, &srv, + put ? http_put_req_handler : http_req_handler, &t); } if (err) goto out; @@ -307,6 +448,9 @@ static int test_http_loop_base(bool secure) if (err) goto out; + if (put) + http_client_set_bufsize_max(cli, REQ_BODY_CHUNK_SIZE + 128); + #ifdef USE_TLS if (secure) { err = http_client_add_ca(cli, path); @@ -318,31 +462,94 @@ static int test_http_loop_base(bool secure) (void)re_snprintf(url, sizeof(url), "http%s://127.0.0.1:%u/index.html", secure ? "s" : "", sa_port(&srv)); - err = http_request(&req, cli, "GET", url, - http_resp_handler, http_data_handler, &t, - NULL); - if (err) - goto out; - err = re_main_timeout(secure ? 1800 : 900); - if (err) - goto out; + for (i = 1; i <= REQ_HTTP_REQUESTS; i++) { + t.i_req_body = 0; + + t.clen = put ? REQ_BODY_SIZE : + 2 * strlen("abcdefghijklmnopqrstuvwxyz"); + + + if (http_conn) { + err = http_reqconn_alloc(&conn, cli, + http_resp_handler, http_data_handler, &t); + if (err) + goto out; + + if (put) { + err = http_reqconn_set_req_bodyh(conn, + put ? http_req_long_body_handler : + http_req_body_handler, + t.clen); + if (err) + goto out; + + pl_set_str(&pl, "PUT"); + err = http_reqconn_set_method(conn, &pl); + if (err) + goto out; + } + else { + mb_body = mbuf_alloc(t.clen); + if (!mb_body) + goto out; + + if (mbuf_write_str(mb_body, + "abcdefghijklmnopqrstuvwxyz"\ + "abcdefghijklmnopqrstuvwxyz")) + goto out; + + err = http_reqconn_set_body(conn, mb_body); + mb_body = mem_deref(mb_body); + if (err) + goto out; + } + + pl_set_str(&pl, url); + err = http_reqconn_send(conn, &pl); + } + else { + err = http_request(&req, cli, met, url, + http_resp_handler, http_data_handler, + put ? http_req_long_body_handler : + http_req_body_handler, + &t, + "Content-Length: %llu\r\n%s\r\n%s", + t.clen, + t.clen > REQ_BODY_CHUNK_SIZE ? + "Expect: 100-continue\r\n" : "", + "abcdefghijklmnopqrstuvwxyz"); + } - if (t.err) { - err = t.err; - goto out; - } + if (err) + goto out; + + err = re_main_timeout(secure ? 1800 : 900); + if (err) + goto out; + + if (t.err) { + err = t.err; + goto out; + } + + /* verify results after HTTP traffic */ + TEST_EQUALS(i, t.n_request); + TEST_EQUALS(i, t.n_response); - /* verify results after HTTP traffic */ - TEST_EQUALS(1, t.n_request); - TEST_EQUALS(1, t.n_response); + if (t.mb_body) + TEST_STRCMP("abcdefghijklmnopqrstuvwxyz", 26, + t.mb_body->buf, t.mb_body->end); - TEST_STRCMP("abcdefghijklmnopqrstuvwxyz", 26, - t.mb_body->buf, t.mb_body->end); + t.mb_body = mem_deref(t.mb_body); + req = mem_deref(req); + conn = mem_deref(conn); + } out: mem_deref(t.mb_body); mem_deref(req); + mem_deref(conn); mem_deref(cli); mem_deref(dnsc); mem_deref(sock); @@ -418,13 +625,39 @@ int test_http_client_set_tls(void) int test_http_loop(void) { - return test_http_loop_base(false); + return test_http_loop_base(false, "GET", false); } #ifdef USE_TLS int test_https_loop(void) { - return test_http_loop_base(true); + return test_http_loop_base(true, "GET", false); } #endif + + +int test_http_large_body(void) +{ + return test_http_loop_base(false, "PUT", false); +} + + +#ifdef USE_TLS +int test_https_large_body(void) +{ + return test_http_loop_base(true, "PUT", false); +} +#endif + + +int test_http_conn(void) +{ + return test_http_loop_base(false, "GET", true); +} + + +int test_http_conn_large_body(void) +{ + return test_http_loop_base(false, "PUT", true); +} diff --git a/src/main.c b/src/main.c index f31cd8f5..f8ffe8dc 100644 --- a/src/main.c +++ b/src/main.c @@ -171,9 +171,11 @@ int main(int argc, char *argv[]) (void)argc; (void)argv; do_reg = true; - do_oom = true; - do_int = true; - do_perf = true; + do_oom = false; + do_int = false; + do_perf = false; + do_all = false; + verbose = true; #endif /* Initialise debugging */ @@ -253,6 +255,8 @@ int main(int argc, char *argv[]) } out: + re_thread_async_close(); + /* Check for open timers */ tmr_debug(); diff --git a/src/mock/turnsrv.c b/src/mock/turnsrv.c index 014c1b5b..e15fad30 100644 --- a/src/mock/turnsrv.c +++ b/src/mock/turnsrv.c @@ -94,7 +94,7 @@ static void relay_udp_recv(const struct sa *src, struct mbuf *mb, void *arg) chan = find_channel_peer(turn, src); if (chan) { - uint16_t len = mbuf_get_left(mb); + uint16_t len = (uint16_t)mbuf_get_left(mb); size_t start; if (mb->pos < 4) { diff --git a/src/rtcp.c b/src/rtcp.c index 38ee8381..bd7cc559 100644 --- a/src/rtcp.c +++ b/src/rtcp.c @@ -32,7 +32,8 @@ struct fixture { }; -static int send_rtp_packet(const struct sa *dst, uint16_t seq, uint32_t ssrc) +static int send_rtp_packet(struct udp_sock *us, const struct sa *dst, + uint16_t seq, uint32_t ssrc) { struct rtp_header hdr; struct mbuf *mb = mbuf_alloc(256); @@ -53,7 +54,7 @@ static int send_rtp_packet(const struct sa *dst, uint16_t seq, uint32_t ssrc) mbuf_fill(mb, 160, 0x00); mb->pos = 0; - err = udp_send_anon(dst, mb); + err = udp_send(us, dst, mb); if (err) goto out; @@ -132,7 +133,8 @@ static int test_loss(const uint16_t *seqv, size_t seqc, for (i=0; irtp_addr, seq, ssrc); + err = send_rtp_packet(rtp_sock(f->rtp), &f->rtp_addr, + seq, ssrc); if (err) goto out; } @@ -141,7 +143,11 @@ static int test_loss(const uint16_t *seqv, size_t seqc, TEST_ERR(err); err = rtcp_stats(f->rtp, ssrc, &stats); - TEST_ERR(err); + if (err) { + if (err == ENOENT) + err = ENOMEM; + goto out; + } /* in OOM-test, detect if member/sender was not allocated */ if (stats.rx.sent == 0 && diff --git a/src/rtp.c b/src/rtp.c index bcd73b8a..c5312b80 100644 --- a/src/rtp.c +++ b/src/rtp.c @@ -520,7 +520,8 @@ static int test_rtp_listen_priv(bool clear) mbuf_write_u8(test.mb, 0); test.mb->pos = pos; sa_set_str(&sa, "127.0.0.1", sa_port(rtp_local(test.rtp))); - err = rtp_send(test.rtp, &sa, false, true, 0, 160, test.mb); + err = rtp_send(test.rtp, &sa, false, true, 0, 160, + tmr_jiffies_rt_usec(), test.mb); TEST_ERR(err); pos = test.mb->end + RTP_HEADER_SIZE; @@ -528,7 +529,8 @@ static int test_rtp_listen_priv(bool clear) mbuf_write_str(test.mb, "bcde"); mbuf_write_u8(test.mb, 0); test.mb->pos = pos; - err = rtp_send(test.rtp, &sa, false, false, 0, 320, test.mb); + err = rtp_send(test.rtp, &sa, false, false, 0, 320, + tmr_jiffies_rt_usec(), test.mb); TEST_ERR(err); if (clear) { diff --git a/src/sa.c b/src/sa.c index 416e995a..5bae68e2 100644 --- a/src/sa.c +++ b/src/sa.c @@ -205,7 +205,7 @@ int test_sa_class(void) #endif }; uint32_t i; - int err; + int err = 0; for (i=0; in_register_req > 0); @@ -197,7 +196,6 @@ int test_sipreg_tcp(void) err = reg_test(SIP_TRANSP_TCP, true, 0); err |= reg_test(SIP_TRANSP_TCP, false, 0); - err |= reg_test(SIP_TRANSP_TCP, false, 56060); return err; } @@ -209,7 +207,6 @@ int test_sipreg_tls(void) err = reg_test(SIP_TRANSP_TLS, true, 0); err |= reg_test(SIP_TRANSP_TLS, false, 0); - err |= reg_test(SIP_TRANSP_TLS, false, 56060); return err; } #endif diff --git a/src/sys.c b/src/sys.c index 07661daf..0b9112b6 100644 --- a/src/sys.c +++ b/src/sys.c @@ -17,31 +17,6 @@ #include -int test_sys_div(void) -{ - static const struct { - uint64_t a, b, res; - } testv[] = { - {15, 5, 3}, - {0x100000000ULL, 0x10000UL, 0x10000}, - {846744073709551616ULL, 8474407795116ULL, 99917}, - {1446744073709551615ULL, 2, 723372036854775807ULL} - }; - uint32_t i; - int err = 0; - - for (i=0; i +#ifdef WIN32 +#define open _open +#define read _read +#define write _write +#define close _close +#endif + + typedef int (test_exec_h)(void); struct test { @@ -43,6 +51,7 @@ static const struct test tests[] = { TEST(test_aubuf), TEST(test_aulevel), TEST(test_auresamp), + TEST(test_async), TEST(test_av1), TEST(test_base64), TEST(test_bfcp), @@ -92,9 +101,13 @@ static const struct test tests[] = { TEST(test_hmac_sha256), TEST(test_http), TEST(test_http_loop), + TEST(test_http_large_body), + TEST(test_http_conn), + TEST(test_http_conn_large_body), #ifdef USE_TLS TEST(test_https_loop), TEST(test_http_client_set_tls), + TEST(test_https_large_body), #endif TEST(test_httpauth_chall), TEST(test_httpauth_resp), @@ -173,7 +186,6 @@ static const struct test tests[] = { TEST(test_stun_resp), TEST(test_stun_reqltc), TEST(test_stun), - TEST(test_sys_div), TEST(test_sys_endian), TEST(test_sys_rand), TEST(test_sys_fs_isdir), @@ -295,8 +307,13 @@ static void restore_output(int err) (void)fclose(f); out: +#ifdef WIN32 + (void)_unlink("stdout.out"); + (void)_unlink("stderr.out"); +#else (void)unlink("stdout.out"); (void)unlink("stderr.out"); +#endif } @@ -534,7 +551,7 @@ static int testcase_perf(const struct test *test, double *usec_avgp) usec_avg = 1.0 * (usec_stop - usec_start) / (double)i; - n = usec_avg ? (REPEATS_USEC / usec_avg) : 0; + n = usec_avg ? (size_t)(REPEATS_USEC / usec_avg) : 0; n = min(REPEATS_MAX, max(n, REPEATS_MIN)); /* now for the real measurement */ @@ -646,7 +663,7 @@ int test_perf(const char *name, bool verbose) return err; } - tim->nsec_avg = 1000.0 * usec_avg; + tim->nsec_avg = (uint64_t)(1000.0 * usec_avg); } /* sort the timing table by average time */ @@ -762,9 +779,10 @@ int test_multithread(void) threadv[i].test = &tests[ti]; threadv[i].err = -1; /* error not set */ - err = thrd_create(&threadv[i].tid, - thread_handler, (void *)&threadv[i]); - if (err != thrd_success) { + err = thrd_success != thrd_create(&threadv[i].tid, + thread_handler, + (void *)&threadv[i]); + if (err) { err = EAGAIN; DEBUG_WARNING("thread_create failed (%m)\n", err); break; @@ -969,17 +987,17 @@ int test_write_file(struct mbuf *mb, const char *filename) for (;;) { uint8_t buf[1024]; - ssize_t n; + size_t count; - n = min(sizeof(buf), mbuf_get_left(mb)); - if (n == 0) + count = min(sizeof(buf), mbuf_get_left(mb)); + if (count == 0) break; - err = mbuf_read_mem(mb, buf, n); + err = mbuf_read_mem(mb, buf, count); if (err) break; - n = write(fd, (void *)buf, n); + ssize_t n = write(fd, (void *)buf, (unsigned int)count); if (n < 0) { err = errno; break; diff --git a/src/test.h b/src/test.h index 43cfed4a..23d2f1b0 100644 --- a/src/test.h +++ b/src/test.h @@ -163,6 +163,7 @@ int test_aes_gcm(void); int test_aubuf(void); int test_aulevel(void); int test_auresamp(void); +int test_async(void); int test_av1(void); int test_base64(void); int test_bfcp(void); @@ -209,9 +210,13 @@ int test_hmac_sha1(void); int test_hmac_sha256(void); int test_http(void); int test_http_loop(void); +int test_http_large_body(void); +int test_http_conn(void); +int test_http_conn_large_body(void); #ifdef USE_TLS int test_https_loop(void); int test_http_client_set_tls(void); +int test_https_large_body(void); #endif int test_httpauth_chall(void); int test_httpauth_resp(void); @@ -302,7 +307,6 @@ int test_stun_req(void); int test_stun_resp(void); int test_stun_reqltc(void); int test_stun(void); -int test_sys_div(void); int test_sys_endian(void); int test_sys_rand(void); int test_sys_fs_isdir(void); diff --git a/src/trace.c b/src/trace.c index 4ffceda3..be85c828 100644 --- a/src/trace.c +++ b/src/trace.c @@ -60,7 +60,11 @@ int test_trace(void) /* Test TRACE after close - should do nothing */ RE_TRACE_BEGIN("test", "test after close"); +#ifdef WIN32 + (void)_unlink("test_trace.json"); +#else (void)unlink("test_trace.json"); +#endif out: return err; diff --git a/src/trice.c b/src/trice.c index a74ed78b..8ba3fdca 100644 --- a/src/trice.c +++ b/src/trice.c @@ -303,14 +303,15 @@ static int fixture_init(struct fixture *f) err = trice_alloc(&f->icem, &conf, f->controlling ? ICE_ROLE_CONTROLLING : ICE_ROLE_CONTROLLED, f->lufrag, f->lpwd); - if (err) - goto out; + TEST_ERR(err); + TEST_ASSERT(f->icem != NULL); - err |= trice_set_remote_ufrag(f->icem, f->rufrag); - err |= trice_set_remote_pwd(f->icem, f->rpwd); - if (err) - goto out; + err = trice_set_remote_ufrag(f->icem, f->rufrag); + TEST_ERR(err); + + err = trice_set_remote_pwd(f->icem, f->rpwd); + TEST_ERR(err); err = sa_set_str(&f->laddr, "127.0.0.1", 0); TEST_ERR(err); @@ -1142,10 +1143,18 @@ int test_trice_loop(void) { int err = 0; - err |= checklist_udp_loop(0, 0); - err |= checklist_udp_loop(0, 1); - err |= checklist_udp_loop(1, 0); - err |= checklist_udp_loop(1, 1); + err = checklist_udp_loop(0, 0); + TEST_ERR(err); + + err = checklist_udp_loop(0, 1); + TEST_ERR(err); + + err = checklist_udp_loop(1, 0); + TEST_ERR(err); + + err = checklist_udp_loop(1, 1); + TEST_ERR(err); +out: return err; }