예제 #1
0
 /**
  * Creates a run to the given problem
  *
  * @param type $problemData
  * @param type $contestant
  */
 public static function createRunToProblem($problemData, $contestant)
 {
     $r = self::createRequestCommon($problemData, null, $contestant);
     // Call API
     RunController::$grader = new GraderMock();
     $response = RunController::apiCreate($r);
     // Clean up
     unset($_REQUEST);
     return array('request' => $r, 'contestant' => $contestant, 'response' => $response);
 }
예제 #2
0
 public function testRunTotals()
 {
     // Get a problem
     $problemData = ProblemsFactory::createProblem();
     // Get a contest
     $contestData = ContestsFactory::createContest();
     // Add the problem to the contest
     ContestsFactory::addProblemToContest($problemData, $contestData);
     // Create our contestant
     $contestant = UserFactory::createUser();
     // Create a run
     $runData = RunsFactory::createRun($problemData, $contestData, $contestant);
     $runDataOld = RunsFactory::createRun($problemData, $contestData, $contestant);
     $run = RunsDAO::getByAlias($runDataOld['response']['guid']);
     $run->setTime(date('Y-m-d H:i:s', strtotime('-72 hours')));
     RunsDAO::save($run);
     $response = RunController::apiCounts(new Request());
     $this->assertGreaterThan(1, count($response));
 }
예제 #3
0
 /**
  * Basic test of viewing run details
  *
  */
 public function testShowRunDetailsValid()
 {
     // Get a problem
     $problemData = ProblemsFactory::createProblem();
     // Get a contest
     $contestData = ContestsFactory::createContest();
     // Add the problem to the contest
     ContestsFactory::addProblemToContest($problemData, $contestData);
     // Create our contestant
     $contestant = UserFactory::createUser();
     // Create a run
     $runData = RunsFactory::createRun($problemData, $contestData, $contestant);
     // Prepare request
     $r = new Request();
     $r['auth_token'] = $this->login($contestant);
     $r['run_alias'] = $runData['response']['guid'];
     // Call API
     $response = RunController::apiStatus($r);
     $this->assertEquals($r['run_alias'], $response['guid']);
     $this->assertEquals('JE', $response['verdict']);
     $this->assertEquals('new', $response['status']);
 }
예제 #4
0
 /**
  * Basic test of viewing run details
  * 
  */
 public function testShowRunDetailsValid()
 {
     // Get a problem
     $problemData = ProblemsFactory::createProblem();
     // Get a contest
     $contestData = ContestsFactory::createContest();
     // Add the problem to the contest
     ContestsFactory::addProblemToContest($problemData, $contestData);
     // Create our contestant
     $contestant = UserFactory::createUser();
     // Create a run
     $runData = RunsFactory::createRun($problemData, $contestData, $contestant);
     // Prepare request
     $r = new Request();
     $r["auth_token"] = $this->login($contestant);
     $r["run_alias"] = $runData["response"]["guid"];
     // Call API
     $response = RunController::apiStatus($r);
     $this->assertEquals($r["run_alias"], $response["guid"]);
     $this->assertEquals("JE", $response["verdict"]);
     $this->assertEquals("new", $response["status"]);
 }
예제 #5
0
 /**
  * Basic test of rerun
  */
 public function testRejudgeWithoutCompileError()
 {
     // Get a problem
     $problemData = ProblemsFactory::createProblem();
     // Get a contest
     $contestData = ContestsFactory::createContest();
     // Add the problem to the contest
     ContestsFactory::addProblemToContest($problemData, $contestData);
     // Create our contestant
     $contestant = UserFactory::createUser();
     // Create a run
     $runData = RunsFactory::createRun($problemData, $contestData, $contestant);
     // Grade the run
     RunsFactory::gradeRun($runData);
     // Detour grader calls expecting one call
     $this->detourGraderCalls($this->once());
     // Build request
     $r = new Request();
     $r['run_alias'] = $runData['response']['guid'];
     $r['auth_token'] = $this->login($contestData['director']);
     // Call API
     $response = RunController::apiRejudge($r);
     $this->assertEquals('ok', $response['status']);
 }
예제 #6
0
 /**
  * Detours the Grader calls.
  * Problem: Submiting a new run invokes the Grader::grade() function which makes 
  * a HTTP call to official grader using CURL. This call will fail if grader is
  * not turned on. We are not testing the Grader functionallity itself, we are
  * only validating that we populate the DB correctly and that we make a call
  * to the function Grader::grade(), without executing the contents.
  * 
  * Solution: We create a phpunit mock of the Grader class. We create a fake 
  * object Grader with the function grade() which will always return true
  * and expects to be excecuted once.	 
  *
  */
 public function detourGraderCalls($times = null)
 {
     if (is_null($times)) {
         $times = $this->once();
     }
     // Create a fake Grader object which will always return true (see
     // next line)
     $graderMock = $this->getMock('Grader', array('Grade'));
     // Set expectations:
     $graderMock->expects($times)->method('Grade')->will($this->returnValue(true));
     // Detour all Grader::grade() calls to our mock
     RunController::$grader = $graderMock;
     ProblemController::$grader = $graderMock;
 }
예제 #7
0
 private static function getScoreboardFromRuns($runs, $raw_contest_users, $problem_mapping, $contest_penalty, $scoreboard_time_limit, $contest, $showAllRuns, $sortByName, $withRunDetails = false, $auth_token = null)
 {
     $test_only = array();
     $no_runs = array();
     $users_info = array();
     $problems = array();
     foreach ($problem_mapping as $problem) {
         array_push($problems, $problem);
     }
     // Calculate score for each contestant x problem
     foreach ($raw_contest_users as $contestant) {
         $user_problems = array();
         $test_only[$contestant->getUserId()] = true;
         $no_runs[$contestant->getUserId()] = true;
         foreach ($problem_mapping as $id => $problem) {
             array_push($user_problems, array('points' => 0, 'percent' => 0, 'penalty' => 0, 'runs' => 0));
         }
         // Add the problems' information
         $users_info[$contestant->getUserId()] = array('problems' => $user_problems, 'username' => $contestant->getUsername(), 'name' => $contestant->getName() ? $contestant->getName() : $contestant->getUsername(), 'total' => null, 'country' => $contestant->getCountryId());
     }
     foreach ($runs as $run) {
         $user_id = $run->user_id;
         $problem_id = $run->problem_id;
         $contest_score = $run->contest_score;
         $score = $run->score;
         $is_test = $run->test != 0;
         $problem =& $users_info[$user_id]['problems'][$problem_mapping[$problem_id]['order']];
         if (!array_key_exists($user_id, $test_only)) {
             //
             // Hay un usuario en la lista de Runs,
             // que no fue regresado por RunsDAO::GetAllRelevantUsers()
             //
             continue;
         }
         $test_only[$user_id] &= $is_test;
         $no_runs[$user_id] = false;
         if (!$showAllRuns) {
             if ($is_test) {
                 continue;
             }
             if (!is_null($scoreboard_time_limit) && strtotime($run->getTime()) >= $scoreboard_time_limit) {
                 $problem['runs']++;
                 $problem['pending'] = true;
                 continue;
             }
         }
         $totalPenalty = $run->penalty + $problem['runs'] * $contest_penalty;
         $rounded_score = round($contest_score, 2);
         if ($problem['points'] < $rounded_score || $problem['points'] == $rounded_score && $problem['penalty'] > $totalPenalty) {
             $problem['points'] = $rounded_score;
             $problem['percent'] = round($score * 100, 2);
             $problem['penalty'] = $totalPenalty;
             if ($withRunDetails === true) {
                 $runDetails = array();
                 $runDetailsRequest = new Request(array('run_alias' => $run->guid, 'auth_token' => $auth_token));
                 $runDetails = RunController::apiDetails($runDetailsRequest);
                 unset($runDetails['source']);
                 $problem['run_details'] = $runDetails;
             }
         }
         $problem['runs']++;
     }
     $result = array();
     foreach ($raw_contest_users as $contestant) {
         $user_id = $contestant->getUserId();
         // Add contestant results to scoreboard data
         if (!$showAllRuns && $test_only[$user_id] && !$no_runs[$user_id]) {
             continue;
         }
         $info = $users_info[$user_id];
         if ($info == null) {
             continue;
         }
         $info[self::TOTAL_COLUMN] = Scoreboard::getTotalScore($info['problems']);
         array_push($result, $info);
     }
     Scoreboard::sortScoreboard($result, $sortByName);
     usort($problems, array('Scoreboard', 'compareOrder'));
     return array('problems' => $problems, 'ranking' => $result, 'start_time' => strtotime($contest->start_time), 'finish_time' => strtotime($contest->finish_time), 'title' => $contest->title, 'time' => time() * 1000);
 }
예제 #8
0
 /**
  * Given the run alias, returns a .zip file with all the .out files generated for a run.
  *
  * @param Request $r
  * @throws ForbiddenAccessException
  */
 public static function apiDownload(Request $r)
 {
     if (OMEGAUP_LOCKDOWN) {
         throw new ForbiddenAccessException('lockdown');
     }
     // Get the user who is calling this API
     self::authenticateRequest($r);
     self::validateAdminDetailsRequest($r);
     $grade_dir = RunController::getGradePath($r['run']);
     $results_zip = "{$grade_dir}/results.zip";
     header('Content-Type: application/zip');
     header('Content-Disposition: attachment; filename=' . $r['run']->guid . '.zip');
     header('Content-Length: ' . filesize($results_zip));
     readfile($results_zip);
     exit;
 }
예제 #9
0
 public static function apiDownload(Request $r)
 {
     self::authenticateRequest($r);
     self::validateStats($r);
     // Get our runs
     $relevant_columns = array("run_id", "guid", "language", "status", "verdict", "runtime", "penalty", "memory", "score", "contest_score", "time", "submit_delay", "Users.username", "Problems.alias");
     try {
         $runs = RunsDAO::search(new Runs(array("contest_id" => $r["contest"]->getContestId())), "time", "DESC", $relevant_columns);
     } catch (Exception $e) {
         // Operation failed in the data layer
         throw new InvalidDatabaseOperationException($e);
     }
     $zip = new ZipStream($r["contest_alias"] . '.zip');
     // Add runs to zip
     $table = "guid,user,problem,verdict,points\n";
     foreach ($runs as $run) {
         $zip->add_file_from_path("runs/" . $run->getGuid(), RunController::getSubmissionPath($run));
         $columns[0] = 'username';
         $columns[1] = 'alias';
         $usernameProblemData = $run->asFilteredArray($columns);
         $table .= $run->getGuid() . "," . $usernameProblemData['username'] . "," . $usernameProblemData['alias'] . "," . $run->getVerdict() . "," . $run->getContestScore();
         $table .= "\n";
     }
     $zip->add_file("summary.csv", $table);
     // Add problem cases to zip
     $contest_problems = ContestProblemsDAO::GetRelevantProblems($r["contest"]->getContestId());
     foreach ($contest_problems as $problem) {
         $zip->add_file_from_path($problem->getAlias() . "_cases.zip", PROBLEMS_PATH . "/" . $problem->getAlias() . "/cases.zip");
     }
     // Return zip
     $zip->finish();
     die;
 }
예제 #10
0
 public static function apiDownload(Request $r)
 {
     self::authenticateRequest($r);
     self::validateStats($r);
     // Get our runs
     $relevant_columns = array('run_id', 'guid', 'language', 'status', 'verdict', 'runtime', 'penalty', 'memory', 'score', 'contest_score', 'time', 'submit_delay', 'Users.username', 'Problems.alias');
     try {
         $runs = RunsDAO::search(new Runs(array('contest_id' => $r['contest']->getContestId())), 'time', 'DESC', $relevant_columns);
     } catch (Exception $e) {
         // Operation failed in the data layer
         throw new InvalidDatabaseOperationException($e);
     }
     $zip = new ZipStream($r['contest_alias'] . '.zip');
     // Add runs to zip
     $table = "guid,user,problem,verdict,points\n";
     foreach ($runs as $run) {
         $zip->add_file_from_path('runs/' . $run->getGuid(), RunController::getSubmissionPath($run));
         $columns[0] = 'username';
         $columns[1] = 'alias';
         $usernameProblemData = $run->asFilteredArray($columns);
         $table .= $run->getGuid() . ',' . $usernameProblemData['username'] . ',' . $usernameProblemData['alias'] . ',' . $run->getVerdict() . ',' . $run->getContestScore();
         $table .= "\n";
     }
     $zip->add_file('summary.csv', $table);
     // Add problem cases to zip
     $contest_problems = ContestProblemsDAO::GetRelevantProblems($r['contest']->getContestId());
     foreach ($contest_problems as $problem) {
         $zip->add_file_from_path($problem->getAlias() . '_cases.zip', PROBLEMS_PATH . '/' . $problem->getAlias() . '/cases.zip');
     }
     // Return zip
     $zip->finish();
     die;
 }
예제 #11
0
// Load test utils
require_once OMEGAUP_ROOT . "/tests/controllers/OmegaupTestCase.php";
require_once OMEGAUP_ROOT . "/tests/common/Utils.php";
// Load Factories
require_once OMEGAUP_ROOT . '/tests/factories/ProblemsFactory.php';
require_once OMEGAUP_ROOT . '/tests/factories/ContestsFactory.php';
require_once OMEGAUP_ROOT . '/tests/factories/ClarificationsFactory.php';
require_once OMEGAUP_ROOT . '/tests/factories/UserFactory.php';
require_once OMEGAUP_ROOT . '/tests/factories/RunsFactory.php';
require_once OMEGAUP_ROOT . '/tests/factories/GroupsFactory.php';
// Clean previous log
Utils::CleanLog();
// Clean problems and runs path
Utils::CleanPath(PROBLEMS_PATH);
Utils::CleanPath(PROBLEMS_GIT_PATH);
Utils::CleanPath(RUNS_PATH);
Utils::CleanPath(GRADE_PATH);
Utils::CleanPath(IMAGES_PATH);
for ($i = 0; $i < 256; $i++) {
    mkdir(RUNS_PATH . sprintf('/%02x', $i), 0775, true);
    mkdir(GRADE_PATH . sprintf('/%02x', $i), 0775, true);
}
// Clean DB
Utils::CleanupDB();
// Create a test default user for manual UI operations
UserController::$sendEmailOnVerify = false;
UserFactory::createUser("test", "testtesttest");
UserController::$sendEmailOnVerify = true;
// Globally disable run wait gap.
RunController::$defaultSubmissionGap = 0;
예제 #12
0
 /**
  * Stats of a problem
  *
  * @param Request $r
  * @return array
  * @throws ForbiddenAccessException
  * @throws InvalidDatabaseOperationException
  */
 public static function apiStats(Request $r)
 {
     // Get user
     self::authenticateRequest($r);
     // Validate request
     self::validateRuns($r);
     // We need to check that the user has priviledges on the problem
     if (!Authorization::CanEditProblem($r['current_user_id'], $r['problem'])) {
         throw new ForbiddenAccessException();
     }
     try {
         // Array of GUIDs of pending runs
         $pendingRunsGuids = RunsDAO::GetPendingRunsOfProblem($r['problem']->getProblemId());
         // Count of pending runs (int)
         $totalRunsCount = RunsDAO::CountTotalRunsOfProblem($r['problem']->getProblemId());
         // List of verdicts
         $verdict_counts = array();
         foreach (self::$verdicts as $verdict) {
             $verdict_counts[$verdict] = RunsDAO::CountTotalRunsOfProblemByVerdict($r['problem']->getProblemId(), $verdict);
         }
         // Array to count AC stats per case.
         // Let's try to get the last snapshot from cache.
         $problemStatsCache = new Cache(Cache::PROBLEM_STATS, $r['problem']->getAlias());
         $cases_stats = $problemStatsCache->get();
         if (is_null($cases_stats)) {
             // Initialize the array at counts = 0
             $cases_stats = array();
             $cases_stats['counts'] = array();
             // We need to save the last_id that we processed, so next time we do not repeat this
             $cases_stats['last_id'] = 0;
             // Build problem dir
             $problem_dir = PROBLEMS_PATH . '/' . $r['problem']->getAlias() . '/cases/';
             // Get list of cases
             $dir = opendir($problem_dir);
             if (is_dir($problem_dir)) {
                 while (($file = readdir($dir)) !== false) {
                     // If we have an input
                     if (strstr($file, '.in')) {
                         // Initialize it to 0
                         $cases_stats['counts'][str_replace('.in', '', $file)] = 0;
                     }
                 }
                 closedir($dir);
             }
         }
         // Get all runs of this problem after the last id we had
         $runs = RunsDAO::searchRunIdGreaterThan(new Runs(array('problem_id' => $r['problem']->getProblemId())), $cases_stats['last_id'], 'run_id');
         // For each run we got
         foreach ($runs as $run) {
             // Build grade dir
             $grade_dir = RunController::getGradePath($run);
             // Skip it if it failed to compile.
             if (file_exists("{$grade_dir}/compile_error.log")) {
                 continue;
             }
             // Try to open the details file.
             if (file_exists("{$grade_dir}/details.json")) {
                 $details = json_decode(file_get_contents("{$grade_dir}/details.json"));
                 foreach ($details as $group) {
                     foreach ($group->cases as $case) {
                         if ($case->score > 0) {
                             $cases_stats['counts'][$case->name]++;
                         }
                     }
                 }
             }
         }
     } catch (Exception $e) {
         throw new InvalidDatabaseOperationException($e);
     }
     // Save the last id we saw in case we saw something
     if (!is_null($runs) && count($runs) > 0) {
         $cases_stats['last_id'] = $runs[count($runs) - 1]->getRunId();
     }
     // Save in cache what we got
     $problemStatsCache->set($cases_stats, APC_USER_CACHE_PROBLEM_STATS_TIMEOUT);
     return array('total_runs' => $totalRunsCount, 'pending_runs' => $pendingRunsGuids, 'verdict_counts' => $verdict_counts, 'cases_stats' => $cases_stats['counts'], 'status' => 'ok');
 }
예제 #13
0
 /**
  * User should wait between consecutive runs.
  *
  * @expectedException NotAllowedToSubmitException
  */
 public function testRunsToPublicProblemInsideSubmissionGap()
 {
     $originalGap = RunController::$defaultSubmissionGap;
     RunController::$defaultSubmissionGap = 60;
     try {
         // Create public problem
         $problemData = ProblemsFactory::createProblem();
         // Create our contestant
         $this->contestant = UserFactory::createUser();
         // Create an empty request
         $r = new Request();
         // Log in as contest director
         $r["auth_token"] = $this->login($this->contestant);
         // Build request
         $r["contest_alias"] = "";
         // Not inside a contest
         $r["problem_alias"] = $problemData["request"]["alias"];
         $r["language"] = "c";
         $r["source"] = "#include <stdio.h>\nint main() { printf(\"3\"); return 0; }";
         //PHPUnit does not set IP address, doing it manually
         $_SERVER["REMOTE_ADDR"] = "127.0.0.1";
         // Call API
         $this->detourGraderCalls($this->exactly(1));
         $response = RunController::apiCreate($r);
         // Validate the run
         $this->assertRun($r, $response);
         // Call API
         $response = RunController::apiCreate($r);
     } finally {
         RunController::$defaultSubmissionGap = $originalGap;
     }
 }
예제 #14
0
 /**
  * User should wait between consecutive runs.
  *
  * @expectedException NotAllowedToSubmitException
  */
 public function testRunsToPublicProblemInsideSubmissionGap()
 {
     $originalGap = RunController::$defaultSubmissionGap;
     RunController::$defaultSubmissionGap = 60;
     try {
         // Create public problem
         $problemData = ProblemsFactory::createProblem();
         // Create our contestant
         $this->contestant = UserFactory::createUser();
         // Create an empty request
         $r = new Request();
         // Log in as contest director
         $r['auth_token'] = $this->login($this->contestant);
         // Build request
         $r['contest_alias'] = '';
         // Not inside a contest
         $r['problem_alias'] = $problemData['request']['alias'];
         $r['language'] = 'c';
         $r['source'] = "#include <stdio.h>\nint main() { printf(\"3\"); return 0; }";
         // Call API
         $this->detourGraderCalls($this->exactly(1));
         $response = RunController::apiCreate($r);
         // Validate the run
         $this->assertRun($r, $response);
         // Call API
         $response = RunController::apiCreate($r);
     } finally {
         RunController::$defaultSubmissionGap = $originalGap;
     }
 }