This is an automated email from the ASF dual-hosted git repository. isapego pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/ignite-php-thin-client.git
commit b09f264194c56180caf5228087fa21ea0a7d7f2e Author: ekaterina-nbl <[email protected]> AuthorDate: Mon Oct 29 15:49:33 2018 +0300 IGNITE-10022: JS, PHP thin clients: a more meaningful exception when ENUM type is not registered This closes #5187 --- .../Ignite/Internal/Binary/BinaryCommunicator.php | 27 ++--- src/Apache/Ignite/Internal/Binary/BinaryUtils.php | 12 +++ tests/CachePutGetTest.php | 119 +++++++++++++++++++++ 3 files changed, 146 insertions(+), 12 deletions(-) diff --git a/src/Apache/Ignite/Internal/Binary/BinaryCommunicator.php b/src/Apache/Ignite/Internal/Binary/BinaryCommunicator.php index 520063c..781a730 100644 --- a/src/Apache/Ignite/Internal/Binary/BinaryCommunicator.php +++ b/src/Apache/Ignite/Internal/Binary/BinaryCommunicator.php @@ -265,8 +265,10 @@ class BinaryCommunicator $ordinal = $buffer->readInteger(); $enumItem->setOrdinal($ordinal); $type = $this->typeStorage->getType($enumItem->getTypeId()); - if (!$type->isEnum() || !$type->getEnumValues() || count($type->getEnumValues()) <= $ordinal) { - BinaryUtils::serializationError(false, 'EnumItem can not be deserialized: type mismatch'); + if (!$type || !$type->isEnum()) { + BinaryUtils::enumSerializationError(false, sprintf('enum type id "%d" is not registered', $enumItem->getTypeId())); + } elseif (!$type->getEnumValues() || count($type->getEnumValues()) <= $ordinal) { + BinaryUtils::enumSerializationError(false, 'type mismatch'); } $enumValues = $type->getEnumValues(); $enumItem->setName($enumValues[$ordinal][0]); @@ -396,21 +398,22 @@ class BinaryCommunicator private function writeEnum(MessageBuffer $buffer, EnumItem $enumValue): void { + $type = $this->typeStorage->getType($enumValue->getTypeId()); + if (!$type || !$type->isEnum()) { + BinaryUtils::enumSerializationError(true, sprintf('enum type id "%d" is not registered', $enumValue->getTypeId())); + } $buffer->writeInteger($enumValue->getTypeId()); if ($enumValue->getOrdinal() !== null) { $buffer->writeInteger($enumValue->getOrdinal()); return; } elseif ($enumValue->getName() !== null || $enumValue->getValue() !== null) { - $type = $this->typeStorage->getType($enumValue->getTypeId()); - if ($type && $type->isEnum()) { - $enumValues = $type->getEnumValues(); - if ($enumValues) { - for ($i = 0; $i < count($enumValues); $i++) { - if ($enumValue->getName() === $enumValues[$i][0] || - $enumValue->getValue() === $enumValues[$i][1]) { - $buffer->writeInteger($i); - return; - } + $enumValues = $type->getEnumValues(); + if ($enumValues) { + for ($i = 0; $i < count($enumValues); $i++) { + if ($enumValue->getName() === $enumValues[$i][0] || + $enumValue->getValue() === $enumValues[$i][1]) { + $buffer->writeInteger($i); + return; } } } diff --git a/src/Apache/Ignite/Internal/Binary/BinaryUtils.php b/src/Apache/Ignite/Internal/Binary/BinaryUtils.php index ad0bf56..e9ff2f1 100644 --- a/src/Apache/Ignite/Internal/Binary/BinaryUtils.php +++ b/src/Apache/Ignite/Internal/Binary/BinaryUtils.php @@ -203,6 +203,9 @@ class BinaryUtils $actualTypeCode === ObjectType::BINARY_OBJECT && $expectedTypeCode === ObjectType::COMPLEX_OBJECT) { return; + } elseif ($expectedTypeCode === ObjectType::ENUM && + $actualTypeCode === ObjectType::BINARY_ENUM) { + return; } elseif ($actualTypeCode !== $expectedTypeCode) { BinaryUtils::typeCastError($actualTypeCode, $expectedTypeCode); } @@ -419,6 +422,15 @@ class BinaryUtils throw new ClientException($msg); } + public static function enumSerializationError(bool $serialize, string $message = null): void + { + $msg = $serialize ? 'Enum item can not be serialized' : 'Enum item can not be deserialized'; + if ($message) { + $msg = $msg . ': ' . $message; + } + throw new ClientException($msg); + } + public static function typeCastError($fromType, $toType): void { throw new ClientException(sprintf('Type "%s" can not be cast to %s', diff --git a/tests/CachePutGetTest.php b/tests/CachePutGetTest.php index 9d15ab2..c3ff1e9 100644 --- a/tests/CachePutGetTest.php +++ b/tests/CachePutGetTest.php @@ -18,14 +18,20 @@ namespace Apache\Ignite\Tests; +use \DateTime; use Ds\Map; use Ds\Set; use PHPUnit\Framework\TestCase; +use Apache\Ignite\Type\ObjectType; use Apache\Ignite\Type\MapObjectType; use Apache\Ignite\Type\CollectionObjectType; use Apache\Ignite\Type\ObjectArrayType; use Apache\Ignite\Type\ComplexObjectType; use Apache\Ignite\Data\BinaryObject; +use Apache\Ignite\Data\Date; +use Apache\Ignite\Data\Timestamp; +use Apache\Ignite\Data\EnumItem; +use Apache\Ignite\Exception\ClientException; class TstComplObjectWithPrimitiveFields { @@ -490,6 +496,119 @@ final class CachePutGetTestCase extends TestCase $this->putGetObjectArrays(new ObjectArrayType(new ObjectArrayType(new ComplexObjectType())), $array); } + public function testPutGetDateTime(): void + { + $this->putGetDate("Y-m-d H:i:s", "2018-10-19 18:31:13", 0); + $this->putGetDate("Y-m-d H:i:s", "2018-10-19 18:31:13", 29726); + $this->putGetDate("Y-m-d H:i:s", "2018-10-19 18:31:13", 999999); + + $this->putGetTimestamp("Y-m-d H:i:s", "2018-10-19 18:31:13", 0); + $this->putGetTimestamp("Y-m-d H:i:s", "2018-10-19 18:31:13", 29726000); + $this->putGetTimestamp("Y-m-d H:i:s", "2018-10-19 18:31:13", 999999999); + + $this->putGetTimestampFromDateTime("Y-m-d H:i:s", "2018-10-19 18:31:13", 0); + $this->putGetTimestampFromDateTime("Y-m-d H:i:s", "2018-10-19 18:31:13", 29726); + $this->putGetTimestampFromDateTime("Y-m-d H:i:s", "2018-10-19 18:31:13", 999999); + } + + public function testPutEnumItems(): void + { + $fakeTypeId = 12345; + $enumItem1 = new EnumItem($fakeTypeId); + $enumItem1->setOrdinal(1); + $this->putEnumItem($enumItem1, null); + $this->putEnumItem($enumItem1, ObjectType::ENUM); + $enumItem2 = new EnumItem($fakeTypeId); + $enumItem2->setName('name'); + $this->putEnumItem($enumItem2, null); + $this->putEnumItem($enumItem2, ObjectType::ENUM); + $enumItem3 = new EnumItem($fakeTypeId); + $enumItem3->setOrdinal(2); + $this->putEnumItem($enumItem3, null); + $this->putEnumItem($enumItem3, ObjectType::ENUM); + } + + private function putEnumItem($value, $valueType): void + { + $key = microtime(); + self::$cache-> + setKeyType(null)-> + setValueType($valueType); + // Enums registration is not supported by the client, therefore put EnumItem must throw ClientException + try { + self::$cache->put($key, $value); + $this->fail('put EnumItem must throw ClientException'); + } catch (ClientException $e) { + $this->assertContains('Enum item can not be serialized', $e->getMessage()); + } finally { + self::$cache->removeAll(); + } + } + + private function putGetDate(string $format, string $dateString, int $micros): void + { + $key = microtime(); + self::$cache-> + setKeyType(null)-> + setValueType(ObjectType::DATE); + try { + $dt = DateTime::createFromFormat("$format.u", sprintf("%s.%06d", $dateString, $micros)); + $iDate = Date::fromDateTime($dt); + self::$cache->put($key, $iDate); + $result = self::$cache->get($key); + + $this->assertEquals(sprintf("%06d", intval($micros / 1000) * 1000), $result->toDateTime()->format('u')); + $this->assertEquals($dateString, $result->toDateTime()->format($format)); + } finally { + self::$cache->removeAll(); + } + } + + private function putGetTimestamp(string $format, string $dateString, int $nanos): void + { + $key = microtime(); + self::$cache-> + setKeyType(null)-> + setValueType(ObjectType::TIMESTAMP); + + try { + $millis = intval($nanos / 1000000); + $nanosInMillis = $nanos % 1000000; + self::$cache->put($key, + new Timestamp( + DateTime::createFromFormat($format, $dateString)->getTimestamp() * 1000 + $millis, + $nanosInMillis + ) + ); + $result = self::$cache->get($key); + + $this->assertEquals($nanos % 1000000, $result->getNanos()); + $this->assertEquals($dateString, $result->toDateTime()->format($format)); + } finally { + self::$cache->removeAll(); + } + } + + private function putGetTimestampFromDateTime(string $format, string $dateString, $micros): void + { + $key = microtime(); + self::$cache-> + setKeyType(null)-> + setValueType(ObjectType::TIMESTAMP); + + try { + self::$cache->put($key, Timestamp::fromDateTime( + DateTime::createFromFormat("$format.u", sprintf("%s.%06d", $dateString, $micros)) + )); + $result = self::$cache->get($key); + + $this->assertEquals(intval($micros / 1000) * 1000, $result->toDateTime()->format('u')); + $this->assertEquals($dateString, $result->toDateTime()->format($format)); + } finally { + self::$cache->removeAll(); + } + } + private function putGetObjectArrays(?ObjectArrayType $arrayType, array $value): void { $key = microtime();
