summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--test/cpp/test_path_std.cpp7
-rw-r--r--test/ensure.h21
-rw-r--r--test/meson.build132
-rw-r--r--test/test_allocator.c21
-rw-r--r--test/test_btree.c427
-rw-r--r--test/test_data.h9
-rw-r--r--test/test_filesystem.c25
-rw-r--r--test/test_hash.c177
-rw-r--r--test/test_ring.c6
-rw-r--r--test/test_tree.c159
10 files changed, 460 insertions, 524 deletions
diff --git a/test/cpp/test_path_std.cpp b/test/cpp/test_path_std.cpp
index db38cfa..cabf3da 100644
--- a/test/cpp/test_path_std.cpp
+++ b/test/cpp/test_path_std.cpp
@@ -501,11 +501,6 @@ run()
int
main()
{
- try {
- run();
- } catch (...) {
- return 1;
- }
-
+ run();
return 0;
}
diff --git a/test/ensure.h b/test/ensure.h
new file mode 100644
index 0000000..b906a1d
--- /dev/null
+++ b/test/ensure.h
@@ -0,0 +1,21 @@
+// Copyright 2023 David Robillard <d@drobilla.net>
+// SPDX-License-Identifier: ISC
+
+#ifndef ZIX_TEST_ENSURE_H
+#define ZIX_TEST_ENSURE_H
+
+#define ENSURE(ctx, condition, fmt) \
+ do { \
+ if (!(condition)) { \
+ return test_fail(ctx, fmt); \
+ } \
+ } while (0)
+
+#define ENSUREV(ctx, condition, fmt, ...) \
+ do { \
+ if (!(condition)) { \
+ return test_fail(ctx, fmt, __VA_ARGS__); \
+ } \
+ } while (0)
+
+#endif // ZIX_TEST_ENSURE_H
diff --git a/test/meson.build b/test/meson.build
index 72d723b..bd752a3 100644
--- a/test/meson.build
+++ b/test/meson.build
@@ -38,75 +38,101 @@ endif
common_test_sources = files('failing_allocator.c')
# Single-threaded tests that should run everywhere
-sequential_tests = [
- 'allocator',
- 'btree',
- 'digest',
- 'hash',
- 'path',
- 'status',
- 'tree',
-]
+sequential_tests = {
+ 'allocator': {'': []},
+ 'btree': {
+ '': [],
+ '_small': ['4'],
+ },
+ 'filesystem': {'': files('../README.md')},
+ 'digest': {'': []},
+ 'hash': {'': []},
+ 'path': {'': []},
+ 'status': {'': []},
+ 'tree': {
+ '': [],
+ '_seed': ['8', '314159'],
+ '_small': ['4'],
+ },
+}
# Multi-threaded tests that require thread support
-threaded_tests = [
- 'ring',
- 'sem',
- 'thread',
-]
+threaded_tests = {
+ 'ring': {
+ '': [],
+ 'small': ['4', '1024'],
+ },
+ 'sem': {
+ '': [],
+ 'one': ['1'],
+ },
+ 'thread': {'': []},
+}
-foreach test : sequential_tests
+# Bad command-line argument (meta-)tests
+bad_tests = {
+ 'btree': {
+ '_extra': ['4', '1337'],
+ },
+ 'ring': {
+ '_extra': ['4', '1024', '1337'],
+ },
+ 'sem': {
+ '_extra': ['4', '1337'],
+ },
+}
+
+# Test single-threaded
+test_executables = {}
+foreach test, cases : sequential_tests
sources = common_test_sources + files('test_@0@.c'.format(test))
+ exe = executable(
+ 'test_@0@'.format(test),
+ sources,
+ c_args: c_suppressions + program_c_args + test_suppressions,
+ dependencies: [zix_dep],
+ include_directories: include_dirs,
+ link_args: program_link_args,
+ )
- test(
- test,
- executable(
+ test_executables += { test: exe }
+ foreach suffix, args : cases
+ test(test + suffix, exe, args: args, suite: 'unit', timeout: 120)
+ endforeach
+endforeach
+
+# Test multi-threaded
+if thread_dep.found()
+ foreach test, cases : threaded_tests
+ sources = common_test_sources + files('test_@0@.c'.format(test))
+ exe = executable(
'test_@0@'.format(test),
sources,
c_args: c_suppressions + program_c_args + test_suppressions,
- dependencies: [zix_dep],
+ dependencies: [zix_dep, thread_dep],
include_directories: include_dirs,
link_args: program_link_args,
- ),
- suite: 'unit',
- timeout: 120,
- )
-endforeach
-
-test(
- 'filesystem',
- executable(
- 'test_filesystem',
- files('test_filesystem.c'),
- c_args: c_suppressions + program_c_args,
- dependencies: [zix_dep],
- include_directories: include_dirs,
- link_args: program_link_args,
- ),
- args: files('../README.md'),
- suite: 'unit',
- timeout: 120,
-)
+ )
-if thread_dep.found()
- foreach test : threaded_tests
- sources = common_test_sources + files('test_@0@.c'.format(test))
+ test_executables += { test: exe }
+ foreach suffix, args : cases
+ test(test + suffix, exe, args: args, suite: 'unit', timeout: 120)
+ endforeach
+ endforeach
+endif
+# Test bad cases
+foreach test, cases : bad_tests
+ foreach suffix, args : cases
test(
- test,
- executable(
- 'test_@0@'.format(test),
- sources,
- c_args: c_suppressions + program_c_args + test_suppressions,
- dependencies: [zix_dep, thread_dep],
- include_directories: include_dirs,
- link_args: program_link_args,
- ),
+ test + suffix,
+ test_executables[test],
+ args: args,
+ should_fail: true,
suite: 'unit',
- timeout: 120,
)
endforeach
-endif
+endforeach
# Test that headers have no warnings (ignoring the usual suppressions)
if cc.get_id() != 'emscripten'
diff --git a/test/test_allocator.c b/test/test_allocator.c
index 3474533..9ecbfa0 100644
--- a/test/test_allocator.c
+++ b/test/test_allocator.c
@@ -1,12 +1,15 @@
-// Copyright 2014-2021 David Robillard <d@drobilla.net>
+// Copyright 2014-2023 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#undef NDEBUG
+#include "failing_allocator.h"
+
#include "zix/allocator.h"
#include "zix/bump_allocator.h"
#include <assert.h>
+#include <stddef.h>
#include <stdint.h>
static void
@@ -108,17 +111,33 @@ test_bump_allocator(void)
assert((uintptr_t)aligned % 128 == 0U);
assert(!zix_aligned_alloc(&allocator.base, 8, 896));
+ assert(zix_aligned_alloc(&allocator.base, 8, 8));
zix_aligned_free(&allocator.base, aligned);
zix_free(&allocator.base, reclaimed); // Correct, but a noop
zix_free(&allocator.base, malloced); // Correct, but a noop
}
+static void
+test_failing_allocator(void)
+{
+ ZixFailingAllocator allocator = zix_failing_allocator();
+ allocator.n_remaining = 0;
+
+ assert(!zix_malloc(&allocator.base, 16U));
+ assert(!zix_calloc(&allocator.base, 16U, 1U));
+ assert(!zix_realloc(&allocator.base, NULL, 32U));
+ zix_free(&allocator.base, NULL);
+ assert(!zix_aligned_alloc(&allocator.base, 8U, 16U));
+ zix_aligned_free(&allocator.base, NULL);
+}
+
int
main(void)
{
test_allocator();
test_bump_allocator();
+ test_failing_allocator();
return 0;
}
diff --git a/test/test_btree.c b/test/test_btree.c
index 7392ff8..e918799 100644
--- a/test/test_btree.c
+++ b/test/test_btree.c
@@ -1,10 +1,11 @@
-// Copyright 2011-2021 David Robillard <d@drobilla.net>
+// Copyright 2011-2023 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#undef NDEBUG
#include "zix/btree.h"
+#include "ensure.h"
#include "failing_allocator.h"
#include "test_args.h"
#include "test_data.h"
@@ -16,12 +17,9 @@
#include <assert.h>
#include <inttypes.h>
#include <stdarg.h>
-#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
-static bool expect_failure = false;
-
ZIX_PURE_FUNC
static int
int_cmp(const void* a, const void* b, const void* ZIX_UNUSED(user_data))
@@ -69,23 +67,13 @@ wildcard_cmp(const void* a, const void* b, const void* user_data)
const uintptr_t ia = (uintptr_t)a;
const uintptr_t ib = (uintptr_t)b;
- if (ia == 0) {
- if (ib >= wildcard_cut(test_num, n_elems)) {
- return 0; // Wildcard match
- }
-
- return 1; // Wildcard a > b
- }
-
- if (ib == 0) {
- if (ia >= wildcard_cut(test_num, n_elems)) {
- return 0; // Wildcard match
- }
-
- return -1; // Wildcard b > a
- }
-
- return int_cmp(a, b, user_data);
+ return (ia == 0)
+ ? ((ib >= wildcard_cut(test_num, n_elems)) ? 0 // Wildcard match
+ : 1) // Wildcard a > b
+ : (ib == 0)
+ ? ((ia >= wildcard_cut(test_num, n_elems)) ? 0 // Wildcard match
+ : -1) // Wildcard b > a
+ : int_cmp(a, b, user_data);
}
ZIX_LOG_FUNC(2, 3)
@@ -93,9 +81,6 @@ static int
test_fail(ZixBTree* t, const char* fmt, ...)
{
zix_btree_free(t, NULL, NULL);
- if (expect_failure) {
- return EXIT_SUCCESS;
- }
va_list args; // NOLINT(cppcoreguidelines-init-variables)
va_start(args, fmt);
@@ -106,24 +91,18 @@ test_fail(ZixBTree* t, const char* fmt, ...)
}
static const size_t n_clear_insertions = 1024U;
+static size_t n_destroy_calls = 0U;
static void
destroy(void* const ptr, const void* const user_data)
{
(void)user_data;
+ ++n_destroy_calls;
assert(ptr);
assert((uintptr_t)ptr <= n_clear_insertions);
}
static void
-no_destroy(void* const ptr, const void* const user_data)
-{
- (void)ptr;
- (void)user_data;
- assert(!ptr);
-}
-
-static void
test_clear(void)
{
ZixBTree* t = zix_btree_new(NULL, int_cmp, NULL);
@@ -132,10 +111,17 @@ test_clear(void)
assert(!zix_btree_insert(t, (void*)(r + 1U)));
}
+ // Clear and check that destroy is called once for each element
+ assert(n_destroy_calls == 0U);
+ zix_btree_clear(t, destroy, &n_destroy_calls);
+ assert(zix_btree_size(t) == 0U);
+ assert(n_destroy_calls == n_clear_insertions);
+
+ // Clear the now-empty tree and check that destroy isn't called again
zix_btree_clear(t, destroy, NULL);
- assert(zix_btree_size(t) == 0);
+ assert(n_destroy_calls == n_clear_insertions);
- zix_btree_free(t, no_destroy, NULL);
+ zix_btree_free(t, destroy, NULL);
}
static void
@@ -257,103 +243,91 @@ stress(ZixAllocator* const allocator,
const unsigned test_num,
const size_t n_elems)
{
- if (n_elems == 0) {
- return 0;
- }
+ assert(n_elems > 0U);
uintptr_t r = 0;
ZixBTree* t = zix_btree_new(allocator, int_cmp, NULL);
ZixStatus st = ZIX_STATUS_SUCCESS;
- if (!t) {
- return test_fail(t, "Failed to allocate tree\n");
- }
+ ENSURE(t, t, "Failed to allocate tree\n");
// Ensure begin iterator is end on empty tree
ZixBTreeIter ti = zix_btree_begin(t);
ZixBTreeIter end = zix_btree_end(t);
- if (!zix_btree_iter_is_end(ti)) {
- return test_fail(t, "Begin iterator on empty tree is not end\n");
- }
+ ENSURE(
+ t, zix_btree_iter_is_end(ti), "Begin iterator on empty tree is not end\n");
- if (!zix_btree_iter_equals(ti, end)) {
- return test_fail(t, "Begin and end of empty tree are not equal\n");
- }
+ ENSURE(t,
+ zix_btree_iter_equals(ti, end),
+ "Begin and end of empty tree are not equal\n");
// Insert n_elems elements
for (size_t i = 0; i < n_elems; ++i) {
- r = ith_elem(test_num, n_elems, i);
- if (!zix_btree_find(t, (void*)r, &ti)) {
- return test_fail(t, "%" PRIuPTR " already in tree\n", (uintptr_t)r);
- }
-
- if ((st = zix_btree_insert(t, (void*)r))) {
- return test_fail(
- t, "Insert %" PRIuPTR " failed (%s)\n", (uintptr_t)r, zix_strerror(st));
- }
+ r = ith_elem(test_num, n_elems, i);
+ st = zix_btree_insert(t, (void*)r);
+ ENSUREV(t, !st, "Insert %" PRIuPTR " failed (%s)\n", r, zix_strerror(st));
}
// Ensure tree size is correct
- if (zix_btree_size(t) != n_elems) {
- return test_fail(t,
- "Tree size %" PRIuPTR " != %" PRIuPTR "\n",
- zix_btree_size(t),
- n_elems);
- }
+ ENSUREV(t,
+ zix_btree_size(t) == n_elems,
+ "Tree size %" PRIuPTR " != %" PRIuPTR "\n",
+ zix_btree_size(t),
+ n_elems);
// Ensure begin no longer equals end
ti = zix_btree_begin(t);
end = zix_btree_end(t);
- if (zix_btree_iter_equals(ti, end)) {
- return test_fail(t, "Begin and end of non-empty tree are equal\n");
- }
+ ENSURE(t,
+ !zix_btree_iter_equals(ti, end),
+ "Begin and end of non-empty tree are equal\n");
// Search for all elements
for (size_t i = 0; i < n_elems; ++i) {
r = ith_elem(test_num, n_elems, i);
- if (zix_btree_find(t, (void*)r, &ti)) {
- return test_fail(
- t, "Find %" PRIuPTR " @ %" PRIuPTR " failed\n", (uintptr_t)r, i);
- }
+ ENSUREV(t,
+ !zix_btree_find(t, (void*)r, &ti),
+ "Find %" PRIuPTR " @ %" PRIuPTR " failed\n",
+ r,
+ i);
- if ((uintptr_t)zix_btree_get(ti) != r) {
- return test_fail(t,
- "Search data corrupt (%" PRIuPTR " != %" PRIuPTR ")\n",
- (uintptr_t)zix_btree_get(ti),
- r);
- }
+ ENSUREV(t,
+ (uintptr_t)zix_btree_get(ti) == r,
+ "Search data corrupt (%" PRIuPTR " != %" PRIuPTR ")\n",
+ (uintptr_t)zix_btree_get(ti),
+ r);
}
// Find the lower bound of all elements and ensure it's exact
for (size_t i = 0; i < n_elems; ++i) {
r = ith_elem(test_num, n_elems, i);
- if (zix_btree_lower_bound(t, int_cmp, NULL, (void*)r, &ti)) {
- return test_fail(
- t, "Lower bound %" PRIuPTR " @ %" PRIuPTR " failed\n", (uintptr_t)r, i);
- }
+ ENSUREV(t,
+ !zix_btree_lower_bound(t, int_cmp, NULL, (void*)r, &ti),
+ "Lower bound %" PRIuPTR " @ %" PRIuPTR " failed\n",
+ r,
+ i);
- if (zix_btree_iter_is_end(ti)) {
- return test_fail(t,
- "Lower bound %" PRIuPTR " @ %" PRIuPTR " hit end\n",
- (uintptr_t)r,
- i);
- }
+ ENSUREV(t,
+ !zix_btree_iter_is_end(ti),
+ "Lower bound %" PRIuPTR " @ %" PRIuPTR " hit end\n",
+ r,
+ i);
- if ((uintptr_t)zix_btree_get(ti) != r) {
- return test_fail(t,
- "Lower bound corrupt (%" PRIuPTR " != %" PRIuPTR "\n",
- (uintptr_t)zix_btree_get(ti),
- r);
- }
+ ENSUREV(t,
+ (uintptr_t)zix_btree_get(ti) == r,
+ "Lower bound corrupt (%" PRIuPTR " != %" PRIuPTR "\n",
+ (uintptr_t)zix_btree_get(ti),
+ r);
}
// Search for elements that don't exist
for (size_t i = 0; i < n_elems; ++i) {
r = ith_elem(test_num, n_elems * 3, n_elems + i);
- if (!zix_btree_find(t, (void*)r, &ti)) {
- return test_fail(t, "Unexpectedly found %" PRIuPTR "\n", (uintptr_t)r);
- }
+ ENSUREV(t,
+ zix_btree_find(t, (void*)r, &ti),
+ "Unexpectedly found %" PRIuPTR "\n",
+ r);
}
// Iterate over all elements
@@ -362,143 +336,132 @@ stress(ZixAllocator* const allocator,
for (ti = zix_btree_begin(t); !zix_btree_iter_is_end(ti);
zix_btree_iter_increment(&ti), ++i) {
const uintptr_t iter_data = (uintptr_t)zix_btree_get(ti);
- if (iter_data < last) {
- return test_fail(t,
- "Iter @ %" PRIuPTR " corrupt (%" PRIuPTR " < %" PRIuPTR
- ")\n",
- i,
- iter_data,
- last);
- }
+ ENSUREV(t,
+ iter_data >= last,
+ "Iter @ %" PRIuPTR " corrupt (%" PRIuPTR " < %" PRIuPTR ")\n",
+ i,
+ iter_data,
+ last);
+
last = iter_data;
}
- if (i != n_elems) {
- return test_fail(t,
- "Iteration stopped at %" PRIuPTR "/%" PRIuPTR
- " elements\n",
- i,
- n_elems);
- }
+ ENSUREV(t,
+ i == n_elems,
+ "Iteration stopped at %" PRIuPTR "/%" PRIuPTR " elements\n",
+ i,
+ n_elems);
// Insert n_elems elements again, ensuring duplicates fail
for (i = 0; i < n_elems; ++i) {
r = ith_elem(test_num, n_elems, i);
- if (!zix_btree_insert(t, (void*)r)) {
- return test_fail(t, "Duplicate insert succeeded\n");
- }
+ ENSURE(t, zix_btree_insert(t, (void*)r), "Duplicate insert succeeded\n");
}
// Search for the middle element then iterate from there
r = ith_elem(test_num, n_elems, n_elems / 2);
- if (zix_btree_find(t, (void*)r, &ti)) {
- return test_fail(t, "Find %" PRIuPTR " failed\n", (uintptr_t)r);
- }
+ ENSUREV(
+ t, !zix_btree_find(t, (void*)r, &ti), "Find %" PRIuPTR " failed\n", r);
last = (uintptr_t)zix_btree_get(ti);
zix_btree_iter_increment(&ti);
for (i = 1; !zix_btree_iter_is_end(ti); zix_btree_iter_increment(&ti), ++i) {
- if ((uintptr_t)zix_btree_get(ti) == last) {
- return test_fail(
- t, "Duplicate element @ %" PRIuPTR " %" PRIuPTR "\n", i, last);
- }
+ ENSUREV(t,
+ (uintptr_t)zix_btree_get(ti) != last,
+ "Duplicate element @ %" PRIuPTR " %" PRIuPTR "\n",
+ i,
+ last);
last = (uintptr_t)zix_btree_get(ti);
}
- // Delete all elements
+ // Remove all elements
ZixBTreeIter next = zix_btree_end_iter;
for (size_t e = 0; e < n_elems; e++) {
r = ith_elem(test_num, n_elems, e);
uintptr_t removed = 0;
- if (zix_btree_remove(t, (void*)r, (void**)&removed, &next)) {
- return test_fail(t, "Error removing item %" PRIuPTR "\n", (uintptr_t)r);
- }
+ ENSUREV(t,
+ !zix_btree_remove(t, (void*)r, (void**)&removed, &next),
+ "Error removing item %" PRIuPTR "\n",
+ r);
- if (removed != r) {
- return test_fail(t,
- "Removed wrong item %" PRIuPTR " != %" PRIuPTR "\n",
- removed,
- (uintptr_t)r);
- }
+ ENSUREV(t,
+ removed == r,
+ "Removed wrong item %" PRIuPTR " != %" PRIuPTR "\n",
+ removed,
+ r);
if (test_num == 0) {
const uintptr_t next_value = ith_elem(test_num, n_elems, e + 1);
- if (!((zix_btree_iter_is_end(next) && e == n_elems - 1) ||
- (uintptr_t)zix_btree_get(next) == next_value)) {
- return test_fail(t,
- "Delete all next iterator %" PRIuPTR " != %" PRIuPTR
- "\n",
- (uintptr_t)zix_btree_get(next),
- next_value);
- }
+ ENSUREV(t,
+ (zix_btree_iter_is_end(next) && e == n_elems - 1) ||
+ ((uintptr_t)zix_btree_get(next) == next_value),
+ "Remove-all next value %" PRIuPTR " != %" PRIuPTR "\n",
+ (uintptr_t)zix_btree_get(next),
+ next_value);
}
}
// Ensure the tree is empty
- if (zix_btree_size(t) != 0) {
- return test_fail(t, "Tree size %" PRIuPTR " != 0\n", zix_btree_size(t));
- }
+ ENSUREV(t,
+ zix_btree_size(t) == 0U,
+ "Tree size %" PRIuPTR " != 0\n",
+ zix_btree_size(t));
// Insert n_elems elements again (to test non-empty destruction)
for (size_t e = 0; e < n_elems; ++e) {
r = ith_elem(test_num, n_elems, e);
- if (zix_btree_insert(t, (void*)r)) {
- return test_fail(t, "Post-deletion insert failed\n");
- }
+ ENSURE(t, !zix_btree_insert(t, (void*)r), "Post-deletion insert failed\n");
}
- // Delete elements that don't exist
+ // Try to remove elements that don't exist
for (size_t e = 0; e < n_elems; e++) {
r = ith_elem(test_num, n_elems * 3, n_elems + e);
uintptr_t removed = 0;
- if (!zix_btree_remove(t, (void*)r, (void**)&removed, &next)) {
- return test_fail(
- t, "Non-existant deletion of %" PRIuPTR " succeeded\n", (uintptr_t)r);
- }
+ ENSUREV(t,
+ zix_btree_remove(t, (void*)r, (void**)&removed, &next),
+ "Removal of non-existant %" PRIuPTR " succeeded\n",
+ r);
}
// Ensure tree size is still correct
- if (zix_btree_size(t) != n_elems) {
- return test_fail(t,
- "Tree size %" PRIuPTR " != %" PRIuPTR "\n",
- zix_btree_size(t),
- n_elems);
- }
+ ENSUREV(t,
+ zix_btree_size(t) == n_elems,
+ "Tree size %" PRIuPTR " != %" PRIuPTR "\n",
+ zix_btree_size(t),
+ n_elems);
// Delete some elements towards the end
for (size_t e = 0; e < n_elems / 4; e++) {
r = ith_elem(test_num, n_elems, n_elems - (n_elems / 4) + e);
uintptr_t removed = 0;
- if (zix_btree_remove(t, (void*)r, (void**)&removed, &next)) {
- return test_fail(t, "Deletion of %" PRIuPTR " failed\n", (uintptr_t)r);
- }
+ ENSUREV(t,
+ !zix_btree_remove(t, (void*)r, (void**)&removed, &next),
+ "Deletion of %" PRIuPTR " failed\n",
+ r);
- if (removed != r) {
- return test_fail(t,
- "Removed wrong item %" PRIuPTR " != %" PRIuPTR "\n",
- removed,
- (uintptr_t)r);
- }
+ ENSUREV(t,
+ removed == r,
+ "Removed wrong item %" PRIuPTR " != %" PRIuPTR "\n",
+ removed,
+ r);
if (test_num == 0) {
const uintptr_t next_value = ith_elem(test_num, n_elems, e + 1);
- if (!zix_btree_iter_is_end(next) &&
- (uintptr_t)zix_btree_get(next) == next_value) {
- return test_fail(t,
- "Next iterator %" PRIuPTR " != %" PRIuPTR "\n",
- (uintptr_t)zix_btree_get(next),
- next_value);
- }
+ ENSUREV(t,
+ zix_btree_iter_is_end(next) ||
+ (uintptr_t)zix_btree_get(next) != next_value,
+ "Next iterator %" PRIuPTR " == %" PRIuPTR "\n",
+ (uintptr_t)zix_btree_get(next),
+ next_value);
}
}
// Check tree size
- if (zix_btree_size(t) != n_elems - (n_elems / 4)) {
- return test_fail(t,
- "Tree size %" PRIuPTR " != %" PRIuPTR "\n",
- zix_btree_size(t),
- n_elems);
- }
+ ENSUREV(t,
+ zix_btree_size(t) == n_elems - (n_elems / 4),
+ "Tree size %" PRIuPTR " != %" PRIuPTR "\n",
+ zix_btree_size(t),
+ n_elems);
// Delete some elements in a random order
for (size_t e = 0; e < zix_btree_size(t) / 2; e++) {
@@ -506,9 +469,10 @@ stress(ZixAllocator* const allocator,
uintptr_t removed = 0;
ZixStatus rst = zix_btree_remove(t, (void*)r, (void**)&removed, &next);
- if (rst != ZIX_STATUS_SUCCESS && rst != ZIX_STATUS_NOT_FOUND) {
- return test_fail(t, "Error deleting %" PRIuPTR "\n", (uintptr_t)r);
- }
+ ENSUREV(t,
+ rst == ZIX_STATUS_SUCCESS || rst == ZIX_STATUS_NOT_FOUND,
+ "Error deleting %" PRIuPTR "\n",
+ r);
}
// Delete all remaining elements via next iterator
@@ -517,25 +481,22 @@ stress(ZixAllocator* const allocator,
while (!zix_btree_iter_is_end(next)) {
const uintptr_t value = (uintptr_t)zix_btree_get(next);
uintptr_t removed = 0;
- if (zix_btree_remove(t, zix_btree_get(next), (void**)&removed, &next)) {
- return test_fail(
- t, "Error removing next item %" PRIuPTR "\n", (uintptr_t)r);
- }
-
- if (removed != value) {
- return test_fail(t,
- "Removed wrong next item %" PRIuPTR " != %" PRIuPTR "\n",
- removed,
- (uintptr_t)value);
- }
-
- if (removed < last_value) {
- return test_fail(t,
- "Removed unordered next item %" PRIuPTR " < %" PRIuPTR
- "\n",
- removed,
- (uintptr_t)value);
- }
+ ENSUREV(t,
+ !zix_btree_remove(t, zix_btree_get(next), (void**)&removed, &next),
+ "Error removing next item %" PRIuPTR "\n",
+ r);
+
+ ENSUREV(t,
+ removed == value,
+ "Removed wrong next item %" PRIuPTR " != %" PRIuPTR "\n",
+ removed,
+ (uintptr_t)value);
+
+ ENSUREV(t,
+ removed >= last_value,
+ "Removed unordered next item %" PRIuPTR " < %" PRIuPTR "\n",
+ removed,
+ (uintptr_t)value);
last_value = removed;
}
@@ -546,51 +507,47 @@ stress(ZixAllocator* const allocator,
// Test lower_bound with wildcard comparator
TestContext ctx = {test_num, n_elems};
- if (!(t = zix_btree_new(NULL, wildcard_cmp, &ctx))) {
- return test_fail(t, "Failed to allocate tree\n");
- }
+ t = zix_btree_new(NULL, wildcard_cmp, &ctx);
+ ENSURE(t, t, "Failed to allocate tree\n");
// Insert n_elems elements
for (i = 0; i < n_elems; ++i) {
- r = ith_elem(test_num, n_elems, i);
- if ((st = zix_btree_insert(t, (void*)r))) {
- return test_fail(
- t, "Insert %" PRIuPTR " failed (%s)\n", (uintptr_t)r, zix_strerror(st));
- }
+ r = ith_elem(test_num, n_elems, i);
+ st = zix_btree_insert(t, (void*)r);
+ ENSUREV(t, !st, "Insert %" PRIuPTR " failed (%s)\n", r, zix_strerror(st));
}
// Find lower bound of wildcard
const uintptr_t wildcard = 0;
- if (zix_btree_lower_bound(t, wildcard_cmp, &ctx, (void*)wildcard, &ti)) {
- return test_fail(t, "Lower bound failed\n");
- }
+ ENSURE(t,
+ !zix_btree_lower_bound(t, wildcard_cmp, &ctx, (void*)wildcard, &ti),
+ "Wildcard lower bound failed\n");
- if (zix_btree_iter_is_end(ti)) {
- return test_fail(t, "Lower bound reached end\n");
- }
+ ENSURE(t, !zix_btree_iter_is_end(ti), "Lower bound reached end\n");
// Check value
const uintptr_t iter_data = (uintptr_t)zix_btree_get(ti);
const uintptr_t cut = wildcard_cut(test_num, n_elems);
- if (iter_data != cut) {
- return test_fail(
- t, "Lower bound %" PRIuPTR " != %" PRIuPTR "\n", iter_data, cut);
- }
-
- if (wildcard_cmp((void*)wildcard, (void*)iter_data, &ctx)) {
- return test_fail(
- t, "Wildcard lower bound %" PRIuPTR " != %" PRIuPTR "\n", iter_data, cut);
- }
+ ENSUREV(t,
+ iter_data == cut,
+ "Lower bound %" PRIuPTR " != %" PRIuPTR "\n",
+ iter_data,
+ cut);
+
+ ENSUREV(t,
+ !wildcard_cmp((void*)wildcard, (void*)iter_data, &ctx),
+ "Wildcard lower bound %" PRIuPTR " != %" PRIuPTR "\n",
+ iter_data,
+ cut);
// Find lower bound of value past end
const uintptr_t max = (uintptr_t)-1;
- if (zix_btree_lower_bound(t, wildcard_cmp, &ctx, (void*)max, &ti)) {
- return test_fail(t, "Lower bound failed\n");
- }
+ ENSURE(t,
+ !zix_btree_lower_bound(t, wildcard_cmp, &ctx, (void*)max, &ti),
+ "End lower bound failed\n");
- if (!zix_btree_iter_is_end(ti)) {
- return test_fail(t, "Lower bound of maximum value is not end\n");
- }
+ ENSURE(
+ t, zix_btree_iter_is_end(ti), "Lower bound of maximum value is not end\n");
zix_btree_free(t, NULL, NULL);
@@ -628,19 +585,19 @@ main(int argc, char** argv)
test_remove_cases();
test_failed_alloc();
- const unsigned n_tests = 2U;
- const size_t n_elems =
- (argc > 1) ? zix_test_size_arg(argv[1], 4U, 1U << 20U) : (1U << 16U);
+ const unsigned n_tests = 3U;
+ const char* size_arg = (argc > 1) ? argv[1] : "65536";
+ const size_t n_elems = zix_test_size_arg(size_arg, 4U, 1U << 20U);
printf("Running %u tests with %zu elements", n_tests, n_elems);
- for (unsigned i = 0; i < n_tests; ++i) {
+
+ int st = 0;
+ for (unsigned i = 0; !st && i < n_tests; ++i) {
printf(".");
fflush(stdout);
- if (stress(NULL, i, n_elems)) {
- return EXIT_FAILURE;
- }
+ st = stress(NULL, i, n_elems);
}
- printf("\n");
- return EXIT_SUCCESS;
+ printf("\n");
+ return st;
}
diff --git a/test/test_data.h b/test/test_data.h
index 603a6c2..bc61cfd 100644
--- a/test/test_data.h
+++ b/test/test_data.h
@@ -1,4 +1,4 @@
-// Copyright 2011-2021 David Robillard <d@drobilla.net>
+// Copyright 2011-2023 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#ifndef ZIX_TEST_DATA_H
@@ -46,12 +46,11 @@ unique_rand(size_t i)
// Largest prime < 2^32 which satisfies (2^32 = 3 mod 4)
static const size_t prime = 4294967291U;
- if (i >= prime) {
- return i; // Values >= prime are mapped to themselves
- }
const size_t residue = (size_t)(((uint64_t)i * i) % prime);
- return (i <= prime / 2) ? residue : prime - residue;
+ return (i >= prime) ? i // Values >= prime are mapped to themselves
+ : (i <= prime / 2) ? residue
+ : prime - residue;
}
#endif // ZIX_TEST_DATA_H
diff --git a/test/test_filesystem.c b/test/test_filesystem.c
index 5006676..cc68249 100644
--- a/test/test_filesystem.c
+++ b/test/test_filesystem.c
@@ -1,4 +1,4 @@
-// Copyright 2020-2022 David Robillard <d@drobilla.net>
+// Copyright 2020-2023 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#undef NDEBUG
@@ -235,17 +235,16 @@ test_is_directory(void)
static int
write_to_path(const char* const path, const char* const contents)
{
- FILE* const f = fopen(path, "w");
- if (!f) {
- return -1;
- }
-
- const size_t len = strlen(contents);
- fwrite(contents, 1, len, f);
+ int ret = -1;
+ FILE* const f = fopen(path, "w");
+ if (f) {
+ const size_t len = strlen(contents);
+ fwrite(contents, 1, len, f);
- const int ret = fflush(f) ? errno : ferror(f) ? EBADF : 0;
+ ret = fflush(f) ? errno : ferror(f) ? EBADF : fclose(f) ? errno : 0;
+ }
- return fclose(f) ? errno : ret;
+ return ret;
}
static void
@@ -600,13 +599,12 @@ test_create_symlink(void)
// Check that the symlink seems equivalent to the original file
assert(!st || st == ZIX_STATUS_NOT_SUPPORTED || st == ZIX_STATUS_BAD_PERMS);
+ assert(!st || zix_symlink_type(link_path) == ZIX_FILE_TYPE_NONE);
if (!st) {
assert(zix_symlink_type(link_path) == ZIX_FILE_TYPE_SYMLINK);
assert(zix_file_type(link_path) == ZIX_FILE_TYPE_REGULAR);
assert(zix_file_equals(NULL, file_path, link_path));
assert(!zix_remove(link_path));
- } else {
- assert(zix_symlink_type(link_path) == ZIX_FILE_TYPE_NONE);
}
assert(!zix_remove(file_path));
@@ -670,12 +668,11 @@ test_create_hard_link(void)
// Check that the link is equivalent to the original file
assert(!st || st == ZIX_STATUS_NOT_SUPPORTED || st == ZIX_STATUS_MAX_LINKS);
+ assert(!st || zix_symlink_type(link_path) == ZIX_FILE_TYPE_NONE);
if (!st) {
assert(zix_file_type(link_path) == ZIX_FILE_TYPE_REGULAR);
assert(zix_file_equals(NULL, file_path, link_path));
assert(!zix_remove(link_path));
- } else {
- assert(zix_symlink_type(link_path) == ZIX_FILE_TYPE_NONE);
}
assert(!zix_remove(file_path));
diff --git a/test/test_hash.c b/test/test_hash.c
index c3aaaba..b1de72a 100644
--- a/test/test_hash.c
+++ b/test/test_hash.c
@@ -1,4 +1,4 @@
-// Copyright 2011-2021 David Robillard <d@drobilla.net>
+// Copyright 2011-2023 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#undef NDEBUG
@@ -6,6 +6,7 @@
#define ZIX_HASH_KEY_TYPE const char
#define ZIX_HASH_RECORD_TYPE const char
+#include "ensure.h"
#include "failing_allocator.h"
#include "test_data.h"
@@ -24,29 +25,26 @@
#include <stdlib.h>
#include <string.h>
-static bool expect_failure = false;
+typedef struct {
+ ZixHash* hash;
+ char* buffer;
+ char** strings;
+} TestState;
-ZIX_LOG_FUNC(4, 5)
+ZIX_LOG_FUNC(2, 3)
static int
-test_fail(ZixHash* const hash,
- char* const buffer,
- char** const strings,
- const char* fmt,
- ...)
+test_fail(TestState* const state, const char* fmt, ...)
{
- if (!expect_failure) {
- va_list args; // NOLINT(cppcoreguidelines-init-variables)
- va_start(args, fmt);
- fprintf(stderr, "error: ");
- vfprintf(stderr, fmt, args);
- va_end(args);
- }
-
- zix_hash_free(hash);
- free(buffer);
- free(strings);
-
- return expect_failure ? 0 : 1;
+ va_list args; // NOLINT(cppcoreguidelines-init-variables)
+ va_start(args, fmt);
+ fprintf(stderr, "error: ");
+ vfprintf(stderr, fmt, args);
+ va_end(args);
+
+ zix_hash_free(state->hash);
+ free(state->buffer);
+ free(state->strings);
+ return EXIT_FAILURE;
}
ZIX_PURE_FUNC static const char*
@@ -130,18 +128,17 @@ stress_with(ZixAllocator* const allocator,
const ZixHashFunc hash_func,
const size_t n_elems)
{
- ZixHash* hash = zix_hash_new(allocator, identity, hash_func, string_equal);
- if (!hash) {
- return test_fail(hash, NULL, NULL, "Failed to allocate hash\n");
- }
+ ZixHash* hash = zix_hash_new(allocator, identity, hash_func, string_equal);
+ TestState state = {hash, NULL, NULL};
+ ENSURE(&state, hash, "Failed to allocate hash\n");
static const size_t string_length = 15;
char* const buffer = (char*)calloc(1, n_elems * (string_length + 1));
- char** const strings = (char**)calloc(sizeof(char*), n_elems);
- if (!buffer || !strings) {
- return test_fail(hash, buffer, strings, "Failed to allocate strings\n");
- }
+ char** const strings = state.strings = (char**)calloc(sizeof(char*), n_elems);
+ state.buffer = buffer;
+ state.strings = strings;
+ ENSURE(&state, buffer && state.strings, "Failed to allocate strings\n");
uint32_t seed = 1U;
for (size_t i = 0U; i < n_elems; ++i) {
@@ -158,46 +155,35 @@ stress_with(ZixAllocator* const allocator,
// Insert each string
for (size_t i = 0; i < n_elems; ++i) {
ZixStatus st = zix_hash_insert(hash, strings[i]);
- if (st) {
- return test_fail(
- hash, buffer, strings, "Failed to insert `%s'\n", strings[i]);
- }
+ ENSUREV(&state, !st, "Failed to insert `%s'\n", strings[i]);
}
// Ensure hash size is correct
- if (zix_hash_size(hash) != n_elems) {
- return test_fail(hash,
- buffer,
- strings,
- "Hash size %" PRIuPTR " != %" PRIuPTR "\n",
- zix_hash_size(hash),
- n_elems);
- }
+ ENSUREV(&state,
+ zix_hash_size(hash) == n_elems,
+ "Hash size %" PRIuPTR " != %" PRIuPTR "\n",
+ zix_hash_size(hash),
+ n_elems);
// Attempt to insert each string again
for (size_t i = 0; i < n_elems; ++i) {
ZixStatus st = zix_hash_insert(hash, strings[i]);
- if (st != ZIX_STATUS_EXISTS) {
- return test_fail(hash,
- buffer,
- strings,
- "Double inserted `%s' (%s)\n",
- strings[i],
- zix_strerror(st));
- }
+ ENSUREV(&state,
+ st == ZIX_STATUS_EXISTS,
+ "Double inserted `%s' (%s)\n",
+ strings[i],
+ zix_strerror(st));
}
// Search for each string
for (size_t i = 0; i < n_elems; ++i) {
const char* match = (const char*)zix_hash_find_record(hash, strings[i]);
- if (!match) {
- return test_fail(
- hash, buffer, strings, "Failed to find `%s'\n", strings[i]);
- }
- if (match != strings[i]) {
- return test_fail(
- hash, buffer, strings, "Bad match for `%s': `%s'\n", strings[i], match);
- }
+ ENSUREV(&state, match, "Failed to find `%s'\n", strings[i]);
+ ENSUREV(&state,
+ match == strings[i],
+ "Bad match for `%s': `%s'\n",
+ strings[i],
+ match);
}
static const char* const not_indexed_string = "__not__indexed__";
@@ -207,10 +193,7 @@ 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);
- if (match) {
- return test_fail(
- hash, buffer, strings, "Unexpectedly found `%s'\n", not_indexed);
- }
+ ENSUREV(&state, !match, "Unexpectedly found `%s'\n", not_indexed);
free(not_indexed);
}
@@ -221,33 +204,26 @@ stress_with(ZixAllocator* const allocator,
// Remove string
const char* removed = NULL;
ZixStatus st = zix_hash_remove(hash, strings[i], &removed);
- if (st) {
- return test_fail(
- hash, buffer, strings, "Failed to remove `%s'\n", strings[i]);
- }
+ ENSUREV(&state, !st, "Failed to remove `%s'\n", strings[i]);
// Ensure the removed value is what we expected
- if (removed != strings[i]) {
- return test_fail(hash,
- buffer,
- strings,
- "Removed `%s` instead of `%s`\n",
- removed,
- strings[i]);
- }
+ ENSUREV(&state,
+ removed == strings[i],
+ "Removed `%s` instead of `%s`\n",
+ removed,
+ strings[i]);
// Ensure size is updated
- if (zix_hash_size(hash) != initial_size - 1) {
- return test_fail(
- hash, buffer, strings, "Removing node did not decrease hash size\n");
- }
+ ENSURE(&state,
+ zix_hash_size(hash) == initial_size - 1,
+ "Removing node did not decrease hash size\n");
// Ensure second removal fails
st = zix_hash_remove(hash, strings[i], &removed);
- if (st != ZIX_STATUS_NOT_FOUND) {
- return test_fail(
- hash, buffer, strings, "Unexpectedly removed `%s' twice\n", strings[i]);
- }
+ ENSUREV(&state,
+ st == ZIX_STATUS_NOT_FOUND,
+ "Unexpectedly removed `%s' twice\n",
+ strings[i]);
// Ensure value can no longer be found
assert(zix_hash_find(hash, strings[i]) == zix_hash_end(hash));
@@ -255,20 +231,11 @@ stress_with(ZixAllocator* const allocator,
// Check to ensure remaining strings are still present
for (size_t j = i + 1; j < n_elems; ++j) {
const char* match = (const char*)zix_hash_find_record(hash, strings[j]);
- if (!match) {
- return test_fail(hash,
- buffer,
- strings,
- "Failed to find `%s' after remove\n",
- strings[j]);
- }
- if (match != strings[j]) {
- return test_fail(hash,
- buffer,
- strings,
- "Bad match for `%s' after remove\n",
- strings[j]);
- }
+ ENSUREV(&state, match, "Failed to find `%s' after remove\n", strings[j]);
+ ENSUREV(&state,
+ match == strings[j],
+ "Bad match for `%s' after remove\n",
+ strings[j]);
}
}
@@ -278,10 +245,7 @@ stress_with(ZixAllocator* const allocator,
assert(!zix_hash_record_at(hash, plan));
ZixStatus st = zix_hash_insert_at(hash, plan, strings[i]);
- if (st) {
- return test_fail(
- hash, buffer, strings, "Failed to insert `%s'\n", strings[i]);
- }
+ ENSUREV(&state, !st, "Failed to insert `%s'\n", strings[i]);
}
// Check key == value (and test zix_hash_foreach)
@@ -290,15 +254,12 @@ stress_with(ZixAllocator* const allocator,
i = zix_hash_next(hash, i)) {
const char* const string = (const char*)zix_hash_get(hash, i);
assert(string);
- if (strlen(string) < 3) {
- return test_fail(hash, buffer, strings, "Corrupt value `%s'\n", string);
- }
+ ENSUREV(&state, strlen(string) >= 3, "Corrupt value `%s'\n", string);
++n_checked;
}
- if (n_checked != n_elems) {
- return test_fail(hash, buffer, strings, "Check failed\n");
- }
+
+ ENSURE(&state, n_checked == n_elems, "Check failed\n");
free(strings);
free(buffer);
@@ -413,9 +374,5 @@ main(void)
static const size_t n_elems = 1024U;
- if (stress(NULL, n_elems)) {
- return 1;
- }
-
- return 0;
+ return stress(NULL, n_elems);
}
diff --git a/test/test_ring.c b/test/test_ring.c
index fc45ac6..46abe05 100644
--- a/test/test_ring.c
+++ b/test/test_ring.c
@@ -1,4 +1,4 @@
-// Copyright 2011-2021 David Robillard <d@drobilla.net>
+// Copyright 2011-2023 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#undef NDEBUG
@@ -182,8 +182,8 @@ test_failed_alloc(void)
int
main(int argc, char** argv)
{
- if (argc > 1 && argv[1][0] == '-') {
- printf("Usage: %s SIZE N_WRITES\n", argv[0]);
+ if (argc > 3) {
+ printf("Usage: %s SIZE [N_WRITES]\n", argv[0]);
return 1;
}
diff --git a/test/test_tree.c b/test/test_tree.c
index b51bb29..5f093d3 100644
--- a/test/test_tree.c
+++ b/test/test_tree.c
@@ -1,8 +1,9 @@
-// Copyright 2011-2020 David Robillard <d@drobilla.net>
+// Copyright 2011-2023 David Robillard <d@drobilla.net>
// SPDX-License-Identifier: ISC
#undef NDEBUG
+#include "ensure.h"
#include "failing_allocator.h"
#include "test_args.h"
#include "test_data.h"
@@ -45,17 +46,18 @@ ith_elem(unsigned test_num, size_t n_elems, size_t i)
}
}
-ZIX_LOG_FUNC(1, 2)
+ZIX_LOG_FUNC(2, 3)
static int
-test_fail(const char* const fmt, ...)
+test_fail(ZixTree* t, const char* fmt, ...)
{
+ zix_tree_free(t);
+
va_list args; // NOLINT(cppcoreguidelines-init-variables)
va_start(args, fmt);
-
fprintf(stderr, "error: ");
vfprintf(stderr, fmt, args);
-
va_end(args);
+
return EXIT_FAILURE;
}
@@ -79,25 +81,17 @@ test_duplicate_insert(void)
}
static int
-check_value(const uintptr_t actual, const uintptr_t expected)
+check_tree_size(const size_t actual, const size_t expected)
{
return (expected == actual)
? 0
- : test_fail("Data corrupt (%" PRIuPTR " != %" PRIuPTR ")\n",
+ : test_fail(NULL, // FIXME
+ "Tree size %" PRIuPTR " != %" PRIuPTR "\n",
actual,
expected);
}
static int
-check_tree_size(const size_t actual, const size_t expected)
-{
- return (expected == actual)
- ? 0
- : test_fail(
- "Tree size %" PRIuPTR " != %" PRIuPTR "\n", actual, expected);
-}
-
-static int
insert_elements(ZixTree* const t, const unsigned test_num, const size_t n_elems)
{
ZixTreeIter* ti = NULL;
@@ -105,14 +99,12 @@ insert_elements(ZixTree* const t, const unsigned test_num, const size_t n_elems)
for (size_t i = 0; i < n_elems; ++i) {
const uintptr_t r = ith_elem(test_num, n_elems, i);
- ZixStatus status = zix_tree_insert(t, (void*)r, &ti);
- if (status) {
- return test_fail("Insert failed\n");
- }
+ const ZixStatus st = zix_tree_insert(t, (void*)r, &ti);
+ ENSURE(NULL, !st, "Insert failed\n");
- if (check_value((uintptr_t)zix_tree_get(ti), r)) {
- return EXIT_FAILURE;
- }
+ const uintptr_t value = (uintptr_t)zix_tree_get(ti);
+ ENSUREV(
+ NULL, value == r, "Insert %" PRIuPTR " != %" PRIuPTR "\n", value, r);
}
return 0;
@@ -125,32 +117,31 @@ stress(ZixAllocator* allocator, unsigned test_num, size_t n_elems)
ZixTreeIter* ti = NULL;
ZixTree* t = zix_tree_new(allocator, true, int_cmp, NULL, NULL, NULL);
- assert(t);
- assert(!zix_tree_begin(t));
- assert(!zix_tree_end(t));
- assert(!zix_tree_rbegin(t));
- assert(!zix_tree_rend(t));
+ ENSURE(t, t, "Failed to allocate tree\n");
+ ENSURE(t, !zix_tree_begin(t), "Empty tree has begin iterator\n");
+ ENSURE(t, !zix_tree_end(t), "Empty tree has end iterator\n");
+ ENSURE(t, !zix_tree_rbegin(t), "Empty tree has reverse begin iterator\n");
+ ENSURE(t, !zix_tree_rend(t), "Empty tree has reverse end iterator\n");
// Insert n_elems elements
- if (insert_elements(t, test_num, n_elems)) {
- return EXIT_FAILURE;
- }
+ ENSURE(t,
+ !insert_elements(t, test_num, n_elems),
+ "Failed to insert initial elements\n");
// Ensure tree size is correct
- if (check_tree_size(zix_tree_size(t), n_elems)) {
- return EXIT_FAILURE;
- }
+ ENSUREV(t,
+ zix_tree_size(t) == n_elems,
+ "Tree size %" PRIuPTR " != %" PRIuPTR "\n",
+ zix_tree_size(t),
+ n_elems);
// Search for all elements
for (size_t i = 0; i < n_elems; ++i) {
r = ith_elem(test_num, n_elems, i);
- if (zix_tree_find(t, (void*)r, &ti)) {
- return test_fail("Find failed\n");
- }
+ ENSURE(t, !zix_tree_find(t, (void*)r, &ti), "Find failed\n");
- if (check_value((uintptr_t)zix_tree_get(ti), r)) {
- return EXIT_FAILURE;
- }
+ const uintptr_t value = (uintptr_t)zix_tree_get(ti);
+ ENSUREV(t, value == r, "Value %" PRIuPTR " != %" PRIuPTR "\n", value, r);
}
// Iterate over all elements
@@ -159,16 +150,18 @@ stress(ZixAllocator* allocator, unsigned test_num, size_t n_elems)
for (ZixTreeIter* iter = zix_tree_begin(t); !zix_tree_iter_is_end(iter);
iter = zix_tree_iter_next(iter), ++i) {
const uintptr_t iter_data = (uintptr_t)zix_tree_get(iter);
- if (iter_data < last) {
- return test_fail(
- "Iter corrupt (%" PRIuPTR " < %" PRIuPTR ")\n", iter_data, last);
- }
+ ENSUREV(t,
+ iter_data >= last,
+ "Iter corrupt (%" PRIuPTR " < %" PRIuPTR ")\n",
+ iter_data,
+ last);
last = iter_data;
}
- if (i != n_elems) {
- return test_fail(
- "Iteration stopped at %" PRIuPTR "/%" PRIuPTR " elements\n", i, n_elems);
- }
+ ENSUREV(t,
+ i == n_elems,
+ "Iteration stopped at %" PRIuPTR "/%" PRIuPTR " elements\n",
+ i,
+ n_elems);
// Iterate over all elements backwards
i = 0;
@@ -176,10 +169,11 @@ stress(ZixAllocator* allocator, unsigned test_num, size_t n_elems)
for (ZixTreeIter* iter = zix_tree_rbegin(t); !zix_tree_iter_is_rend(iter);
iter = zix_tree_iter_prev(iter), ++i) {
const uintptr_t iter_data = (uintptr_t)zix_tree_get(iter);
- if (iter_data > last) {
- return test_fail(
- "Iter corrupt (%" PRIuPTR " < %" PRIuPTR ")\n", iter_data, last);
- }
+ ENSUREV(t,
+ iter_data <= last,
+ "Iter corrupt (%" PRIuPTR " < %" PRIuPTR ")\n",
+ iter_data,
+ last);
last = iter_data;
}
@@ -188,23 +182,17 @@ stress(ZixAllocator* allocator, unsigned test_num, size_t n_elems)
r = ith_elem(test_num, n_elems, e);
ZixTreeIter* item = NULL;
- if (zix_tree_find(t, (void*)r, &item) != ZIX_STATUS_SUCCESS) {
- return test_fail("Failed to find item to remove\n");
- }
- if (zix_tree_remove(t, item)) {
- return test_fail("Error removing item\n");
- }
+ ENSURE(t,
+ zix_tree_find(t, (void*)r, &item) == ZIX_STATUS_SUCCESS,
+ "Failed to find item to remove\n");
+ ENSURE(t, !zix_tree_remove(t, item), "Error removing item\n");
}
// Ensure the tree is empty
- if (check_tree_size(zix_tree_size(t), 0)) {
- return EXIT_FAILURE;
- }
+ ENSURE(t, zix_tree_size(t) == 0U, "Tree isn't empty\n");
// Insert n_elems elements again (to test non-empty destruction)
- if (insert_elements(t, test_num, n_elems)) {
- return EXIT_FAILURE;
- }
+ ENSURE(t, !insert_elements(t, test_num, n_elems), "Reinsertion failed\n");
// Ensure tree size is correct
const int ret = check_tree_size(zix_tree_size(t), n_elems);
@@ -217,34 +205,17 @@ stress(ZixAllocator* allocator, unsigned test_num, size_t n_elems)
static void
test_failed_alloc(void)
{
- static const size_t n_insertions = 4096;
-
ZixFailingAllocator allocator = zix_failing_allocator();
- // Successfully test insertions to count the number of allocations
- ZixTree* t = zix_tree_new(&allocator.base, false, int_cmp, NULL, NULL, NULL);
- for (size_t i = 0U; i < n_insertions; ++i) {
- assert(!zix_tree_insert(t, (void*)i, NULL));
- }
-
- // Test that tree allocation failure is handled gracefully
- allocator.n_remaining = 0;
- zix_tree_free(t);
- assert(!zix_tree_new(&allocator.base, false, int_cmp, NULL, NULL, NULL));
-
- // Allocate a new tree to try the same test again, but with allocation failure
- allocator.n_remaining = 1;
- t = zix_tree_new(&allocator.base, false, int_cmp, NULL, NULL, NULL);
- assert(t);
-
- // Test that each insertion allocation failing is handled gracefully
- for (size_t i = 0U; i < n_insertions; ++i) {
- allocator.n_remaining = 0;
+ // Successfully stress test the tree to count the number of allocations
+ assert(!stress(&allocator.base, 0, 16));
- assert(zix_tree_insert(t, (void*)i, NULL) == ZIX_STATUS_NO_MEM);
+ // Test that each allocation failing is handled gracefully
+ const size_t n_new_allocs = allocator.n_allocations;
+ for (size_t i = 0U; i < n_new_allocs; ++i) {
+ allocator.n_remaining = i;
+ assert(stress(&allocator.base, 0, 16));
}
-
- zix_tree_free(t);
}
int
@@ -270,20 +241,14 @@ main(int argc, char** argv)
}
}
- if (!n_elems) {
- fprintf(stderr, "USAGE: %s [N_ELEMS]\n", argv[0]);
- return 1;
- }
-
printf(
"Running %u tests with %zu elements (seed %zu)", n_tests, n_elems, seed);
- for (unsigned i = 0; i < n_tests; ++i) {
+ int st = 0;
+ for (unsigned i = 0; !st && i < n_tests; ++i) {
printf(".");
fflush(stdout);
- if (stress(NULL, i, n_elems)) {
- return test_fail("Failure with random seed %zu\n", seed);
- }
+ st = stress(NULL, i, n_elems);
}
printf("\n");