diff options
| author | Charles <sircharlesaze@gmail.com> | 2019-11-05 03:06:09 +0100 |
|---|---|---|
| committer | Charles <sircharlesaze@gmail.com> | 2019-11-05 03:09:09 +0100 |
| commit | a4969e7e47b27b47fc06ceeebfb826d73ea78c52 (patch) | |
| tree | b4b43a72ad0b7e095fdf59672d7121e9d74f4eaa | |
| parent | a3ea830c6ecebcfe85356d10fb5263f45ea01956 (diff) | |
| download | ft_printf_test-a4969e7e47b27b47fc06ceeebfb826d73ea78c52.tar.gz ft_printf_test-a4969e7e47b27b47fc06ceeebfb826d73ea78c52.tar.bz2 ft_printf_test-a4969e7e47b27b47fc06ceeebfb826d73ea78c52.zip | |
Refactored generator.py
| -rw-r--r-- | generate.py | 201 | ||||
| -rw-r--r-- | tmp.c | 3 |
2 files changed, 123 insertions, 81 deletions
diff --git a/generate.py b/generate.py index bbe4312..22051c4 100644 --- a/generate.py +++ b/generate.py @@ -2,6 +2,7 @@ import os import sys import argparse import string +import subprocess from random import randrange, choice, shuffle @@ -13,95 +14,139 @@ CHAR_MAX = 127 ULONG_INT_MAX = 18446744073709551616 -chars = (list(string.ascii_lowercase) + list(string.ascii_uppercase) +CHARS = (list(string.ascii_lowercase) + list(string.ascii_uppercase) + list(string.punctuation) + list(string.digits)) -chars.remove("\"") -chars.remove("\\") -chars.extend([r"\t", r"\n", r"\r", r"\v", r"\f", "\\\\"]) +CHARS.remove("\"") +CHARS.remove("\\") +CHARS.extend([r"\t", r"\n", r"\r", r"\v", r"\f", "\\\\"]) + 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, default=100) + parser = argparse.ArgumentParser( + prog="ft_printf_test generator", description="A random test generator") + parser.add_argument("-n", type=int, default=100, + help="number of tests to generate") return vars(parser.parse_args(sys.argv[1:])) -def random_string(n): - b = "".join([choice(chars) for _ in range(randrange(n))]) - return b - -def random_flags(): - flags = "" - possible = "#0- +'" - for _ in range(randrange(len(possible))): - flags += choice(possible) - return flags - -def random_width(): - r = randrange(100) - if r < 5: - return "*" - elif r < 10: - return "" - return str(randrange(200)) - -def random_precision(): - r = randrange(100) - if r < 5: - return ".*" - elif r < 10: - return "" - elif r < 12: - return "." - return "." + str(randrange(200)) - -def generate_args(): - a = [] - b = [] - fmt_str ="diuxXcsp%" - for _ in range(15): - t = fmt_str[randrange(len(fmt_str))] - a.append(f"%{random_flags()}{random_width()}{random_precision()}{t}") - b.append({ +class Generator: + def __init__(self, options): + self.test_nb = options["n"] + self.output_filename = "generated.c" + self.output_file = None + self.tmp_filename = "tmp.c" + self.str_max_len = 10 + self.args_max = 10 + self.flags_max = 2 + self.width_max = 200 + self.width_wildcard_rate = 10 + self.width_empty_rate = 2 + self.precision_max = 200 + self.precision_wildcard_rate = 10 + self.precision_empty_rate = 2 + self.precision_point_rate = 4 + self.possible_flags = "#0- +" + self.possible_conv ="diuxXcsp" + self.possible_conv_len = len(self.possible_conv) + self.pool = [] + + def run(self): + with open(self.output_filename, "w") as self.output_file: + self._write_header() + while self.test_nb > 0: + assert_printf = self._random_printf() + print(assert_printf) + # self.test_nb -= 1 + if self._compile(assert_printf): + self.output_file.write(assert_printf + "\n\t") + self.test_nb -= 1 + print("generated") + self._write_footer() + os.system(f"rm {self.tmp_filename}") + + def quit(self): + pass + + + def _compile(self, assert_printf): + with open(self.tmp_filename, "w") as tmp_file: + tmp_file.write("#include <stdio.h>\n#include \"header.h\"\nvoid t (){") + tmp_file.write(assert_printf + "}") + return os.system("gcc -c -Wformat -Werror tmp.c > /dev/null 2>&1") == 0 + + def _random_printf(self): + formats, args = self._random_args() + args_str = "".join(["," + str(a) for a in args if a is not None]) + return f"ASSERT_PRINTF(\"{''.join(formats)}\" {args_str});" + + def _random_args(self): + args = [] + formats = [] + for _ in range(randrange(1, self.args_max + 1)): + conv = self.possible_conv[randrange(self.possible_conv_len)] + f = self._random_fmt(conv) + for _ in range(f.count("*")): + args.append(randrange(-100, 100)) + formats.append(f) + args.append(self._random_arg(conv)) + return formats, args + + def _random_fmt(self, conv): + return f"%{self._random_flags()}{self._random_width()}{self._random_precision()}{conv}" + + def _random_arg(self, conv): + return { 'c': randrange(CHAR_MIN, CHAR_MAX + 1), - 's': "\"" + random_string(10) + "\"", + 's': "\"" + self._random_string() + "\"", 'd': randrange(INT_MIN, INT_MAX + 1), 'i': randrange(INT_MIN, INT_MAX + 1), 'u': randrange(UINT_MAX), 'x': randrange(UINT_MAX), 'X': randrange(UINT_MAX), - 'p': str(randrange(ULONG_INT_MAX)) + "lu", - '%': None - }[t]) - return a, b - - -def generate_printf(): - a, b = generate_args() - s = "\"" - s2 = "" - for x, y in zip(a, b): - s += x - if x[-1] != '%': - s2 += "," + str(y) - - return f"ASSERT_PRINTF({s}\" {s2});" - - + 'p': str(randrange(ULONG_INT_MAX)) + "lu" + # '%': None + }[conv] + + def _random_flags(self): + if self.flags_max <= 0: + return "" + return "".join([choice(self.possible_conv) for _ in range(randrange(self.flags_max))]) + + def _random_width(self): + p = randrange(100) + if p < self.width_wildcard_rate: + return "*" + p -= self.width_wildcard_rate + if p < self.width_empty_rate: + return "" + return str(randrange(self.width_max)) + + def _random_precision(self): + p = randrange(100) + if p < self.precision_wildcard_rate: + return ".*" + p -= self.precision_wildcard_rate + if p < self.precision_empty_rate: + return "" + p -= self.precision_empty_rate + if p < self.precision_point_rate: + return "." + return "." + str(randrange(self.precision_max)) + + def _random_string(self): + return "".join([choice(CHARS) for _ in range(randrange(self.str_max_len))]) + + def _write_header(self): + self.output_file.write("#include \"header.h\"\n\nvoid generated_test(void)\n{\n\t") + + def _write_footer(self): + self.output_file.write("}\n") if __name__ == "__main__": options = parse_args() - nb_tests = options["n"] - with open("generated.c", "w") as file: - file.write("#include \"header.h\"\n\nvoid generated_test(void)\n{\n\t") - - while nb_tests > 0: - with open("tmp.c", "w") as tmp: - tmp.write("#include <stdio.h>\n#include \"header.h\"\nvoid t (){") - tmp_assert = generate_printf() - tmp.write(tmp_assert + "}") - ret = os.system("gcc -c -Wall -Wextra -Werror tmp.c > /dev/null 2>&1") - print(ret) - if ret == 0: - file.write(tmp_assert + "\n\t") - nb_tests -= 1 - - file.write("}\n") + g = Generator(options) + try: + g.run() + except KeyboardInterrupt: + pass + finally: + g.quit() @@ -1,3 +0,0 @@ -#include <stdio.h> -#include "header.h" -void t (){
\ No newline at end of file |
