// Copyright © 2024 Rot127 // SPDX-License-Identifier: BSD-3 #define _XOPEN_SOURCE 500 #include "../../../utils.h" #include "test_run.h" #include #include #include #include #include #include // Pointer to the file list table // Must be a thread local, because we cannot pass arguments to `nftw`. // So the found test files can only be saved, very annoyingly, // to a global/thread-local mutable variables. char ***test_files = NULL; uint32_t file_count = 0; static void help(const char *self) { fprintf(stderr, "%s / ...\n", self); } static int handle_ftree_entry(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { if (typeflag != FTW_F) { return 0; } const char *suffix = strstr(fpath, ".yaml"); if (!suffix || suffix - fpath != strlen(fpath) - 5) { // Misses the .yaml suffix. return 0; } file_count++; *test_files = cs_mem_realloc(*test_files, sizeof(char *) * file_count); if (!*test_files) { fprintf(stderr, "[!] realloc failed\n"); return -1; } test_files[0][file_count - 1] = cs_strdup(fpath); return 0; } /// Parses the test file paths from the @argv array. static void get_tfiles(int argc, const char **argv) { for (size_t i = 1; i < argc; ++i) { if (nftw(argv[i], handle_ftree_entry, 20, FTW_DEPTH | FTW_PHYS) == -1) { fprintf(stderr, "[!] nftw failed.\n"); return; } } } void print_test_run_stats(const TestRunStats *stats) { printf("\n-----------------------------------------\n"); printf("Test run statistics\n\n"); printf("Valid files: %" PRId32 "\n", stats->valid_test_files); printf("Invalid files: %" PRId32 "\n", stats->invalid_files); printf("Errors: %" PRId32 "\n\n", stats->errors); printf("Test cases:\n"); printf("\tTotal: %" PRId32 "\n", stats->tc_total); printf("\tSuccessful: %" PRId32 "\n", stats->successful); printf("\tSkipped: %" PRId32 "\n", stats->skipped); printf("\tFailed: %" PRId32 "\n", stats->failed); printf("-----------------------------------------\n"); printf("\n"); } int main(int argc, const char **argv) { if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0) { help(argv[0]); exit(EXIT_FAILURE); } test_files = malloc(sizeof(char **)); *test_files = NULL; get_tfiles(argc, argv); if (!*test_files || file_count == 0) { fprintf(stderr, "Arguments are invalid. No files found.\n"); exit(EXIT_FAILURE); } printf("Test files found: %" PRId32 "\n", file_count); TestRunStats stats = { 0 }; TestRunResult res = cstest_run_tests(*test_files, file_count, &stats); print_test_run_stats(&stats); if (res == TEST_RUN_ERROR) { fprintf(stderr, "[!] An error occured.\n"); exit(EXIT_FAILURE); } else if (res == TEST_RUN_SUCCESS) { printf("[o] All tests succeeded.\n"); exit(EXIT_SUCCESS); } else if (res == TEST_RUN_FAILURE) { printf("\nNOTE: Asserts have the actual data on the left side: 'actual' != 'expected'\n\n"); fprintf(stderr, "[!] Some tests failed.\n"); exit(EXIT_FAILURE); } fprintf(stderr, "[!] Unhandled Test Run result\n"); exit(EXIT_FAILURE); }