From a625bbff505c912f8a19f62bcb92313a63c60ed4 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 6 Sep 2024 13:07:18 +0200 Subject: Add the tester --- tools/init.c | 205 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 tools/init.c (limited to 'tools') diff --git a/tools/init.c b/tools/init.c new file mode 100644 index 0000000..cb646bd --- /dev/null +++ b/tools/init.c @@ -0,0 +1,205 @@ +#include +#include +#include +#include +#include +#include +#include + +#define FILENAME_BUFFER_SIZE 256 + +size_t read_command(int descriptor, char *command_buffer) +{ + ssize_t bytes_read = 0; + size_t read_so_far = 0; + + while ((bytes_read = read(descriptor, command_buffer + read_so_far, FILENAME_BUFFER_SIZE - read_so_far - 1)) > 0) + { + read_so_far += bytes_read; + if (read_so_far >= FILENAME_BUFFER_SIZE - 1) + { + break; + } + } + command_buffer[read_so_far] = 0; + return read_so_far; +} + +enum status +{ + status_success, + status_failure, + status_warning, + status_fatal +}; + +unsigned int make_path(char *destination, const char *directory, const char *filename, const char *extension) +{ + unsigned int i = 0; + + for (; i < FILENAME_BUFFER_SIZE; i++) + { + if (directory[i] == 0) + { + break; + } + destination[i] = directory[i]; + } + for (int j = 0; i < FILENAME_BUFFER_SIZE; i++, j++) + { + if (filename[j] == 0) + { + break; + } + destination[i] = filename[j]; + } + if (extension == NULL) + { + goto done; + } + for (int j = 0; i < FILENAME_BUFFER_SIZE; i++, j++) + { + if (extension[j] == 0) + { + break; + } + destination[i] = extension[j]; + } +done: + destination[i] = 0; + + return i; +} + +enum status run_test(const char *file_entry_name) +{ + printf("Running %s. ", file_entry_name); + + char filename[FILENAME_BUFFER_SIZE]; + char command_buffer[FILENAME_BUFFER_SIZE]; + char file_buffer[256]; + int pipe_ends[2]; + + if (pipe(pipe_ends) == -1) + { + perror("pipe"); + return status_fatal; + } + make_path(filename, "./tests/", file_entry_name, NULL); + + int child_pid = fork(); + if (child_pid == -1) + { + return status_fatal; + } + else if (child_pid == 0) + { + close(STDIN_FILENO); + close(STDERR_FILENO); + close(pipe_ends[0]); // Close the read end. + + if (dup2(pipe_ends[1], STDOUT_FILENO) == -1) + { + perror("dup2"); + } + else + { + execl(filename, filename); + perror("execl"); + } + close(STDOUT_FILENO); + close(pipe_ends[1]); + _exit(1); + } + else + { + close(pipe_ends[1]); // Close the write end. + read_command(pipe_ends[0], command_buffer); + close(pipe_ends[0]); + + int wait_status = 0; + wait(&wait_status); + + make_path(filename, "./expectations/", file_entry_name, ".txt"); + + FILE *expectation_descriptor = fopen(filename, "r"); + + if (expectation_descriptor == NULL) + { + return status_warning; + } + size_t read_from_file = fread(file_buffer, 1, sizeof(file_buffer) - 1, expectation_descriptor); + fclose(expectation_descriptor); + + file_buffer[read_from_file] = 0; + for (unsigned int i = 0; ; ++i) + { + if (command_buffer[i] == 0 && file_buffer[i] == 0) + { + fwrite("\n", 1, 1, stdout); + return status_success; + } + else if (command_buffer[i] != file_buffer[i]) + { + printf("Failed. Got:\n%s", command_buffer); + return status_failure; + } + } + } +} + +struct summary +{ + size_t total; + size_t failure; + size_t success; +}; + +void walk() +{ + DIR *directory_stream = opendir("./tests"); + struct dirent *file_entry; + + struct summary test_summary = { .total = 0, .failure = 0, .success = 0 }; + + while ((file_entry = readdir(directory_stream)) != NULL) + { + if (file_entry->d_name[0] == '.') + { + continue; + } + ++test_summary.total; + switch (run_test(file_entry->d_name)) + { + case status_failure: + ++test_summary.failure; + break; + case status_success: + ++test_summary.success; + break; + case status_warning: + break; + case status_fatal: + goto end_walk; + } + } + printf("Successful: %lu, Failed: %lu, Total: %lu.\n", + test_summary.success, test_summary.failure, test_summary.total); +end_walk: + closedir(directory_stream); +} + +int main() +{ + int dev_console = open("/dev/console", O_WRONLY); + if (dev_console != -1) + { + dup2(dev_console, STDOUT_FILENO); + walk(); + close(dev_console); + } + sync(); + reboot(RB_POWER_OFF); + + return 1; +} -- cgit v1.2.3