def test_submit(self, g_f_s_mock, g_i_mock): Utils.start_contest() self._insert_data() self.handler.generate_input(token='token', task='poldo', _ip='1.1.1.1') Database.c.execute( "INSERT INTO outputs (id, input, path, size, result) " "VALUES ('outputid', 'inputid', '/output', 42," ":result)", { "result": b'{\"score\":0.5,\"feedback\":{\"a\":1},' b'\"validation\":{\"b\":2}}' }) Database.c.execute("INSERT INTO sources (id, input, path, size) " "VALUES ('sourceid', 'inputid', '/source', 42)") response = self.handler.submit(output_id='outputid', source_id='sourceid', _ip='1.1.1.1') self.assertEqual("token", response["token"]) self.assertEqual("poldo", response["task"]) self.assertEqual(21, response["score"]) self.assertEqual("inputid", response["input"]["id"]) self.assertEqual("sourceid", response["source"]["id"]) self.assertEqual("outputid", response["output"]["id"]) self.assertEqual(1, response["feedback"]["a"]) self.assertEqual(2, response["output"]["validation"]["b"]) user_task = Database.get_user_task("token", "poldo") self.assertEqual(21, user_task["score"]) self.assertEqual(response["id"], Database.get_submission(response["id"])["id"])
def test_submit_broken_transaction(self, gen_i_mock, a_s_mock, g_f_s_mock, g_i_mock): Utils.start_contest() self._insert_data() self.handler.generate_input(token="token", task="poldo", _ip="1.1.1.1") Database.c.execute( "INSERT INTO outputs (id, input, path, size, result) " "VALUES ('outputid', 'inputid', '/output', 42," ":result)", { "result": b'{"score":0.5,"feedback":{"a":1},' b'"validation":{"b":2}}' }, ) Database.c.execute("INSERT INTO sources (id, input, path, size) " "VALUES ('sourceid', 'inputid', '/source', 42)") with self.assertRaises(BadRequest) as ex: self.handler.submit(output_id="outputid", source_id="sourceid", _ip="1.1.1.1") self.assertIn("Error inserting the submission", ex.exception.response.data.decode()) self.assertIsNone(Database.get_submission("subid"))
def submit(self, output, source): """ POST /submit """ input = Database.get_input(output["input"]) if input is None: Logger.warning("DB_CONSISTENCY_ERROR", "Input %s not found in the db" % output["input"]) self.raise_exc(BadRequest, "WRONG_INPUT", "The provided input in invalid") if output["input"] != source["input"]: Logger.warning("POSSIBLE_CHEAT", "Trying to submit wrong pair source-output") self.raise_exc(Forbidden, "WRONG_OUTPUT_SOURCE", "The provided pair of source-output is invalid") score = ContestHandler.compute_score(input["task"], output["result"]) Database.begin() try: submission_id = Database.gen_id() if not Database.add_submission(submission_id, input["id"], output["id"], source["id"], score, autocommit=False): self.raise_exc(BadRequest, "INTERNAL_ERROR", "Error inserting the submission") ContestHandler.update_user_score(input["token"], input["task"], score) Database.set_user_attempt(input["token"], input["task"], None, autocommit=False) Database.commit() except sqlite3.IntegrityError as ex: Database.rollback() # provide a better error message if the input has already been # submitted if "UNIQUE constraint failed: submissions.input" in str(ex): self.raise_exc(Forbidden, "ALREADY_SUBMITTED", "This input has already been submitted") raise except: Database.rollback() raise Logger.info( "CONTEST", "User %s has submitted %s on %s" % (input["token"], submission_id, input["task"])) return InfoHandler.patch_submission( Database.get_submission(submission_id))
def _guess_token(**kwargs): if "token" in kwargs: return kwargs["token"] elif "input_id" in kwargs: input = Database.get_input(kwargs["input_id"]) if input: return input["token"] elif "output_id" in kwargs: output = Database.get_output(kwargs["output_id"]) if output: input = Database.get_input(output["input"]) if input: return input["token"] elif "source_id" in kwargs: source = Database.get_source(kwargs["source_id"]) if source: input = Database.get_input(source["input"]) if input: return input["token"] elif "submission_id" in kwargs: submission = Database.get_submission(kwargs["submission_id"]) if submission: return submission["token"] return None