commit 612c64ca212cf4cfb47495ac37fc7d419efb052f Author: dm1sh Date: Mon Feb 15 07:47:13 2021 +0500 Added basic test execution collector and runner and some reference assertions diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..869c0e6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +obj/ +.vscode +*.so* \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..a2c0541 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.associations": { + "ctest.h": "c", + "typeinfo": "c", + "*.a": "c" + } +} \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..aec38fd --- /dev/null +++ b/Makefile @@ -0,0 +1,49 @@ +CC=gcc + +CFLAGS=-Wall -pedantic -std=c11 -fPIC +LDFLAGS= +DFLAGS=-gdb3 + +NAMES=ctest funcs + +set_values = $(addprefix $(1),$(addsuffix $(2),$(3))) + +sourcefy = $(call set_values,./src/,.c,$(1)) +objectify = $(call set_values,./obj/,.o,$(1)) + +SOURCES=$(foreach N,$(NAMES),$(call sourcefy,$(N))) +OBJECTS=$(foreach N,$(NAMES),$(call objectify,$(N))) + +all: libctest + +libctest: $(OBJECTS) check-env + gcc -shared -Wl,-soname,$(addsuffix .so.$(CT_VERSION),$@) -o $(addsuffix .so.$(CT_VERSION).0,$@) $(OBJECTS) + + +$(OBJECTS):%.o: $($(call sourcefy $@)) objdir + $(CC) $(CFLAGS) -c -o $@ $(call sourcefy,$(subst .o,,$(@F))) + +objdir: + mkdir -p obj + +install: check-env + cp libctest.so.$(CT_VERSION).0 /usr/local/lib/ + ln -sf /usr/local/lib/libctest.so.$(CT_VERSION).0 /usr/local/lib/libctest.so.$(CT_VERSION) + ln -sf /usr/local/lib/libctest.so.$(CT_VERSION).0 /usr/local/lib/libctest.so + mkdir -p /usr/local/include/ctest + cp $(wildcard ./include/*) /usr/local/include/ctest + +uninstall: check-env + rm -f $(wildcard /usr/local/lib/libctest.so*) + rm -rf $(wildcard /usr/local/include/ctest/*) + +check-env: +ifndef CT_VERSION + $(error CT_VERSION is undefined) +endif + +.PHONY: + clean +clean: + rm -rf obj + rm $(wildcard libctest.so*) \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..dadf814 --- /dev/null +++ b/README.md @@ -0,0 +1,15 @@ +# Testing library for C + +Mostly specialized on unit tests library for improved testing experience + +# Example: + +```c +#include "ctest.h" +#include "funcs.h" +... +test(is_true(some_function()), "Function is true"); +run_tests(); +... + +``` diff --git a/include/ctest.h b/include/ctest.h new file mode 100644 index 0000000..3b34dc5 --- /dev/null +++ b/include/ctest.h @@ -0,0 +1,19 @@ +#ifndef CTEST_H +#define CTEST_H + +#include +#include +#include + +typedef struct test_structure +{ + int result; + char *name; +} test_t; + +void run_tests(int *which); +test_t *new_test(int res, char *name); +void free_test(test_t *o_t); +void test(int res, char *name); + +#endif \ No newline at end of file diff --git a/include/funcs.h b/include/funcs.h new file mode 100644 index 0000000..0d48e75 --- /dev/null +++ b/include/funcs.h @@ -0,0 +1,8 @@ +#ifndef FUNCS_H +#define FUNCS_H + +int is_equal(void *res, void *correct); +int is_true(void *res); +int is_false(void *res); + +#endif \ No newline at end of file diff --git a/obj/ctest.o b/obj/ctest.o new file mode 100644 index 0000000..f180cb7 Binary files /dev/null and b/obj/ctest.o differ diff --git a/obj/funcs.o b/obj/funcs.o new file mode 100644 index 0000000..258666c Binary files /dev/null and b/obj/funcs.o differ diff --git a/src/ctest.c b/src/ctest.c new file mode 100644 index 0000000..391c6ee --- /dev/null +++ b/src/ctest.c @@ -0,0 +1,114 @@ +#include "../include/ctest.h" + +static test_t **tests; +static int tests_k; + +/** + * Executes one test check. Fails if NULL passed + * @param test Test to execute + * @param failde_k Counter of failed tests. Link is passed because it is incremented inside function body + * @param n Test number to print + */ +void execute_test(test_t *test, int *failed_k, int n) +{ + if (test == NULL) + { + fprintf(stderr, "No such test: %d", n + 1); + exit(EXIT_FAILURE); + } + + if (test->result) + fprintf(stdout, "%s\n\033[0;32m%d - Passed\033[0m\n", test->name, n + 1); + else + { + fprintf(stdout, "\033[0;31m%d FAILED\033[0m\n", n + 1); + fprintf(stderr, "Test %d failded", n + 1); + failed_k++; + } +} + +/** + * Runs all tests + * Execute after all test declarations. + * @param which Array of numbers of tests to execute ending with -1 or NULL if all tests must be run. + */ +void run_tests(int *which) +{ + fprintf(stdout, "Executing tests:\n"); + + int failed_k = 0; + + if (which == NULL) + { + for (int i = 0; i < tests_k; i++) + execute_test(tests[i], &failed_k, i); + } + else + { + int i = 0; + while (which[i] != -1) + { + int j = which[i]; + + if (j < 0 || j >= tests_k) + { + fprintf(stderr, "No such test: %d", j + 1); + exit(EXIT_FAILURE); + } + + execute_test(tests[j], &failed_k, j); + i++; + } + } + + if (failed_k > 0) + { + fprintf(stderr, "%d tests failed", failed_k); + exit(EXIT_FAILURE); + } + else + { + fprintf(stdout, "All tests passed"); + exit(EXIT_SUCCESS); + } +} + +/** + * Creates new test struct + */ +test_t *new_test(int res, char *name) +{ + test_t *n_t = (test_t *)malloc(sizeof(test_t)); + + n_t->name = strdup(name); + n_t->result = res; + + return n_t; +} + +/** + * Frees memory allocated for test structure + */ +void free_test(test_t *o_t) +{ + free(o_t->name); + free(o_t); +} + +/** + * Test declarator. Adds specified test to list of tests + * @param res Response of testing function + * @param name Test name + */ +void test(int res, char *name) +{ + if (tests == NULL) + { + tests = malloc(0); + tests_k = 0; + } + + tests = realloc(tests, (tests_k + 1) * sizeof(test_t *)); + tests[tests_k] = new_test(res, name); + tests_k++; +} \ No newline at end of file diff --git a/src/funcs.c b/src/funcs.c new file mode 100644 index 0000000..3495bb8 --- /dev/null +++ b/src/funcs.c @@ -0,0 +1,16 @@ +#include "../include/funcs.h" + +int is_equal(void *res, void *correct) +{ + return res == correct; +} + +int is_true(void *res) +{ + return res && 1; +} + +int is_false(void *res) +{ + return !res; +} \ No newline at end of file