1<?php
2
3/*
4 * This file is part of the Symfony package.
5 *
6 * (c) Fabien Potencier <fabien@symfony.com>
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Symfony\Component\VarDumper\Tests\Caster;
13
14use PHPUnit\Framework\TestCase;
15use Symfony\Component\VarDumper\Caster\Caster;
16use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
17use Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo;
18use Symfony\Component\VarDumper\Tests\Fixtures\NotLoadableClass;
19
20/**
21 * @author Nicolas Grekas <p@tchwork.com>
22 */
23class ReflectionCasterTest extends TestCase
24{
25    use VarDumperTestTrait;
26
27    public function testReflectionCaster()
28    {
29        $var = new \ReflectionClass('ReflectionClass');
30
31        $this->assertDumpMatchesFormat(
32            <<<'EOTXT'
33ReflectionClass {
34  +name: "ReflectionClass"
35%Aimplements: array:%d [
36    0 => "Reflector"
37%A]
38  constants: array:3 [
39    "IS_IMPLICIT_ABSTRACT" => 16
40    "IS_EXPLICIT_ABSTRACT" => %d
41    "IS_FINAL" => %d
42  ]
43  properties: array:%d [
44    "name" => ReflectionProperty {
45%A    +name: "name"
46      +class: "ReflectionClass"
47%A    modifiers: "public"
48    }
49%A]
50  methods: array:%d [
51%A
52    "export" => ReflectionMethod {
53      +name: "export"
54      +class: "ReflectionClass"
55%A    parameters: {
56        $%s: ReflectionParameter {
57%A         position: 0
58%A
59}
60EOTXT
61            , $var
62        );
63    }
64
65    public function testClosureCaster()
66    {
67        $a = $b = 123;
68        $var = function ($x) use ($a, &$b) {};
69
70        $this->assertDumpMatchesFormat(
71            <<<'EOTXT'
72Closure($x) {
73%Ause: {
74    $a: 123
75    $b: & 123
76  }
77  file: "%sReflectionCasterTest.php"
78  line: "68 to 68"
79}
80EOTXT
81            , $var
82        );
83    }
84
85    public function testFromCallableClosureCaster()
86    {
87        if (\defined('HHVM_VERSION_ID')) {
88            $this->markTestSkipped('Not for HHVM.');
89        }
90        $var = [
91            (new \ReflectionMethod($this, __FUNCTION__))->getClosure($this),
92            (new \ReflectionMethod(__CLASS__, 'stub'))->getClosure(),
93        ];
94
95        $this->assertDumpMatchesFormat(
96            <<<EOTXT
97array:2 [
98  0 => Symfony\Component\VarDumper\Tests\Caster\ReflectionCasterTest::testFromCallableClosureCaster() {
99    this: Symfony\Component\VarDumper\Tests\Caster\ReflectionCasterTest { …}
100    file: "%sReflectionCasterTest.php"
101    line: "%d to %d"
102  }
103  1 => Symfony\Component\VarDumper\Tests\Caster\ReflectionCasterTest::stub(): void {
104    returnType: "void"
105    file: "%sReflectionCasterTest.php"
106    line: "%d to %d"
107  }
108]
109EOTXT
110            , $var
111        );
112    }
113
114    public function testClosureCasterExcludingVerbosity()
115    {
116        $var = function &($a = 5) {};
117
118        $this->assertDumpEquals('Closure&($a = 5) { …5}', $var, Caster::EXCLUDE_VERBOSE);
119    }
120
121    public function testReflectionParameter()
122    {
123        $var = new \ReflectionParameter(reflectionParameterFixture::class, 0);
124
125        $this->assertDumpMatchesFormat(
126            <<<'EOTXT'
127ReflectionParameter {
128  +name: "arg1"
129  position: 0
130  typeHint: "Symfony\Component\VarDumper\Tests\Fixtures\NotLoadableClass"
131  default: null
132}
133EOTXT
134            , $var
135        );
136    }
137
138    public function testReflectionParameterScalar()
139    {
140        $f = eval('return function (int $a) {};');
141        $var = new \ReflectionParameter($f, 0);
142
143        $this->assertDumpMatchesFormat(
144            <<<'EOTXT'
145ReflectionParameter {
146  +name: "a"
147  position: 0
148  typeHint: "int"
149}
150EOTXT
151            , $var
152        );
153    }
154
155    public function testReturnType()
156    {
157        $f = eval('return function ():int {};');
158        $line = __LINE__ - 1;
159
160        $this->assertDumpMatchesFormat(
161            <<<EOTXT
162Closure(): int {
163  returnType: "int"
164  class: "Symfony\Component\VarDumper\Tests\Caster\ReflectionCasterTest"
165  this: Symfony\Component\VarDumper\Tests\Caster\ReflectionCasterTest { …}
166  file: "%sReflectionCasterTest.php($line) : eval()'d code"
167  line: "1 to 1"
168}
169EOTXT
170            , $f
171        );
172    }
173
174    public function testGenerator()
175    {
176        if (\extension_loaded('xdebug')) {
177            $this->markTestSkipped('xdebug is active');
178        }
179
180        $generator = new GeneratorDemo();
181        $generator = $generator->baz();
182
183        $expectedDump = <<<'EODUMP'
184Generator {
185  this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
186  executing: {
187    %sGeneratorDemo.php:14 {
188      Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo->baz()
189      › {
190      ›     yield from bar();
191      › }
192    }
193  }
194  closed: false
195}
196EODUMP;
197
198        $this->assertDumpMatchesFormat($expectedDump, $generator);
199
200        foreach ($generator as $v) {
201            break;
202        }
203
204        $expectedDump = <<<'EODUMP'
205array:2 [
206  0 => ReflectionGenerator {
207    this: Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo { …}
208    trace: {
209      %s%eTests%eFixtures%eGeneratorDemo.php:9 {
210        Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo()
211        › {
212        ›     yield 1;
213        › }
214      }
215      %s%eTests%eFixtures%eGeneratorDemo.php:20 { …}
216      %s%eTests%eFixtures%eGeneratorDemo.php:14 { …}
217    }
218    closed: false
219  }
220  1 => Generator {
221    executing: {
222      %sGeneratorDemo.php:10 {
223        Symfony\Component\VarDumper\Tests\Fixtures\GeneratorDemo::foo()
224        ›     yield 1;
225        › }
226
227      }
228    }
229    closed: false
230  }
231]
232EODUMP;
233
234        $r = new \ReflectionGenerator($generator);
235        $this->assertDumpMatchesFormat($expectedDump, [$r, $r->getExecutingGenerator()]);
236
237        foreach ($generator as $v) {
238        }
239
240        $expectedDump = <<<'EODUMP'
241Generator {
242  closed: true
243}
244EODUMP;
245        $this->assertDumpMatchesFormat($expectedDump, $generator);
246    }
247
248    public static function stub(): void
249    {
250    }
251}
252
253function reflectionParameterFixture(NotLoadableClass $arg1 = null, $arg2)
254{
255}
256