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\VarDumper\Tests\Dumper;
Chris@0:
Chris@0: use PHPUnit\Framework\TestCase;
Chris@0: use Symfony\Component\VarDumper\Cloner\VarCloner;
Chris@0: use Symfony\Component\VarDumper\Dumper\CliDumper;
Chris@0: use Symfony\Component\VarDumper\Test\VarDumperTestTrait;
Chris@0: use Twig\Environment;
Chris@0: use Twig\Loader\FilesystemLoader;
Chris@0:
Chris@0: /**
Chris@0: * @author Nicolas Grekas
Chris@0: */
Chris@0: class CliDumperTest extends TestCase
Chris@0: {
Chris@0: use VarDumperTestTrait;
Chris@0:
Chris@0: public function testGet()
Chris@0: {
Chris@0: require __DIR__.'/../Fixtures/dumb-var.php';
Chris@0:
Chris@0: $dumper = new CliDumper('php://output');
Chris@0: $dumper->setColors(false);
Chris@0: $cloner = new VarCloner();
Chris@17: $cloner->addCasters([
Chris@0: ':stream' => function ($res, $a) {
Chris@0: unset($a['uri'], $a['wrapper_data']);
Chris@0:
Chris@0: return $a;
Chris@0: },
Chris@17: ]);
Chris@0: $data = $cloner->cloneVar($var);
Chris@0:
Chris@0: ob_start();
Chris@0: $dumper->dump($data);
Chris@0: $out = ob_get_clean();
Chris@0: $out = preg_replace('/[ \t]+$/m', '', $out);
Chris@0: $intMax = PHP_INT_MAX;
Chris@0: $res = (int) $var['res'];
Chris@0:
Chris@17: $r = \defined('HHVM_VERSION') ? '' : '#%d';
Chris@0: $this->assertStringMatchesFormat(
Chris@0: << 1
Chris@0: 0 => &1 null
Chris@0: "const" => 1.1
Chris@0: 1 => true
Chris@0: 2 => false
Chris@0: 3 => NAN
Chris@0: 4 => INF
Chris@0: 5 => -INF
Chris@0: 6 => {$intMax}
Chris@0: "str" => "déjà\\n"
Chris@0: 7 => b"é\\x00"
Chris@0: "[]" => []
Chris@0: "res" => stream resource {@{$res}
Chris@0: %A wrapper_type: "plainfile"
Chris@0: stream_type: "STDIO"
Chris@0: mode: "r"
Chris@0: unread_bytes: 0
Chris@0: seekable: true
Chris@0: %A options: []
Chris@0: }
Chris@0: "obj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d
Chris@0: +foo: "foo"
Chris@0: +"bar": "bar"
Chris@0: }
Chris@0: "closure" => Closure {{$r}
Chris@0: class: "Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest"
Chris@0: this: Symfony\Component\VarDumper\Tests\Dumper\CliDumperTest {{$r} …}
Chris@0: parameters: {
Chris@0: \$a: {}
Chris@0: &\$b: {
Chris@0: typeHint: "PDO"
Chris@0: default: null
Chris@0: }
Chris@0: }
Chris@12: file: "%s%eTests%eFixtures%edumb-var.php"
Chris@0: line: "{$var['line']} to {$var['line']}"
Chris@0: }
Chris@0: "line" => {$var['line']}
Chris@0: "nobj" => array:1 [
Chris@0: 0 => &3 {#%d}
Chris@0: ]
Chris@0: "recurs" => &4 array:1 [
Chris@0: 0 => &4 array:1 [&4]
Chris@0: ]
Chris@0: 8 => &1 null
Chris@0: "sobj" => Symfony\Component\VarDumper\Tests\Fixture\DumbFoo {#%d}
Chris@0: "snobj" => &3 {#%d}
Chris@0: "snobj2" => {#%d}
Chris@0: "file" => "{$var['file']}"
Chris@0: b"bin-key-é" => ""
Chris@0: ]
Chris@0:
Chris@0: EOTXT
Chris@0: ,
Chris@0: $out
Chris@0: );
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * @dataProvider provideDumpWithCommaFlagTests
Chris@0: */
Chris@0: public function testDumpWithCommaFlag($expected, $flags)
Chris@0: {
Chris@0: $dumper = new CliDumper(null, null, $flags);
Chris@0: $dumper->setColors(false);
Chris@0: $cloner = new VarCloner();
Chris@0:
Chris@17: $var = [
Chris@17: 'array' => ['a', 'b'],
Chris@0: 'string' => 'hello',
Chris@0: 'multiline string' => "this\nis\na\multiline\nstring",
Chris@17: ];
Chris@0:
Chris@0: $dump = $dumper->dump($cloner->cloneVar($var), true);
Chris@0:
Chris@0: $this->assertSame($expected, $dump);
Chris@0: }
Chris@0:
Chris@0: public function testDumpWithCommaFlagsAndExceptionCodeExcerpt()
Chris@0: {
Chris@0: $dumper = new CliDumper(null, null, CliDumper::DUMP_TRAILING_COMMA);
Chris@0: $dumper->setColors(false);
Chris@0: $cloner = new VarCloner();
Chris@0:
Chris@0: $ex = new \RuntimeException('foo');
Chris@0:
Chris@0: $dump = $dumper->dump($cloner->cloneVar($ex)->withRefHandles(false), true);
Chris@0:
Chris@0: $this->assertStringMatchesFormat(<<<'EOTXT'
Chris@0: RuntimeException {
Chris@0: #message: "foo"
Chris@0: #code: 0
Chris@0: #file: "%ACliDumperTest.php"
Chris@0: #line: %d
Chris@0: trace: {
Chris@12: %ACliDumperTest.php:%d {
Chris@12: ›
Chris@12: › $ex = new \RuntimeException('foo');
Chris@12: ›
Chris@0: }
Chris@0: %A
Chris@0: }
Chris@0: }
Chris@0:
Chris@0: EOTXT
Chris@0: , $dump);
Chris@0: }
Chris@0:
Chris@0: public function provideDumpWithCommaFlagTests()
Chris@0: {
Chris@0: $expected = <<<'EOTXT'
Chris@0: array:3 [
Chris@0: "array" => array:2 [
Chris@0: 0 => "a",
Chris@0: 1 => "b"
Chris@0: ],
Chris@0: "string" => "hello",
Chris@0: "multiline string" => """
Chris@0: this\n
Chris@0: is\n
Chris@0: a\multiline\n
Chris@0: string
Chris@0: """
Chris@0: ]
Chris@0:
Chris@0: EOTXT;
Chris@0:
Chris@17: yield [$expected, CliDumper::DUMP_COMMA_SEPARATOR];
Chris@0:
Chris@0: $expected = <<<'EOTXT'
Chris@0: array:3 [
Chris@0: "array" => array:2 [
Chris@0: 0 => "a",
Chris@0: 1 => "b",
Chris@0: ],
Chris@0: "string" => "hello",
Chris@0: "multiline string" => """
Chris@0: this\n
Chris@0: is\n
Chris@0: a\multiline\n
Chris@0: string
Chris@0: """,
Chris@0: ]
Chris@0:
Chris@0: EOTXT;
Chris@0:
Chris@17: yield [$expected, CliDumper::DUMP_TRAILING_COMMA];
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * @requires extension xml
Chris@0: */
Chris@0: public function testXmlResource()
Chris@0: {
Chris@0: $var = xml_parser_create();
Chris@0:
Chris@0: $this->assertDumpMatchesFormat(
Chris@0: <<<'EOTXT'
Chris@0: xml resource {
Chris@0: current_byte_index: %i
Chris@0: current_column_number: %i
Chris@0: current_line_number: 1
Chris@0: error_code: XML_ERROR_NONE
Chris@0: }
Chris@0: EOTXT
Chris@0: ,
Chris@0: $var
Chris@0: );
Chris@0: }
Chris@0:
Chris@0: public function testJsonCast()
Chris@0: {
Chris@0: $var = (array) json_decode('{"0":{},"1":null}');
Chris@0: foreach ($var as &$v) {
Chris@0: }
Chris@0: $var[] = &$v;
Chris@0: $var[''] = 2;
Chris@0:
Chris@0: if (\PHP_VERSION_ID >= 70200) {
Chris@0: $this->assertDumpMatchesFormat(
Chris@0: <<<'EOTXT'
Chris@0: array:4 [
Chris@0: 0 => {}
Chris@0: 1 => &1 null
Chris@0: 2 => &1 null
Chris@0: "" => 2
Chris@0: ]
Chris@0: EOTXT
Chris@0: ,
Chris@0: $var
Chris@0: );
Chris@0: } else {
Chris@0: $this->assertDumpMatchesFormat(
Chris@0: <<<'EOTXT'
Chris@0: array:4 [
Chris@0: "0" => {}
Chris@0: "1" => &1 null
Chris@0: 0 => &1 null
Chris@0: "" => 2
Chris@0: ]
Chris@0: EOTXT
Chris@0: ,
Chris@0: $var
Chris@0: );
Chris@0: }
Chris@0: }
Chris@0:
Chris@0: public function testObjectCast()
Chris@0: {
Chris@17: $var = (object) [1 => 1];
Chris@0: $var->{1} = 2;
Chris@0:
Chris@0: if (\PHP_VERSION_ID >= 70200) {
Chris@0: $this->assertDumpMatchesFormat(
Chris@0: <<<'EOTXT'
Chris@0: {
Chris@0: +"1": 2
Chris@0: }
Chris@0: EOTXT
Chris@0: ,
Chris@0: $var
Chris@0: );
Chris@0: } else {
Chris@0: $this->assertDumpMatchesFormat(
Chris@0: <<<'EOTXT'
Chris@0: {
Chris@0: +1: 1
Chris@0: +"1": 2
Chris@0: }
Chris@0: EOTXT
Chris@0: ,
Chris@0: $var
Chris@0: );
Chris@0: }
Chris@0: }
Chris@0:
Chris@0: public function testClosedResource()
Chris@0: {
Chris@17: if (\defined('HHVM_VERSION') && HHVM_VERSION_ID < 30600) {
Chris@0: $this->markTestSkipped();
Chris@0: }
Chris@0:
Chris@0: $var = fopen(__FILE__, 'r');
Chris@0: fclose($var);
Chris@0:
Chris@0: $dumper = new CliDumper('php://output');
Chris@0: $dumper->setColors(false);
Chris@0: $cloner = new VarCloner();
Chris@0: $data = $cloner->cloneVar($var);
Chris@0:
Chris@0: ob_start();
Chris@0: $dumper->dump($data);
Chris@0: $out = ob_get_clean();
Chris@0: $res = (int) $var;
Chris@0:
Chris@0: $this->assertStringMatchesFormat(
Chris@0: << 'bar'],
Chris@17: ];
Chris@0:
Chris@0: $this->assertDumpEquals(
Chris@0: << (3) "foo"
Chris@0: 2 => (3) "bar"
Chris@0: ]
Chris@0: ]
Chris@0: EOTXT
Chris@0: ,
Chris@0: $var
Chris@0: );
Chris@0:
Chris@0: putenv('DUMP_LIGHT_ARRAY=');
Chris@0: putenv('DUMP_STRING_LENGTH=');
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * @requires function Twig\Template::getSourceContext
Chris@0: */
Chris@0: public function testThrowingCaster()
Chris@0: {
Chris@0: $out = fopen('php://memory', 'r+b');
Chris@0:
Chris@0: require_once __DIR__.'/../Fixtures/Twig.php';
Chris@0: $twig = new \__TwigTemplate_VarDumperFixture_u75a09(new Environment(new FilesystemLoader()));
Chris@0:
Chris@0: $dumper = new CliDumper();
Chris@0: $dumper->setColors(false);
Chris@0: $cloner = new VarCloner();
Chris@17: $cloner->addCasters([
Chris@0: ':stream' => function ($res, $a) {
Chris@0: unset($a['wrapper_data']);
Chris@0:
Chris@0: return $a;
Chris@0: },
Chris@17: ]);
Chris@17: $cloner->addCasters([
Chris@0: ':stream' => eval('return function () use ($twig) {
Chris@0: try {
Chris@17: $twig->render([]);
Chris@0: } catch (\Twig\Error\RuntimeError $e) {
Chris@0: throw $e->getPrevious();
Chris@0: }
Chris@0: };'),
Chris@17: ]);
Chris@0: $ref = (int) $out;
Chris@0:
Chris@0: $data = $cloner->cloneVar($out);
Chris@0: $dumper->dump($data, $out);
Chris@0: $out = stream_get_contents($out, -1, 0);
Chris@0:
Chris@17: $r = \defined('HHVM_VERSION') ? '' : '#%d';
Chris@0: $this->assertStringMatchesFormat(
Chris@0: << 'foo'];
Chris@0: $var->bar = &$var->foo;
Chris@0:
Chris@0: $dumper = new CliDumper();
Chris@0: $dumper->setColors(false);
Chris@0: $cloner = new VarCloner();
Chris@0:
Chris@0: $data = $cloner->cloneVar($var);
Chris@0: $out = $dumper->dump($data, true);
Chris@0:
Chris@17: $r = \defined('HHVM_VERSION') ? '' : '#%d';
Chris@0: $this->assertStringMatchesFormat(
Chris@0: <<getSpecialVars();
Chris@0:
Chris@0: $this->assertDumpEquals(
Chris@0: <<<'EOTXT'
Chris@0: array:3 [
Chris@0: 0 => array:1 [
Chris@0: 0 => &1 array:1 [
Chris@0: 0 => &1 array:1 [&1]
Chris@0: ]
Chris@0: ]
Chris@0: 1 => array:1 [
Chris@0: "GLOBALS" => &2 array:1 [
Chris@0: "GLOBALS" => &2 array:1 [&2]
Chris@0: ]
Chris@0: ]
Chris@0: 2 => &2 array:1 [&2]
Chris@0: ]
Chris@0: EOTXT
Chris@0: ,
Chris@0: $var
Chris@0: );
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * @runInSeparateProcess
Chris@0: * @preserveGlobalState disabled
Chris@0: */
Chris@0: public function testGlobalsNoExt()
Chris@0: {
Chris@0: $var = $this->getSpecialVars();
Chris@0: unset($var[0]);
Chris@0: $out = '';
Chris@0:
Chris@0: $dumper = new CliDumper(function ($line, $depth) use (&$out) {
Chris@0: if ($depth >= 0) {
Chris@0: $out .= str_repeat(' ', $depth).$line."\n";
Chris@0: }
Chris@0: });
Chris@0: $dumper->setColors(false);
Chris@0: $cloner = new VarCloner();
Chris@0:
Chris@0: $refl = new \ReflectionProperty($cloner, 'useExt');
Chris@0: $refl->setAccessible(true);
Chris@0: $refl->setValue($cloner, false);
Chris@0:
Chris@0: $data = $cloner->cloneVar($var);
Chris@0: $dumper->dump($data);
Chris@0:
Chris@0: $this->assertSame(
Chris@0: <<<'EOTXT'
Chris@0: array:2 [
Chris@0: 1 => array:1 [
Chris@0: "GLOBALS" => &1 array:1 [
Chris@0: "GLOBALS" => &1 array:1 [&1]
Chris@0: ]
Chris@0: ]
Chris@0: 2 => &1 array:1 [&1]
Chris@0: ]
Chris@0:
Chris@0: EOTXT
Chris@0: ,
Chris@0: $out
Chris@0: );
Chris@0: }
Chris@0:
Chris@0: /**
Chris@0: * @runInSeparateProcess
Chris@0: * @preserveGlobalState disabled
Chris@0: */
Chris@0: public function testBuggyRefs()
Chris@0: {
Chris@0: if (\PHP_VERSION_ID >= 50600) {
Chris@0: $this->markTestSkipped('PHP 5.6 fixed refs counting');
Chris@0: }
Chris@0:
Chris@0: $var = $this->getSpecialVars();
Chris@0: $var = $var[0];
Chris@0:
Chris@0: $dumper = new CliDumper();
Chris@0: $dumper->setColors(false);
Chris@0: $cloner = new VarCloner();
Chris@0:
Chris@0: $data = $cloner->cloneVar($var)->withMaxDepth(3);
Chris@0: $out = '';
Chris@0: $dumper->dump($data, function ($line, $depth) use (&$out) {
Chris@0: if ($depth >= 0) {
Chris@0: $out .= str_repeat(' ', $depth).$line."\n";
Chris@0: }
Chris@0: });
Chris@0:
Chris@0: $this->assertSame(
Chris@0: <<<'EOTXT'
Chris@0: array:1 [
Chris@0: 0 => array:1 [
Chris@0: 0 => array:1 [
Chris@0: 0 => array:1 [ …1]
Chris@0: ]
Chris@0: ]
Chris@0: ]
Chris@0:
Chris@0: EOTXT
Chris@0: ,
Chris@0: $out
Chris@0: );
Chris@0: }
Chris@0:
Chris@0: public function testIncompleteClass()
Chris@0: {
Chris@0: $unserializeCallbackHandler = ini_set('unserialize_callback_func', null);
Chris@0: $var = unserialize('O:8:"Foo\Buzz":0:{}');
Chris@0: ini_set('unserialize_callback_func', $unserializeCallbackHandler);
Chris@0:
Chris@0: $this->assertDumpMatchesFormat(
Chris@0: <<