| 
<?php
 /*
 * This file is part of Chevere.
 *
 * (c) Rodolfo Berrios <[email protected]>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */
 
 declare(strict_types=1);
 
 namespace Chevere\Tests\Processors;
 
 use Chevere\Tests\src\DummyClass;
 use Chevere\Tests\Traits\VarDumperTrait;
 use Chevere\VarDump\Processors\ObjectProcessor;
 use InvalidArgumentException;
 use PHPUnit\Framework\TestCase;
 use stdClass;
 
 final class ObjectProcessorTest extends TestCase
 {
 use VarDumperTrait;
 
 public function testInvalidArgument(): void
 {
 $this->expectException(InvalidArgumentException::class);
 new ObjectProcessor($this->getVarDumper(null));
 }
 
 public function testEmptyObject(): void
 {
 $object = new stdClass();
 $id = strval(spl_object_id($object));
 $varDumper = $this->getVarDumper($object);
 $this->assertProcessor(ObjectProcessor::class, $varDumper);
 $processor = new ObjectProcessor($varDumper);
 $this->assertSame(1, $processor->depth());
 $this->assertSame(stdClass::class . '#' . $id, $processor->info());
 $this->assertSame(
 stdClass::class . '#' . $id,
 $varDumper->writer()->__toString()
 );
 }
 
 public function testUnsetObject(): void
 {
 $object = new DummyClass();
 $className = $object::class;
 $id = strval(spl_object_id($object));
 $varDumper = $this->getVarDumper($object);
 $processor = new ObjectProcessor($varDumper);
 $this->assertSame(DummyClass::class . '#' . $id, $processor->info());
 $dump = <<<EOT
 {$className}#{$id}
 public code int 101 (length=3)
 public public uninitialized
 public readonly readonly uninitialized
 private private uninitialized
 private protected uninitialized
 private circularReference uninitialized
 private deep uninitialized
 EOT;
 $this->assertSame(
 $dump,
 $varDumper->writer()->__toString()
 );
 }
 
 public function testObjectProperty(): void
 {
 $object = (new DummyClass())->withPublic();
 $className = $object::class;
 $id = strval(spl_object_id($object));
 $pubId = strval(spl_object_id($object->public));
 $dump = <<<EOT
 {$className}#{$id}
 public code int 101 (length=3)
 public public stdClass#{$pubId}
 public string string string (length=6)
 public array array [] (size=0)
 public int int 1 (length=1)
 public bool bool true
 public readonly readonly uninitialized
 private private uninitialized
 private protected uninitialized
 private circularReference uninitialized
 private deep uninitialized
 EOT;
 $varDumper = $this->getVarDumper($object);
 $this->assertSame(
 $dump,
 $varDumper->writer()->__toString()
 );
 $dump = <<<EOT
 {$className}#{$id}
 public code int 102 (length=3)
 public public stdClass#{$pubId}
 EOT;
 $object->code = 102;
 $varDumper = $this->getVarDumper($object);
 $this->assertStringStartsWith(
 $dump,
 $varDumper->writer()->__toString()
 );
 }
 
 public function testCircularReferences(): void
 {
 $var = new stdClass();
 $ref = new stdClass();
 $ref->scalar = 'REF';
 $ref->circular = $ref;
 $ref->var = $var;
 $var->scalar = 'VAR';
 $var->ref = $ref;
 $var->circular = $var;
 $var->refArr = [$ref];
 $var->circularArr = [$var];
 $varDumper = $this->getVarDumper($var);
 $varId = strval(spl_object_id($var));
 $refId = strval(spl_object_id($ref));
 $dump = <<<EOT
 stdClass#{$varId}
 public scalar string VAR (length=3)
 public ref stdClass#{$refId}
 public scalar string REF (length=3)
 public circular stdClass#{$refId} (circular reference #{$refId})
 public var stdClass#{$varId} (circular reference #{$varId})
 public circular stdClass#{$varId} (circular reference #{$varId})
 public refArr array (size=1)
 0 => stdClass#{$refId} (circular reference #{$refId})
 public circularArr array (size=1)
 0 => stdClass#{$varId} (circular reference #{$varId})
 EOT;
 $this->assertSame(
 $dump,
 $varDumper->writer()->__toString()
 );
 }
 
 public function testAnonClass(): void
 {
 $object = new class() {
 };
 $id = strval(spl_object_id($object));
 $varDumper = $this->getVarDumper($object);
 $this->assertSame(
 'class@anonymous#' . $id,
 $varDumper->writer()->__toString()
 );
 }
 
 public function testCircularReference(): void
 {
 $object = (new DummyClass())->withCircularReference();
 $className = $object::class;
 $id = strval(spl_object_id($object));
 $varDumper = $this->getVarDumper($object);
 $dump = <<<EOT
 {$className}#{$id}
 public code int 101 (length=3)
 public public uninitialized
 public readonly readonly uninitialized
 private private uninitialized
 private protected uninitialized
 private circularReference {$className}#{$id} (circular reference #{$id})
 private deep uninitialized
 EOT;
 $this->assertSame(
 $dump,
 $varDumper->writer()->__toString()
 );
 }
 
 public function testDeep(): void
 {
 $deep = new stdClass();
 for ($i = 0; $i <= ObjectProcessor::MAX_DEPTH; $i++) {
 $deep = new class($deep) {
 public function __construct(
 public $deep
 ) {
 }
 };
 $objectIds[] = strval(spl_object_id($deep));
 }
 $objectIds = array_reverse($objectIds);
 $lastId = $objectIds[99];
 $object = (new DummyClass())->withDeep($deep);
 $className = $object::class;
 $id = strval(spl_object_id($object));
 $varDumper = $this->getVarDumper($object);
 $stringEls = <<<EOT
 {$className}#{$id}
 public code int 101 (length=3)
 public public uninitialized
 public readonly readonly uninitialized
 private private uninitialized
 private protected uninitialized
 private circularReference uninitialized
 private deep class@anonymous#{$objectIds[0]}
 EOT;
 $toString = $varDumper->writer()->__toString();
 $this->assertStringStartsWith($stringEls, $toString);
 $stringEls = <<<EOT
 public deep class@anonymous#{$lastId} (max depth reached)
 EOT;
 $this->assertStringEndsWith($stringEls, $toString);
 }
 }
 
 |