comparison vendor/psy/psysh/test/Psy/Test/ShellTest.php @ 0:4c8ae668cc8c

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