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