diff options
| author | Garrett D'Amore <garrett@damore.org> | 2020-11-16 20:44:29 -0800 |
|---|---|---|
| committer | Garrett D'Amore <garrett@damore.org> | 2020-11-18 21:05:16 -0800 |
| commit | b826bfc171d90f8bde7bd672c0ac14201b8b2742 (patch) | |
| tree | 5c416487f24104e6305a797af31c5e8b1aab99d1 /src/platform | |
| parent | cda4885676f009e2e7f2ad5e6c52743efc8b8924 (diff) | |
| download | nng-b826bfc171d90f8bde7bd672c0ac14201b8b2742.tar.gz nng-b826bfc171d90f8bde7bd672c0ac14201b8b2742.tar.bz2 nng-b826bfc171d90f8bde7bd672c0ac14201b8b2742.zip | |
Work for test refactoring.
There are a few major areas in this change.
* CMake options are now located in a common cmake/NNGOptions.cmake
file. This should make it easier for folks to figure out what
the options are, and how they are used.
* Tests are now scoped with their directory name, which should
avoid possible name collisions with test names.
* A number of tests have been either moved or incorporated into
the newer testutil/acutest framework. We are moving away from
my old c-convey framework to something easier to debug.
* We use CMake directories a bit more extensively leading to a much
cleaner CMake structure. It's not complete, but a big step in the
right direction, and a preview of future work.
* Tests are now run with verbose flags, so we get more test results
in the CI/CD logs.
Diffstat (limited to 'src/platform')
| -rw-r--r-- | src/platform/CMakeLists.txt | 17 | ||||
| -rw-r--r-- | src/platform/platform_test.c | 181 | ||||
| -rw-r--r-- | src/platform/posix/posix_file.c | 13 | ||||
| -rw-r--r-- | src/platform/resolver_test.c | 199 |
4 files changed, 402 insertions, 8 deletions
diff --git a/src/platform/CMakeLists.txt b/src/platform/CMakeLists.txt new file mode 100644 index 00000000..2b2288e1 --- /dev/null +++ b/src/platform/CMakeLists.txt @@ -0,0 +1,17 @@ +# +# Copyright 2020 Staysail Systems, Inc. <info@staystail.tech> +# +# This software is supplied under the terms of the MIT License, a +# copy of which should be located in the distribution where this +# file was obtained (LICENSE.txt). A copy of the license may also be +# found online at https://opensource.org/licenses/MIT. +# + +# Platforms. +nng_directory(platform) + +add_subdirectory(posix) +add_subdirectory(windows) + +nng_test(platform_test) +nng_test(resolver_test)
\ No newline at end of file diff --git a/src/platform/platform_test.c b/src/platform/platform_test.c new file mode 100644 index 00000000..e7dcabaa --- /dev/null +++ b/src/platform/platform_test.c @@ -0,0 +1,181 @@ +// +// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#include "testutil.h" + +#include <nng/nng.h> +#include <nng/supplemental/util/platform.h> + +#include "acutest.h" + +struct add_arg { + int cnt; + nng_mtx *mx; + nng_cv * cv; +}; + +void +add(void *arg) +{ + struct add_arg *aa = arg; + + nng_mtx_lock(aa->mx); + aa->cnt++; + nng_cv_wake(aa->cv); + nng_mtx_unlock(aa->mx); +} + +void +test_sleep(void) +{ + uint64_t start, end; + start = testutil_clock(); + nng_msleep(100); + end = testutil_clock(); + TEST_CHECK((end - start) >= 100); +#ifdef __has_feature +#if !__has_feature(thread_sanitizer) && !__has_feature(memory_sanitizer) + TEST_CHECK((end - start) <= 500); +#endif +#endif +} + +void +test_clock(void) +{ + uint64_t mstart; + uint64_t msend; + nng_time usend; + nng_time usnow; + + mstart = testutil_clock(); + usnow = nng_clock(); + nng_msleep(200); + usend = nng_clock(); + msend = testutil_clock(); + + TEST_CHECK(usend > usnow); + TEST_CHECK(msend > mstart); + +#ifdef __has_feature +#if !__has_feature(thread_sanitizer) && !__has_feature(memory_sanitizer) + uint64_t usdelta; + uint64_t msdelta; + usdelta = usend - usnow; + msdelta = msend - mstart; + TEST_CHECK(usdelta >= 200); + TEST_CHECK(usdelta < 500); // increased tolerance for CIs + if (msdelta > usdelta) { + TEST_CHECK((msdelta - usdelta) < 50); + } else { + TEST_CHECK((usdelta - msdelta) < 50); + } +#endif +#endif +} + +void +test_mutex(void) +{ + nng_mtx *mx, *mx2; + + TEST_CHECK(nng_mtx_alloc(&mx) == 0); + nng_mtx_lock(mx); + nng_mtx_unlock(mx); + + nng_mtx_lock(mx); + nng_mtx_unlock(mx); + nng_mtx_free(mx); + + // Verify that the mutexes are not always the same! + TEST_CHECK(nng_mtx_alloc(&mx) == 0); + TEST_CHECK(nng_mtx_alloc(&mx2) == 0); + TEST_CHECK(mx != mx2); + nng_mtx_free(mx); + nng_mtx_free(mx2); +} + +void +test_thread(void) +{ + nng_thread * thr; + int rv; + struct add_arg aa; + + TEST_CHECK(nng_mtx_alloc(&aa.mx) == 0); + TEST_CHECK(nng_cv_alloc(&aa.cv, aa.mx) == 0); + aa.cnt = 0; + + TEST_CHECK((rv = nng_thread_create(&thr, add, &aa)) == 0); + nng_thread_destroy(thr); + TEST_CHECK(aa.cnt == 1); + + nng_cv_free(aa.cv); + nng_mtx_free(aa.mx); +} + +void +test_cond_var(void) +{ + nng_thread * thr; + int rv; + struct add_arg aa; + + TEST_CHECK(nng_mtx_alloc(&aa.mx) == 0); + TEST_CHECK(nng_cv_alloc(&aa.cv, aa.mx) == 0); + aa.cnt = 0; + + TEST_CHECK((rv = nng_thread_create(&thr, add, &aa)) == 0); + + nng_mtx_lock(aa.mx); + while (aa.cnt == 0) { + nng_cv_wait(aa.cv); + } + nng_mtx_unlock(aa.mx); + nng_thread_destroy(thr); + TEST_CHECK(aa.cnt == 1); + + nng_cv_free(aa.cv); + nng_mtx_free(aa.mx); +} + +void +test_random(void) +{ + int same = 0; + uint32_t values[1000]; + + for (int i = 0; i < 1000; i++) { + values[i] = nng_random(); + } + for (int i = 0; i < 1000; i++) { + for (int j = 0; j < i; j++) { + if (values[j] == values[i]) { + same++; + } + } + } + + // 1% reproduction is *highly* unlikely. + // There are 4 billion possible options, we are only looking at + // 1000 of them. In general, it would be an extreme outlier + // to see more than 2 repeats, unless you RNG is biased. + TEST_CHECK_(same < 5, "fewer than 5 in 1000 repeats: %d", same); +} + +TEST_LIST = { + { "sleep", test_sleep }, + { "clock", test_clock }, + { "mutex", test_mutex }, + { "thread", test_thread }, + { "cond var", test_cond_var }, + { "random", test_random }, + { NULL, NULL }, +}; diff --git a/src/platform/posix/posix_file.c b/src/platform/posix/posix_file.c index 5d918d6b..d5fb5016 100644 --- a/src/platform/posix/posix_file.c +++ b/src/platform/posix/posix_file.c @@ -1,5 +1,5 @@ // -// Copyright 2018 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> // Copyright 2018 Capitar IT Group BV <info@capitar.com> // // This software is supplied under the terms of the MIT License, a @@ -323,15 +323,12 @@ nni_plat_temp_dir(void) char * nni_plat_join_dir(const char *prefix, const char *suffix) { - char * newdir; - size_t len; + char *result; - len = strlen(prefix) + strlen(suffix) + 2; - newdir = nni_alloc(strlen(prefix) + strlen(suffix) + 2); - if (newdir != NULL) { - (void) snprintf(newdir, len, "%s/%s", prefix, suffix); + if (nni_asprintf(&result, "%s/%s", prefix, suffix) == 0) { + return (result); } - return (newdir); + return (NULL); } #endif // NNG_PLATFORM_POSIX diff --git a/src/platform/resolver_test.c b/src/platform/resolver_test.c new file mode 100644 index 00000000..43168cdb --- /dev/null +++ b/src/platform/resolver_test.c @@ -0,0 +1,199 @@ +// +// Copyright 2020 Staysail Systems, Inc. <info@staysail.tech> +// Copyright 2018 Capitar IT Group BV <info@capitar.com> +// +// This software is supplied under the terms of the MIT License, a +// copy of which should be located in the distribution where this +// file was obtained (LICENSE.txt). A copy of the license may also be +// found online at https://opensource.org/licenses/MIT. +// + +#include "testutil.h" + +#include <string.h> + +#include "core/nng_impl.h" +#include "stubs.h" + +#include "acutest.h" + +#ifndef _WIN32 +#include <arpa/inet.h> // for htons, htonl +#endif + +uint8_t v6loop[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1 }; + +void +test_google_dns(void) +{ + nng_aio * aio; + nng_sockaddr sa; + + TEST_NNG_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nni_resolv_ip("google-public-dns-a.google.com", "80", NNG_AF_INET, + true, &sa, aio); + nng_aio_wait(aio); + TEST_NNG_PASS(nng_aio_result(aio)); + TEST_CHECK(sa.s_in.sa_family == NNG_AF_INET); + TEST_CHECK(sa.s_in.sa_port == ntohs(80)); + TEST_CHECK(sa.s_in.sa_addr == 0x08080808); // aka 8.8.8.8 + nng_aio_free(aio); +} + +void +test_numeric_addr(void) +{ + nng_aio * aio; + nng_sockaddr sa; + + TEST_NNG_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nni_resolv_ip("8.8.4.4", "69", NNG_AF_INET, true, &sa, aio); + nng_aio_wait(aio); + TEST_NNG_PASS(nng_aio_result(aio)); + TEST_CHECK(sa.s_in.sa_family == NNG_AF_INET); + TEST_CHECK(sa.s_in.sa_port == ntohs(69)); + TEST_CHECK(sa.s_in.sa_addr == ntohl(0x08080404)); // 8.8.4.4. + nng_aio_free(aio); +} + +void +test_numeric_v6(void) +{ + nng_aio * aio; + nng_sockaddr sa; + + // Travis CI has moved some of their services to host that + // apparently don't support IPv6 at all. This is very sad. + // CircleCI 2.0 is in the same boat. (Amazon to blame.) + if ((getenv("TRAVIS") != NULL) || (getenv("CIRCLECI") != NULL)) { + return; // skip this one. + } + + TEST_NNG_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nni_resolv_ip("::1", "80", NNG_AF_INET6, true, &sa, aio); + nng_aio_wait(aio); + TEST_NNG_PASS(nng_aio_result(aio)); + TEST_CHECK(sa.s_in6.sa_family == NNG_AF_INET6); + TEST_CHECK(sa.s_in6.sa_port == ntohs(80)); + TEST_CHECK(memcmp(sa.s_in6.sa_addr, v6loop, 16) == 0); + nng_aio_free(aio); +} + +void +test_service_names(void) +{ + nng_aio * aio; + nng_sockaddr sa; + + TEST_NNG_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nni_resolv_ip("8.8.4.4", "http", NNG_AF_INET, true, &sa, aio); + nng_aio_wait(aio); + TEST_NNG_PASS(nng_aio_result(aio)); + TEST_CHECK(sa.s_in.sa_port == ntohs(80)); + TEST_CHECK(sa.s_in.sa_addr = ntohl(0x08080404)); + nng_aio_free(aio); +} + +void +test_localhost_v4(void) +{ + nng_aio * aio; + nng_sockaddr sa; + + TEST_NNG_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nni_resolv_ip("localhost", "80", NNG_AF_INET, true, &sa, aio); + nng_aio_wait(aio); + TEST_NNG_PASS(nng_aio_result(aio)); + TEST_CHECK(sa.s_in.sa_family == NNG_AF_INET); + TEST_CHECK(sa.s_in.sa_port == ntohs(80)); + TEST_CHECK(sa.s_in.sa_addr == ntohl(0x7f000001)); + nng_aio_free(aio); +} + +void +test_localhost_unspec(void) +{ + nng_aio * aio; + nng_sockaddr sa; + + TEST_NNG_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nni_resolv_ip("localhost", "80", NNG_AF_UNSPEC, true, &sa, aio); + nng_aio_wait(aio); + TEST_NNG_PASS(nng_aio_result(aio)); + TEST_CHECK( + (sa.s_family == NNG_AF_INET) || (sa.s_family == NNG_AF_INET6)); + switch (sa.s_family) { + case NNG_AF_INET: + TEST_CHECK(sa.s_in.sa_port == ntohs(80)); + TEST_CHECK(sa.s_in.sa_addr == ntohl(0x7f000001)); + break; + case NNG_AF_INET6: + TEST_CHECK(sa.s_in6.sa_port == ntohs(80)); + TEST_CHECK(memcmp(sa.s_in6.sa_addr, v6loop, 16) == 0); + break; + } + nng_aio_free(aio); +} + +void +test_null_passive(void) +{ + nng_aio * aio; + nng_sockaddr sa; + + TEST_NNG_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nni_resolv_ip(NULL, "80", NNG_AF_INET, true, &sa, aio); + nng_aio_wait(aio); + TEST_NNG_PASS(nng_aio_result(aio)); + TEST_CHECK(sa.s_in.sa_family == NNG_AF_INET); + TEST_CHECK(sa.s_in.sa_port == ntohs(80)); + TEST_CHECK(sa.s_in.sa_addr == 0); // INADDR_ANY + nng_aio_free(aio); +} + +void +test_null_not_passive(void) +{ + nng_aio * aio; + nng_sockaddr sa; + + TEST_NNG_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nni_resolv_ip(NULL, "80", NNG_AF_INET, false, &sa, aio); + nng_aio_wait(aio); + // We can either get NNG_EADDRINVAL, or a loopback address. + // Most systems do the former, but Linux does the latter. + if (nng_aio_result(aio) == 0) { + TEST_CHECK(sa.s_family == NNG_AF_INET); + TEST_CHECK(sa.s_in.sa_addr == htonl(0x7f000001)); + TEST_CHECK(sa.s_in.sa_port == htons(80)); + } else { + TEST_NNG_FAIL(nng_aio_result(aio), NNG_EADDRINVAL); + } + nng_aio_free(aio); +} + +void +test_bad_port_number(void) +{ + nng_aio * aio; + nng_sockaddr sa; + + TEST_NNG_PASS(nng_aio_alloc(&aio, NULL, NULL)); + nni_resolv_ip("1.1.1.1", "1000000", NNG_AF_INET, true, &sa, aio); + nng_aio_wait(aio); + TEST_NNG_FAIL(nng_aio_result(aio), NNG_EADDRINVAL); + nng_aio_free(aio); +} + +TEST_LIST = { + { "resolve google dns", test_google_dns }, + { "resolve numeric addr", test_numeric_addr }, + { "resolve numeric v6", test_numeric_v6 }, + { "resolve service names", test_service_names }, + { "resolve localhost v4", test_localhost_v4 }, + { "resolve localhost unspec", test_localhost_unspec }, + { "resolve null passive", test_null_passive }, + { "resolve null not passive", test_null_not_passive }, + { "resolve bad port number", test_bad_port_number }, + { NULL, NULL }, +}; |
