olaf@13: /* universe@103: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. olaf@13: * universe@259: * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved. universe@103: * universe@103: * Redistribution and use in source and binary forms, with or without universe@103: * modification, are permitted provided that the following conditions are met: universe@103: * universe@103: * 1. Redistributions of source code must retain the above copyright universe@103: * notice, this list of conditions and the following disclaimer. universe@103: * universe@103: * 2. Redistributions in binary form must reproduce the above copyright universe@103: * notice, this list of conditions and the following disclaimer in the universe@103: * documentation and/or other materials provided with the distribution. universe@103: * universe@103: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" universe@103: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE universe@103: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE universe@103: * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE universe@103: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR universe@103: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF universe@103: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS universe@103: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN universe@103: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) universe@103: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE universe@103: * POSSIBILITY OF SUCH DAMAGE. olaf@13: */ olaf@13: universe@185: #include "stack_tests.h" olaf@30: universe@185: #define test_ucx_stack_before \ universe@187: char space[99]; \ universe@185: UcxStack stack; \ universe@187: ucx_stack_init(&stack, space, 99) \ olaf@13: universe@185: UCX_TEST(test_ucx_stack_init) { universe@28: universe@185: test_ucx_stack_before; olaf@113: olaf@113: UCX_TEST_BEGIN olaf@113: universe@185: UCX_TEST_ASSERT( universe@185: stack.allocator.malloc == (ucx_allocator_malloc) ucx_stack_malloc && universe@185: stack.allocator.calloc == (ucx_allocator_calloc) ucx_stack_calloc && universe@185: stack.allocator.realloc == (ucx_allocator_realloc) ucx_stack_realloc && universe@185: stack.allocator.free == (ucx_allocator_free) ucx_stack_free && universe@185: stack.allocator.pool == &stack, universe@185: "allocator not properly set"); olaf@113: universe@185: UCX_TEST_ASSERT(!stack.top && stack.space == space universe@187: && stack.size == 99 - 99 % sizeof(void*), universe@185: "struct fields not properly set"); olaf@113: olaf@113: UCX_TEST_END universe@28: } olaf@13: universe@185: UCX_TEST(test_ucx_stack_malloc) { universe@185: universe@185: test_ucx_stack_before; universe@185: universe@185: const size_t metasize = sizeof(struct ucx_stack_metadata); universe@185: universe@185: universe@185: char* first = (char*) ucx_stack_malloc(&stack, 30); universe@185: char* second = (char*) ucx_stack_malloc(&stack, 30); universe@185: char* full = (char*) ucx_stack_malloc(&stack, 30); universe@185: universe@185: memcpy(first, "012345678901234567890123456789", 30); universe@185: memcpy(second, "abcdefghijklmnopqrstuvwxyzABCD", 30); universe@185: universe@185: UCX_TEST_BEGIN universe@185: universe@185: UCX_TEST_ASSERT(!memcmp(space + metasize, universe@185: "012345678901234567890123456789", 30), "first element corrupted"); universe@185: UCX_TEST_ASSERT(!memcmp(space + 32+2*metasize, universe@185: "abcdefghijklmnopqrstuvwxyzABCD", 30), "first element corrupted"); universe@185: universe@185: UCX_TEST_ASSERT(!full, "stack can be overflowed"); universe@185: UCX_TEST_ASSERT(stack.top == space + 32 + 2*metasize, "wrong top pointer"); universe@185: universe@185: if (3*metasize < 32) { universe@185: UCX_TEST_ASSERT(ucx_stack_avail(&stack) == 32-3*metasize, universe@185: "wrong remaining available memory"); universe@185: } else { universe@185: UCX_TEST_ASSERT(ucx_stack_avail(&stack) == 0, universe@185: "wrong remaining available memory"); universe@185: } universe@185: universe@185: UCX_TEST_END universe@28: } olaf@13: universe@185: UCX_TEST(test_ucx_stack_calloc) { universe@28: universe@185: test_ucx_stack_before; universe@185: universe@187: char zeros[99]; universe@187: memset(zeros, 0, 99); universe@187: memset(space, 32, 99); universe@185: ucx_stack_calloc(&stack, 4, sizeof(int)); universe@185: universe@33: UCX_TEST_BEGIN universe@28: universe@185: UCX_TEST_ASSERT(!memcmp(space+sizeof(struct ucx_stack_metadata), universe@185: zeros, 4*sizeof(int)), "memory not nulled"); universe@185: UCX_TEST_ASSERT(!memcmp(space+sizeof(struct ucx_stack_metadata) universe@185: +4*sizeof(int), " ", 10), "too much memory nulled"); universe@185: universe@185: UCX_TEST_END universe@185: } universe@185: universe@185: UCX_TEST(test_ucx_stack_free) { universe@28: universe@185: test_ucx_stack_before; universe@28: universe@185: void *fst = ucx_stack_malloc(&stack, 10); universe@185: void *snd = ucx_stack_malloc(&stack, 10); universe@185: void *thrd = ucx_stack_malloc(&stack, 10); universe@28: universe@185: UCX_TEST_BEGIN universe@28: universe@185: UCX_TEST_ASSERT(stack.top == thrd, "wrong stack"); universe@185: UCX_TEST_ASSERT(((struct ucx_stack_metadata*) thrd - 1)->prev == snd, universe@185: "wrong thrd prev pointer before free"); universe@28: universe@185: ucx_stack_free(&stack, snd); universe@185: universe@185: UCX_TEST_ASSERT(((struct ucx_stack_metadata*) thrd - 1)->prev == fst, universe@185: "wrong thrd prev pointer after freeing snd"); universe@185: UCX_TEST_ASSERT(stack.top == thrd, "wrong top after freeing snd"); universe@185: universe@185: ucx_stack_free(&stack, thrd); universe@185: universe@185: UCX_TEST_ASSERT(stack.top == fst, "wrong top after freeing thrd"); universe@28: universe@28: UCX_TEST_END universe@28: } olaf@13: universe@185: UCX_TEST(test_ucx_stack_realloc) { olaf@14: universe@185: test_ucx_stack_before; universe@185: universe@187: void *fst = ucx_stack_malloc(&stack, 14); universe@185: void *snd = ucx_stack_malloc(&stack, 10); universe@185: universe@33: UCX_TEST_BEGIN universe@28: universe@185: void *nfst = ucx_stack_realloc(&stack, fst, 16); universe@185: UCX_TEST_ASSERT(nfst == fst, "unnecessary move on reallocation"); universe@185: UCX_TEST_ASSERT(((struct ucx_stack_metadata*)fst - 1)->size == 16, universe@185: "wrong size after reallocation"); universe@28: universe@185: void *nsnd = ucx_stack_realloc(&stack, snd, 30); universe@185: UCX_TEST_ASSERT(nsnd == snd, "unnecessary move on top reallocation"); universe@185: UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 30, universe@185: "wrong size after top reallocation"); universe@28: universe@185: nsnd = ucx_stack_realloc(&stack, snd, 5); universe@185: UCX_TEST_ASSERT(nsnd == snd, "unnecessary move on top shrink"); universe@185: UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 5, universe@185: "wrong size after top shrink"); universe@185: UCX_TEST_ASSERT(ucx_stack_avail(&stack) == universe@185: 72-3*sizeof(struct ucx_stack_metadata), "wrong size after top shrink"); universe@28: universe@185: nfst = ucx_stack_realloc(&stack, fst, 24); universe@185: UCX_TEST_ASSERT(nfst != fst, "missing move on huge reallocation"); universe@185: UCX_TEST_ASSERT(stack.top == nfst, "wrong top after huge reallocation"); universe@185: UCX_TEST_ASSERT(ucx_stack_topsize(&stack) == 24, universe@185: "wrong size after huge reallocation"); universe@185: UCX_TEST_ASSERT(!((struct ucx_stack_metadata*)snd - 1)->prev, universe@185: "element not freed after huge reallocation"); universe@28: universe@33: UCX_TEST_END universe@28: } olaf@13: universe@185: UCX_TEST(test_ucx_stack_pop) { universe@185: universe@185: test_ucx_stack_before; universe@187: memset(space, 32, 99); universe@185: universe@185: void *fst = ucx_stack_malloc(&stack, 10); universe@185: void *snd = ucx_stack_malloc(&stack, 10); universe@185: ucx_stack_malloc(&stack, 10); universe@185: universe@185: char buf[16]; universe@185: universe@33: UCX_TEST_BEGIN universe@28: universe@185: memset(buf, '0', 16); universe@185: ucx_stack_pop(&stack, buf); universe@185: UCX_TEST_ASSERT(memcmp(buf, " 000000", 16) == 0, universe@185: "popped wrong content"); universe@185: UCX_TEST_ASSERT(stack.top == snd, "wrong top after pop"); universe@28: universe@185: memset(buf, '0', 16); universe@185: ucx_stack_popn(&stack, buf, 5); universe@185: UCX_TEST_ASSERT(memcmp(buf, " 00000000000", 16) == 0, universe@185: "n-popped wrong content"); universe@185: UCX_TEST_ASSERT(stack.top == fst, "wrong top after pop"); universe@28: universe@185: ucx_stack_pop(&stack, buf); universe@185: UCX_TEST_ASSERT(!stack.top, "top not NULL after last pop"); universe@28: universe@185: memset(buf, '0', 16); universe@185: ucx_stack_pop(&stack, buf); universe@185: UCX_TEST_ASSERT(memcmp(buf, "0000000000000000", 16) == 0, universe@185: "content not unchanged after empty pop"); universe@28: universe@28: UCX_TEST_END olaf@13: }