/
githubmirror
/
symfony
Обзор
Документация
Войти
/
githubmirror
/
symfony
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
8.2
src/Symfony/Component/JsonStreamer/Tests/JsonStreamReaderTest.php
342 строки
16 KB
Mathias Arlaud
[JsonStreamer] Add UID value object support
28 июл 2026, 00:38
28 июл 2026, 00:38
868180e
Код
Авторство
О чём код?
<?php /* * This file is part of the Symfony package. * * (c) Fabien Potencier <fabien@symfony.com> * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ namespace Symfony\Component\JsonStreamer\Tests; use PHPUnit\Framework\Attributes\RequiresPhpExtension; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\JsonStreamer\JsonStreamReader; use Symfony\Component\JsonStreamer\Tests\Fixtures\Enum\DummyBackedEnum; use Symfony\Component\JsonStreamer\Tests\Fixtures\Mapping\SyntheticPropertyMetadataLoader; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\ClassicDummy; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithBcMathNumber; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithDateIntervals; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithDateTimes; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithDateTimeZones; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithGenerics; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithGmpNumber; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithNameAttributes; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithNullableProperties; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithPhpDoc; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithSyntheticProperties; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithUids; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithValueObjects; use Symfony\Component\JsonStreamer\Tests\Fixtures\Model\DummyWithValueTransformerAttributes; use Symfony\Component\JsonStreamer\Tests\Fixtures\Transformer\DivideStringAndCastToIntValueTransformer; use Symfony\Component\JsonStreamer\Tests\Fixtures\Transformer\HeightValueObjectTransformer; use Symfony\Component\JsonStreamer\Tests\Fixtures\Transformer\StringToBooleanValueTransformer; use Symfony\Component\JsonStreamer\Tests\Fixtures\ValueObject\Height; use Symfony\Component\TypeInfo\Type; use Symfony\Component\TypeInfo\TypeIdentifier; use Symfony\Component\Uid\Ulid; use Symfony\Component\Uid\Uuid; use Symfony\Component\Uid\UuidV7; class JsonStreamReaderTest extends TestCase { private string $streamReadersDir; protected function setUp(): void { parent::setUp(); $this->streamReadersDir = \sprintf('%s/symfony_json_streamer_test/stream_reader', sys_get_temp_dir()); if (is_dir($this->streamReadersDir)) { array_map('unlink', glob($this->streamReadersDir.'/*')); rmdir($this->streamReadersDir); } } public function testReadScalar() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, null, 'null', Type::nullable(Type::int())); $this->assertRead($reader, true, 'true', Type::bool()); $this->assertRead($reader, [['foo' => 1, 'bar' => 2], ['foo' => 3]], '[{"foo": 1, "bar": 2}, {"foo": 3}]', Type::builtin(TypeIdentifier::ARRAY)); $this->assertRead($reader, [['foo' => 1, 'bar' => 2], ['foo' => 3]], '[{"foo": 1, "bar": 2}, {"foo": 3}]', Type::builtin(TypeIdentifier::ITERABLE)); $this->assertRead($reader, (object) ['foo' => 'bar'], '{"foo": "bar"}', Type::object()); $this->assertRead($reader, DummyBackedEnum::ONE, '1', Type::enum(DummyBackedEnum::class, Type::string())); } public function testReadCollection() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead( $reader, [true, false], '{"0": true, "1": false}', Type::array(Type::bool()), ); $this->assertRead( $reader, [true, false], '[true, false]', Type::list(Type::bool()), ); $this->assertRead($reader, function (mixed $read) { $this->assertIsIterable($read); $this->assertSame([true, false], iterator_to_array($read)); }, '{"0": true, "1": false}', Type::iterable(Type::bool())); $this->assertRead($reader, function (mixed $read) { $this->assertIsIterable($read); $this->assertSame([true, false], iterator_to_array($read)); }, '[true, false]', Type::iterable(Type::bool(), Type::int())); } public function testReadObject() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(ClassicDummy::class, $read); $this->assertSame(10, $read->id); $this->assertSame('dummy name', $read->name); }, '{"id": 10, "name": "dummy name"}', Type::object(ClassicDummy::class)); } public function testReadObjectWithGenerics() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithGenerics::class, $read); $this->assertSame(10, $read->dummies[0]->id); $this->assertSame('dummy name', $read->dummies[0]->name); }, '{"dummies":[{"id":10,"name":"dummy name"}]}', Type::generic(Type::object(DummyWithGenerics::class), Type::object(ClassicDummy::class))); } public function testReadObjectWithStreamedName() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithNameAttributes::class, $read); $this->assertSame(10, $read->id); }, '{"@id": 10}', Type::object(DummyWithNameAttributes::class)); } public function testReadObjectWithValueTransformer() { $reader = JsonStreamReader::create([ StringToBooleanValueTransformer::class => new StringToBooleanValueTransformer(), DivideStringAndCastToIntValueTransformer::class => new DivideStringAndCastToIntValueTransformer(), ], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithValueTransformerAttributes::class, $read); $this->assertSame(10, $read->id); $this->assertTrue($read->active); $this->assertSame('LOWERCASE NAME', $read->name); $this->assertSame([0, 1], $read->range); }, '{"id": "20", "active": "true", "name": "lowercase name", "range": "0..1"}', Type::object(DummyWithValueTransformerAttributes::class), ['scale' => 1]); } public function testReadObjectWithValueObjects() { $reader = JsonStreamReader::create([ Height::class => new HeightValueObjectTransformer(), ], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithValueObjects::class, $read); $this->assertEquals(new Height(10, 'm'), $read->height); $this->assertEquals(new Height(10, 'dm'), $read->nullableHeight); $this->assertEquals(new Height(10, 'cm'), $read->unionHeight); }, '{"height":"10 m","nullableHeight":"10 dm","unionHeight":"10 cm"}', Type::object(DummyWithValueObjects::class)); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithValueObjects::class, $read); $this->assertEquals(new Height(10, 'm'), $read->height); $this->assertNull($read->nullableHeight); $this->assertSame(10, $read->unionHeight); }, '{"height":"10 m","nullableHeight":null,"unionHeight":10}', Type::object(DummyWithValueObjects::class)); } public function testReadObjectWithPhpDoc() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithPhpDoc::class, $read); $this->assertIsArray($read->arrayOfDummies); $this->assertContainsOnlyInstancesOf(DummyWithNameAttributes::class, $read->arrayOfDummies); $this->assertArrayHasKey('key', $read->arrayOfDummies); }, '{"arrayOfDummies":{"key":{"@id":10,"name":"dummy"}}}', Type::object(DummyWithPhpDoc::class)); } public function testReadObjectWithNullableProperties() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithNullableProperties::class, $read); $this->assertNull($read->name); $this->assertNull($read->enum); }, '{"name":null,"enum":null}', Type::object(DummyWithNullableProperties::class)); } public function testReadObjectWithDateTimes() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithDateTimes::class, $read); $this->assertEquals(new \DateTimeImmutable('2024-11-20'), $read->interface); $this->assertEquals(new \DateTimeImmutable('2025-11-20'), $read->immutable); $this->assertEquals(new \DateTimeImmutable('2026-11-20'), $read->union); }, '{"interface":"2024-11-20","immutable":"2025-11-20","union":"2026-11-20"}', Type::object(DummyWithDateTimes::class)); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithDateTimes::class, $read); $this->assertEquals(new \DateTimeImmutable('2024-11-20'), $read->interface); $this->assertEquals(new \DateTimeImmutable('2025-11-20'), $read->immutable); $this->assertEquals(10, $read->union); }, '{"interface":"2024-11-20","immutable":"2025-11-20","union":10}', Type::object(DummyWithDateTimes::class)); } public function testReadObjectWithDateIntervals() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithDateIntervals::class, $read); $this->assertEquals(new \DateInterval('P2Y6M1DT12H30M5S'), $read->interval); }, '{"interval":"P2Y6M1DT12H30M5S"}', Type::object(DummyWithDateIntervals::class)); } public function testReadObjectWithDateTimeZones() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithDateTimeZones::class, $read); $this->assertEquals(new \DateTimeZone('Asia/Tokyo'), $read->timezone); }, '{"timezone":"Asia/Tokyo"}', Type::object(DummyWithDateTimeZones::class)); } #[RequiresPhpExtension('bcmath')] public function testReadObjectWithBcMathNumber() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithBcMathNumber::class, $read); $this->assertEquals(new \BcMath\Number('3.14'), $read->number); }, '{"number":"3.14"}', Type::object(DummyWithBcMathNumber::class)); } #[RequiresPhpExtension('gmp')] public function testReadObjectWithGmpNumber() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithGmpNumber::class, $read); $this->assertEquals(new \GMP('99999999999999999999'), $read->gmp); }, '{"gmp":"99999999999999999999"}', Type::object(DummyWithGmpNumber::class)); } public function testReadObjectWithUids() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithUids::class, $read); $this->assertEquals(Uuid::fromString('a7613e0a-5986-4f29-b3f8-3b6f8e5e6b40'), $read->uuid); $this->assertEquals(UuidV7::fromString('018f7a5e-3c1e-7a4e-8b1a-2c3d4e5f6a7b'), $read->uuidV7); $this->assertEquals(Ulid::fromString('01ARZ3NDEKTSV4RRFFQ69G5FAV'), $read->ulid); }, '{"uuid":"a7613e0a-5986-4f29-b3f8-3b6f8e5e6b40","uuidV7":"018f7a5e-3c1e-7a4e-8b1a-2c3d4e5f6a7b","ulid":"01ARZ3NDEKTSV4RRFFQ69G5FAV"}', Type::object(DummyWithUids::class)); } public function testReadObjectWithUidsUsingNonCanonicalFormat() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $uuid = Uuid::fromString('a7613e0a-5986-4f29-b3f8-3b6f8e5e6b40'); $uuidV7 = UuidV7::fromString('018f7a5e-3c1e-7a4e-8b1a-2c3d4e5f6a7b'); $ulid = Ulid::fromString('01ARZ3NDEKTSV4RRFFQ69G5FAV'); $this->assertRead($reader, function (mixed $read) use ($uuid, $uuidV7, $ulid) { $this->assertInstanceOf(DummyWithUids::class, $read); $this->assertEquals($uuid, $read->uuid); $this->assertEquals($uuidV7, $read->uuidV7); $this->assertEquals($ulid, $read->ulid); }, \sprintf('{"uuid":"%s","uuidV7":"%s","ulid":"%s"}', $uuid->toBase58(), $uuidV7->toBase58(), $ulid->toBase58()), Type::object(DummyWithUids::class)); } public function testReadUnion() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithNameAttributes::class, $read); $this->assertSame(10, $read->id); $this->assertSame('dummy', $read->name); }, '{"@id": 10, "name": "dummy"}', Type::union(Type::int(), Type::list(Type::enum(DummyBackedEnum::class)), Type::object(DummyWithNameAttributes::class))); $this->assertRead($reader, [DummyBackedEnum::ONE, DummyBackedEnum::TWO], '[1, 2]', Type::union(Type::int(), Type::list(Type::enum(DummyBackedEnum::class)), Type::object(DummyWithNameAttributes::class))); } public function testReadObjectWithSyntheticProperties() { $reader = new JsonStreamReader(new Container(), new SyntheticPropertyMetadataLoader(), $this->streamReadersDir); $this->assertRead($reader, function (mixed $read) { $this->assertInstanceOf(DummyWithSyntheticProperties::class, $read); $this->assertSame([], get_object_vars($read)); }, '{"synthetic":true}', Type::object(DummyWithSyntheticProperties::class)); } public function testCreateStreamReaderFile() { $reader = JsonStreamReader::create([], $this->streamReadersDir); $reader->read('true', Type::bool()); $this->assertFileExists($this->streamReadersDir); $this->assertCount(1, glob($this->streamReadersDir.'/*')); } public function testCreateStreamReaderFileOnlyIfNotExists() { $reader = JsonStreamReader::create([], $this->streamReadersDir); if (!file_exists($this->streamReadersDir)) { mkdir($this->streamReadersDir, recursive: true); } file_put_contents( \sprintf('%s%s%s.json.php', $this->streamReadersDir, \DIRECTORY_SEPARATOR, hash('xxh128', (string) Type::bool())), '<?php return static function () { return "CACHED"; };' ); $this->assertSame('CACHED', $reader->read('true', Type::bool())); } private function assertRead(JsonStreamReader $reader, mixed $readOrAssert, string $json, Type $type, array $options = []): void { $assert = \is_callable($readOrAssert, syntax_only: true) ? $readOrAssert : fn (mixed $read) => $this->assertEquals($readOrAssert, $read); $assert($reader->read($json, $type, $options)); $resource = fopen('php://temp', 'w'); fwrite($resource, $json); rewind($resource); $assert($reader->read($resource, $type, $options)); } }