Exemple #1
0
def run_test_memcheck(tool: str,
                      compiler: Optional[Compiler],
                      reporter: Reporter,
                      tests: List[str],
                      config: Config,
                      timeout: Optional[float] = None) -> bool:
    reporter.log(f'Running tests with cuda-memcheck --tool {tool}', 'title')
    runner = MemcheckRunner(tool)
    compiler = config.find_compiler() if compiler is None else compiler
    if compiler is None:
        raise RuntimeError("Could not find a suitable compiler")
    compiler = config.common_flags(compiler).add_flag('-O3').add_flag(
        '-g').add_flag('-Xcompiler', '-rdynamic').add_flag('-lineinfo')
    orig_tests = tests
    tests = expand_glob(tests, ['tests/*medium*'])
    if not tests:
        no_tests_error(orig_tests, ['tests'])

    return run_test(compiler=compiler,
                    runner=runner,
                    reporter=reporter,
                    name=f'test-memcheck-{tool}',
                    tests=tests,
                    config=config,
                    timeout=timeout)
Exemple #2
0
def run_test_asan(compiler: Optional[Compiler],
                  reporter: Reporter,
                  tests: List[str],
                  config: Config,
                  timeout: Optional[float] = None) -> bool:
    reporter.log('Running tests with address sanitizer', 'title')
    runner = AsanRunner()
    compiler = config.find_compiler() if compiler is None else compiler
    if compiler is None:
        sys.exit("I'm sorry, I could not find a suitable compiler.")
    if isinstance(compiler, NvccCompiler):
        compiler = config.common_flags(compiler).add_flag(
            '-Xcompiler',
            '"-fsanitize=address"').add_flag('-Xcompiler',
                                             '"-fsanitize=undefined"')
        runner.env[
            'ASAN_OPTIONS'] = 'protect_shadow_gap=0:replace_intrin=0:detect_leaks=0'
    else:
        compiler = config.common_flags(compiler).add_flag(
            '-fsanitize=address').add_flag('-fsanitize=undefined')
    compiler = compiler.add_flag('-g')
    orig_tests = tests
    tests = expand_glob(tests, ['tests/*'])
    if not tests:
        no_tests_error(orig_tests, ['tests'])

    return run_test(compiler=compiler,
                    runner=runner,
                    reporter=reporter,
                    name='test-asan',
                    tests=tests,
                    config=config,
                    timeout=timeout)
Exemple #3
0
def run_test_tsan(compiler: Compiler,
                  reporter: Reporter,
                  tests: List[str],
                  config: Config,
                  timeout: Optional[float] = None) -> bool:
    reporter.log('Running tests with thread sanitizer', 'title')

    reporter.log('Not implemented')
    return True

    runner = TsanRunner()
    compiler = config.find_compiler() if compiler is None else compiler
    if not isinstance(compiler, ClangCompiler):
        reporter.log(
            'Thread sanitizer is supported only with clang. Skipping test')
        return True

    compiler = common_flags(compiler).add_flag('-fsanitize=thread')
    orig_tests = tests
    tests = expand_glob(tests, ['tests/*'])
    if not tests:
        no_tests_error(orig_tests, ['tests'])

    return run_test(compiler=compiler,
                    runner=runner,
                    reporter=reporter,
                    name='test-tsan',
                    tests=tests,
                    timeout=timeout)
Exemple #4
0
def run_test_uninit(compiler: Optional[Compiler],
                    reporter: Reporter,
                    tests: List[str],
                    config: Config,
                    timeout: Optional[float] = None) -> bool:
    reporter.log('Running tests with uninitialized variable check', 'title')
    runner = Runner()
    compiler = find_clang_compiler() if compiler is None else compiler
    if compiler is None:
        sys.exit("I'm sorry, I could not find a suitable clang compiler.")
    if isinstance(compiler, ClangCompiler) and compiler.version[0] < 8:
        sys.exit(f"I'm sorry, but the clang compiler {compiler} is too old.")

    compiler = config.common_flags(compiler).add_flag('-O3').add_flag(
        '-g').add_flag('-ftrivial-auto-var-init=pattern')
    orig_tests = tests
    tests = expand_glob(tests, ['tests/*', 'benchmarks/*'])
    if not tests:
        no_tests_error(orig_tests, ['tests', 'benchmarks'])

    return run_test(compiler=compiler,
                    runner=runner,
                    reporter=reporter,
                    name='test-uninit',
                    tests=tests,
                    config=config,
                    timeout=timeout)
Exemple #5
0
def compile_assembly(compiler: Compiler,
                     reporter: Reporter,
                     tests: List[str],
                     config: Config,
                     timeout: Optional[float] = None) -> bool:
    reporter.log('Compiling to assembly', 'title')
    compiler = config.find_compiler() if compiler is None else compiler
    if compiler is None:
        raise RuntimeError("Could not find a suitable compiler")
    compiler = config.common_flags(compiler).add_flag('-O3').add_flag(
        '-S').add_flag('-fverbose-asm')

    rep = reporter.analysis_group('assembly')
    output = rep.compilation(compiler.add_source(
        config.source)).compile(out_file=config.binary)
    if not output.is_success():
        return False

    rep.analyze(open(config.binary, 'r').read())

    return True
Exemple #6
0
def run_test_plain(compiler: Optional[Compiler],
                   reporter: Reporter,
                   tests: List[str],
                   config: Config,
                   timeout: Optional[float] = None) -> bool:
    reporter.log('Running tests', 'title')
    runner = Runner()
    compiler = config.find_compiler() if compiler is None else compiler
    if compiler is None:
        sys.exit("I'm sorry, I could not find a suitable compiler.")
    compiler = config.common_flags(compiler).add_flag('-O3').add_flag('-g')
    orig_tests = tests
    tests = expand_glob(tests, ['tests/*', 'benchmarks/*'])
    if not tests:
        no_tests_error(orig_tests, ['tests', 'benchmarks'])

    return run_test(compiler=compiler,
                    runner=runner,
                    reporter=reporter,
                    name='test-plain',
                    tests=tests,
                    config=config,
                    timeout=timeout)
Exemple #7
0
def run_benchmark_all(compiler: Optional[Compiler],
                      reporter: Reporter,
                      tests: List[str],
                      config: Config,
                      timeout: Optional[float] = None) -> bool:
    reporter.log('Running benchmark', 'title')
    runner = Runner()
    compiler = config.find_compiler() if compiler is None else compiler
    if compiler is None:
        raise RuntimeError("Could not find a suitable compiler")
    compiler = config.common_flags(compiler).add_flag('-O3').add_flag('-g')
    orig_tests = tests
    tests = expand_glob(tests, ['benchmarks/*'])
    if not tests:
        no_tests_error(orig_tests, ['benchmarks'])

    return run_benchmark(compiler=compiler,
                         runner=runner,
                         reporter=reporter,
                         name='benchmark-all',
                         tests=tests,
                         config=config,
                         timeout=timeout)
Exemple #8
0
def compile_assembly(compiler: Compiler,
                     reporter: Reporter,
                     tests: List[str],
                     config: Config,
                     timeout: Optional[float] = None) -> bool:
    reporter.log('Compiling to assembly', 'title')
    compiler = config.find_compiler() if compiler is None else compiler
    if compiler is None:
        raise RuntimeError("Could not find a suitable compiler")
    compiler = config.common_flags(compiler).add_flag('-O3').add_flag(
        '-S').add_flag('-fverbose-asm')

    rep = reporter.analysis_group('assembly')
    output = rep.compilation(compiler.add_source(
        config.source)).compile(out_file=config.binary)
    if not output.is_success():
        return False

    assembly = open(config.binary, 'r').read()
    if len(assembly.encode('utf-8')) > MAX_ASSEMBLY_OUTPUT:
        assembly = "Generated assembly was too long and wasn't stored"
    rep.analyze(assembly)

    return True
Exemple #9
0
def run_benchmark(compiler: Compiler,
                  runner: Runner,
                  reporter: Reporter,
                  name: str,
                  tests: List[str],
                  config: Config,
                  timeout: Optional[float] = None) -> bool:
    rep = reporter.benchmark_group(name, tests)
    output = rep.compilation(
        compiler.add_source(config.tester).add_source(
            config.source)).compile(out_file=config.binary)
    if not output.is_success():
        return False

    for test in tests:
        runner_output = runner.run(config,
                                   config.benchmark_command(test),
                                   timeout=parse_timeout(test, timeout))
        rep.benchmark(test, runner_output)
        if runner_output.errors or not runner_output.run_successful:
            return False

    return True
Exemple #10
0
def cli(config: Config):
    parser = argparse.ArgumentParser(
        usage=f'{sys.argv[0]} [-h|--help] [options] command [tests ...]',
        description=f'''
PPC grading tool

Run all tests:
    {sys.argv[0]} test

Run all benchmarks
    {sys.argv[0]} benchmark

Run tests with address sanitizer only
    {sys.argv[0]} test-asan

Run only tests 001 and 017
    {sys.argv[0]} test tests/001 tests/017
''',
        allow_abbrev=False,
        formatter_class=argparse.RawTextHelpFormatter,
        add_help=False,
    )
    # We'll handle help manually to add tests argument in help but not when
    # parsing for the first time. Otherwise argparse asks to give both command
    # and tests even though giving zero tests suffices.
    parser.add_argument('-h',
                        '--help',
                        action=HelpAction,
                        nargs=0,
                        dest='help',
                        help='show this help message and exit')

    parser.add_argument('--json',
                        action='store_const',
                        dest='reporter',
                        default=TerminalReporter,
                        const=JsonReporter,
                        help=argparse.SUPPRESS)
    parser.add_argument('--timeout', type=float, help='timeout for each test')
    compiler_group = parser.add_mutually_exclusive_group()
    compiler_group.add_argument(
        '--clang',
        dest='compiler',
        nargs='?',
        default=None,
        const='',
        help=
        'use given clang compiler, or if left empty try to find a suitable compiler',
        type=clang_compiler)
    compiler_group.add_argument(
        '--gcc',
        dest='compiler',
        nargs='?',
        default=None,
        const='',
        help=
        'use given gcc compiler, or if left empty try to find a suitable compiler',
        type=gcc_compiler)
    compiler_group.add_argument(
        '--nvcc',
        dest='compiler',
        nargs='?',
        default=None,
        const='',
        help=
        'use given nvcc compiler, or if left empty try to find a suitable compiler',
        type=nvcc_compiler)

    parser.add_argument('--file',
                        dest='file',
                        default=config.source,
                        help='file to be graded',
                        type=str)

    parser.add_argument('--binary',
                        dest='binary',
                        default=config.binary,
                        help=argparse.SUPPRESS,
                        type=str)

    parser.add_argument(
        '--ignore-errors',
        action='store_const',
        dest='ignore_errors',
        default=False,
        const=True,
        help='run through all tests without stopping at the first error',
    )

    parser.add_argument(
        '-v',
        '--verbose',
        action=VerboseAction,
        nargs=0,
        help=
        'show the commands that I run (give twice to make me more talkative)')

    parser.add_argument(
        'commands',
        metavar='command',
        type=command_type(config.gpu),
        help='command to run, for example \'test\' or \'benchmark\'')

    # Rest of the arguments are considered to be tests
    args, tests = parser.parse_known_args()

    # Check that there aren't any extra flags
    for test in tests:
        if test.startswith('-'):
            sys.exit(f'{sys.argv[0]}: error: Unknown flag {test}')
    reporter = args.reporter(config)
    compiler = args.compiler
    timeout = args.timeout

    config.source = args.file
    config.binary = args.binary

    config.ignore_errors = args.ignore_errors

    for command in args.commands:
        passed = command(compiler=compiler,
                         reporter=reporter,
                         tests=tests,
                         timeout=timeout,
                         config=config)
        if not passed:
            break

    reporter.finalize()