def evaluate_output(task_name, input_path, output_path):
     """
     Given an input of a task, evaluate the correctness of the output
     :param task_name: Name of the task
     :param input_path: Path to the user's input file
     :param output_path: Path to the user's output file
     :return: The stdout of the checker
     """
     try:
         # call the checker and store the output
         start_time = time.monotonic()
         output = gevent.subprocess.check_output([
             ContestManager.tasks[task_name]["checker"],
             StorageManager.get_absolute_path(input_path),
             StorageManager.get_absolute_path(output_path)
         ])
         if time.monotonic() > start_time + 1:
             Logger.warning(
                 "TASK", "Evaluation of output %s "
                 "for task %s, with input %s, took %f "
                 "seconds" % (output_path, task_name, input_path,
                              time.monotonic() - start_time))
     except:
         # TODO log the stdout and stderr of the checker
         Logger.error(
             "TASK", "Error while evaluating output %s "
             "for task %s, with input %s: %s" %
             (output_path, task_name, input_path, traceback.format_exc()))
         raise
     Logger.info(
         "TASK", "Evaluated output %s for task %s, with input %s" %
         (output_path, task_name, input_path))
     return output
    def test_get_absolute_path(self):
        backup = Config.storedir
        Config.storedir = Utils.new_tmp_dir()

        relative_path = 'path/to/file'
        abs_path = StorageManager.get_absolute_path(relative_path)

        self.assertTrue(abs_path.find(Config.storedir) >= 0)
        self.assertTrue(abs_path.find(relative_path) >= 0)

        Config.storedir = backup
    def test_rename_file(self):
        backup = Config.storedir
        Config.storedir = Utils.new_tmp_dir()

        relative_path = 'baz/file.txt'
        new_path = 'baz/txt.elif'
        StorageManager.save_file(relative_path, 'foobar'.encode())
        StorageManager.rename_file(relative_path, new_path)

        with open(StorageManager.get_absolute_path(new_path), 'r') as file:
            lines = file.readlines()
            self.assertEqual('foobar', lines[0])

        Config.storedir = backup
    def test_save_file(self):
        backup = Config.storedir
        Config.storedir = Utils.new_tmp_dir("new_path")

        relative_path = os.path.join("baz", "file.txt")
        content = 'This is the content of the file'

        try:
            os.remove(Config.storedir)
        except:
            pass

        StorageManager.save_file(relative_path, content.encode())
        with open(StorageManager.get_absolute_path(relative_path),
                  'r') as file:
            file_content = file.readlines()
            self.assertEqual(1, len(file_content))
            self.assertEqual(content, file_content[0])

        Config.storedir = backup
Пример #5
0
    def worker(task_name):
        """ Method that stays in the background and generates inputs """
        task = ContestManager.tasks[task_name]
        queue = ContestManager.input_queue[task_name]

        while True:
            try:
                id = Database.gen_id()
                path = StorageManager.new_input_file(id, task_name, "invalid")
                seed = int(sha256(id.encode()).hexdigest(), 16) % (2**31)

                stdout = os.open(
                    StorageManager.get_absolute_path(path),
                    os.O_WRONLY | os.O_CREAT,
                    0o644,
                )

                try:
                    start_time = time.monotonic()
                    # generate the input and store the stdout into a file
                    retcode = gevent.subprocess.call(
                        [task["generator"], str(seed), "0"], stdout=stdout)
                    if time.monotonic() > start_time + 1:
                        Logger.warning(
                            "TASK",
                            "Generation of input %s for task %s took %f seconds"
                            % (seed, task_name, time.monotonic() - start_time),
                        )
                finally:
                    os.close(stdout)

                if retcode != 0:
                    Logger.error(
                        "TASK",
                        "Error %d generating input %s (%d) for task %s" %
                        (retcode, id, seed, task_name),
                    )
                    # skip the input
                    continue

                # if there is a validator in the task use it to check if the
                # generated input is valid
                if "validator" in task:
                    stdin = os.open(StorageManager.get_absolute_path(path),
                                    os.O_RDONLY)
                    try:
                        start_time = time.monotonic()
                        # execute the validator piping the input file to stdin
                        retcode = gevent.subprocess.call(
                            [task["validator"], "0"], stdin=stdin)
                        if time.monotonic() > start_time + 1:
                            Logger.warning(
                                "TASK",
                                "Validation of input %s for task %s took %f "
                                "seconds" % (seed, task_name,
                                             time.monotonic() - start_time),
                            )
                    finally:
                        os.close(stdin)

                    if retcode != 0:
                        Logger.error(
                            "TASK",
                            "Error %d validating input %s (%d) for task %s" %
                            (retcode, id, seed, task_name),
                        )
                        # skip the input
                        continue

                Logger.debug(
                    "TASK",
                    "Generated input %s (%d) for task %s" %
                    (id, seed, task_name),
                )
                # this method is blocking if the queue is full
                queue.put({"id": id, "path": path})
            except:
                Logger.error(
                    "TASK",
                    "Exception while creating an input file: " +
                    traceback.format_exc(),
                )