annotate vendor/psy/psysh/test/Psy/Test/ShellTest.php @ 8:50b0d041100e

Further files for download
author Chris Cannam
date Mon, 05 Feb 2018 10:56:40 +0000
parents 4c8ae668cc8c
children 7a779792577d
rev   line source
Chris@0 1 <?php
Chris@0 2
Chris@0 3 /*
Chris@0 4 * This file is part of Psy Shell.
Chris@0 5 *
Chris@0 6 * (c) 2012-2017 Justin Hileman
Chris@0 7 *
Chris@0 8 * For the full copyright and license information, please view the LICENSE
Chris@0 9 * file that was distributed with this source code.
Chris@0 10 */
Chris@0 11
Chris@0 12 namespace Psy\Test;
Chris@0 13
Chris@0 14 use Psy\Configuration;
Chris@0 15 use Psy\Exception\ErrorException;
Chris@0 16 use Psy\Exception\ParseErrorException;
Chris@0 17 use Psy\Shell;
Chris@0 18 use Psy\TabCompletion\Matcher\ClassMethodsMatcher;
Chris@0 19 use Symfony\Component\Console\Output\StreamOutput;
Chris@0 20
Chris@0 21 class ShellTest extends \PHPUnit\Framework\TestCase
Chris@0 22 {
Chris@0 23 private $streams = array();
Chris@0 24
Chris@0 25 public function tearDown()
Chris@0 26 {
Chris@0 27 foreach ($this->streams as $stream) {
Chris@0 28 fclose($stream);
Chris@0 29 }
Chris@0 30 }
Chris@0 31
Chris@0 32 public function testScopeVariables()
Chris@0 33 {
Chris@0 34 $one = 'banana';
Chris@0 35 $two = 123;
Chris@0 36 $three = new \StdClass();
Chris@0 37 $__psysh__ = 'ignore this';
Chris@0 38 $_ = 'ignore this';
Chris@0 39 $_e = 'ignore this';
Chris@0 40
Chris@0 41 $shell = new Shell($this->getConfig());
Chris@0 42 $shell->setScopeVariables(compact('one', 'two', 'three', '__psysh__', '_', '_e', 'this'));
Chris@0 43
Chris@0 44 $this->assertNotContains('__psysh__', $shell->getScopeVariableNames());
Chris@0 45 $this->assertEquals(array('one', 'two', 'three', '_'), $shell->getScopeVariableNames());
Chris@0 46 $this->assertEquals('banana', $shell->getScopeVariable('one'));
Chris@0 47 $this->assertEquals(123, $shell->getScopeVariable('two'));
Chris@0 48 $this->assertSame($three, $shell->getScopeVariable('three'));
Chris@0 49 $this->assertNull($shell->getScopeVariable('_'));
Chris@0 50
Chris@0 51 $shell->setScopeVariables(array());
Chris@0 52 $this->assertEquals(array('_'), $shell->getScopeVariableNames());
Chris@0 53
Chris@0 54 $shell->setBoundObject($this);
Chris@0 55 $this->assertEquals(array('_', 'this'), $shell->getScopeVariableNames());
Chris@0 56 $this->assertSame($this, $shell->getScopeVariable('this'));
Chris@0 57 $this->assertEquals(array('_' => null), $shell->getScopeVariables(false));
Chris@0 58 $this->assertEquals(array('_' => null, 'this' => $this), $shell->getScopeVariables());
Chris@0 59 }
Chris@0 60
Chris@0 61 /**
Chris@0 62 * @expectedException \InvalidArgumentException
Chris@0 63 */
Chris@0 64 public function testUnknownScopeVariablesThrowExceptions()
Chris@0 65 {
Chris@0 66 $shell = new Shell($this->getConfig());
Chris@0 67 $shell->setScopeVariables(array('foo' => 'FOO', 'bar' => 1));
Chris@0 68 $shell->getScopeVariable('baz');
Chris@0 69 }
Chris@0 70
Chris@0 71 public function testIncludes()
Chris@0 72 {
Chris@0 73 $config = $this->getConfig(array('configFile' => __DIR__ . '/../../fixtures/empty.php'));
Chris@0 74
Chris@0 75 $shell = new Shell($config);
Chris@0 76 $this->assertEmpty($shell->getIncludes());
Chris@0 77 $shell->setIncludes(array('foo', 'bar', 'baz'));
Chris@0 78 $this->assertEquals(array('foo', 'bar', 'baz'), $shell->getIncludes());
Chris@0 79 }
Chris@0 80
Chris@0 81 public function testIncludesConfig()
Chris@0 82 {
Chris@0 83 $config = $this->getConfig(array(
Chris@0 84 'defaultIncludes' => array('/file.php'),
Chris@0 85 'configFile' => __DIR__ . '/../../fixtures/empty.php',
Chris@0 86 ));
Chris@0 87
Chris@0 88 $shell = new Shell($config);
Chris@0 89
Chris@0 90 $includes = $shell->getIncludes();
Chris@0 91 $this->assertEquals('/file.php', $includes[0]);
Chris@0 92 }
Chris@0 93
Chris@0 94 public function testAddMatchersViaConfig()
Chris@0 95 {
Chris@0 96 $config = $this->getConfig(array(
Chris@0 97 'tabCompletionMatchers' => array(
Chris@0 98 new ClassMethodsMatcher(),
Chris@0 99 ),
Chris@0 100 ));
Chris@0 101
Chris@0 102 $matchers = $config->getTabCompletionMatchers();
Chris@0 103
Chris@0 104 $this->assertTrue(array_pop($matchers) instanceof ClassMethodsMatcher);
Chris@0 105 }
Chris@0 106
Chris@0 107 public function testRenderingExceptions()
Chris@0 108 {
Chris@0 109 $shell = new Shell($this->getConfig());
Chris@0 110 $output = $this->getOutput();
Chris@0 111 $stream = $output->getStream();
Chris@0 112 $e = new ParseErrorException('message', 13);
Chris@0 113
Chris@0 114 $shell->setOutput($output);
Chris@0 115 $shell->addCode('code');
Chris@0 116 $this->assertTrue($shell->hasCode());
Chris@0 117 $this->assertNotEmpty($shell->getCodeBuffer());
Chris@0 118
Chris@0 119 $shell->writeException($e);
Chris@0 120
Chris@0 121 $this->assertSame($e, $shell->getScopeVariable('_e'));
Chris@0 122 $this->assertFalse($shell->hasCode());
Chris@0 123 $this->assertEmpty($shell->getCodeBuffer());
Chris@0 124
Chris@0 125 rewind($stream);
Chris@0 126 $streamContents = stream_get_contents($stream);
Chris@0 127
Chris@0 128 $this->assertContains('PHP Parse error', $streamContents);
Chris@0 129 $this->assertContains('message', $streamContents);
Chris@0 130 $this->assertContains('line 13', $streamContents);
Chris@0 131 }
Chris@0 132
Chris@0 133 public function testHandlingErrors()
Chris@0 134 {
Chris@0 135 $shell = new Shell($this->getConfig());
Chris@0 136 $output = $this->getOutput();
Chris@0 137 $stream = $output->getStream();
Chris@0 138 $shell->setOutput($output);
Chris@0 139
Chris@0 140 $oldLevel = error_reporting();
Chris@0 141 error_reporting($oldLevel & ~E_USER_NOTICE);
Chris@0 142
Chris@0 143 try {
Chris@0 144 $shell->handleError(E_USER_NOTICE, 'wheee', null, 13);
Chris@0 145 } catch (ErrorException $e) {
Chris@0 146 error_reporting($oldLevel);
Chris@0 147 $this->fail('Unexpected error exception');
Chris@0 148 }
Chris@0 149 error_reporting($oldLevel);
Chris@0 150
Chris@0 151 rewind($stream);
Chris@0 152 $streamContents = stream_get_contents($stream);
Chris@0 153
Chris@0 154 $this->assertContains('PHP Notice:', $streamContents);
Chris@0 155 $this->assertContains('wheee', $streamContents);
Chris@0 156 $this->assertContains('line 13', $streamContents);
Chris@0 157 }
Chris@0 158
Chris@0 159 /**
Chris@0 160 * @expectedException \Psy\Exception\ErrorException
Chris@0 161 */
Chris@0 162 public function testNotHandlingErrors()
Chris@0 163 {
Chris@0 164 $shell = new Shell($this->getConfig());
Chris@0 165 $oldLevel = error_reporting();
Chris@0 166 error_reporting($oldLevel | E_USER_NOTICE);
Chris@0 167
Chris@0 168 try {
Chris@0 169 $shell->handleError(E_USER_NOTICE, 'wheee', null, 13);
Chris@0 170 } catch (ErrorException $e) {
Chris@0 171 error_reporting($oldLevel);
Chris@0 172 throw $e;
Chris@0 173 }
Chris@0 174 }
Chris@0 175
Chris@0 176 public function testVersion()
Chris@0 177 {
Chris@0 178 $shell = new Shell($this->getConfig());
Chris@0 179
Chris@0 180 $this->assertInstanceOf('Symfony\Component\Console\Application', $shell);
Chris@0 181 $this->assertContains(Shell::VERSION, $shell->getVersion());
Chris@0 182 $this->assertContains(phpversion(), $shell->getVersion());
Chris@0 183 $this->assertContains(php_sapi_name(), $shell->getVersion());
Chris@0 184 }
Chris@0 185
Chris@0 186 public function testCodeBuffer()
Chris@0 187 {
Chris@0 188 $shell = new Shell($this->getConfig());
Chris@0 189
Chris@0 190 $shell->addCode('class');
Chris@0 191 $this->assertNull($shell->flushCode());
Chris@0 192 $this->assertTrue($shell->hasCode());
Chris@0 193
Chris@0 194 $shell->addCode('a');
Chris@0 195 $this->assertNull($shell->flushCode());
Chris@0 196 $this->assertTrue($shell->hasCode());
Chris@0 197
Chris@0 198 $shell->addCode('{}');
Chris@0 199 $code = $shell->flushCode();
Chris@0 200 $this->assertFalse($shell->hasCode());
Chris@0 201 $code = preg_replace('/\s+/', ' ', $code);
Chris@0 202 $this->assertNotNull($code);
Chris@0 203 $this->assertEquals('class a { } return new \\Psy\\CodeCleaner\\NoReturnValue();', $code);
Chris@0 204 }
Chris@0 205
Chris@0 206 public function testKeepCodeBufferOpen()
Chris@0 207 {
Chris@0 208 $shell = new Shell($this->getConfig());
Chris@0 209
Chris@0 210 $shell->addCode('1 \\');
Chris@0 211 $this->assertNull($shell->flushCode());
Chris@0 212 $this->assertTrue($shell->hasCode());
Chris@0 213
Chris@0 214 $shell->addCode('+ 1 \\');
Chris@0 215 $this->assertNull($shell->flushCode());
Chris@0 216 $this->assertTrue($shell->hasCode());
Chris@0 217
Chris@0 218 $shell->addCode('+ 1');
Chris@0 219 $code = $shell->flushCode();
Chris@0 220 $this->assertFalse($shell->hasCode());
Chris@0 221 $code = preg_replace('/\s+/', ' ', $code);
Chris@0 222 $this->assertNotNull($code);
Chris@0 223 $this->assertEquals('return 1 + 1 + 1;', $code);
Chris@0 224 }
Chris@0 225
Chris@0 226 /**
Chris@0 227 * @expectedException \Psy\Exception\ParseErrorException
Chris@0 228 */
Chris@0 229 public function testCodeBufferThrowsParseExceptions()
Chris@0 230 {
Chris@0 231 $shell = new Shell($this->getConfig());
Chris@0 232 $shell->addCode('this is not valid');
Chris@0 233 $shell->flushCode();
Chris@0 234 }
Chris@0 235
Chris@0 236 public function testClosuresSupport()
Chris@0 237 {
Chris@0 238 $shell = new Shell($this->getConfig());
Chris@0 239 $code = '$test = function () {}';
Chris@0 240 $shell->addCode($code);
Chris@0 241 $shell->flushCode();
Chris@0 242 $code = '$test()';
Chris@0 243 $shell->addCode($code);
Chris@0 244 $shell->flushCode();
Chris@0 245 }
Chris@0 246
Chris@0 247 public function testWriteStdout()
Chris@0 248 {
Chris@0 249 $output = $this->getOutput();
Chris@0 250 $stream = $output->getStream();
Chris@0 251 $shell = new Shell($this->getConfig());
Chris@0 252 $shell->setOutput($output);
Chris@0 253
Chris@0 254 $shell->writeStdout("{{stdout}}\n");
Chris@0 255
Chris@0 256 rewind($stream);
Chris@0 257 $streamContents = stream_get_contents($stream);
Chris@0 258
Chris@0 259 $this->assertEquals('{{stdout}}' . PHP_EOL, $streamContents);
Chris@0 260 }
Chris@0 261
Chris@0 262 public function testWriteStdoutWithoutNewline()
Chris@0 263 {
Chris@0 264 $output = $this->getOutput();
Chris@0 265 $stream = $output->getStream();
Chris@0 266 $shell = new Shell($this->getConfig());
Chris@0 267 $shell->setOutput($output);
Chris@0 268
Chris@0 269 $shell->writeStdout('{{stdout}}');
Chris@0 270
Chris@0 271 rewind($stream);
Chris@0 272 $streamContents = stream_get_contents($stream);
Chris@0 273
Chris@0 274 $this->assertEquals('{{stdout}}<aside>⏎</aside>' . PHP_EOL, $streamContents);
Chris@0 275 }
Chris@0 276
Chris@0 277 /**
Chris@0 278 * @dataProvider getReturnValues
Chris@0 279 */
Chris@0 280 public function testWriteReturnValue($input, $expected)
Chris@0 281 {
Chris@0 282 $output = $this->getOutput();
Chris@0 283 $stream = $output->getStream();
Chris@0 284 $shell = new Shell($this->getConfig());
Chris@0 285 $shell->setOutput($output);
Chris@0 286
Chris@0 287 $shell->writeReturnValue($input);
Chris@0 288 rewind($stream);
Chris@0 289 $this->assertEquals($expected, stream_get_contents($stream));
Chris@0 290 }
Chris@0 291
Chris@0 292 public function getReturnValues()
Chris@0 293 {
Chris@0 294 return array(
Chris@0 295 array('{{return value}}', "=> \"\033[32m{{return value}}\033[39m\"" . PHP_EOL),
Chris@0 296 array(1, "=> \033[35m1\033[39m" . PHP_EOL),
Chris@0 297 );
Chris@0 298 }
Chris@0 299
Chris@0 300 /**
Chris@0 301 * @dataProvider getRenderedExceptions
Chris@0 302 */
Chris@0 303 public function testWriteException($exception, $expected)
Chris@0 304 {
Chris@0 305 $output = $this->getOutput();
Chris@0 306 $stream = $output->getStream();
Chris@0 307 $shell = new Shell($this->getConfig());
Chris@0 308 $shell->setOutput($output);
Chris@0 309
Chris@0 310 $shell->writeException($exception);
Chris@0 311 rewind($stream);
Chris@0 312 $this->assertEquals($expected, stream_get_contents($stream));
Chris@0 313 }
Chris@0 314
Chris@0 315 public function getRenderedExceptions()
Chris@0 316 {
Chris@0 317 return array(
Chris@0 318 array(new \Exception('{{message}}'), "Exception with message '{{message}}'" . PHP_EOL),
Chris@0 319 );
Chris@0 320 }
Chris@0 321
Chris@0 322 private function getOutput()
Chris@0 323 {
Chris@0 324 $stream = fopen('php://memory', 'w+');
Chris@0 325 $this->streams[] = $stream;
Chris@0 326
Chris@0 327 $output = new StreamOutput($stream, StreamOutput::VERBOSITY_NORMAL, false);
Chris@0 328
Chris@0 329 return $output;
Chris@0 330 }
Chris@0 331
Chris@0 332 private function getConfig(array $config = array())
Chris@0 333 {
Chris@0 334 // Mebbe there's a better way than this?
Chris@0 335 $dir = tempnam(sys_get_temp_dir(), 'psysh_shell_test_');
Chris@0 336 unlink($dir);
Chris@0 337
Chris@0 338 $defaults = array(
Chris@0 339 'configDir' => $dir,
Chris@0 340 'dataDir' => $dir,
Chris@0 341 'runtimeDir' => $dir,
Chris@0 342 );
Chris@0 343
Chris@0 344 return new Configuration(array_merge($defaults, $config));
Chris@0 345 }
Chris@0 346 }