1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
|
/* -*- coding: utf-8 -*-
* ----------------------------------------------------------------------
* Copyright © 2012-2015, RedJack, LLC.
* All rights reserved.
*
* Please see the COPYING file in this distribution for license details.
* ----------------------------------------------------------------------
*/
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <check.h>
#include "libcork/core/mempool.h"
#include "libcork/core/types.h"
#include "helpers.h"
/*-----------------------------------------------------------------------
* Memory pools
*/
START_TEST(test_mempool_01)
{
#define OBJECT_COUNT 16
DESCRIBE_TEST;
struct cork_mempool *mp;
/* Small enough that we'll have to allocate a couple of blocks */
mp = cork_mempool_new_ex(int64_t, 64);
size_t i;
int64_t *objects[OBJECT_COUNT];
for (i = 0; i < OBJECT_COUNT; i++) {
fail_if((objects[i] = cork_mempool_new_object(mp)) == NULL,
"Cannot allocate object #%zu", i);
}
for (i = 0; i < OBJECT_COUNT; i++) {
cork_mempool_free_object(mp, objects[i]);
}
for (i = 0; i < OBJECT_COUNT; i++) {
fail_if((objects[i] = cork_mempool_new_object(mp)) == NULL,
"Cannot reallocate object #%zu", i);
}
for (i = 0; i < OBJECT_COUNT; i++) {
cork_mempool_free_object(mp, objects[i]);
}
cork_mempool_free(mp);
}
END_TEST
START_TEST(test_mempool_fail_01)
{
DESCRIBE_TEST;
struct cork_mempool *mp;
mp = cork_mempool_new(int64_t);
int64_t *obj;
fail_if((obj = cork_mempool_new_object(mp)) == NULL,
"Cannot allocate object");
/* This should raise an assertion since we never freed obj. */
cork_mempool_free(mp);
}
END_TEST
static void
int64_init(void *user_data, void *vobj)
{
int64_t *obj = vobj;
*obj = 12;
}
static void
int64_done(void *user_data, void *vobj)
{
size_t *done_call_count = user_data;
(*done_call_count)++;
}
/* This is based on our knowledge of the internal structure of a memory
* pool's blocks and objects. */
#define OBJECTS_PER_BLOCK(block_size, obj_size) \
(((block_size) - CORK_SIZEOF_POINTER) / (obj_size + CORK_SIZEOF_POINTER))
START_TEST(test_mempool_reuse_01)
{
#define BLOCK_SIZE 64
DESCRIBE_TEST;
size_t done_call_count = 0;
struct cork_mempool *mp;
mp = cork_mempool_new_ex(int64_t, BLOCK_SIZE);
cork_mempool_set_user_data(mp, &done_call_count, NULL);
cork_mempool_set_init_object(mp, int64_init);
cork_mempool_set_done_object(mp, int64_done);
int64_t *obj;
fail_if((obj = cork_mempool_new_object(mp)) == NULL,
"Cannot allocate object");
/* The init_object function sets the value to 12 */
fail_unless(*obj == 12, "Unexpected value %" PRId64, *obj);
/* Set the value to something new, free the object, then reallocate.
* Since we know memory pools are LIFO, we should get back the same
* object, unchanged. */
*obj = 42;
cork_mempool_free_object(mp, obj);
fail_if((obj = cork_mempool_new_object(mp)) == NULL,
"Cannot allocate object");
fail_unless(*obj == 42, "Unexpected value %" PRId64, *obj);
cork_mempool_free_object(mp, obj);
cork_mempool_free(mp);
fail_unless(done_call_count ==
OBJECTS_PER_BLOCK(BLOCK_SIZE, sizeof(int64_t)),
"done_object called an unexpected number of times: %zu",
done_call_count);
}
END_TEST
/*-----------------------------------------------------------------------
* Testing harness
*/
Suite *
test_suite()
{
Suite *s = suite_create("mempool");
TCase *tc_mempool = tcase_create("mempool");
tcase_add_test(tc_mempool, test_mempool_01);
#if NDEBUG
/* If we're not compiling assertions then this test won't abort */
tcase_add_test(tc_mempool, test_mempool_fail_01);
#else
tcase_add_test_raise_signal(tc_mempool, test_mempool_fail_01, SIGABRT);
#endif
tcase_add_test(tc_mempool, test_mempool_reuse_01);
suite_add_tcase(s, tc_mempool);
return s;
}
int
main(int argc, const char **argv)
{
int number_failed;
Suite *suite = test_suite();
SRunner *runner = srunner_create(suite);
setup_allocator();
srunner_run_all(runner, CK_NORMAL);
number_failed = srunner_ntests_failed(runner);
srunner_free(runner);
return (number_failed == 0)? EXIT_SUCCESS: EXIT_FAILURE;
}
|