import os import random import re from string import ascii_letters, digits try: import processing except ModuleNotFoundError: from util import processing types = ('integer', 'unsigned_integer', 'character', 'string') list_sep = '...' re_task = re.compile(r'^-- (?P<title>.*)\n(USAGE: (?P<cmd>[\./\w]+) (?P<syntax>.*)|NO EXECUTABLE)', re.MULTILINE) # noqa: E501 re_args = re.compile(rf"<({'|'.join(types)}|{'|'.join(t + '_list' for t in types)})>") # noqa: E501 def call_function(name: str, *args, **kwargs): return globals()[name](*args, **kwargs) def integer(bounds=50): return random.randint(-bounds, bounds) def unsigned_integer(upper=50): return random.randint(0, upper) def character(): return random.choice(10 * ascii_letters + 2 * digits + '%*+,-./:?@[]^_{}~') def string(lenght=31): return ''.join(character() for i in range(2, 2 + unsigned_integer(lenght))) def type_list(_type): def generic_list(): return ' '.join(str( call_function(_type)) for i in range(2, unsigned_integer(6) * 2)) return generic_list def rubbish(): return str(call_function( random.choice(tuple(t + '_list' for t in types) + types))) def argument_generator(syntax): syntax, _ = re.subn( r'<([\w\s]+)> <\1> \.\.\. <\1> <\1>', r'<\1_list>', syntax) syntax, _ = re.subn(r'<(\w+)\s(\w+)>', r'<\1_\2>', syntax) return ' '.join( str(call_function(arg)) for arg in re.findall(re_args, syntax)) def testcases_generator(task, n=10): syntax = task.group('syntax') if not syntax: return if syntax == 'NO INPUT': yield 'NO INPUT' return for i in range(n): yield argument_generator(syntax) def testcases(description_path): for t in types: globals()[t + '_list'] = type_list(t) # I fucking love it with open(description_path) as description_file: description = description_file.read() return { task['title']: { 'cmd': task['cmd'], 'cases': [t for t in testcases_generator(task)] } for task in re.finditer(re_task, description) } def evaluated_testcases(description_path, binaries): task_testcases = testcases(description_path) for task in filter(lambda t: t['cmd'], task_testcases.values()): path_to_binary = os.path.join(os.path.join( binaries, os.path.basename(task['cmd']))) task['results'] = [processing.run_cmd( f"{path_to_binary} {case}").stdout for case in task['cases']] return task_testcases