From 537b22d8731af4d8d6d20ce2eade5c0c4a5f2253 Mon Sep 17 00:00:00 2001 From: Aargh Rai Date: Mon, 25 May 2026 10:48:41 +0530 Subject: coming up with a testing setup --- build.c | 17 ++++ generate/find_tests.c | 209 ++++++++++++++++++++++++++++++++++++++++++++++++ generated/tests.c | 13 +++ src/search/king_moves.c | 16 ++++ tests/main.c | 40 +++++++++ 5 files changed, 295 insertions(+) create mode 100644 generate/find_tests.c create mode 100644 generated/tests.c create mode 100644 tests/main.c diff --git a/build.c b/build.c index 56c4d74..ec698c8 100644 --- a/build.c +++ b/build.c @@ -36,6 +36,23 @@ int main(int argc, char** argv) { } } + if (argc > 1) { + if (strcmp(argv[1], "test") == 0) { + printf("Test mode\n"); + if (fork() == 0) { + char* args[] = {"gcc", "tests/main.c", "-o", "test.o", NULL}; + execvp(args[0], args); + return 0; + } else { + wait(NULL); + } + + char* args[] = {"./test.o", NULL}; + execvp(args[0], args); + return 0; + } + } + if (fork() == 0) { char* args[] = {"gcc", "src/main.c", "-o", "main.o", NULL}; execvp(args[0], args); 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 +#include +#include +#include +#include + +#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); +} diff --git a/generated/tests.c b/generated/tests.c new file mode 100644 index 0000000..d883af5 --- /dev/null +++ b/generated/tests.c @@ -0,0 +1,13 @@ +#include "../src/search/king_moves.c" + +int total_test_count = 2; +bool (*tests[2])(void) = { + test_empty_board, + test_friendly_pieces, +}; + +int max_test_name_size = 15; +char test_names[2][100] = { + "empty_board", + "friendly_pieces", +}; diff --git a/src/search/king_moves.c b/src/search/king_moves.c index 631b7f0..b1fc55f 100644 --- a/src/search/king_moves.c +++ b/src/search/king_moves.c @@ -1,4 +1,10 @@ #include "../search.h" +#include + +#ifdef TEST_MOD +#include "../bitboard.c" +#include "./moves.c" +#endif void get_king_moves(moves_t* moves, position_t position) { assert_valid_position(position); @@ -35,3 +41,13 @@ void get_king_moves(moves_t* moves, position_t position) { add_move(moves, king_square, to); } } + +bool test_empty_board() { + int i = 0; + while (i++ < 10000000); + return true; +} + +bool test_friendly_pieces() { + return false; +} diff --git a/tests/main.c b/tests/main.c new file mode 100644 index 0000000..9333aec --- /dev/null +++ b/tests/main.c @@ -0,0 +1,40 @@ +#include +#include +#include + +#define TEST_MOD +#include "../generated/tests.c" + +double diff_time(struct timespec a, struct timespec b) { + double a_time = (double)a.tv_sec + a.tv_nsec * 1e-9; + double b_time = (double)b.tv_sec + b.tv_nsec * 1e-9; + + return a_time - b_time; +} + +int main() { + int i = 0; + while (i < total_test_count) { + char padded_testname[max_test_name_size + 2]; + int j = 0; + while (test_names[i][j] != 0) { + padded_testname[j] = test_names[i][j]; + j++; + } + while (j < max_test_name_size + 2) { + padded_testname[j++] = ' '; + } + padded_testname[j] = 0; + printf("%s", padded_testname); + fflush(stdout); + + struct timespec begin, end; + + clock_gettime(CLOCK_MONOTONIC, &begin); + bool result = tests[i](); + clock_gettime(CLOCK_MONOTONIC, &end); + + printf(" %s %.2lfs\n", result ? "P" : "F", diff_time(end, begin)); + i++; + } +} -- cgit v1.2.3