def test_source_code(tmpdir, language_manager, repo_manager): repo = repo_manager.repo tmpdir = Path(str(tmpdir)) (tmpdir / 'src').mkdir() src_cpp1 = tmpdir / 'src' / 'aplusb.cpp' src_py1 = tmpdir / 'src' / 'code.py' shutil.copy(fspath(tests_location() / 'aplusb.cpp'), fspath(src_cpp1)) shutil.copy(fspath(tests_location() / 'code.py'), fspath(src_py1)) lang1 = language_manager.get_lang('cpp.g++11') lang2 = language_manager.get_lang('cpp.g++14') src1 = language_manager.create_source(src_cpp1, language=lang1) src1.compile() src1.runner.stdin = '2 3' assert src1.runner.stdin == '2 3' src1.run(EmptyRunProfile(repo)) assert src1.runner.stdout == '5\n' assert src1.runner.stderr == '' src2 = language_manager.create_source(src_cpp1, language=lang2) with pytest.raises(CompileError): src2.compile() src3 = language_manager.create_source(src_py1) src3.compile() src3.run(EmptyRunProfile(repo)) assert src3.runner.stdout == 'hello world\n'
def shell_str(self): if fspath(self.work_dir) == path.curdir: return '{}{}'.format(command_flags_to_str(self.flags), self._shell_str_internal()) return '{}cd {} && {}'.format(command_flags_to_str(self.flags), shlex.quote(fspath(self.work_dir)), self._shell_str_internal())
def __copyfile(self, src, dst): try: shutil.copy(fspath(src), fspath(dst)) except shutil.SameFileError as exc: pass except OSError as exc: msg = 'could not copy file \"{}\" due to OS error: {}' self.compiler_output = msg.format(fspath(src), exc.strerror) self._raise_error()
def test_make_rules(tmpdir, language_manager, repo_manager, taker_app): repo = repo_manager.repo tmpdir = Path(str(tmpdir)) (tmpdir / 'task' / 'src').mkdir() lib_dir = tmpdir / 'task' / 'lib' lib_dir.mkdir() src_cpp1 = tmpdir / 'task' / 'src' / 'aplusb.cpp' src_cpp2 = tmpdir / 'task' / 'src' / 'code_libs.cpp' src_cpp3 = tmpdir / 'task' / 'src' / 'code_gen_out.cpp' src_cpplib = tmpdir / 'task' / 'lib' / 'code_mylib.h' src_py1 = tmpdir / 'task' / 'src' / 'code.py' shutil.copy(fspath(tests_location() / 'aplusb.cpp'), fspath(src_cpp1)) shutil.copy(fspath(tests_location() / 'code_libs.cpp'), fspath(src_cpp2)) shutil.copy(fspath(tests_location() / 'code_gen_out.cpp'), fspath(src_cpp3)) shutil.copy(fspath(tests_location() / 'code_mylib.h'), fspath(src_cpplib)) shutil.copy(fspath(tests_location() / 'code.py'), fspath(src_py1)) src1 = language_manager.create_source(src_cpp1, language='cpp.g++11') rule1 = src1.add_compile_rule() src2 = language_manager.create_source(src_cpp2, language='cpp.g++14', library_dirs=[lib_dir]) rule2 = src2.add_compile_rule() src3 = language_manager.create_source(src_py1) rule3 = src3.add_compile_rule() src4 = language_manager.create_source(src_cpp3) rule4 = src4.add_compile_rule() rule5 = repo_manager.makefile.add_phony_rule('genout') src4.add_run_command(rule5, CompilerRunProfile(repo), ['arg1', 'arg2']) src4.add_run_command(rule5, 'generator', quiet=True, stdin="see '42'!", working_dir=tmpdir) assert rule3 is None assert rule4 is not None repo_manager.makefile.all_rule.add_depend(rule1) repo_manager.makefile.all_rule.add_depend(rule2) repo_manager.makefile.all_rule.add_depend(rule3) repo_manager.makefile.all_rule.add_depend(rule5) make_template = (tests_location() / 'srcbuild.make').open('r').read() make_template = make_template.format(taker_app) assert repo_manager.makefile.dump() == make_template repo_manager.build() assert src1.exe_file.exists() assert src2.exe_file.exists() assert src3.exe_file.exists() assert (tmpdir / 'output.txt').exists() assert (tmpdir / 'task' / 'src' / 'output.txt').exists()
def test_files(): infile = InputFile('q.txt') outfile = OutputFile('w.txt') assert fspath(infile) == 'q.txt' assert fspath(outfile) == 'w.txt' assert str(infile) == 'q.txt' assert InputFile('q.txt') == InputFile('q.txt') assert not InputFile('q.txt') != InputFile('q.txt') assert InputFile('q.txt') != InputFile('w.txt') assert not InputFile('q.txt') == InputFile('w.txt') assert not File('q.txt') == InputFile('q.txt') assert File('q.txt') != InputFile('q.txt') assert File('q.txt') == File('q.txt', prefix='t=')
def test_app(): old_app = consoleapp.__APP try: consoleapp.__APP = None with pytest.raises(RuntimeError): app() my_app = ConsoleApp('take') register_app(my_app) assert consoleapp.__APP is my_app with pytest.raises(RuntimeError): register_app(ConsoleApp('taker2')) assert consoleapp.__APP is my_app exe = app_exe() assert fspath(exe) == shutil.which('take') with pytest.raises(RuntimeError): app_exe('taker2') got_value = 0 def callback(value): nonlocal got_value got_value = value return 142 my_app.add_subcommand(MySubcommand(callback)) with pytest.raises(SystemExit) as exc: my_app.run(['cmd', '42']) assert exc.value.code == 142 assert got_value == 42 finally: consoleapp.__APP = old_app
def run(self, args): repo_manager = RepositoryManager() language_manager = LanguageManager(repo_manager) profile = create_profile(args.profile, repo_manager.repo) runner = ProfiledRunner(profile) cmdline = [] if args.lang is None: cmdline = [fspath(args.exe.absolute())] + args.args else: lang = language_manager.get_lang(args.lang) cmdline = lang.run_args(args.exe, args.args) if args.input is not None: runner.stdin = args.input runner.run(cmdline, args.work_dir) if args.quiet: print(runner.stdout, end='') print(runner.stderr, end='', file=sys.stderr) status = runner.results.status if status not in {Status.OK, Status.RUNTIME_ERROR}: print(Fore.RED + Style.BRIGHT + 'error: ' + Style.RESET_ALL + 'program exited with status ' + repr(status), file=sys.stderr) else: print(runner.format_results()) return runner.get_cli_exitcode()
def __arg_to_shell(self, arg): if isinstance(arg, str): return arg if isinstance(arg, File): return arg.prefix + fspath( arg.relative_to(self.repo, self.work_dir)) raise TypeError('arg has invalid type (str or File expected)')
def _do_add_command(self, command): for the_file in command.get_output_files(): the_file = fspath(the_file) if the_file not in self.files: self.output_files.add(the_file) self.files.add(the_file) for the_file in command.get_input_files(): the_file = fspath(the_file) if the_file not in self.files: self.input_files.add(the_file) self.files.add(the_file) for the_file in command.get_all_files(): the_file = fspath(the_file) self.files.add(the_file)
def __init__(self, makefile, target_name, description=None, options=DEFAULT_OPTIONS): super().__init__(makefile, target_name, description, options) self.target_file = self.target_path() / target_name self.makefile.alias(self.name, fspath(self.target_file))
def build(self, target=None): self.makefile.save() jobs = config()['make']['jobs'] if jobs is None: jobs = os.cpu_count() args = ['make', '-j', str(jobs)] if target is not None: args += [target] subprocess.check_call(args, cwd=fspath(self.repo.directory))
def compile(self): if not self.language.compile_args(self.src_file, self.exe_file): # just copy the file if not self.save_exe: return self.__copyfile(self.src_file, self.exe_file) return temp_dir = Path( mkdtemp('compilebox', '', fspath(self.repo.internal_dir(True)))) try: src = temp_dir / self.src_file.name exe = temp_dir / self.exe_file.name self.__copyfile(self.src_file, src) self.__runner.run( self.language.compile_args(src, exe, self.library_dirs)) self.compiler_output = self.__runner.format_results() if self.__runner.results.status != Status.OK: self._raise_error(self.__runner.get_cli_exitcode()) if self.save_exe: self.__copyfile(exe, self.exe_file) finally: shutil.rmtree(fspath(temp_dir))
def test_compile(repo_manager, monkeypatch): monkeypatch.chdir(fspath(repo_manager.repo.directory)) make_source() make_badsource() res = subprocess.run(['take', 'compile', 'file.cpp'], stdout=PIPE, stderr=PIPE, universal_newlines=True) assert res.returncode == 0 assert res.stdout.find('ok') >= 0 res = subprocess.run(['take', 'compile', 'bad.cpp'], stdout=PIPE, stderr=PIPE, universal_newlines=True) assert res.returncode != 0 assert res.stdout.find('compilation error') >= 0
def parameters_to_json(parameters): param_dict = parameters._asdict() param_dict = dict_keys_replace(param_dict, '_', '-') # convert paths to strings for key in param_dict: if isinstance(param_dict[key], Path): param_dict[key] = fspath(param_dict[key]) # set default values (if unset) if parameters.idle_limit is None: param_dict['idle-limit'] = 3.5 * parameters.time_limit if parameters.isolate_dir is None: param_dict['isolate-dir'] = parameters.working_dir if parameters.isolate_policy is None: param_dict['isolate-policy'] = IsolatePolicy.NORMAL param_dict['isolate-policy'] = param_dict['isolate-policy'].value # dump as JSON return json.dumps(param_dict)
def __fspath__(self): return fspath(self.filename)
def test_run(repo_manager, monkeypatch): tests_loc = tests_location() badexe_loc = bad_exe_location() monkeypatch.chdir(fspath(repo_manager.repo.directory)) shutil.copy(fspath(tests_loc / 'code_div.cpp'), '.') subprocess.run(['take', 'compile', 'code_div.cpp'], check=True, stdout=PIPE, stderr=PIPE, universal_newlines=True) code_div_exe = 'code_div' + default_exe_ext() open('input.txt', 'w').write('12 3') res = subprocess.run(['take', 'run', code_div_exe, '-p', 'compiler'], check=True, stdout=PIPE, stderr=PIPE, universal_newlines=True) assert res.stdout.startswith('stdout:\n4\n\nstderr:\n') res = subprocess.run(['take', 'run', code_div_exe, '-p', 'compiler', '-q'], check=True, stdout=PIPE, stderr=PIPE, universal_newlines=True) assert res.stdout == '4\n' assert res.stderr == 'done\n' open('input.txt', 'w').write('12 0') res = subprocess.run(['take', 'run', code_div_exe, '-p', 'compiler'], stdout=PIPE, stderr=PIPE, universal_newlines=True) assert res.returncode != 0 assert res.stdout.find('runtime-error') >= 0 assert res.stdout.find('signal: ') >= 0 os.mkdir('work') inner_in = Path('work') / 'input.txt' inner_in.open('w').write('42 6') res = subprocess.run( ['take', 'run', code_div_exe, '-p', 'compiler', '-q', '-w', 'work'], check=True, stdout=PIPE, stderr=PIPE, universal_newlines=True) assert res.stdout == '7\n' res = subprocess.run( ['take', 'run', fspath(badexe_loc), '-p', 'compiler'], stdout=PIPE, stderr=PIPE, universal_newlines=True) assert res.returncode != 0 assert res.stdout.find('run-fail') >= 0 res = subprocess.run( ['take', 'run', fspath(badexe_loc), '-p', 'compiler', '-q'], stdout=PIPE, stderr=PIPE, universal_newlines=True) assert res.returncode != 0 assert res.stdout == '' assert res.stderr.find('error: program exited with status run-fail') >= 0
def abspath(cur_path): return Path(path.abspath(fspath(cur_path)))
def normalize(self, repo): new_filename = shutil.which(fspath(self.filename)) if new_filename is None: raise FileNotFoundError( 'command {} not found'.format(new_filename)) self.filename = Path(new_filename)
def command_name(self, repo, work_dir): return fspath(self.filename)
def save_to_file(self, file_name): open(fspath(file_name), 'w', encoding='utf8').write(self.dump())
def load_from_file(self, file_name): self.load(open(fspath(file_name), 'r', encoding='utf8').read())
def relpath(cur_path, start=None): if start is None: start = Path.cwd() return Path(path.relpath(fspath(cur_path), fspath(start)))
def to_task_dir(self): os.chdir(fspath(self.directory))
def test_mock_app_exe(taker_app): assert taker_app == app_exe() assert fspath(app_exe()) == shutil.which('take')
def test_profiles(config_manager, repo_manager, monkeypatch, taker_app): config_manager.user_config(CONFIG_NAME).open( 'w', encoding='utf8').write(''' [compiler] time-limit = 3.0 memory-limit = 100.0 [checker] time-limit = 6.0 memory-limit = 200.0 [validator] time-limit = 9.0 memory-limit = 300.0 [generator] time-limit = 12.0 memory-limit = 400.0 [custom] time-limit = 15.0 memory-limit = 500.0 ''') runner = Runner() repo = repo_manager.repo compiler_profile = create_profile('compiler', repo) assert type(compiler_profile) is CompilerRunProfile compiler_profile.update_runner(runner) assert runner.parameters.time_limit == 3.0 assert runner.parameters.memory_limit == 100.0 checker_profile = create_profile('checker', repo) assert type(checker_profile) is CheckerRunProfile checker_profile.update_runner(runner) assert runner.parameters.time_limit == 6.0 assert runner.parameters.memory_limit == 200.0 validator_profile = create_profile('validator', repo) assert type(validator_profile) is ValidatorRunProfile validator_profile.update_runner(runner) assert runner.parameters.time_limit == 9.0 assert runner.parameters.memory_limit == 300.0 generator_profile = create_profile('generator', repo) assert type(generator_profile) is GeneratorRunProfile generator_profile.update_runner(runner) assert runner.parameters.time_limit == 12.0 assert runner.parameters.memory_limit == 400.0 with pytest.raises(KeyError): create_profile('custom', repo) register_profile(CustomRunProfile) custom_profile = create_profile('custom', repo) assert type(custom_profile) is CustomRunProfile custom_profile.update_runner(runner) assert runner.parameters.time_limit == 15.0 assert runner.parameters.memory_limit == 500.0 run_count = 0 def run(self): nonlocal run_count run_count += 1 monkeypatch.setattr(Runner, 'run', run) profiled_runner = ProfiledRunner(generator_profile) profiled_runner.stdin = 'some input' in_runner = profiled_runner._ProfiledRunner__runner profiled_runner.run([fspath(taker_app)]) assert run_count == 1 assert in_runner.parameters.time_limit == 12.0 assert in_runner.parameters.memory_limit == 400.0 assert not in_runner.pass_stdin assert not in_runner.capture_stdout assert in_runner.capture_stderr assert in_runner.stdin == 'some input' assert in_runner.stdin == profiled_runner.stdin assert in_runner.parameters.working_dir == taker_app.parent profiled_runner.run([fspath(taker_app)], repo_manager.task_dir) assert run_count == 2 assert in_runner.parameters.working_dir == repo_manager.task_dir profiles = set(list_profiles()) assert 'compiler' in profiles assert 'validator' in profiles
def command_name(self, repo, work_dir): result = fspath(self.relative_to(repo, work_dir)) if path.basename(result) == result: result = path.join(path.curdir, result) return result
def __init__(self, makefile, filename, options=DEFAULT_OPTIONS): super().__init__(makefile, fspath(makefile.repo.relpath(filename)), options=options)
def test_languages(tmpdir, config_manager): tmpdir = Path(str(tmpdir)) config = ''' [lang/sh.sh] run-args = ['sh', '{exe}'] priority = 42 exe-ext = '.sh' [lang/cpp.g++] # Overwrite default g++ compile-args = ['<cpp-compiler>', '{src}', '-o', '{exe}', '-Ofast'] priority = 1150 exe-ext = '.42.exe' [lang/cpp.g++14] active = false ''' c_compiler = shutil.which('gcc') if not c_compiler: c_compiler = shutil.which('clang') cpp_compiler = shutil.which('g++') if not cpp_compiler: cpp_compiler = shutil.which('clang++') config = config.replace('<cpp-compiler>', cpp_compiler) config_manager.user_config(CONFIG_NAME).open('w', encoding='utf8').write(config) lang_manager = LanguageManagerBase() assert ([str(lang.name) for lang in lang_manager.get_ext('.cpp') ] == ['cpp.g++17', 'cpp.g++', 'cpp.g++11']) assert lang_manager.get_ext('.bad_ext') == [] assert lang_manager['py.py2'].name == 'py.py2' assert lang_manager['py.py3'].name == 'py.py3' assert lang_manager['py.py3'].exe_ext == '.py' with pytest.raises(LanguageError): lang_manager['bad_ext.bad_lang'] with pytest.raises(ValueError): Language('q.q', exe_ext='iNeedDot') lang = lang_manager['c.gcc'] compile_arg_exp = [ c_compiler, fspath(Path.cwd() / 'file.cpp'), '-o', fspath(Path.cwd() / 'file.exe'), '-O2', '-I' + fspath(Path.cwd() / 'libs'), '-I' + fspath(Path.cwd() / 'morelibs') ] compile_arg_found = lang.compile_args( Path('file.cpp'), Path('file.exe'), [Path('libs'), Path('morelibs')]) assert compile_arg_exp == compile_arg_found run_arg_exp = [fspath(tmpdir / 'file.exe'), 'arg1', 'arg2'] with pytest.raises(FileNotFoundError): lang.run_args(tmpdir / 'file.exe') (tmpdir / 'file.exe').touch() (tmpdir / 'file.exe').chmod(0o755) assert run_arg_exp == lang.run_args(tmpdir / 'file.exe', ['arg1', 'arg2']) assert lang.exe_ext == default_exe_ext() lang = lang_manager['cpp.g++'] compile_arg_exp = [ cpp_compiler, fspath(Path.cwd() / 'file.cpp'), '-o', fspath(Path.cwd() / 'file.exe'), '-Ofast' ] compile_arg_found = lang.compile_args(Path('file.cpp'), Path('file.exe')) assert compile_arg_exp == compile_arg_found assert lang.exe_ext == '.42.exe' lang = lang_manager['sh.sh'] assert lang.compile_args(Path('file.sh'), Path('file.exe')) is None run_arg_exp = [shutil.which('sh'), fspath(Path.cwd() / 'file.sh')] assert lang.run_args(Path('file.sh')) == run_arg_exp assert lang.exe_ext == '.sh' assert lang_manager.get_best_lang('.py').name == 'py.py3' with pytest.raises(LanguageError): lang_manager.get_best_lang('.red')
def test_compiler(tmpdir, repo_manager, language_manager): tmpdir = Path(str(tmpdir)) repo = repo_manager.repo lang_cpp = language_manager.get_lang('cpp.g++14') lang_py = language_manager.get_lang('py.py3') src_dir = tmpdir / 'src' src_dir.mkdir() for fname in ['code.cpp', 'compile_error.cpp', 'code_libs.cpp', 'code.py']: shutil.copy(fspath(tests_location() / fname), fspath(src_dir / fname)) src_cpp1 = src_dir / 'code.cpp' src_cpp2 = src_dir / 'compile_error.cpp' src_cpp3 = src_dir / 'code_libs.cpp' src_py1 = src_dir / 'code.py' src_bad1 = src_dir / 'bad_code.py' src_bad2 = src_dir / 'bad_code2.py' exe_cpp1 = src_dir / ('1-code' + default_exe_ext()) exe_py1 = src_dir / ('1-code' + default_exe_ext()) with pytest.raises(CompileError): compiler = Compiler(repo, lang_cpp, src_cpp2) compiler.compile() with pytest.raises(CompileError): compiler = Compiler(repo, lang_cpp, src_py1) compiler.compile() with pytest.raises(CompileError): compiler = Compiler(repo, lang_py, src_bad1, src_bad2) compiler.compile() runner = Runner() runner.capture_stdout = True runner.capture_stderr = True compiler = Compiler(repo, lang_cpp, src_cpp1) compiler.compile() runner.parameters.executable = compiler.exe_file runner.run() assert runner.results.status == Status.OK assert runner.stdout == 'hello world\n' compiler = Compiler(repo, lang_cpp, src_cpp3, library_dirs=[tests_location()]) compiler.compile() runner.parameters.executable = compiler.exe_file runner.run() assert runner.results.status == Status.OK assert runner.stdout == 'hello world\n' compiler = Compiler(repo, lang_py, src_py1) compiler.compile() runner.parameters.executable = lang_py.run_args(compiler.exe_file)[0] runner.parameters.args = lang_py.run_args(compiler.exe_file)[1:] runner.run() assert runner.results.status == Status.OK assert runner.stdout == 'hello world\n' compiler = Compiler(repo, lang_cpp, src_cpp1, exe_cpp1) compiler.compile() runner.parameters.executable = exe_cpp1 runner.run() assert runner.results.status == Status.OK assert runner.stdout == 'hello world\n' compiler = Compiler(repo, lang_py, src_py1, exe_py1) compiler.compile() runner.parameters.executable = lang_py.run_args(exe_py1)[0] runner.parameters.args = lang_py.run_args(exe_py1)[1:] runner.run() assert runner.results.status == Status.OK assert runner.stdout == 'hello world\n'