Example #1
0
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)
Example #2
0
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)
Example #3
0
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)
Example #4
0
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
Example #5
0
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
Example #6
0
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)
Example #7
0
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)
Example #8
0
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