You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by is...@apache.org on 2018/10/29 12:50:03 UTC
ignite git commit: IGNITE-10022: JS,
PHP thin clients: a more meaningful exception when ENUM type is not
registered
Repository: ignite
Updated Branches:
refs/heads/master 862c9264f -> 2ad04930d
IGNITE-10022: JS, PHP thin clients: a more meaningful exception when
ENUM type is not registered
This closes #5187
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/2ad04930
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/2ad04930
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/2ad04930
Branch: refs/heads/master
Commit: 2ad04930dd5854c4272fb347858292e464daa83d
Parents: 862c926
Author: ekaterina-nbl <ek...@nobitlost.com>
Authored: Mon Oct 29 15:49:33 2018 +0300
Committer: Igor Sapego <is...@apache.org>
Committed: Mon Oct 29 15:49:33 2018 +0300
----------------------------------------------------------------------
modules/platforms/nodejs/lib/EnumItem.js | 17 ++-
modules/platforms/nodejs/lib/Errors.js | 12 ++
.../nodejs/lib/internal/BinaryUtils.js | 4 +
modules/platforms/nodejs/spec/TestingHelper.js | 7 ++
.../spec/cache/CachePutGetDiffTypes.spec.js | 39 ++++++
.../Internal/Binary/BinaryCommunicator.php | 27 +++--
.../Ignite/Internal/Binary/BinaryUtils.php | 12 ++
modules/platforms/php/tests/CachePutGetTest.php | 119 +++++++++++++++++++
8 files changed, 221 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ad04930/modules/platforms/nodejs/lib/EnumItem.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/lib/EnumItem.js b/modules/platforms/nodejs/lib/EnumItem.js
index 1d1725e..5e80da9 100644
--- a/modules/platforms/nodejs/lib/EnumItem.js
+++ b/modules/platforms/nodejs/lib/EnumItem.js
@@ -17,6 +17,7 @@
'use strict';
+const Util = require('util');
const ArgumentChecker = require('./internal/ArgumentChecker');
const Errors = require('./Errors');
@@ -157,14 +158,18 @@ class EnumItem {
* @ignore
*/
async _write(communicator, buffer) {
+ const type = await this._getType(communicator, this._typeId);
+ if (!type || !type._isEnum) {
+ throw Errors.IgniteClientError.enumSerializationError(
+ true, Util.format('enum type id "%d" is not registered', this._typeId));
+ }
buffer.writeInteger(this._typeId);
if (this._ordinal !== null) {
buffer.writeInteger(this._ordinal);
return;
}
else if (this._name !== null || this._value !== null) {
- const type = await this._getType(communicator, this._typeId);
- if (type._isEnum && type._enumValues) {
+ if (type._enumValues) {
for (let i = 0; i < type._enumValues.length; i++) {
if (this._name === type._enumValues[i][0] ||
this._value === type._enumValues[i][1]) {
@@ -185,8 +190,12 @@ class EnumItem {
this._typeId = buffer.readInteger();
this._ordinal = buffer.readInteger();
const type = await this._getType(communicator, this._typeId);
- if (!type._isEnum || !type._enumValues || type._enumValues.length <= this._ordinal) {
- throw new Errors.IgniteClientError('EnumItem can not be deserialized: type mismatch');
+ if (!type || !type._isEnum) {
+ throw Errors.IgniteClientError.enumSerializationError(
+ false, Util.format('enum type id "%d" is not registered', this._typeId));
+ }
+ else if (!type._enumValues || type._enumValues.length <= this._ordinal) {
+ throw Errors.IgniteClientError.enumSerializationError(false, 'type mismatch');
}
this._name = type._enumValues[this._ordinal][0];
this._value = type._enumValues[this._ordinal][1];
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ad04930/modules/platforms/nodejs/lib/Errors.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/lib/Errors.js b/modules/platforms/nodejs/lib/Errors.js
index 57a7a8c..89baf38 100644
--- a/modules/platforms/nodejs/lib/Errors.js
+++ b/modules/platforms/nodejs/lib/Errors.js
@@ -83,6 +83,18 @@ class IgniteClientError extends Error {
}
return new IgniteClientError(msg);
}
+
+ /**
+ * EnumItem serialization/deserialization errors.
+ * @ignore
+ */
+ static enumSerializationError(serialize, message = null) {
+ let msg = serialize ? 'Enum item can not be serialized' : 'Enum item can not be deserialized';
+ if (message) {
+ msg = msg + ': ' + message;
+ }
+ return new IgniteClientError(msg);
+ }
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ad04930/modules/platforms/nodejs/lib/internal/BinaryUtils.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/lib/internal/BinaryUtils.js b/modules/platforms/nodejs/lib/internal/BinaryUtils.js
index 2619df7..fe1e403 100644
--- a/modules/platforms/nodejs/lib/internal/BinaryUtils.js
+++ b/modules/platforms/nodejs/lib/internal/BinaryUtils.js
@@ -497,6 +497,10 @@ class BinaryUtils {
expectedTypeCode === BinaryUtils.TYPE_CODE.COMPLEX_OBJECT) {
return;
}
+ else if (expectedTypeCode === BinaryUtils.TYPE_CODE.ENUM &&
+ actualTypeCode === BinaryUtils.TYPE_CODE.BINARY_ENUM) {
+ return;
+ }
else if (actualTypeCode !== expectedTypeCode) {
throw Errors.IgniteClientError.typeCastError(actualTypeCode, expectedTypeCode);
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ad04930/modules/platforms/nodejs/spec/TestingHelper.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/spec/TestingHelper.js b/modules/platforms/nodejs/spec/TestingHelper.js
index 79a5336..78df0cb 100644
--- a/modules/platforms/nodejs/spec/TestingHelper.js
+++ b/modules/platforms/nodejs/spec/TestingHelper.js
@@ -232,6 +232,13 @@ class TestingHelper {
TestingHelper.checkError(error, Errors.IgniteClientError, done)
}
+ static checkEnumItemSerializationError(error, done) {
+ if (!(error instanceof Errors.IgniteClientError) ||
+ error.message.indexOf('Enum item can not be serialized') < 0) {
+ done.fail('unexpected error: ' + error);
+ }
+ }
+
static checkError(error, errorType, done) {
if (!(error instanceof errorType)) {
done.fail('unexpected error: ' + error);
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ad04930/modules/platforms/nodejs/spec/cache/CachePutGetDiffTypes.spec.js
----------------------------------------------------------------------
diff --git a/modules/platforms/nodejs/spec/cache/CachePutGetDiffTypes.spec.js b/modules/platforms/nodejs/spec/cache/CachePutGetDiffTypes.spec.js
index 28a9ae3..a6e1bba 100644
--- a/modules/platforms/nodejs/spec/cache/CachePutGetDiffTypes.spec.js
+++ b/modules/platforms/nodejs/spec/cache/CachePutGetDiffTypes.spec.js
@@ -543,6 +543,45 @@ describe('cache put get test suite >', () => {
catch(error => done.fail(error));
});
+ it('put enum items', (done) => {
+ Promise.resolve().
+ then(async () => {
+ const fakeTypeId = 12345;
+ const enumItem1 = new EnumItem(fakeTypeId);
+ enumItem1.setOrdinal(1);
+ await putEnumItem(enumItem1, null, done);
+ await putEnumItem(enumItem1, ObjectType.PRIMITIVE_TYPE.ENUM, done);
+ const enumItem2 = new EnumItem(fakeTypeId);
+ enumItem2.setName('name');
+ await putEnumItem(enumItem2, null, done);
+ await putEnumItem(enumItem2, ObjectType.PRIMITIVE_TYPE.ENUM, done);
+ const enumItem3 = new EnumItem(fakeTypeId);
+ enumItem3.setValue(2);
+ await putEnumItem(enumItem3, null, done);
+ await putEnumItem(enumItem3, ObjectType.PRIMITIVE_TYPE.ENUM, done);
+ }).
+ then(done).
+ catch(error => done.fail(error));
+ });
+
+ async function putEnumItem(value, valueType, done) {
+ const cache = igniteClient.getCache(CACHE_NAME).
+ setKeyType(null).
+ setValueType(valueType);
+ const key = new Date();
+ // Enums registration is not supported by the client, therefore put EnumItem must throw IgniteClientError
+ try {
+ await cache.put(key, value);
+ done.fail('put EnumItem must throw IgniteClientError');
+ }
+ catch (err) {
+ TestingHelper.checkEnumItemSerializationError(err, done);
+ }
+ finally {
+ await cache.removeAll();
+ }
+ }
+
async function putGetPrimitiveValues(keyType, valueType, key, value, modificator) {
const cache = await igniteClient.getCache(CACHE_NAME).
setKeyType(keyType).
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ad04930/modules/platforms/php/src/Apache/Ignite/Internal/Binary/BinaryCommunicator.php
----------------------------------------------------------------------
diff --git a/modules/platforms/php/src/Apache/Ignite/Internal/Binary/BinaryCommunicator.php b/modules/platforms/php/src/Apache/Ignite/Internal/Binary/BinaryCommunicator.php
index 520063c..781a730 100644
--- a/modules/platforms/php/src/Apache/Ignite/Internal/Binary/BinaryCommunicator.php
+++ b/modules/platforms/php/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;
}
}
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ad04930/modules/platforms/php/src/Apache/Ignite/Internal/Binary/BinaryUtils.php
----------------------------------------------------------------------
diff --git a/modules/platforms/php/src/Apache/Ignite/Internal/Binary/BinaryUtils.php b/modules/platforms/php/src/Apache/Ignite/Internal/Binary/BinaryUtils.php
index ad0bf56..e9ff2f1 100644
--- a/modules/platforms/php/src/Apache/Ignite/Internal/Binary/BinaryUtils.php
+++ b/modules/platforms/php/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',
http://git-wip-us.apache.org/repos/asf/ignite/blob/2ad04930/modules/platforms/php/tests/CachePutGetTest.php
----------------------------------------------------------------------
diff --git a/modules/platforms/php/tests/CachePutGetTest.php b/modules/platforms/php/tests/CachePutGetTest.php
index 9d15ab2..c3ff1e9 100644
--- a/modules/platforms/php/tests/CachePutGetTest.php
+++ b/modules/platforms/php/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();