def run(environ, executor, use_sandboxes=True): """ Common code for executors. :param: environ Recipe to pass to `filetracker` and `sio.workers.executors` For all supported options, see the global documentation for `sio.workers.executors` and prefix them with ``exec_``. :param: executor Executor instance used for executing commands. :param: use_sandboxes Enables safe checking output correctness. See `sio.executors.checkers`. True by default. """ input_name = tempcwd('in') file_executor = get_file_runner(executor, environ) exe_filename = file_executor.preferred_filename() ft.download(environ, 'exe_file', exe_filename, add_to_cache=True) os.chmod(tempcwd(exe_filename), 0700) ft.download(environ, 'in_file', input_name, add_to_cache=True) zipdir = tempcwd('in_dir') os.mkdir(zipdir) try: if is_zipfile(input_name): try: # If not a zip file, will pass it directly to exe with ZipFile(tempcwd('in'), 'r') as f: if len(f.namelist()) != 1: raise Exception("Archive should have only one file.") f.extract(f.namelist()[0], zipdir) input_name = os.path.join(zipdir, f.namelist()[0]) # zipfile throws some undocumented exceptions except Exception as e: raise StandardError("Failed to open archive: " + unicode(e)) with file_executor as fe: with open(input_name, 'rb') as inf: with open(tempcwd('out'), 'wb') as outf: renv = fe(tempcwd(exe_filename), [], stdin=inf, stdout=outf, ignore_errors=True, environ=environ, environ_prefix='exec_') _populate_environ(renv, environ) if renv['result_code'] == 'OK' and environ.get('check_output'): environ = checker.run(environ, use_sandboxes=use_sandboxes) for key in ('result_code', 'result_string'): environ[key] = replace_invalid_UTF(environ[key]) if 'out_file' in environ: ft.upload(environ, 'out_file', tempcwd('out'), to_remote_store=environ.get('upload_out', False)) finally: rmtree(zipdir) return environ
def compile_and_execute(source, executor, **exec_args): cenv = compile(source, use_sandboxes=isinstance(executor, _SIOSupervisedExecutor)) frunner = get_file_runner(executor, cenv) ft.download({'exe_file': cenv['out_file']}, 'exe_file', frunner.preferred_filename()) os.chmod(tempcwd('exe'), 0700) ft.download({'in_file': '/input'}, 'in_file', 'in') with frunner: with open(tempcwd('in'), 'rb') as inf: renv = frunner(tempcwd('exe'), [], stdin=inf, **exec_args) return renv
def compile_and_run(compiler_env, expected_output, program_args=None): """Helper function for compiling, launching and testing the result of a program. """ # Dummy sandbox doesn't support asking for versioned filename out_file = compiler_env['out_file'] if compiler_env.get('compiler', '').endswith('-java'): compiler_env['compilation_time_limit'] = 180000 with TemporaryCwd('compile'): result_env = run(compiler_env) print_env(result_env) eq_(result_env['result_code'], 'OK') binary = ft.download({'path': out_file}, 'path') os.chmod(binary, stat.S_IXUSR | os.stat(binary).st_mode) if not program_args: program_args = [] executor = UnprotectedExecutor() frkwargs = {} # Hack for java if compiler_env.get('compiler') == 'default-java': executor = PRootExecutor('compiler-java.1_8') frkwargs['proot_options'] = ['-b', '/proc'] frunner = get_file_runner(executor, result_env) with frunner: renv = frunner(binary, program_args, stderr=sys.__stderr__, capture_output=True, **frkwargs) eq_(renv['return_code'], 0) eq_(renv['stdout'].decode().strip(), expected_output) os.remove(binary)
def compile_and_run(compiler_env, expected_output, program_args=None): """Helper function for compiling, launching and testing the result of a program. """ # Dummy sandbox doesn't support asking for versioned filename out_file = compiler_env['out_file'] if compiler_env.get('compiler', '').endswith('-java'): compiler_env['compilation_time_limit'] = 180000 with TemporaryCwd('compile'): result_env = run(compiler_env) print_env(result_env) eq_(result_env['result_code'], 'OK') binary = ft.download({'path': out_file}, 'path') os.chmod(binary, stat.S_IXUSR | os.stat(binary).st_mode) if not program_args: program_args = [] executor = UnprotectedExecutor() frkwargs = {} # Hack for java if compiler_env.get('compiler') == 'default-java': executor = PRootExecutor('compiler-java.1_8') frkwargs['proot_options'] = ['-b', '/proc'] frunner = get_file_runner(executor, result_env) with frunner: renv = frunner(binary, program_args, stderr=sys.__stderr__, capture_output=True, **frkwargs) eq_(renv['return_code'], 0) eq_(renv['stdout'].strip(), expected_output) os.remove(binary)
def run(environ, executor, use_sandboxes=True): """ Common code for executors. :param: environ Recipe to pass to `filetracker` and `sio.workers.executors` For all supported options, see the global documentation for `sio.workers.executors` and prefix them with ``exec_``. :param: executor Executor instance used for executing commands. :param: use_sandboxes Enables safe checking output correctness. See `sio.executors.checkers`. True by default. """ input_name = tempcwd('in') file_executor = get_file_runner(executor, environ) exe_filename = file_executor.preferred_filename() ft.download(environ, 'exe_file', exe_filename, add_to_cache=True) os.chmod(tempcwd(exe_filename), 0o700) ft.download(environ, 'in_file', input_name, add_to_cache=True) zipdir = tempcwd('in_dir') os.mkdir(zipdir) try: if is_zipfile(input_name): try: # If not a zip file, will pass it directly to exe with ZipFile(tempcwd('in'), 'r') as f: if len(f.namelist()) != 1: raise Exception("Archive should have only one file.") f.extract(f.namelist()[0], zipdir) input_name = os.path.join(zipdir, f.namelist()[0]) # zipfile throws some undocumented exceptions except Exception as e: raise Exception("Failed to open archive: " + six.text_type(e)) with file_executor as fe: with open(input_name, 'rb') as inf: # Open output file in append mode to allow appending # only to the end of the output file. Otherwise, # a contestant's program could modify the middle of the file. with open(tempcwd('out'), 'ab') as outf: renv = fe(tempcwd(exe_filename), [], stdin=inf, stdout=outf, ignore_errors=True, environ=environ, environ_prefix='exec_') _populate_environ(renv, environ) if renv['result_code'] == 'OK' and environ.get('check_output'): environ = checker.run(environ, use_sandboxes=use_sandboxes) for key in ('result_code', 'result_string'): environ[key] = replace_invalid_UTF(environ[key]) if 'out_file' in environ: ft.upload(environ, 'out_file', tempcwd('out'), to_remote_store=environ.get('upload_out', False)) finally: rmtree(zipdir) return environ
def run(environ, executor, use_sandboxes=True): """ Common code for executors. :param: environ Recipe to pass to `filetracker` and `sio.workers.executors` For all supported options, see the global documentation for `sio.workers.executors` and prefix them with ``exec_``. :param: executor Executor instance used for executing commands. :param: use_sandboxes Enables safe checking output correctness. See `sio.executors.checkers`. True by default. """ if feedback.judge_prepare(environ).force_not_judge: environ['time_used'] = 0 environ['result_string'] = 'not judged' environ['result_code'] = 'NJ' environ['mem_used'] = 0 environ['num_syscalls'] = 0 environ['stderr'] = '' return environ input_name = tempcwd('in') file_executor = get_file_runner(executor, environ) exe_filename = file_executor.preferred_filename() ft.download(environ, 'exe_file', exe_filename, add_to_cache=True) os.chmod(tempcwd(exe_filename), 0700) ft.download(environ, 'in_file', input_name, add_to_cache=True) zipdir = tempcwd('in_dir') os.mkdir(zipdir) try: if is_zipfile(input_name): try: # If not a zip file, will pass it directly to exe with ZipFile(tempcwd('in'), 'r') as f: if len(f.namelist()) != 1: raise Exception("Archive should have only one file.") f.extract(f.namelist()[0], zipdir) input_name = os.path.join(zipdir, f.namelist()[0]) # zipfile throws some undocumented exceptions except Exception as e: raise StandardError("Failed to open archive: " + unicode(e)) with file_executor as fe: with open(input_name, 'rb') as inf: with open(tempcwd('out'), 'wb') as outf: feedback.judge_started(environ) renv = fe(tempcwd(exe_filename), [], stdin=inf, stdout=outf, ignore_errors=True, environ=environ, environ_prefix='exec_') _populate_environ(renv, environ) if renv['result_code'] == 'OK' and environ.get('check_output'): environ = checker.run(environ, use_sandboxes=use_sandboxes) for key in ('result_code', 'result_string'): environ[key] = replace_invalid_UTF(environ[key]) feedback.judge_finished(environ) if 'out_file' in environ: ft.upload(environ, 'out_file', tempcwd('out'), to_remote_store=environ.get('upload_out', False)) finally: rmtree(zipdir) return environ