PASS: /qc/__sm_chunk_get_position

This commit is contained in:
Gregory Burd 2024-07-19 04:44:26 -04:00
parent dfda0017d5
commit b0280271df
9 changed files with 305 additions and 177 deletions

View file

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CLionExternalBuildManager">
<target id="db0ccaeb-4851-470b-83d0-afa663f6ceb9" name="tests/soak" defaultType="MAKE">
<configuration id="98973a90-a9d0-431b-9071-9ce6960b0b01" name="tests/soak">
<build type="MAKE">
<make targetName="tests/soak" />
</build>
<clean type="MAKE">
<make targetName="clean" />
</clean>
</configuration>
</target>
</component>
</project>

View file

@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MakefileBuildTargetsManager">
<user-build-targets>
<build-target name="tests/soak">
<build-configurations>
<build-configuration>
<make-targets>
<make-target>tests/soak</make-target>
</make-targets>
</build-configuration>
</build-configurations>
</build-target>
<build-target name="clean">
<build-configurations>
<build-configuration>
<make-targets>
<make-target>clean</make-target>
</make-targets>
</build-configuration>
</build-configurations>
</build-target>
</user-build-targets>
</component>
</project>

View file

@ -4,29 +4,8 @@
<option name="executionMode" value="BINARY" />
<option name="pathToExecutable" value="$USER_HOME$/.nix-profile/bin/black" />
</component>
<component name="CidrRootsConfiguration">
<sourceRoots>
<file path="$PROJECT_DIR$/examples" />
<file path="$PROJECT_DIR$/include" />
<file path="$PROJECT_DIR$/lib" />
<file path="$PROJECT_DIR$/src" />
<file path="$PROJECT_DIR$/test" />
<file path="$PROJECT_DIR$/tests" />
</sourceRoots>
<component name="CMakePythonSetting">
<option name="pythonIntegrationState" value="YES" />
</component>
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MakefileSettings">
<option name="linkedExternalProjectsSettings">
<MakefileProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="version" value="2" />
</MakefileProjectSettings>
</option>
</component>
<component name="MakefileWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>
<component name="CMakeWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>

View file

@ -15,7 +15,7 @@ set(SOURCE_DIR .)
set(HEADER_DIR . test)
set(COMMON_CMAKE_C_FLAGS "-Wall -Wextra -Wpedantic")
set(CMAKE_C_FLAGS_DEBUG "-DSPARSEMAP_DIAGNOSTIC -DDEBUG -g -Og")
set(CMAKE_C_FLAGS_DEBUG "-DSPARSEMAP_DIAGNOSTIC -DSPARSEMAP_TESTING -DDEBUG -g -O0")
set(CMAKE_C_FLAGS_PROFILE "-DSPARSEMAP_DIAGNOSTIC -DDEBUG -g -Og -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope")
set(CMAKE_C_FLAGS_RELEASE "-Ofast")
@ -73,9 +73,10 @@ target_include_directories(ex_4 PRIVATE ${HEADER_DIR})
add_custom_target(run_ex_4 COMMAND ex_4 WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# Add test program
add_executable(test test/test.c test/munit.c test/common.c)
add_executable(test test/test.c test/munit.c test/qc.c test/common.c)
target_link_libraries(test PRIVATE sparsemap)
target_include_directories(test PRIVATE ${HEADER_DIR})
set_source_files_properties(test/test.c PROPERTIES COMPILE_FLAGS "-DDEBUG -DDIAGNOSTIC -DSPARSEMAP_TESTING" )
add_custom_target(run_test COMMAND test WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# Add soak program

View file

@ -1,67 +0,0 @@
#!/usr/bin/env python
# Gererate a C function that contains a pre-calculated static table where each
# 8bit offset into that table encodes the required additional space for what is
# described.
# The 2 bit patters are:
# 00 -> 0 additional sm_bitvec_t (ZEROS)
# 11 -> 0 additional sm_bitvec_t (ONES)
# 10 -> 0 additional sm_bitvec_t (NONE, or RLE if at the start)
# 01 -> 1 additional sm_bitvec_t (MIXED, requires additional space)
# The goal is to output this:
# /**
# * Calculates the number of sm_bitvec_ts required by a single byte with flags
# * (in m_data[0]).
# */
# static size_t
# __sm_chunk_calc_vector_size(uint8_t b)
# {
# // clang-format off
# static int lookup[] = {
# 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 2, 1, 0, 0, 1, 0,
# 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 2, 1, 0, 0, 1, 0,
# 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, 2, 1, 1, 2, 1,
# 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 2, 1, 0, 0, 1, 0,
# 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 2, 1, 0, 0, 1, 0,
# 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 2, 1, 0, 0, 1, 0,
# 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, 2, 1, 1, 2, 1,
# 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 2, 1, 0, 0, 1, 0,
# 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, 2, 1, 1, 2, 1,
# 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, 2, 1, 1, 2, 1,
# 2, 2, 3, 2, 2, 2, 3, 2, 3, 3, 4, 3, 2, 2, 3, 2,
# 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, 2, 1, 1, 2, 1,
# 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 2, 1, 0, 0, 1, 0,
# 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 2, 1, 0, 0, 1, 0,
# 1, 1, 2, 1, 1, 1, 2, 1, 2, 2, 3, 2, 1, 1, 2, 1,
# 0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 2, 1, 0, 0, 1, 0
# };
# // clang-format on
# return (size_t)lookup[b];
# }
# TODO: fix this... :)
def create_lookup_table_c_format():
"""Creates a lookup table in C-style format."""
lookup_table = []
for byte in range(256):
count = 0
for i in range(3):
if (byte >> (i * 2)) & 3 == 1:
count += 1
lookup_table.append(count)
# Format the output as a C array
output = "static int lookup[] = {\n"
for i in range(0, 256, 16):
line = " " + ", ".join(str(x) for x in lookup_table[i:i+16]) + ",\n"
output += line
output += "};"
print(output)
if __name__ == "__main__":
create_lookup_table_c_format()

View file

@ -68,6 +68,10 @@ void __attribute__((format(printf, 4, 5))) __sm_diag_(const char *file, int line
typedef uint64_t __sm_bitvec_t;
typedef struct {
__sm_bitvec_t *m_data;
} __sm_chunk_t;
enum __SM_CHUNK_INFO {
/* metadata overhead: 4 bytes for __sm_chunk_t count */
SM_SIZEOF_OVERHEAD = sizeof(uint32_t),
@ -85,7 +89,7 @@ enum __SM_CHUNK_INFO {
SM_CHUNK_MAX_CAPACITY = (SM_BITS_PER_VECTOR * SM_FLAGS_PER_INDEX),
/* minimum capacity of a __sm_chunk_t (in bits) */
SM_CHUNK_MIN_CAPACITY = SM_BITS_PER_VECTOR,
SM_CHUNK_MIN_CAPACITY = (SM_BITS_PER_VECTOR - 2),
/* __sm_bitvec_t payload is all zeros (2#00) */
SM_PAYLOAD_ZEROS = 0,
@ -113,13 +117,10 @@ enum __SM_CHUNK_INFO {
};
#define SM_CHUNK_GET_FLAGS(from, at) ((((from)) & ((__sm_bitvec_t)SM_FLAG_MASK << ((at)*2))) >> ((at)*2))
#define SM_IS_CHUNK_RLE(chunk) ((*((__sm_bitvec_t *)(chunk)->m_data) & (((__sm_bitvec_t)0x3) << (SM_BITS_PER_VECTOR - 2))) == SM_PAYLOAD_NONE)
#define SM_IS_CHUNK_RLE(chunk) \
(((*((__sm_bitvec_t *)(chunk)->m_data) & (((__sm_bitvec_t)0x3) << (SM_BITS_PER_VECTOR - 2))) >> (SM_BITS_PER_VECTOR - 2)) == SM_PAYLOAD_NONE)
#define SM_CHUNK_RLE_LENGTH(chunk) (size_t)(*((__sm_bitvec_t *)(chunk)->m_data) & ~(((__sm_bitvec_t)0x3) << (SM_BITS_PER_VECTOR - 2)))
typedef struct {
__sm_bitvec_t *m_data;
} __sm_chunk_t;
struct __attribute__((aligned(8))) sparsemap {
size_t m_capacity; /* The total size of m_data */
size_t m_data_used; /* The used size of m_data */
@ -141,7 +142,6 @@ struct __attribute__((aligned(8))) sparsemap {
* @return The calculated number of vectors.
* @see bin/gen_chunk_vector_size_table.py
*/
#if 1
static size_t
__sm_chunk_calc_vector_size(uint8_t b)
{
@ -167,22 +167,6 @@ __sm_chunk_calc_vector_size(uint8_t b)
// clang-format on
return (size_t)lookup[b];
}
#else
/* Alternative, non-lookup table, implementation. */
static size_t
__sm_chunk_calc_vector_size(uint8_t b)
{
int count = 0;
for (int i = 0; i < 4; i++) {
if (((b >> (i * 2)) & 0x03) == 0x02) {
count++;
}
}
return count;
}
#endif
/** @brief Calculates the byte offset of a vector within a chunk.
*
@ -192,11 +176,11 @@ __sm_chunk_calc_vector_size(uint8_t b)
* additional vectors are stored.
*
* @param[in] chunk Pointer to the chunk containing the vector.
* @param[in] nth Index of the desired vector within the chunk (0-based).
* @param[in] bv Index of the desired vector within the chunk (0-based).
* @return Byte offset of the vector within the chunk's data.
*/
static size_t
__sm_chunk_get_position(__sm_chunk_t *chunk, size_t nth)
__sm_chunk_get_position(__sm_chunk_t *chunk, size_t bv)
{
/* Handle 4 indices (1 byte) at a time. */
size_t num_bytes;
@ -208,13 +192,13 @@ __sm_chunk_get_position(__sm_chunk_t *chunk, size_t nth)
return position;
}
num_bytes = nth / ((size_t)SM_FLAGS_PER_INDEX_BYTE * SM_BITS_PER_VECTOR);
num_bytes = bv / ((size_t)SM_FLAGS_PER_INDEX_BYTE * SM_BITS_PER_VECTOR);
for (size_t i = 0; i < num_bytes; i++, p++) {
position += __sm_chunk_calc_vector_size(*p);
}
nth -= num_bytes * SM_FLAGS_PER_INDEX_BYTE;
for (size_t i = 0; i < nth; i++) {
bv -= num_bytes * SM_FLAGS_PER_INDEX_BYTE;
for (size_t i = 0; i < bv; i++) {
size_t flags = SM_CHUNK_GET_FLAGS(*chunk->m_data, i);
if (flags == SM_PAYLOAD_MIXED) {
position++;
@ -316,6 +300,7 @@ __sm_chunk_reduce_capacity(__sm_chunk_t *chunk, size_t capacity)
}
}
__sm_assert(__sm_chunk_get_capacity(chunk) == capacity);
__sm_assert(SM_IS_CHUNK_RLE(chunk) == false);
return 0;
}
@ -1281,10 +1266,10 @@ sparsemap_set(sparsemap_t *map, sparsemap_idx_t idx, bool value)
__sm_chunk_t chunk;
__sm_chunk_init(&chunk, p + sizeof(sm_idx_t));
if (__sm_chunk_reduce_capacity(&chunk, start - aligned_idx)) {
/* The __sm_chunk_t is empty then remove it.
__sm_remove_data(map, offset, sizeof(sm_idx_t) + sizeof(__sm_bitvec_t) * 2);
__sm_set_chunk_count(map, __sm_get_chunk_count(map) - 1);
*/
/* TODO: The __sm_chunk_t is empty then remove it.
__sm_remove_data(map, offset, sizeof(sm_idx_t) + sizeof(__sm_bitvec_t) * 2);
__sm_set_chunk_count(map, __sm_get_chunk_count(map) - 1);
*/
}
}
*(sm_idx_t *)p = start = aligned_idx;
@ -1714,7 +1699,7 @@ sparsemap_split(sparsemap_t *map, sparsemap_idx_t offset, sparsemap_t *other)
__sm_chunk_t d_chunk;
__sm_chunk_init(&d_chunk, dst);
if (__sm_chunk_reduce_capacity(&d_chunk, __sm_get_vector_aligned_offset(capacity - (offset % capacity)))) {
/* The __sm_chunk_t is empty then remove it.
/* TODO: The __sm_chunk_t is empty then remove it.
__sm_remove_data(map, offset, sizeof(sm_idx_t) + sizeof(__sm_bitvec_t) * 2);
__sm_set_chunk_count(map, __sm_get_chunk_count(map) - 1);
*/
@ -1741,7 +1726,7 @@ sparsemap_split(sparsemap_t *map, sparsemap_idx_t offset, sparsemap_t *other)
/* Reduce the capacity of the source-chunk effectively erases bits. */
size_t r = __sm_get_vector_aligned_offset(((offset - start) % capacity) + SM_BITS_PER_VECTOR);
if (__sm_chunk_reduce_capacity(&s_chunk, r)) {
/* The __sm_chunk_t is empty then remove it.
/* TODO: The __sm_chunk_t is empty then remove it.
__sm_remove_data(map, offset, sizeof(sm_idx_t) + sizeof(__sm_bitvec_t) * 2);
__sm_set_chunk_count(map, __sm_get_chunk_count(map) - 1);
*/
@ -1964,3 +1949,188 @@ sparsemap_span(sparsemap_t *map, sparsemap_idx_t idx, size_t len, bool value)
return offset;
}
#ifdef SPARSEMAP_TESTING
#include <qc.h>
static double
_tst_pow(double base, int exponent)
{
if (exponent == 0) {
return 1.0; // 0^0 is 1
} else if (base == 0.0) {
return 0.0; // 0 raised to any positive exponent is 0 (except 0^0)
} else if (base < 0.0 && (exponent & 1) != 0) {
// negative base with odd exponent, results in a negative
return -_tst_pow(-base, exponent);
}
double result = base;
for (unsigned int i = 1; i < exponent; i++) {
result *= base;
}
return result;
}
static char *
QCC_showChunk(void *value, int len)
{
static char buffer[(SM_FLAGS_PER_INDEX * 16) + (SM_BITS_PER_VECTOR * 64) + 16];
__sm_chunk_t *chunk = (__sm_chunk_t *)value;
__sm_bitvec_t desc = chunk->m_data[0];
if (!SM_IS_CHUNK_RLE(chunk)) {
char desc_str[SM_FLAGS_PER_INDEX + 1] = { 0 };
char *str = desc_str;
int mixed = 0;
for (int i = 0; i < SM_FLAGS_PER_INDEX; i++) {
uint8_t flag = SM_CHUNK_GET_FLAGS(desc, i);
switch (flag) {
case SM_PAYLOAD_NONE:
str += sprintf(str, "Ø");
break;
case SM_PAYLOAD_ONES:
str += sprintf(str, "1");
break;
case SM_PAYLOAD_ZEROS:
str += sprintf(str, "0");
break;
case SM_PAYLOAD_MIXED:
str += sprintf(str, "");
mixed++;
break;
default:
}
}
str = buffer + snprintf(buffer, sizeof(buffer), "%s :: ", desc_str);
for (int i = 0; i < mixed; i++) {
str += sprintf(str, "0x%lx%s", chunk->m_data[1 + i], i + 1 < mixed ? " " : "");
}
} else {
sprintf(buffer, "1»%zu", SM_CHUNK_RLE_LENGTH(chunk));
}
return buffer;
}
static void
QCC_freeChunkValue(void *value)
{
free(value);
}
QCC_GenValue *
QCC_genChunk()
{
bool rle = ((double)random() / (double)RAND_MAX) > 0.5;
if (rle) {
// Generate a chunk with the offset equal to the encoded run length.
sparsemap_idx_t from = 1, to = (sparsemap_idx_t)1ULL << (SM_BITS_PER_VECTOR - 2);
unsigned int len = ((unsigned int)random() % (to - from)) + from;
__sm_chunk_t *chunk = malloc(sizeof(__sm_chunk_t) + (sizeof(__sm_bitvec_t) * 2));
__sm_bitvec_t *v = (__sm_bitvec_t *)(chunk + sizeof(__sm_chunk_t));
chunk->m_data = v;
*v = ((((__sm_bitvec_t)1) << (SM_BITS_PER_VECTOR - 2)) | len);
assert(SM_IS_CHUNK_RLE(chunk));
assert(SM_CHUNK_RLE_LENGTH(chunk) == (unsigned int)len);
QCC_showChunk(chunk, len);
return QCC_initGenValue(chunk, 1, QCC_showChunk, QCC_freeChunkValue);
} else {
// Generate a chunk with the offset equal to the number of additional
// vectors (len) and a descriptor that matches that with random data.
unsigned int from = 0, to = SM_FLAGS_PER_INDEX;
unsigned int len = ((unsigned int)random() % (to - from)) + from;
unsigned int cut = ((unsigned int)random() % ((SM_FLAGS_PER_INDEX - len) - from)) + from;
__sm_chunk_t *chunk = malloc(sizeof(__sm_chunk_t) + (sizeof(__sm_bitvec_t) * (len + 2)));
chunk->m_data = (__sm_bitvec_t *)((uintptr_t)chunk + sizeof(__sm_chunk_t));
__sm_bitvec_t *desc = &chunk->m_data[0];
*desc = 0;
// Run through the flags (2 bits), we know that exactly `len` many flags
// must be SM_PAYLOAD_MIXED.
for (size_t i = 0, n = len; (i < SM_FLAGS_PER_INDEX - cut) && n; i++) {
size_t left = SM_FLAGS_PER_INDEX - cut - i;
double prob = (double)n / (double)left;
double dice = (double)random() / RAND_MAX;
if (dice < prob || left == n) {
*desc |= ((__sm_bitvec_t)SM_PAYLOAD_MIXED) << i;
size_t pos = (len - n);
chunk->m_data[1 + pos] = (uintptr_t)chunk + pos;
n--;
}
}
for (int i = 1; i < SM_FLAGS_PER_INDEX - cut; i++) {
uint8_t flag = SM_CHUNK_GET_FLAGS(*desc, i);
if (flag != SM_PAYLOAD_MIXED && ((double)random() / (double)RAND_MAX) > 0.5) {
*desc ^= ~((__sm_bitvec_t)SM_PAYLOAD_ONES << (i * 2));
}
}
//TODO: __sm_chunk_reduce_capacity(chunk, SM_CHUNK_MAX_CAPACITY - (cut * SM_BITS_PER_VECTOR));
assert(SM_IS_CHUNK_RLE(chunk) == false);
return QCC_initGenValue(chunk, 1, QCC_showChunk, QCC_freeChunkValue);
}
}
static size_t
_tst_sm_chunk_calc_vector_size(uint8_t b)
{
int count = 0;
for (int i = 0; i < 4; i++) {
if (((b >> (i * 2)) & 0x03) == 0x02) {
count++;
}
}
return count;
}
QCC_TestStatus
_tst_chunk_calc_vector_size_equality(QCC_GenValue **vals, int len, QCC_Stamp **stamp)
{
unsigned int a = *QCC_getValue(vals, 0, unsigned int *) % 256;
return _tst_sm_chunk_calc_vector_size(a) == __sm_chunk_calc_vector_size(a);
}
QCC_TestStatus
_tst_chunk_get_position(QCC_GenValue **vals, int len, QCC_Stamp **stamp)
{
size_t pos;
__sm_chunk_t *chunk = QCC_getValue(vals, 0, __sm_chunk_t *);
if (SM_IS_CHUNK_RLE(chunk)) {
for (size_t i = 0; i < SM_FLAGS_PER_INDEX; i++) {
pos = __sm_chunk_get_position(chunk, i);
if (pos != 0) {
return QCC_FAIL;
}
}
} else {
size_t mixed = 0;
for (size_t i = 0; i < SM_FLAGS_PER_INDEX; i++) {
uint8_t flag = SM_CHUNK_GET_FLAGS(*chunk->m_data, i);
switch (flag) {
case SM_PAYLOAD_MIXED:
pos = __sm_chunk_get_position(chunk, i);
if (chunk->m_data[1 + pos] != (uintptr_t)chunk + pos) {
return QCC_FAIL;
}
mixed++;
break;
case SM_PAYLOAD_ONES:
case SM_PAYLOAD_ZEROS:
pos = __sm_chunk_get_position(chunk, i);
if (pos != mixed) {
return QCC_FAIL;
}
break;
case SM_PAYLOAD_NONE:
default:
break;
}
}
}
return QCC_OK;
}
#endif

View file

@ -37,7 +37,7 @@ typedef struct QCC_Result {
int argumentsN;
} QCC_Result;
enum QCC_deref_type { NONE, LONG, INT, FLOAT, DOUBLE, CHAR };
enum QCC_deref_type { NONE, LONG, INT, FLOAT, DOUBLE, BYTE, CHAR };
void
QCC_init(int seed)
@ -73,6 +73,9 @@ QCC_showSimpleValue(void *value, enum QCC_deref_type dt, int maxsize, const char
case CHAR:
snprintf(vc, maxsize + 1, format, *(char *)value);
break;
case BYTE:
snprintf(vc, maxsize + 1, format, *(uint8_t *)value);
break;
default:
snprintf(vc, maxsize + 1, format, *(int *)value);
break;
@ -380,6 +383,49 @@ QCC_showSimpleArray(void *value, size_t elemSize, QCC_showValue showValue, int l
return str;
}
static char *
QCC_showByte(void *value, int len)
{
return QCC_showSimpleValue(value, BYTE, 3, "'%x'");
}
static char *
QCC_showArrayByte(void *value, int n)
{
return QCC_showSimpleArray(value, sizeof(long), QCC_showByte, n);
}
void
QCC_genByteAtR(uint8_t *b, uint8_t *from, uint8_t *to)
{
uint8_t r = (uint8_t)random() / (uint8_t)RAND_MAX;
*b = *from + (*to - *from) * r;
}
void
QCC_genByteAt(uint8_t *b)
{
*b = ((uint8_t)random() / (uint8_t)RAND_MAX) % UINT8_MAX;
}
QCC_GenValue *
QCC_genArrayByteLR(int len, long from, long to)
{
return QCC_genArrayOfR(len, (QCC_genRawR)QCC_genByteAtR, &from, &to, sizeof(long), QCC_showArrayByte, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayByteL(int len)
{
return QCC_genArrayOf(len, (QCC_genRaw)QCC_genByteAt, sizeof(long), QCC_showArrayByte, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayByte()
{
return QCC_genArrayOf(50, (QCC_genRaw)QCC_genByteAt, sizeof(long), QCC_showArrayByte, QCC_freeSimpleValue);
}
static char *
QCC_showArrayLong(void *value, int n)
{
@ -760,7 +806,7 @@ QCC_testForAll(int num, int maxFail, QCC_property prop, int genNum, ...)
}
if (succ == num) {
printf("%d test passed (%d)!\n", succ, fail);
//printf("%d test passed (%d)!\n", succ, fail);
QCC_printStamps(stamps, succ);
if (stamps)
QCC_freeStamp(stamps);

View file

@ -253,6 +253,10 @@ QCC_GenValue *QCC_genChar();
QCC_GenValue *QCC_genString();
QCC_GenValue *QCC_genStringL(int len);
QCC_GenValue *QCC_genArrayByte();
QCC_GenValue *QCC_genArrayByteL(int len);
QCC_GenValue *QCC_genArrayByteLR(int len, long from, long to);
QCC_GenValue *QCC_genArrayLong();
QCC_GenValue *QCC_genArrayLongL(int len);
QCC_GenValue *QCC_genArrayLongLR(int len, long from, long to);

View file

@ -1,5 +1,5 @@
/*
* smartmap is MIT-licensed, but for this file:
* sparsemap is MIT-licensed, but for this file:
*
* To the extent possible under law, the author(s) of this file have
* waived all copyright and related or neighboring rights to this
@ -10,16 +10,15 @@
#define MUNIT_NO_FORK (1)
#define MUNIT_ENABLE_ASSERT_ALIASES (1)
#include <common.h>
#include <errno.h>
#include <munit.h>
#include <qc.h>
#include <sparsemap.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sparsemap.h>
#include <common.h>
#include <munit.h>
#include <qc.h>
#define munit_free free
#if defined(_MSC_VER)
@ -89,7 +88,7 @@ test_api_new(const MunitParameter params[], void *data)
assert_ptr_not_null(map);
assert_true(map->m_capacity == 1024);
assert_true(map->m_data_used == sizeof(uint32_t));
assert_true((((uint8_t)map->m_data[0]) & 0x03) ==0x00);
assert_true((((uint8_t)map->m_data[0]) & 0x03) == 0x00);
munit_free(map);
@ -1268,6 +1267,39 @@ static MunitTest api_test_suite[] = {
};
// clang-format on
/* -------------------------- Quickcheck, Property Based Tests */
extern QCC_TestStatus _tst_chunk_calc_vector_size_equality(QCC_GenValue **vals, int len, QCC_Stamp **stamp);
static MunitResult
qc__sm_chunk_calc_vector_size(const MunitParameter params[], void *data)
{
(void)params;
(void)data;
return QCC_testForAll(1000, 1000, _tst_chunk_calc_vector_size_equality, 1, QCC_genInt);
}
extern QCC_GenValue *QCC_genChunk();
extern QCC_TestStatus _tst_chunk_get_position(QCC_GenValue **vals, int len, QCC_Stamp **stamp);
static MunitResult
qc__sm_chunk_get_position(const MunitParameter params[], void *data)
{
(void)params;
(void)data;
return QCC_testForAll(100, 1000, _tst_chunk_get_position, 1, QCC_genChunk);
}
// clang-format off
static MunitTest qc_test_suite[] = {
{ (char *)"/__sm_chunk_calc_vector_size", qc__sm_chunk_calc_vector_size, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
{ (char *)"/__sm_chunk_get_position", qc__sm_chunk_get_position, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL },
{ NULL, NULL, NULL, NULL, MUNIT_TEST_OPTION_NONE, NULL }
};
// clang-format off
/* -------------------------- Scale Tests */
static void *
@ -1682,6 +1714,7 @@ static MunitTest perf_test_suite[] = {
// clang-format off
static MunitSuite other_test_suite[] = {
{ "/api", api_test_suite, NULL, 1, MUNIT_SUITE_OPTION_NONE },
{ "/qc", qc_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 } };
@ -1704,6 +1737,8 @@ main(int argc, char *argv[MUNIT_ARRAY_PARAM(argc + 1)])
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
QCC_init(0);
return munit_suite_main(&main_test_suite, (void *)&info, argc, argv);
}