Return-Path: X-Original-To: archive-asf-public-internal@cust-asf2.ponee.io Delivered-To: archive-asf-public-internal@cust-asf2.ponee.io Received: from cust-asf.ponee.io (cust-asf.ponee.io [163.172.22.183]) by cust-asf2.ponee.io (Postfix) with ESMTP id CDAF2200C48 for ; Thu, 6 Apr 2017 15:31:17 +0200 (CEST) Received: by cust-asf.ponee.io (Postfix) id CC678160B84; Thu, 6 Apr 2017 13:31:17 +0000 (UTC) Delivered-To: archive-asf-public@cust-asf.ponee.io Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by cust-asf.ponee.io (Postfix) with SMTP id B51CD160BAB for ; Thu, 6 Apr 2017 15:31:13 +0200 (CEST) Received: (qmail 95559 invoked by uid 500); 6 Apr 2017 13:31:12 -0000 Mailing-List: contact commits-help@ignite.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@ignite.apache.org Delivered-To: mailing list commits@ignite.apache.org Received: (qmail 94824 invoked by uid 99); 6 Apr 2017 13:31:10 -0000 Received: from git1-us-west.apache.org (HELO git1-us-west.apache.org) (140.211.11.23) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 06 Apr 2017 13:31:10 +0000 Received: by git1-us-west.apache.org (ASF Mail Server at git1-us-west.apache.org, from userid 33) id 3B7D7E9809; Thu, 6 Apr 2017 13:31:09 +0000 (UTC) Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: sboikov@apache.org To: commits@ignite.apache.org Date: Thu, 06 Apr 2017 13:31:22 -0000 Message-Id: <1b6564449126436eafb27daa89ec3234@git.apache.org> In-Reply-To: <358816612602444bb6656810c8375230@git.apache.org> References: <358816612602444bb6656810c8375230@git.apache.org> X-Mailer: ASF-Git Admin Mailer Subject: [15/50] [abbrv] ignite git commit: IGNITE-2703 .NET: Dynamic type registration archived-at: Thu, 06 Apr 2017 13:31:18 -0000 IGNITE-2703 .NET: Dynamic type registration * BinaryTypeConfiguration is not required anymore * Serializable types are written in Ignite binary format Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/79bac4f8 Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/79bac4f8 Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/79bac4f8 Branch: refs/heads/ignite-2893 Commit: 79bac4f87b15081d44e096d5bfc2c22854aad20e Parents: 2ad2365 Author: Pavel Tupitsyn Authored: Fri Mar 31 16:31:56 2017 +0300 Committer: Pavel Tupitsyn Committed: Fri Mar 31 16:31:56 2017 +0300 ---------------------------------------------------------------------- .../ignite/internal/MarshallerPlatformIds.java | 3 + .../ignite/internal/binary/BinaryUtils.java | 4 + .../platform/PlatformContextImpl.java | 10 +- .../binary/PlatformBinaryProcessor.java | 40 +- .../Apache.Ignite.Core.Tests.csproj | 11 +- .../Binary/BinaryBuilderSelfTest.cs | 112 +-- .../BinaryBuilderSelfTestDynamicRegistration.cs | 40 + .../Binary/BinaryCompactFooterInteropTest.cs | 2 +- .../Binary/BinaryDynamicRegistrationTest.cs | 441 +++++++++++ .../Binary/BinarySelfTest.cs | 197 +++-- .../Binary/BinarySelfTestFullFooter.cs | 5 +- .../Binary/JavaBinaryInteropTest.cs | 182 +++++ .../Serializable/AdvancedSerializationTest.cs | 228 ++++++ .../BasicSerializableObjectsTest.cs | 124 +++ .../Binary/Serializable/CallbacksTest.cs | 369 +++++++++ .../Binary/Serializable/DelegatesTest.cs | 161 ++++ .../Binary/Serializable/ObjectReferenceTests.cs | 131 ++++ .../Binary/Serializable/PrimitivesTest.cs | 754 +++++++++++++++++++ .../Binary/Serializable/SqlDmlTest.cs | 277 +++++++ .../Cache/Affinity/AffinityFunctionTest.cs | 21 - .../Cache/CacheAbstractTest.cs | 56 +- .../Cache/Query/CacheQueriesTest.cs | 13 +- .../Continuous/ContinuousQueryAbstractTest.cs | 15 +- .../Cache/Store/CacheStoreTest.cs | 5 +- .../Compute/ComputeApiTest.cs | 28 +- .../Compute/IgniteExceptionTaskSelfTest.cs | 40 +- .../Compute/ResourceTaskTest.cs | 13 +- .../Apache.Ignite.Core.Tests/DeploymentTest.cs | 16 +- .../Examples/ExamplesTest.cs | 2 +- .../Apache.Ignite.Core.Tests/ExecutableTest.cs | 28 +- .../SerializationTest.cs | 240 ------ .../Services/ServiceProxyTest.cs | 40 +- .../Apache.Ignite.Core.Tests/TestUtils.cs | 11 + .../Apache.Ignite.Core.csproj | 7 +- .../Cache/Configuration/CacheConfiguration.cs | 8 +- .../Apache.Ignite.Core/IgniteConfiguration.cs | 25 +- .../dotnet/Apache.Ignite.Core/Ignition.cs | 4 +- .../Impl/Binary/BinarizableSerializer.cs | 5 +- .../Impl/Binary/BinaryFullTypeDescriptor.cs | 49 +- .../Impl/Binary/BinaryObjectBuilder.cs | 27 +- .../Impl/Binary/BinaryObjectHeader.cs | 13 +- .../Impl/Binary/BinaryObjectSchemaSerializer.cs | 2 + .../Impl/Binary/BinaryProcessor.cs | 38 +- .../Impl/Binary/BinaryReader.cs | 39 +- .../Impl/Binary/BinaryReflectiveActions.cs | 2 +- .../BinaryReflectiveSerializerInternal.cs | 84 ++- .../Binary/BinarySurrogateTypeDescriptor.cs | 13 +- .../Impl/Binary/BinarySystemHandlers.cs | 96 +-- .../Impl/Binary/BinarySystemTypeSerializer.cs | 2 +- .../Impl/Binary/BinaryUtils.cs | 54 +- .../Impl/Binary/BinaryWriter.cs | 242 +++--- .../Impl/Binary/DateTimeHolder.cs | 101 --- .../Impl/Binary/DateTimeSerializer.cs | 48 -- .../Binary/DeserializationCallbackProcessor.cs | 102 +++ .../Impl/Binary/IBinarySerializerInternal.cs | 4 +- .../Impl/Binary/IBinaryTypeDescriptor.cs | 8 + .../Impl/Binary/Io/BinaryStreamAdapter.cs | 119 --- .../Impl/Binary/Marshaller.cs | 248 ++++-- .../Impl/Binary/ReflectionUtils.cs | 50 ++ .../Impl/Binary/SerializableObjectHolder.cs | 96 --- .../Impl/Binary/SerializableSerializer.cs | 656 +++++++++++++++- .../Impl/Binary/TypeResolver.cs | 7 + .../Impl/Binary/UserSerializerProxy.cs | 5 +- .../Affinity/AffinityFunctionSerializer.cs | 3 - .../Apache.Ignite.Core/Impl/Cache/CacheImpl.cs | 3 +- .../Common/CopyOnWriteConcurrentDictionary.cs | 35 + .../Impl/Common/DelegateConverter.cs | 90 ++- .../Impl/Common/DelegateTypeDescriptor.cs | 3 +- .../Impl/Common/SerializableTypeDescriptor.cs | 222 ++++++ .../dotnet/Apache.Ignite.Core/Impl/Ignite.cs | 13 +- .../Impl/Services/ServiceProxySerializer.cs | 4 +- .../Impl/Unmanaged/UnmanagedCallbacks.cs | 8 +- .../NuGet/LINQPad/ComputeExample.linq | 1 - .../NuGet/LINQPad/PutGetExample.linq | 5 +- .../NuGet/LINQPad/QueryExample.linq | 5 +- .../NuGet/LINQPad/QueryExample.linq | 5 +- .../examples/Apache.Ignite.Examples/App.config | 16 +- .../Apache.Ignite.ExamplesDll/Binary/Address.cs | 2 - .../Compute/CharacterCountClosure.cs | 1 - .../Datagrid/ContinuousQueryFilter.cs | 2 - .../Datagrid/EmployeeStorePredicate.cs | 2 - .../Messaging/RemoteOrderedListener.cs | 1 - .../Messaging/RemoteUnorderedListener.cs | 1 - .../Services/MapService.cs | 1 - 84 files changed, 4956 insertions(+), 1240 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/core/src/main/java/org/apache/ignite/internal/MarshallerPlatformIds.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/MarshallerPlatformIds.java b/modules/core/src/main/java/org/apache/ignite/internal/MarshallerPlatformIds.java index 458ae49..4167f41 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/MarshallerPlatformIds.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/MarshallerPlatformIds.java @@ -25,6 +25,9 @@ public final class MarshallerPlatformIds { public static final byte JAVA_ID = 0; /** */ + public static final byte DOTNET_ID = 1; + + /** */ private MarshallerPlatformIds() { } } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java index c59b8b7..e4011a4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/binary/BinaryUtils.java @@ -110,6 +110,10 @@ public class BinaryUtils { /** Flag: compact footer, no field IDs. */ public static final short FLAG_COMPACT_FOOTER = 0x0020; + /** Flag: raw data contains .NET type information. Always 0 in Java. Keep it here for information only. */ + @SuppressWarnings("unused") + public static final short FLAG_CUSTOM_DOTNET_TYPE = 0x0040; + /** Offset which fits into 1 byte. */ public static final int OFFSET_1 = 1; http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java index 10a8f74..bdcb88c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/PlatformContextImpl.java @@ -430,10 +430,12 @@ public class PlatformContextImpl implements PlatformContext { if (schema == null) { BinaryTypeImpl meta = (BinaryTypeImpl)cacheObjProc.metadata(typeId); - for (BinarySchema typeSchema : meta.metadata().schemas()) { - if (schemaId == typeSchema.schemaId()) { - schema = typeSchema; - break; + if (meta != null) { + for (BinarySchema typeSchema : meta.metadata().schemas()) { + if (schemaId == typeSchema.schemaId()) { + schema = typeSchema; + break; + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java index 3c00abc..8d95ac8 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/platform/binary/PlatformBinaryProcessor.java @@ -18,6 +18,8 @@ package org.apache.ignite.internal.processors.platform.binary; import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.internal.MarshallerPlatformIds; import org.apache.ignite.internal.binary.BinaryRawReaderEx; import org.apache.ignite.internal.binary.BinaryRawWriterEx; import org.apache.ignite.internal.processors.platform.PlatformAbstractTarget; @@ -39,6 +41,12 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget { /** */ private static final int OP_GET_SCHEMA = 4; + /** */ + private static final int OP_REGISTER_TYPE = 5; + + /** */ + private static final int OP_GET_TYPE = 6; + /** * Constructor. * @@ -50,10 +58,20 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget { /** {@inheritDoc} */ @Override public long processInStreamOutLong(int type, BinaryRawReaderEx reader) throws IgniteCheckedException { - if (type == OP_PUT_META) { - platformCtx.processMetadata(reader); + switch (type) { + case OP_PUT_META: + platformCtx.processMetadata(reader); + + return TRUE; + + case OP_REGISTER_TYPE: { + int typeId = reader.readInt(); + String typeName = reader.readString(); - return TRUE; + return platformContext().kernalContext().marshallerContext() + .registerClassName(MarshallerPlatformIds.DOTNET_ID, typeId, typeName) + ? TRUE : FALSE; + } } return super.processInStreamOutLong(type, reader); @@ -88,6 +106,22 @@ public class PlatformBinaryProcessor extends PlatformAbstractTarget { break; } + case OP_GET_TYPE: { + int typeId = reader.readInt(); + + try { + String typeName = platformContext().kernalContext().marshallerContext() + .getClassName(MarshallerPlatformIds.DOTNET_ID, typeId); + + writer.writeString(typeName); + } + catch (ClassNotFoundException e) { + throw new BinaryObjectException(e); + } + + break; + } + default: super.processInStreamOutStream(type, reader, writer); break; http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj index 1540243..27aec9c 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Apache.Ignite.Core.Tests.csproj @@ -69,9 +69,17 @@ + + + + + + + + @@ -103,6 +111,7 @@ + @@ -190,7 +199,7 @@ - + http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs index e59611b..35c7e47 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTest.cs @@ -56,36 +56,7 @@ namespace Apache.Ignite.Core.Tests.Binary { BinaryConfiguration = new BinaryConfiguration { - TypeConfigurations = new List - { - new BinaryTypeConfiguration(typeof(Empty)), - new BinaryTypeConfiguration(typeof(Primitives)), - new BinaryTypeConfiguration(typeof(PrimitiveArrays)), - new BinaryTypeConfiguration(typeof(StringDateGuidEnum)), - new BinaryTypeConfiguration(typeof(WithRaw)), - new BinaryTypeConfiguration(typeof(MetaOverwrite)), - new BinaryTypeConfiguration(typeof(NestedOuter)), - new BinaryTypeConfiguration(typeof(NestedInner)), - new BinaryTypeConfiguration(typeof(MigrationOuter)), - new BinaryTypeConfiguration(typeof(MigrationInner)), - new BinaryTypeConfiguration(typeof(InversionOuter)), - new BinaryTypeConfiguration(typeof(InversionInner)), - new BinaryTypeConfiguration(typeof(CompositeOuter)), - new BinaryTypeConfiguration(typeof(CompositeInner)), - new BinaryTypeConfiguration(typeof(CompositeArray)), - new BinaryTypeConfiguration(typeof(CompositeContainer)), - new BinaryTypeConfiguration(typeof(ToBinary)), - new BinaryTypeConfiguration(typeof(Remove)), - new BinaryTypeConfiguration(typeof(RemoveInner)), - new BinaryTypeConfiguration(typeof(BuilderInBuilderOuter)), - new BinaryTypeConfiguration(typeof(BuilderInBuilderInner)), - new BinaryTypeConfiguration(typeof(BuilderCollection)), - new BinaryTypeConfiguration(typeof(BuilderCollectionItem)), - new BinaryTypeConfiguration(typeof(DecimalHolder)), - new BinaryTypeConfiguration(TypeEmpty), - new BinaryTypeConfiguration(typeof(TestEnumRegistered)), - new BinaryTypeConfiguration(typeof(NameMapperTestType)) - }, + TypeConfigurations = GetTypeConfigurations(), DefaultIdMapper = new IdMapper(), DefaultNameMapper = new NameMapper(), CompactFooter = GetCompactFooter() @@ -98,6 +69,43 @@ namespace Apache.Ignite.Core.Tests.Binary } /// + /// Gets the type configurations. + /// + protected virtual ICollection GetTypeConfigurations() + { + return new[] + { + new BinaryTypeConfiguration(typeof(Empty)), + new BinaryTypeConfiguration(typeof(Primitives)), + new BinaryTypeConfiguration(typeof(PrimitiveArrays)), + new BinaryTypeConfiguration(typeof(StringDateGuidEnum)), + new BinaryTypeConfiguration(typeof(WithRaw)), + new BinaryTypeConfiguration(typeof(MetaOverwrite)), + new BinaryTypeConfiguration(typeof(NestedOuter)), + new BinaryTypeConfiguration(typeof(NestedInner)), + new BinaryTypeConfiguration(typeof(MigrationOuter)), + new BinaryTypeConfiguration(typeof(MigrationInner)), + new BinaryTypeConfiguration(typeof(InversionOuter)), + new BinaryTypeConfiguration(typeof(InversionInner)), + new BinaryTypeConfiguration(typeof(CompositeOuter)), + new BinaryTypeConfiguration(typeof(CompositeInner)), + new BinaryTypeConfiguration(typeof(CompositeArray)), + new BinaryTypeConfiguration(typeof(CompositeContainer)), + new BinaryTypeConfiguration(typeof(ToBinary)), + new BinaryTypeConfiguration(typeof(Remove)), + new BinaryTypeConfiguration(typeof(RemoveInner)), + new BinaryTypeConfiguration(typeof(BuilderInBuilderOuter)), + new BinaryTypeConfiguration(typeof(BuilderInBuilderInner)), + new BinaryTypeConfiguration(typeof(BuilderCollection)), + new BinaryTypeConfiguration(typeof(BuilderCollectionItem)), + new BinaryTypeConfiguration(typeof(DecimalHolder)), + new BinaryTypeConfiguration(TypeEmpty), + new BinaryTypeConfiguration(typeof(TestEnumRegistered)), + new BinaryTypeConfiguration(typeof(NameMapperTestType)) + }; + } + + /// /// Gets the compact footer setting. /// protected virtual bool GetCompactFooter() @@ -213,7 +221,7 @@ namespace Apache.Ignite.Core.Tests.Binary // 2. Special types. Assert.AreEqual("a", api.ToBinary("a")); - Assert.AreEqual(date, api.ToBinary(date)); + Assert.AreEqual(date, api.ToBinary(date).Deserialize()); Assert.AreEqual(guid, api.ToBinary(guid)); Assert.AreEqual(TestEnumRegistered.One, api.ToBinary(TestEnumRegistered.One) .Deserialize()); @@ -231,7 +239,8 @@ namespace Apache.Ignite.Core.Tests.Binary Assert.AreEqual(new[] { 'a' }, api.ToBinary(new[] { 'a' })); Assert.AreEqual(new[] { "a" }, api.ToBinary(new[] { "a" })); - Assert.AreEqual(new[] { date }, api.ToBinary(new[] { date })); + Assert.AreEqual(new[] {date}, api.ToBinary(new[] {date}) + .Select(x => x.Deserialize())); Assert.AreEqual(new[] { guid }, api.ToBinary(new[] { guid })); Assert.AreEqual(new[] { TestEnumRegistered.One}, api.ToBinary(new[] { TestEnumRegistered.One}) @@ -619,6 +628,11 @@ namespace Apache.Ignite.Core.Tests.Binary CheckPrimitiveFields1(binObj); + // Rebuild unchanged. + binObj = binObj.ToBuilder().Build(); + + CheckPrimitiveFields1(binObj); + // Specific setter methods. var binObj2 = _grid.GetBinary().GetBuilder(typeof(Primitives)) .SetByteField("fByte", 1) @@ -766,6 +780,11 @@ namespace Apache.Ignite.Core.Tests.Binary CheckPrimitiveArrayFields1(binObj); + // Rebuild unchanged. + binObj = binObj.ToBuilder().Build(); + + CheckPrimitiveArrayFields1(binObj); + // Specific setters. var binObj2 = _grid.GetBinary().GetBuilder(typeof(PrimitiveArrays)) .SetByteArrayField("fByte", new byte[] {1}) @@ -814,7 +833,7 @@ namespace Apache.Ignite.Core.Tests.Binary .Build(); CheckPrimitiveArrayFields2(binObj); - + // Check equality. Assert.AreEqual(binObj, binObj2); Assert.AreEqual(binObj.GetHashCode(), binObj2.GetHashCode()); @@ -918,6 +937,11 @@ namespace Apache.Ignite.Core.Tests.Binary CheckStringDateGuidEnum1(binObj, nDate, nGuid); + // Rebuild with no changes. + binObj = binObj.ToBuilder().Build(); + + CheckStringDateGuidEnum1(binObj, nDate, nGuid); + // Specific setters. var binObj2 = _grid.GetBinary().GetBuilder(typeof(StringDateGuidEnum)) .SetStringField("fStr", "str") @@ -1001,12 +1025,13 @@ namespace Apache.Ignite.Core.Tests.Binary Assert.AreEqual(BinaryTypeNames.TypeNameArrayEnum, meta.GetFieldTypeName("fEnumArr")); Assert.AreEqual("str", binObj.GetField("fStr")); - Assert.AreEqual(nDate, binObj.GetField("fNDate")); + Assert.AreEqual(nDate, binObj.GetField("fNDate").Deserialize()); Assert.AreEqual(nDate, binObj.GetField("fNTimestamp")); Assert.AreEqual(nGuid, binObj.GetField("fNGuid")); Assert.AreEqual(TestEnum.One, binObj.GetField("fEnum").Deserialize()); Assert.AreEqual(new[] {"str"}, binObj.GetField("fStrArr")); - Assert.AreEqual(new[] {nDate}, binObj.GetField("fDateArr")); + Assert.AreEqual(new[] {nDate}, binObj.GetField("fDateArr") + .Select(x => x.Deserialize())); Assert.AreEqual(new[] {nDate}, binObj.GetField("fTimestampArr")); Assert.AreEqual(new[] {nGuid}, binObj.GetField("fGuidArr")); Assert.AreEqual(new[] {TestEnum.One}, @@ -1028,12 +1053,13 @@ namespace Apache.Ignite.Core.Tests.Binary var builder = _grid.GetBinary().GetBuilder(binObj); Assert.AreEqual("str", builder.GetField("fStr")); - Assert.AreEqual(nDate, builder.GetField("fNDate")); + Assert.AreEqual(nDate, builder.GetField("fNDate").Build().Deserialize()); Assert.AreEqual(nDate, builder.GetField("fNTimestamp")); Assert.AreEqual(nGuid, builder.GetField("fNGuid")); Assert.AreEqual(TestEnum.One, builder.GetField("fEnum").Deserialize()); Assert.AreEqual(new[] {"str"}, builder.GetField("fStrArr")); - Assert.AreEqual(new[] {nDate}, builder.GetField("fDateArr")); + Assert.AreEqual(new[] {nDate}, builder.GetField("fDateArr") + .Select(x => x.Build().Deserialize())); Assert.AreEqual(new[] {nDate}, builder.GetField("fTimestampArr")); Assert.AreEqual(new[] {nGuid}, builder.GetField("fGuidArr")); Assert.AreEqual(new[] {TestEnum.One}, @@ -1043,12 +1069,13 @@ namespace Apache.Ignite.Core.Tests.Binary binObj = builder.Build(); Assert.AreEqual("str", binObj.GetField("fStr")); - Assert.AreEqual(nDate, binObj.GetField("fNDate")); + Assert.AreEqual(nDate, binObj.GetField("fNDate").Deserialize()); Assert.AreEqual(nDate, binObj.GetField("fNTimestamp")); Assert.AreEqual(nGuid, binObj.GetField("fNGuid")); Assert.AreEqual(TestEnum.One, binObj.GetField("fEnum").Deserialize()); Assert.AreEqual(new[] {"str"}, binObj.GetField("fStrArr")); - Assert.AreEqual(new[] {nDate}, binObj.GetField("fDateArr")); + Assert.AreEqual(new[] {nDate}, binObj.GetField("fDateArr") + .Select(x => x.Deserialize())); Assert.AreEqual(new[] {nDate}, binObj.GetField("fTimestampArr")); Assert.AreEqual(new[] {nGuid}, binObj.GetField("fGuidArr")); Assert.AreEqual(new[] { TestEnum.One }, @@ -1073,12 +1100,13 @@ namespace Apache.Ignite.Core.Tests.Binary private static void CheckStringDateGuidEnum2(IBinaryObject binObj, DateTime? nDate, Guid? nGuid) { Assert.AreEqual("str2", binObj.GetField("fStr")); - Assert.AreEqual(nDate, binObj.GetField("fNDate")); + Assert.AreEqual(nDate, binObj.GetField("fNDate").Deserialize()); Assert.AreEqual(nDate, binObj.GetField("fNTimestamp")); Assert.AreEqual(nGuid, binObj.GetField("fNGuid")); Assert.AreEqual(TestEnum.Two, binObj.GetField("fEnum").Deserialize()); Assert.AreEqual(new[] { "str2" }, binObj.GetField("fStrArr")); - Assert.AreEqual(new[] { nDate }, binObj.GetField("fDateArr")); + Assert.AreEqual(new[] {nDate}, binObj.GetField("fDateArr") + .Select(x => x.Deserialize())); Assert.AreEqual(new[] { nDate }, binObj.GetField("fTimestampArr")); Assert.AreEqual(new[] { nGuid }, binObj.GetField("fGuidArr")); Assert.AreEqual(new[] {TestEnum.Two}, @@ -1659,7 +1687,7 @@ namespace Apache.Ignite.Core.Tests.Binary cache1[1] = new Primitives {FByte = 3}; var obj = cache2[1]; - // Rebuild with no changes + // Rebuild with no changes. cache2[2] = obj.ToBuilder().Build(); Assert.AreEqual(3, cache1[2].FByte); http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTestDynamicRegistration.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTestDynamicRegistration.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTestDynamicRegistration.cs new file mode 100644 index 0000000..3f37833 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryBuilderSelfTestDynamicRegistration.cs @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Binary +{ + using System.Collections.Generic; + using Apache.Ignite.Core.Binary; + + /// + /// Binary builder self test with dynamic type registration. + /// + public class BinaryBuilderSelfTestDynamicRegistration : BinaryBuilderSelfTest + { + /** */ + protected override ICollection GetTypeConfigurations() + { + // The only type to be registered is TestEnumRegistered, + // because unregistered enums are handled differently. + + return new [] + { + new BinaryTypeConfiguration(typeof(TestEnumRegistered)) + }; + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryCompactFooterInteropTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryCompactFooterInteropTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryCompactFooterInteropTest.cs index 830e7f4..76ef999 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryCompactFooterInteropTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryCompactFooterInteropTest.cs @@ -30,7 +30,7 @@ namespace Apache.Ignite.Core.Tests.Binary public class BinaryCompactFooterInteropTest { /** */ - private const string PlatformSqlQueryTask = "org.apache.ignite.platform.PlatformSqlQueryTask"; + public const string PlatformSqlQueryTask = "org.apache.ignite.platform.PlatformSqlQueryTask"; /** */ private IIgnite _grid; http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs new file mode 100644 index 0000000..10e6e0b --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinaryDynamicRegistrationTest.cs @@ -0,0 +1,441 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// ReSharper disable UnusedAutoPropertyAccessor.Local +namespace Apache.Ignite.Core.Tests.Binary +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using Apache.Ignite.Core.Binary; + using Apache.Ignite.Core.Cache.Configuration; + using Apache.Ignite.Core.Cache.Store; + using Apache.Ignite.Core.Common; + using Apache.Ignite.Core.Compute; + using Apache.Ignite.Core.Impl.Binary; + using Apache.Ignite.Core.Impl.Common; + using Apache.Ignite.Core.Tests.Compute; + using NUnit.Framework; + + /// + /// Tests the dynamic type registration. + /// + public class BinaryDynamicRegistrationTest + { + /// + /// Executes before each test. + /// + [SetUp] + public void SetUp() + { + ClearMarshallerWorkDir(); + } + + /// + /// Tests the failed registration. + /// + [Test] + public void TestFailedRegistration() + { + TestFailedRegistration(false, false); + TestFailedRegistration(true, false); + TestFailedRegistration(true, true); + } + + /// + /// Tests the failed registration, when we write type name after the header. + /// + private static void TestFailedRegistration(bool rawStr, bool rawInt) where T : ITest, new() + { + // Disable compact footers for local mode + var cfg = new BinaryConfiguration {CompactFooter = false}; + + // Test in local mode so that MarshallerContext can't propagate type registration. + var bytes = new Marshaller(cfg).Marshal(new T {Int = 1, Str = "2"}); + + var res = new Marshaller(cfg).Unmarshal(bytes); + + Assert.AreEqual(1, res.Int); + Assert.AreEqual("2", res.Str); + + // Check binary mode + var bin = new Marshaller(cfg).Unmarshal(bytes, BinaryMode.ForceBinary); + + if (!rawStr) + Assert.AreEqual("2", bin.GetField("Str")); + + if (!rawInt) + Assert.AreEqual(1, bin.GetField("Int")); + + res = bin.Deserialize(); + + Assert.AreEqual(1, res.Int); + Assert.AreEqual("2", res.Str); + } + + /// + /// Tests the store with node restart to make sure type names are persisted to disk properly. + /// + [Test] + public void TestStore() + { + var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) + { + // Disable compact footers to test grid restart with persistent store + // (Because store operates on raw binary objects). + BinaryConfiguration = new BinaryConfiguration {CompactFooter = false}, + CacheConfiguration = new[] + { + new CacheConfiguration + { + CacheStoreFactory = new StoreFactory(), + ReadThrough = true, + WriteThrough = true + } + } + }; + + using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration())) + { + // Put through dynamically started cache + var dynCache = ignite.CreateCache(new CacheConfiguration("dynCache") + { + CacheStoreFactory = new StoreFactory(), + ReadThrough = true, + WriteThrough = true + }); + dynCache[2] = new Foo { Str = "test2", Int = 3 }; + + // Start another server node so that store is initialized there + using (var ignite2 = Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration()) + { + IgniteInstanceName = "grid2" + })) + { + var dynCache2 = ignite2.GetCache(dynCache.Name); + + Assert.AreEqual("test2", dynCache2[2].Str); + Assert.AreEqual(3, dynCache2[2].Int); + } + } + + using (var ignite = Ignition.Start(cfg)) + { + // Put through statically started cache + var staticCache = ignite.GetCache(null); + staticCache[1] = new Foo {Str = "test", Int = 2}; + } + + using (var ignite = Ignition.Start(cfg)) + { + var foo = ignite.GetCache(null)[1]; + var foo2 = ignite.GetCache(null)[2]; + + Assert.AreEqual("test", foo.Str); + Assert.AreEqual(2, foo.Int); + + Assert.AreEqual("test2", foo2.Str); + Assert.AreEqual(3, foo2.Int); + + // Client node + using (var igniteClient = Ignition.Start(new IgniteConfiguration(cfg) + { + ClientMode = true, + IgniteInstanceName = "grid2" + })) + { + var fooClient = igniteClient.GetCache(null)[1]; + var fooClient2 = igniteClient.GetCache(null)[2]; + + Assert.AreEqual("test", fooClient.Str); + Assert.AreEqual(2, fooClient.Int); + + Assert.AreEqual("test2", fooClient2.Str); + Assert.AreEqual(3, fooClient2.Int); + } + } + + // Delete directory and check that store no longer works + ClearMarshallerWorkDir(); + + using (var ignite = Ignition.Start(cfg)) + { + var ex = Assert.Throws(() => ignite.GetCache(null).Get(1)); + + Assert.IsTrue(ex.Message.Contains("Unknown pair")); + } + } + + /// + /// Tests the store factory property propagation. + /// + [Test] + public void TestStoreFactory() + { + var cfg = new IgniteConfiguration(TestUtils.GetTestConfiguration()) + { + CacheConfiguration = new[] + { + new CacheConfiguration + { + CacheStoreFactory = new StoreFactory {StringProp = "test", IntProp = 9}, + ReadThrough = true, + WriteThrough = true + } + } + }; + + using (Ignition.Start(cfg)) + { + var storeFactory = StoreFactory.LastInstance; + + Assert.AreEqual("test", storeFactory.StringProp); + Assert.AreEqual(9, storeFactory.IntProp); + } + } + + /// + /// Tests the single grid scenario. + /// + [Test] + public void TestSingleGrid() + { + using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration())) + { + Test(ignite, ignite); + } + } + + /// + /// Tests the two grid scenario. + /// + [Test] + public void TestTwoGrids([Values(false, true)] bool clientMode) + { + using (var ignite1 = Ignition.Start(TestUtils.GetTestConfiguration())) + { + using (var ignite2 = Ignition.Start(new IgniteConfiguration(TestUtils.GetTestConfiguration()) + { + IgniteInstanceName = "grid2", + ClientMode = clientMode + })) + { + Test(ignite1, ignite2); + } + } + } + + /// + /// Tests interop scenario: Java and .NET exchange an object with the same type id, + /// but marshaller cache contains different entries for different platforms for the same id. + /// + [Test] + public void TestJavaInterop() + { + using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration())) + { + var cacheCfg = new CacheConfiguration(null, new QueryEntity(typeof(PlatformComputeBinarizable)) + { + Fields = new[] {new QueryField("Field", typeof(int))} + }); + + var cache = ignite.CreateCache(cacheCfg); + + // Force dynamic registration for .NET + cache.Put(1, new PlatformComputeBinarizable {Field = 7}); + + // Run Java code that will also perform dynamic registration + var fromJava = ignite.GetCompute().ExecuteJavaTask(ComputeApiTest.EchoTask, + ComputeApiTest.EchoTypeBinarizable); + + // Check that objects are compatible + Assert.AreEqual(1, fromJava.Field); + + // Check that Java can read what .NET has put + var qryRes = ignite.GetCompute().ExecuteJavaTask( + BinaryCompactFooterInteropTest.PlatformSqlQueryTask, "Field < 10"); + + Assert.AreEqual(7, qryRes.OfType().Single().Field); + } + } + + /// + /// Tests the type registration. + /// + private static void Test(IIgnite ignite1, IIgnite ignite2) + { + const string cacheName = "cache"; + + // Put on one grid. + var cache1 = ignite1.CreateCache(cacheName); + cache1[1] = new Foo {Int = 1, Str = "1"}; + cache1[2] = ignite1.GetBinary().GetBuilder(typeof (Bar)).SetField("Int", 5).SetField("Str", "s").Build(); + + // Get on another grid. + var cache2 = ignite2.GetCache(cacheName); + var foo = cache2[1]; + + Assert.AreEqual(1, foo.Int); + Assert.AreEqual("1", foo.Str); + + var bar = cache2.WithKeepBinary()[2]; + + Assert.AreEqual("s", bar.GetField("Str")); + Assert.AreEqual(5, bar.GetField("Int")); + + var bar0 = bar.Deserialize(); + + Assert.AreEqual("s", bar0.Str); + Assert.AreEqual(5, bar0.Int); + + // Test compute. + var serverNodeCount = ignite1.GetCluster().ForServers().GetNodes().Count; + + var res = ignite1.GetCompute().Broadcast(new CompFn(() => DateTime.Now)); + Assert.AreEqual(serverNodeCount, res.Count); + + // Variable capture. + var res2 = ignite1.GetCompute().Broadcast(new CompFn(() => bar0.Str)); + Assert.AreEqual(Enumerable.Repeat(bar0.Str, serverNodeCount), res2); + } + + /// + /// Clears the marshaller work dir. + /// + private static void ClearMarshallerWorkDir() + { + // Delete all *.classname files within IGNITE_HOME + var home = IgniteHome.Resolve(null); + + var files = Directory.GetFiles(home, "*.classname*", SearchOption.AllDirectories); + + files.ToList().ForEach(File.Delete); + } + + private interface ITest + { + int Int { get; set; } + string Str { get; set; } + } + + private class Foo : ITest + { + public int Int { get; set; } + public string Str { get; set; } + } + + private class Bar : ITest + { + public int Int { get; set; } + public string Str { get; set; } + } + + private class Bin : IBinarizable, ITest + { + public int Int { get; set; } + public string Str { get; set; } + + public void WriteBinary(IBinaryWriter writer) + { + writer.WriteInt("Int", Int); + writer.GetRawWriter().WriteString(Str); + } + + public void ReadBinary(IBinaryReader reader) + { + Int = reader.ReadInt("Int"); + Str = reader.GetRawReader().ReadString(); + } + } + + private class BinRaw : IBinarizable, ITest + { + public int Int { get; set; } + public string Str { get; set; } + + public void WriteBinary(IBinaryWriter writer) + { + var w = writer.GetRawWriter(); + + w.WriteInt(Int); + w.WriteString(Str); + } + + public void ReadBinary(IBinaryReader reader) + { + var r = reader.GetRawReader(); + + Int = r.ReadInt(); + Str = r.ReadString(); + } + } + + [Serializable] + private class StoreFactory : IFactory + { + public string StringProp { get; set; } + + public int IntProp { get; set; } + + public static StoreFactory LastInstance { get; set; } + + public ICacheStore CreateInstance() + { + LastInstance = this; + return new CacheStore(); + } + } + + private class CacheStore : CacheStoreAdapter + { + private static readonly Dictionary Dict = new Dictionary(); + + public override object Load(object key) + { + object res; + return Dict.TryGetValue(key, out res) ? res : null; + } + + public override void Write(object key, object val) + { + Dict[key] = val; + } + + public override void Delete(object key) + { + Dict.Remove(key); + } + } + + private class CompFn : IComputeFunc + { + private readonly Func _func; + + public CompFn(Func func) + { + _func = func; + } + + public T Invoke() + { + return _func(); + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs index 70226e6..eb2751e 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTest.cs @@ -63,16 +63,16 @@ namespace Apache.Ignite.Core.Tests.Binary [TestFixtureSetUp] public void BeforeTest() { - _marsh = new Marshaller(GetBinaryConfiguration()); + _marsh = new Marshaller(new BinaryConfiguration{CompactFooter = GetCompactFooter()}); } /// /// Gets the binary configuration. /// /// - protected virtual BinaryConfiguration GetBinaryConfiguration() + protected virtual bool GetCompactFooter() { - return new BinaryConfiguration { CompactFooter = true }; + return true; } /** @@ -691,7 +691,8 @@ namespace Apache.Ignite.Core.Tests.Binary { new BinaryTypeConfiguration(typeof (PrimitiveFieldType)), new BinaryTypeConfiguration(typeof (GenericCollectionsType)) - } + }, + CompactFooter = GetCompactFooter() }); var obj = new GenericCollectionsType @@ -721,6 +722,52 @@ namespace Apache.Ignite.Core.Tests.Binary CollectionAssert.AreEquivalent(obj.Objects, result.Objects); } + /// + /// Tests the circular reference handling with List. + /// + [Test] + public void TestListCircularReference() + { + var list1 = new List {1}; + var list2 = new List {2}; + + list1.Add(list2); + list2.Add(list1); + + var data = _marsh.Marshal(list1); + + var resList1 = _marsh.Unmarshal>(data); + Assert.AreEqual(1, resList1[0]); + + var resList2 = (List) resList1[1]; + Assert.AreEqual(2, resList2[0]); + Assert.AreEqual(resList1, resList2[1]); + } + + /// + /// Tests the circular reference handling with Dictionary. + /// This test checks proper handle support in combination with OnDeserialization callback, + /// which has to be called after entire graph is deserialized. + /// + [Test] + public void TestDictionaryCircularReference() + { + var dict1 = new Dictionary {{0, 1}}; + var dict2 = new Dictionary {{0, 2}}; + + dict1[1] = dict2; + dict2[1] = dict1; + + var data = _marsh.Marshal(dict1); + + var resDict1 = _marsh.Unmarshal>(data); + Assert.AreEqual(1, resDict1[0]); + + var resDict2 = (Dictionary) resDict1[1]; + Assert.AreEqual(2, resDict2[0]); + Assert.AreEqual(resDict1, resDict2[1]); + } + /** * Check property read. */ @@ -778,7 +825,8 @@ namespace Apache.Ignite.Core.Tests.Binary { Serializer = serializer } - } + }, + CompactFooter = GetCompactFooter() }); // Use utc date fields because reflective serializer writes [QuerySqlField] fields as timestamp @@ -791,20 +839,17 @@ namespace Apache.Ignite.Core.Tests.Binary CheckPrimitiveFields(marsh, obj); } - /** - * Check write of primitive fields through binary interface. - */ + /// + /// Check write of primitive fields through binary interface. + /// [Test] public void TestPrimitiveFieldsBinary() { - ICollection typeCfgs = - new List(); - - typeCfgs.Add(new BinaryTypeConfiguration(typeof(PrimitiveFieldBinaryType))); - - BinaryConfiguration cfg = new BinaryConfiguration(); - - cfg.TypeConfigurations = typeCfgs; + var cfg = new BinaryConfiguration + { + TypeConfigurations = new[] { new BinaryTypeConfiguration(typeof(PrimitiveFieldBinaryType)) }, + CompactFooter = GetCompactFooter() + }; Marshaller marsh = new Marshaller(cfg); @@ -813,44 +858,41 @@ namespace Apache.Ignite.Core.Tests.Binary CheckPrimitiveFields(marsh, obj); } - /** - * Check write of primitive fields through binary interface. - */ + /// + /// Check write of primitive fields through binary interface. + /// [Test] public void TestPrimitiveFieldsRawBinary() { - ICollection typeCfgs = - new List(); - - typeCfgs.Add(new BinaryTypeConfiguration(typeof(PrimitiveFieldRawBinaryType))); - - BinaryConfiguration cfg = new BinaryConfiguration(); - - cfg.TypeConfigurations = typeCfgs; - - Marshaller marsh = new Marshaller(cfg); + var marsh = new Marshaller(new BinaryConfiguration + { + TypeConfigurations = new[] { new BinaryTypeConfiguration(typeof(PrimitiveFieldRawBinaryType)) }, + CompactFooter = GetCompactFooter() + }); - PrimitiveFieldRawBinaryType obj = new PrimitiveFieldRawBinaryType(); + var obj = new PrimitiveFieldRawBinaryType(); CheckPrimitiveFields(marsh, obj); } - /** - * Check write of primitive fields through binary interface. - */ + /// + /// Check write of primitive fields through binary interface. + /// [Test] public void TestPrimitiveFieldsSerializer() { - var typeCfgs = new List + var cfg = new BinaryConfiguration { - new BinaryTypeConfiguration(typeof (PrimitiveFieldType)) + TypeConfigurations = new[] { - Serializer = new PrimitiveFieldsSerializer() - } + new BinaryTypeConfiguration(typeof(PrimitiveFieldType)) + { + Serializer = new PrimitiveFieldsSerializer(), + } + }, + CompactFooter = GetCompactFooter() }; - BinaryConfiguration cfg = new BinaryConfiguration {TypeConfigurations = typeCfgs}; - Marshaller marsh = new Marshaller(cfg); PrimitiveFieldType obj = new PrimitiveFieldType(); @@ -909,31 +951,25 @@ namespace Apache.Ignite.Core.Tests.Binary Assert.AreEqual(obj2.RawValArr, portObj.Deserialize().RawValArr); } - /** - * Check write of primitive fields through raw serializer. - */ + /// + /// Check write of primitive fields through raw serializer. + /// [Test] public void TestPrimitiveFieldsRawSerializer() { - ICollection typeCfgs = - new List(); - - BinaryTypeConfiguration typeCfg = - new BinaryTypeConfiguration(typeof(PrimitiveFieldType)); - - typeCfg.Serializer = new PrimitiveFieldsRawSerializer(); - - typeCfgs.Add(typeCfg); - - BinaryConfiguration cfg = new BinaryConfiguration(); - - cfg.TypeConfigurations = typeCfgs; - - Marshaller marsh = new Marshaller(cfg); - - PrimitiveFieldType obj = new PrimitiveFieldType(); + Marshaller marsh = new Marshaller(new BinaryConfiguration + { + TypeConfigurations = new[] + { + new BinaryTypeConfiguration(typeof(PrimitiveFieldType)) + { + Serializer = new PrimitiveFieldsRawSerializer() + } + }, + CompactFooter = GetCompactFooter() + }); - CheckPrimitiveFields(marsh, obj); + CheckPrimitiveFields(marsh, new PrimitiveFieldType()); } private void CheckPrimitiveFields(Marshaller marsh, PrimitiveFieldType obj) @@ -941,7 +977,7 @@ namespace Apache.Ignite.Core.Tests.Binary CheckPrimitiveFieldsSerialization(marsh, obj); } - private void CheckPrimitiveFieldsSerialization(Marshaller marsh, PrimitiveFieldType obj) + private static void CheckPrimitiveFieldsSerialization(Marshaller marsh, PrimitiveFieldType obj) { byte[] bytes = marsh.Marshal(obj); @@ -1029,7 +1065,8 @@ namespace Apache.Ignite.Core.Tests.Binary { Serializer = new BinaryReflectiveSerializer {RawMode = raw} } - } + }, + CompactFooter = GetCompactFooter() }); var obj = new CollectionsType @@ -1239,9 +1276,7 @@ namespace Apache.Ignite.Core.Tests.Binary { var reader = new BinaryReader(marsh, new BinaryHeapStream(bytes), BinaryMode.ForceBinary, null); - reader.DetachNext(); - - outerObj = reader.Deserialize(); + outerObj = reader.DetachNext().Deserialize(); } else outerObj = marsh.Unmarshal(bytes, BinaryMode.ForceBinary); @@ -1272,7 +1307,8 @@ namespace Apache.Ignite.Core.Tests.Binary TypeConfigurations = new[] { new BinaryTypeConfiguration(typeof (HandleCollection)) - } + }, + CompactFooter = GetCompactFooter() }); // Collection in collection dependency loop @@ -1441,8 +1477,10 @@ namespace Apache.Ignite.Core.Tests.Binary Assert.AreEqual(guidArr, portObj.GetField("guidArr")); Assert.AreEqual(nGuidArr, portObj.GetField("nGuidArr")); - Assert.AreEqual(dateArr, portObj.GetField("dateArr")); - Assert.AreEqual(nDateArr, portObj.GetField("nDateArr")); + Assert.AreEqual(dateArr, portObj.GetField("dateArr") + .Select(x => x.Deserialize())); + Assert.AreEqual(nDateArr, portObj.GetField("nDateArr") + .Select(x => x.Deserialize())); obj1 = portObj.Deserialize(); @@ -1452,12 +1490,13 @@ namespace Apache.Ignite.Core.Tests.Binary Assert.AreEqual(nDateArr, obj1.NDateArr); // Use special with IGridbinaryMarshalAware. - SpecialArrayMarshalAware obj2 = new SpecialArrayMarshalAware(); - - obj2.GuidArr = guidArr; - obj2.NGuidArr = nGuidArr; - obj2.DateArr = dateArr; - obj2.NDateArr = nDateArr; + SpecialArrayMarshalAware obj2 = new SpecialArrayMarshalAware + { + GuidArr = guidArr, + NGuidArr = nGuidArr, + DateArr = dateArr, + NDateArr = nDateArr + }; bytes = marsh.Marshal(obj2); @@ -1465,8 +1504,8 @@ namespace Apache.Ignite.Core.Tests.Binary Assert.AreEqual(guidArr, portObj.GetField("a")); Assert.AreEqual(nGuidArr, portObj.GetField("b")); - Assert.AreEqual(dateArr, portObj.GetField("c")); - Assert.AreEqual(nDateArr, portObj.GetField("d")); + Assert.AreEqual(dateArr, portObj.GetField("c").Select(x => x.Deserialize())); + Assert.AreEqual(nDateArr, portObj.GetField("d").Select(x => x.Deserialize())); obj2 = portObj.Deserialize(); @@ -1523,7 +1562,7 @@ namespace Apache.Ignite.Core.Tests.Binary [Test] public void TestCompactFooterSetting() { - Assert.AreEqual(GetBinaryConfiguration().CompactFooter, _marsh.CompactFooter); + Assert.AreEqual(GetCompactFooter(), _marsh.CompactFooter); } private static void CheckKeepSerialized(BinaryConfiguration cfg, bool expKeep) @@ -1842,8 +1881,8 @@ namespace Apache.Ignite.Core.Tests.Binary PString = "abc"; PGuid = Guid.NewGuid(); PnGuid = Guid.NewGuid(); - PDate = DateTime.Now; - PnDate = DateTime.Now; + PDate = DateTime.UtcNow; + PnDate = DateTime.UtcNow; IgniteGuid = new IgniteGuid(Guid.NewGuid(), 123); } http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTestFullFooter.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTestFullFooter.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTestFullFooter.cs index 06e43e1..72228cf 100644 --- a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTestFullFooter.cs +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/BinarySelfTestFullFooter.cs @@ -17,7 +17,6 @@ namespace Apache.Ignite.Core.Tests.Binary { - using Apache.Ignite.Core.Binary; using NUnit.Framework; /// @@ -27,9 +26,9 @@ namespace Apache.Ignite.Core.Tests.Binary public class BinarySelfTestFullFooter : BinarySelfTest { /** */ - protected override BinaryConfiguration GetBinaryConfiguration() + protected override bool GetCompactFooter() { - return new BinaryConfiguration {CompactFooter = false}; + return false; } } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/JavaBinaryInteropTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/JavaBinaryInteropTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/JavaBinaryInteropTest.cs new file mode 100644 index 0000000..9af5c35 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/JavaBinaryInteropTest.cs @@ -0,0 +1,182 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Binary +{ + using System; + using System.Collections; + using System.Collections.Generic; + using System.Linq; + using NUnit.Framework; + + /// + /// Tests binary type interoperability between .NET and Java code. + /// + public class JavaBinaryInteropTest + { + /// + /// Tests that all kinds of values from .NET can be handled properly on Java side. + /// + [Test] + public void TestValueRoundtrip() + { + using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration())) + { + ignite.CreateCache((string) null); + + // Basic types. + // Types which map directly to Java are returned properly when retrieved as object. + // Non-directly mapped types are returned as their counterpart. + CheckValueCaching((char) 128); + CheckValueCaching((byte) 255); + CheckValueCaching((sbyte) -10, false); + CheckValueCaching((short) -32000); + CheckValueCaching((ushort) 65350, false); + CheckValueCaching(int.MinValue); + CheckValueCaching(uint.MaxValue, false); + CheckValueCaching(long.MinValue); + CheckValueCaching(ulong.MaxValue, false); + + CheckValueCaching((float) 1.1); + CheckValueCaching(2.2); + + CheckValueCaching((decimal) 3.3, asArray: false); + CheckValueCaching(Guid.NewGuid(), asArray: false); + CheckValueCaching(DateTime.Now, asArray: false); + + CheckValueCaching("foobar"); + + // Special arrays. + CheckValueCaching(new[] {Guid.Empty, Guid.NewGuid()}, false); + CheckValueCaching(new Guid?[] {Guid.Empty, Guid.NewGuid()}); + + CheckValueCaching(new[] {1.2m, -3.4m}, false); + CheckValueCaching(new decimal?[] {1.2m, -3.4m}); + + CheckValueCaching(new[] {DateTime.Now}, false); + + // Custom types. + CheckValueCaching(new Foo {X = 10}, asArray: false); + CheckValueCaching(new Bar {X = 20}, asArray: false); + + // Collections. + CheckValueCaching(new List(GetFoo())); + CheckValueCaching(new List(GetBar())); + + CheckValueCaching(new HashSet(GetFoo())); + CheckValueCaching(new HashSet(GetBar())); + + CheckValueCaching(GetFoo().ToDictionary(x => x.X, x => x)); + CheckValueCaching(GetBar().ToDictionary(x => x.X, x => x)); + + // Custom type arrays. + // Array type is lost, because in binary mode on Java side we receive the value as Object[]. + CheckValueCaching(new[] {new Foo {X = -1}, new Foo {X = 1}}, false); + CheckValueCaching(new[] {new Bar {X = -10}, new Bar {X = 10}}, false); + } + } + + /// + /// Checks caching of a value with generic cache. + /// + private static void CheckValueCaching(T val, bool asObject = true, bool asArray = true) + { + var cache = Ignition.GetIgnite(null).GetCache(null); + + cache[1] = val; + Assert.AreEqual(val, cache[1]); + + if (asObject) + { + CheckValueCachingAsObject(val); + } + + // Array of T + if (asArray && !(val is IEnumerable)) + { + CheckValueCaching(new[] {val}, asObject, false); + } + } + + /// + /// Checks caching of a value with object cache. + /// + private static void CheckValueCachingAsObject(T val) + { + var cache = Ignition.GetIgnite(null).GetCache(null); + + cache[1] = val; + Assert.AreEqual(val, (T) cache[1]); + } + + /// + /// Gets Foo collection. + /// + private static IEnumerable GetFoo() + { + return Enumerable.Range(-50, 100).Select(x => new Foo {X = x}); + } + + /// + /// Gets Bar collection. + /// + private static IEnumerable GetBar() + { + return Enumerable.Range(-50, 100).Select(x => new Bar {X = x}); + } + + /// + /// Test custom class. + /// + private class Foo + { + public int X { get; set; } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + if (ReferenceEquals(this, obj)) return true; + if (obj.GetType() != GetType()) return false; + return X == ((Foo) obj).X; + } + + public override int GetHashCode() + { + return X; + } + } + + /// + /// Test custom struct. + /// + private struct Bar + { + public int X { get; set; } + + public override bool Equals(object obj) + { + if (ReferenceEquals(null, obj)) return false; + return obj is Bar && X == ((Bar) obj).X; + } + + public override int GetHashCode() + { + return X; + } + } + } +} http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/AdvancedSerializationTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/AdvancedSerializationTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/AdvancedSerializationTest.cs new file mode 100644 index 0000000..c96d111 --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/AdvancedSerializationTest.cs @@ -0,0 +1,228 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Binary.Serializable +{ + using System; + using System.Collections.Generic; + using System.Linq; + using System.Reflection; + using System.Reflection.Emit; + using System.Runtime.Serialization; + using System.Xml; + using Apache.Ignite.Core.Cluster; + using Apache.Ignite.Core.Compute; + using NUnit.Framework; + + /// + /// Tests additional [Serializable] scenarios. + /// + public class AdvancedSerializationTest + { + /// + /// Set up routine. + /// + [TestFixtureSetUp] + public void SetUp() + { + Ignition.Start(TestUtils.GetTestConfiguration()); + } + + /// + /// Tear down routine. + /// + [TestFixtureTearDown] + public void TearDown() + { + Ignition.StopAll(true); + } + + /// + /// Test complex file serialization. + /// + [Test] + public void TestSerializableXmlDoc() + { + var grid = Ignition.GetIgnite(null); + var cache = grid.GetOrCreateCache("cache"); + + var doc = new SerializableXmlDoc(); + + doc.LoadXml("val"); + + for (var i = 0; i < 50; i++) + { + // Test cache + cache.Put(i, doc); + + var resultDoc = cache.Get(i); + + Assert.AreEqual(doc.OuterXml, resultDoc.OuterXml); + + // Test task with document arg + CheckTask(grid, doc); + } + } + + /// + /// Checks task execution. + /// + /// Grid. + /// Task arg. + private static void CheckTask(IIgnite grid, object arg) + { + var jobResult = grid.GetCompute().Execute(new CombineStringsTask(), arg); + + var nodeCount = grid.GetCluster().GetNodes().Count; + + var expectedRes = + CombineStringsTask.CombineStrings(Enumerable.Range(0, nodeCount).Select(x => arg.ToString())); + + Assert.AreEqual(expectedRes, jobResult.InnerXml); + } + + /// + /// Tests custom serialization binder. + /// + [Test] + public void TestSerializationBinder() + { + const int count = 50; + + var cache = Ignition.GetIgnite(null).GetOrCreateCache("cache"); + + // Put multiple objects from multiple same-named assemblies to cache + for (var i = 0; i < count; i++) + { + dynamic val = Activator.CreateInstance(GenerateDynamicType()); + + val.Id = i; + val.Name = "Name_" + i; + + cache.Put(i, val); + } + + // Verify correct deserialization + for (var i = 0; i < count; i++) + { + dynamic val = cache.Get(i); + + Assert.AreEqual(val.Id, i); + Assert.AreEqual(val.Name, "Name_" + i); + } + } + + /// + /// Generates a Type in runtime, puts it into a dynamic assembly. + /// + /// + private static Type GenerateDynamicType() + { + var asmBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly( + new AssemblyName("GridSerializationTestDynamicAssembly"), AssemblyBuilderAccess.Run); + + var moduleBuilder = asmBuilder.DefineDynamicModule("GridSerializationTestDynamicModule"); + + var typeBuilder = moduleBuilder.DefineType("GridSerializationTestDynamicType", + TypeAttributes.Class | TypeAttributes.Public | TypeAttributes.Serializable); + + typeBuilder.DefineField("Id", typeof (int), FieldAttributes.Public); + + typeBuilder.DefineField("Name", typeof (string), FieldAttributes.Public); + + return typeBuilder.CreateType(); + } + } + + [Serializable] + [DataContract] + public sealed class SerializableXmlDoc : XmlDocument, ISerializable + { + /// + /// Default ctor. + /// + public SerializableXmlDoc() + { + // No-op + } + + /// + /// Serialization ctor. + /// + private SerializableXmlDoc(SerializationInfo info, StreamingContext context) + { + LoadXml(info.GetString("xmlDocument")); + } + + /** */ + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + info.AddValue("xmlDocument", OuterXml, typeof(string)); + } + } + + [Serializable] + public class CombineStringsTask : IComputeTask + { + public IDictionary, IClusterNode> Map(IList subgrid, object arg) + { + return subgrid.ToDictionary(x => (IComputeJob) new ToStringJob {Arg = arg}, x => x); + } + + public ComputeJobResultPolicy OnResult(IComputeJobResult res, IList> rcvd) + { + return ComputeJobResultPolicy.Wait; + } + + public SerializableXmlDoc Reduce(IList> results) + { + var result = new SerializableXmlDoc(); + + result.LoadXml(CombineStrings(results.Select(x => x.Data))); + + return result; + } + + public static string CombineStrings(IEnumerable strings) + { + var text = string.Concat(strings.Select(x => string.Format("{0}", x))); + + return string.Format("{0}", text); + } + } + + [Serializable] + public class ToStringJob : IComputeJob + { + /// + /// Job argument. + /// + public object Arg { get; set; } + + /** */ + public string Execute() + { + return Arg.ToString(); + } + + /** */ + public void Cancel() + { + // No-op. + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/79bac4f8/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs ---------------------------------------------------------------------- diff --git a/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs new file mode 100644 index 0000000..82deb3c --- /dev/null +++ b/modules/platforms/dotnet/Apache.Ignite.Core.Tests/Binary/Serializable/BasicSerializableObjectsTest.cs @@ -0,0 +1,124 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +namespace Apache.Ignite.Core.Tests.Binary.Serializable +{ + using System; + using System.Runtime.Serialization; + using Apache.Ignite.Core.Binary; + using NUnit.Framework; + + /// + /// Tests basic ISerializable scenarios. + /// + public class BasicSerializableObjectsTest + { + /// + /// Tests the object with no fields. + /// + [Test] + public void TestEmptyObject() + { + var res = TestUtils.SerializeDeserialize(new EmptyObject()); + + Assert.IsNotNull(res); + } + + /// + /// Tests the object with no fields. + /// + [Test] + public void TestEmptyObjectOnline() + { + using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration())) + { + var cache = ignite.CreateCache("c"); + + cache[1] = new EmptyObject(); + + var res = cache[1]; + + Assert.IsNotNull(res); + } + } + + /// + /// Tests ISerializable without serialization ctor. + /// + [Test] + public void TestMissingCtor() + { + var ex = Assert.Throws(() => TestUtils.SerializeDeserialize(new MissingCtor())); + Assert.AreEqual(string.Format("The constructor to deserialize an object of type '{0}' was not found.", + typeof(MissingCtor)), ex.Message); + } + + /// + /// Tests serialization. + /// + [Test] + public void TestTypes() + { + var type = GetType(); + + var res = TestUtils.SerializeDeserialize(type); + + Assert.AreEqual(type, res); + } + + /// + /// Missing serialization ctor. + /// + private class MissingCtor : ISerializable + { + /** */ + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + // No-op. + } + } + + /// + /// Object with no fields. + /// + [Serializable] + private class EmptyObject : ISerializable + { + /// + /// Initializes a new instance of the class. + /// + public EmptyObject() + { + // No-op. + } + + /// + /// Initializes a new instance of the class. + /// + private EmptyObject(SerializationInfo info, StreamingContext context) + { + Assert.IsInstanceOf(context.Context); + } + + /** */ + public void GetObjectData(SerializationInfo info, StreamingContext context) + { + Assert.IsInstanceOf(context.Context); + } + } + } +}