From 4ad9a96b410079a72d1a11109664c49955044dd0 Mon Sep 17 00:00:00 2001 From: Chris C Date: Sun, 22 May 2016 13:18:57 -0500 Subject: [PATCH 1/8] exclude warnings from verify output; will still fail on warnings. warnings will still show in run output, as it is written differently. this is correct behavior. do not force error to display, in fact, turn them off. --- app/config.php | 4 +-- src/ExerciseRunner/CliRunner.php | 13 ++++----- src/Result/StdOutFailure.php | 28 +++++++++++++++++++- src/ResultRenderer/OutputFailureRenderer.php | 6 +++-- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/app/config.php b/app/config.php index fdf9896b..6f741f1d 100644 --- a/app/config.php +++ b/app/config.php @@ -203,9 +203,9 @@ }), CodePatcher::class => factory(function (ContainerInterface $c) { $patch = (new Patch) - ->withInsertion(new Insertion(Insertion::TYPE_BEFORE, 'ini_set("display_errors", 1);')) + ->withInsertion(new Insertion(Insertion::TYPE_BEFORE, 'ini_set("display_errors", 0);')) ->withInsertion(new Insertion(Insertion::TYPE_BEFORE, 'error_reporting(E_ALL);')) - ->withInsertion(new Insertion(Insertion ::TYPE_BEFORE, 'date_default_timezone_set("Europe/London");')); + ->withInsertion(new Insertion(Insertion::TYPE_BEFORE, 'date_default_timezone_set("Europe/London");')); return new CodePatcher($c->get(Parser::class), new Standard, $patch); }), diff --git a/src/ExerciseRunner/CliRunner.php b/src/ExerciseRunner/CliRunner.php index 0cdf95b4..35c9328b 100644 --- a/src/ExerciseRunner/CliRunner.php +++ b/src/ExerciseRunner/CliRunner.php @@ -2,7 +2,6 @@ namespace PhpSchool\PhpWorkshop\ExerciseRunner; -use PhpSchool\PhpWorkshop\Event\CliEvent; use PhpSchool\PhpWorkshop\Event\CliExecuteEvent; use PhpSchool\PhpWorkshop\Event\Event; use PhpSchool\PhpWorkshop\Event\EventDispatcher; @@ -11,7 +10,6 @@ use PhpSchool\PhpWorkshop\Exercise\CliExercise; use PhpSchool\PhpWorkshop\Exercise\ExerciseInterface; use PhpSchool\PhpWorkshop\Exercise\ExerciseType; -use PhpSchool\PhpWorkshop\ExerciseCheck\StdOutExerciseCheck; use PhpSchool\PhpWorkshop\Output\OutputInterface; use PhpSchool\PhpWorkshop\Result\Failure; use PhpSchool\PhpWorkshop\Result\ResultInterface; @@ -71,8 +69,7 @@ private function executePhpFile($fileName, ArrayObject $args, $type) if (!$process->isSuccessful()) { throw CodeExecutionException::fromProcess($process); } - - return $process->getOutput(); + return ($type == 'user' ? ['output' => $process->getOutput(), 'warnings' => $process->getErrorOutput()] : $process->getOutput()); } /** @@ -110,13 +107,17 @@ public function verify($fileName) try { $event = $this->eventDispatcher->dispatch(new CliExecuteEvent('cli.verify.user-execute.pre', $args)); - $userOutput = $this->executePhpFile($fileName, $event->getArgs(), 'user'); + list($userOutput, $userWarnings) = $this->executePhpFile($fileName, $event->getArgs(), 'user'); } catch (CodeExecutionException $e) { $this->eventDispatcher->dispatch(new Event('cli.verify.user-execute.fail', ['exception' => $e])); return Failure::fromNameAndCodeExecutionFailure($this->getName(), $e); } if ($solutionOutput === $userOutput) { - return new Success($this->getName()); + if (!empty($userWarnings)) { + return StdOutFailure::fromNameAndWarnings($this->getName(), $solutionOutput, $userOutput, $userWarnings); + } else { + return new Success($this->getName()); + } } return StdOutFailure::fromNameAndOutput($this->getName(), $solutionOutput, $userOutput); diff --git a/src/Result/StdOutFailure.php b/src/Result/StdOutFailure.php index 30d84f3c..856036be 100644 --- a/src/Result/StdOutFailure.php +++ b/src/Result/StdOutFailure.php @@ -26,16 +26,22 @@ class StdOutFailure implements FailureInterface */ private $actualOutput; + /** + * @var string + */ + private $warnings; + /** * @param string $name * @param string $expectedOutput * @param string $actualOutput */ - public function __construct($name, $expectedOutput, $actualOutput) + public function __construct($name, $expectedOutput, $actualOutput, $warnings) { $this->name = $name; $this->expectedOutput = $expectedOutput; $this->actualOutput = $actualOutput; + $this->warnings = $warnings; } /** @@ -49,6 +55,18 @@ public static function fromNameAndOutput($name, $expectedOutput, $actualOutput) return new static($name, $expectedOutput, $actualOutput); } + /** + * @param string $name + * @param $expectedOutput + * @param $actualOutput + * @param $warnings + * @return static + */ + public static function fromNameAndWarnings($name, $expectedOutput, $actualOutput, $warnings) + { + return new static($name, $expectedOutput, $actualOutput, $warnings); + } + /** * @param CheckInterface $check * @param $expectedOutput @@ -83,4 +101,12 @@ public function getActualOutput() { return $this->actualOutput; } + + /** + * @return string + */ + public function getWarnings() + { + return $this->warnings; + } } diff --git a/src/ResultRenderer/OutputFailureRenderer.php b/src/ResultRenderer/OutputFailureRenderer.php index db2c08a3..174e5dda 100644 --- a/src/ResultRenderer/OutputFailureRenderer.php +++ b/src/ResultRenderer/OutputFailureRenderer.php @@ -32,11 +32,13 @@ public function __construct(StdOutFailure $result) public function render(ResultsRenderer $renderer) { return sprintf( - " %s\n%s\n\n %s\n%s\n", + " %s\n%s\n\n %s\n%s\n" . ($this->result->getWarnings() ? "\n %s\n%s\n" : ""), $renderer->style("ACTUAL", ['bold', 'underline', 'yellow']), $this->indent($renderer->style(sprintf('"%s"', $this->result->getActualOutput()), 'red')), $renderer->style("EXPECTED", ['yellow', 'bold', 'underline']), - $this->indent($renderer->style(sprintf('"%s"', $this->result->getExpectedOutput()), 'red')) + $this->indent($renderer->style(sprintf('"%s"', $this->result->getExpectedOutput()), 'red')), + $renderer->style("WARNINGS", ['yellow', 'bold', 'underline']), + $this->indent($renderer->style(sprintf('"%s"', $this->result->getWarnings()), 'red')) ); } From 284372c4f26e848184b778c789caf3f9935623f0 Mon Sep 17 00:00:00 2001 From: Chris C Date: Sun, 22 May 2016 13:24:14 -0500 Subject: [PATCH 2/8] correct the test. --- test/CodePatcherTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/CodePatcherTest.php b/test/CodePatcherTest.php index d4b7149a..ff978964 100644 --- a/test/CodePatcherTest.php +++ b/test/CodePatcherTest.php @@ -26,12 +26,12 @@ class CodePatcherTest extends PHPUnit_Framework_TestCase public function testDefaultPatchIsAppliedIfAvailable() { $patch = (new Patch) - ->withInsertion(new Insertion(Insertion::TYPE_BEFORE, 'ini_set("display_errors", 1);')); + ->withInsertion(new Insertion(Insertion::TYPE_BEFORE, 'ini_set("display_errors", 0);')); $patcher = new CodePatcher((new ParserFactory)->create(ParserFactory::PREFER_PHP7), new Standard, $patch); $exercise = $this->getMock(ExerciseInterface::class); - $expected = "assertEquals($expected, $patcher->patch($exercise, ' Date: Tue, 24 May 2016 14:17:53 -0500 Subject: [PATCH 3/8] Check code for warnings and errors, in both CliRunner and CgiRunner. Ref: #4 --- src/Exception/CodeExecutionException.php | 40 +++++++++++++++-- src/ExerciseRunner/CgiRunner.php | 8 ++-- src/ExerciseRunner/CliRunner.php | 4 +- src/Result/CgiOutRequestFailure.php | 18 +++++++- src/Result/Failure.php | 56 +++++++++++++++++++++--- src/ResultRenderer/FailureRenderer.php | 31 ++++++++++++- 6 files changed, 141 insertions(+), 16 deletions(-) diff --git a/src/Exception/CodeExecutionException.php b/src/Exception/CodeExecutionException.php index ec238831..3eb0bc9e 100644 --- a/src/Exception/CodeExecutionException.php +++ b/src/Exception/CodeExecutionException.php @@ -12,14 +12,48 @@ */ class CodeExecutionException extends RuntimeException { + + /** + * @var string + */ + private $actual; + /** + * @var string + */ + private $errors; + + /** + * CodeExecutionException constructor. + * @param string $reason + * @param string $actual + * @param string $errors + */ + public function __construct($reason, $actual, $errors) { + $this->message = $reason; + $this->actual = $actual; + $this->errors = $errors; + } + /** * @param Process $process * @return static */ public static function fromProcess(Process $process) { - $message = 'PHP Code failed to execute. Error: "%s"'; - $processOutput = $process->getErrorOutput() ? $process->getErrorOutput() : $process->getOutput(); - return new static(sprintf($message, $processOutput)); + $message = "PHP Code failed to execute. Error: \n%s"; + $processOutput = $process->getOutput(); + $processErrorOutput = $process->getErrorOutput(); + return new static(sprintf($message, $processErrorOutput ?: $processOutput), $processOutput, $processErrorOutput); + } + + public function getActual() + { + return $this->actual; } + + public function getErrors() + { + return $this->errors; + } + } diff --git a/src/ExerciseRunner/CgiRunner.php b/src/ExerciseRunner/CgiRunner.php index a306d793..d852c760 100644 --- a/src/ExerciseRunner/CgiRunner.php +++ b/src/ExerciseRunner/CgiRunner.php @@ -98,7 +98,7 @@ private function checkRequest(RequestInterface $request, $fileName) try { $event = $this->eventDispatcher->dispatch(new CgiExecuteEvent('cgi.verify.user-execute.pre', $request)); - $userResponse = $this->executePhpFile($fileName, $event->getRequest(), 'user'); + list($userResponse, $userWarnings) = $this->executePhpFile($fileName, $event->getRequest(), 'user'); } catch (CodeExecutionException $e) { $this->eventDispatcher->dispatch(new Event('cgi.verify.user-execute.fail', ['exception' => $e])); return Failure::fromNameAndCodeExecutionFailure($this->getName(), $e); @@ -109,8 +109,8 @@ private function checkRequest(RequestInterface $request, $fileName) $solutionHeaders = $this->getHeaders($solutionResponse); $userHeaders = $this->getHeaders($userResponse); - if ($solutionBody !== $userBody || $solutionHeaders !== $userHeaders) { - return new CgiOutRequestFailure($request, $solutionBody, $userBody, $solutionHeaders, $userHeaders); + if ($solutionBody !== $userBody || $solutionHeaders !== $userHeaders || $userWarnings) { + return new CgiOutRequestFailure($request, $solutionBody, $userBody, $solutionHeaders, $userHeaders, $userWarnings); } return new Success($this->getName()); @@ -153,7 +153,7 @@ private function executePhpFile($fileName, RequestInterface $request, $type) $output = "HTTP/1.0 200 OK\r\n" . $output; } - return ResponseSerializer::fromString($output); + return ($type == 'user' ? [ResponseSerializer::fromString($output), $process->getErrorOutput()] : ResponseSerializer::fromString($output)); } /** diff --git a/src/ExerciseRunner/CliRunner.php b/src/ExerciseRunner/CliRunner.php index 35c9328b..4e76d923 100644 --- a/src/ExerciseRunner/CliRunner.php +++ b/src/ExerciseRunner/CliRunner.php @@ -110,9 +110,9 @@ public function verify($fileName) list($userOutput, $userWarnings) = $this->executePhpFile($fileName, $event->getArgs(), 'user'); } catch (CodeExecutionException $e) { $this->eventDispatcher->dispatch(new Event('cli.verify.user-execute.fail', ['exception' => $e])); - return Failure::fromNameAndCodeExecutionFailure($this->getName(), $e); + return Failure::fromNameAndCodeExecutionFailure($this->getName(), $e, $solutionOutput, $e->getActual(), $e->getErrors()); } - if ($solutionOutput === $userOutput) { + if ($solutionOutput === $userOutput || !empty($userWarnings)) { if (!empty($userWarnings)) { return StdOutFailure::fromNameAndWarnings($this->getName(), $solutionOutput, $userOutput, $userWarnings); } else { diff --git a/src/Result/CgiOutRequestFailure.php b/src/Result/CgiOutRequestFailure.php index 77e0085f..510ff2ce 100644 --- a/src/Result/CgiOutRequestFailure.php +++ b/src/Result/CgiOutRequestFailure.php @@ -36,25 +36,33 @@ class CgiOutRequestFailure implements FailureInterface */ private $actualHeaders; + /** + * @var string|null + */ + private $warnings; + /** * @param RequestInterface $request * @param string $expectedOutput * @param string $actualOutput * @param array $expectedHeaders * @param array $actualHeaders + * @param string|null $warnings */ public function __construct( RequestInterface $request, $expectedOutput, $actualOutput, array $expectedHeaders, - array $actualHeaders + array $actualHeaders, + $warnings = null ) { $this->request = $request; $this->expectedOutput = $expectedOutput; $this->actualOutput = $actualOutput; $this->expectedHeaders = $expectedHeaders; $this->actualHeaders = $actualHeaders; + $this->warnings = $warnings; } /** @@ -128,4 +136,12 @@ public function getCheckName() { return 'Request Failure'; } + + /** + * @return string|null + */ + public function getWarnings() + { + return $this->warnings; + } } diff --git a/src/Result/Failure.php b/src/Result/Failure.php index 9b6b219d..b24844ea 100644 --- a/src/Result/Failure.php +++ b/src/Result/Failure.php @@ -18,6 +18,21 @@ class Failure implements FailureInterface */ private $reason; + /** + * @var string|null + */ + private $expectedOutput; + + /** + * @var string|null + */ + private $actualOutput; + + /** + * @var string|null + */ + private $errors; + /** * @var string */ @@ -26,11 +41,16 @@ class Failure implements FailureInterface /** * @param string $name * @param string|null $reason + * @param string|null $expectedOutput + * @param string|null $actualOutput */ - public function __construct($name, $reason = null) + public function __construct($name, $reason = null, $expectedOutput = null, $actualOutput = null, $errors = null) { - $this->name = $name; - $this->reason = $reason; + $this->name = $name; + $this->reason = $reason; + $this->expectedOutput = $expectedOutput; + $this->actualOutput = $actualOutput; + $this->errors = $errors; } /** @@ -56,11 +76,14 @@ public static function fromCheckAndReason(CheckInterface $check, $reason) /** * @param string $name * @param CodeExecutionException $e + * @param string|null $expectedOutput + * @param string|null $actualOutput + * @param string|null $errors * @return static */ - public static function fromNameAndCodeExecutionFailure($name, CodeExecutionException $e) + public static function fromNameAndCodeExecutionFailure($name, CodeExecutionException $e, $expectedOutput = null, $actualOutput = null, $errors = null) { - return new static($name, $e->getMessage()); + return new static($name, $e->getMessage(), $expectedOutput, $actualOutput, $errors); } /** @@ -92,4 +115,27 @@ public function getReason() { return $this->reason; } + + /** + * @return string|null + */ + public function getExpectedOutput() + { + return $this->expectedOutput; + } + + /** + * @return string|null + */ + public function getActualOutput() + { + return $this->actualOutput; + } + + /** + * @return string|null + */ + public function getErrors() { + return $this->errors; + } } diff --git a/src/ResultRenderer/FailureRenderer.php b/src/ResultRenderer/FailureRenderer.php index 5c4cdac2..743b1bfe 100644 --- a/src/ResultRenderer/FailureRenderer.php +++ b/src/ResultRenderer/FailureRenderer.php @@ -30,6 +30,35 @@ public function __construct(Failure $result) */ public function render(ResultsRenderer $renderer) { - return ' ' . $this->result->getReason() . "\n"; + if ($this->result->getExpectedOutput()) { + return sprintf( + " %s\n%s\n\n %s\n%s\n" . ($this->result->getErrors() ? "\n %s\n%s\n" : ""), + $renderer->style("ACTUAL", ['bold', 'underline', 'yellow']), + $this->indent($renderer->style(sprintf('"%s"', $this->result->getActualOutput()), 'red')), + $renderer->style("EXPECTED", ['yellow', 'bold', 'underline']), + $this->indent($renderer->style(sprintf('"%s"', $this->result->getExpectedOutput()), 'red')), + $renderer->style("ERRORS/WARNINGS", ['yellow', 'bold', 'underline']), + $this->indent($renderer->style(sprintf('%s', $this->result->getErrors()), 'red')) + ); + } else { + return ' ' . $this->result->getReason() . "\n"; + } + } + + /** + * @param string $string + * @return string + */ + private function indent($string) + { + return implode( + "\n", + array_map( + function ($line) { + return sprintf(" %s", $line); + }, + explode("\n", $string) + ) + ); } } From e0928fef37bd95f9b5ff7a2d8f0484e479801dc8 Mon Sep 17 00:00:00 2001 From: Chris C Date: Tue, 24 May 2016 14:53:20 -0500 Subject: [PATCH 4/8] phpcs fixes for line length. --- src/Exception/CodeExecutionException.php | 8 +++++--- src/ExerciseRunner/CgiRunner.php | 15 +++++++++++++-- src/ExerciseRunner/CliRunner.php | 21 ++++++++++++++++++--- src/Result/Failure.php | 12 +++++++++--- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/Exception/CodeExecutionException.php b/src/Exception/CodeExecutionException.php index 3eb0bc9e..54f26ccc 100644 --- a/src/Exception/CodeExecutionException.php +++ b/src/Exception/CodeExecutionException.php @@ -28,7 +28,8 @@ class CodeExecutionException extends RuntimeException * @param string $actual * @param string $errors */ - public function __construct($reason, $actual, $errors) { + public function __construct($reason, $actual, $errors) + { $this->message = $reason; $this->actual = $actual; $this->errors = $errors; @@ -43,7 +44,9 @@ public static function fromProcess(Process $process) $message = "PHP Code failed to execute. Error: \n%s"; $processOutput = $process->getOutput(); $processErrorOutput = $process->getErrorOutput(); - return new static(sprintf($message, $processErrorOutput ?: $processOutput), $processOutput, $processErrorOutput); + return new static( + sprintf($message, $processErrorOutput ?: $processOutput), $processOutput, $processErrorOutput + ); } public function getActual() @@ -55,5 +58,4 @@ public function getErrors() { return $this->errors; } - } diff --git a/src/ExerciseRunner/CgiRunner.php b/src/ExerciseRunner/CgiRunner.php index d852c760..d2f98d32 100644 --- a/src/ExerciseRunner/CgiRunner.php +++ b/src/ExerciseRunner/CgiRunner.php @@ -110,7 +110,14 @@ private function checkRequest(RequestInterface $request, $fileName) $userHeaders = $this->getHeaders($userResponse); if ($solutionBody !== $userBody || $solutionHeaders !== $userHeaders || $userWarnings) { - return new CgiOutRequestFailure($request, $solutionBody, $userBody, $solutionHeaders, $userHeaders, $userWarnings); + return new CgiOutRequestFailure( + $request, + $solutionBody, + $userBody, + $solutionHeaders, + $userHeaders, + $userWarnings + ); } return new Success($this->getName()); @@ -153,7 +160,11 @@ private function executePhpFile($fileName, RequestInterface $request, $type) $output = "HTTP/1.0 200 OK\r\n" . $output; } - return ($type == 'user' ? [ResponseSerializer::fromString($output), $process->getErrorOutput()] : ResponseSerializer::fromString($output)); + return ( + $type == 'user' ? + [ResponseSerializer::fromString($output), $process->getErrorOutput()] + : ResponseSerializer::fromString($output) + ); } /** diff --git a/src/ExerciseRunner/CliRunner.php b/src/ExerciseRunner/CliRunner.php index 4e76d923..176bb5ae 100644 --- a/src/ExerciseRunner/CliRunner.php +++ b/src/ExerciseRunner/CliRunner.php @@ -69,7 +69,11 @@ private function executePhpFile($fileName, ArrayObject $args, $type) if (!$process->isSuccessful()) { throw CodeExecutionException::fromProcess($process); } - return ($type == 'user' ? ['output' => $process->getOutput(), 'warnings' => $process->getErrorOutput()] : $process->getOutput()); + return ( + $type == 'user' ? + ['output' => $process->getOutput(), 'warnings' => $process->getErrorOutput()] + : $process->getOutput() + ); } /** @@ -110,11 +114,22 @@ public function verify($fileName) list($userOutput, $userWarnings) = $this->executePhpFile($fileName, $event->getArgs(), 'user'); } catch (CodeExecutionException $e) { $this->eventDispatcher->dispatch(new Event('cli.verify.user-execute.fail', ['exception' => $e])); - return Failure::fromNameAndCodeExecutionFailure($this->getName(), $e, $solutionOutput, $e->getActual(), $e->getErrors()); + return Failure::fromNameAndCodeExecutionFailure( + $this->getName(), + $e, + $solutionOutput, + $e->getActual(), + $e->getErrors() + ); } if ($solutionOutput === $userOutput || !empty($userWarnings)) { if (!empty($userWarnings)) { - return StdOutFailure::fromNameAndWarnings($this->getName(), $solutionOutput, $userOutput, $userWarnings); + return StdOutFailure::fromNameAndWarnings( + $this->getName(), + $solutionOutput, + $userOutput, + $userWarnings + ); } else { return new Success($this->getName()); } diff --git a/src/Result/Failure.php b/src/Result/Failure.php index b24844ea..cbefcab4 100644 --- a/src/Result/Failure.php +++ b/src/Result/Failure.php @@ -81,8 +81,13 @@ public static function fromCheckAndReason(CheckInterface $check, $reason) * @param string|null $errors * @return static */ - public static function fromNameAndCodeExecutionFailure($name, CodeExecutionException $e, $expectedOutput = null, $actualOutput = null, $errors = null) - { + public static function fromNameAndCodeExecutionFailure( + $name, + CodeExecutionException $e, + $expectedOutput = null, + $actualOutput = null, + $errors = null + ) { return new static($name, $e->getMessage(), $expectedOutput, $actualOutput, $errors); } @@ -135,7 +140,8 @@ public function getActualOutput() /** * @return string|null */ - public function getErrors() { + public function getErrors() + { return $this->errors; } } From becc71a575a4e88f7a4e767a8807d6ba7dba7e68 Mon Sep 17 00:00:00 2001 From: Chris C Date: Sat, 28 May 2016 03:14:16 -0500 Subject: [PATCH 5/8] default some parameters that shouldn't affect existing behavior. remove some array keys that worked in some environments, but not all. rewrite some test comparisons due to the changed formatting of some error messages. ran composer update, so have new lock file. --- composer.lock | 77 ++++++++++--------- src/Exception/CodeExecutionException.php | 2 +- src/ExerciseRunner/CliRunner.php | 2 +- src/Result/StdOutFailure.php | 2 +- test/Exception/CodeExecutionExceptionTest.php | 4 +- test/ExerciseRunner/CgiRunnerTest.php | 4 +- test/ExerciseRunner/CliRunnerTest.php | 6 +- 7 files changed, 50 insertions(+), 47 deletions(-) diff --git a/composer.lock b/composer.lock index 93372587..6905b95d 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "3235a8dc2d974f4b27bc4cd545ed37fb", + "hash": "d12a566491d807f91315a39b604ff0ac", "content-hash": "21f1705d07a93a8b7f249bd23a0755df", "packages": [ { @@ -665,7 +665,7 @@ }, { "name": "symfony/filesystem", - "version": "v3.0.5", + "version": "v3.0.6", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", @@ -714,7 +714,7 @@ }, { "name": "symfony/process", - "version": "v3.0.5", + "version": "v3.0.6", "source": { "type": "git", "url": "https://github.com/symfony/process.git", @@ -870,16 +870,16 @@ }, { "name": "composer/composer", - "version": "1.1.0-RC", + "version": "1.1.1", "source": { "type": "git", "url": "https://github.com/composer/composer.git", - "reference": "94c2a21fe51016758212fa0aebd8add36757f354" + "reference": "48156b0fd9888bf528fbe9c9cba6963223cdd584" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/composer/composer/zipball/94c2a21fe51016758212fa0aebd8add36757f354", - "reference": "94c2a21fe51016758212fa0aebd8add36757f354", + "url": "https://api.github.com/repos/composer/composer/zipball/48156b0fd9888bf528fbe9c9cba6963223cdd584", + "reference": "48156b0fd9888bf528fbe9c9cba6963223cdd584", "shasum": "" }, "require": { @@ -943,7 +943,7 @@ "dependency", "package" ], - "time": "2016-04-29 16:32:14" + "time": "2016-05-17 11:25:44" }, { "name": "composer/semver", @@ -1343,16 +1343,16 @@ }, { "name": "phpunit/php-code-coverage", - "version": "3.3.1", + "version": "3.3.3", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git", - "reference": "2431befdd451fac43fbcde94d1a92fb3b8b68f86" + "reference": "44cd8e3930e431658d1a5de7d282d5cb37837fd5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/2431befdd451fac43fbcde94d1a92fb3b8b68f86", - "reference": "2431befdd451fac43fbcde94d1a92fb3b8b68f86", + "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/44cd8e3930e431658d1a5de7d282d5cb37837fd5", + "reference": "44cd8e3930e431658d1a5de7d282d5cb37837fd5", "shasum": "" }, "require": { @@ -1402,7 +1402,7 @@ "testing", "xunit" ], - "time": "2016-04-08 08:14:53" + "time": "2016-05-27 16:24:29" }, { "name": "phpunit/php-file-iterator", @@ -1494,21 +1494,24 @@ }, { "name": "phpunit/php-timer", - "version": "1.0.7", + "version": "1.0.8", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/php-timer.git", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b" + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/3e82f4e9fc92665fafd9157568e4dcb01d014e5b", - "reference": "3e82f4e9fc92665fafd9157568e4dcb01d014e5b", + "url": "https://api.github.com/repos/sebastianbergmann/php-timer/zipball/38e9124049cf1a164f1e4537caf19c99bf1eb260", + "reference": "38e9124049cf1a164f1e4537caf19c99bf1eb260", "shasum": "" }, "require": { "php": ">=5.3.3" }, + "require-dev": { + "phpunit/phpunit": "~4|~5" + }, "type": "library", "autoload": { "classmap": [ @@ -1531,7 +1534,7 @@ "keywords": [ "timer" ], - "time": "2015-06-21 08:01:12" + "time": "2016-05-12 18:03:57" }, { "name": "phpunit/php-token-stream", @@ -1584,16 +1587,16 @@ }, { "name": "phpunit/phpunit", - "version": "5.3.2", + "version": "5.3.4", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/phpunit.git", - "reference": "2c6da3536035617bae3fe3db37283c9e0eb63ab3" + "reference": "00dd95ffb48805503817ced06399017df315fe5c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/2c6da3536035617bae3fe3db37283c9e0eb63ab3", - "reference": "2c6da3536035617bae3fe3db37283c9e0eb63ab3", + "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/00dd95ffb48805503817ced06399017df315fe5c", + "reference": "00dd95ffb48805503817ced06399017df315fe5c", "shasum": "" }, "require": { @@ -1655,7 +1658,7 @@ "testing", "xunit" ], - "time": "2016-04-12 16:20:08" + "time": "2016-05-11 13:28:45" }, { "name": "phpunit/phpunit-mock-objects", @@ -1914,16 +1917,16 @@ }, { "name": "sebastian/environment", - "version": "1.3.6", + "version": "1.3.7", "source": { "type": "git", "url": "https://github.com/sebastianbergmann/environment.git", - "reference": "2292b116f43c272ff4328083096114f84ea46a56" + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/2292b116f43c272ff4328083096114f84ea46a56", - "reference": "2292b116f43c272ff4328083096114f84ea46a56", + "url": "https://api.github.com/repos/sebastianbergmann/environment/zipball/4e8f0da10ac5802913afc151413bc8c53b6c2716", + "reference": "4e8f0da10ac5802913afc151413bc8c53b6c2716", "shasum": "" }, "require": { @@ -1960,7 +1963,7 @@ "environment", "hhvm" ], - "time": "2016-05-04 07:59:13" + "time": "2016-05-17 03:18:57" }, { "name": "sebastian/exporter", @@ -2481,7 +2484,7 @@ }, { "name": "symfony/console", - "version": "v3.0.5", + "version": "v3.0.6", "source": { "type": "git", "url": "https://github.com/symfony/console.git", @@ -2541,7 +2544,7 @@ }, { "name": "symfony/finder", - "version": "v3.0.5", + "version": "v3.0.6", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", @@ -2590,16 +2593,16 @@ }, { "name": "symfony/polyfill-mbstring", - "version": "v1.1.1", + "version": "v1.2.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "1289d16209491b584839022f29257ad859b8532d" + "reference": "dff51f72b0706335131b00a7f49606168c582594" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/1289d16209491b584839022f29257ad859b8532d", - "reference": "1289d16209491b584839022f29257ad859b8532d", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/dff51f72b0706335131b00a7f49606168c582594", + "reference": "dff51f72b0706335131b00a7f49606168c582594", "shasum": "" }, "require": { @@ -2611,7 +2614,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "1.2-dev" } }, "autoload": { @@ -2645,11 +2648,11 @@ "portable", "shim" ], - "time": "2016-01-20 09:13:37" + "time": "2016-05-18 14:26:46" }, { "name": "symfony/yaml", - "version": "v3.0.5", + "version": "v3.0.6", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", diff --git a/src/Exception/CodeExecutionException.php b/src/Exception/CodeExecutionException.php index 54f26ccc..c92cf512 100644 --- a/src/Exception/CodeExecutionException.php +++ b/src/Exception/CodeExecutionException.php @@ -28,7 +28,7 @@ class CodeExecutionException extends RuntimeException * @param string $actual * @param string $errors */ - public function __construct($reason, $actual, $errors) + public function __construct($reason, $actual = null, $errors = null) { $this->message = $reason; $this->actual = $actual; diff --git a/src/ExerciseRunner/CliRunner.php b/src/ExerciseRunner/CliRunner.php index 176bb5ae..c9207b97 100644 --- a/src/ExerciseRunner/CliRunner.php +++ b/src/ExerciseRunner/CliRunner.php @@ -71,7 +71,7 @@ private function executePhpFile($fileName, ArrayObject $args, $type) } return ( $type == 'user' ? - ['output' => $process->getOutput(), 'warnings' => $process->getErrorOutput()] + [$process->getOutput(), $process->getErrorOutput()] : $process->getOutput() ); } diff --git a/src/Result/StdOutFailure.php b/src/Result/StdOutFailure.php index 856036be..c0da3701 100644 --- a/src/Result/StdOutFailure.php +++ b/src/Result/StdOutFailure.php @@ -36,7 +36,7 @@ class StdOutFailure implements FailureInterface * @param string $expectedOutput * @param string $actualOutput */ - public function __construct($name, $expectedOutput, $actualOutput, $warnings) + public function __construct($name, $expectedOutput, $actualOutput, $warnings = null) { $this->name = $name; $this->expectedOutput = $expectedOutput; diff --git a/test/Exception/CodeExecutionExceptionTest.php b/test/Exception/CodeExecutionExceptionTest.php index fe26f6ae..ca1aa332 100644 --- a/test/Exception/CodeExecutionExceptionTest.php +++ b/test/Exception/CodeExecutionExceptionTest.php @@ -31,7 +31,7 @@ public function testFromProcessUsesErrorOutputIfNotEmpty() ->will($this->returnValue('Error Output')); $e = CodeExecutionException::fromProcess($process); - $this->assertEquals('PHP Code failed to execute. Error: "Error Output"', $e->getMessage()); + $this->assertEquals("PHP Code failed to execute. Error: \nError Output", $e->getMessage()); } public function testFromProcessUsesStdOutputIfErrorOutputEmpty() @@ -51,6 +51,6 @@ public function testFromProcessUsesStdOutputIfErrorOutputEmpty() ->will($this->returnValue('Std Output')); $e = CodeExecutionException::fromProcess($process); - $this->assertEquals('PHP Code failed to execute. Error: "Std Output"', $e->getMessage()); + $this->assertEquals("PHP Code failed to execute. Error: \nStd Output", $e->getMessage()); } } diff --git a/test/ExerciseRunner/CgiRunnerTest.php b/test/ExerciseRunner/CgiRunnerTest.php index dd5f37b2..2496c053 100644 --- a/test/ExerciseRunner/CgiRunnerTest.php +++ b/test/ExerciseRunner/CgiRunnerTest.php @@ -65,7 +65,7 @@ public function testVerifyThrowsExceptionIfSolutionFailsExecution() ->method('getRequests') ->will($this->returnValue([$request])); - $regex = "/^PHP Code failed to execute\\. Error: \"PHP Parse error: syntax error, unexpected end of file in/"; + $regex = "/^PHP Code failed to execute\\. Error: \\nPHP Parse error: syntax error, unexpected end of file in/"; $this->setExpectedExceptionRegExp(SolutionExecutionException::class, $regex); $this->runner->verify(''); } @@ -167,7 +167,7 @@ public function testVerifyReturnsFailureIfUserSolutionFailsToExecute() $result = iterator_to_array($failure)[0]; $this->assertInstanceOf(Failure::class, $result); - $failureMsg = "/^PHP Code failed to execute. Error: \"PHP Parse error: syntax error, unexpected end of file"; + $failureMsg = "/^PHP Code failed to execute. Error: \\nPHP Parse error: syntax error, unexpected end of file"; $failureMsg .= " in/"; $this->assertRegExp($failureMsg, $result->getReason()); } diff --git a/test/ExerciseRunner/CliRunnerTest.php b/test/ExerciseRunner/CliRunnerTest.php index 203544ae..64e6f64f 100644 --- a/test/ExerciseRunner/CliRunnerTest.php +++ b/test/ExerciseRunner/CliRunnerTest.php @@ -58,7 +58,7 @@ public function testVerifyThrowsExceptionIfSolutionFailsExecution() ->method('getArgs') ->will($this->returnValue([])); - $regex = "/^PHP Code failed to execute\\. Error: \"PHP Parse error: syntax error, unexpected end of file"; + $regex = "/^PHP Code failed to execute\\. Error: \\nPHP Parse error: syntax error, unexpected end of file"; $regex .= ", expecting ',' or ';'/"; $this->setExpectedExceptionRegExp(SolutionExecutionException::class, $regex); $this->runner->verify(''); @@ -98,7 +98,7 @@ public function testVerifyReturnsFailureIfUserSolutionFailsToExecute() $failure = $this->runner->verify(__DIR__ . '/../res/cli/user-error.php'); - $failureMsg = "/^PHP Code failed to execute. Error: \"PHP Parse error: syntax error, "; + $failureMsg = "/^PHP Code failed to execute. Error: \\nPHP Parse error: syntax error, "; $failureMsg .= "unexpected end of file, expecting ',' or ';'/"; $this->assertInstanceOf(Failure::class, $failure); @@ -155,7 +155,7 @@ public function testRunPassesOutputAndReturnsFailureIfScriptFails() ->method('getArgs') ->will($this->returnValue([1, 2, 3])); - $this->expectOutputRegex('/PHP Parse error: syntax error, unexpected end of file, expecting \',\' or \';\' /'); + $this->expectOutputRegex("/PHP Parse error: \\nsyntax error, unexpected end of file, expecting ',' or ';' /"); $success = $this->runner->run(__DIR__ . '/../res/cli/user-error.php', $output); $this->assertFalse($success); From f892657972abeac5cb195c817b27d964cc8aee6d Mon Sep 17 00:00:00 2001 From: Chris C Date: Mon, 30 May 2016 12:29:57 -0500 Subject: [PATCH 6/8] With separation, we might only need to call this once. It's only being called once. --- test/Exception/CodeExecutionExceptionTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/Exception/CodeExecutionExceptionTest.php b/test/Exception/CodeExecutionExceptionTest.php index ca1aa332..3ba7d1bd 100644 --- a/test/Exception/CodeExecutionExceptionTest.php +++ b/test/Exception/CodeExecutionExceptionTest.php @@ -26,7 +26,7 @@ public function testFromProcessUsesErrorOutputIfNotEmpty() ->getMock(); $process - ->expects($this->exactly(2)) + ->expects($this->exactly(1)) ->method('getErrorOutput') ->will($this->returnValue('Error Output')); From 3a03c3dea6f7550c3d612e1a3e1c09e747f659fa Mon Sep 17 00:00:00 2001 From: Chris C Date: Mon, 30 May 2016 12:39:48 -0500 Subject: [PATCH 7/8] This was not something we were throwing, it's straight from php, so no linebreak. --- test/ExerciseRunner/CliRunnerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ExerciseRunner/CliRunnerTest.php b/test/ExerciseRunner/CliRunnerTest.php index 64e6f64f..953d382e 100644 --- a/test/ExerciseRunner/CliRunnerTest.php +++ b/test/ExerciseRunner/CliRunnerTest.php @@ -155,7 +155,7 @@ public function testRunPassesOutputAndReturnsFailureIfScriptFails() ->method('getArgs') ->will($this->returnValue([1, 2, 3])); - $this->expectOutputRegex("/PHP Parse error: \\nsyntax error, unexpected end of file, expecting ',' or ';' /"); + $this->expectOutputRegex("/PHP Parse error: syntax error, unexpected end of file, expecting ',' or ';' /"); $success = $this->runner->run(__DIR__ . '/../res/cli/user-error.php', $output); $this->assertFalse($success); From c2397abbc52407812c823ba46d8b8255069ebecd Mon Sep 17 00:00:00 2001 From: Chris C Date: Mon, 30 May 2016 12:48:29 -0500 Subject: [PATCH 8/8] need to install php-cs-fixer, so i can run it before every commit. --- test/ExerciseRunner/CgiRunnerTest.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/ExerciseRunner/CgiRunnerTest.php b/test/ExerciseRunner/CgiRunnerTest.php index 2496c053..0b529f88 100644 --- a/test/ExerciseRunner/CgiRunnerTest.php +++ b/test/ExerciseRunner/CgiRunnerTest.php @@ -65,7 +65,8 @@ public function testVerifyThrowsExceptionIfSolutionFailsExecution() ->method('getRequests') ->will($this->returnValue([$request])); - $regex = "/^PHP Code failed to execute\\. Error: \\nPHP Parse error: syntax error, unexpected end of file in/"; + $regex = + "/^PHP Code failed to execute\\. Error: \\nPHP Parse error: syntax error, unexpected end of file in/"; $this->setExpectedExceptionRegExp(SolutionExecutionException::class, $regex); $this->runner->verify(''); }