Chris@0: Chris@0: * Chris@0: * For the full copyright and license information, please view the LICENSE Chris@0: * file that was distributed with this source code. Chris@0: */ Chris@0: Chris@0: namespace Symfony\Component\Console\Tester; Chris@0: Chris@0: use Symfony\Component\Console\Application; Chris@0: use Symfony\Component\Console\Input\ArrayInput; Chris@0: use Symfony\Component\Console\Input\InputInterface; Chris@0: use Symfony\Component\Console\Output\ConsoleOutput; Chris@0: use Symfony\Component\Console\Output\OutputInterface; Chris@0: use Symfony\Component\Console\Output\StreamOutput; Chris@0: Chris@0: /** Chris@0: * Eases the testing of console applications. Chris@0: * Chris@0: * When testing an application, don't forget to disable the auto exit flag: Chris@0: * Chris@0: * $application = new Application(); Chris@0: * $application->setAutoExit(false); Chris@0: * Chris@0: * @author Fabien Potencier Chris@0: */ Chris@0: class ApplicationTester Chris@0: { Chris@0: private $application; Chris@0: private $input; Chris@0: private $statusCode; Chris@0: /** Chris@0: * @var OutputInterface Chris@0: */ Chris@0: private $output; Chris@0: private $captureStreamsIndependently = false; Chris@0: Chris@0: public function __construct(Application $application) Chris@0: { Chris@0: $this->application = $application; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Executes the application. Chris@0: * Chris@0: * Available options: Chris@0: * Chris@0: * * interactive: Sets the input interactive flag Chris@0: * * decorated: Sets the output decorated flag Chris@0: * * verbosity: Sets the output verbosity flag Chris@0: * * capture_stderr_separately: Make output of stdOut and stdErr separately available Chris@0: * Chris@0: * @param array $input An array of arguments and options Chris@0: * @param array $options An array of options Chris@0: * Chris@0: * @return int The command exit code Chris@0: */ Chris@17: public function run(array $input, $options = []) Chris@0: { Chris@0: $this->input = new ArrayInput($input); Chris@0: if (isset($options['interactive'])) { Chris@0: $this->input->setInteractive($options['interactive']); Chris@0: } Chris@0: Chris@18: $this->captureStreamsIndependently = \array_key_exists('capture_stderr_separately', $options) && $options['capture_stderr_separately']; Chris@0: if (!$this->captureStreamsIndependently) { Chris@0: $this->output = new StreamOutput(fopen('php://memory', 'w', false)); Chris@0: if (isset($options['decorated'])) { Chris@0: $this->output->setDecorated($options['decorated']); Chris@0: } Chris@0: if (isset($options['verbosity'])) { Chris@0: $this->output->setVerbosity($options['verbosity']); Chris@0: } Chris@0: } else { Chris@0: $this->output = new ConsoleOutput( Chris@0: isset($options['verbosity']) ? $options['verbosity'] : ConsoleOutput::VERBOSITY_NORMAL, Chris@0: isset($options['decorated']) ? $options['decorated'] : null Chris@0: ); Chris@0: Chris@0: $errorOutput = new StreamOutput(fopen('php://memory', 'w', false)); Chris@0: $errorOutput->setFormatter($this->output->getFormatter()); Chris@0: $errorOutput->setVerbosity($this->output->getVerbosity()); Chris@0: $errorOutput->setDecorated($this->output->isDecorated()); Chris@0: Chris@0: $reflectedOutput = new \ReflectionObject($this->output); Chris@0: $strErrProperty = $reflectedOutput->getProperty('stderr'); Chris@0: $strErrProperty->setAccessible(true); Chris@0: $strErrProperty->setValue($this->output, $errorOutput); Chris@0: Chris@0: $reflectedParent = $reflectedOutput->getParentClass(); Chris@0: $streamProperty = $reflectedParent->getProperty('stream'); Chris@0: $streamProperty->setAccessible(true); Chris@0: $streamProperty->setValue($this->output, fopen('php://memory', 'w', false)); Chris@0: } Chris@0: Chris@0: return $this->statusCode = $this->application->run($this->input, $this->output); Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the display returned by the last execution of the application. Chris@0: * Chris@0: * @param bool $normalize Whether to normalize end of lines to \n or not Chris@0: * Chris@0: * @return string The display Chris@0: */ Chris@0: public function getDisplay($normalize = false) Chris@0: { Chris@0: rewind($this->output->getStream()); Chris@0: Chris@0: $display = stream_get_contents($this->output->getStream()); Chris@0: Chris@0: if ($normalize) { Chris@0: $display = str_replace(PHP_EOL, "\n", $display); Chris@0: } Chris@0: Chris@0: return $display; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the output written to STDERR by the application. Chris@0: * Chris@0: * @param bool $normalize Whether to normalize end of lines to \n or not Chris@0: * Chris@0: * @return string Chris@0: */ Chris@0: public function getErrorOutput($normalize = false) Chris@0: { Chris@0: if (!$this->captureStreamsIndependently) { Chris@0: throw new \LogicException('The error output is not available when the tester is run without "capture_stderr_separately" option set.'); Chris@0: } Chris@0: Chris@0: rewind($this->output->getErrorOutput()->getStream()); Chris@0: Chris@0: $display = stream_get_contents($this->output->getErrorOutput()->getStream()); Chris@0: Chris@0: if ($normalize) { Chris@0: $display = str_replace(PHP_EOL, "\n", $display); Chris@0: } Chris@0: Chris@0: return $display; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the input instance used by the last execution of the application. Chris@0: * Chris@0: * @return InputInterface The current input instance Chris@0: */ Chris@0: public function getInput() Chris@0: { Chris@0: return $this->input; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the output instance used by the last execution of the application. Chris@0: * Chris@0: * @return OutputInterface The current output instance Chris@0: */ Chris@0: public function getOutput() Chris@0: { Chris@0: return $this->output; Chris@0: } Chris@0: Chris@0: /** Chris@0: * Gets the status code returned by the last execution of the application. Chris@0: * Chris@0: * @return int The status code Chris@0: */ Chris@0: public function getStatusCode() Chris@0: { Chris@0: return $this->statusCode; Chris@0: } Chris@0: }