summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/.clang-tidy6
-rw-r--r--test/cpp/.clang-tidy8
-rw-r--r--test/cpp/test_headers_cpp.cpp31
-rw-r--r--test/cpp/test_path_std.cpp14
-rw-r--r--test/failing_allocator.c30
-rw-r--r--test/failing_allocator.h15
-rw-r--r--test/headers/test_headers.c31
-rw-r--r--test/lint/meson.build42
-rw-r--r--test/meson.build112
-rw-r--r--test/test_allocator.c6
-rw-r--r--test/test_btree.c36
-rw-r--r--test/test_digest.c7
-rw-r--r--test/test_environment.c143
-rw-r--r--test/test_filesystem.c44
-rw-r--r--test/test_hash.c43
-rw-r--r--test/test_path.c4
-rw-r--r--test/test_ring.c15
-rw-r--r--test/test_sem.c8
-rw-r--r--test/test_status.c2
-rw-r--r--test/test_string_view.c7
-rw-r--r--test/test_thread.c4
-rw-r--r--test/test_tree.c12
22 files changed, 404 insertions, 216 deletions
diff --git a/test/.clang-tidy b/test/.clang-tidy
index 2d684a6..401b1b0 100644
--- a/test/.clang-tidy
+++ b/test/.clang-tidy
@@ -1,16 +1,18 @@
-# Copyright 2020-2022 David Robillard <d@drobilla.net>
+# Copyright 2020-2024 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
Checks: >
+ -*-macro-to-enum,
-*-magic-numbers,
-android-cloexec-fopen,
-bugprone-easily-swappable-parameters,
+ -bugprone-multi-level-implicit-pointer-conversion,
-cert-err33-c,
-clang-analyzer-security.insecureAPI.DeprecatedOrUnsafeBufferHandling,
+ -concurrency-mt-unsafe,
-cppcoreguidelines-avoid-non-const-global-variables,
-google-readability-casting,
-llvm-header-guard,
- -modernize-macro-to-enum,
-performance-no-int-to-ptr,
-readability-function-cognitive-complexity,
InheritParentConfig: true
diff --git a/test/cpp/.clang-tidy b/test/cpp/.clang-tidy
index 9a3cd8c..1cbcc07 100644
--- a/test/cpp/.clang-tidy
+++ b/test/cpp/.clang-tidy
@@ -1,13 +1,19 @@
-# Copyright 2020-2022 David Robillard <d@drobilla.net>
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
Checks: >
-*-avoid-c-arrays,
-*-no-malloc,
+ -*-use-nullptr,
-android-cloexec-fopen,
+ -bugprone-exception-escape,
+ -cppcoreguidelines-macro-usage,
-cppcoreguidelines-owning-memory,
-fuchsia-default-arguments-calls,
-modernize-raw-string-literal,
+ -modernize-redundant-void-arg,
-modernize-use-trailing-return-type,
+ -modernize-use-using,
+ -performance-enum-size,
-readability-implicit-bool-conversion,
InheritParentConfig: true
diff --git a/test/cpp/test_headers_cpp.cpp b/test/cpp/test_headers_cpp.cpp
index f8038c1..fe367ad 100644
--- a/test/cpp/test_headers_cpp.cpp
+++ b/test/cpp/test_headers_cpp.cpp
@@ -5,21 +5,22 @@
# define WIN32_LEAN_AND_MEAN
#endif
-#include "zix/allocator.h" // IWYU pragma: keep
-#include "zix/attributes.h" // IWYU pragma: keep
-#include "zix/btree.h" // IWYU pragma: keep
-#include "zix/bump_allocator.h" // IWYU pragma: keep
-#include "zix/digest.h" // IWYU pragma: keep
-#include "zix/filesystem.h" // IWYU pragma: keep
-#include "zix/hash.h" // IWYU pragma: keep
-#include "zix/path.h" // IWYU pragma: keep
-#include "zix/ring.h" // IWYU pragma: keep
-#include "zix/sem.h" // IWYU pragma: keep
-#include "zix/status.h" // IWYU pragma: keep
-#include "zix/string_view.h" // IWYU pragma: keep
-#include "zix/thread.h" // IWYU pragma: keep
-#include "zix/tree.h" // IWYU pragma: keep
-#include "zix/zix.h" // IWYU pragma: keep
+#include <zix/allocator.h> // IWYU pragma: keep
+#include <zix/attributes.h> // IWYU pragma: keep
+#include <zix/btree.h> // IWYU pragma: keep
+#include <zix/bump_allocator.h> // IWYU pragma: keep
+#include <zix/digest.h> // IWYU pragma: keep
+#include <zix/environment.h> // IWYU pragma: keep
+#include <zix/filesystem.h> // IWYU pragma: keep
+#include <zix/hash.h> // IWYU pragma: keep
+#include <zix/path.h> // IWYU pragma: keep
+#include <zix/ring.h> // IWYU pragma: keep
+#include <zix/sem.h> // IWYU pragma: keep
+#include <zix/status.h> // IWYU pragma: keep
+#include <zix/string_view.h> // IWYU pragma: keep
+#include <zix/thread.h> // IWYU pragma: keep
+#include <zix/tree.h> // IWYU pragma: keep
+#include <zix/zix.h> // IWYU pragma: keep
#if defined(__GNUC__)
__attribute__((const))
diff --git a/test/cpp/test_path_std.cpp b/test/cpp/test_path_std.cpp
index cabf3da..b0850a9 100644
--- a/test/cpp/test_path_std.cpp
+++ b/test/cpp/test_path_std.cpp
@@ -10,15 +10,16 @@
#undef NDEBUG
-#include "zix/path.h"
-#include "zix/string_view.h"
+#include <zix/path.h>
+#include <zix/string_view.h>
#include <cassert>
#include <cstdlib>
#include <filesystem>
-#include <sstream>
#include <string>
+// IWYU pragma: no_include <version>
+
namespace {
struct BinaryCase {
@@ -483,8 +484,11 @@ run()
}
for (const auto& relatives : lexical_relatives) {
- const Path l = relatives.lhs ? Path{relatives.lhs} : Path{};
- const Path r = relatives.rhs ? Path{relatives.rhs} : Path{};
+ assert(relatives.lhs);
+ assert(relatives.rhs);
+
+ const Path l = Path{relatives.lhs};
+ const Path r = Path{relatives.rhs};
assert(match(
l.lexically_relative(r),
diff --git a/test/failing_allocator.c b/test/failing_allocator.c
index 684a8ec..6cffc7b 100644
--- a/test/failing_allocator.c
+++ b/test/failing_allocator.c
@@ -1,10 +1,10 @@
-// Copyright 2021 David Robillard <d@drobilla.net>
+// Copyright 2021-2024 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#include "failing_allocator.h"
-#include "zix/allocator.h"
-#include "zix/attributes.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
#include <stdbool.h>
#include <stddef.h>
@@ -23,8 +23,7 @@ attempt(ZixFailingAllocator* const allocator)
return true;
}
-ZIX_MALLOC_FUNC
-static void*
+ZIX_MALLOC_FUNC static void*
zix_failing_malloc(ZixAllocator* const allocator, const size_t size)
{
ZixFailingAllocator* const state = (ZixFailingAllocator*)allocator;
@@ -33,8 +32,7 @@ zix_failing_malloc(ZixAllocator* const allocator, const size_t size)
return attempt(state) ? base->malloc(base, size) : NULL;
}
-ZIX_MALLOC_FUNC
-static void*
+ZIX_MALLOC_FUNC static void*
zix_failing_calloc(ZixAllocator* const allocator,
const size_t nmemb,
const size_t size)
@@ -66,8 +64,7 @@ zix_failing_free(ZixAllocator* const allocator, void* const ptr)
base->free(base, ptr);
}
-ZIX_MALLOC_FUNC
-static void*
+ZIX_MALLOC_FUNC static void*
zix_failing_aligned_alloc(ZixAllocator* const allocator,
const size_t alignment,
const size_t size)
@@ -88,8 +85,7 @@ zix_failing_aligned_free(ZixAllocator* const allocator, void* const ptr)
base->aligned_free(base, ptr);
}
-ZIX_CONST_FUNC
-ZixFailingAllocator
+ZIX_CONST_FUNC ZixFailingAllocator
zix_failing_allocator(void)
{
ZixFailingAllocator failing_allocator = {
@@ -107,3 +103,15 @@ zix_failing_allocator(void)
return failing_allocator;
}
+
+size_t
+zix_failing_allocator_reset(ZixFailingAllocator* const allocator,
+ const size_t n_allowed)
+{
+ const size_t n_allocations = allocator->n_allocations;
+
+ allocator->n_allocations = 0U;
+ allocator->n_remaining = n_allowed;
+
+ return n_allocations;
+}
diff --git a/test/failing_allocator.h b/test/failing_allocator.h
index 982874d..215f2b6 100644
--- a/test/failing_allocator.h
+++ b/test/failing_allocator.h
@@ -1,10 +1,10 @@
-// Copyright 2021 David Robillard <d@drobilla.net>
+// Copyright 2021-2024 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
-#ifndef ZIX_FAILING_ALLOCATOR_H
-#define ZIX_FAILING_ALLOCATOR_H
+#ifndef ZIX_TEST_FAILING_ALLOCATOR_H
+#define ZIX_TEST_FAILING_ALLOCATOR_H
-#include "zix/allocator.h"
+#include <zix/allocator.h>
#include <stddef.h>
@@ -15,7 +15,12 @@ typedef struct {
size_t n_remaining; ///< Number of remaining successful allocations
} ZixFailingAllocator;
+/// Return an allocator configured by default to succeed
ZixFailingAllocator
zix_failing_allocator(void);
-#endif // ZIX_FAILING_ALLOCATOR_H
+/// Reset an allocator to fail after some number of "allowed" allocations
+size_t
+zix_failing_allocator_reset(ZixFailingAllocator* allocator, size_t n_allowed);
+
+#endif // ZIX_TEST_FAILING_ALLOCATOR_H
diff --git a/test/headers/test_headers.c b/test/headers/test_headers.c
index a610600..f10d05f 100644
--- a/test/headers/test_headers.c
+++ b/test/headers/test_headers.c
@@ -1,21 +1,22 @@
// Copyright 2022 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
-#include "zix/allocator.h" // IWYU pragma: keep
-#include "zix/attributes.h" // IWYU pragma: keep
-#include "zix/btree.h" // IWYU pragma: keep
-#include "zix/bump_allocator.h" // IWYU pragma: keep
-#include "zix/digest.h" // IWYU pragma: keep
-#include "zix/filesystem.h" // IWYU pragma: keep
-#include "zix/hash.h" // IWYU pragma: keep
-#include "zix/path.h" // IWYU pragma: keep
-#include "zix/ring.h" // IWYU pragma: keep
-#include "zix/sem.h" // IWYU pragma: keep
-#include "zix/status.h" // IWYU pragma: keep
-#include "zix/string_view.h" // IWYU pragma: keep
-#include "zix/thread.h" // IWYU pragma: keep
-#include "zix/tree.h" // IWYU pragma: keep
-#include "zix/zix.h" // IWYU pragma: keep
+#include <zix/allocator.h> // IWYU pragma: keep
+#include <zix/attributes.h> // IWYU pragma: keep
+#include <zix/btree.h> // IWYU pragma: keep
+#include <zix/bump_allocator.h> // IWYU pragma: keep
+#include <zix/digest.h> // IWYU pragma: keep
+#include <zix/environment.h> // IWYU pragma: keep
+#include <zix/filesystem.h> // IWYU pragma: keep
+#include <zix/hash.h> // IWYU pragma: keep
+#include <zix/path.h> // IWYU pragma: keep
+#include <zix/ring.h> // IWYU pragma: keep
+#include <zix/sem.h> // IWYU pragma: keep
+#include <zix/status.h> // IWYU pragma: keep
+#include <zix/string_view.h> // IWYU pragma: keep
+#include <zix/thread.h> // IWYU pragma: keep
+#include <zix/tree.h> // IWYU pragma: keep
+#include <zix/zix.h> // IWYU pragma: keep
#if defined(__GNUC__)
__attribute__((const))
diff --git a/test/lint/meson.build b/test/lint/meson.build
new file mode 100644
index 0000000..13966cf
--- /dev/null
+++ b/test/lint/meson.build
@@ -0,0 +1,42 @@
+# Copyright 2024 David Robillard <d@drobilla.net>
+# SPDX-License-Identifier: 0BSD OR ISC
+
+if not meson.is_subproject()
+ # Check release metadata
+ autoship = find_program('autoship', required: get_option('tests'))
+ if autoship.found()
+ test('autoship', autoship, args: ['test', zix_src_root], suite: 'data')
+ endif
+
+ # Check code with cppcheck
+ cppcheck = find_program('cppcheck', required: false)
+ if cppcheck.found()
+ compdb_path = join_paths(zix_build_root, 'compile_commands.json')
+ cppcheck_args = [
+ '--cppcheck-build-dir=' + meson.current_build_dir(),
+ '--enable=warning,style,performance,portability',
+ '--error-exitcode=1',
+ '--project=' + compdb_path,
+ '--suppress=constParameterCallback',
+ '--suppress=constParameterPointer',
+ '--suppress=normalCheckLevelMaxBranches',
+ '--suppress=unreadVariable',
+ '-q',
+ ]
+ test('cppcheck', cppcheck, args: cppcheck_args, suite: 'code')
+ endif
+endif
+
+# Check licensing metadata
+reuse = find_program('reuse', required: get_option('tests'))
+if reuse.found()
+ reuse_args = ['--root', zix_src_root, 'lint']
+ test('REUSE', reuse, args: reuse_args, suite: 'data')
+endif
+
+# Check code formatting
+clang_format = find_program('clang-format', required: false)
+if clang_format.found()
+ clang_format_args = ['--Werror', '--dry-run'] + c_headers + sources
+ test('format', clang_format, args: clang_format_args, suite: 'code')
+endif
diff --git a/test/meson.build b/test/meson.build
index 96fe455..0db182c 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -1,72 +1,34 @@
-# Copyright 2020-2024 David Robillard <d@drobilla.net>
+# Copyright 2020-2025 David Robillard <d@drobilla.net>
# SPDX-License-Identifier: 0BSD OR ISC
-if not meson.is_subproject() and get_option('lint')
- # Check release metadata
- autoship = find_program('autoship', required: get_option('tests'))
- if autoship.found()
- test(
- 'autoship',
- autoship,
- args: ['test', zix_src_root],
- suite: 'data',
- )
- endif
+########
+# Lint #
+########
- # Check licensing metadata
- reuse = find_program('reuse', required: get_option('tests'))
- if reuse.found()
- test(
- 'REUSE',
- reuse,
- args: ['--root', zix_src_root, 'lint'],
- suite: 'data',
- )
- endif
+if get_option('lint')
+ subdir('lint')
+endif
- # Check code formatting
- clang_format = find_program('clang-format', required: false)
- if clang_format.found()
- test(
- 'format',
- clang_format,
- args: ['--Werror', '--dry-run'] + c_headers + sources,
- suite: 'code',
- )
- endif
+##############
+# Unit Tests #
+##############
- # Check code with cppcheck
- if not meson.is_subproject()
- cppcheck = find_program('cppcheck', required: false)
- if cppcheck.found()
- compdb_path = join_paths(zix_build_root, 'compile_commands.json')
- test(
- 'cppcheck',
- cppcheck,
- args: [
- '--check-level=exhaustive',
- '--enable=warning,style,performance,portability',
- '--error-exitcode=1',
- '--project=' + compdb_path,
- '--suppress=constParameterCallback',
- '--suppress=constParameterPointer',
- '--suppress=unreadVariable',
- '-q',
- ],
- suite: 'code',
- )
+# Set warning suppression flags specific to tests
+test_suppressions = []
+if cc.get_id() in ['clang', 'emscripten']
+ if warning_level == 'everything'
+ test_suppressions += ['-Wno-bad-function-cast']
+
+ if host_machine.system() == 'windows'
+ if cc.get_id() in ['clang', 'emscripten']
+ test_suppressions += ['-Wno-format-nonliteral']
+ endif
endif
endif
-endif
+elif cc.get_id() == 'gcc'
+ test_suppressions += ['-Wno-bad-function-cast']
-# Set warning suppression flags specific to tests
-test_suppressions = []
-if host_machine.system() == 'windows'
- if cc.get_id() in ['clang', 'emscripten']
- test_suppressions += [
- '-Wno-format-nonliteral',
- ]
- elif cc.get_id() == 'gcc'
+ if host_machine.system() == 'windows'
test_suppressions += ['-Wno-format']
endif
endif
@@ -80,8 +42,9 @@ sequential_tests = {
'': [],
'_small': ['4'],
},
- 'filesystem': {'': files('../README.md')},
'digest': {'': []},
+ 'environment': {'': []},
+ 'filesystem': {'': files('../README.md')},
'hash': {'': []},
'path': {'': []},
'status': {'': []},
@@ -128,6 +91,7 @@ foreach test, cases : sequential_tests
sources,
c_args: c_suppressions + program_c_args + test_suppressions,
dependencies: [zix_dep],
+ implicit_include_directories: false,
include_directories: include_dirs,
link_args: program_link_args,
)
@@ -147,6 +111,7 @@ if thread_dep.found()
sources,
c_args: c_suppressions + program_c_args + test_suppressions,
dependencies: [zix_dep, thread_dep],
+ implicit_include_directories: false,
include_directories: include_dirs,
link_args: program_link_args,
)
@@ -182,15 +147,11 @@ if cc.get_id() != 'emscripten'
]
if not meson.is_cross_build()
- header_suppressions += [
- '-Wno-poison-system-directories',
- ]
+ header_suppressions += ['-Wno-poison-system-directories']
endif
if host_machine.system() == 'windows'
- header_suppressions += [
- '-Wno-nonportable-system-include-path',
- ]
+ header_suppressions += ['-Wno-nonportable-system-include-path']
endif
elif cc.get_id() == 'gcc'
@@ -216,6 +177,7 @@ if cc.get_id() != 'emscripten'
files('headers/test_headers.c'),
c_args: header_suppressions + program_c_args,
dependencies: zix_dep,
+ implicit_include_directories: false,
include_directories: include_dirs,
),
suite: 'build',
@@ -233,19 +195,16 @@ if add_languages(['cpp'], native: false, required: get_option('tests_cpp'))
'-Wno-c++98-compat-pedantic',
'-Wno-nullability-extension',
'-Wno-padded',
+ '-Wno-unsafe-buffer-usage-in-libc-call',
'-Wno-zero-as-null-pointer-constant',
]
if not meson.is_cross_build()
- cpp_test_args += [
- '-Wno-poison-system-directories',
- ]
+ cpp_test_args += ['-Wno-poison-system-directories']
endif
if host_machine.system() == 'windows'
- cpp_test_args += [
- '-Wno-nonportable-system-include-path',
- ]
+ cpp_test_args += ['-Wno-nonportable-system-include-path']
endif
elif cpp.get_id() == 'gcc'
@@ -267,11 +226,14 @@ if add_languages(['cpp'], native: false, required: get_option('tests_cpp'))
'/wd4711', # function selected for automatic inline expansion
'/wd4820', # padding added after construct
'/wd5039', # throwing function passed to C (winbase.h)
+ '/wd5045', # will insert Spectre mitigation for memory load
'/wd5262', # implicit fall-through
'/wd5264', # const variable is not used
]
endif
+ cpp_test_args = cpp.get_supported_arguments(cpp_test_args)
+
test(
'headers_cpp',
executable(
@@ -279,6 +241,7 @@ if add_languages(['cpp'], native: false, required: get_option('tests_cpp'))
files('cpp/test_headers_cpp.cpp'),
cpp_args: cpp_test_args + program_c_args,
dependencies: [zix_dep],
+ implicit_include_directories: false,
include_directories: include_dirs,
link_args: program_link_args,
),
@@ -296,6 +259,7 @@ int main(void) { return 0; }'''
files('cpp/test_path_std.cpp'),
cpp_args: cpp_test_args + program_c_args,
dependencies: [zix_dep],
+ implicit_include_directories: false,
include_directories: include_dirs,
link_args: program_link_args,
),
diff --git a/test/test_allocator.c b/test/test_allocator.c
index 9ecbfa0..e9be7ea 100644
--- a/test/test_allocator.c
+++ b/test/test_allocator.c
@@ -5,8 +5,8 @@
#include "failing_allocator.h"
-#include "zix/allocator.h"
-#include "zix/bump_allocator.h"
+#include <zix/allocator.h>
+#include <zix/bump_allocator.h>
#include <assert.h>
#include <stddef.h>
@@ -122,7 +122,7 @@ static void
test_failing_allocator(void)
{
ZixFailingAllocator allocator = zix_failing_allocator();
- allocator.n_remaining = 0;
+ zix_failing_allocator_reset(&allocator, 0);
assert(!zix_malloc(&allocator.base, 16U));
assert(!zix_calloc(&allocator.base, 16U, 1U));
diff --git a/test/test_btree.c b/test/test_btree.c
index e918799..a87e26e 100644
--- a/test/test_btree.c
+++ b/test/test_btree.c
@@ -3,16 +3,15 @@
#undef NDEBUG
-#include "zix/btree.h"
-
#include "ensure.h"
#include "failing_allocator.h"
#include "test_args.h"
#include "test_data.h"
-#include "zix/allocator.h"
-#include "zix/attributes.h"
-#include "zix/status.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
+#include <zix/btree.h>
+#include <zix/status.h>
#include <assert.h>
#include <inttypes.h>
@@ -20,8 +19,7 @@
#include <stdio.h>
#include <stdlib.h>
-ZIX_PURE_FUNC
-static int
+ZIX_PURE_FUNC static int
int_cmp(const void* a, const void* b, const void* ZIX_UNUSED(user_data))
{
const uintptr_t ia = (uintptr_t)a;
@@ -103,6 +101,23 @@ destroy(void* const ptr, const void* const user_data)
}
static void
+test_empty(void)
+{
+ ZixBTree* const t = zix_btree_new(NULL, int_cmp, NULL);
+ assert(t);
+
+ // Check that reading functions work properly with an empty (rootless) tree
+ const int e = 42;
+ ZixBTreeIter ti = zix_btree_end(t);
+ zix_btree_clear(t, NULL, NULL);
+ assert(!zix_btree_size(t));
+ assert(zix_btree_find(t, &e, &ti) == ZIX_STATUS_NOT_FOUND);
+ assert(!zix_btree_lower_bound(t, int_cmp, NULL, &e, &ti));
+
+ zix_btree_free(t, destroy, NULL);
+}
+
+static void
test_clear(void)
{
ZixBTree* t = zix_btree_new(NULL, int_cmp, NULL);
@@ -419,7 +434,7 @@ stress(ZixAllocator* const allocator,
uintptr_t removed = 0;
ENSUREV(t,
zix_btree_remove(t, (void*)r, (void**)&removed, &next),
- "Removal of non-existant %" PRIuPTR " succeeded\n",
+ "Removal of non-existent %" PRIuPTR " succeeded\n",
r);
}
@@ -563,9 +578,9 @@ test_failed_alloc(void)
assert(!stress(&allocator.base, 0, 4096));
// Test that each allocation failing is handled gracefully
- const size_t n_new_allocs = allocator.n_allocations;
+ const size_t n_new_allocs = zix_failing_allocator_reset(&allocator, 0);
for (size_t i = 0U; i < n_new_allocs; ++i) {
- allocator.n_remaining = i;
+ zix_failing_allocator_reset(&allocator, i);
assert(stress(&allocator.base, 0, 4096));
}
}
@@ -578,6 +593,7 @@ main(int argc, char** argv)
return EXIT_FAILURE;
}
+ test_empty();
test_clear();
test_free();
test_iter_comparison();
diff --git a/test/test_digest.c b/test/test_digest.c
index 7228f86..65a0e41 100644
--- a/test/test_digest.c
+++ b/test/test_digest.c
@@ -3,8 +3,8 @@
#undef NDEBUG
-#include "zix/attributes.h"
-#include "zix/digest.h"
+#include <zix/attributes.h>
+#include <zix/digest.h>
#include <assert.h>
#include <stddef.h>
@@ -116,8 +116,7 @@ test_digest_aligned(void)
}
}
-ZIX_PURE_FUNC
-int
+ZIX_PURE_FUNC int
main(void)
{
test_digest32();
diff --git a/test/test_environment.c b/test/test_environment.c
new file mode 100644
index 0000000..8756441
--- /dev/null
+++ b/test/test_environment.c
@@ -0,0 +1,143 @@
+// Copyright 2012-2024 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#undef NDEBUG
+
+#include "failing_allocator.h"
+
+#include <zix/allocator.h>
+#include <zix/environment.h>
+#include <zix/path.h>
+
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef _WIN32
+
+# define HOME_NAME "USERPROFILE"
+# define HOME_VAR "%USERPROFILE%"
+
+#else
+
+# define HOME_NAME "HOME"
+# define HOME_VAR "$HOME"
+
+static char*
+concat(ZixAllocator* const allocator,
+ const char* const prefix,
+ const char* const suffix)
+{
+ const size_t prefix_len = strlen(prefix);
+ const size_t suffix_len = strlen(suffix);
+ const size_t result_len = prefix_len + suffix_len;
+
+ char* const result = (char*)zix_calloc(allocator, 1U, result_len + 1U);
+ assert(result);
+ memcpy(result, prefix, prefix_len + 1U);
+ memcpy(result + prefix_len, suffix, suffix_len + 1U);
+ return result;
+}
+
+#endif
+
+static void
+check_expansion(const char* const path, const char* const expected)
+{
+ char* const expanded = zix_expand_environment_strings(NULL, path);
+ assert(expanded);
+ assert(!strcmp(expanded, expected));
+ zix_free(NULL, expanded);
+}
+
+static void
+test_expansion(void)
+{
+ // Check non-expansion of hopefully unset variables
+ check_expansion("$ZIX_UNSET0", "$ZIX_UNSET0");
+ check_expansion("$ZIX_unset0", "$ZIX_unset0");
+ check_expansion("%ZIX_UNSET0%", "%ZIX_UNSET0%");
+ check_expansion("%ZIX_unset0%", "%ZIX_unset0%");
+
+ // Check non-expansion of invalid variable names
+ check_expansion("$%INVALID", "$%INVALID");
+ check_expansion("$<INVALID>", "$<INVALID>");
+ check_expansion("$[INVALID]", "$[INVALID]");
+ check_expansion("$invalid", "$invalid");
+ check_expansion("${INVALID}", "${INVALID}");
+
+ const char* const home = getenv(HOME_NAME);
+ if (home) {
+ char* const var_foo = zix_path_join(NULL, HOME_VAR, "foo");
+ char* const home_foo = zix_path_join(NULL, home, "foo");
+
+ check_expansion(var_foo, home_foo);
+
+#ifndef _WIN32
+ char* const tilde_foo = zix_path_join(NULL, "~", "foo");
+ char* const home_and_other = concat(NULL, home, ":/other");
+ char* const other_and_home = concat(NULL, "/other:", home);
+ check_expansion("~other", "~other");
+ check_expansion("~", home);
+ check_expansion("~/foo", home_foo);
+ check_expansion("~:/other", home_and_other);
+ check_expansion("/other:~", other_and_home);
+ check_expansion("$HO", "$HO");
+ check_expansion("$HOMEZIX", "$HOMEZIX");
+ zix_free(NULL, other_and_home);
+ zix_free(NULL, home_and_other);
+ zix_free(NULL, tilde_foo);
+#endif
+
+ zix_free(NULL, home_foo);
+ zix_free(NULL, var_foo);
+ }
+}
+
+static void
+test_failed_alloc(void)
+{
+ ZixFailingAllocator allocator = zix_failing_allocator();
+
+ zix_failing_allocator_reset(&allocator, 0U);
+ assert(!zix_expand_environment_strings(&allocator.base, "/one:~"));
+ assert(!zix_expand_environment_strings(&allocator.base, "/only"));
+ assert(!zix_expand_environment_strings(&allocator.base, "~"));
+
+#ifndef _WIN32
+ zix_failing_allocator_reset(&allocator, 1U);
+ assert(!zix_expand_environment_strings(&allocator.base, "/one:~"));
+ assert(!zix_expand_environment_strings(&allocator.base, "/one:$HOME/two"));
+
+ zix_failing_allocator_reset(&allocator, 2U);
+ assert(!zix_expand_environment_strings(&allocator.base, "/one:$HOME/two"));
+
+ zix_failing_allocator_reset(&allocator, 1U);
+ assert(!zix_expand_environment_strings(&allocator.base, "/one:$UNSET/two"));
+#endif
+}
+
+#ifndef _WIN32
+
+// NOLINTNEXTLINE(cppcoreguidelines-avoid-non-const-global-variables)
+extern char** environ;
+
+static void
+test_null_environ(void)
+{
+ environ = NULL;
+ check_expansion(HOME_VAR, HOME_VAR);
+}
+
+#endif
+
+int
+main(void)
+{
+ test_expansion();
+ test_failed_alloc();
+#ifndef _WIN32
+ test_null_environ();
+#endif
+ return 0;
+}
diff --git a/test/test_filesystem.c b/test/test_filesystem.c
index 87a3d15..40fc9a2 100644
--- a/test/test_filesystem.c
+++ b/test/test_filesystem.c
@@ -1,13 +1,13 @@
-// Copyright 2020-2023 David Robillard <d@drobilla.net>
+// Copyright 2020-2024 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#undef NDEBUG
-#include "zix/allocator.h"
-#include "zix/filesystem.h"
-#include "zix/path.h"
-#include "zix/status.h"
-#include "zix/string_view.h"
+#include <zix/allocator.h>
+#include <zix/filesystem.h>
+#include <zix/path.h>
+#include <zix/status.h>
+#include <zix/string_view.h>
#ifndef _WIN32
# include <unistd.h>
@@ -64,6 +64,10 @@ test_canonical_path(void)
char* const temp_dir = create_temp_dir("zixXXXXXX");
assert(temp_dir);
+ char* const sub_dir = zix_path_join(NULL, temp_dir, "sub");
+ assert(!zix_create_directory(sub_dir));
+ assert(zix_file_type(temp_dir) == ZIX_FILE_TYPE_DIRECTORY);
+
char* const file_path = zix_path_join(NULL, temp_dir, "zix_test_file");
assert(file_path);
@@ -96,10 +100,10 @@ test_canonical_path(void)
// Test dot segment resolution
- char* const parent_dir_1 = zix_path_join(NULL, temp_dir, "..");
+ char* const parent_dir_1 = zix_path_join(NULL, sub_dir, "..");
assert(parent_dir_1);
- const ZixStringView parent_view = zix_path_parent_path(temp_dir);
+ const ZixStringView parent_view = zix_path_parent_path(sub_dir);
char* const parent_dir_2 = zix_string_view_copy(NULL, parent_view);
assert(parent_dir_2);
assert(parent_dir_2[0]);
@@ -120,6 +124,7 @@ test_canonical_path(void)
// Clean everything up
assert(!zix_remove(file_path));
+ assert(!zix_remove(sub_dir));
assert(!zix_remove(temp_dir));
free(real_parent_dir_2);
@@ -127,6 +132,7 @@ test_canonical_path(void)
free(parent_dir_2);
free(parent_dir_1);
free(file_path);
+ free(sub_dir);
free(temp_dir);
}
@@ -161,6 +167,7 @@ test_file_type(void)
if (sock >= 0) {
const socklen_t addr_len = sizeof(struct sockaddr_un);
struct sockaddr_un* const addr = (struct sockaddr_un*)calloc(1, addr_len);
+ assert(addr);
if (strlen(file_path) < sizeof(addr->sun_path)) {
addr->sun_family = AF_UNIX;
@@ -172,9 +179,7 @@ test_file_type(void)
assert(!zix_remove(file_path));
close(fd);
}
- } else {
- fprintf(stderr, "warning: Skipped socket test with oddly long TMPDIR\n");
- }
+ } // otherwise, TMPDIR is oddly long, skip test
close(sock);
free(addr);
@@ -245,7 +250,8 @@ write_to_path(const char* const path, const char* const contents)
const size_t len = strlen(contents);
fwrite(contents, 1, len, f);
- ret = fflush(f) ? errno : ferror(f) ? EBADF : fclose(f) ? errno : 0;
+ ret = fflush(f) ? errno : ferror(f) ? EBADF : 0;
+ ret = (fclose(f) && !ret) ? errno : ret;
}
return ret;
@@ -261,9 +267,7 @@ test_copy_file(const char* data_file_path)
assert(tmp_file_path);
assert(copy_path);
- if (!data_file_path) {
- data_file_path = tmp_file_path;
- }
+ data_file_path = data_file_path ? data_file_path : tmp_file_path;
assert(!write_to_path(tmp_file_path, "test\n"));
@@ -395,6 +399,7 @@ visit(const char* const path, const char* const name, void* const data)
if (new_names) {
char* const name_copy = (char*)calloc(name_len + 1, 1);
+ assert(name_copy);
memcpy(name_copy, name, name_len + 1);
file_list->names = new_names;
@@ -695,10 +700,11 @@ int
main(const int argc, char** const argv)
{
// Try to find some existing data file that's ideally not on a tmpfs
- const char* data_file_path = (argc > 1) ? argv[1] : "build.ninja";
- if (zix_file_type(data_file_path) != ZIX_FILE_TYPE_REGULAR) {
- data_file_path = NULL;
- }
+ const char* const default_file_path = (argc > 1) ? argv[1] : "build.ninja";
+ const char* const data_file_path =
+ (zix_file_type(default_file_path) == ZIX_FILE_TYPE_REGULAR)
+ ? default_file_path
+ : NULL;
test_temp_directory_path();
test_current_path();
diff --git a/test/test_hash.c b/test/test_hash.c
index 3d3ca95..2ff286c 100644
--- a/test/test_hash.c
+++ b/test/test_hash.c
@@ -10,11 +10,11 @@
#include "failing_allocator.h"
#include "test_data.h"
-#include "zix/allocator.h"
-#include "zix/attributes.h"
-#include "zix/digest.h"
-#include "zix/hash.h"
-#include "zix/status.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
+#include <zix/digest.h>
+#include <zix/hash.h>
+#include <zix/status.h>
#include <assert.h>
#include <inttypes.h>
@@ -47,24 +47,21 @@ test_fail(TestState* const state, const char* fmt, ...)
return EXIT_FAILURE;
}
-ZIX_PURE_FUNC
-static const char*
+ZIX_PURE_FUNC static const char*
identity(const char* record)
{
return record;
}
/// Decent hash function using zix_digest (murmur2)
-ZIX_PURE_FUNC
-static size_t
+ZIX_PURE_FUNC static size_t
decent_string_hash(const char* const str)
{
return zix_digest(0U, str, strlen(str));
}
/// Terrible hash function from K&R first edition
-ZIX_PURE_FUNC
-static size_t
+ZIX_PURE_FUNC static size_t
terrible_string_hash(const char* str)
{
size_t hash = 0U;
@@ -77,8 +74,7 @@ terrible_string_hash(const char* str)
return hash;
}
-ZIX_PURE_FUNC
-static size_t
+ZIX_PURE_FUNC static size_t
string_hash_aligned(const char* const str)
{
size_t length = strlen(str);
@@ -87,22 +83,19 @@ string_hash_aligned(const char* const str)
return zix_digest_aligned(0U, str, length);
}
-ZIX_PURE_FUNC
-static size_t
+ZIX_PURE_FUNC static size_t
string_hash32(const char* const str)
{
return (size_t)zix_digest32(0U, str, strlen(str));
}
-ZIX_PURE_FUNC
-static size_t
+ZIX_PURE_FUNC static size_t
string_hash64(const char* const str)
{
return (size_t)zix_digest64(0U, str, strlen(str));
}
-ZIX_PURE_FUNC
-static size_t
+ZIX_PURE_FUNC static size_t
string_hash32_aligned(const char* const str)
{
size_t length = strlen(str);
@@ -113,8 +106,7 @@ string_hash32_aligned(const char* const str)
#if UINTPTR_MAX >= UINT64_MAX
-ZIX_PURE_FUNC
-static size_t
+ZIX_PURE_FUNC static size_t
string_hash64_aligned(const char* const str)
{
size_t length = strlen(str);
@@ -201,8 +193,8 @@ stress_with(ZixAllocator* const allocator,
if (not_indexed) {
memcpy(not_indexed, not_indexed_string, strlen(not_indexed_string) + 1);
const char* match = (const char*)zix_hash_find_record(hash, not_indexed);
- ENSUREV(&state, !match, "Unexpectedly found `%s'\n", not_indexed);
free(not_indexed);
+ ENSUREV(&state, !match, "Unexpectedly found `%s'\n", not_indexed_string);
}
// Remove strings
@@ -298,8 +290,7 @@ stress(ZixAllocator* const allocator, const size_t n_elems)
}
/// Identity hash function for numeric strings for explicitly hitting cases
-ZIX_PURE_FUNC
-static size_t
+ZIX_PURE_FUNC static size_t
identity_index_hash(const char* const str)
{
return strtoul(str, NULL, 10);
@@ -366,9 +357,9 @@ test_failed_alloc(void)
assert(!stress(&allocator.base, 16));
// Test that each allocation failing is handled gracefully
- const size_t n_new_allocs = allocator.n_allocations;
+ const size_t n_new_allocs = zix_failing_allocator_reset(&allocator, 0);
for (size_t i = 0U; i < n_new_allocs; ++i) {
- allocator.n_remaining = i;
+ zix_failing_allocator_reset(&allocator, i);
assert(stress(&allocator.base, 16));
}
}
diff --git a/test/test_path.c b/test/test_path.c
index 5c98c32..3a8353d 100644
--- a/test/test_path.c
+++ b/test/test_path.c
@@ -3,8 +3,8 @@
#undef NDEBUG
-#include "zix/path.h"
-#include "zix/string_view.h"
+#include <zix/path.h>
+#include <zix/string_view.h>
#include <assert.h>
#include <stdbool.h>
diff --git a/test/test_ring.c b/test/test_ring.c
index b1845ce..06ac183 100644
--- a/test/test_ring.c
+++ b/test/test_ring.c
@@ -6,10 +6,10 @@
#include "failing_allocator.h"
#include "test_args.h"
-#include "zix/attributes.h"
-#include "zix/ring.h"
-#include "zix/status.h"
-#include "zix/thread.h"
+#include <zix/attributes.h>
+#include <zix/ring.h>
+#include <zix/status.h>
+#include <zix/thread.h>
#include <assert.h>
#include <limits.h>
@@ -34,8 +34,7 @@ gen_msg(int* const msg, int start)
return start;
}
-ZIX_PURE_FUNC
-static int
+ZIX_PURE_FUNC static int
cmp_msg(const int* const msg1, const int* const msg2)
{
for (unsigned i = 0U; i < MSG_SIZE; ++i) {
@@ -170,9 +169,9 @@ test_failed_alloc(void)
assert(ring);
// Test that each allocation failing is handled gracefully
- const size_t n_new_allocs = allocator.n_allocations;
+ const size_t n_new_allocs = zix_failing_allocator_reset(&allocator, 0);
for (size_t i = 0U; i < n_new_allocs; ++i) {
- allocator.n_remaining = i;
+ zix_failing_allocator_reset(&allocator, i);
assert(!zix_ring_new(&allocator.base, 512));
}
diff --git a/test/test_sem.c b/test/test_sem.c
index 0118f50..ad2ea6d 100644
--- a/test/test_sem.c
+++ b/test/test_sem.c
@@ -3,10 +3,10 @@
#undef NDEBUG
-#include "zix/attributes.h"
-#include "zix/sem.h"
-#include "zix/status.h"
-#include "zix/thread.h"
+#include <zix/attributes.h>
+#include <zix/sem.h>
+#include <zix/status.h>
+#include <zix/thread.h>
#include <assert.h>
#include <stdio.h>
diff --git a/test/test_status.c b/test/test_status.c
index 6857928..b047fe8 100644
--- a/test/test_status.c
+++ b/test/test_status.c
@@ -3,7 +3,7 @@
#undef NDEBUG
-#include "zix/status.h"
+#include <zix/status.h>
#include <assert.h>
#include <stdio.h>
diff --git a/test/test_string_view.c b/test/test_string_view.c
index 52b824d..9aeb826 100644
--- a/test/test_string_view.c
+++ b/test/test_string_view.c
@@ -5,7 +5,8 @@
#include "failing_allocator.h"
-#include "zix/string_view.h"
+#include <zix/allocator.h>
+#include <zix/string_view.h>
#include <assert.h>
#include <string.h>
@@ -94,7 +95,7 @@ test_copy(void)
ZixFailingAllocator allocator = zix_failing_allocator();
// Copying a string takes exactly one allocation
- allocator.n_remaining = 1U;
+ zix_failing_allocator_reset(&allocator, 1U);
char* const copy = zix_string_view_copy(&allocator.base, orig);
assert(copy);
@@ -102,7 +103,7 @@ test_copy(void)
zix_free(&allocator.base, copy);
// Check that allocation failure is handled gracefully
- allocator.n_remaining = 0U;
+ zix_failing_allocator_reset(&allocator, 0U);
assert(!zix_string_view_copy(&allocator.base, orig));
}
diff --git a/test/test_thread.c b/test/test_thread.c
index 09edde6..ede0f31 100644
--- a/test/test_thread.c
+++ b/test/test_thread.c
@@ -3,8 +3,8 @@
#undef NDEBUG
-#include "zix/status.h"
-#include "zix/thread.h"
+#include <zix/status.h>
+#include <zix/thread.h>
#include <assert.h>
#include <string.h>
diff --git a/test/test_tree.c b/test/test_tree.c
index fae6d85..61be9be 100644
--- a/test/test_tree.c
+++ b/test/test_tree.c
@@ -8,10 +8,10 @@
#include "test_args.h"
#include "test_data.h"
-#include "zix/allocator.h"
-#include "zix/attributes.h"
-#include "zix/status.h"
-#include "zix/tree.h"
+#include <zix/allocator.h>
+#include <zix/attributes.h>
+#include <zix/status.h>
+#include <zix/tree.h>
#include <assert.h>
#include <inttypes.h>
@@ -211,9 +211,9 @@ test_failed_alloc(void)
assert(!stress(&allocator.base, 0, 16));
// Test that each allocation failing is handled gracefully
- const size_t n_new_allocs = allocator.n_allocations;
+ const size_t n_new_allocs = zix_failing_allocator_reset(&allocator, 0);
for (size_t i = 0U; i < n_new_allocs; ++i) {
- allocator.n_remaining = i;
+ zix_failing_allocator_reset(&allocator, i);
assert(stress(&allocator.base, 0, 16));
}
}