aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--generate.py201
-rw-r--r--tmp.c3
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()
diff --git a/tmp.c b/tmp.c
deleted file mode 100644
index 1c94ea3..0000000
--- a/tmp.c
+++ /dev/null
@@ -1,3 +0,0 @@
-#include <stdio.h>
-#include "header.h"
-void t (){ \ No newline at end of file