data-pool-t.c (libmaxminddb-1.5.0) | : | data-pool-t.c (libmaxminddb-1.5.2) | ||
---|---|---|---|---|
#include "libtap/tap.h" | ||||
#include "maxminddb_test_helper.h" | ||||
#include <assert.h> | #include <assert.h> | |||
#include <data-pool.h> | #include <data-pool.h> | |||
#include <inttypes.h> | #include <inttypes.h> | |||
#include "libtap/tap.h" | ||||
#include <math.h> | #include <math.h> | |||
#include "maxminddb_test_helper.h" | ||||
static void test_data_pool_new(void); | static void test_data_pool_new(void); | |||
static void test_data_pool_destroy(void); | static void test_data_pool_destroy(void); | |||
static void test_data_pool_alloc(void); | static void test_data_pool_alloc(void); | |||
static void test_data_pool_to_list(void); | static void test_data_pool_to_list(void); | |||
static bool create_and_check_list(size_t const, | static bool create_and_check_list(size_t const, size_t const); | |||
size_t const); | ||||
static void check_block_count(MMDB_entry_data_list_s const *const, | static void check_block_count(MMDB_entry_data_list_s const *const, | |||
size_t const); | size_t const); | |||
int main(void) | int main(void) { | |||
{ | ||||
plan(NO_PLAN); | plan(NO_PLAN); | |||
test_data_pool_new(); | test_data_pool_new(); | |||
test_data_pool_destroy(); | test_data_pool_destroy(); | |||
test_data_pool_alloc(); | test_data_pool_alloc(); | |||
test_data_pool_to_list(); | test_data_pool_to_list(); | |||
done_testing(); | done_testing(); | |||
} | } | |||
static void test_data_pool_new(void) | static void test_data_pool_new(void) { | |||
{ | ||||
{ | { | |||
MMDB_data_pool_s *const pool = data_pool_new(0); | MMDB_data_pool_s *const pool = data_pool_new(0); | |||
ok(!pool, "size 0 is not valid"); | ok(!pool, "size 0 is not valid"); | |||
} | } | |||
{ | { | |||
MMDB_data_pool_s *const pool = data_pool_new(SIZE_MAX - 10); | MMDB_data_pool_s *const pool = data_pool_new(SIZE_MAX - 10); | |||
ok(!pool, "very large size is not valid"); | ok(!pool, "very large size is not valid"); | |||
} | } | |||
{ | { | |||
MMDB_data_pool_s *const pool = data_pool_new(512); | MMDB_data_pool_s *const pool = data_pool_new(512); | |||
ok(pool != NULL, "size 512 is valid"); | ok(pool != NULL, "size 512 is valid"); | |||
cmp_ok(pool->size, "==", 512, "size is 512"); | cmp_ok(pool->size, "==", 512, "size is 512"); | |||
cmp_ok(pool->used, "==", 0, "used size is 0"); | cmp_ok(pool->used, "==", 0, "used size is 0"); | |||
data_pool_destroy(pool); | data_pool_destroy(pool); | |||
} | } | |||
} | } | |||
static void test_data_pool_destroy(void) | static void test_data_pool_destroy(void) { | |||
{ | { data_pool_destroy(NULL); } | |||
{ | ||||
data_pool_destroy(NULL); | ||||
} | ||||
{ | { | |||
MMDB_data_pool_s *const pool = data_pool_new(512); | MMDB_data_pool_s *const pool = data_pool_new(512); | |||
ok(pool != NULL, "created pool"); | ok(pool != NULL, "created pool"); | |||
data_pool_destroy(pool); | data_pool_destroy(pool); | |||
} | } | |||
} | } | |||
static void test_data_pool_alloc(void) | static void test_data_pool_alloc(void) { | |||
{ | ||||
{ | { | |||
MMDB_data_pool_s *const pool = data_pool_new(1); | MMDB_data_pool_s *const pool = data_pool_new(1); | |||
ok(pool != NULL, "created pool"); | ok(pool != NULL, "created pool"); | |||
cmp_ok(pool->used, "==", 0, "used size starts at 0"); | cmp_ok(pool->used, "==", 0, "used size starts at 0"); | |||
MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool); | MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool); | |||
ok(entry1 != NULL, "allocated first entry"); | ok(entry1 != NULL, "allocated first entry"); | |||
// Arbitrary so that we can recognize it. | // Arbitrary so that we can recognize it. | |||
entry1->entry_data.offset = (uint32_t)123; | entry1->entry_data.offset = (uint32_t)123; | |||
skipping to change at line 112 | skipping to change at line 105 | |||
} | } | |||
} | } | |||
cmp_ok(pool->size, "==", initial_size, "size is the initial size"); | cmp_ok(pool->size, "==", initial_size, "size is the initial size"); | |||
cmp_ok(pool->used, "==", initial_size, "used size is as expected"); | cmp_ok(pool->used, "==", initial_size, "used size is as expected"); | |||
MMDB_entry_data_list_s *const entry = data_pool_alloc(pool); | MMDB_entry_data_list_s *const entry = data_pool_alloc(pool); | |||
ok(entry != NULL, "got an entry"); | ok(entry != NULL, "got an entry"); | |||
entry->entry_data.offset = (uint32_t)initial_size; | entry->entry_data.offset = (uint32_t)initial_size; | |||
cmp_ok(pool->size, "==", initial_size * 2, | cmp_ok( | |||
"size is the initial size*2"); | pool->size, "==", initial_size * 2, "size is the initial size*2"); | |||
cmp_ok(pool->used, "==", 1, "used size is as expected"); | cmp_ok(pool->used, "==", 1, "used size is as expected"); | |||
MMDB_entry_data_list_s *const list = data_pool_to_list(pool); | MMDB_entry_data_list_s *const list = data_pool_to_list(pool); | |||
MMDB_entry_data_list_s *element = list; | MMDB_entry_data_list_s *element = list; | |||
for (size_t i = 0; i < initial_size + 1; i++) { | for (size_t i = 0; i < initial_size + 1; i++) { | |||
ok( | ok(element->entry_data.offset == (uint32_t)i, | |||
element->entry_data.offset == (uint32_t)i, | "found offset %" PRIu32 ", should have %zu", | |||
"found offset %" PRIu32 ", should have %zu", | element->entry_data.offset, | |||
element->entry_data.offset, | i); | |||
i | ||||
); | ||||
element = element->next; | element = element->next; | |||
} | } | |||
ok(entry1->entry_data.offset == (uint32_t)0, | ok(entry1->entry_data.offset == (uint32_t)0, | |||
"accessing entry1's original memory is ok after growing the pool"); | "accessing entry1's original memory is ok after growing the pool"); | |||
data_pool_destroy(pool); | data_pool_destroy(pool); | |||
} | } | |||
} | } | |||
static void test_data_pool_to_list(void) | static void test_data_pool_to_list(void) { | |||
{ | ||||
{ | { | |||
size_t const initial_size = 16; | size_t const initial_size = 16; | |||
MMDB_data_pool_s *const pool = data_pool_new(initial_size); | MMDB_data_pool_s *const pool = data_pool_new(initial_size); | |||
ok(pool != NULL, "created pool"); | ok(pool != NULL, "created pool"); | |||
MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool); | MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool); | |||
ok(entry1 != NULL, "got an entry"); | ok(entry1 != NULL, "got an entry"); | |||
MMDB_entry_data_list_s *const list_one_element | MMDB_entry_data_list_s *const list_one_element = | |||
= data_pool_to_list(pool); | data_pool_to_list(pool); | |||
ok(list_one_element != NULL, "got a list"); | ok(list_one_element != NULL, "got a list"); | |||
ok(list_one_element == entry1, | ok(list_one_element == entry1, | |||
"list's first element is the first we retrieved"); | "list's first element is the first we retrieved"); | |||
ok(list_one_element->next == NULL, "list is one element in size"); | ok(list_one_element->next == NULL, "list is one element in size"); | |||
MMDB_entry_data_list_s *const entry2 = data_pool_alloc(pool); | MMDB_entry_data_list_s *const entry2 = data_pool_alloc(pool); | |||
ok(entry2 != NULL, "got another entry"); | ok(entry2 != NULL, "got another entry"); | |||
MMDB_entry_data_list_s *const list_two_elements | MMDB_entry_data_list_s *const list_two_elements = | |||
= data_pool_to_list(pool); | data_pool_to_list(pool); | |||
ok(list_two_elements != NULL, "got a list"); | ok(list_two_elements != NULL, "got a list"); | |||
ok(list_two_elements == entry1, | ok(list_two_elements == entry1, | |||
"list's first element is the first we retrieved"); | "list's first element is the first we retrieved"); | |||
ok(list_two_elements->next != NULL, "list has a second element"); | ok(list_two_elements->next != NULL, "list has a second element"); | |||
MMDB_entry_data_list_s *const second_element = list_two_elements->next; | MMDB_entry_data_list_s *const second_element = list_two_elements->next; | |||
ok(second_element == entry2, | ok(second_element == entry2, | |||
"second item in list is second we retrieved"); | "second item in list is second we retrieved"); | |||
ok(second_element->next == NULL, "list ends with the second element"); | ok(second_element->next == NULL, "list ends with the second element"); | |||
skipping to change at line 179 | skipping to change at line 169 | |||
} | } | |||
{ | { | |||
size_t const initial_size = 1; | size_t const initial_size = 1; | |||
MMDB_data_pool_s *const pool = data_pool_new(initial_size); | MMDB_data_pool_s *const pool = data_pool_new(initial_size); | |||
ok(pool != NULL, "created pool"); | ok(pool != NULL, "created pool"); | |||
MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool); | MMDB_entry_data_list_s *const entry1 = data_pool_alloc(pool); | |||
ok(entry1 != NULL, "got an entry"); | ok(entry1 != NULL, "got an entry"); | |||
MMDB_entry_data_list_s *const list_one_element | MMDB_entry_data_list_s *const list_one_element = | |||
= data_pool_to_list(pool); | data_pool_to_list(pool); | |||
ok(list_one_element != NULL, "got a list"); | ok(list_one_element != NULL, "got a list"); | |||
ok(list_one_element == entry1, | ok(list_one_element == entry1, | |||
"list's first element is the first we retrieved"); | "list's first element is the first we retrieved"); | |||
ok(list_one_element->next == NULL, "list ends with this element"); | ok(list_one_element->next == NULL, "list ends with this element"); | |||
data_pool_destroy(pool); | data_pool_destroy(pool); | |||
} | } | |||
{ | { | |||
size_t const initial_size = 2; | size_t const initial_size = 2; | |||
skipping to change at line 216 | skipping to change at line 206 | |||
MMDB_entry_data_list_s *const list_element2 = list_element1->next; | MMDB_entry_data_list_s *const list_element2 = list_element1->next; | |||
ok(list_element2 == entry2, | ok(list_element2 == entry2, | |||
"second element is the second we retrieved"); | "second element is the second we retrieved"); | |||
ok(list_element2->next == NULL, "list ends with this element"); | ok(list_element2->next == NULL, "list ends with this element"); | |||
data_pool_destroy(pool); | data_pool_destroy(pool); | |||
} | } | |||
{ | { | |||
diag("starting test: fill one block save for one spot"); | diag("starting test: fill one block save for one spot"); | |||
ok( | ok(create_and_check_list(3, 2), "fill one block save for one spot"); | |||
create_and_check_list(3, 2), | ||||
"fill one block save for one spot" | ||||
); | ||||
} | } | |||
{ | { | |||
diag("starting test: fill one block"); | diag("starting test: fill one block"); | |||
ok( | ok(create_and_check_list(3, 3), "fill one block"); | |||
create_and_check_list(3, 3), | ||||
"fill one block" | ||||
); | ||||
} | } | |||
{ | { | |||
diag("starting test: fill one block and use one spot in the next block") | diag( | |||
; | "starting test: fill one block and use one spot in the next block"); | |||
ok( | ok(create_and_check_list(3, 3 + 1), | |||
create_and_check_list(3, 3 + 1), | "fill one block and use one spot in the next block"); | |||
"fill one block and use one spot in the next block" | ||||
); | ||||
} | } | |||
{ | { | |||
diag("starting test: fill two blocks save for one spot"); | diag("starting test: fill two blocks save for one spot"); | |||
ok( | ok(create_and_check_list(3, 3 + 3 * 2 - 1), | |||
create_and_check_list(3, 3 + 3 * 2 - 1), | "fill two blocks save for one spot"); | |||
"fill two blocks save for one spot" | ||||
); | ||||
} | } | |||
{ | { | |||
diag("starting test: fill two blocks"); | diag("starting test: fill two blocks"); | |||
ok( | ok(create_and_check_list(3, 3 + 3 * 2), "fill two blocks"); | |||
create_and_check_list(3, 3 + 3 * 2), | ||||
"fill two blocks" | ||||
); | ||||
} | } | |||
{ | { | |||
diag("starting test: fill two blocks and use one spot in the next"); | diag("starting test: fill two blocks and use one spot in the next"); | |||
ok( | ok(create_and_check_list(3, 3 + 3 * 2 + 1), | |||
create_and_check_list(3, 3 + 3 * 2 + 1), | "fill two blocks and use one spot in the next"); | |||
"fill two blocks and use one spot in the next" | ||||
); | ||||
} | } | |||
{ | { | |||
diag("starting test: fill three blocks save for one spot"); | diag("starting test: fill three blocks save for one spot"); | |||
ok( | ok(create_and_check_list(3, 3 + 3 * 2 + 3 * 2 * 2 - 1), | |||
create_and_check_list(3, 3 + 3 * 2 + 3 * 2 * 2 - 1), | "fill three blocks save for one spot"); | |||
"fill three blocks save for one spot" | ||||
); | ||||
} | } | |||
{ | { | |||
diag("starting test: fill three blocks"); | diag("starting test: fill three blocks"); | |||
ok( | ok(create_and_check_list(3, 3 + 3 * 2 + 3 * 2 * 2), | |||
create_and_check_list(3, 3 + 3 * 2 + 3 * 2 * 2), | "fill three blocks"); | |||
"fill three blocks" | ||||
); | ||||
} | } | |||
// It would be nice to have a larger number of these, but it's expensive to | // It would be nice to have a larger number of these, but it's expensive to | |||
// run many. We currently hardcode what this will be anyway, so varying | // run many. We currently hardcode what this will be anyway, so varying | |||
// this is not very interesting. | // this is not very interesting. | |||
size_t const initial_sizes[] = { 1, 2, 32, 64, 128, 256 }; | size_t const initial_sizes[] = {1, 2, 32, 64, 128, 256}; | |||
size_t const max_element_count = 4096; | size_t const max_element_count = 4096; | |||
for (size_t i = 0; i < sizeof(initial_sizes) / sizeof(initial_sizes[0]); | for (size_t i = 0; i < sizeof(initial_sizes) / sizeof(initial_sizes[0]); | |||
i++) { | i++) { | |||
size_t const initial_size = initial_sizes[i]; | size_t const initial_size = initial_sizes[i]; | |||
for (size_t element_count = 0; element_count < max_element_count; | for (size_t element_count = 0; element_count < max_element_count; | |||
element_count++) { | element_count++) { | |||
assert(create_and_check_list(initial_size, element_count)); | assert(create_and_check_list(initial_size, element_count)); | |||
} | } | |||
} | } | |||
} | } | |||
// Use assert() rather than libtap as libtap is significantly slower and we run | // Use assert() rather than libtap as libtap is significantly slower and we run | |||
// this frequently. | // this frequently. | |||
static bool create_and_check_list(size_t const initial_size, | static bool create_and_check_list(size_t const initial_size, | |||
size_t const element_count) | size_t const element_count) { | |||
{ | ||||
MMDB_data_pool_s *const pool = data_pool_new(initial_size); | MMDB_data_pool_s *const pool = data_pool_new(initial_size); | |||
assert(pool != NULL); | assert(pool != NULL); | |||
assert(pool->used == 0); | assert(pool->used == 0); | |||
// Hold on to the pointers as we initially see them so that we can check | // Hold on to the pointers as we initially see them so that we can check | |||
// they are still valid after building the list. | // they are still valid after building the list. | |||
MMDB_entry_data_list_s **const entry_array | MMDB_entry_data_list_s **const entry_array = | |||
= calloc(element_count, sizeof(MMDB_entry_data_list_s *)); | calloc(element_count, sizeof(MMDB_entry_data_list_s *)); | |||
assert(entry_array != NULL); | assert(entry_array != NULL); | |||
for (size_t i = 0; i < element_count; i++) { | for (size_t i = 0; i < element_count; i++) { | |||
MMDB_entry_data_list_s *const entry = data_pool_alloc(pool); | MMDB_entry_data_list_s *const entry = data_pool_alloc(pool); | |||
assert(entry != NULL); | assert(entry != NULL); | |||
entry->entry_data.offset = (uint32_t)i; | entry->entry_data.offset = (uint32_t)i; | |||
entry_array[i] = entry; | entry_array[i] = entry; | |||
} | } | |||
skipping to change at line 352 | skipping to change at line 323 | |||
check_block_count(list, initial_size); | check_block_count(list, initial_size); | |||
data_pool_destroy(pool); | data_pool_destroy(pool); | |||
free(entry_array); | free(entry_array); | |||
return true; | return true; | |||
} | } | |||
// Use assert() rather than libtap as libtap is significantly slower and we run | // Use assert() rather than libtap as libtap is significantly slower and we run | |||
// this frequently. | // this frequently. | |||
static void check_block_count(MMDB_entry_data_list_s const *const list, | static void check_block_count(MMDB_entry_data_list_s const *const list, | |||
size_t const initial_size) | size_t const initial_size) { | |||
{ | ||||
size_t got_block_count = 0; | size_t got_block_count = 0; | |||
size_t got_element_count = 0; | size_t got_element_count = 0; | |||
MMDB_entry_data_list_s const *element = list; | MMDB_entry_data_list_s const *element = list; | |||
while (element) { | while (element) { | |||
got_element_count++; | got_element_count++; | |||
if (element->pool) { | if (element->pool) { | |||
got_block_count++; | got_block_count++; | |||
} | } | |||
End of changes. 26 change blocks. | ||||
72 lines changed or deleted | 41 lines changed or added |