diff options
author | David Robillard <d@drobilla.net> | 2021-09-10 20:54:08 -0400 |
---|---|---|
committer | David Robillard <d@drobilla.net> | 2021-09-10 21:41:29 -0400 |
commit | cf3b3048da0f80d3643ba0a9bc61a29ca5c5cf8b (patch) | |
tree | b24292319826dd451b2b4a2228c63c246dd1d549 | |
parent | 592961cc6b6c92ba6af2c30d01aa4f2a00955b68 (diff) | |
download | zix-cf3b3048da0f80d3643ba0a9bc61a29ca5c5cf8b.tar.gz zix-cf3b3048da0f80d3643ba0a9bc61a29ca5c5cf8b.tar.bz2 zix-cf3b3048da0f80d3643ba0a9bc61a29ca5c5cf8b.zip |
Test failed Ring allocation
-rw-r--r-- | meson.build | 2 | ||||
-rw-r--r-- | test/failing_allocator.c | 94 | ||||
-rw-r--r-- | test/failing_allocator.h | 33 | ||||
-rw-r--r-- | test/ring_test.c | 69 |
4 files changed, 179 insertions, 19 deletions
diff --git a/meson.build b/meson.build index 2da63a0..d967a42 100644 --- a/meson.build +++ b/meson.build @@ -244,7 +244,7 @@ if get_option('tests') foreach test : tests c_args = [] - sources = ['test/@0@.c'.format(test)] + sources = files('test/@0@.c'.format(test), 'test/failing_allocator.c') if get_option('test_malloc') and host_machine.system() != 'windows' sources += ['test/test_malloc.c'] diff --git a/test/failing_allocator.c b/test/failing_allocator.c new file mode 100644 index 0000000..bb569de --- /dev/null +++ b/test/failing_allocator.c @@ -0,0 +1,94 @@ +/* + Copyright 2021 David Robillard <d@drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#include "failing_allocator.h" + +#include "zix/allocator.h" +#include "zix/attributes.h" + +#include <stdbool.h> +#include <stddef.h> + +static bool +attempt(ZixFailingAllocatorState* const state) +{ + ++state->n_allocations; + + if (!state->n_remaining) { + return false; + } + + --state->n_remaining; + return true; +} + +ZIX_MALLOC_FUNC +static void* +zix_failing_malloc(ZixAllocatorHandle* const handle, const size_t size) +{ + ZixFailingAllocatorState* const state = (ZixFailingAllocatorState*)handle; + const ZixAllocator* const base = zix_default_allocator(); + + return attempt(state) ? base->malloc(base->handle, size) : NULL; +} + +ZIX_MALLOC_FUNC +static void* +zix_failing_calloc(ZixAllocatorHandle* const handle, + const size_t nmemb, + const size_t size) +{ + ZixFailingAllocatorState* const state = (ZixFailingAllocatorState*)handle; + const ZixAllocator* const base = zix_default_allocator(); + + return attempt(state) ? base->calloc(base->handle, nmemb, size) : NULL; +} + +static void* +zix_failing_realloc(ZixAllocatorHandle* const handle, + void* const ptr, + const size_t size) +{ + ZixFailingAllocatorState* const state = (ZixFailingAllocatorState*)handle; + const ZixAllocator* const base = zix_default_allocator(); + + return attempt(state) ? base->realloc(base->handle, ptr, size) : NULL; +} + +static void +zix_failing_free(ZixAllocatorHandle* const handle, void* const ptr) +{ + (void)handle; + + const ZixAllocator* const base = zix_default_allocator(); + + base->free(base->handle, ptr); +} + +ZIX_CONST_FUNC +ZixAllocator +zix_failing_allocator(ZixFailingAllocatorState* const state) +{ + const ZixAllocator failing_allocator = { + state, + zix_failing_malloc, + zix_failing_calloc, + zix_failing_realloc, + zix_failing_free, + }; + + return failing_allocator; +} diff --git a/test/failing_allocator.h b/test/failing_allocator.h new file mode 100644 index 0000000..b9daf75 --- /dev/null +++ b/test/failing_allocator.h @@ -0,0 +1,33 @@ +/* + Copyright 2021 David Robillard <d@drobilla.net> + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ + +#ifndef ZIX_FAILING_ALLOCATOR_H +#define ZIX_FAILING_ALLOCATOR_H + +#include "zix/allocator.h" + +#include <stddef.h> + +/// An allocator that fails after some number of successes for testing +typedef struct { + size_t n_allocations; ///< The number of allocations that have been attempted + size_t n_remaining; ///< The number of remaining successful allocations +} ZixFailingAllocatorState; + +ZixAllocator +zix_failing_allocator(ZixFailingAllocatorState* state); + +#endif // ZIX_FAILING_ALLOCATOR_H diff --git a/test/ring_test.c b/test/ring_test.c index 23c5adc..2b20822 100644 --- a/test/ring_test.c +++ b/test/ring_test.c @@ -1,5 +1,5 @@ /* - Copyright 2011-2020 David Robillard <d@drobilla.net> + Copyright 2011-2021 David Robillard <d@drobilla.net> Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -14,6 +14,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#undef NDEBUG + +#include "failing_allocator.h" + +#include "zix/allocator.h" #include "zix/attributes.h" #include "zix/ring.h" #include "zix/thread.h" @@ -112,24 +117,9 @@ writer(void* ZIX_UNUSED(arg)) return NULL; } -int -main(int argc, char** argv) +static int +test_ring(const unsigned size) { - if (argc > 1 && argv[1][0] == '-') { - printf("Usage: %s SIZE N_WRITES\n", argv[0]); - return 1; - } - - unsigned size = 1024; - if (argc > 1) { - size = (unsigned)strtoul(argv[1], NULL, 10); - } - - n_writes = size * 1024; - if (argc > 2) { - n_writes = (unsigned)strtoul(argv[2], NULL, 10); - } - zix_ring_free(NULL); printf("Testing %u writes of %u ints to a %u int ring...\n", @@ -239,3 +229,46 @@ main(int argc, char** argv) zix_ring_free(ring); return 0; } + +static void +test_failed_alloc(void) +{ + ZixFailingAllocatorState state = {0u, SIZE_MAX}; + ZixAllocator allocator = zix_failing_allocator(&state); + + // Successfully allocate a ring to count the number of allocations + ring = zix_ring_new(&allocator, 512); + assert(ring); + + // Test that each allocation failing is handled gracefully + const size_t n_new_allocs = state.n_allocations; + for (size_t i = 0u; i < n_new_allocs; ++i) { + state.n_remaining = i; + assert(!zix_ring_new(&allocator, 512)); + } + + zix_ring_free(ring); +} + +int +main(int argc, char** argv) +{ + if (argc > 1 && argv[1][0] == '-') { + printf("Usage: %s SIZE N_WRITES\n", argv[0]); + return 1; + } + + unsigned size = 1024; + if (argc > 1) { + size = (unsigned)strtoul(argv[1], NULL, 10); + } + + n_writes = size * 1024; + if (argc > 2) { + n_writes = (unsigned)strtoul(argv[2], NULL, 10); + } + + test_failed_alloc(); + test_ring(size); + return 0; +} |