summaryrefslogtreecommitdiff
path: root/generate/find_tests.c
diff options
context:
space:
mode:
Diffstat (limited to 'generate/find_tests.c')
-rw-r--r--generate/find_tests.c209
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);
+}