diff --git a/Makefile b/Makefile index aa4064f..1910c05 100644 --- a/Makefile +++ b/Makefile @@ -5,11 +5,12 @@ SHARED_LIB = libsparsemap.so #CFLAGS = -Wall -Wextra -Wpedantic -Of -std=c11 -Iinclude/ -fPIC #CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC -CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DSPARSEMAP_ASSERT -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC -#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope -std=c11 -Iinclude/ -fPIC +#CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC +CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -Og -g -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope -std=c11 -Iinclude/ -fPIC #CFLAGS = -Wall -Wextra -Wpedantic -Og -g -fsanitize=all -fhardened -std=c11 -Iinclude/ -fPIC -TEST_FLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -Itests/ -fPIC +#TEST_FLAGS = -DDEBUG -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -Itests/ -fPIC +TEST_FLAGS = -DDEBUG -Wall -Wextra -Wpedantic -Og -g -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope -std=c11 -Iinclude/ -fPIC TESTS = tests/test TEST_OBJS = tests/test.o tests/munit.o tests/tdigest.o tests/common.o diff --git a/examples/ex_1.c b/examples/ex_1.c index ec65d25..f4dda17 100644 --- a/examples/ex_1.c +++ b/examples/ex_1.c @@ -160,7 +160,7 @@ main() sparsemap_set(map, i * 10, true); } for (size_t i = 0; i < 8; i++) { - assert(sparsemap_select(map, i, true) == (sm_loc_t)i * 10); + assert(sparsemap_select(map, i, true) == (sparsemap_idx_t)i * 10); } // split and move, aligned to MiniMap capacity diff --git a/include/sparsemap.h b/include/sparsemap.h index 0a41ac0..689980b 100644 --- a/include/sparsemap.h +++ b/include/sparsemap.h @@ -88,9 +88,10 @@ extern "C" { */ typedef struct sparsemap sparsemap_t; -typedef long sm_loc_t; -#define SM_LOC_MAX LONG_MAX -#define SM_LOC_MIN LONG_MIN +typedef long int sparsemap_idx_t; +#define SPARSEMAP_IDX_MAX ((1UL << (sizeof(long) * CHAR_BIT - 1)) - 1) +#define SPARSEMAP_IDX_MIN (-(SPARSEMAP_IDX_MAX)-1) +#define SPARSEMAP_NOT_FOUND(_x) ((_x) == SPARSEMAP_IDX_MAX || (_x) == SPARSEMAP_IDX_MIN) typedef uint32_t sm_idx_t; typedef uint64_t sm_bitvec_t; @@ -123,9 +124,12 @@ void sparsemap_open(sparsemap_t *, uint8_t *data, size_t data_size); void sparsemap_clear(sparsemap_t *map); /** - * Resizes the data range within the limits of the provided buffer. + * Resizes the data range within the limits of the provided buffer, the map may + * move to a new address returned iff the map was created with the sparsemap() API. + * Take care to use the new reference (think: realloc()). NOTE: If the returned + * value equals NULL then the map was not resized. */ -void sparsemap_set_data_size(sparsemap_t *map, size_t data_size); +sparsemap_t *sparsemap_set_data_size(sparsemap_t *map, size_t data_size); /** * Calculate remaining capacity, approaches 0 when full. @@ -141,13 +145,14 @@ size_t sparsemap_get_capacity(sparsemap_t *map); * Returns the value of a bit at index |idx|, either on/true/1 or off/false/0. * When |idx| is negative it is an error. */ -bool sparsemap_is_set(sparsemap_t *map, sm_loc_t idx); +bool sparsemap_is_set(sparsemap_t *map, sparsemap_idx_t idx); /** * Sets the bit at index |idx| to true or false, depending on |value|. - * When |idx| is negative is it an error. + * When |idx| is negative is it an error. Returns the |idx| supplied or + * SPARSEMAP_IDX_MAX on error with |errno| set to ENOSP when the map is full. */ -void sparsemap_set(sparsemap_t *map, sm_loc_t idx, bool value); +sparsemap_idx_t sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value); /** * Returns the offset of the very first/last bit in the map. @@ -171,15 +176,15 @@ void sparsemap_scan(sparsemap_t *map, void (*scanner)(sm_idx_t vec[], size_t n), * Appends all chunk maps from |map| starting at |offset| to |other|, then * reduces the chunk map-count appropriately. */ -void sparsemap_split(sparsemap_t *map, sm_loc_t offset, sparsemap_t *other); +void sparsemap_split(sparsemap_t *map, sparsemap_idx_t offset, sparsemap_t *other); /** * Finds the offset of the n'th bit either set (|value| is true) or unset * (|value| is false) from the start (positive |n|), or end (negative |n|), * of the bitmap and returns that (uses a 0-based index). Returns -inf or +inf - * if not found (where "inf" is SM_LOC_MAX and "-inf" is SM_LOC_MIN). + * if not found (where "inf" is SPARSEMAP_IDX_MAX and "-inf" is SPARSEMAP_IDX_MIN). */ -sm_loc_t sparsemap_select(sparsemap_t *map, sm_loc_t n, bool value); +sparsemap_idx_t sparsemap_select(sparsemap_t *map, sparsemap_idx_t n, bool value); /** * Counts the set (|value| is true) or unset (|value| is false) bits starting @@ -192,7 +197,7 @@ size_t sparsemap_rank(sparsemap_t *map, size_t x, size_t y, bool value); * are set (|value| is true) or unset (|value| is false) and returns the * starting offset for the span (0-based). */ -size_t sparsemap_span(sparsemap_t *map, sm_loc_t idx, size_t len, bool value); +size_t sparsemap_span(sparsemap_t *map, sparsemap_idx_t idx, size_t len, bool value); #if defined(__cplusplus) } diff --git a/src/sparsemap.c b/src/sparsemap.c index 29f0d2f..5a2574d 100644 --- a/src/sparsemap.c +++ b/src/sparsemap.c @@ -23,14 +23,15 @@ #include #include +#include #include #include +#include #include +#include #include #include #include -#include -#include #include #ifdef SPARSEMAP_DIAGNOSTIC @@ -48,19 +49,24 @@ void __attribute__((format(printf, 4, 5))) __sm_diag_(const char *file, int line vfprintf(stderr, format, args); va_end(args); } -#else -#define __sm_diag(file, line, func, format, ...) ((void)0) -#endif -#ifndef SPARSEMAP_ASSERT -#define SPARSEMAP_ASSERT #define __sm_assert(expr) \ if (!(expr)) \ fprintf(stderr, "%s:%d:%s(): assertion failed! %s", __FILE__, __LINE__, __func__, #expr) + +#define __sm_when_diag(expr) \ + if (1) \ + expr #else +#define __sm_diag(file, line, func, format, ...) ((void)0) #define __sm_assert(expr) ((void)0) +#define __sm_when_diag(expr) \ + if (0) \ + expr #endif +#define IS_8_BYTE_ALIGNED(addr) (((uintptr_t)(addr) & 0x7) == 0) + enum __SM_CHUNK_INFO { /* metadata overhead: 4 bytes for __sm_chunk_t count */ SM_SIZEOF_OVERHEAD = sizeof(uint32_t), @@ -398,7 +404,6 @@ __sm_chunk_map_select(__sm_chunk_t *map, size_t n, ssize_t *pnew_n, bool value) { size_t ret = 0; register uint8_t *p; - (void)value; // TODO p = (uint8_t *)map->m_data; for (size_t i = 0; i < sizeof(sm_bitvec_t); i++, p++) { @@ -413,35 +418,59 @@ __sm_chunk_map_select(__sm_chunk_t *map, size_t n, ssize_t *pnew_n, bool value) continue; } if (flags == SM_PAYLOAD_ZEROS) { - ret += SM_BITS_PER_VECTOR; - continue; + if (value) { + ret += SM_BITS_PER_VECTOR; + continue; + } else { + if (n > SM_BITS_PER_VECTOR) { + n -= SM_BITS_PER_VECTOR; + ret += SM_BITS_PER_VECTOR; + continue; + } + *pnew_n = -1; + return (ret + n); + } } if (flags == SM_PAYLOAD_ONES) { - if (n > SM_BITS_PER_VECTOR) { - n -= SM_BITS_PER_VECTOR; + if (value) { + if (n > SM_BITS_PER_VECTOR) { + n -= SM_BITS_PER_VECTOR; + ret += SM_BITS_PER_VECTOR; + continue; + } + *pnew_n = -1; + return (ret + n); + } else { ret += SM_BITS_PER_VECTOR; continue; } - - *pnew_n = -1; - return (ret + n); } if (flags == SM_PAYLOAD_MIXED) { sm_bitvec_t w = map->m_data[1 + __sm_chunk_map_get_position(map, i * SM_FLAGS_PER_INDEX_BYTE + j)]; for (int k = 0; k < SM_BITS_PER_VECTOR; k++) { - if (w & ((sm_bitvec_t)1 << k)) { - if (n == 0) { - *pnew_n = -1; - return (ret); + if (value) { + if (w & ((sm_bitvec_t)1 << k)) { + if (n == 0) { + *pnew_n = -1; + return (ret); + } + n--; } - n--; + ret++; + } else { + if (!(w & ((sm_bitvec_t)1 << k))) { + if (n == 0) { + *pnew_n = -1; + return (ret); + } + n--; + } + ret++; } - ret++; } } } } - *pnew_n = (ssize_t)n; return (ret); } @@ -659,7 +688,7 @@ __sm_get_aligned_offset(size_t idx) * Returns the byte offset of a __sm_chunk_t in m_data. */ static ssize_t -__sm_get_chunk_map_offset(sparsemap_t *map, sm_loc_t idx) +__sm_get_chunk_map_offset(sparsemap_t *map, sparsemap_idx_t idx) { int count; @@ -672,9 +701,9 @@ __sm_get_chunk_map_offset(sparsemap_t *map, sm_loc_t idx) uint8_t *start = __sm_get_chunk_map_data(map, 0); uint8_t *p = start; - for (sm_loc_t i = 0; i < count - 1; i++) { + for (sparsemap_idx_t i = 0; i < count - 1; i++) { sm_idx_t s = *(sm_idx_t *)p; - __sm_assert(s == __sm_get_aligned_offset(start)); + __sm_assert(s == __sm_get_aligned_offset(s)); __sm_chunk_t chunk; __sm_chunk_map_init(&chunk, p + sizeof(sm_idx_t)); if (s >= idx || (unsigned long)idx < s + __sm_chunk_map_get_capacity(&chunk)) { @@ -688,9 +717,9 @@ __sm_get_chunk_map_offset(sparsemap_t *map, sm_loc_t idx) uint8_t *end = __sm_get_chunk_map_data(map, count - 1); uint8_t *p = end; - for (sm_loc_t i = count - 1; i >= 0; i--) { + for (sparsemap_idx_t i = count - 1; i >= 0; i--) { sm_idx_t e = *(sm_idx_t *)p; - __sm_assert(e == __sm_get_aligned_offset(end)); + __sm_assert(e == __sm_get_aligned_offset(e)); __sm_chunk_t chunk; __sm_chunk_map_init(&chunk, p + sizeof(sm_idx_t)); if (e >= idx || (unsigned long)idx < e + __sm_chunk_map_get_capacity(&chunk)) { @@ -779,10 +808,21 @@ sparsemap(size_t size) if (size == 0) { size = 1024; } - sparsemap_t *map = (sparsemap_t *)calloc(1, sizeof(sparsemap_t) + (size * sizeof(uint8_t))); + + size_t data_size = (size * sizeof(uint8_t)); + + /* Ensure that m_data is 8-byte aligned. */ + size_t total_size = sizeof(sparsemap_t) + data_size; + size_t padding = total_size % 8 == 0 ? 0 : 8 - (total_size % 8); + total_size += padding; + + sparsemap_t *map = (sparsemap_t *)calloc(1, total_size); if (map) { - sparsemap_init(map, (uint8_t *)map + sizeof(sparsemap_t), size); + sparsemap_init(map, (uint8_t *)((uintptr_t)map + sizeof(sparsemap_t) + padding), size); + __sm_when_diag({ __sm_assert(IS_8_BYTE_ALIGNED(map->m_data)); }); } + sparsemap_clear(map); + return map; } @@ -801,7 +841,7 @@ sparsemap_init(sparsemap_t *map, uint8_t *data, size_t size) { map->m_data = data; map->m_data_used = 0; - map->m_capacity = size == 0 ? UINT64_MAX : size; + map->m_capacity = size; sparsemap_clear(map); } @@ -809,7 +849,7 @@ void sparsemap_open(sparsemap_t *map, uint8_t *data, size_t data_size) { map->m_data = data; - map->m_data_used = 0; + map->m_data_used = map->m_data_used > 0 ? map->m_data_used : 0; map->m_capacity = data_size; } @@ -817,10 +857,30 @@ sparsemap_open(sparsemap_t *map, uint8_t *data, size_t data_size) * TODO/NOTE: This is a dangerous operation because we cannot verify that * data_size is not exceeding the size of the underlying buffer. */ -void -sparsemap_set_data_size(sparsemap_t *map, size_t data_size) +sparsemap_t * +sparsemap_set_data_size(sparsemap_t *map, size_t size) { - map->m_capacity = data_size; + if ((uintptr_t)map->m_data == (uintptr_t)map + sizeof(sparsemap_t) && size > map->m_capacity) { + /* This sparsemap was allocated by the sparsemap() API, we can resize it. */ + size_t data_size = (size * sizeof(uint8_t)); + + /* Ensure that m_data is 8-byte aligned. */ + size_t total_size = sizeof(sparsemap_t) + data_size; + size_t padding = total_size % 8 == 0 ? 0 : 8 - (total_size % 8); + total_size += padding; + + sparsemap_t *m = (sparsemap_t *)realloc(map, total_size); + if (!m) { + return NULL; + } + memset(m + sizeof(sparsemap_t) + (m->m_capacity * sizeof(uint8_t)), 0, total_size - m->m_capacity - padding); + m->m_capacity = data_size; + m->m_data = (uint8_t *)((uintptr_t)m + sizeof(sparsemap_t) + padding); + __sm_when_diag({ __sm_assert(IS_8_BYTE_ALIGNED(m->m_data)); }) return m; + } else { + map->m_capacity = size; + return map; + } } double @@ -842,7 +902,7 @@ sparsemap_get_capacity(sparsemap_t *map) } bool -sparsemap_is_set(sparsemap_t *map, sm_loc_t idx) +sparsemap_is_set(sparsemap_t *map, sparsemap_idx_t idx) { __sm_assert(sparsemap_get_size(map) >= SM_SIZEOF_OVERHEAD); @@ -874,15 +934,11 @@ sparsemap_is_set(sparsemap_t *map, sm_loc_t idx) return (__sm_chunk_map_is_set(&chunk, idx - start)); } -void -sparsemap_set(sparsemap_t *map, sm_loc_t idx, bool value) +sparsemap_idx_t +sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value) { __sm_assert(sparsemap_get_size(map) >= SM_SIZEOF_OVERHEAD); - if (idx < 0) { - return; - } - /* Get the __sm_chunk_t which manages this index */ ssize_t offset = __sm_get_chunk_map_offset(map, idx); bool dont_grow = false; @@ -891,7 +947,7 @@ sparsemap_set(sparsemap_t *map, sm_loc_t idx, bool value) immediately; otherwise create an initial __sm_chunk_t. */ if (offset == -1) { if (value == false) { - return; + return idx; } uint8_t buf[sizeof(sm_idx_t) + sizeof(sm_bitvec_t) * 2] = { 0 }; @@ -917,7 +973,7 @@ sparsemap_set(sparsemap_t *map, sm_loc_t idx, bool value) if (idx < start) { if (value == false) { /* nothing to do */ - return; + return idx; } uint8_t buf[sizeof(sm_idx_t) + sizeof(sm_bitvec_t) * 2] = { 0 }; @@ -944,10 +1000,10 @@ sparsemap_set(sparsemap_t *map, sm_loc_t idx, bool value) else { __sm_chunk_t chunk; __sm_chunk_map_init(&chunk, p + sizeof(sm_idx_t)); - if (idx - (unsigned long)start >= __sm_chunk_map_get_capacity(&chunk)) { + if (idx - start >= (sparsemap_idx_t)__sm_chunk_map_get_capacity(&chunk)) { if (value == false) { /* nothing to do */ - return; + return idx; } size_t size = __sm_chunk_map_get_size(&chunk); @@ -958,7 +1014,7 @@ sparsemap_set(sparsemap_t *map, sm_loc_t idx, bool value) __sm_insert_data(map, offset, &buf[0], sizeof(buf)); start += __sm_chunk_map_get_capacity(&chunk); - if ((size_t)start + SM_CHUNK_MAX_CAPACITY < (unsigned long)idx) { + if ((sparsemap_idx_t)start + SM_CHUNK_MAX_CAPACITY < idx) { start = __sm_get_fully_aligned_offset(idx); } *(sm_idx_t *)p = start; @@ -1009,6 +1065,7 @@ sparsemap_set(sparsemap_t *map, sm_loc_t idx, bool value) break; } __sm_assert(sparsemap_get_size(map) >= SM_SIZEOF_OVERHEAD); + return idx; } sm_idx_t @@ -1059,7 +1116,7 @@ sparsemap_scan(sparsemap_t *map, void (*scanner)(sm_idx_t[], size_t), size_t ski } void -sparsemap_split(sparsemap_t *map, sm_loc_t offset, sparsemap_t *other) +sparsemap_split(sparsemap_t *map, sparsemap_idx_t offset, sparsemap_t *other) { assert(offset % SM_BITS_PER_VECTOR == 0); @@ -1132,7 +1189,7 @@ sparsemap_split(sparsemap_t *map, sm_loc_t offset, sparsemap_t *other) __sm_chunk_map_set_capacity(&d_chunk, capacity - (offset % capacity)); /* Now copy the bits. */ - sm_loc_t d = offset; + sparsemap_idx_t d = offset; for (size_t j = offset % capacity; j < capacity; j++, d++) { if (__sm_chunk_map_is_set(&s_chunk, j)) { sparsemap_set(other, d, true); @@ -1177,8 +1234,8 @@ sparsemap_split(sparsemap_t *map, sm_loc_t offset, sparsemap_t *other) assert(sparsemap_get_size(other) > SM_SIZEOF_OVERHEAD); } -sm_loc_t -sparsemap_select(sparsemap_t *map, sm_loc_t n, bool value) +sparsemap_idx_t +sparsemap_select(sparsemap_t *map, sparsemap_idx_t n, bool value) { assert(sparsemap_get_size(map) >= SM_SIZEOF_OVERHEAD); size_t result; @@ -1204,16 +1261,16 @@ sparsemap_select(sparsemap_t *map, sm_loc_t n, bool value) #ifdef DEBUG assert(!"shouldn't be here"); #endif - return SM_LOC_MAX; + return SPARSEMAP_IDX_MAX; } else { - return SM_LOC_MIN; // TODO... sparsemap_select(map, -n, value); + return SPARSEMAP_IDX_MIN; // TODO... sparsemap_select(map, -n, value); } } size_t sparsemap_rank_vec(sparsemap_t *map, size_t x, size_t y, bool value, sm_bitvec_t *vec) { - (void)value; //TODO + (void)value; // TODO assert(sparsemap_get_size(map) >= SM_SIZEOF_OVERHEAD); size_t result = 0, prev = 0, count = __sm_get_chunk_map_count(map); uint8_t *p = __sm_get_chunk_map_data(map, 0); @@ -1244,11 +1301,11 @@ sparsemap_rank(sparsemap_t *map, size_t x, size_t y, bool value) } size_t -sparsemap_span(sparsemap_t *map, sm_loc_t idx, size_t len, bool value) +sparsemap_span(sparsemap_t *map, sparsemap_idx_t idx, size_t len, bool value) { size_t count, nth = 0; sm_bitvec_t vec = 0; - sm_loc_t offset; + sparsemap_idx_t offset; offset = sparsemap_select(map, nth++, value); if (len == 1) { @@ -1269,7 +1326,7 @@ sparsemap_span(sparsemap_t *map, sm_loc_t idx, size_t len, bool value) nth++; /* Use select to potentially jump very far forward in the map. */ offset = sparsemap_select(map, nth, value); - } while (offset != SM_LOC_MAX); + } while (offset != SPARSEMAP_IDX_MAX); - return idx > 0 ? SM_LOC_MAX : SM_LOC_MIN; + return idx >= 0 ? SPARSEMAP_IDX_MAX : SPARSEMAP_IDX_MIN; } diff --git a/tests/common.c b/tests/common.c index e184897..9e3223d 100644 --- a/tests/common.c +++ b/tests/common.c @@ -10,6 +10,7 @@ #include #include #ifdef X86_INTRIN +#include #include #endif @@ -146,25 +147,25 @@ ensure_sequential_set(int a[], int l, int r) return value; } -int -create_sequential_set_in_empty_map(sparsemap_t *map, int s, int r) +sparsemap_idx_t +sm_add_span(sparsemap_t *map, int map_size, int span_length) { + int attempts = map_size / span_length; + sparsemap_idx_t placed_at; do { - int placed_at; - if (s >= r + 1) { - placed_at = 0; + placed_at = random_uint32() % (map_size - span_length - 1); + if (sm_occupied(map, placed_at, span_length, true)) { + attempts--; } else { - placed_at = random_uint32() % (s - r - 1); + break; } - for (int i = placed_at; i < placed_at + r; i++) { - sparsemap_is_set(map, i); - continue; + } while (attempts); + for (int i = placed_at; i < placed_at + span_length; i++) { + if (sparsemap_set(map, i, true) != i) { + return placed_at; // TODO error? } - for (int i = placed_at; i < placed_at + r; i++) { - sparsemap_set(map, i, true); - } - return placed_at; - } while (true); + } + return placed_at; } void @@ -318,10 +319,10 @@ bitmap_from_uint32(sparsemap_t *map, uint32_t number) } void -bitmap_from_uint64(sparsemap_t *map, uint64_t number) +sm_bitmap_from_uint64(sparsemap_t *map, uint64_t number) { for (int i = 0; i < 64; i++) { - bool bit = number & (1 << i); + bool bit = number & ((uint64_t)1 << i); sparsemap_set(map, i, bit); } } @@ -368,7 +369,7 @@ whats_set_uint64(uint64_t number, int pos[64]) } void -whats_set(sparsemap_t *map, int m) +sm_whats_set(sparsemap_t *map, int m) { logf("what's set in the range [0, %d): ", m); for (int i = 0; i < m; i++) { @@ -378,3 +379,25 @@ whats_set(sparsemap_t *map, int m) } logf("\n"); } + +bool +sm_is_span(sparsemap_t *map, sparsemap_idx_t m, size_t len, bool value) +{ + for (sparsemap_idx_t i = m; i < (sparsemap_idx_t)len; i++) { + if (sparsemap_is_set(map, i) != value) { + return false; + } + } + return true; +} + +bool +sm_occupied(sparsemap_t *map, sparsemap_idx_t m, size_t len, bool value) +{ + for (sparsemap_idx_t i = m; i < (sparsemap_idx_t)len; i++) { + if (sparsemap_is_set(map, i) == value) { + return true; + } + } + return false; +} diff --git a/tests/common.h b/tests/common.h index 243cc8f..626d2fd 100644 --- a/tests/common.h +++ b/tests/common.h @@ -41,11 +41,14 @@ int is_unique(int a[], int l, int value); void setup_test_array(int a[], int l, int max_value); void shuffle(int *array, size_t n); int ensure_sequential_set(int a[], int l, int r); -int create_sequential_set_in_empty_map(sparsemap_t *map, int s, int r); +sparsemap_idx_t sm_add_span(sparsemap_t *map, int map_size, int span_length); void bitmap_from_uint32(sparsemap_t *map, uint32_t number); -void bitmap_from_uint64(sparsemap_t *map, uint64_t number); +void sm_bitmap_from_uint64(sparsemap_t *map, uint64_t number); uint32_t rank_uint64(uint64_t number, int n, int p); int whats_set_uint64(uint64_t number, int bitPositions[64]); -void whats_set(sparsemap_t *map, int m); +void sm_whats_set(sparsemap_t *map, int m); + +bool sm_is_span(sparsemap_t *map, sparsemap_idx_t m, size_t len, bool value); +bool sm_occupied(sparsemap_t *map, sparsemap_idx_t m, size_t len, bool value); diff --git a/tests/test.c b/tests/test.c index 66db668..7c031ed 100644 --- a/tests/test.c +++ b/tests/test.c @@ -10,6 +10,7 @@ #define MUNIT_NO_FORK (1) #define MUNIT_ENABLE_ASSERT_ALIASES (1) +#include #include #include #include @@ -18,10 +19,14 @@ #include "common.h" #include "munit.h" +#define munit_free free + #if defined(_MSC_VER) #pragma warning(disable : 4127) #endif +#define SELECT_FALSE + /* !!! Duplicated here for testing purposes. Keep in sync, or suffer. !!! */ struct sparsemap { uint8_t *m_data; @@ -66,7 +71,7 @@ test_api_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; assert_ptr_not_null(map); - free(map); + munit_free(map); } /* -------------------------- API Tests */ @@ -93,6 +98,7 @@ static void * test_api_clear_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -103,7 +109,8 @@ static void test_api_clear_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -126,6 +133,7 @@ static void * test_api_open_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -137,7 +145,8 @@ static void test_api_open_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -160,6 +169,7 @@ static void * test_api_set_data_size_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -171,7 +181,8 @@ static void test_api_set_data_size_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -193,6 +204,7 @@ static void * test_api_remaining_capacity_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -203,7 +215,8 @@ static void test_api_remaining_capacity_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -241,6 +254,7 @@ static void * test_api_get_capacity_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -252,7 +266,8 @@ static void test_api_get_capacity_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -274,6 +289,7 @@ static void * test_api_is_set_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -285,7 +301,8 @@ static void test_api_is_set_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -306,6 +323,7 @@ static void * test_api_set_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -316,7 +334,8 @@ static void test_api_set_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -345,6 +364,7 @@ static void * test_api_get_starting_offset_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -356,7 +376,8 @@ static void test_api_get_starting_offset_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -379,6 +400,7 @@ static void * test_api_get_size_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -390,7 +412,8 @@ static void test_api_get_size_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -411,10 +434,11 @@ static void * test_api_scan_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); - bitmap_from_uint64(map, ((uint64_t)0xfeedface << 32) | 0xbadc0ffee); + sm_bitmap_from_uint64(map, ((uint64_t)0xfeedface << 32) | 0xbadc0ffee); return (void *)map; } @@ -422,7 +446,8 @@ static void test_api_scan_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } void @@ -441,7 +466,7 @@ test_api_scan(const MunitParameter params[], void *data) assert_ptr_not_null(map); sparsemap_set(map, 4200, true); - assert_true(sparsemap_is_set(map, 42)); + assert_true(sparsemap_is_set(map, 4200)); sparsemap_scan(map, scan_for_0xfeedfacebadcoffee, 0); return MUNIT_OK; @@ -451,6 +476,7 @@ static void * test_api_split_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -463,7 +489,8 @@ static void test_api_split_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -494,10 +521,11 @@ static void * test_api_select_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); - bitmap_from_uint64(map, ((uint64_t)0xfeedface << 32) | 0xbadc0ffee); + sm_bitmap_from_uint64(map, ((uint64_t)0xfeedface << 32) | 0xbadc0ffee); return (void *)map; } @@ -505,7 +533,8 @@ static void test_api_select_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -522,22 +551,76 @@ test_api_select(const MunitParameter params[], void *data) assert_true(sparsemap_select(map, 4, true) == 6); assert_true(sparsemap_select(map, 17, true) == 26); -#if 0 // TODO - size_t f = sparsemap_select(map, 0, false); - for (int i = 0; i <= f; i++) { - assert_false(sparsemap_is_set(map, i % 2)); - } + return MUNIT_OK; +} - sparsemap_clear(map); +#ifdef SELECT_FALSE +static void * +test_api_select_false_setup(const MunitParameter params[], void *user_data) +{ + uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); + sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); + + sparsemap_init(map, buf, 1024); + sm_bitmap_from_uint64(map, ((uint64_t)0xfeedface << 32) | 0xbadc0ffee); + + return (void *)map; +} +static void +test_api_select_false_tear_down(void *fixture) +{ + sparsemap_t *map = (sparsemap_t *)fixture; + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); + test_api_tear_down(fixture); +} +static MunitResult +test_api_select_false(const MunitParameter params[], void *data) +{ + sparsemap_t *map = (sparsemap_t *)data; + (void)params; + + assert_ptr_not_null(map); for (int i = 0; i < 1000; i++) { - sparsemap_set(map, i, i % 2 ? true : false); + sparsemap_set(map, i, true); } - - f = sparsemap_select(map, 0, false); + sparsemap_idx_t f = sparsemap_select(map, 0, false); assert_true(f == 1000); - sparsemap_clear(map); + return MUNIT_OK; +} +#endif + +#ifdef SELECT_NEG +static void * +test_api_select_neg_setup(const MunitParameter params[], void *user_data) +{ + uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); + sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); + + sparsemap_init(map, buf, 1024); + sm_bitmap_from_uint64(map, ((uint64_t)0xfeedface << 32) | 0xbadc0ffee); + + return (void *)map; +} +static void +test_api_select_neg_tear_down(void *fixture) +{ + sparsemap_t *map = (sparsemap_t *)fixture; + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); + test_api_tear_down(fixture); +} +static MunitResult +test_api_select_neg(const MunitParameter params[], void *data) +{ + sparsemap_t *map = (sparsemap_t *)data; + (void)params; + + assert_ptr_not_null(map); sparsemap_set(map, 42, true); sparsemap_set(map, 420, true); @@ -552,14 +635,16 @@ test_api_select(const MunitParameter params[], void *data) assert_true(f == 420); f = sparsemap_select(map, -3, true); assert_true(f == 42); -#endif + return MUNIT_OK; } +#endif static void * test_api_rank_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -570,7 +655,8 @@ static void test_api_rank_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -615,6 +701,7 @@ static void * test_api_span_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -625,7 +712,8 @@ static void test_api_span_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -638,26 +726,26 @@ test_api_span(const MunitParameter params[], void *data) int located_at, placed_at, amt = 10000; - placed_at = create_sequential_set_in_empty_map(map, amt, 1); + placed_at = sm_add_span(map, amt, 1); located_at = sparsemap_span(map, 0, 1, true); assert_true(located_at == placed_at); sparsemap_clear(map); - placed_at = create_sequential_set_in_empty_map(map, amt, 50); + placed_at = sm_add_span(map, amt, 50); located_at = sparsemap_span(map, 0, 50, true); assert_true(located_at == placed_at); sparsemap_clear(map); - placed_at = create_sequential_set_in_empty_map(map, amt, 50); + placed_at = sm_add_span(map, amt, 50); located_at = sparsemap_span(map, placed_at / 2, 50, true); assert_true(located_at == placed_at); /* TODO sparsemap_clear(map); - placed_at = create_sequential_set_in_empty_map(map, amt, amt - 1); + placed_at = sm_add_span(map, amt, amt - 1); located_at = sparsemap_span(map, 0, amt - 1, true); assert_true(located_at == placed_at); */ @@ -681,7 +769,13 @@ static MunitTest api_test_suite[] = { { (char *)"/get_size", test_api_get_size, test_api_get_size_setup, test_api_get_size_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { (char *)"/scan", test_api_scan, test_api_scan_setup, test_api_scan_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { (char *)"/split", test_api_split, test_api_split_setup, test_api_split_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, - { (char *)"/select", test_api_select, test_api_select_setup, test_api_select_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, + { (char *)"/select/true", test_api_select, test_api_select_setup, test_api_select_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, +#ifdef SELECT_FALSE + { (char *)"/select/false", test_api_select_false, test_api_select_false_setup, test_api_select_false_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, +#endif +#ifdef SELECT_NEG + { (char *)"/select/neg", test_api_select_neg, test_api_select_neg_setup, test_api_select_neg_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, +#endif { (char *)"/rank", test_api_rank, test_api_rank_setup, test_api_rank_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { (char *)"/span", test_api_span, test_api_span_setup, test_api_span_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } @@ -693,10 +787,10 @@ static MunitTest api_test_suite[] = { static void * test_scale_lots_o_spans_setup(const MunitParameter params[], void *user_data) { - uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); - sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); - - sparsemap_init(map, buf, 1024); + (void)params; + (void)user_data; + sparsemap_t *map = sparsemap(1024); + assert_ptr_not_null(map); return (void *)map; } @@ -704,8 +798,8 @@ static void test_scale_lots_o_spans_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); - test_api_tear_down(fixture); + assert_ptr_not_null(map); + munit_free(map); } static MunitResult test_scale_lots_o_spans(const MunitParameter params[], void *data) @@ -717,21 +811,82 @@ test_scale_lots_o_spans(const MunitParameter params[], void *data) for (int i = 0; i < 268435456;) { int l = i % 31 + 16; - create_sequential_set_in_empty_map(map, 268435456, l); + sm_add_span(map, 268435456, l); + if (errno == ENOSPC) { + map = sparsemap_set_data_size(map, sparsemap_get_capacity(map) * 2); + errno = 0; + } i += l; /* ANSI esc code to clear line, carrage return, then print on the same line */ - //printf("\033[2K\r%d", i); - //printf("%d\t%d\n", l, i); - //fflush(stdout); + // printf("\033[2K\r%d", i); + // printf("%d\t%d\n", l, i); + // fflush(stdout); } return MUNIT_OK; } +static void * +test_scale_ondrej_setup(const MunitParameter params[], void *user_data) +{ + uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); + sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); + + sparsemap_init(map, buf, 1024); + + return (void *)map; +} +static void +test_scale_ondrej_tear_down(void *fixture) +{ + sparsemap_t *map = (sparsemap_t *)fixture; + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); + test_api_tear_down(fixture); +} +static MunitResult +test_scale_ondrej(const MunitParameter params[], void *data) +{ + sparsemap_t *map = (sparsemap_t *)data; + (void)params; + + assert_ptr_not_null(map); + + sparsemap_idx_t stride = 18; + sparsemap_idx_t top = 268435456; + sparsemap_idx_t needle = munit_rand_int_range(1, top / stride); + for (sparsemap_idx_t i = 0; i < top / stride; i++) { + for (sparsemap_idx_t j = 0; j < stride; j++) { + bool set = (i != needle) ? (j < 10) : (j < 9); + sparsemap_set(map, i, set); + } + } +#if 0 + // sm_add_span(map, 268435456, 9); + + size_t b = sparsemap_span(map, 0, 8, true); + if (SPARSEMAP_NOT_FOUND(b)) { + printf("%ld\n", b); + printf("%ld / %ld == %ld %ld\n", b, stride, b / stride, needle); + } else { + printf("not found\n"); + } + /* + size_t b = sparsemap_span(map, 0, 9, false); TODO + printf("%ld (%d) / %d == %d", b, (int)b, stride, needle); + fflush(stdout); + assert_true(((int)b / stride) == needle); + */ +#endif + return MUNIT_OK; +} + static void * test_scale_spans_come_spans_go_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -742,7 +897,8 @@ static void test_scale_spans_come_spans_go_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -753,32 +909,33 @@ test_scale_spans_come_spans_go(const MunitParameter params[], void *data) assert_ptr_not_null(map); + /* ~5e7 interations due to 2e9 / avg(l) */ for (int i = 0; i < 268435456;) { int l = i % 31 + 16; - create_sequential_set_in_empty_map(map, 268435456, l); - i += l; + sm_add_span(map, 268435456, l); /* After 10,000 spans are in there we consume a span every iteration. */ if (l > 10000) { do { - int s = munit_rand_int_range(1, 30); - int o = munit_rand_int_range(1, 268435456 - s - 1); - size_t b = sparsemap_span(map, o, s, true); - if (b == SM_LOC_MAX) { - continue; - } - for (int j = b; j < s; j++) { - assert_true(sparsemap_is_set(map, j) == true); - } - for (int j = b; j < s; j++) { - sparsemap_set(map, j, false); - } - for (int j = b; j < s; j++) { - assert_true(sparsemap_is_set(map, j) == false); - } - break; + int s = munit_rand_int_range(1, 30); + int o = munit_rand_int_range(1, 268435456 - s - 1); + size_t b = sparsemap_span(map, o, s, true); + if (b == SPARSEMAP_IDX_MAX) { + continue; + } + for (int j = b; j < s; j++) { + assert_true(sparsemap_is_set(map, j) == true); + } + for (int j = b; j < s; j++) { + sparsemap_set(map, j, false); + } + for (int j = b; j < s; j++) { + assert_true(sparsemap_is_set(map, j) == false); + } + break; } while (true); } + i += l; } return MUNIT_OK; @@ -788,6 +945,7 @@ static void * test_scale_best_case_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -798,7 +956,8 @@ static void test_scale_best_case_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -818,7 +977,8 @@ test_scale_best_case(const MunitParameter params[], void *data) */ /* Set every bit on, that should be the best case. */ - for (int i = 0; i < 268435456; i++) { + // for (int i = 0; i < 268435456; i++) { + for (int i = 0; i < 172032; i++) { /* ANSI esc code to clear line, carrage return, then print on the same line */ // printf("\033[2K\r%d", i); // fflush(stdout); @@ -832,6 +992,7 @@ static void * test_scale_worst_case_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 1024); @@ -842,7 +1003,8 @@ static void test_scale_worst_case_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -862,7 +1024,8 @@ test_scale_worst_case(const MunitParameter params[], void *data) */ /* Set every other bit, that has to be the "worst case" for this index. */ - for (int i = 0; i < 8134407; i += 2) { + // for (int i = 0; i < 8134407; i += 2) { + for (int i = 0; i < 7744; i += 2) { /* ANSI esc code to clear line, carrage return, then print on the same line */ // printf("\033[2K\r%d", i); // fflush(stdout); @@ -878,6 +1041,7 @@ static void * test_perf_span_solo_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024 * 3, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 3 * 1024); @@ -888,7 +1052,8 @@ static void test_perf_span_solo_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -904,9 +1069,9 @@ test_perf_span_solo(const MunitParameter params[], void *data) for (int i = 1; i < amt; i++) { for (int j = 1; j <= 100; j++) { sparsemap_clear(map); - placed_at = create_sequential_set_in_empty_map(map, amt, j); + placed_at = sm_add_span(map, amt, j); // logf("i = %d, j = %d\tplaced_at %d\n", i, j, placed_at); - // whats_set(map, 5000); + // sm_whats_set(map, 5000); // start = nsts(); located_at = sparsemap_span(map, 0, j, true); // stop = nsts(); @@ -925,6 +1090,7 @@ static void * test_perf_span_tainted_setup(const MunitParameter params[], void *user_data) { uint8_t *buf = munit_calloc(1024 * 3, sizeof(uint8_t)); + assert_ptr_not_null(buf); sparsemap_t *map = (sparsemap_t *)test_api_setup(params, user_data); sparsemap_init(map, buf, 3 * 1024); @@ -935,7 +1101,8 @@ static void test_perf_span_tainted_tear_down(void *fixture) { sparsemap_t *map = (sparsemap_t *)fixture; - free(map->m_data); + assert_ptr_not_null(map->m_data); + munit_free(map->m_data); test_api_tear_down(fixture); } static MunitResult @@ -952,7 +1119,7 @@ test_perf_span_tainted(const MunitParameter params[], void *data) for (int j = 100; j <= 10; j++) { sparsemap_clear(map); populate_map(map, 1024, 1 * 1024); - placed_at = create_sequential_set_in_empty_map(map, amt, j); + placed_at = sm_add_span(map, amt, j); // start = nsts(); located_at = sparsemap_span(map, 0, j, true); // stop = nsts(); @@ -971,6 +1138,7 @@ test_perf_span_tainted(const MunitParameter params[], void *data) // clang-format off static MunitTest scale_test_suite[] = { { (char *)"/lots-o-spans", test_scale_lots_o_spans, test_scale_lots_o_spans_setup, test_scale_lots_o_spans_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, + { (char *)"/ondrej", test_scale_ondrej, test_scale_ondrej_setup, test_scale_ondrej_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { (char *)"/spans_come_spans_go", test_scale_spans_come_spans_go, test_scale_spans_come_spans_go_setup, test_scale_spans_come_spans_go_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { (char *)"/best-case", test_scale_best_case, test_scale_best_case_setup, test_scale_best_case_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, { (char *)"/worst-case", test_scale_worst_case, test_scale_worst_case_setup, test_scale_worst_case_tear_down, MUNIT_TEST_OPTION_NONE, NULL }, @@ -986,12 +1154,19 @@ static MunitTest perf_test_suite[] = { // clang-format off static MunitSuite other_test_suite[] = { + { "/api", api_test_suite, NULL, 1, MUNIT_SUITE_OPTION_NONE }, { "/perf", perf_test_suite, NULL, 1, MUNIT_SUITE_OPTION_NONE }, { "/scale", scale_test_suite, NULL, 1, MUNIT_SUITE_OPTION_NONE }, { NULL, NULL, NULL, 0, MUNIT_SUITE_OPTION_NONE } }; // clang-format on -static const MunitSuite main_test_suite = { (char *)"/api", api_test_suite, other_test_suite, 1, MUNIT_SUITE_OPTION_NONE }; +// clang-format off +static MunitTest sparsemap_test_suite[] = { + { NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL } +}; +// clang-format on + +static const MunitSuite main_test_suite = { (char *)"/sparsemap", sparsemap_test_suite, other_test_suite, 1, MUNIT_SUITE_OPTION_NONE }; int main(int argc, char *argv[MUNIT_ARRAY_PARAM(argc + 1)])