diff --git a/.github/workflows/all.yml b/.github/workflows/all.yml index 9e379306..e0683f50 100644 --- a/.github/workflows/all.yml +++ b/.github/workflows/all.yml @@ -22,7 +22,7 @@ jobs: # os: [ubuntu-latest, macos-latest] # @todo: macOS need fixes steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: sreimers/pr-dependency-action@v0.5 with: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index db109c91..b223eb4d 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -27,7 +27,12 @@ jobs: CC: ${{ matrix.compiler }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 + + - name: install packages linux + if: ${{ runner.os == 'Linux' }} + run: | + sudo apt-get update -q -y && sudo apt-get install -q -y libssl-dev valgrind - name: openssl path macos if: ${{ runner.os == 'macOS' }} @@ -70,7 +75,7 @@ jobs: if: ${{ runner.os == 'Linux' }} run: | cmake -DCMAKE_C_FLAGS="-Werror" . && make - ./retest -r + valgrind --leak-check=full --show-reachable=yes --error-exitcode=42 ./retest -v -r - name: retest if: ${{ runner.os == 'macOS' }} diff --git a/.github/workflows/ccheck.yml b/.github/workflows/ccheck.yml index 050fdc0c..17836868 100644 --- a/.github/workflows/ccheck.yml +++ b/.github/workflows/ccheck.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: ccheck run: | wget "https://raw.githubusercontent.com/baresip/baresip/main/test/ccheck.py" diff --git a/.github/workflows/fedora.yml b/.github/workflows/fedora.yml index 48684d93..a39050fb 100644 --- a/.github/workflows/fedora.yml +++ b/.github/workflows/fedora.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - uses: sreimers/pr-dependency-action@v0.5 with: @@ -50,7 +50,7 @@ jobs: CC: ${{ matrix.compiler }} steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - name: install devel tools run: | yum -y install git gcc clang cmake openssl-devel pkgconfig zlib-devel net-tools diff --git a/.github/workflows/run-on-arch.yml b/.github/workflows/run-on-arch.yml new file mode 100644 index 00000000..4b068a80 --- /dev/null +++ b/.github/workflows/run-on-arch.yml @@ -0,0 +1,110 @@ +on: [push, pull_request] + +jobs: + prepare: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - uses: sreimers/pr-dependency-action@v0.5 + with: + name: re + repo: https://github.com/baresip/re + secret: ${{ secrets.GITHUB_TOKEN }} + + - uses: sreimers/pr-dependency-action@v0.5 + with: + name: rem + repo: https://github.com/baresip/rem + secret: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/upload-artifact@v3 + with: + name: prepare + path: | + re + rem + + build_job: + # The host should always be linux + runs-on: ubuntu-18.04 + name: Build on ${{ matrix.distro }} ${{ matrix.arch }} + needs: prepare + + # Run steps on a matrix of 3 arch/distro combinations + strategy: + matrix: + include: + - arch: armv7 + distro: alpine_latest + - arch: aarch64 + distro: bullseye + - arch: s390x + distro: fedora_latest + + steps: + - uses: actions/checkout@v3 + + - name: Download re/rem + uses: actions/download-artifact@v3 + with: + name: prepare + + - uses: uraimo/run-on-arch-action@v2 + name: Build artifact + id: build + with: + arch: ${{ matrix.arch }} + distro: ${{ matrix.distro }} + + # Not required, but speeds up builds + githubToken: ${{ github.token }} + + # Create an artifacts directory + setup: | + mkdir -p "${PWD}/artifacts" + + # The shell to run commands with in the container + shell: /bin/sh + + # Install some dependencies in the container. This speeds up builds if + # you are also using githubToken. Any dependencies installed here will + # be part of the container image that gets cached, so subsequent + # builds don't have to re-install them. The image layer is cached + # publicly in your project's package repository, so it is vital that + # no secrets are present in the container state or logs. + install: | + case "${{ matrix.distro }}" in + ubuntu*|jessie|stretch|buster|bullseye) + apt-get update -q -y + apt-get install -q -y cmake gcc git make libssl-dev + ;; + fedora*) + dnf -y update + dnf -y install cmake gcc git make openssl-devel + ;; + alpine*) + apk update + apk add cmake gcc git linux-headers make musl-dev openssl-dev + ;; + esac + + # Produce a binary artifact and place it in the mounted volume + run: | + for p in re rem; do + cmake -S $p -B $p/build -DCMAKE_C_FLAGS="-Werror" + cmake --build $p/build -j + done + for p in re rem; do + mv $p ../. + done + cmake -B build -DCMAKE_C_FLAGS="-Werror" + cmake --build build -j + ./build/retest -v -r + + - name: Show the artifact + # Items placed in /artifacts in the container will be in + # ${PWD}/artifacts on the host. + run: | + ls -al "${PWD}/artifacts" diff --git a/.gitignore b/.gitignore index 064a29d3..01581350 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,8 @@ tags # Vim swp files *.swp + +# cmake +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake diff --git a/src/av1.c b/src/av1.c index d9e4c7e9..6f3c3605 100644 --- a/src/av1.c +++ b/src/av1.c @@ -49,16 +49,11 @@ static int test_leb128(void) if (err) goto out; - re_printf("leb128 value: [ %w ]\n", mb->buf, mb->end); - mb->pos = 0; err = av1_leb128_decode(mb, &val_dec); ASSERT_EQ(0, err); - printf("decoded: %" PRIu64 " / %" PRIx64 "\n", - val_dec, val_dec); - ASSERT_EQ(val, val_dec); mb = mem_deref(mb); diff --git a/src/bfcp.c b/src/bfcp.c index ea3b17e9..90103df9 100644 --- a/src/bfcp.c +++ b/src/bfcp.c @@ -441,6 +441,18 @@ int test_bfcp_tcp(void) err = re_main_timeout(100); TEST_ERR(err); + if (cli->handler_err) { + DEBUG_WARNING("client error: %m\n", cli->handler_err); + err = cli->handler_err; + goto out; + } + + if (srv->handler_err) { + DEBUG_WARNING("server error: %m\n", srv->handler_err); + err = srv->handler_err; + goto out; + } + TEST_EQUALS((estab_handler_called | resp_handler_called), cli->flags); TEST_EQUALS((conn_handler_called | estab_handler_called | recv_handler_called), srv->flags); diff --git a/src/fmt.c b/src/fmt.c index e1ddc076..045d20fd 100644 --- a/src/fmt.c +++ b/src/fmt.c @@ -1056,3 +1056,35 @@ int test_fmt_str_bool(void) return err; } + + +int test_fmt_str_itoa(void) +{ + char buf[ITOA_BUFSZ]; + char *s; + int err = 0; + + s = str_itoa(0, buf, 10); + TEST_ASSERT(!str_casecmp(s, "0")); + + s = str_itoa(42, buf, 10); + TEST_ASSERT(!str_casecmp(s, "42")); + + s = str_itoa(UINT32_MAX, buf, 10); + TEST_ASSERT(!str_casecmp(s, "4294967295")); + + s = str_itoa(UINT32_MAX, buf, 16); + TEST_ASSERT(!str_casecmp(s, "FFFFFFFF")); + + s = str_itoa(23, buf, 2); + TEST_ASSERT(!str_casecmp(s, "10111")); + + s = str_itoa(UINT32_MAX, buf, 2); + TEST_ASSERT(!str_casecmp(s, "11111111111111111111111111111111")); + +out: + if (err) + DEBUG_WARNING("err itoa string: %s\n", s); + + return err; +} diff --git a/src/http.c b/src/http.c index 597730e5..c7e65d1d 100644 --- a/src/http.c +++ b/src/http.c @@ -18,6 +18,9 @@ enum large_body_test { REQ_HTTP_REQUESTS = 2 }; +enum { + IP_127_0_0_1 = 0x7f000001, +}; static int test_http_response_no_reasonphrase(void) { @@ -392,13 +395,15 @@ static size_t http_req_long_body_handler(struct mbuf *mb, void *arg) } -static int test_http_loop_base(bool secure, const char *met, bool http_conn) +static int test_http_loop_base(bool secure, const char *met, bool http_conn, + bool dns_srv_query) { 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 dns_server *dns_srv = NULL; struct sa srv, dns; struct test t; char url[256]; @@ -416,10 +421,18 @@ static int test_http_loop_base(bool secure, const char *met, bool http_conn) t.secure = secure; + if (dns_srv_query) { + /* Setup Mocking DNS Server */ + err = dns_server_alloc(&dns_srv, false); + TEST_ERR(err); + + err = dns_server_add_a(dns_srv, "test1.example.net", + IP_127_0_0_1, 1); + TEST_ERR(err); + } + err |= sa_set_str(&srv, "127.0.0.1", 0); err |= sa_set_str(&dns, "127.0.0.1", 53); /* note: unused */ - if (err) - goto out; if (secure) { @@ -440,7 +453,7 @@ static int test_http_loop_base(bool secure, const char *met, bool http_conn) if (err) goto out; - err = dnsc_alloc(&dnsc, NULL, &dns, 1); + err = dnsc_alloc(&dnsc, NULL, dns_srv ? &dns_srv->addr : &dns, 1); if (err) goto out; @@ -460,8 +473,10 @@ static int test_http_loop_base(bool secure, const char *met, bool http_conn) #endif (void)re_snprintf(url, sizeof(url), - "http%s://127.0.0.1:%u/index.html", - secure ? "s" : "", sa_port(&srv)); + "http%s://%s:%u/index.html", + secure ? "s" : "", + dns_srv_query ? "test1.example.net" : "127.0.0.1", + sa_port(&srv)); for (i = 1; i <= REQ_HTTP_REQUESTS; i++) { t.i_req_body = 0; @@ -514,7 +529,7 @@ static int test_http_loop_base(bool secure, const char *met, bool http_conn) put ? http_req_long_body_handler : http_req_body_handler, &t, - "Content-Length: %llu\r\n%s\r\n%s", + "Content-Length: %zu\r\n%s\r\n%s", t.clen, t.clen > REQ_BODY_CHUNK_SIZE ? "Expect: 100-continue\r\n" : "", @@ -553,6 +568,7 @@ static int test_http_loop_base(bool secure, const char *met, bool http_conn) mem_deref(cli); mem_deref(dnsc); mem_deref(sock); + mem_deref(dns_srv); return err; } @@ -625,39 +641,45 @@ int test_http_client_set_tls(void) int test_http_loop(void) { - return test_http_loop_base(false, "GET", false); + return test_http_loop_base(false, "GET", false, false); } #ifdef USE_TLS int test_https_loop(void) { - return test_http_loop_base(true, "GET", false); + return test_http_loop_base(true, "GET", false, false); } #endif int test_http_large_body(void) { - return test_http_loop_base(false, "PUT", false); + return test_http_loop_base(false, "PUT", false, false); } #ifdef USE_TLS int test_https_large_body(void) { - return test_http_loop_base(true, "PUT", false); + return test_http_loop_base(true, "PUT", false, false); } #endif int test_http_conn(void) { - return test_http_loop_base(false, "GET", true); + return test_http_loop_base(false, "GET", true, false); } int test_http_conn_large_body(void) { - return test_http_loop_base(false, "PUT", true); + return test_http_loop_base(false, "PUT", true, false); +} + + +int test_dns_http_integration(void) +{ + return test_http_loop_base(false, "GET", true, true); } diff --git a/src/list.c b/src/list.c index 1b1eb086..f5d030af 100644 --- a/src/list.c +++ b/src/list.c @@ -4,6 +4,7 @@ * Copyright (C) 2010 Creytiv.com */ #include +#include #include #include "test.h" @@ -190,3 +191,52 @@ int test_list_sort(void) out: return err; } + + +struct flush_data { + struct le le; + struct list *flushl; +}; + + +static void data_destroy(void *arg) +{ + struct flush_data *data = arg; + struct le *le; + + LIST_FOREACH(data->flushl, le) + { + assert(list_count(data->flushl)); + } +} + + +int test_list_flush(void) +{ + struct flush_data *data[2]; + struct list flushl = LIST_INIT; + int err = 0; + + data[0] = mem_zalloc(sizeof(struct flush_data), data_destroy); + if (!data[0]) + return ENOMEM; + + data[1] = mem_zalloc(sizeof(struct flush_data), data_destroy); + if (!data[1]) { + mem_deref(data[0]); + return ENOMEM; + } + + data[0]->flushl = &flushl; + data[1]->flushl = &flushl; + + list_append(&flushl, &data[0]->le, data[0]); + list_append(&flushl, &data[1]->le, data[1]); + + list_flush(&flushl); + + TEST_EQUALS(0, list_count(&flushl)); + +out: + return err; +} diff --git a/src/net.c b/src/net.c index b43b2b01..6ece560f 100644 --- a/src/net.c +++ b/src/net.c @@ -10,6 +10,30 @@ #include +static bool ipv6_handler(const char *ifname, const struct sa *sa, void *arg) +{ + bool *supp = arg; + (void)ifname; + + if (AF_INET6 == sa_af(sa)) { + *supp = true; + return true; + } + + return false; +} + + +static bool ipv6_supported(void) +{ + bool supp = false; + + net_if_apply(ipv6_handler, &supp); + + return supp; +} + + int test_net_dst_source_addr_get(void) { struct sa dst; @@ -27,15 +51,21 @@ int test_net_dst_source_addr_get(void) TEST_ASSERT(sa_is_loopback(&ip)); - sa_init(&dst, AF_INET6); - sa_init(&ip, AF_UNSPEC); - sa_set_str(&dst, "::1", 53); + if (ipv6_supported()) { - err = net_dst_source_addr_get(&dst, &ip); - if (err) - return err; + sa_init(&dst, AF_INET6); + sa_init(&ip, AF_UNSPEC); + sa_set_str(&dst, "::1", 53); - TEST_ASSERT(sa_is_loopback(&ip)); + err = net_dst_source_addr_get(&dst, &ip); + if (err) + return err; + + TEST_ASSERT(sa_is_loopback(&ip)); + } + else { + DEBUG_NOTICE("ipv6 disabled\n"); + } out: return err; diff --git a/src/odict.c b/src/odict.c index 6e1a708f..4b68f853 100644 --- a/src/odict.c +++ b/src/odict.c @@ -43,7 +43,7 @@ static int compare(const struct dtest *test, const struct odict_entry *entry) break; case ODICT_BOOL: - TEST_EQUALS(test->u.i, odict_entry_boolean(entry)); + TEST_EQUALS(test->u.b, odict_entry_boolean(entry)); break; case ODICT_DOUBLE: @@ -151,7 +151,9 @@ int test_odict(void) /* verify that entry exist after adding */ entry = odict_lookup(dict, test->key); TEST_ASSERT(entry != NULL); - compare(test, entry); + + err = compare(test, entry); + TEST_ERR(err); } /* verify size of dictionary, after adding all entries */ diff --git a/src/sip.c b/src/sip.c index 885c8751..55a6092f 100644 --- a/src/sip.c +++ b/src/sip.c @@ -760,14 +760,16 @@ int test_sip_drequestf(void) int test_sip_drequestf_network(void) { - int err; struct sa laddr; + int err = 0; - err = net_if_getlinklocal(NULL, AF_INET6, &laddr); - TEST_ERR(err); + sa_init(&laddr, AF_INET6); - err = do_sip_drequestf(&laddr); - TEST_ERR(err); + if (0 == net_if_getlinklocal(NULL, AF_INET6, &laddr)) { + + err = do_sip_drequestf(&laddr); + TEST_ERR(err); + } out: return err; diff --git a/src/sipevent.c b/src/sipevent.c index 3b774a17..2ee2d1fa 100644 --- a/src/sipevent.c +++ b/src/sipevent.c @@ -425,13 +425,15 @@ int test_sipevent(void) int test_sipevent_network(void) { - int err; struct sa laddr; + int err = 0; - err = net_if_getlinklocal(NULL, AF_INET6, &laddr); - TEST_ERR(err); + sa_init(&laddr, AF_INET6); + + if (0 == net_if_getlinklocal(NULL, AF_INET6, &laddr)) { + + err = do_sipevent(&laddr); + } - err = do_sipevent(&laddr); -out: return err; } diff --git a/src/sys.c b/src/sys.c index 0b9112b6..ab1bafa6 100644 --- a/src/sys.c +++ b/src/sys.c @@ -171,27 +171,34 @@ int test_sys_fs_isfile(void) int test_sys_fs_fopen(void) { + char filename[256]; FILE *file; int err; - err = fs_fopen(&file, "retest_fs_fopen", "w+"); + /* Use a unique filename to avoid clash when running + * multiple instances of test + */ + re_snprintf(filename, sizeof(filename), + "retest_fs_fopen-%llu", rand_u64()); + + err = fs_fopen(&file, filename, "w+"); TEST_ERR(err); - TEST_EQUALS(true, fs_isfile("retest_fs_fopen")); + TEST_EQUALS(true, fs_isfile(filename)); err = fclose(file); TEST_ERR(err); /* Try reopen */ - err = fs_fopen(&file, "retest_fs_fopen", "w+"); + err = fs_fopen(&file, filename, "w+"); TEST_ERR(err); err = fclose(file); TEST_ERR(err); #ifdef WIN32 - (void)_unlink("retest_fs_fopen"); + (void)_unlink(filename); #else - (void)unlink("retest_fs_fopen"); + (void)unlink(filename); #endif out: diff --git a/src/test.c b/src/test.c index c801075c..0b603c69 100644 --- a/src/test.c +++ b/src/test.c @@ -87,6 +87,7 @@ static const struct test tests[] = { TEST(test_fmt_str), TEST(test_fmt_str_bool), TEST(test_fmt_str_error), + TEST(test_fmt_str_itoa), TEST(test_fmt_unicode), TEST(test_fmt_unicode_decode), TEST(test_g711_alaw), @@ -121,6 +122,7 @@ static const struct test tests[] = { TEST(test_json_bad), TEST(test_json_array), TEST(test_list), + TEST(test_list_flush), TEST(test_list_ref), TEST(test_list_sort), TEST(test_mbuf), @@ -244,6 +246,7 @@ static const struct test tests_integration[] = { TEST(test_tmr_jiffies), TEST(test_tmr_jiffies_usec), TEST(test_dns_integration), + TEST(test_dns_http_integration), }; @@ -275,13 +278,7 @@ static void restore_output(int err) fflush(stderr); /* Restore stdout/stderr */ -#ifdef WIN32 - freopen("CON", "w", stdout); - freopen("CON", "w", stderr); -#else - freopen("/dev/tty", "w", stdout); - freopen("/dev/tty", "w", stderr); -#endif + fs_stdio_restore(); if (!err) goto out; @@ -331,6 +328,18 @@ static const struct test *find_test(const char *name) } +static const struct test *find_test_int(const char *name) +{ + for (size_t i=0; iname); + (void)re_fprintf(stderr, " %-26s: ", test->name); /* All memory levels */ for (i=0; itest) continue; - re_fprintf(stderr, "%-32s: %10.2f usec\n", + re_fprintf(stderr, "%-34s: %10.2f usec\n", tim->test->name, usec_avg); } re_fprintf(stderr, "\n"); @@ -764,7 +773,7 @@ int test_multithread(void) test_mode = TEST_THREAD; - timeout_override = 10000; + timeout_override = 15000; memset(threadv, 0, sizeof(threadv)); @@ -1034,13 +1043,36 @@ int test_integration(const char *name, bool verbose) (void)re_fprintf(stderr, "integration tests\n"); + if (name) { + test = find_test_int(name); + if (!test) { + (void)re_fprintf(stderr, "no such test: %s\n", name); + return ENOENT; + } + + if (!test->name) + return EINVAL; + + (void)re_fprintf(stderr, " %-24s: ", test->name); + + if (test->exec) + err = test->exec(); + + if (err) + DEBUG_WARNING(" %-24s: NOK: %m\n", test->name, err); + else + (void)re_fprintf(stderr, "\x1b[32mOK\x1b[;m\n"); + + return err; + } + for (i=0; iname) continue; - (void)re_fprintf(stderr, " %-24s: ", test->name); + (void)re_fprintf(stderr, " %-28s: ", test->name); if (test->exec) err = test->exec(); diff --git a/src/test.h b/src/test.h index 23d2f1b0..bee5b06c 100644 --- a/src/test.h +++ b/src/test.h @@ -196,6 +196,7 @@ int test_fmt_snprintf(void); int test_fmt_str(void); int test_fmt_str_bool(void); int test_fmt_str_error(void); +int test_fmt_str_itoa(void); int test_fmt_unicode(void); int test_fmt_unicode_decode(void); int test_g711_alaw(void); @@ -213,6 +214,7 @@ int test_http_loop(void); int test_http_large_body(void); int test_http_conn(void); int test_http_conn_large_body(void); +int test_dns_http_integration(void); #ifdef USE_TLS int test_https_loop(void); int test_http_client_set_tls(void); @@ -230,6 +232,7 @@ int test_json_file(void); int test_json_unicode(void); int test_json_array(void); int test_list(void); +int test_list_flush(void); int test_list_ref(void); int test_list_sort(void); int test_mbuf(void); diff --git a/src/tls.c b/src/tls.c index 2ece7c6e..58239064 100644 --- a/src/tls.c +++ b/src/tls.c @@ -524,8 +524,8 @@ int test_tls_cli_conn_change_cert(void) (void)re_snprintf(clientcert, sizeof(clientcert), "%s/not_a_file.pem", test_datapath()); - err = tls_conn_change_cert(tt.sc_cli, clientcert); - TEST_EQUALS(EINVAL, err); + int ret = tls_conn_change_cert(tt.sc_cli, clientcert); + ASSERT_TRUE(ret==EINVAL || ret==ENOENT); memset(clientcert, 0, sizeof(clientcert)); (void)re_snprintf(clientcert, sizeof(clientcert), diff --git a/src/tmr.c b/src/tmr.c index adc04dfa..06cc66b8 100644 --- a/src/tmr.c +++ b/src/tmr.c @@ -43,7 +43,7 @@ int test_tmr_jiffies_usec(void) diff = tmr_jiffies_usec() - tmr_start; TEST_ASSERT(diff >= 1); - TEST_ASSERT(diff < 100); + TEST_ASSERT(diff < 1000); out: return err;