diff -r 52802c36b261 -r 8ff82697f2c3 docs/Writerside/topics/test.h.md
--- a/docs/Writerside/topics/test.h.md Sat Jan 25 14:05:35 2025 +0100
+++ b/docs/Writerside/topics/test.h.md Sat Jan 25 15:22:01 2025 +0100
@@ -1,1 +1,119 @@
# Test Framework
+
+UCX brings its own testing framework, which can also be used by your applications.
+
+A test new suite is created by `cx_test_suite_new()`.
+An arbitrary number of test cases can be registered with `cx_test_register()`.
+
+```C
+CxTestSuite *suite = cx_test_suite_new("My Suite");
+
+cx_test_register(suite, test_foo);
+cx_test_register(suite, test_bar);
+cx_test_register(suite, test_baz);
+```
+
+A test case needs to be defined with the `CX_TEST` macro.
+The general structure of a test case is 1) setup code, 2) the actual test, 3) tear down code.
+In UCX this is realized by the `CX_TEST_DO` macro with which you can define a scope for the actual test.
+Whenever a test assertion fails, the scope is exited and the tear down code is executed.
+
+
+
+
+CX_TEST(test_foo) {
+ struct mystruct *x = malloc(sizeof(*x));
+ x->d = 42;
+ CX_TEST_DO {
+ int y = foo(x);
+
+ // auto-generated failure message
+ CX_TEST_ASSERT(y == 42);
+
+ // alternatively: custom failure message
+ CX_TEST_ASSERTM(y == 42,
+ "foo does not return correct value");
+ }
+ free(x);
+}
+
+
+
+
+struct mystruct {
+ int d;
+};
+
+int foo(struct mystruct *s) {
+ return s->d;
+}
+
+
+
+
+Once you have registered all test cases, you can run the test suite with `cx_test_run()`
+or one of the convenience macros.
+
+
+
+
+cx_test_run_stdout(suite);
+
+
+
+
+FILE *f = fopen("test-result.txt", "w");
+cx_test_run_f(suite, f);
+fclose(f);
+
+
+
+
+// for example: UCX buffer
+CxBuffer buf;
+cxBufferInit(&buf, NULL, 1024, NULL, 0);
+cx_test_run(suite, &buf, cxBufferWriteFunc);
+// do something with the buffer
+cxBufferDestroy(&buf);
+
+
+
+Finally, clean up all resources consumed by the test suite.
+
+```C
+cx_test_suite_free(suite);
+```
+
+## Test Subroutines
+
+For parameterized testing you can define and call test subroutines.
+It is _not_ possible to call arbitrary functions and use the `CX_TEST_ASSERT` macro.
+Instead, you define a callable test subroutine with `CX_TEST_SUBROUTINE` and call it with `CX_TEST_CALL_SUBROUTINE`.
+The following example illustrates this with an adaption of the above test case.
+
+
+CX_TEST_SUBROUTINE(test_foo_params, struct mystruct *x, int d) {
+ x->d = d;
+ CX_TEST_ASSERT(foo(x) == d);
+}
+
+CX_TEST(test_foo) {
+ struct mystruct *x = malloc(sizeof(*x));
+ CX_TEST_DO {
+ CX_TEST_CALL_SUBROUTINE(test_foo_params, x, 42);
+ CX_TEST_CALL_SUBROUTINE(test_foo_params, x, -42);
+ CX_TEST_CALL_SUBROUTINE(test_foo_params, x, 1337);
+ }
+ free(x);
+}
+
+
+> Any test function, test case or test subroutine, is a normal C function.
+> As such you can decide to make them `static` when you do not want external linkage.
+> For example, just define the test as `static CX_TEST(test_foo)` instead of `CX_TEST(test_foo)`.
+
+
+
+test.h
+
+