Skip to content

Generator

TestcaseGenerator

1
2
3
4
5
6
7
8
9
The generator class.

!!! attributes
    values ValueGroup: Structure to build the testcase on.
    output_dir Path: Folder where the generated testcase files will be saved.
    answer_script Path: Script that can solve the testcase to produce the correct stdout.
    stdin_filename_format str: Filename used for stdin. There is 2 placeholders: subtask name and testcase number.
    stdout_filename_format str: Filename used for stdout. There is 2 placeholders: subtask name and testcase number.
    newline: Preferred newline format used for stdin and stdout files. Defaults to

.

answer_script

newline

output_directory

stdin_filename_format

stdout_filename_format

values

new_subtask(self, no_of_testcase, name=None)

Creates a new subtask to work with.

Parameters:

Name Type Description Default
no_of_testcase int

The number of testcases to generate for this subtask.

required
name str

Name of the subtask. To be reflected in testcase filename.

None

Returns:

Type Description
Subtask

The new subtask object.

Source code in testcase_maker/generator.py
def new_subtask(self, no_of_testcase: int, name: str = None) -> Subtask:
    """
    Creates a new subtask to work with.

    Args:
        no_of_testcase: The number of testcases to generate for this subtask.
        name: Name of the subtask. To be reflected in testcase filename.

    returns:
        The new subtask object.
    """
    if not name:
        name = str(len(self._subtasks) + 1)

    subtask = Subtask(name, no_of_testcase)
    self._subtasks.append(subtask)
    return subtask

generate(self, override=False)

Generates both stdin and stdout for testcases.

Parameters:

Name Type Description Default
override bool

Set to True if you want to override existing testcase files (if any). Defaults to False.

False
Source code in testcase_maker/generator.py
def generate(self, override: bool = False):
    """
    Generates both stdin and stdout for testcases.

    Args:
        override: Set to ``True`` if you want to override existing testcase files (if any). Defaults to ``False``.
    """
    self.generate_stdin(override)
    self.generate_stdout(override)

generate_stdin(self, override=False)

Generates stdin for testcases.

Parameters:

Name Type Description Default
override bool

Set to True if you want to override existing testcase files (if any). Defaults to False.

False
Source code in testcase_maker/generator.py
def generate_stdin(self, override: bool = False):
    """
    Generates stdin for testcases.

    Args:
        override: Set to ``True`` if you want to override existing testcase files (if any). Defaults to ``False``.
    """
    self._pre_generation()

    for subtask in self._subtasks:
        for testcase_no, overrides in subtask.iterate():
            start = timer()
            log.info(f"Generating stdin for subtask '{subtask.name}', testcase '{testcase_no}'...")

            stdin_file = self._stdin_path(subtask.name, testcase_no)
            if stdin_file.is_file() and not override:
                log.info(f"Skipped '{stdin_file}' as file already exist.")
                continue

            resolver = Resolver(overrides)
            stdin = resolver.resolve(self.values)

            with open(stdin_file, "w", newline=self.newline) as input_buffer:
                input_buffer.write(stdin)
                input_buffer.write(self.newline)
            end = timer()
            log.info(f"Saved '{stdin_file}'. Took {end-start} seconds.")

generate_stdout(self, override=False)

Generates stdout for testcases.

Notice

Valid stdin files must be generated and present first.

Parameters:

Name Type Description Default
override bool

Set to True if you want to override existing testcase files (if any). Defaults to False.

False
Source code in testcase_maker/generator.py
def generate_stdout(self, override: bool = False):
    """
    Generates stdout for testcases.

    !!! danger "Notice"
        Valid stdin files must be generated and present first.

    Args:
        override: Set to ``True`` if you want to override existing testcase files (if any). Defaults to ``False``.
    """
    self._pre_generation()

    if not self.answer_script:
        log.error("Unable to generate stdout as there is no answer script specified.")
        return

    with get_executor_for_script(self.answer_script) as executor:
        for subtask in self._subtasks:
            for testcase_no in range(1, subtask.no_of_testcase + 1):
                start = timer()
                log.info(f"Generating stdout for subtask '{subtask.name}', testcase '{testcase_no}'...")

                stdin_file = self._stdin_path(subtask.name, testcase_no)
                if not stdin_file.is_file():
                    log.info(f"Skipped as stdin '{stdin_file}' does not exist.")
                    continue
                with open(stdin_file, "r", newline=self.newline) as input_buffer:
                    stdin = input_buffer.read()

                stdout_file = self._stdout_path(subtask.name, testcase_no)
                if stdout_file.is_file() and not override:
                    log.info(f"Skipped '{stdout_file}' as file already exist.")
                    continue

                stdout = self._execute_script(stdin, executor)
                with open(stdout_file, "w", newline=self.newline) as output_buffer:
                    output_buffer.write(stdout)

                end = timer()
                log.info(f"Saved '{stdout_file}'. Took {end-start} seconds.")

validate(self)

Checks that answer script matches the stdout for the respective stdin.

Source code in testcase_maker/generator.py
def validate(self):
    """
    Checks that answer script matches the stdout for the respective stdin.
    """
    if not self.answer_script:
        log.error("Unable to validate stdout as there is no answer script specified.")
        return

    with get_executor_for_script(self.answer_script) as executor:
        for subtask in self._subtasks:
            for testcase_no in range(1, subtask.no_of_testcase + 1):
                start = timer()
                log.info(f"Validating stdout for subtask '{subtask.name}', testcase '{testcase_no}'...")

                stdin_file = self._stdin_path(subtask.name, testcase_no)
                if not stdin_file.is_file():
                    log.warning(f"Skipped as stdin '{stdin_file}' does not exist.")
                    continue
                with open(stdin_file, "r", newline=self.newline) as input_buffer:
                    stdin = input_buffer.read()

                stdout_file = self._stdout_path(subtask.name, testcase_no)
                if not stdout_file.is_file():
                    log.warning(f"Skipped as stdout '{stdout_file}' does not exist.")
                    continue

                with open(stdout_file, "r", newline=self.newline) as output_buffer:
                    stdout = output_buffer.read()

                actual_stdout = self._execute_script(stdin, executor)
                if actual_stdout.rstrip() != stdout.rstrip():
                    log.warning(f"Incorrect stdout detected, got {actual_stdout} instead of {stdout}.")
                else:
                    log.info(f"Correct!")

                end = timer()
                log.info(f"Validated '{stdout_file}'. Took {end-start} seconds.")

log