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
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(), )