First are the debug macros which I use all the time:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #ifndef __dbg_h__ #define __dbg_h__ #include <stdio.h> #include <errno.h> #include <string.h> #ifdef NDEBUG #define debug(M, ...) #else #define debug(M, ...) fprintf(stderr, "DEBUG %s:%d: " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) #endif #define clean_errno() (errno == 0 ? "None" : strerror(errno)) #define log_err(M, ...) fprintf(stderr, "[ERROR] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) #define log_warn(M, ...) fprintf(stderr, "[WARN] (%s:%d: errno: %s) " M "\n", __FILE__, __LINE__, clean_errno(), ##__VA_ARGS__) #define log_info(M, ...) fprintf(stderr, "[INFO] (%s:%d) " M "\n", __FILE__, __LINE__, ##__VA_ARGS__) #define check(A, M, ...) if(!(A)) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } #define sentinel(M, ...) { log_err(M, ##__VA_ARGS__); errno=0; goto error; } #define check_mem(A) check((A), "Out of memory.") #define check_debug(A, M, ...) if(!(A)) { debug(M, ##__VA_ARGS__); errno=0; goto error; } #endif |
Then there is the unit testing that I just paste into whatever file I need.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | #undef NDEBUG #ifndef _minunit_h #define _minunit_h #include <stdio.h> #include <dbg.h> #include <stdlib.h> #define mu_suite_start() char *message = NULL #define mu_assert(test, message) if (!(test)) { log_err(message); return message; } #define mu_run_test(test) debug("\n-----%s", " " #test); \ message = test(); tests_run++; if (message) return message; #define RUN_TESTS(name) int main(int argc, char *argv[]) {\ argc = 1; \ debug("----- RUNNING: %s", argv[0]);\ printf("----\nRUNNING: %s\n", argv[0]);\ char *result = name();\ if (result != 0) {\ printf("FAILED: %s\n", result);\ }\ else {\ printf("ALL TESTS PASSED\n");\ }\ printf("Tests run: %d\n", tests_run);\ exit(result != 0);\ } int tests_run; #endif |
Which is a little janky but fun. Used like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #include "minunit.h" #include "math.h" #define KISS_VEC_IMP #include "kiss_vec.h" #define EPSILON 0.000001f #define EQ(a,b) (fabs((a) - (b)) < EPSILON) char* test_vec_add() { vec v0 = vec3( 1.0f, 2.0f, 3.0f ); vec v1 = vec3( 2.0f, 3.0f, 5.0f ); vec_add( &v0, &v0, &v1 ); mu_assert( EQ( v0.x, 3.0f ), "x not equal" ); mu_assert( EQ( v0.y, 5.0f ), "y not equal" ); mu_assert( EQ( v0.z, 8.0f ), "z not equal" ); return NULL; } char *all_tests() { mu_suite_start(); mu_run_test(test_vec_add); return NULL; } RUN_TESTS(all_tests); |
Again, not mine, adapted from examples: Learn C the Hard Way
Here's the handmade project (which will have more stuff soon): https://kiss.handmade.network/