diff options
Diffstat (limited to 'generate')
| -rw-r--r-- | generate/find_tests.c | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/generate/find_tests.c b/generate/find_tests.c new file mode 100644 index 0000000..0530ae5 --- /dev/null +++ b/generate/find_tests.c @@ -0,0 +1,209 @@ +#include <dirent.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> + +#define MAX_NUMBER_OF_TESTS_PER_FILE 100 +#define MAX_LENGTH_OF_TEST_NAME 100 + +typedef enum { + path_type_unknown, + path_type_directory, + path_type_file +} path_type; + +int check_path_type(const char* path) { + struct stat path_stat; + if (stat(path, &path_stat) != 0) return path_type_unknown; + if (S_ISDIR(path_stat.st_mode)) return path_type_directory; + return path_type_file; +} + +void handle_input_file( + const char* input_path, + int path_strip_index, + void (*handle)(const char*, int, FILE*) +) { + FILE* input_fd = fopen(input_path, "rb"); + handle(input_path, path_strip_index, input_fd); + fclose(input_fd); +} + +void push(char* directories, int cursor, const char* to_add) { + int i = 0; + for (; to_add[i] != 0; i++) { + directories[cursor * PATH_MAX + i] = to_add[i]; + } + while (i < PATH_MAX) directories[cursor * PATH_MAX + i++] = 0; +} + +void handle_input_directory( + const char* input_path, + void (*handle)(const char*, int, FILE*) +) { + int cursor = 0; + char* directories = malloc(PATH_MAX * PATH_MAX * sizeof(*directories)); + push(directories, cursor, input_path); + int input_shift = strlen(input_path) + 1; + while (cursor != -1) { + char* path = &directories[(cursor--) * PATH_MAX]; + DIR* dir_ptr = opendir(path); + if (dir_ptr == NULL) { + fprintf(stderr, "Couldn't open the directory: %s\n", path); + continue; + } + + struct dirent* entry_ptr; + char full_path[PATH_MAX]; + int i = 0; + for (; path[i] != 0; i++) { + full_path[i] = path[i]; + } + full_path[i++] = '/'; + while ((entry_ptr = readdir(dir_ptr)) != NULL) { + if ( + strcmp(entry_ptr->d_name, ".") == 0 || + strcmp(entry_ptr->d_name, "..") == 0 + ) continue; + int j = 0; + for (; entry_ptr->d_name[j] != 0; j++) { + full_path[i + j] = entry_ptr->d_name[j]; + } + full_path[i + j] = 0; + + if (entry_ptr->d_type == DT_REG) { + handle_input_file(full_path, input_shift, handle); + continue; + } + push(directories, ++cursor, full_path); + } + closedir(dir_ptr); + } + free(directories); +} + +void handle_input( + const char* input_path, + int input_type, + void (*handle)(const char*, int, FILE*) +) { + if (input_type == path_type_file) { + handle_input_file(input_path, 0, handle); + } else { + handle_input_directory(input_path, handle); + return; + } +} + +struct file_tests { + char path[PATH_MAX]; + int test_count; + char test_names[MAX_NUMBER_OF_TESTS_PER_FILE][MAX_LENGTH_OF_TEST_NAME]; +}; +struct tests { + int count; + int capacity; + struct file_tests* items; +}; + +struct tests tests; + +int max(int a, int b) { + if (a > b) return a; + return b; +} + +void append_tests(struct file_tests file_tests) { + if (tests.count + 1 > tests.capacity) { + tests.capacity = max(32, tests.count) + tests.count; + tests.items = realloc(tests.items, tests.capacity * sizeof(*tests.items)); + } + + tests.items[tests.count++] = file_tests; +} + +void handle_fn(const char* input_path, int path_strip_index, FILE* file) { + if (input_path[strlen(input_path) - 1] != 'c') return; + char ch; + char match[] = "\nbool test_"; + int match_len = strlen(match); + int i = 0; + char output[MAX_NUMBER_OF_TESTS_PER_FILE][MAX_LENGTH_OF_TEST_NAME]; + int k = 0; int kk = 0; + enum { search_mode, read_test_name }; + int mode = search_mode; + while ((ch = fgetc(file)) != EOF) { + if (mode == search_mode) { + if (match[i] == ch) i++; + else i = match[0] == ch; + + if (i == match_len) { + mode = read_test_name; + kk = 0; + } + } else if (mode == read_test_name) { + if (ch == '(') { + mode = search_mode; + k++; + continue; + } + + output[k][kk++] = ch; + } + } + struct file_tests tests = { .test_count = k }; + memcpy(tests.path, input_path, strlen(input_path) + 1); + memcpy(tests.test_names, output, sizeof(output)); + append_tests(tests); +} + +int main() { + tests.items = malloc(sizeof(*tests.items) * 100); + tests.capacity = 100; + tests.count = 0; + + handle_input("src", path_type_directory, handle_fn); + + FILE* f = fopen("generated/tests.c", "w"); + + int total_test_count = 0; + for (int i = 0; i < tests.count; i++) { + struct file_tests item = tests.items[i]; + if (item.test_count == 0) continue; + total_test_count += item.test_count; + fprintf(f, "#include \"../%s\"\n", item.path); + } + fprintf( + f, + "\nint total_test_count = %d;\nbool (*tests[%d])(void) = {\n", + total_test_count, + total_test_count + ); + int max_test_name_size = 0; + for (int i = 0; i < tests.count; i++) { + struct file_tests item = tests.items[i]; + printf("%s\n", item.path); + if (item.test_count == 0) continue; + for (int j = 0; j < item.test_count; j++) { + printf("\t%s\n", item.test_names[j]); + fprintf(f, " test_%s,\n", item.test_names[j]); + int test_name_size = strlen(item.test_names[j]); + if (max_test_name_size < test_name_size) { + max_test_name_size = test_name_size; + } + } + } + fprintf(f, "};\n"); + fprintf(f, "\nint max_test_name_size = %d;", max_test_name_size); + fprintf(f, "\nchar test_names[%d][100] = {\n", total_test_count); + for (int i = 0; i < tests.count; i++) { + struct file_tests item = tests.items[i]; + if (item.test_count == 0) continue; + for (int j = 0; j < item.test_count; j++) { + fprintf(f, " \"%s\",\n", item.test_names[j]); + } + } + fprintf(f, "};\n"); + fclose(f); +} |
