def test_execute(): with TemporaryCwd(): rc, out = execute(['echo', '2']) eq_(rc, 0) eq_(out, '2\n') rc, out = execute(['exit', '1'], ignore_errors=True) eq_(rc, 1) assert_raises(ExecError, execute, ['exit', '1']) rc, out = execute(['mkdir', tempcwd('spam')]) eq_(rc, 0) rc, out = execute(['ls', tempcwd()]) in_('spam', out)
def run(environ): exe_file = ft.download(environ, 'exe_file', 'exe', add_to_cache=True) os.chmod(exe_file, 0700) in_file = ft.download(environ, 'in_file', 'in', add_to_cache=True) env = os.environ.copy() for key, default in _options: value = environ.get('exec_' + key.lower(), default) env[key] = value with get_sandbox('vcpu_exec-sandbox') as sandbox: retcode, output = execute( [os.path.join(sandbox.path, 'pin-supervisor/supervisor-bin/', 'supervisor'), '-f', '3', '--', './exe', noquote('<'), 'in', noquote('3>'), 'supervisor_result', noquote('>'), 'out'], env=env) result_file = open('supervisor_result') status_line = result_file.readline().strip().split() environ['result_string'] = result_file.readline().strip() result_file.close() try: for num, key in enumerate((None, 'result_code', 'time_used', 'exectime_used', 'mem_used', 'num_syscalls')): if key: environ[key] = int(status_line[num]) result_code = _supervisor_result_to_code(environ['result_code']) except Exception, e: result_code = 'SE' for i in ('time_used', 'exectime_used', 'mem_used', 'num_syscalls'): environ.setdefault(i, 0) environ['result_string'] = str(e)
def run(environ, no_sandbox=False): ft.download(environ, 'out_file', 'out', skip_if_exists=True) ft.download(environ, 'hint_file', 'hint', add_to_cache=True) if environ.get('chk_file'): sandbox = NullSandbox() ft.download(environ, 'in_file', 'in', skip_if_exists=True, add_to_cache=True) ft.download(environ, 'chk_file', 'chk', add_to_cache=True) os.chmod('chk', 0700) cmd = ['./chk', 'in', 'out', 'hint', noquote('2>'), '/dev/null'] elif no_sandbox: sandbox = NullSandbox() cmd = ['diff', '-b', '-q', 'out', 'hint', noquote('>'), '/dev/null', noquote('2>&1'), noquote('&&'), 'echo', 'OK'] else: sandbox = get_sandbox('exec-sandbox') cmd = [os.path.join(sandbox.path, 'bin', 'compare'), 'hint', 'out', noquote('2>'), '/dev/null'] with sandbox: retcode, output = execute(cmd, ignore_errors=True, split_lines=True) while len(output) < 3: output.append('') if output[0] == 'OK': environ['result_code'] = 'OK' if output[1]: environ['result_string'] = output[1] environ['result_percentage'] = float(output[2] or 100) else: environ['result_code'] = 'WA' environ['result_string'] = output[1] environ['result_percentage'] = 0 return environ
def run(environ): exe_file = ft.download(environ, 'exe_file', 'exe', add_to_cache=True) os.chmod(exe_file, 0700) in_file = ft.download(environ, 'in_file', 'in', add_to_cache=True) if 'exec_time_limit' in environ: time_limit = environ['exec_time_limit'] time_ulimit = (time_limit + 999) / 1000 else: time_limit = time_ulimit = None if 'exec_mem_limit' in environ: mem_limit = environ['exec_mem_limit'] / 1024 else: mem_limit = None retcode, output = execute(['bash', '-c', 'time ./exe < in > out'], time_limit=time_ulimit, mem_limit=mem_limit, ignore_errors=True) time_output_matches = TIME_OUTPUT_RE.findall(output) if time_output_matches: mins, secs = time_output_matches[-1] time_used = int((int(mins) * 60 + float(secs)) * 1000) else: raise RuntimeError('Could not find output of time program. ' 'Captured output: %s' % output) if time_limit is not None and time_used >= 0.99 * time_limit: environ['result_string'] = 'time limit exceeded' environ['result_code'] = 'TLE' elif retcode == 0: environ['result_string'] = 'ok' environ['result_code'] = 'OK' else: environ['result_string'] = 'program exited with code %d' % retcode environ['result_code'] = 'RE' environ['time_used'] = time_used environ['exectime_used'] = 0 environ['mem_used'] = 0 environ['num_syscalls'] = 0 if environ['result_code'] == 'OK' and environ.get('check_output'): environ = checker.run(environ, no_sandbox=True) if 'out_file' in environ: ft.upload(environ, 'out_file', 'out', to_remote_store=environ.get('upload_out', False)) return environ
def compile_and_run(compiler_env, expected_output): """Helper function for compiling, launching and testing the result of a program. """ run(compiler_env) binary = ft.download({'path': '/out'}, 'path') os.chmod(binary, stat.S_IXUSR) retcode, output = execute(['./' + binary]) eq_(retcode, 0) eq_(output.strip(), expected_output) os.remove(binary)
def compile_and_run(compiler_env, expected_output): """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'] result_env = run(compiler_env) eq_(result_env['result_code'], 'OK') binary = ft.download({'path': out_file}, 'path') os.chmod(binary, stat.S_IXUSR) retcode, output = execute(['./' + binary]) eq_(retcode, 0) eq_(output.strip(), expected_output) os.remove(binary)
def run(environ, lang, compiler, extension, output_file, compiler_options=(), compile_additional_sources=True, sandbox=False, sandbox_callback=None): """ Common code for compiler handlers: :param environ: Recipe to pass to `filetracker` and `sio.workers.execute` For all supported options, see the global documentation for `sio.compilers`. :param lang: Language code (for example: `c`, `cpp`, `pas`) :param compiler: Compiler binary name :param extension: Usual extension for source files of the given language. :param output_file: Default output binary file, assuming the input is named `a.<extension>` :param compiler_options: Optional tuple of command line parameters to the compiler. :param compile_additional_sources: Disables passing additional source files to the compiler - used as a hack to support FPC. Defaults to False. :param sandbox: Enables sandboxing (using compiler name as a sandbox). Defaults to False. :param sandbox_callback: Optional callback called immediately after creating the sandbox, with the said sandbox as its sole parameter. """ if sandbox is True: sandbox = get_sandbox('compiler-' + environ['compiler']) elif not sandbox: sandbox = NullSandbox() extra_compilation_args = \ _lang_option(environ, 'extra_compilation_args', lang) ft.download(environ, 'source_file', 'a.' + extension) cmdline = (compiler, ) + tuple(compiler_options) + \ tuple(extra_compilation_args) + ('a.' + extension, ) # this cmdline may be later extended # using a copy of the environment in order to avoid polluting it with # temoporary elements tmp_environ = environ.copy() additional_includes = _lang_option(environ, 'additional_includes', lang) additional_sources = _lang_option(environ, 'additional_sources', lang) for include in additional_includes: tmp_environ['additional_include'] = include ft.download(tmp_environ, 'additional_include', os.path.basename(include)) for source in additional_sources: tmp_environ['additional_source'] = source ft.download(tmp_environ, 'additional_source', os.path.basename(source)) if compile_additional_sources: cmdline += (os.path.basename(source), ) extra_files = environ.get('extra_files', {}) for name, ft_path in extra_files.iteritems(): tmp_environ['extra_file'] = ft_path ft.download(tmp_environ, 'extra_file', os.path.basename(name)) shell_environ = os.environ.copy() if sandbox: shell_environ['LD_LIBRARY_PATH'] = (lang == 'pas') \ and os.path.join(sandbox.path, 'lib') \ or os.path.join(sandbox.path, 'usr', 'lib') shell_environ['PATH'] = (lang == 'pas') \ and os.path.join(sandbox.path, 'bin') \ or os.path.join(sandbox.path, 'usr', 'bin') shell_environ['PATH'] += ':' + os.environ['PATH'] with sandbox: if sandbox_callback: sandbox_callback(sandbox) retcode, output = execute(list(cmdline), env=shell_environ, time_limit=30, mem_limit=256, ignore_errors=True, environ=tmp_environ, environ_prefix='compilation_') environ['compiler_output'] = output if retcode: environ['result_code'] = 'CE' elif 'compilation_result_size_limit' in environ and \ os.path.getsize(output_file) > \ environ['compilation_result_size_limit']: environ['result_code'] = 'CE' environ['compiler_output'] = 'Compiled file size limit exceeded.' else: environ['result_code'] = 'OK' ft.upload(environ, 'out_file', output_file) return environ