def setUp(self): """Manually add a problem to the test database""" self.p = Problem(**test_problem) self.pd = ProblemData(**test_problem_data) self.cases = list() for c in test_cases: self.cases.append(SampleCase(**c)) # Ship it off to the db try: session.add(self.p) session.add(self.pd) for c in self.cases: session.add(c) session.commit() except: session.rollback() _reinsert_test_problem(self.p, self.pd, self.cases) # Log in self.login()
def create_problem(): """Add a new problem to the database and data folder""" try: # Convert the JSON to python array of dictionaries cases = request.form['cases'] cases = loads(cases) for case in cases: if 'input' not in case or 'output' not in case: return serve_error( 'Sample case(s) were not formed correctly', response_code=400) # Create the problem name = request.form['name'][:32] shortname = name.lower().replace(' ', '') problem = Problem( name=name, shortname=shortname ) if 'difficulty' in request.form: problem.difficulty = request.form['difficulty'] if 'appeared_in' in request.form: problem.appeared = request.form['appeared_in'] problem.comp_release = request.form['comp_release'] or None # Create the problem data and add it to the database problem_data = ProblemData( description=request.form['description'], input_desc=request.form['input_desc'], output_desc=request.form['output_desc'] ) if 'time_limit' in request.form: problem_data.time_limit = request.form['time_limit'] # Create list of sample cases case_num = 1 sample_cases = list() for case in cases: sample = SampleCase( case_num=case_num, input=case['input'], output=case['output'] ) case_num += 1 sample_cases.append(sample) in_file = zipfile.ZipFile(request.files['in_file']) out_file = zipfile.ZipFile(request.files['out_file']) sol_file = request.files['sol_file'] # If any required values were missing, serve an error except KeyError as err: return serve_error('Form field not found: ' + err[0], response_code=400) # Commit everything to the database pid = problem.commit_to_session() problem_data.pid = pid problem_data.commit_to_session() for case in sample_cases: case.pid = pid case.commit_to_session() # Store the judge data directory = os.path.join(app.config['DATA_FOLDER'], 'problems', str(problem.pid)) in_file.extractall(directory) out_file.extractall(directory) os.mkdir(os.path.join(directory, 'test')) sol_file.save(os.path.join(directory, 'test', sol_file.filename)) return serve_response({ 'name': problem.name, 'shortname': problem.shortname, 'description': problem_data.description, 'input_desc': problem_data.input_desc, 'output_desc': problem_data.output_desc, 'sample_cases': cases, 'pid': problem.pid, 'difficulty': problem.difficulty })
class ProblemGetTests(AUACMTest): """Tests functionality for GET-ing problems from the API""" def setUp(self): """Manually add a problem to the test database""" self.p = Problem(**test_problem) self.pd = ProblemData(**test_problem_data) self.cases = list() for c in test_cases: self.cases.append(SampleCase(**c)) # Ship it off to the db try: session.add(self.p) session.add(self.pd) for c in self.cases: session.add(c) session.commit() except: session.rollback() _reinsert_test_problem(self.p, self.pd, self.cases) # Log in self.login() def tearDown(self): """Manually remove test problem from the test database""" for c in self.cases: session.delete(c) session.delete(self.pd) session.delete(self.p) session.commit() # Log out of this session too self.logout() def testGetAll(self): """Should get basic info about all the problems""" # Check that the request went through resp = test_app.get('/api/problems') self.assertEqual(200, resp.status_code) rv = json.loads(resp.data.decode()) self.assertFalse('Please log in' in str(rv)) # Find the test problem in the list returned found = None for prob in rv['data']: if prob['pid'] == test_problem['pid']: found = prob self.assertTrue(len(rv['data']) > 0) self.assertFalse(found is None) # All the original values should be maintained for k in test_problem: self.assertEqual(str(test_problem[k]), str(found[k])) def testGetOne(self): """Should get detailed info about one specific problem""" resp = test_app.get('/api/problems/' + str(test_problem['pid'])) self.assertEqual(200, resp.status_code) rv = json.loads(resp.data.decode()) self.assertFalse('Please log in' in str(rv)) # Time limit doesn't get returned from the API, so take it out of our # validation data_validate = copy.deepcopy(test_problem_data) data_validate.pop('time_limit') prob = rv['data'] for key in test_problem: self.assertEqual(str(test_problem[key]), str(prob[key])) for key in data_validate: self.assertEqual(str(test_problem_data[key]), str(prob[key])) def testHideUnreleasedProblem(self): """Test that GET-ting an unreleased problem returns a 404""" unreleased_cid = self._setUpUnreleasedComp() resp = test_app.get('/api/problems/{}'.format(self.p.pid)) self.assertEqual(404, resp.status_code) self._tearDownComp(unreleased_cid) def testHideUnreleasedProblems(self): """ Test that GET-ting all problems doesn't return unreleased problems """ unreleased_cid = self._setUpUnreleasedComp() resp = test_app.get('/api/problems') self.assertEqual(200, resp.status_code) rv = json.loads(resp.data.decode())['data'] # Test problem should be hidden for prob in rv: self.assertNotEqual(self.p.pid, prob['pid']) self._tearDownComp(unreleased_cid) def _setUpUnreleasedComp(self): """ Creates an unreleased competition and associates the test's problem with it :return: the cid of the new competition """ unreleased_cid = Competition( name='Test Competition', start=int(time() + 10000), stop=int(time() + 20000), closed=0 ).commit_to_session(session) self.p.comp_release = unreleased_cid self.p.commit_to_session(session) return unreleased_cid def _tearDownComp(self, cid): """Removes a competition from the database by its cid""" session.delete( session.query(Competition) .filter_by(cid=cid) .first() ) session.commit()