WIP: moving things around

This commit is contained in:
Gregory Burd 2024-07-16 06:20:28 -04:00
parent d99b1ac98d
commit 99035d8a0f
24 changed files with 1251 additions and 111 deletions

View file

@ -10,6 +10,7 @@
<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>

View file

@ -11,12 +11,11 @@ set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_C_OUTPUT_EXTENSION .o)
# Set source and header file locations
set(SOURCE_DIR src)
set(HEADER_DIR include)
set(SOURCE_DIR .)
set(HEADER_DIR . test)
set(COMMON_CMAKE_C_FLAGS "-Wall -Wextra -Wpedantic")
set(CMAKE_C_FLAGS_DEBUG "-DSPARSEMAP_DIAGNOSTIC -DDEBUG -g -O0")
set(CMAKE_C_FLAGS_DEBUG "-DSPARSEMAP_DIAGNOSTIC -DDEBUG -g -Og")
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")
@ -50,37 +49,37 @@ set_target_properties(sparsemap PROPERTIES
target_include_directories(sparsemap PRIVATE ${HEADER_DIR})
# Add ex_1 program
add_executable(ex_1 examples/ex_1.c tests/munit.c lib/common.c)
add_executable(ex_1 test/ex_1.c test/munit.c test/common.c)
target_link_libraries(ex_1 PRIVATE sparsemap)
target_include_directories(ex_1 PRIVATE ${HEADER_DIR})
add_custom_target(run_ex_1 COMMAND ex_1 WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# Add ex_2 program
add_executable(ex_2 examples/ex_2.c tests/munit.c lib/common.c)
add_executable(ex_2 test/ex_2.c test/munit.c test/common.c)
target_link_libraries(ex_2 PRIVATE sparsemap)
target_include_directories(ex_2 PRIVATE ${HEADER_DIR})
add_custom_target(run_ex_2 COMMAND ex_2 WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# Add ex_3 program
add_executable(ex_3 examples/ex_3.c tests/munit.c lib/common.c)
add_executable(ex_3 test/ex_3.c test/munit.c test/common.c)
target_link_libraries(ex_3 PRIVATE sparsemap)
target_include_directories(ex_3 PRIVATE ${HEADER_DIR})
add_custom_target(run_ex_3 COMMAND ex_3 WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# Add ex_4 program
add_executable(ex_4 examples/ex_4.c tests/munit.c lib/common.c)
add_executable(ex_4 test/ex_4.c test/munit.c test/common.c)
target_link_libraries(ex_4 PRIVATE sparsemap)
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 tests/test.c tests/munit.c lib/common.c)
add_executable(test test/test.c test/munit.c test/common.c)
target_link_libraries(test PRIVATE sparsemap)
target_include_directories(test PRIVATE ${HEADER_DIR})
add_custom_target(run_test COMMAND test WORKING_DIRECTORY ${CMAKE_BINARY_DIR})
# Add soak program
add_executable(soak tests/soak.c lib/common.c lib/tdigest.c lib/roaring.c)
add_executable(soak test/soak.c test/common.c test/tdigest.c test/roaring.c)
target_link_libraries(soak PRIVATE sparsemap)
target_include_directories(soak PRIVATE ${HEADER_DIR} lib)
target_link_libraries(soak PUBLIC m)

138
Makefile
View file

@ -1,106 +1,68 @@
# Build type (debug, sanitize, or release)
BUILD_TYPE := debug
OBJS = sparsemap.o
COMMON_CFLAGS = -Wall -Wextra -Wpedantic -std=c11 -fPIC -I.
CFLAGS_DEBUG = $(COMMON_CFLAGS) -Og -g -DSPARSEMAP_DIAGNOSTIC -DDEBUG
CFLAGS_SANITIZE = $(COMMON_CFLAGS) -Og -g -DSPARSEMAP_DIAGNOSTIC -DDEBUG -fsanitize=address,leak,object-size,pointer-compare,pointer-subtract,null,return,bounds,pointer-overflow,undefined -fsanitize-address-use-after-scope -std=c11
CFLAGS_RELEASE = $(COMMON_CFLAGS) -Ofast
CFLAGS_TEST = $(COMMON_CFLAGS) -Og -g -DDEBUG -I. -Itest
CFLAGS := $(if $(filter debug,$(BUILD_TYPE)),$(CFLAGS_DEBUG), \
$(if $(filter release,$(BUILD_TYPE)),$(CFLAGS_RELEASE), \
$(if $(filter sanitize,$(BUILD_TYPE)),$(CFLAGS_SANITIZE), \
$(error Unknown build type: $(BUILD_TYPE)))))
LDFLAGS = -lm
LDFLAGS_VERBOSE = -Wl,-v
SRCS = $(wildcard *.c)
OBJS = $(SRCS:.c=.o)
STATIC_LIB = libsparsemap.a
SHARED_LIB = libsparsemap.so
TEST_TARGETS = test/test test/soak test/ex_1 test/ex_2 test/ex_3 test/ex_4
TEST_SRCS = $(filter-out $(wildcard test/ex_*) test/midl.c $(TEST_TARGETS:=.c), $(wildcard test/*.c))
TEST_OBJS = $(TEST_SRCS:.c=.o)
TEST_DEPS = $(filter-out $(TEST_TARGETS:=.h), $(TEST_SRCS:.c=.h))
LIBS = -lm
#CFLAGS = -Wall -Wextra -Wpedantic -Of -std=c11 -Iinclude/ -fPIC
#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC
CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -O0 -g -std=c11 -Iinclude/ -fPIC
#CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Ofast -g -std=c11 -Iinclude/ -fPIC
#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC
#CFLAGS = -Wall -Wextra -Wpedantic -Ofast -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
# Targets
all: $(STATIC_LIB) $(SHARED_LIB)
TEST_FLAGS = -DDEBUG -Wall -Wextra -Wpedantic -O0 -g -std=c11 -Iinclude/ -Itests/ -fPIC
#TEST_FLAGS = -Wall -Wextra -Wpedantic -Ofast -g -std=c11 -Iinclude/ -Itests/ -fPIC
#TEST_FLAGS = -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 tests/soak
TEST_OBJS = tests/test.o lib/munit.o lib/tdigest.o lib/common.o
LIB_OBJS = lib/munit.o lib/tdigest.o lib/common.o lib/roaring.o
EXAMPLES = examples/ex_1 examples/ex_2 examples/ex_3 examples/ex_4
.PHONY: all shared static clean test examples mls
all: static shared
static: $(STATIC_LIB)
shared: $(SHARED_LIB)
info:
$(info TEST_SRCS: $(TEST_SRCS))
$(info TEST_OBJS: $(TEST_OBJS))
$(info TEST_DEPS: $(TEST_DEPS))
$(STATIC_LIB): $(OBJS)
ar rcs $(STATIC_LIB) $?
ar rcs libsparsemap.a $(OBJS)
$(SHARED_LIB): $(OBJS)
$(CC) $(CFLAGS) -o $@ $? -shared
$(CC) -shared -o libsparsemap.so $(OBJS) $(LDFLAGS)
examples: $(STATIC_LIB) $(EXAMPLES) $(TEST_OBJS)
check: $(TEST_TARGETS)
mls: examples/mls
test/test: $(TEST_OBJS) $(STATIC_LIB) test/test.o
$(CC) $^ $(LDFLAGS) -o $@
tests: $(TESTS)
test/soak: $(TEST_OBJS) $(STATIC_LIB) test/soak.o
$(CC) $^ $(LDFLAGS) -o $@
test: tests
env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/test
test/ex_1: test/ex_1.o $(STATIC_LIB)
$(CC) $^ $(LDFLAGS) -o $@
soak: tests
env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/soak
test/ex_2: test/ex_2.o $(STATIC_LIB)
$(CC) $^ $(LDFLAGS) -o $@
fuzzer: tests
env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/fuzzer ./crash.case
test/ex_3: test/ex_3.o $(STATIC_LIB)
$(CC) $^ $(LDFLAGS) -o $@
tests/test: $(TEST_OBJS) $(LIB_OBJS) $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
test/ex_4: test/ex_4.o $(STATIC_LIB)
$(CC) $^ $(LDFLAGS) -o $@
$(TEST_OBJS): $(TEST_SRCS) $(TEST_DEPS)
$(CC) $(CFLAGS_TEST) -c $(subst .o,.c,$@) -o $@
$(OBJS): $(SRCS)
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -f $(OBJS)
rm -f examples/main.c
rm -f $(STATIC_LIB) $(SHARED_LIB)
rm -f $(TESTS) tests/*.o
rm -f $(EXAMPLES) examples/*.o
format:
clang-format -i src/sparsemap.c include/sparsemap.h examples/ex_*.c tests/soak.c tests/test.c tests/midl.c lib/common.c include/common.h
# clang-format -i include/*.h src/*.c tests/*.c tests/*.h examples/*.c
%.o: src/%.c
$(CC) $(CFLAGS) -c -o $@ $^
lib/%.o: tests/%.c
$(CC) $(CFLAGS) -c -o $@ $^
tests/%.o: tests/%.c
$(CC) $(CFLAGS) -c -o $@ $^
examples/%.o: examples/%.c
$(CC) $(CFLAGS) -c -o $@ $^
examples/ex_1: $(LIB_OBJS) examples/ex_1.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
examples/ex_2: $(LIB_OBJS) examples/ex_2.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
examples/ex_3: $(LIB_OBJS) examples/ex_3.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
examples/ex_4: $(LIB_OBJS) examples/ex_4.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
tests/soak: $(LIB_OBJS) tests/soak.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
tests/fuzzer: $(LIB_OBJS) tests/fuzzer.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS) -DFUZZ_DEBUG
todo:
rg -i 'todo|gsb|abort'
# cp src/sparsemap.c /tmp && clang-tidy src/sparsemap.c -fix -fix-errors -checks="readability-braces-around-statements" -- -DDEBUG -DSPARSEMAP_DIAGNOSTIC -DSPARSEMAP_ASSERT -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC
# clear; make clean examples test && env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/test
# clear; make clean examples test && env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./examples/soak
rm -f libsparsemap.a libsparsemap.so $(OBJS) $(TEST_OBJS) \
test/test test/soak test/ex_1 test/ex_2 test/ex_3 test/ex_4

112
Makefile_ Normal file
View file

@ -0,0 +1,112 @@
OBJS = sparsemap.o
STATIC_LIB = libsparsemap.a
SHARED_LIB = libsparsemap.so
LIBS = -lm
#CFLAGS = -Wall -Wextra -Wpedantic -Of -std=c11 -Iinclude/ -fPIC
#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC
CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Wpedantic -O0 -g -std=c11 -Iinclude/ -fPIC
#CFLAGS = -DSPARSEMAP_DIAGNOSTIC -DDEBUG -Wall -Wextra -Ofast -g -std=c11 -Iinclude/ -fPIC
#CFLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC
#CFLAGS = -Wall -Wextra -Wpedantic -Ofast -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 = -DDEBUG -Wall -Wextra -Wpedantic -O0 -g -std=c11 -Iinclude/ -Ilib/ -fPIC
#TEST_FLAGS = -Wall -Wextra -Wpedantic -Ofast -g -std=c11 -Iinclude/ -Ilib/ -fPIC
#TEST_FLAGS = -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -Ilib/ -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 tests/soak
LIB_SRCS = $(wildcard lib/*.c)
LIB_OBJS = $(SRCS:.c=.o)
EXAMPLES = examples/ex_1 examples/ex_2 examples/ex_3 examples/ex_4
.PHONY: all shared static clean test examples mls
all: static shared
static: $(STATIC_LIB)
shared: $(SHARED_LIB)
$(STATIC_LIB): $(OBJS)
ar rcs $(STATIC_LIB) $?
$(SHARED_LIB): $(OBJS)
$(CC) $(CFLAGS) -o $@ $? -shared
examples: $(STATIC_LIB) $(LIB_OBJS) $(EXAMPLES)
mls: examples/mls
tests: $(TESTS)
test: tests
env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/test
soak: tests
env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/soak
fuzzer: tests
env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/fuzzer ./crash.case
lib/common.o: lib/common.h
lib/munit.o: lib/munit.h
lib/tdigest.o: lib/tdigest.h
lib/roaring.o: lib/roaring.h
lib/qc.o: lib/qc.h
tests/test: $(LIB_OBJS) $(STATIC_LIB) tests/test.o
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
clean:
rm -f $(OBJS)
rm -f examples/main.c
rm -f $(STATIC_LIB) $(SHARED_LIB)
rm -f $(TESTS) tests/*.o lib/*.o
rm -f $(EXAMPLES) examples/*.o
format:
clang-format -i src/sparsemap.c include/sparsemap.h examples/ex_*.c tests/soak.c tests/test.c tests/midl.c lib/common.c include/common.h
# clang-format -i include/*.h src/*.c tests/*.c tests/*.h examples/*.c
%.o: src/%.c
$(CC) $(CFLAGS) -c -o $@ $^
lib/%.o: lib/%.c
$(CC) $(TEST_CFLAGS) -c -o $@ $^
tests/%.o: tests/%.c
$(CC) $(TEST_CFLAGS) -c -o $@ $^
examples/%.o: examples/%.c
$(CC) $(TEST_CFLAGS) -c -o $@ $^
examples/ex_1: $(TEST_OBJS) examples/ex_1.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
examples/ex_2: $(TEST_OBJS) examples/ex_2.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
examples/ex_3: $(TEST_OBJS) examples/ex_3.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
examples/ex_4: $(TEST_OBJS) examples/ex_4.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
tests/soak: $(TEST_OBJS) tests/soak.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS)
tests/fuzzer: $(TEST_OBJS) tests/fuzzer.o $(STATIC_LIB)
$(CC) $^ $(LIBS) -o $@ $(TEST_FLAGS) -DFUZZ_DEBUG
todo:
rg -i 'todo|gsb|abort'
# cp src/sparsemap.c /tmp && clang-tidy src/sparsemap.c -fix -fix-errors -checks="readability-braces-around-statements" -- -DDEBUG -DSPARSEMAP_DIAGNOSTIC -DSPARSEMAP_ASSERT -Wall -Wextra -Wpedantic -Og -g -std=c11 -Iinclude/ -fPIC
# clear; make clean examples test && env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./tests/test
# clear; make clean examples test && env ASAN_OPTIONS=detect_leaks=1 LSAN_OPTIONS=verbosity=1:log_threads=1 ./examples/soak

View file

@ -18,8 +18,8 @@
#endif
#endif
#include "../include/common.h"
#include "../include/sparsemap.h"
#include <common.h>
#include <sparsemap.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"
@ -122,7 +122,7 @@ shuffle(int *array, size_t n)
}
}
int
static int
compare_ints(const void *a, const void *b)
{
return *(const int *)a - *(const int *)b;

View file

@ -1,5 +1,5 @@
#include "../include/sparsemap.h"
#include <sparsemap.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"

View file

@ -4,7 +4,7 @@
#include <stdint.h>
#include <stdio.h>
#include "../include/sparsemap.h"
#include <sparsemap.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"

View file

@ -3,7 +3,7 @@
#include <stdio.h>
#include <stdlib.h>
#include "../include/sparsemap.h"
#include <sparsemap.h>
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wvariadic-macros"

785
test/qc.c Normal file
View file

@ -0,0 +1,785 @@
/********************************************************************
* Copyright (c) 2014, Andrea Zito
* All rights reserved.
*
* License: BSD3
********************************************************************/
#include <stddef.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "qc.h"
// TODO: fix these...
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wimplicit-function-declaration"
#pragma GCC diagnostic ignored "-Wunused-parameter"
#pragma GCC diagnostic ignored "-Wint-conversion"
#pragma GCC diagnostic ignored "-Wpedantic"
typedef void (*QCC_genRaw)(void *ptr);
typedef void (*QCC_genRawR)(void *ptr, void *from, void *to);
struct QCC_Stamp {
char *label;
int n;
struct QCC_Stamp *next;
};
typedef struct QCC_Result {
QCC_TestStatus status;
QCC_Stamp *stamps;
QCC_GenValue **arguments;
int argumentsN;
} QCC_Result;
enum QCC_deref_type { NONE, LONG, INT, FLOAT, DOUBLE, CHAR };
void
QCC_init(int seed)
{
if (seed) {
srandom(seed);
} else {
srandom(time(NULL));
}
}
/***********************************************************************
* Generators helper functions
***********************************************************************/
static char *
QCC_showSimpleValue(void *value, enum QCC_deref_type dt, int maxsize, const char *format)
{
char *vc = malloc(sizeof(char) * (maxsize + 1));
switch (dt) {
case LONG:
snprintf(vc, maxsize + 1, format, *(long *)value);
break;
case INT:
snprintf(vc, maxsize + 1, format, *(int *)value);
break;
case FLOAT:
snprintf(vc, maxsize + 1, format, *(float *)value);
break;
case DOUBLE:
snprintf(vc, maxsize + 1, format, *(double *)value);
break;
case CHAR:
snprintf(vc, maxsize + 1, format, *(char *)value);
break;
default:
snprintf(vc, maxsize + 1, format, *(int *)value);
break;
}
vc[maxsize] = 0;
return vc;
}
static void
QCC_freeSimpleValue(void *value)
{
free(value);
}
QCC_GenValue *
QCC_initGenValue(void *value, int n, QCC_showValue show, QCC_freeValue free)
{
QCC_GenValue *gv = malloc(sizeof(QCC_GenValue));
*gv = (QCC_GenValue) { .value = value, .n = n, .show = show, .free = free };
return gv;
}
/***********************************************************************
* Generators implementations
***********************************************************************/
static char *
QCC_showLong(void *value, int len)
{
return QCC_showSimpleValue(value, LONG, 21, "%ld");
}
void
QCC_genLongAtR(long *l, long *from, long *to)
{
long _from = *from;
long _to = *to;
unsigned long n = _to - _from;
if (n > RAND_MAX) {
_from = _from + n / 2 - RAND_MAX / 2;
_to = _from + n / 2 + RAND_MAX / 2;
n = _to - _from;
}
*l = (random() % n) + _from;
}
void
QCC_genLongAt(long *l)
{
long from = QCC_LONG_FROM;
long to = QCC_LONG_TO;
QCC_genLongAtR(l, &from, &to);
}
QCC_GenValue *
QCC_genLongR(long from, long to)
{
long *v = malloc(sizeof(long));
QCC_genLongAtR(v, &from, &to);
return QCC_initGenValue(v, 1, QCC_showLong, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genLong()
{
return QCC_genLongR(QCC_LONG_FROM, QCC_LONG_TO);
}
static char *
QCC_showInt(void *value, int len)
{
return QCC_showSimpleValue(value, INT, 11, "%d");
}
void
QCC_genIntAtR(int *i, int *from, int *to)
{
int n = *to - *from;
*i = (random() % n) + *from;
}
void
QCC_genIntAt(int *i)
{
int from = QCC_INT_FROM;
int to = QCC_INT_TO;
QCC_genIntAtR(i, &from, &to);
}
QCC_GenValue *
QCC_genIntR(int from, int to)
{
int *v = malloc(sizeof(int));
QCC_genIntAtR(v, &from, &to);
return QCC_initGenValue(v, 1, QCC_showInt, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genInt()
{
return QCC_genIntR(QCC_INT_FROM, QCC_INT_TO);
}
static char *
QCC_showDouble(void *value, int len)
{
return QCC_showSimpleValue(value, DOUBLE, 50, "%.12e");
}
void
QCC_genDoubleAtR(double *d, double *from, double *to)
{
double r = (double)random() / (double)RAND_MAX;
*d = *from + (*to - *from) * r;
}
void
QCC_genDoubleAt(double *d)
{
double from = QCC_DOUBLE_FROM;
double to = QCC_DOUBLE_TO;
QCC_genDoubleAtR(d, &from, &to);
}
QCC_GenValue *
QCC_genDoubleR(double from, double to)
{
double *v = malloc(sizeof(double));
QCC_genDoubleAtR(v, &from, &to);
return QCC_initGenValue(v, 1, QCC_showDouble, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genDouble()
{
return QCC_genDoubleR(QCC_DOUBLE_FROM, QCC_DOUBLE_TO);
}
static char *
QCC_showFloat(void *value, int len)
{
return QCC_showSimpleValue(value, FLOAT, 50, "%.12e");
}
void
QCC_genFloatAtR(float *f, float *from, float *to)
{
float r = (float)random() / (float)RAND_MAX;
*f = *from + (*to - *from) * r;
}
void
QCC_genFloatAt(float *f)
{
float from = QCC_FLOAT_FROM;
float to = QCC_FLOAT_TO;
QCC_genFloatAtR(f, &from, &to);
}
QCC_GenValue *
QCC_genFloatR(float from, float to)
{
float *v = malloc(sizeof(float));
QCC_genFloatAtR(v, &from, &to);
return QCC_initGenValue(v, 1, QCC_showFloat, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genFloat()
{
return QCC_genFloatR(QCC_FLOAT_FROM, QCC_FLOAT_TO);
}
static char *
QCC_showBoolean(void *value, int len)
{
QCC_Boolean *b = (QCC_Boolean *)value;
if (*b) {
return strdup("TRUE");
} else {
return strdup("FALSE");
}
}
void
QCC_genBooleanAt(QCC_Boolean *b)
{
double r = (double)random() / (double)RAND_MAX;
*b = r > 0.5 ? QCC_TRUE : QCC_FALSE;
}
QCC_GenValue *
QCC_genBoolean()
{
QCC_Boolean *v = malloc(sizeof(QCC_Boolean));
QCC_genBooleanAt(v);
return QCC_initGenValue(v, 1, QCC_showBoolean, QCC_freeSimpleValue);
}
static char *
QCC_showChar(void *value, int len)
{
return QCC_showSimpleValue(value, CHAR, 3, "'%c'");
}
void
QCC_genCharAt(char *c)
{
*c = (char)(random() % 93) + 33;
}
QCC_GenValue *
QCC_genChar()
{
char *v = malloc(sizeof(char));
QCC_genCharAt(v);
return QCC_initGenValue(v, 1, QCC_showChar, QCC_freeSimpleValue);
}
/***********************************************************************
* Array generators implementations
***********************************************************************/
QCC_GenValue *
QCC_genArrayOf(int len, QCC_genRaw elemGen, size_t elemSize, QCC_showValue show, QCC_freeValue free)
{
int n = random() % len;
uint8_t *arr = malloc(n * elemSize);
int p, i;
for (i = 0, p = 0; i < n; i++, p += elemSize)
elemGen(arr + p);
return QCC_initGenValue(arr, n, show, free);
}
QCC_GenValue *
QCC_genArrayOfR(int len, QCC_genRawR elemGen, void *from, void *to, size_t elemSize, QCC_showValue show, QCC_freeValue free)
{
int n = random() % len;
uint8_t *arr = malloc(n * elemSize);
int p, i;
for (i = 0, p = 0; i < n; i++, p += elemSize)
elemGen(arr + p, from, to);
return QCC_initGenValue(arr, n, show, free);
}
static char *
QCC_showString(void *value, int len)
{
return QCC_showSimpleValue(value, NONE, len, "%s");
}
QCC_GenValue *
QCC_genStringL(int len)
{
QCC_GenValue *s = QCC_genArrayOf(len, (QCC_genRaw)QCC_genCharAt, sizeof(char), QCC_showString, QCC_freeSimpleValue);
((char *)s->value)[s->n - 1] = '\0';
return s;
}
QCC_GenValue *
QCC_genString()
{
return QCC_genStringL(50);
}
static char *
QCC_showSimpleArray(void *value, size_t elemSize, QCC_showValue showValue, int len)
{
char **valStr = malloc(sizeof(char *) * len);
int valStrLen = 0;
int i;
for (i = 0; i < len; i++) {
valStr[i] = showValue(((uint8_t *)value) + (i * elemSize), 1);
valStrLen += strlen(valStr[i]);
}
int totStrLen = valStrLen + 2 + 2 * len + 1;
char *str = malloc(sizeof(char) * totStrLen);
sprintf(str, "[");
int currLen = 1;
for (i = 0; i < len; i++) {
if (i == 0) {
sprintf(str + currLen, "%s", valStr[i]);
} else {
sprintf(str + currLen, ", %s", valStr[i]);
currLen += 2;
}
currLen += strlen(valStr[i]);
free(valStr[i]);
}
sprintf(str + currLen, "]");
free(valStr);
return str;
}
static char *
QCC_showArrayLong(void *value, int n)
{
return QCC_showSimpleArray(value, sizeof(long), QCC_showLong, n);
}
QCC_GenValue *
QCC_genArrayLongLR(int len, long from, long to)
{
return QCC_genArrayOfR(len, (QCC_genRawR)QCC_genLongAtR, &from, &to, sizeof(long), QCC_showArrayLong, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayLongL(int len)
{
return QCC_genArrayOf(len, (QCC_genRaw)QCC_genLongAt, sizeof(long), QCC_showArrayLong, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayLong()
{
return QCC_genArrayOf(50, (QCC_genRaw)QCC_genLongAt, sizeof(long), QCC_showArrayLong, QCC_freeSimpleValue);
}
static char *
QCC_showArrayInt(void *value, int n)
{
return QCC_showSimpleArray(value, sizeof(int), QCC_showInt, n);
}
QCC_GenValue *
QCC_genArrayIntLR(int len, int from, int to)
{
return QCC_genArrayOfR(len, (QCC_genRawR)QCC_genIntAtR, &from, &to, sizeof(int), QCC_showArrayInt, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayIntL(int len)
{
return QCC_genArrayOf(len, (QCC_genRaw)QCC_genIntAt, sizeof(int), QCC_showArrayInt, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayInt()
{
return QCC_genArrayOf(50, (QCC_genRaw)QCC_genIntAt, sizeof(int), QCC_showArrayInt, QCC_freeSimpleValue);
}
static char *
QCC_showArrayDouble(void *value, int n)
{
return QCC_showSimpleArray(value, sizeof(double), QCC_showDouble, n);
}
QCC_GenValue *
QCC_genArrayDoubleLR(int len, double from, double to)
{
return QCC_genArrayOfR(len, (QCC_genRawR)QCC_genDoubleAtR, &from, &to, sizeof(double), QCC_showArrayDouble, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayDoubleL(int len)
{
return QCC_genArrayOf(len, (QCC_genRaw)QCC_genDoubleAt, sizeof(double), QCC_showArrayDouble, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayDouble()
{
return QCC_genArrayOf(50, (QCC_genRaw)QCC_genDoubleAt, sizeof(double), QCC_showArrayDouble, QCC_freeSimpleValue);
}
static char *
QCC_showArrayFloat(void *value, int n)
{
return QCC_showSimpleArray(value, sizeof(float), QCC_showFloat, n);
}
QCC_GenValue *
QCC_genArrayFloatLR(int len, float from, float to)
{
return QCC_genArrayOfR(len, (QCC_genRawR)QCC_genFloatAtR, &from, &to, sizeof(float), QCC_showArrayFloat, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayFloatL(int len)
{
return QCC_genArrayOf(len, (QCC_genRaw)QCC_genFloatAt, sizeof(float), QCC_showArrayFloat, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayFloat()
{
return QCC_genArrayOf(50, (QCC_genRaw)QCC_genFloatAt, sizeof(float), QCC_showArrayFloat, QCC_freeSimpleValue);
}
static char *
QCC_showArrayBoolean(void *value, int n)
{
return QCC_showSimpleArray(value, sizeof(QCC_Boolean), QCC_showBoolean, n);
}
QCC_GenValue *
QCC_genArrayBooleanL(int len)
{
return QCC_genArrayOf(len, (QCC_genRaw)QCC_genBooleanAt, sizeof(QCC_Boolean), QCC_showArrayBoolean, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayBoolean()
{
return QCC_genArrayOf(50, (QCC_genRaw)QCC_genBooleanAt, sizeof(QCC_Boolean), QCC_showArrayBoolean, QCC_freeSimpleValue);
}
static char *
QCC_showArrayChar(void *value, int n)
{
return QCC_showSimpleArray(value, sizeof(char), QCC_showChar, n);
}
QCC_GenValue *
QCC_genArrayCharL(int len)
{
return QCC_genArrayOf(len, (QCC_genRaw)QCC_genCharAt, sizeof(char), QCC_showArrayChar, QCC_freeSimpleValue);
}
QCC_GenValue *
QCC_genArrayChar()
{
return QCC_genArrayOf(50, (QCC_genRaw)QCC_genCharAt, sizeof(char), QCC_showArrayChar, QCC_freeSimpleValue);
}
/***********************************************************************
* Convenience functions
***********************************************************************/
QCC_TestStatus
QCC_not(QCC_TestStatus propStatus)
{
switch (propStatus) {
case QCC_OK:
return QCC_FAIL;
case QCC_FAIL:
return QCC_OK;
case QCC_NOTHING:
return QCC_NOTHING;
default:
return QCC_FAIL;
}
}
QCC_TestStatus
QCC_and(QCC_TestStatus prop1Status, QCC_TestStatus prop2Status)
{
switch (prop1Status) {
case QCC_OK:
return prop2Status;
case QCC_FAIL:
return QCC_FAIL;
case QCC_NOTHING:
return QCC_NOTHING;
default:
return QCC_FAIL;
}
}
QCC_TestStatus
QCC_or(QCC_TestStatus prop1Status, QCC_TestStatus prop2Status)
{
switch (prop1Status) {
case QCC_OK:
return QCC_OK;
case QCC_FAIL:
case QCC_NOTHING:
return prop2Status;
default:
return QCC_FAIL;
}
}
QCC_TestStatus
QCC_xor(QCC_TestStatus prop1Status, QCC_TestStatus prop2Status)
{
switch (prop1Status) {
case QCC_OK:
return QCC_not(prop2Status);
case QCC_FAIL:
return prop2Status;
case QCC_NOTHING:
return QCC_NOTHING;
default:
return QCC_FAIL;
}
}
/***********************************************************************
* Categorization function
***********************************************************************/
void
QCC_freeStamp(QCC_Stamp *stamps)
{
QCC_Stamp *tstamps;
QCC_Stamp *curr;
for (tstamps = stamps; tstamps != NULL;) {
curr = tstamps;
tstamps = tstamps->next;
free(curr->label);
free(curr);
}
}
static void
QCC_insertOrdStamp(QCC_Stamp **stamps, QCC_Stamp *s)
{
QCC_Stamp *new = malloc(sizeof(QCC_Stamp));
*new = (QCC_Stamp) { .label = strdup(s->label), .n = s->n, .next = NULL };
QCC_Stamp *tstamp = *stamps;
QCC_Stamp **pre = stamps;
while (tstamp) {
if (tstamp->n < new->n) {
break;
} else {
pre = &tstamp->next;
tstamp = tstamp->next;
}
}
*pre = new;
new->next = tstamp;
}
static QCC_Stamp *
QCC_sortStamp(QCC_Stamp *stamps)
{
QCC_Stamp *sortedStamps = NULL;
QCC_Stamp *tstamp;
for (tstamp = stamps; tstamp != NULL; tstamp = tstamp->next) {
QCC_insertOrdStamp(&sortedStamps, tstamp);
}
return sortedStamps;
}
static void
QCC_labelN(QCC_Stamp **stamps, char *label, int n)
{
QCC_Stamp *ptr = *stamps;
QCC_Stamp *pre = NULL;
QCC_Stamp *new;
while (ptr) {
if (strcmp(ptr->label, label) == 0) {
(ptr->n)++;
return;
}
pre = ptr;
ptr = ptr->next;
}
new = malloc(sizeof(QCC_Stamp));
*new = (QCC_Stamp) { .label = strdup(label), .n = 1, .next = NULL };
if (pre) {
pre->next = new;
} else {
*stamps = new;
}
}
void
QCC_label(QCC_Stamp **stamps, char *label)
{
return QCC_labelN(stamps, label, 1);
}
static void
QCC_mergeLabels(QCC_Stamp **dst, QCC_Stamp *src)
{
for (; src != NULL; src = src->next)
QCC_labelN(dst, src->label, src->n);
}
/***********************************************************************
* Testing functions
***********************************************************************/
void
QCC_freeGenValues(QCC_GenValue **arguments, int argumentsN)
{
int i;
for (i = 0; i < argumentsN; i++) {
arguments[i]->free(arguments[i]->value);
free(arguments[i]);
}
if (arguments)
free(arguments);
}
void
QCC_freeResult(QCC_Result *res)
{
QCC_freeStamp(res->stamps);
QCC_freeGenValues(res->arguments, res->argumentsN);
}
QCC_Result
QCC_vforAll(QCC_property prop, int genNum, va_list genP)
{ // QCC_gen *genLst,
QCC_GenValue **vals = NULL;
if (genNum) {
int i;
vals = malloc(sizeof(QCC_GenValue *) * genNum);
for (i = 0; i < genNum; i++) {
QCC_gen gen = va_arg(genP, QCC_gen);
vals[i] = gen();
}
}
QCC_Stamp *stamps = NULL;
QCC_TestStatus status = prop(vals, genNum, &stamps);
return (QCC_Result) { .status = status, .stamps = stamps, .arguments = vals, .argumentsN = genNum };
}
QCC_Result
QCC_forAll(QCC_property prop, int genNum, ...)
{ // QCC_gen *genLst,
va_list genP;
QCC_Result res;
va_start(genP, genNum);
res = QCC_vforAll(prop, genNum, genP);
va_end(genP);
return res;
}
static void
QCC_printStamps(QCC_Stamp *stamps, int n)
{
QCC_Stamp *sortedStamps = QCC_sortStamp(stamps);
QCC_Stamp *tstamps;
for (tstamps = sortedStamps; tstamps != NULL; tstamps = tstamps->next)
printf("%.2f%%\t%s\n", (tstamps->n / (float)n) * 100, tstamps->label);
if (sortedStamps)
QCC_freeStamp(sortedStamps);
}
static void
QCC_printArguments(QCC_GenValue **arguments, int argumentsN)
{
int i;
for (i = 0; i < argumentsN; i++) {
char *s = arguments[i]->show(arguments[i]->value, arguments[i]->n);
printf("%s\n", s);
free(s);
}
}
int
QCC_testForAll(int num, int maxFail, QCC_property prop, int genNum, ...)
{
va_list genP;
int succ = 0;
int fail = 0;
QCC_Result res = { .status = QCC_OK };
QCC_Stamp *stamps = NULL;
while (succ < num && fail < maxFail) {
va_start(genP, genNum);
res = QCC_vforAll(prop, genNum, genP);
va_end(genP);
if (res.status == QCC_FAIL) {
break;
} else {
if (res.status == QCC_OK) {
succ++;
QCC_mergeLabels(&stamps, res.stamps);
} else
fail++;
QCC_freeResult(&res);
}
}
if (succ == num) {
printf("%d test passed (%d)!\n", succ, fail);
QCC_printStamps(stamps, succ);
if (stamps)
QCC_freeStamp(stamps);
return 0;
} else if (res.status == QCC_FAIL) {
printf("Falsifiable after %d test\n", succ + 1);
QCC_printArguments(res.arguments, res.argumentsN);
QCC_freeResult(&res);
if (stamps)
QCC_freeStamp(stamps);
return 1;
} else if (fail >= maxFail) {
printf("Gave up after %d tests!\n", succ);
QCC_printStamps(stamps, succ);
if (stamps)
QCC_freeStamp(stamps);
return -1;
}
return 0;
}
#pragma GCC diagnostic pop

280
test/qc.h Normal file
View file

@ -0,0 +1,280 @@
/********************************************************************
* Copyright (c) 2014, Andrea Zito
* All rights reserved.
*
* License: BSD3
********************************************************************/
#ifndef QUICKCHECK4C_C
#define QUICKCHECK4C_C
#include <stdarg.h>
#include <stdlib.h>
/* Default ranges used for type generation */
#define QCC_LONG_FROM -RAND_MAX / 2
#define QCC_LONG_TO RAND_MAX / 2
#define QCC_INT_FROM -RAND_MAX / 2
#define QCC_INT_TO RAND_MAX / 2
#define QCC_DOUBLE_FROM ((double)-(RAND_MAX / 2))
#define QCC_DOUBLE_TO ((double)(RAND_MAX / 2))
#define QCC_FLOAT_FROM ((float)-(RAND_MAX / 2))
#define QCC_FLOAT_TO ((float)(RAND_MAX / 2))
/**
* Explicit definition of a boolean type compatible with
* normal C boolean interpretation.
*/
typedef enum { QCC_TRUE = 1, QCC_FALSE = 0 } QCC_Boolean;
/**
* Enumerator defining the evaluation of a property.
* QCC_OK represent a satisfied property.
* QCC_FAIL represent a falsified property.
* QCC_NOTHING indicates a property that didn't fail
* but should NOT be considered in the successes count or
* categorization (used by QCC_IMPLY)
*/
typedef enum { QCC_OK = 1, QCC_FAIL = 0, QCC_NOTHING = -1 } QCC_TestStatus;
/**
* Convenince macro to extract generated values inside a property.
* Es: int a = *QCC_getValue(vals, 0, int*)
*
* @param vals A QCC_GenValue array
* @param idx Index of the value to extract
* @param type Type of the generated value
*/
#define QCC_getValue(vals, idx, type) ((type)vals[idx]->value)
/**
* Signature of function used to represent values in a human readable
* fashion.
* Calling this function allocates memory that must be freed by the caller.
*
* @param value Pointer to the value to show
* @param len Lenght of the data (used to keep track of array lengths)
* @return String representation of the value.
*/
typedef char *(*QCC_showValue)(void *value, int len);
/**
* Signature of function used to free generated values.
*
* @param value Pointer to the value to free
*/
typedef void (*QCC_freeValue)(void *value);
/**
* Structure defining a generated value.
* It specifies the value itself (alongside its length in case
* of arrays), a function pointer for getting a human readable
* string representation of the value and a function pointer to
* free the memory allocated for the value.
*
* @param value Pointer to the memory allocated for the value
* @param n Length of the value (1 for simple types, length for arrays)
* @param show Function to get string representation of the value
* @param free Function to free the memory of the value
*/
typedef struct QCC_GenValue {
void *value;
int n;
QCC_showValue show;
QCC_freeValue free;
} QCC_GenValue;
/**
* Opaque structure used to categorize test instances.
* See QCC_property and QCC_label.
*/
typedef struct QCC_Stamp QCC_Stamp;
/**
* Signature of functions used to generate random values
*/
typedef QCC_GenValue *(*QCC_gen)();
/**
* Signature of property functions.
*
* @param vals Array of generated random values
* @param len Number of generated values
* @param stamp Used to categorize test instances via QCC_label
*/
typedef QCC_TestStatus (*QCC_property)(QCC_GenValue **vals, int len, QCC_Stamp **stamps);
/**
* Implements logic implication.
* The implication is satisfied if both the precondition and the property are
* satisfied.
* In case the precondition is not satisfied the special QCC_NOTHING value is
* returned, indicating that the current test should not be considered as a
* success.
*
* @param precondition A boolean condition
* @param property A QCC_property to evaluate iff the precondition is satisfied
* @return QCC_TestStatus
*/
#define QCC_imply(precondition, property) precondition ? property : QCC_NOTHING
/**
* Convenience function to express property conjunction.
* The function returns:
* - QCC_OK iff prop1Status == prop2Status == QCC_OK
* - QCC_FAIL iff prop1Status == QCC_FAIL || prop2Status == QCC_FAIL
* - QCC_NOTHING iff prop1Status != QCC_FAIL && prop2Status != QCC_FAIL &&
* (prop1Status == QCC_NOTHING || prop2Status == QCC_NOTHING)
*
* @param prop1Status The evaluation status of property 1
* @param prop2Status The evaluation status of property 2
* @return The evaluation status of the conjunction of property 1 and property 2
*/
QCC_TestStatus QCC_and(QCC_TestStatus prop1Status, QCC_TestStatus prop2Status);
/**
* Convenience function to express property disjunction.
* The function returns:
* - QCC_OK iff prop1Status == QCC_OK || prop2Status == QCC_OK
* - QCC_FAIL iff prop1Status == QCC_FAIL && prop2Status == QCC_FAIL
* - QCC_NOTHING iff prop1Status != QCC_OK && prop2Status != QCC_OK &&
* (prop1Status == QCC_NOTHING || prop2Status == QCC_NOTHING)
*
* @param prop1Status The evaluation status of property 1
* @param prop2Status The evaluation status of property 2
* @return The evaluation status of the disjunction of property 1 and property 2
*/
QCC_TestStatus QCC_or(QCC_TestStatus prop1Status, QCC_TestStatus prop2Status);
/**
* Convenience function to express property exclusive disjunction.
* The function returns:
* - QCC_OK iff (prop1Status == QCC_OK && prop2Status == QCC_FAIL) ||
* (prop1Status == QCC_FAIL && prop2Status == QCC_OK)
* - QCC_FAIL iff prop1Status == prop2Status != QCC_NOTHING
* - QCC_NOTHING iff prop1Status == QCC_NOTHING || prop2Status = QCC_NOTHING
*
* @param prop1Status The evaluation status of property 1
* @param prop2Status The evaluation status of property 2
* @return The evaluation status of the exclusive disjunction of property 1 and
* property 2
*/
QCC_TestStatus QCC_xor(QCC_TestStatus prop1Status, QCC_TestStatus prop2Status);
/**
* Convenience function to express property negation.
* The function returns:
* - QCC_OK iff propStatus == QCC_FAIL
* - QCC_FAIL iff propStatus == QCC_OK
* - QCC_NOTHING iff propStatus == QCC_NOTHING
*/
QCC_TestStatus QCC_not(QCC_TestStatus propStatus);
/**
* Initialize the random generator using a specific seed.
*
* @param seed The seed to use or 0 to automatically select seed
*/
void QCC_init(int seed);
/**
* Adds a label to the test stamps.
*
* @param stamps Stamps associated to the current test
* @param label Label to add to the test stamps
*/
void QCC_label(QCC_Stamp **stamps, char *label);
/**
* Test a property for num times allowing at most maxFail unsuccesful
* argument generation.
*
* If all num test succede, the function outputs a success string and
* return 0. If argument generation fails maxFail time before a success
* string is printed reporting the number of success test cases and return -1.
*
* In both cases any label label gathered during test evaluation is printed
* alongside its distribution.
*
* If a set of arguments falsifying the property is found, the testing is
* interrupted immediately and a failure string is printed alongside the
* set of arguments which caused the failure.
*
* @parm num Number of successful test to perform
* @parm maxFail Maximum number of unsuccessful argument generation
* (i.e. unsatisfied implication precondition)
* @parm prop Property to test
* @parm genNum Number of generators specified as vararg
* @param ... genNum QCC_gen function to use as generators
* @return 0 (all num test passed),
* -1 (gave up after maxFail unsuccessful arguments generation),
* 1 (property falsified)
*/
int QCC_testForAll(int num, int maxFail, QCC_property prop, int genNum, ...);
/*************************************************************
* Helper function for generator definitions
*************************************************************/
/**
* Initialize a QCC_GenValue using the specified parameters
*
* @param value Raw generated balue
* @param n Length of the value in case of an array (1 should be used otherwise)
* @param show Pointer to a QCC_ShowValue function to use for displaying the raw
* value
* @param free Pointer to a QCC_FreeValue function to use for free the raw value
* memory
* @return Initialized QCC_GenValue
*/
QCC_GenValue *QCC_initGenValue(void *value, int n, QCC_showValue show, QCC_freeValue free);
/*************************************************************
* Simple types generators
*************************************************************/
QCC_GenValue *QCC_genLong();
QCC_GenValue *QCC_genLongR(long from, long to);
QCC_GenValue *QCC_genInt();
QCC_GenValue *QCC_genIntR(int from, int to);
QCC_GenValue *QCC_genDouble();
QCC_GenValue *QCC_genDoubleR(double from, double to);
QCC_GenValue *QCC_genFloat();
QCC_GenValue *QCC_genFloatR(float from, float to);
QCC_GenValue *QCC_genBoolean();
QCC_GenValue *QCC_genChar();
/*************************************************************
* Array types generators
*************************************************************/
QCC_GenValue *QCC_genString();
QCC_GenValue *QCC_genStringL(int len);
QCC_GenValue *QCC_genArrayLong();
QCC_GenValue *QCC_genArrayLongL(int len);
QCC_GenValue *QCC_genArrayLongLR(int len, long from, long to);
QCC_GenValue *QCC_genArrayInt();
QCC_GenValue *QCC_genArrayIntL(int len);
QCC_GenValue *QCC_genArrayIntLR(int len, int from, int to);
QCC_GenValue *QCC_genArrayDouble();
QCC_GenValue *QCC_genArrayDoubleL(int len);
QCC_GenValue *QCC_genArrayDoubleLR(int len, double from, double to);
QCC_GenValue *QCC_genArrayFloat();
QCC_GenValue *QCC_genArrayFloatL(int len);
QCC_GenValue *QCC_genArrayFloatLR(int len, float from, float to);
QCC_GenValue *QCC_genArrayBoolean();
QCC_GenValue *QCC_genArrayBooleanL(int len);
QCC_GenValue *QCC_genArrayChar();
QCC_GenValue *QCC_genArrayCharL(int len);
QCC_GenValue *QCC_genArrayString();
QCC_GenValue *QCC_genArrayStringL(int len, int strLen);
#endif

View file

@ -10,10 +10,10 @@
#include <time.h>
#include <unistd.h>
#include "../include/common.h"
#include "../include/roaring.h"
#include "../include/sparsemap.h"
#include "../include/tdigest.h"
#include <common.h>
#include <roaring.h>
#include <sparsemap.h>
#include <tdigest.h>
#include "midl.c"

View file

@ -15,9 +15,10 @@
#include <stdlib.h>
#include <unistd.h>
#include "../include/sparsemap.h"
#include "common.h"
#include "munit.h"
#include <sparsemap.h>
#include <common.h>
#include <munit.h>
#include <qc.h>
#define munit_free free