/* Editor Settings: expandtabs and use 4 spaces for indentation * ex: set softtabstop=4 tabstop=8 expandtab shiftwidth=4: * * -*- mode: c, c-basic-offset: 4 -*- */ /* * Copyright Likewise Software 2004-2008 * All rights reserved. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the license, or (at * your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser * General Public License for more details. You should have received a copy * of the GNU Lesser General Public License along with this program. If * not, see . * * LIKEWISE SOFTWARE MAKES THIS SOFTWARE AVAILABLE UNDER OTHER LICENSING * TERMS AS WELL. IF YOU HAVE ENTERED INTO A SEPARATE LICENSE AGREEMENT * WITH LIKEWISE SOFTWARE, THEN YOU MAY ELECT TO USE THE SOFTWARE UNDER THE * TERMS OF THAT SOFTWARE LICENSE AGREEMENT INSTEAD OF THE TERMS OF THE GNU * LESSER GENERAL PUBLIC LICENSE, NOTWITHSTANDING THE ABOVE NOTICE. IF YOU * HAVE QUESTIONS, OR WISH TO REQUEST A COPY OF THE ALTERNATE LICENSING * TERMS OFFERED BY LIKEWISE SOFTWARE, PLEASE CONTACT LIKEWISE SOFTWARE AT * license@likewisesoftware.com */ #include #include #include /* Test that basic allocations work */ MU_TEST(Alloc, basic) { void* mem = talloc(NULL, 123, NULL); unsigned long addr = (unsigned long) mem; MU_ASSERT(addr % 8 == 0); memset(mem, 0xFF, 123); tfree(mem); } /* Destructor that increments an integer to count total number of objects freed */ static void count_destruct(void* data) { int** d = (int**) data; (**d)++; tfree_children(data); } /* Calculates an exponent */ static int int_pow(int base, int exp) { int res = 1; for (; exp; exp--) res = res * base; return res; } /* Recursively builds and tears down a talloc tree: * parent: the root node * size: the size of each node * destruct: destructor * ply: number of children created at each level * depth: maximum depth of the tree * level_mod: if 0, nothing is freed, else children are freed when the current level % level_mod is 0 * child_mod: only free children if their index % child_mod is 0 */ static void build_and_destroy_tree_mod(void* parent, int size, void (*destruct) (void*), int ply, int depth, int level_mod, int child_mod) { if (depth > 0) { int i; void** children = malloc(sizeof (void*) * ply); for (i = 0; i < ply; i++) { children[i] = tdup(parent, parent, size, destruct); build_and_destroy_tree_mod(children[i], size, destruct, ply, depth-1, level_mod, child_mod); } if (level_mod && depth % level_mod == 0) { for (i = 0; i < ply; i++) { if (i % child_mod == 0) tfree(children[i]); } } free(children); } } static void generic_test(int ply, int depth, int level_mod, int child_mod) { int count = ply == 1 ? depth + 1 : (int_pow(ply, depth + 1) - 1) / (ply - 1); int freed = 0; int** root = talloc(NULL, sizeof(int*), count_destruct); *root = &freed; build_and_destroy_tree_mod(root, sizeof(int*), count_destruct, ply, depth, 0, 0); tfree(root); MU_ASSERT_EQUAL(MU_TYPE_INTEGER, freed, count); } MU_TEST(Alloc, stress) { int ply, depth, level_mod, child_mod; for (ply = 1; ply <= 4; ply++) for (depth = 1; depth <= 8; depth++) for (level_mod = 0; level_mod <= depth; level_mod++) for (child_mod = 1; child_mod <= ply; child_mod++) { MU_TRACE("Ply: %i Depth: %i Level mod: %i Child mod: %i", ply, depth, level_mod, child_mod); generic_test(ply, depth, level_mod, child_mod); } } MU_TEST(Alloc, unlink_children) { int freed = 0; int** parent = talloc(NULL, sizeof(int*), count_destruct); int** child = talloc(parent, sizeof(int*), count_destruct); *parent = *child = &freed; tunlink_children(parent); tfree(parent); MU_ASSERT_EQUAL(MU_TYPE_INTEGER, freed, 1); tfree(child); MU_ASSERT_EQUAL(MU_TYPE_INTEGER, freed, 2); } MU_TEST(Alloc, link) { int freed = 0; int** parent = talloc(NULL, sizeof(int*), count_destruct); int** child = talloc(NULL, sizeof(int*), count_destruct); *parent = *child = &freed; tlink(parent, child); tfree(parent); MU_ASSERT_EQUAL(MU_TYPE_INTEGER, freed, 2); }