Mercurial > hg > isophonics-drupal-site
comparison vendor/phpspec/prophecy/tests/Doubler/Generator/ClassMirrorTest.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 | |
3 namespace Tests\Prophecy\Doubler\Generator; | |
4 | |
5 use Prophecy\Doubler\Generator\ClassMirror; | |
6 | |
7 class ClassMirrorTest extends \PHPUnit_Framework_TestCase | |
8 { | |
9 /** | |
10 * @test | |
11 */ | |
12 public function it_reflects_allowed_magic_methods() | |
13 { | |
14 $class = new \ReflectionClass('Fixtures\Prophecy\SpecialMethods'); | |
15 | |
16 $mirror = new ClassMirror(); | |
17 | |
18 $node = $mirror->reflect($class, array()); | |
19 | |
20 $this->assertCount(7, $node->getMethods()); | |
21 } | |
22 | |
23 /** | |
24 * @test | |
25 */ | |
26 public function it_reflects_protected_abstract_methods() | |
27 { | |
28 $class = new \ReflectionClass('Fixtures\Prophecy\WithProtectedAbstractMethod'); | |
29 | |
30 $mirror = new ClassMirror(); | |
31 | |
32 $classNode = $mirror->reflect($class, array()); | |
33 | |
34 $this->assertEquals('Fixtures\Prophecy\WithProtectedAbstractMethod', $classNode->getParentClass()); | |
35 | |
36 $methodNodes = $classNode->getMethods(); | |
37 $this->assertCount(1, $methodNodes); | |
38 | |
39 $this->assertEquals('protected', $methodNodes['innerDetail']->getVisibility()); | |
40 } | |
41 | |
42 /** | |
43 * @test | |
44 */ | |
45 public function it_reflects_public_static_methods() | |
46 { | |
47 $class = new \ReflectionClass('Fixtures\Prophecy\WithStaticMethod'); | |
48 | |
49 $mirror = new ClassMirror(); | |
50 | |
51 $classNode = $mirror->reflect($class, array()); | |
52 | |
53 $this->assertEquals('Fixtures\Prophecy\WithStaticMethod', $classNode->getParentClass()); | |
54 | |
55 $methodNodes = $classNode->getMethods(); | |
56 $this->assertCount(1, $methodNodes); | |
57 | |
58 $this->assertTrue($methodNodes['innerDetail']->isStatic()); | |
59 } | |
60 | |
61 /** | |
62 * @test | |
63 */ | |
64 public function it_marks_required_args_without_types_as_not_optional() | |
65 { | |
66 $class = new \ReflectionClass('Fixtures\Prophecy\WithArguments'); | |
67 | |
68 $mirror = new ClassMirror(); | |
69 | |
70 $classNode = $mirror->reflect($class, array()); | |
71 $methodNode = $classNode->getMethod('methodWithoutTypeHints'); | |
72 $argNodes = $methodNode->getArguments(); | |
73 | |
74 $this->assertCount(1, $argNodes); | |
75 | |
76 $this->assertEquals('arg', $argNodes[0]->getName()); | |
77 $this->assertNull($argNodes[0]->getTypeHint()); | |
78 $this->assertFalse($argNodes[0]->isOptional()); | |
79 $this->assertNull($argNodes[0]->getDefault()); | |
80 $this->assertFalse($argNodes[0]->isPassedByReference()); | |
81 $this->assertFalse($argNodes[0]->isVariadic()); | |
82 } | |
83 | |
84 /** | |
85 * @test | |
86 */ | |
87 public function it_properly_reads_methods_arguments_with_types() | |
88 { | |
89 $class = new \ReflectionClass('Fixtures\Prophecy\WithArguments'); | |
90 | |
91 $mirror = new ClassMirror(); | |
92 | |
93 $classNode = $mirror->reflect($class, array()); | |
94 $methodNode = $classNode->getMethod('methodWithArgs'); | |
95 $argNodes = $methodNode->getArguments(); | |
96 | |
97 $this->assertCount(3, $argNodes); | |
98 | |
99 $this->assertEquals('arg_1', $argNodes[0]->getName()); | |
100 $this->assertEquals('array', $argNodes[0]->getTypeHint()); | |
101 $this->assertTrue($argNodes[0]->isOptional()); | |
102 $this->assertEquals(array(), $argNodes[0]->getDefault()); | |
103 $this->assertFalse($argNodes[0]->isPassedByReference()); | |
104 $this->assertFalse($argNodes[0]->isVariadic()); | |
105 | |
106 $this->assertEquals('arg_2', $argNodes[1]->getName()); | |
107 $this->assertEquals('ArrayAccess', $argNodes[1]->getTypeHint()); | |
108 $this->assertFalse($argNodes[1]->isOptional()); | |
109 | |
110 $this->assertEquals('arg_3', $argNodes[2]->getName()); | |
111 $this->assertEquals('ArrayAccess', $argNodes[2]->getTypeHint()); | |
112 $this->assertTrue($argNodes[2]->isOptional()); | |
113 $this->assertNull($argNodes[2]->getDefault()); | |
114 $this->assertFalse($argNodes[2]->isPassedByReference()); | |
115 $this->assertFalse($argNodes[2]->isVariadic()); | |
116 } | |
117 | |
118 /** | |
119 * @test | |
120 * @requires PHP 5.4 | |
121 */ | |
122 public function it_properly_reads_methods_arguments_with_callable_types() | |
123 { | |
124 $class = new \ReflectionClass('Fixtures\Prophecy\WithCallableArgument'); | |
125 | |
126 $mirror = new ClassMirror(); | |
127 | |
128 $classNode = $mirror->reflect($class, array()); | |
129 $methodNode = $classNode->getMethod('methodWithArgs'); | |
130 $argNodes = $methodNode->getArguments(); | |
131 | |
132 $this->assertCount(2, $argNodes); | |
133 | |
134 $this->assertEquals('arg_1', $argNodes[0]->getName()); | |
135 $this->assertEquals('callable', $argNodes[0]->getTypeHint()); | |
136 $this->assertFalse($argNodes[0]->isOptional()); | |
137 $this->assertFalse($argNodes[0]->isPassedByReference()); | |
138 $this->assertFalse($argNodes[0]->isVariadic()); | |
139 | |
140 $this->assertEquals('arg_2', $argNodes[1]->getName()); | |
141 $this->assertEquals('callable', $argNodes[1]->getTypeHint()); | |
142 $this->assertTrue($argNodes[1]->isOptional()); | |
143 $this->assertNull($argNodes[1]->getDefault()); | |
144 $this->assertFalse($argNodes[1]->isPassedByReference()); | |
145 $this->assertFalse($argNodes[1]->isVariadic()); | |
146 } | |
147 | |
148 /** | |
149 * @test | |
150 * @requires PHP 5.6 | |
151 */ | |
152 public function it_properly_reads_methods_variadic_arguments() | |
153 { | |
154 $class = new \ReflectionClass('Fixtures\Prophecy\WithVariadicArgument'); | |
155 | |
156 $mirror = new ClassMirror(); | |
157 | |
158 $classNode = $mirror->reflect($class, array()); | |
159 $methodNode = $classNode->getMethod('methodWithArgs'); | |
160 $argNodes = $methodNode->getArguments(); | |
161 | |
162 $this->assertCount(1, $argNodes); | |
163 | |
164 $this->assertEquals('args', $argNodes[0]->getName()); | |
165 $this->assertNull($argNodes[0]->getTypeHint()); | |
166 $this->assertFalse($argNodes[0]->isOptional()); | |
167 $this->assertFalse($argNodes[0]->isPassedByReference()); | |
168 $this->assertTrue($argNodes[0]->isVariadic()); | |
169 } | |
170 | |
171 /** | |
172 * @test | |
173 * @requires PHP 5.6 | |
174 */ | |
175 public function it_properly_reads_methods_typehinted_variadic_arguments() | |
176 { | |
177 if (defined('HHVM_VERSION_ID')) { | |
178 $this->markTestSkipped('HHVM does not support typehints on variadic arguments.'); | |
179 } | |
180 | |
181 $class = new \ReflectionClass('Fixtures\Prophecy\WithTypehintedVariadicArgument'); | |
182 | |
183 $mirror = new ClassMirror(); | |
184 | |
185 $classNode = $mirror->reflect($class, array()); | |
186 $methodNode = $classNode->getMethod('methodWithTypeHintedArgs'); | |
187 $argNodes = $methodNode->getArguments(); | |
188 | |
189 $this->assertCount(1, $argNodes); | |
190 | |
191 $this->assertEquals('args', $argNodes[0]->getName()); | |
192 $this->assertEquals('array', $argNodes[0]->getTypeHint()); | |
193 $this->assertFalse($argNodes[0]->isOptional()); | |
194 $this->assertFalse($argNodes[0]->isPassedByReference()); | |
195 $this->assertTrue($argNodes[0]->isVariadic()); | |
196 } | |
197 | |
198 /** | |
199 * @test | |
200 */ | |
201 public function it_marks_passed_by_reference_args_as_passed_by_reference() | |
202 { | |
203 $class = new \ReflectionClass('Fixtures\Prophecy\WithReferences'); | |
204 | |
205 $mirror = new ClassMirror(); | |
206 | |
207 $classNode = $mirror->reflect($class, array()); | |
208 | |
209 $this->assertTrue($classNode->hasMethod('methodWithReferenceArgument')); | |
210 | |
211 $argNodes = $classNode->getMethod('methodWithReferenceArgument')->getArguments(); | |
212 | |
213 $this->assertCount(2, $argNodes); | |
214 | |
215 $this->assertTrue($argNodes[0]->isPassedByReference()); | |
216 $this->assertTrue($argNodes[1]->isPassedByReference()); | |
217 } | |
218 | |
219 /** | |
220 * @test | |
221 */ | |
222 public function it_throws_an_exception_if_class_is_final() | |
223 { | |
224 $class = new \ReflectionClass('Fixtures\Prophecy\FinalClass'); | |
225 | |
226 $mirror = new ClassMirror(); | |
227 | |
228 $this->setExpectedException('Prophecy\Exception\Doubler\ClassMirrorException'); | |
229 | |
230 $mirror->reflect($class, array()); | |
231 } | |
232 | |
233 /** | |
234 * @test | |
235 */ | |
236 public function it_ignores_final_methods() | |
237 { | |
238 $class = new \ReflectionClass('Fixtures\Prophecy\WithFinalMethod'); | |
239 | |
240 $mirror = new ClassMirror(); | |
241 | |
242 $classNode = $mirror->reflect($class, array()); | |
243 | |
244 $this->assertCount(0, $classNode->getMethods()); | |
245 } | |
246 | |
247 /** | |
248 * @test | |
249 */ | |
250 public function it_marks_final_methods_as_unextendable() | |
251 { | |
252 $class = new \ReflectionClass('Fixtures\Prophecy\WithFinalMethod'); | |
253 | |
254 $mirror = new ClassMirror(); | |
255 | |
256 $classNode = $mirror->reflect($class, array()); | |
257 | |
258 $this->assertCount(1, $classNode->getUnextendableMethods()); | |
259 $this->assertFalse($classNode->isExtendable('finalImplementation')); | |
260 } | |
261 | |
262 /** | |
263 * @test | |
264 */ | |
265 public function it_throws_an_exception_if_interface_provided_instead_of_class() | |
266 { | |
267 $class = new \ReflectionClass('Fixtures\Prophecy\EmptyInterface'); | |
268 | |
269 $mirror = new ClassMirror(); | |
270 | |
271 $this->setExpectedException('Prophecy\Exception\InvalidArgumentException'); | |
272 | |
273 $mirror->reflect($class, array()); | |
274 } | |
275 | |
276 /** | |
277 * @test | |
278 */ | |
279 public function it_reflects_all_interfaces_methods() | |
280 { | |
281 $mirror = new ClassMirror(); | |
282 | |
283 $classNode = $mirror->reflect(null, array( | |
284 new \ReflectionClass('Fixtures\Prophecy\Named'), | |
285 new \ReflectionClass('Fixtures\Prophecy\ModifierInterface'), | |
286 )); | |
287 | |
288 $this->assertEquals('stdClass', $classNode->getParentClass()); | |
289 $this->assertEquals(array( | |
290 'Prophecy\Doubler\Generator\ReflectionInterface', | |
291 'Fixtures\Prophecy\ModifierInterface', | |
292 'Fixtures\Prophecy\Named', | |
293 ), $classNode->getInterfaces()); | |
294 | |
295 $this->assertCount(3, $classNode->getMethods()); | |
296 $this->assertTrue($classNode->hasMethod('getName')); | |
297 $this->assertTrue($classNode->hasMethod('isAbstract')); | |
298 $this->assertTrue($classNode->hasMethod('getVisibility')); | |
299 } | |
300 | |
301 /** | |
302 * @test | |
303 */ | |
304 public function it_ignores_virtually_private_methods() | |
305 { | |
306 $class = new \ReflectionClass('Fixtures\Prophecy\WithVirtuallyPrivateMethod'); | |
307 | |
308 $mirror = new ClassMirror(); | |
309 | |
310 $classNode = $mirror->reflect($class, array()); | |
311 | |
312 $this->assertCount(2, $classNode->getMethods()); | |
313 $this->assertTrue($classNode->hasMethod('isAbstract')); | |
314 $this->assertTrue($classNode->hasMethod('__toString')); | |
315 $this->assertFalse($classNode->hasMethod('_getName')); | |
316 } | |
317 | |
318 /** | |
319 * @test | |
320 */ | |
321 public function it_does_not_throw_exception_for_virtually_private_finals() | |
322 { | |
323 $class = new \ReflectionClass('Fixtures\Prophecy\WithFinalVirtuallyPrivateMethod'); | |
324 | |
325 $mirror = new ClassMirror(); | |
326 | |
327 $classNode = $mirror->reflect($class, array()); | |
328 | |
329 $this->assertCount(0, $classNode->getMethods()); | |
330 } | |
331 | |
332 /** | |
333 * @test | |
334 * @requires PHP 7 | |
335 */ | |
336 public function it_reflects_return_typehints() | |
337 { | |
338 $class = new \ReflectionClass('Fixtures\Prophecy\WithReturnTypehints'); | |
339 | |
340 $mirror = new ClassMirror(); | |
341 | |
342 $classNode = $mirror->reflect($class, array()); | |
343 | |
344 $this->assertCount(3, $classNode->getMethods()); | |
345 $this->assertTrue($classNode->hasMethod('getName')); | |
346 $this->assertTrue($classNode->hasMethod('getSelf')); | |
347 $this->assertTrue($classNode->hasMethod('getParent')); | |
348 | |
349 $this->assertEquals('string', $classNode->getMethod('getName')->getReturnType()); | |
350 $this->assertEquals('\Fixtures\Prophecy\WithReturnTypehints', $classNode->getMethod('getSelf')->getReturnType()); | |
351 $this->assertEquals('\Fixtures\Prophecy\EmptyClass', $classNode->getMethod('getParent')->getReturnType()); | |
352 } | |
353 | |
354 /** | |
355 * @test | |
356 */ | |
357 public function it_throws_an_exception_if_class_provided_in_interfaces_list() | |
358 { | |
359 $class = new \ReflectionClass('Fixtures\Prophecy\EmptyClass'); | |
360 | |
361 $mirror = new ClassMirror(); | |
362 | |
363 $this->setExpectedException('InvalidArgumentException'); | |
364 | |
365 $mirror->reflect(null, array($class)); | |
366 } | |
367 | |
368 /** | |
369 * @test | |
370 */ | |
371 public function it_throws_an_exception_if_not_reflection_provided_as_interface() | |
372 { | |
373 $mirror = new ClassMirror(); | |
374 | |
375 $this->setExpectedException('InvalidArgumentException'); | |
376 | |
377 $mirror->reflect(null, array(null)); | |
378 } | |
379 | |
380 /** | |
381 * @test | |
382 */ | |
383 public function it_doesnt_use_scalar_typehints() | |
384 { | |
385 $mirror = new ClassMirror(); | |
386 | |
387 $classNode = $mirror->reflect(new \ReflectionClass('ReflectionMethod'), array()); | |
388 $method = $classNode->getMethod('export'); | |
389 $arguments = $method->getArguments(); | |
390 | |
391 $this->assertNull($arguments[0]->getTypeHint()); | |
392 $this->assertNull($arguments[1]->getTypeHint()); | |
393 $this->assertNull($arguments[2]->getTypeHint()); | |
394 } | |
395 | |
396 /** | |
397 * @test | |
398 */ | |
399 public function it_doesnt_fail_to_typehint_nonexistent_FQCN() | |
400 { | |
401 $mirror = new ClassMirror(); | |
402 | |
403 $classNode = $mirror->reflect(new \ReflectionClass('Fixtures\Prophecy\OptionalDepsClass'), array()); | |
404 $method = $classNode->getMethod('iHaveAStrangeTypeHintedArg'); | |
405 $arguments = $method->getArguments(); | |
406 $this->assertEquals('I\Simply\Am\Nonexistent', $arguments[0]->getTypeHint()); | |
407 } | |
408 | |
409 /** | |
410 * @test | |
411 */ | |
412 public function it_doesnt_fail_to_typehint_nonexistent_RQCN() | |
413 { | |
414 $mirror = new ClassMirror(); | |
415 | |
416 $classNode = $mirror->reflect(new \ReflectionClass('Fixtures\Prophecy\OptionalDepsClass'), array()); | |
417 $method = $classNode->getMethod('iHaveAnEvenStrangerTypeHintedArg'); | |
418 $arguments = $method->getArguments(); | |
419 $this->assertEquals('I\Simply\Am\Not', $arguments[0]->getTypeHint()); | |
420 } | |
421 | |
422 /** | |
423 * @test | |
424 */ | |
425 function it_changes_argument_names_if_they_are_varying() | |
426 { | |
427 // Use test doubles in this test, as arguments named ... in the Reflection API can only happen for internal classes | |
428 $class = $this->prophesize('ReflectionClass'); | |
429 $method = $this->prophesize('ReflectionMethod'); | |
430 $parameter = $this->prophesize('ReflectionParameter'); | |
431 | |
432 $class->getName()->willReturn('Custom\ClassName'); | |
433 $class->isInterface()->willReturn(false); | |
434 $class->isFinal()->willReturn(false); | |
435 $class->getMethods(\ReflectionMethod::IS_PUBLIC)->willReturn(array($method)); | |
436 $class->getMethods(\ReflectionMethod::IS_ABSTRACT)->willReturn(array()); | |
437 | |
438 $method->getParameters()->willReturn(array($parameter)); | |
439 $method->getName()->willReturn('methodName'); | |
440 $method->isFinal()->willReturn(false); | |
441 $method->isProtected()->willReturn(false); | |
442 $method->isStatic()->willReturn(false); | |
443 $method->returnsReference()->willReturn(false); | |
444 | |
445 if (version_compare(PHP_VERSION, '7.0', '>=')) { | |
446 $method->hasReturnType()->willReturn(false); | |
447 } | |
448 | |
449 $parameter->getName()->willReturn('...'); | |
450 $parameter->isDefaultValueAvailable()->willReturn(true); | |
451 $parameter->getDefaultValue()->willReturn(null); | |
452 $parameter->isPassedByReference()->willReturn(false); | |
453 $parameter->getClass()->willReturn($class); | |
454 if (version_compare(PHP_VERSION, '5.6', '>=')) { | |
455 $parameter->isVariadic()->willReturn(false); | |
456 } | |
457 | |
458 $mirror = new ClassMirror(); | |
459 | |
460 $classNode = $mirror->reflect($class->reveal(), array()); | |
461 | |
462 $methodNodes = $classNode->getMethods(); | |
463 | |
464 $argumentNodes = $methodNodes['methodName']->getArguments(); | |
465 $argumentNode = $argumentNodes[0]; | |
466 | |
467 $this->assertEquals('__dot_dot_dot__', $argumentNode->getName()); | |
468 } | |
469 } |