Skip to content
Snippets Groups Projects
testcases.py 2.59 KiB
import json
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)
re_args = re.compile(rf"<({'|'.join(types)}|{'|'.join(t + '_list' for t in types)})>")


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

    yield ''
    yield '0'

    for i in range(n // 2):
        yield rubbish()

    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):
    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(
            processing.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


if __name__ == '__main__':
    print(json.dumps(evaluated_testcases(
        processing.DESCFILE), sort_keys=True, indent=4))