mirror of
https://github.com/sigmasternchen/libviscosity
synced 2025-03-15 07:08:57 +00:00
working version
This commit is contained in:
parent
a32699545b
commit
01fbb18c27
3 changed files with 248 additions and 0 deletions
40
Makefile
Normal file
40
Makefile
Normal file
|
@ -0,0 +1,40 @@
|
|||
CC = gcc
|
||||
CFLAGS = -std=c99 -Wall -D_POSIX_C_SOURCE=201112L -D_XOPEN_SOURCE=500 -D_GNU_SOURCE -static
|
||||
LD = gcc
|
||||
LDFLAGS =
|
||||
AR = ar
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS = obj/viscocity.o
|
||||
OBJS_SHARED = obj/viscocity-shared.o
|
||||
DEPS = $(OBJS:%.o=%.d)
|
||||
|
||||
all: libviscocity.so libviscocity.a viscocity.h
|
||||
|
||||
libviscocity.so: $(OBJS_SHARED)
|
||||
$(LD) $(LDFLAGS) -shared -o $@ $^
|
||||
|
||||
libviscocity.a: $(OBJS)
|
||||
$(AR) $(ARFLAGS) $@ $^
|
||||
|
||||
viscocity.h: src/viscocity.h
|
||||
cp $< $@
|
||||
|
||||
-include $(DEPS)
|
||||
|
||||
obj/%.o: src/%.c obj
|
||||
$(CC) $(CFLAGS) -MMD -c -o $@ $<
|
||||
|
||||
obj/%-shared.o: src/%.c obj
|
||||
$(CC) $(CFLAGS) -fPIC -MMD -c -o $@ $<
|
||||
|
||||
obj:
|
||||
@mkdir -p obj
|
||||
|
||||
clean:
|
||||
@echo "Cleaning up..."
|
||||
@rm -f obj/*.o
|
||||
@rm -f obj/*.d
|
||||
@rm -f libviscocity.so
|
||||
@rm -f libviscocity.a
|
||||
@rm -f viscocity.h
|
173
src/viscocity.c
Normal file
173
src/viscocity.c
Normal file
|
@ -0,0 +1,173 @@
|
|||
#include "viscocity.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
int failedTests = 0;
|
||||
bool testOkay = true;
|
||||
|
||||
const char* currentTestName;
|
||||
const char* currentTestFunction;
|
||||
|
||||
int totalTests = 0;
|
||||
|
||||
|
||||
void _assert(bool b, const char* condition, const char* name, const char* file, int line, const char* function) {
|
||||
if (!b) {
|
||||
printf("\033[31mAssertion failed");
|
||||
if (name != NULL) {
|
||||
|
||||
printf(": %s", name);
|
||||
}
|
||||
printf("\033[0m\n");
|
||||
if (condition != NULL) {
|
||||
printf("%s\n", condition);
|
||||
}
|
||||
if (strcmp(function, "__fn__") == 0)
|
||||
function = "lambda";
|
||||
|
||||
printf("in %s:%d (%s)\n", file, line, function);
|
||||
|
||||
testOkay = false;
|
||||
}
|
||||
}
|
||||
|
||||
#define MAX_CALL_ASSERTIONS (10)
|
||||
|
||||
struct callAssertion {
|
||||
const char* name;
|
||||
int target;
|
||||
int current;
|
||||
enum callAssertionBehaviour behaviour;
|
||||
const char* file;
|
||||
int line;
|
||||
const char* function;
|
||||
} callAssertions[MAX_CALL_ASSERTIONS];
|
||||
int numberOfCallAssertions;
|
||||
|
||||
void _assertCall(int number, const char* name, enum callAssertionBehaviour behaviour, const char* file, int line, const char* function) {
|
||||
int i;
|
||||
for (i = 0; i < numberOfCallAssertions; i++) {
|
||||
if (strcmp(callAssertions[i].name, name) == 0)
|
||||
break;
|
||||
}
|
||||
if (i == numberOfCallAssertions) {
|
||||
numberOfCallAssertions++;
|
||||
callAssertions[i] = (struct callAssertion) {
|
||||
.name = name,
|
||||
.target = number,
|
||||
.current = 0,
|
||||
.behaviour = behaviour
|
||||
};
|
||||
}
|
||||
|
||||
callAssertions[i].current++;
|
||||
callAssertions[i].file = file;
|
||||
callAssertions[i].line = line;
|
||||
callAssertions[i].function = function;
|
||||
|
||||
}
|
||||
|
||||
#define CALL_ASSERTION_CONDITION_BUFFER_SIZE (255)
|
||||
|
||||
void checkCallAssertions() {
|
||||
for (int i = 0; i < numberOfCallAssertions; i++) {
|
||||
struct callAssertion assertion = callAssertions[i];
|
||||
|
||||
char buffer[CALL_ASSERTION_CONDITION_BUFFER_SIZE];
|
||||
|
||||
switch(assertion.behaviour) {
|
||||
case MIN:
|
||||
snprintf(buffer, CALL_ASSERTION_CONDITION_BUFFER_SIZE, ">%d calls expected; got %d", assertion.target, assertion.current);
|
||||
_assert(assertion.current >= assertion.target, buffer, assertion.name, assertion.file, assertion.line, assertion.function);
|
||||
break;
|
||||
case MAX:
|
||||
snprintf(buffer, CALL_ASSERTION_CONDITION_BUFFER_SIZE, "<%d calls expected; got %d", assertion.target, assertion.current);
|
||||
_assert(assertion.current <= assertion.target, buffer, assertion.name, assertion.file, assertion.line, assertion.function);
|
||||
break;
|
||||
case EXACT:
|
||||
snprintf(buffer, CALL_ASSERTION_CONDITION_BUFFER_SIZE, "%d calls expected; got %d", assertion.target, assertion.current);
|
||||
_assert(assertion.current == assertion.target, buffer, assertion.name, assertion.file, assertion.line, assertion.function);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testBegin(const char* name, const char* file, int line, const char* function) {
|
||||
testOkay = true;
|
||||
|
||||
printf("=====================\n");
|
||||
printf("\033[33mTest %d", ++totalTests);
|
||||
if (name != NULL) {
|
||||
printf(": %s", name);
|
||||
}
|
||||
printf("\033[0m\n");
|
||||
printf("in %s:%d (%s)\n\n", file, line, function);
|
||||
|
||||
currentTestName = name;
|
||||
currentTestFunction = function;
|
||||
numberOfCallAssertions = 0;
|
||||
}
|
||||
|
||||
void testEnd() {
|
||||
checkCallAssertions();
|
||||
|
||||
if (!testOkay) {
|
||||
failedTests++;
|
||||
|
||||
printf("\n");
|
||||
printf("\033[31mTest failed\033[0m ");
|
||||
/*if (currentTestName != NULL) {
|
||||
printf("%s ", currentTestName);
|
||||
}*/
|
||||
printf("(%s)\n\n", currentTestFunction);
|
||||
} else {
|
||||
printf("\033[32mTest succeeded\033[0m\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
int testsFinal() {
|
||||
printf("\n");
|
||||
if (failedTests == 0) {
|
||||
printf("\033[32mAll tests were successful.\033[0m\n");
|
||||
} else {
|
||||
printf("\033[31mSome tests failed.\033[0m\n");
|
||||
}
|
||||
printf("%d of %d tests failed.\n", failedTests, totalTests);
|
||||
|
||||
return failedTests == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
#define MAX_NUMBER_OF_TESTS (1<<15)
|
||||
|
||||
struct test {
|
||||
void (*testfunc)();
|
||||
const char* name;
|
||||
const char* file;
|
||||
const char* function;
|
||||
int line;
|
||||
} testRegister[MAX_NUMBER_OF_TESTS];
|
||||
int numberOfTests = 0;
|
||||
|
||||
void addTest(void (*testfunc)(), const char* name, const char* file, const char* function, int line) {
|
||||
testRegister[numberOfTests++] = (struct test) {
|
||||
.testfunc = testfunc,
|
||||
.name = name,
|
||||
.file = file,
|
||||
.function = function,
|
||||
line = line
|
||||
};
|
||||
}
|
||||
|
||||
int doTests() {
|
||||
for (int i = 0; i < numberOfTests; i++) {
|
||||
struct test test = testRegister[i];
|
||||
|
||||
testBegin(test.name, test.file, test.line, test.function);
|
||||
test.testfunc();
|
||||
testEnd();
|
||||
}
|
||||
|
||||
return testsFinal();
|
||||
}
|
||||
|
35
src/viscocity.h
Normal file
35
src/viscocity.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
#ifndef VISCOCITY_H
|
||||
#define VISCOCITY_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
void _assert(bool, const char*, const char*, const char*, int, const char*);
|
||||
|
||||
#define assertTrue(b, n) _assert(b, #b, n, __FILE__, __LINE__, __FUNCTION__)
|
||||
#define assertFalse(b, n) assertTrue(!b, n)
|
||||
#define assertNull(o, n) assertTrue(o == NULL, n)
|
||||
#define assertNotNull(o, n) assertTrue(o != NULL, n)
|
||||
#define assertStringEqual(s1, s2, n) assertTrue(strcmp(s1, s2) == 0, n)
|
||||
|
||||
enum callAssertionBehaviour {
|
||||
MAX, MIN, EXACT
|
||||
};
|
||||
|
||||
void _assertCall(int, const char*, enum callAssertionBehaviour, const char*, int, const char*);
|
||||
|
||||
#define assertCall(i, n, b) _assertCall(i, n, b, __FILE__, __LINE__, __FUNCTION__)
|
||||
#define assertCallMin(i, n) assertCall(i, n, MIN)
|
||||
#define assertCallMax(i, n) assertCall(i, n, MAX)
|
||||
#define assertCallExact(i, n) assertCall(i, n, EXACT)
|
||||
|
||||
|
||||
void addTest(void (*)(), const char*, const char*, const char*, int);
|
||||
|
||||
#define test(f, n) void test_##f(); \
|
||||
__attribute__((constructor)) void register##f() { addTest(& test_##f, n, __FILE__, "test_" # f, __LINE__); }\
|
||||
void test_##f()
|
||||
|
||||
int doTests();
|
||||
|
||||
#endif
|
Loading…
Reference in a new issue