diff options
| -rw-r--r-- | Makefile | 2 | ||||
| -rw-r--r-- | generate.py | 17 | ||||
| -rw-r--r-- | header.h | 1 | ||||
| -rw-r--r-- | helper.c | 67 | ||||
| -rw-r--r-- | prettier.py | 37 |
5 files changed, 96 insertions, 28 deletions
@@ -30,7 +30,7 @@ raw: all all: $(NAME) -$(NAME): ft_printf_all clean $(OBJ) +$(NAME): ft_printf_all $(OBJ) $(CC) $(LDFLAGS) $(CCFLAGS) -o $@ $(OBJ) %.o: %.c diff --git a/generate.py b/generate.py new file mode 100644 index 0000000..6ac04b0 --- /dev/null +++ b/generate.py @@ -0,0 +1,17 @@ +import os +import sys +import argparse + + +def parse_args(): + parser = argparse.ArgumentParser(prog="ft_printf_test generator", description="A random test generator") + parser.add_argument("-n", help="number of tests to generate", type=int) + parser.add_argument("-q", "--quiet", + help="decrease vebosity", action="store_true") + parser.add_argument("-c", "--no-clear", help="disable terminal clear before output") + parser.add_argument("-f", "--output-file", help="output file name", default="tests/generated.c")) + return vars(parser.parse_args(sys.argv[1:])) + + +if __name__ == "__main__": + pass @@ -24,6 +24,7 @@ void print_ret_ko(char *msg); void print_signaled_ko(char *msg); void print_ok(void); void print_ko(void); +void ft_putstr_non_printable(char *str); void test_setup(void); void test_tear_down(void); @@ -12,16 +12,22 @@ char buf[BUF_SIZE + 1] = {0}; void test_setup(void) { + if (saved_stdout != -1) + test_tear_down(); saved_stdout = dup(STDOUT_FILENO); if (pipe(pipefd) != 0) exit(EXIT_FAILURE); dup2(pipefd[1], STDOUT_FILENO); + long flags = fcntl(pipefd[0], F_GETFL); + flags |= O_NONBLOCK; + fcntl(pipefd[0], F_SETFL, flags); } void test_tear_down(void) { dup2(saved_stdout, STDOUT_FILENO); close(saved_stdout); + saved_stdout = -1; close(pipefd[0]); close(pipefd[1]); } @@ -29,9 +35,6 @@ void test_tear_down(void) char *read_stdout_buf(void) { fflush(stdout); - long flags = fcntl(pipefd[0], F_GETFL); - flags |= O_NONBLOCK; - fcntl(pipefd[0], F_SETFL, flags); buf[0] = 0; int ret = read(pipefd[0], buf, BUF_SIZE); if (ret != -1) @@ -41,28 +44,62 @@ char *read_stdout_buf(void) void print_buf_ko(char *msg) { - print_ko(); - printf("ft_printf(%s): output error\n", msg); - printf("actual: \"%s\"\n", user_buf); - printf("expected: \"%s\"\n", origin_buf); + printf("FAIL/OUTPUT<>ARGS:%s", msg); + fflush(stdout); + printf("<>EXPECTED:\""); + fflush(stdout); + ft_putstr_non_printable(origin_buf); + printf("\"<>ACTUAL:\""); + fflush(stdout); + ft_putstr_non_printable(user_buf); + printf("\"\n"); fflush(stdout); } void print_ret_ko(char *msg) { - print_ko(); - printf("ft_printf(%s): return error\n", msg); - printf("actual: %d\n", user_ret); - printf("expected: %d\n", origin_ret); + printf("FAIL/RETURN<>ARGS:%s<>EXPECTED:%d<>ACTUAL%d\n", msg, origin_ret, user_ret); fflush(stdout); } void print_signaled_ko(char *msg) { - print_ko(); - printf("ft_printf(\"%s\"): segfault)\n", msg); + printf("FAIL/SEGFAULT<>ARGS:%s<>EXPECTED:<>ACTUAL:\n", msg); fflush(stdout); } -inline void print_ok(void) { printf("[OK]\n"); fflush(stdout); } -inline void print_ko(void) { printf("[KO] "); fflush(stdout);} +inline void print_ok(void) { printf("OK\n"); fflush(stdout); } + +void ft_putstr_non_printable(char *str) +{ + unsigned char tmp; + unsigned char *cursor; + char *hex_symbols; + + hex_symbols = "0123456789abcdef"; + cursor = (unsigned char*)str; + while (*cursor != '\0') + { + if (*cursor >= ' ' && *cursor <= '~') + write(1, cursor, 1); + else if (*cursor == '\n') + printf("\\n"); + else if (*cursor == '\r') + printf("\\r"); + else if (*cursor == '\t') + printf("\\t"); + else if (*cursor == '\v') + printf("\\v"); + else if (*cursor == '\0') + printf("\\0"); + else + { + ft_putchar('\\'); + tmp = *cursor / 16; + ft_putchar(hex_symbols[tmp]); + tmp = *cursor % 16; + ft_putchar(hex_symbols[tmp]); + } + cursor++; + } +} diff --git a/prettier.py b/prettier.py index 39edeaa..4bf84a8 100644 --- a/prettier.py +++ b/prettier.py @@ -1,5 +1,6 @@ import os import sys +import re import argparse @@ -30,20 +31,32 @@ def parse(): "ko": 0, "ko_info": [] } + dot_line_len = 0 for line in sys.stdin: + sys.stdout.flush() + if dot_line_len > 89: + print() + dot_line_len = 0 line = line.strip() - if line.find("[OK]") != -1: + if line == "OK": logs["ok"] += 1 print(green("."), end="") - elif line.find("[KO]") != -1: - logs["ko"] += 1 - logs["ko_info"].append({ - "msg": line[line.find("[KO]") + 5:], - "expected": sys.stdin.readline().rstrip(), - "actual": sys.stdin.readline().rstrip() - }) - print(red("!"), end="") - sys.stdout.flush() + dot_line_len += 1 + continue + m = re.search("^FAIL/(OUTPUT|RETURN|SEGFAULT)<>ARGS:(.*)<>EXPECTED:(.*)<>ACTUAL:(.*)$", line) + if m is None: + print(line) + print("PARSING ERROR") + continue + logs["ko"] += 1 + logs["ko_info"].append({ + "type": m.group(1), + "args": m.group(2), + "expected": m.group(3), + "actual": m.group(4), + }) + print(red("!"), end="") + dot_line_len += 1 return logs @@ -54,7 +67,7 @@ def write_logs(logs, options): with open(filename, "w") as log_file: for ko in logs["ko_info"]: try: - log_file.write("- " + ko["msg"]+ "\n") + log_file.write(f"- [{ko['type']}] ft_printf({ko['args']})\n") log_file.write(" " + ko["expected"] + "\n") log_file.write(" " + ko["actual"] + "\n") except UnicodeEncodeError: @@ -70,7 +83,7 @@ def print_logs(logs, options): infos = logs["ko_info"][:20] if options["quiet"] else logs["ko_info"] for ko in infos: - print("-", ko["msg"]) + print(f"- [{red(ko['type'])}] ft_printf({ko['args']})") if options["verbose"]: print(" ", ko["expected"]) print(" ", ko["actual"]) |
