#ifndef COSMS_CORE_TEST
#define COSMS_CORE_TEST

#include <stdio.h>

#define COSMS_CORE_TEST_EXPORT_TEST(name) { #name, cosms_core_##name##_test }
#define COSMS_CORE_TEST_DEFINE(name) const char *cosms_core_##name##_test(void)
#define COSMS_CORE_TEST_TEST(name, implementation) const char *cosms_core_##name##_test(void) { \
    implementation                                                                              \
}

#define COSMS_CORE_TEST_EXPORT(name, ...) static const struct cosms_core_test cosms_core_test_##name[] = {  \
        __VA_ARGS__,                                                                                        \
        0                                                                                                   \
    }

#define COSMS_CORE_TEST_START static const struct cosms_core_test *cosms_core_test_tests[] = {
#define COSMS_CORE_TEST_IMPORT(name) cosms_core_test_##name
#define COSMS_CORE_TEST_END };

#define COSMS_CORE_TEST_RUN()                                                                                                   \
    for (unsigned long long index = 0; index < sizeof(cosms_core_test_tests) / sizeof(cosms_core_test_tests[0]); index += 1) {  \
        unsigned long long test_index = 0;                                                                                      \
        struct cosms_core_test current_test = cosms_core_test_tests[index][test_index];                                         \
        while (current_test.name != 0) {                                                                                        \
            printf("[*] running test %s...", current_test.name);                                                                \
            fflush(stdout);                                                                                                     \
            const char *result = current_test.function();                                                                       \
            if (result == NULL) {                                                                                               \
                printf("\r[PASS] test %s completed successfully!\n", current_test.name);                                        \
            } else {                                                                                                            \
                printf("\r[FAIL] test %s failed with error:\n\t%s\n", current_test.name, result);                               \
            }                                                                                                                   \
                                                                                                                                \
            test_index += 1;                                                                                                    \
            current_test = cosms_core_test_tests[index][test_index];                                                            \
        }                                                                                                                       \
    }

struct cosms_core_test {
    const char *name;
    const char *(*function)(void);    
};

#endif
