Esempio n. 1
0
def grade_from_lang(lang, source, iospec, **kwargs):
    """A version of grade_from_manager() in which both the inputs and ouputs
    can be converted to JSON."""

    manager = manager_from_lang(lang, source)
    iospec = IoSpec.from_json(iospec)
    result = grade_from_manager(manager, iospec, **kwargs)
    return result.to_json()
Esempio n. 2
0
def grade_from_lang(lang, source, iospec, **kwargs):
    """A version of grade_from_manager() in which both the inputs and ouputs
    can be converted to JSON."""

    manager = manager_from_lang(lang, source)
    iospec = IoSpec.from_json(iospec)
    result = grade_from_manager(manager, iospec, **kwargs)
    return result.to_json()
Esempio n. 3
0
def run(source,
        inputs,
        lang=None,
        *,
        timeout=None,
        raises=False,
        path=None,
        sandbox=True):
    """Run program with the given list of inputs and returns the
    corresponding :cls:`iospec.IoSpec` instance.

    Parameters
    ----------

    source : str or file
        The source code for the test program
    inputs : sequence
        A sequence of input strings. If input is a sequence of sequences,
        this function will perform multiple test cases. It can also be a IoSpec
        or a TestCase instance which are used to extract the necessary input
        strings.
    lang : str
        The name for the source code language. See
        :func:`ejudge.graders.io.grade` for more details.
    timeout : float
        A time limit for the entire run (in seconds). If this attribute is not
        given, the program will run without any timeout. This can be potentially
        dangerous if the input program has an infinite loop.
    sandbox : bool
        Controls if code is run in sandboxed mode or not. Sandbox protection
        is the default behavior on supported platforms.
    raises : bool
        If True, raise a BuildError if the build process fails. The default
        behavior is to return a IoSpec instance with a single ErrorTestCase with
        a type string of 'error-build'.
    path : str
        The absolute file path for the input string or file object.

    Returns
    -------

    A :cls:`iospec.IoSpec` structure. If ``inputs`` is a sequence of strings,
    the resulting tree will have a single test case.
    """

    manager = get_manager(lang, source, path)
    manager.is_sandboxed = sandbox

    # Normalize inputs
    if isinstance(inputs, (IoSpec, TestCase)):
        inputs = inputs.inputs()
    else:
        if isinstance(inputs[0], str):
            inputs = [list(inputs)]
        else:
            inputs = [list(x) for x in inputs]

    # Execute
    with manager.keep_cwd():
        if sandbox:
            imports = manager.modules()
            result = run_sandbox(
                run_from_lang,
                args=(manager.lang, manager.source, inputs),
                kwargs={
                    'raises': raises,
                    'timeout': timeout
                },
                imports=imports,
            )
            result = IoSpec.from_json(result)
        else:
            result = run_from_manager(manager,
                                      inputs,
                                      raises=raises,
                                      timeout=timeout)
    return result
Esempio n. 4
0
def run_worker(source, inputs, lang=None, *,
               fast=False, timeout=None, raises=False, path=None, sandbox=True,
               compare_streams=False, is_sandboxed=False, fake_sandbox=False,
               debug=False):
    # Normalize inputs
    if isinstance(inputs, (IoSpec, TestCase)):
        inputs = inputs.inputs()
    else:
        if inputs and isinstance(inputs[0], str):
            inputs = [list(inputs)]
        else:
            inputs = [list(map(str, x)) for x in inputs]

    # Validate params
    if timeout is not None and timeout <= 0:
        raise ValueError('timeout must be positive, got: %s' % timeout)
    if sandbox and is_sandboxed:
        raise ValueError('cannot set sandbox = is_sandboxed = True')

    # Create build manager
    build_manager = registry.build_manager_from_path(
        lang, source, path,
        is_sandboxed=is_sandboxed,
        compare_streams=compare_streams,
    )

    # Run in sandboxed mode
    if sandbox:
        logger.debug('executing %s program inside sandbox' % lang)
        imports = build_manager.get_modules()
        args = (source, inputs, lang)
        kwargs = {
            'raises': raises,
            'timeout': timeout,
            'fast': fast,
            'path': path,
            'sandbox': False,
            'compare_streams': compare_streams,
            'is_sandboxed': True,
        }

        if fake_sandbox:
            result, messages = run_worker(*args, **kwargs)
        else:
            try:
                with capture_print() as data:
                    result, messages = run_sandbox(
                        run_worker,
                        args=args,
                        kwargs=kwargs,
                        imports=imports,
                        print_messages=True,
                    )
            except Exception:
                print(data.read(), file=sys.stderr)
                raise

        for (level, message) in messages:
            getattr(logger, level)(message)

        return IoSpec.from_json(result), []

    # Prepare build manager
    try:
        build_manager.build()
    except BuildError as ex:
        if raises:
            raise
        result = IoSpec([ErrorTestCase.build(error_message=str(ex))])
        if is_sandboxed:
            return result.to_json(), []
        else:
            return result, []

    # Run all examples with the execution manager
    data = []
    language = build_manager.language
    for input_strings in inputs:
        ctrl = registry.execution_manager(language, build_manager,
                                          input_strings)
        result = ctrl.run(timeout)
        assert isinstance(result, TestCase)
        data.append(result)
        if fast and result.is_error_test_case:
            break

    build_manager.log('info', 'executed all %s testcases in %s sec' %
                      (len(inputs), build_manager.execution_duration))

    # Prepare resulting iospec object
    result = IoSpec(data)
    result.set_meta('lang', build_manager.language)
    if is_sandboxed:
        return result.to_json(), build_manager.messages
    else:
        return result, []
Esempio n. 5
0
def run(source, inputs, lang=None, *,
        timeout=None, raises=False, path=None, sandbox=True):
    """Run program with the given list of inputs and returns the
    corresponding :cls:`iospec.IoSpec` instance.

    Parameters
    ----------

    source : str or file
        The source code for the test program
    inputs : sequence
        A sequence of input strings. If input is a sequence of sequences,
        this function will perform multiple test cases. It can also be a IoSpec
        or a TestCase instance which are used to extract the necessary input
        strings.
    lang : str
        The name for the source code language. See
        :func:`ejudge.graders.io.grade` for more details.
    timeout : float
        A time limit for the entire run (in seconds). If this attribute is not
        given, the program will run without any timeout. This can be potentially
        dangerous if the input program has an infinite loop.
    sandbox : bool
        Controls if code is run in sandboxed mode or not. Sandbox protection
        is the default behavior on supported platforms.
    raises : bool
        If True, raise a BuildError if the build process fails. The default
        behavior is to return a IoSpec instance with a single ErrorTestCase with
        a type string of 'error-build'.
    path : str
        The absolute file path for the input string or file object.

    Returns
    -------

    A :cls:`iospec.IoSpec` structure. If ``inputs`` is a sequence of strings,
    the resulting tree will have a single test case.
    """

    manager = get_manager(lang, source, path)
    manager.is_sandboxed = sandbox

    # Normalize inputs
    if isinstance(inputs, (IoSpec, TestCase)):
        inputs = inputs.inputs()
    else:
        if isinstance(inputs[0], str):
            inputs = [list(inputs)]
        else:
            inputs = [list(x) for x in inputs]

    # Execute
    with manager.keep_cwd():
        if sandbox:
            imports = manager.modules()
            result = run_sandbox(
                run_from_lang,
                args=(manager.lang, manager.source, inputs),
                kwargs={'raises': raises, 'timeout': timeout},
                imports=imports,
            )
            result = IoSpec.from_json(result)
        else:
            result = run_from_manager(
                manager,
                inputs,
                raises=raises,
                timeout=timeout
            )
    return result