def test_simple(self): run = Run(user=self.users[0], problem=self.problems[0], statement=self.statements[0], score=123, create_time=datetime.datetime(2018, 3, 24, 10, 49, 0), ejudge_score=456, ejudge_status=7, ejudge_language_id=27, ejudge_create_time=datetime.datetime(2010, 1, 1, 1, 1, 1)) db.session.add(run) db.session.flush() assert_that( run.serialize(), equal_to({ 'id': 1, 'create_time': '2018-03-24 10:49:00', 'ejudge_contest_id': None, 'ejudge_run_id': None, 'problem_id': self.problems[0].id, 'statement_id': self.statements[0].id, 'score': 123, 'status': 7, 'language_id': 27, 'user': { 'id': 1, 'ejudge_id': 179, 'firstname': 'Maxim', 'lastname': 'Grishkin', } }))
def test_handles_submit_exception(self): # В случае, если функция submit бросила исключение run = Run( user_id=self.users[0].id, problem_id=self.ejudge_problems[0].id, statement_id=self.statements[0].id, create_time=datetime.datetime(2018, 3, 30, 16, 59, 0), ejudge_contest_id=self.ejudge_problems[0].ejudge_contest_id, ejudge_language_id=27, ejudge_status=EjudgeStatuses.COMPILING.value, ) db.session.add(run) db.session.flush() db.session.refresh(run) file = self.file_mock text = file.read() run.update_source(text) submit = Submit( id=1, run_id=run.id, ejudge_url='ejudge_url', ) ejudge_submit_mock.side_effect = lambda *args, **kwargs: 1 / 0 assert_that( calling(submit.send), is_not(raises(anything())), ) ejudge_submit_mock.side_effect = None
def post(self, problem_id: int): args = parser.parse(self.post_args) language_id = args['lang_id'] statement_id = args.get('statement_id') user_id = args.get('user_id') file = parser.parse_files(request, 'file', 'file') # Здесь НЕЛЬЗЯ использовать .get(problem_id), см EjudgeProblem.__doc__ problem = db.session.query(EjudgeProblem) \ .filter_by(id=problem_id) \ .one_or_none() if not problem: raise NotFound('Problem with this id is not found') try: text = self.check_file_restriction(file) except ValueError as e: raise BadRequest(e.args[0]) source_hash = Run.generate_source_hash(text) duplicate = db.session.query(Run).filter(Run.user_id == user_id) \ .filter(Run.problem_id == problem_id) \ .order_by(Run.id.desc()).first() if duplicate is not None and duplicate.source_hash == source_hash: raise BadRequest('Source file is duplicate of your previous submission') # TODO: разобраться, есть ли там constraint на statement_id run = Run( user_id=user_id, problem_id=problem_id, statement_id=statement_id, ejudge_contest_id=problem.ejudge_contest_id, ejudge_language_id=language_id, ejudge_status=377, # In queue source_hash=source_hash, ) db.session.add(run) db.session.flush() run.update_source(text) run_id = run.id ejudge_url = current_app.config['EJUDGE_NEW_CLIENT_URL'] # Коммит должен быть до отправки в очередь иначе это гонка db.session.commit() queue_submit(run_id, ejudge_url) return jsonify({ 'run_id': run_id })
def send(self): try: ejudge_response = submit(run_file=self.file, contest_id=self.problem.ejudge_contest_id, prob_id=self.problem.problem_id, lang_id=self.language_id, login=self.user.login, password=self.user.password, filename=self.file.filename, url=self.ejudge_url, user_id=self.user.id) except Exception: log.exception('Unknown Ejudge submit error') notify_user(self.user.id, SUBMIT_ERROR, ejudge_error_notification()) return try: if ejudge_response['code'] != 0: notify_user(self.user.id, SUBMIT_ERROR, ejudge_error_notification(ejudge_response)) return run_id = ejudge_response['run_id'] except Exception: log.exception('ejudge_proxy.submit returned bad value') notify_user(self.user.id, SUBMIT_ERROR, message=ejudge_error_notification()) return run = Run( user_id=self.user.id, problem=self.problem, statement_id=self.statement_id, create_time=self.create_time, ejudge_run_id=run_id, ejudge_contest_id=self.problem.ejudge_contest_id, ejudge_language_id=self.language_id, ejudge_status=98, # compiling ) db.session.add(run) db.session.commit() db.session.refresh(run) run.update_source(text=self.source) g.user = self.user notify_user(self.user.id, SUBMIT_SUCCESS, { 'run': run.serialize(), 'submit_id': self.id, })
def test_simple(self): run = Run( user_id=self.users[0].id, problem_id=self.ejudge_problems[0].id, statement_id=self.statements[0].id, create_time=datetime.datetime(2018, 3, 30, 16, 59, 0), ejudge_contest_id=self.ejudge_problems[0].ejudge_contest_id, ejudge_language_id=27, ejudge_status=EjudgeStatuses.COMPILING.value, ) db.session.add(run) db.session.flush() db.session.refresh(run) file = self.file_mock text = file.read() run.update_source(text) submit = Submit( id=1, run_id=run.id, ejudge_url='ejudge_url', ) ejudge_submit_mock.return_value = { 'code': 0, 'run_id': self.run.run_id, } submit.send() from flask import current_app ejudge_submit_mock.assert_called_once_with( run_file=b'source', contest_id=1, prob_id=1, lang_id=27, login=current_app.config['EJUDGE_USER'], password=current_app.config['EJUDGE_PASSWORD'], filename='common_filename', url='ejudge_url', ) run = db.session.query(Run).one() assert_that(run.ejudge_run_id, equal_to(self.run.run_id)) assert_that(run.ejudge_contest_id, equal_to(self.ejudge_problems[0].ejudge_contest_id)) assert_that(run.user.id, equal_to(self.users[0].id)) assert_that(run.problem.id, equal_to(self.ejudge_problems[0].id))
def notification_update_run(): contest_id = int(request.args['contest_id']) run_id = int(request.args['run_id']) try: run = db.session.query(EjudgeRun) \ .filter_by(contest_id=contest_id) \ .filter_by(run_id=run_id) \ .one() except Exception: raise RunNotFound run = Run.sync( ejudge_run_id=run_id, ejudge_contest_id=contest_id ) db.session.commit() db.session.refresh(run) g.user = run.user notify_user( run.user_id, RUNS_FETCH, { 'runs': [run.serialize()], } ) return jsonify({})
def setUp(self): super().setUp() self.create_ejudge_problems() self.create_problems() self.create_statements() self.create_statement_problems() self.create_course_module_statement() self.user1 = SimpleUser(firstname='user1', lastname='user1') self.user2 = SimpleUser(firstname='user2', lastname='user2') db.session.add_all([self.user1, self.user2]) db.session.flush() self.run1 = Run(user_id=self.user1.id, problem_id=self.problems[1].id, ejudge_status=0, ejudge_language_id=1) self.run2 = Run(user_id=self.user1.id, problem_id=self.problems[2].id, ejudge_status=0, ejudge_language_id=1) self.run3 = Run(user_id=self.user2.id, problem_id=self.problems[1].id, ejudge_status=2, ejudge_language_id=2) self.run4 = Run(user_id=self.user2.id, problem_id=self.problems[2].id, ejudge_status=2, ejudge_language_id=2) self.run4.create_time = datetime.utcnow() - timedelta(days=1) db.session.add_all([self.run1, self.run2, self.run3, self.run4]) self.group = Group() db.session.add(self.group) db.session.flush() user_group = UserGroup(user_id=self.user1.id, group_id=self.group.id) db.session.add(user_group) db.session.commit()
def test_create(self): run = Run.sync( ejudge_run_id=self.ejudge_run.run_id, ejudge_contest_id=self.ejudge_run.contest_id, ) db.session.flush() assert_that(run.user_id, equal_to(self.users[1].id)) assert_that(run.problem_id, equal_to(self.problems[1].id)) assert_that(run.score, equal_to(self.ejudge_run.score))
def send_problem_run_updates(self, problem_id: int, run: Run): current_app.logger.debug( f'CentrifugoClient: send update for problem {problem_id}') channel = f'problem.{problem_id}' try: self.client.publish(channel, {'run': run.serialize()}) except AttributeError: current_app.logger.exception( f'CentrifugoClient: client is not initialized') except CentException: current_app.logger.exception( f'CentrifugoClient: can\'t send message to centrifugo')
def test_handles_submit_error(self): # В случае, если ejudge вернул не 0 код run = Run( user_id=self.users[0].id, problem_id=self.ejudge_problems[0].id, statement_id=self.statements[0].id, create_time=datetime.datetime(2018, 3, 30, 17, 10, 11), ejudge_contest_id=self.ejudge_problems[0].ejudge_contest_id, ejudge_language_id=27, ejudge_status=EjudgeStatuses.COMPILING.value, ) db.session.add(run) db.session.flush() db.session.refresh(run) file = self.file_mock text = file.read() run.update_source(text) submit = Submit( id=1, run_id=run.id, ejudge_url='ejudge_url', ) ejudge_submit_mock.return_value = { 'code': 123, 'message': 'some message', 'other': 'secrets' } assert_that( calling(submit.send), is_not(raises(anything())), ) ejudge_submit_mock.side_effect = None
def test_simple(self): ejudge_run = EjudgeRun( run_id=2, user=self.users[0], problem=self.problems[0], run_uuid='some string', score=10, status=7, lang_id=27, test_num=3, create_time=datetime.datetime(2018, 3, 24, 9, 51, 30), last_change_time=datetime.datetime(2018, 3, 24, 9, 51, 31), ) db.session.add(ejudge_run) db.session.flush() run = Run.from_ejudge_run(ejudge_run) db.session.add(run) db.session.flush() assert_that( attrs_to_dict( run, 'user_id', 'problem_id', 'statement_id', 'score', 'ejudge_run_id', 'ejudge_contest_id', 'ejudge_score', 'ejudge_status', 'ejudge_language_id', 'ejudge_test_num', 'ejudge_create_time', 'ejudge_last_change_time', ), has_entries({ 'user_id': self.users[0].id, 'problem_id': self.problems[0].id, 'score': ejudge_run.score, 'ejudge_run_id': ejudge_run.run_id, 'ejudge_contest_id': ejudge_run.contest_id, 'ejudge_score': ejudge_run.score, 'ejudge_status': ejudge_run.status, 'ejudge_language_id': ejudge_run.lang_id, 'ejudge_test_num': ejudge_run.test_num, 'ejudge_create_time': ejudge_run.create_time, 'ejudge_last_change_time': ejudge_run.last_change_time, }))
def test_update(self): run = Run.sync( ejudge_run_id=self.ejudge_run.run_id, ejudge_contest_id=self.ejudge_run.contest_id, ) run.statement = self.statements[0] self.ejudge_run.score = 179 db.session.flush() assert_that(run.score, equal_to(456)) assert_that(run.ejudge_score, equal_to(456)) assert_that(run.statement_id, equal_to(self.statements[0].id)) assert_that(self.ejudge_run.score, equal_to(179)) run = Run.sync( ejudge_run_id=self.ejudge_run.run_id, ejudge_contest_id=self.ejudge_run.contest_id, ) db.session.flush() assert_that(run.score, equal_to(179)) assert_that(run.ejudge_score, equal_to(179)) assert_that(run.statement_id, equal_to(self.statements[0].id)) assert_that(db.session.query(Run).count(), equal_to(1))
def setUp(self): super(TestView__problem_runs, self).setUp() self.create_problems() self.create_statements() self.create_users() self.user1 = self.users[0] self.user2 = self.users[1] self.problem = self.problems[0] self.runs = [[Run(problem=self.problem, user=user) for i in range(3)] for user in [self.user1, self.user2]] db.session.add_all(self.runs[0]) # user1 runs db.session.add_all(self.runs[1]) # user2 runs db.session.flush()
def setUp(self): super(TestAPI__notification_update_run, self).setUp() self.create_problems() self.create_users() self.ej_run = EjudgeRun( run_id=123, user=self.users[0], problem=self.problems[0], ) db.session.add(self.ej_run) db.session.flush() self.run = Run.from_ejudge_run(self.ej_run) db.session.add(self.run) db.session.flush()
def post(self, problem_id: int): args = parser.parse(self.post_args) language_id = args['lang_id'] statement_id = args.get('statement_id') user_id = args.get('user_id') file = parser.parse_files(request, 'file', 'file') # If context parameters are unavialable, # consider it as Moodle submission and set defaults context_id = args.get('context_id') context_source = args.get('context_source', DEFAULT_MOODLE_CONTEXT_SOURCE) is_visible = args.get('is_visible', True) # Здесь НЕЛЬЗЯ использовать .get(problem_id), см EjudgeProblem.__doc__ problem = db.session.query(EjudgeProblem) \ .filter_by(id=problem_id) \ .one_or_none() if not problem: raise NotFound('Problem with this id is not found') if int(user_id) <= 0: raise BadRequest('Wrong user status') try: limit = 64 if problem.output_only: limit = 1024 * 16 text = self.check_file_restriction(file, limit) except ValueError as e: raise BadRequest(e.args[0]) source_hash = Run.generate_source_hash(text) duplicate: Run = db.session.query(Run).filter(Run.user_id == user_id) \ .filter(Run.problem_id == problem_id) \ .order_by(Run.id.desc()).first() if duplicate is not None and \ duplicate.source_hash == source_hash and \ duplicate.ejudge_language_id == language_id: raise BadRequest( 'Source file is duplicate of your previous submission') # There is not constraint on statement_id run = Run( user_id=user_id, problem_id=problem_id, statement_id=statement_id, ejudge_contest_id=problem.ejudge_contest_id, ejudge_language_id=language_id, ejudge_status=377, # In queue source_hash=source_hash, # Context related properties context_source=context_source, is_visible=is_visible, ) # If it's context aware submission, # overwrite statement_id with context if context_id: run.statement_id = context_id db.session.add(run) db.session.flush() run.update_source(text) run_id = run.id ejudge_url = current_app.config['EJUDGE_NEW_CLIENT_URL'] # Коммит должен быть до отправки в очередь иначе это гонка db.session.commit() queue_submit(run_id, ejudge_url) return jsonify({'run_id': run_id})
def _remove_run(self, run: Run): run.remove_source() db.session.delete(run) db.session.commit()
def setUp(self): super().setUp() self.create_ejudge_problems() self.create_problems() self.create_statements() self.create_statement_problems() self.create_course_module_statement() self.user1 = SimpleUser(firstname='user1', lastname='user1') self.user2 = SimpleUser(firstname='user2', lastname='user2') db.session.add_all([self.user1, self.user2]) db.session.flush() self.run1 = Run(user_id=self.user1.id, problem_id=self.problems[1].id, ejudge_status=0, ejudge_language_id=1, is_visible=True) self.run2 = Run(user_id=self.user1.id, problem_id=self.problems[2].id, ejudge_status=0, ejudge_language_id=1, is_visible=True) self.run3 = Run(user_id=self.user2.id, problem_id=self.problems[1].id, ejudge_status=2, ejudge_language_id=2, is_visible=True) self.run4 = Run(user_id=self.user2.id, problem_id=self.problems[2].id, ejudge_status=2, ejudge_language_id=2, is_visible=True) self.run5 = Run(user_id=self.user2.id, problem_id=self.problems[1].id, ejudge_status=2, ejudge_language_id=2, is_visible=False) self.run4.create_time = datetime.utcnow() - timedelta(days=1) # Context tests fixtures self.run1.context_source = CONTEXT_SOURCE self.run5.context_source = CONTEXT_SOURCE self.run1.statement_id = CONTEXT_ID_1 self.run3.statement_id = CONTEXT_ID_1 self.run5.statement_id = CONTEXT_ID_1 self.run2.statement_id = CONTEXT_ID_2 self.run4.statement_id = CONTEXT_ID_2 db.session.add_all( [self.run1, self.run2, self.run3, self.run4, self.run5]) self.group = Group() db.session.add(self.group) db.session.flush() user_group = UserGroup(user_id=self.user1.id, group_id=self.group.id) db.session.add(user_group) db.session.commit()