working version

This commit is contained in:
overflowerror 2020-04-17 23:25:33 +02:00
parent a32699545b
commit 01fbb18c27
3 changed files with 248 additions and 0 deletions

40
Makefile Normal file
View 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
View 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
View 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