コード例 #1
0
 /**
  * Simply check that the file exists.
  *
  * @param ExerciseInterface $exercise The exercise to check against.
  * @param Input $input The command line arguments passed to the command.
  * @return ResultInterface The result of the check.
  */
 public function check(ExerciseInterface $exercise, Input $input)
 {
     if (file_exists($input->getArgument('program'))) {
         return Success::fromCheck($this);
     }
     return Failure::fromCheckAndReason($this, sprintf('File: "%s" does not exist', $input->getArgument('program')));
 }
コード例 #2
0
ファイル: InputTest.php プロジェクト: php-school/php-workshop
 public function testSetArgument()
 {
     $input = new Input('app');
     $this->assertFalse($input->hasArgument('arg1'));
     $input->setArgument('arg1', 'some-value');
     $this->assertEquals('some-value', $input->getArgument('arg1'));
 }
コード例 #3
0
 /**
  * Parse the students solution and check that there are usages of
  * required functions and that banned functions are not used. The requirements
  * are pulled from the exercise.
  *
  * @param ExerciseInterface $exercise The exercise to check against.
  * @param Input $input The command line arguments passed to the command.
  * @return ResultInterface The result of the check.
  */
 public function check(ExerciseInterface $exercise, Input $input)
 {
     if (!$exercise instanceof FunctionRequirementsExerciseCheck) {
         throw new \InvalidArgumentException();
     }
     $requiredFunctions = $exercise->getRequiredFunctions();
     $bannedFunctions = $exercise->getBannedFunctions();
     $code = file_get_contents($input->getArgument('program'));
     try {
         $ast = $this->parser->parse($code);
     } catch (Error $e) {
         return Failure::fromCheckAndCodeParseFailure($this, $e, $input->getArgument('program'));
     }
     $visitor = new FunctionVisitor($requiredFunctions, $bannedFunctions);
     $traverser = new NodeTraverser();
     $traverser->addVisitor($visitor);
     $traverser->traverse($ast);
     $bannedFunctions = [];
     if ($visitor->hasUsedBannedFunctions()) {
         $bannedFunctions = array_map(function (FuncCall $node) {
             return ['function' => $node->name->__toString(), 'line' => $node->getLine()];
         }, $visitor->getBannedUsages());
     }
     $missingFunctions = [];
     if (!$visitor->hasMetFunctionRequirements()) {
         $missingFunctions = $visitor->getMissingRequirements();
     }
     if (!empty($bannedFunctions) || !empty($missingFunctions)) {
         return new FunctionRequirementsFailure($this, $bannedFunctions, $missingFunctions);
     }
     return Success::fromCheck($this);
 }
コード例 #4
0
 public function testInputIsUnchangedIfNoProgramArgument()
 {
     $exercise = new CliExerciseImpl();
     $input = new Input('app', ['some-arg' => 'some-value']);
     $listener = new RealPathListener();
     $listener->__invoke(new ExerciseRunnerEvent('some.event', $exercise, $input));
     $this->assertEquals('some-value', $input->getArgument('some-arg'));
 }
コード例 #5
0
 /**
  * Simply check the student's solution can be linted with `php -l`.
  *
  * @param ExerciseInterface $exercise The exercise to check against.
  * @param Input $input The command line arguments passed to the command.
  * @return ResultInterface The result of the check.
  */
 public function check(ExerciseInterface $exercise, Input $input)
 {
     $process = new Process(sprintf('%s -l %s', PHP_BINARY, $input->getArgument('program')));
     $process->run();
     if ($process->isSuccessful()) {
         return Success::fromCheck($this);
     }
     return Failure::fromCheckAndReason($this, $process->getErrorOutput());
 }
コード例 #6
0
 /**
  * This check grabs the contents of the student's solution and
  * attempts to parse it with `nikic/php-parser`. If any exceptions are thrown
  * by the parser, it is treated as a failure.
  *
  * @param ExerciseInterface $exercise The exercise to check against.
  * @param Input $input The command line arguments passed to the command.
  * @return ResultInterface The result of the check.
  */
 public function check(ExerciseInterface $exercise, Input $input)
 {
     $code = file_get_contents($input->getArgument('program'));
     try {
         $this->parser->parse($code);
     } catch (Error $e) {
         return Failure::fromCheckAndCodeParseFailure($this, $e, $input->getArgument('program'));
     }
     return Success::fromCheck($this);
 }
コード例 #7
0
 /**
  * This check parses the `composer.lock` file and checks that the student
  * installed a set of required packages. If they did not a failure is returned, otherwise,
  * a success is returned.
  *
  * @param ExerciseInterface $exercise The exercise to check against.
  * @param Input $input The command line arguments passed to the command.
  * @return ResultInterface The result of the check.
  */
 public function check(ExerciseInterface $exercise, Input $input)
 {
     if (!$exercise instanceof ComposerExerciseCheck) {
         throw new \InvalidArgumentException();
     }
     if (!file_exists(sprintf('%s/composer.json', dirname($input->getArgument('program'))))) {
         return new Failure($this->getName(), 'No composer.json file found');
     }
     if (!file_exists(sprintf('%s/composer.lock', dirname($input->getArgument('program'))))) {
         return new Failure($this->getName(), 'No composer.lock file found');
     }
     if (!file_exists(sprintf('%s/vendor', dirname($input->getArgument('program'))))) {
         return new Failure($this->getName(), 'No vendor folder found');
     }
     $lockFile = new LockFileParser(sprintf('%s/composer.lock', dirname($input->getArgument('program'))));
     $missingPackages = array_filter($exercise->getRequiredPackages(), function ($package) use($lockFile) {
         return !$lockFile->hasInstalledPackage($package);
     });
     if (count($missingPackages) > 0) {
         return new Failure($this->getName(), sprintf('Lockfile doesn\'t include the following packages at any version: "%s"', implode('", "', $missingPackages)));
     }
     return new Success($this->getName());
 }
コード例 #8
0
 /**
  * @param Input $input
  * @return ResultInterface
  */
 public function check(Input $input)
 {
     $statements = $this->parser->parse(file_get_contents($input->getArgument('program')));
     $include = null;
     foreach ($statements as $statement) {
         if ($statement instanceof Include_) {
             $include = $statement;
             break;
         }
     }
     if (null === $include) {
         return Failure::fromNameAndReason($this->getName(), 'No require statement found');
     }
     return new Success($this->getName());
 }
コード例 #9
0
ファイル: CgiRunner.php プロジェクト: php-school/php-workshop
 /**
  * Runs a student's solution by invoking PHP via the `php-cgi` binary, populating all the super globals with
  * the information from the request objects returned from the exercise. The exercise can return multiple
  * requests so the solution will be invoked for however many requests there are.
  *
  * Running only runs the student's solution, the reference solution is not run and no verification is performed,
  * the output of the student's solution is written directly to the output.
  *
  * Events dispatched (for each request):
  *
  * * cgi.run.student-execute.pre
  * * cgi.run.student.executing
  *
  * @param Input $input The command line arguments passed to the command.
  * @param OutputInterface $output A wrapper around STDOUT.
  * @return bool If the solution was successfully executed, eg. exit code was 0.
  */
 public function run(Input $input, OutputInterface $output)
 {
     $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cgi.run.start', $this->exercise, $input));
     $success = true;
     foreach ($this->exercise->getRequests() as $i => $request) {
         $event = $this->eventDispatcher->dispatch(new CgiExecuteEvent('cgi.run.student-execute.pre', $request));
         $process = $this->getProcess($input->getArgument('program'), $event->getRequest());
         $output->writeTitle("Request");
         $output->emptyLine();
         $output->write($this->requestRenderer->renderRequest($request));
         $output->writeTitle("Output");
         $output->emptyLine();
         $process->start();
         $this->eventDispatcher->dispatch(new CgiExecuteEvent('cgi.run.student.executing', $request, ['output' => $output]));
         $process->wait(function ($outputType, $outputBuffer) use($output) {
             $output->write($outputBuffer);
         });
         $output->emptyLine();
         if (!$process->isSuccessful()) {
             $success = false;
         }
         $output->lineBreak();
     }
     $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cgi.run.finish', $this->exercise, $input));
     return $success;
 }
コード例 #10
0
ファイル: CliRunner.php プロジェクト: php-school/php-workshop
 /**
  * Runs a student's solution by invoking PHP from the CLI passing the arguments gathered from the exercise
  * as command line arguments to PHP.
  *
  * Running only runs the student's solution, the reference solution is not run and no verification is performed,
  * the output of the student's solution is written directly to the output.
  *
  * Events dispatched:
  *
  *  * cli.run.student-execute.pre
  *  * cli.run.student.executing
  *
  * @param Input $input The command line arguments passed to the command.
  * @param OutputInterface $output A wrapper around STDOUT.
  * @return bool If the solution was successfully executed, eg. exit code was 0.
  */
 public function run(Input $input, OutputInterface $output)
 {
     $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cli.run.start', $this->exercise, $input));
     $success = true;
     foreach ($this->preserveOldArgFormat($this->exercise->getArgs()) as $i => $args) {
         /** @var CliExecuteEvent $event */
         $event = $this->eventDispatcher->dispatch(new CliExecuteEvent('cli.run.student-execute.pre', new ArrayObject($args)));
         $args = $event->getArgs();
         if (count($args)) {
             $glue = max(array_map('strlen', $args->getArrayCopy())) > 30 ? "\n" : ', ';
             $output->writeTitle('Arguments');
             $output->write(implode($glue, $args->getArrayCopy()));
             $output->emptyLine();
         }
         $output->writeTitle("Output");
         $process = $this->getPhpProcess($input->getArgument('program'), $args);
         $process->start();
         $this->eventDispatcher->dispatch(new CliExecuteEvent('cli.run.student.executing', $args, ['output' => $output]));
         $process->wait(function ($outputType, $outputBuffer) use($output) {
             $output->write($outputBuffer);
         });
         $output->emptyLine();
         if (!$process->isSuccessful()) {
             $success = false;
         }
         $output->lineBreak();
     }
     $this->eventDispatcher->dispatch(new ExerciseRunnerEvent('cli.run.finish', $this->exercise, $input));
     return $success;
 }