You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by sb...@apache.org on 2017/04/06 13:31:22 UTC
[15/50] [abbrv] ignite git commit: IGNITE-2703 .NET: Dynamic type
registration
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 <pt...@apache.org>
Authored: Fri Mar 31 16:31:56 2017 +0300
Committer: Pavel Tupitsyn <pt...@apache.org>
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 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Binary\BinaryEqualityComparerTest.cs" />
+ <Compile Include="Binary\BinaryBuilderSelfTestDynamicRegistration.cs" />
<Compile Include="Binary\BinaryReaderWriterTest.cs" />
<Compile Include="Binary\IO\BinaryStreamsTest.cs" />
+ <Compile Include="Binary\JavaBinaryInteropTest.cs" />
<Compile Include="Binary\JavaTypeMappingTest.cs" />
+ <Compile Include="Binary\Serializable\CallbacksTest.cs" />
+ <Compile Include="Binary\Serializable\DelegatesTest.cs" />
+ <Compile Include="Binary\Serializable\BasicSerializableObjectsTest.cs" />
+ <Compile Include="Binary\Serializable\ObjectReferenceTests.cs" />
+ <Compile Include="Binary\Serializable\PrimitivesTest.cs" />
+ <Compile Include="Binary\Serializable\SqlDmlTest.cs" />
<Compile Include="Binary\TypeResolverTest.cs" />
<Compile Include="Cache\Affinity\AffinityKeyTest.cs" />
<Compile Include="Cache\Affinity\AffinityTopologyVersionTest.cs" />
@@ -103,6 +111,7 @@
<Compile Include="TestAppConfig.cs" />
<Compile Include="Binary\BinaryBuilderSelfTestFullFooter.cs" />
<Compile Include="Binary\BinaryCompactFooterInteropTest.cs" />
+ <Compile Include="Binary\BinaryDynamicRegistrationTest.cs" />
<Compile Include="Binary\BinarySelfTestFullFooter.cs" />
<Compile Include="Binary\BinaryStringTest.cs" />
<Compile Include="Cache\Affinity\AffinityFieldTest.cs" />
@@ -190,7 +199,7 @@
<Compile Include="ProcessExtensions.cs" />
<Compile Include="ProjectFilesTest.cs" />
<Compile Include="ReconnectTest.cs" />
- <Compile Include="SerializationTest.cs" />
+ <Compile Include="Binary\Serializable\AdvancedSerializationTest.cs" />
<Compile Include="IgniteStartStopTest.cs" />
<Compile Include="Services\ServicesTestFullFooter.cs" />
<Compile Include="TestUtils.cs" />
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<BinaryTypeConfiguration>
- {
- 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
}
/// <summary>
+ /// Gets the type configurations.
+ /// </summary>
+ protected virtual ICollection<BinaryTypeConfiguration> 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))
+ };
+ }
+
+ /// <summary>
/// Gets the compact footer setting.
/// </summary>
protected virtual bool GetCompactFooter()
@@ -213,7 +221,7 @@ namespace Apache.Ignite.Core.Tests.Binary
// 2. Special types.
Assert.AreEqual("a", api.ToBinary<string>("a"));
- Assert.AreEqual(date, api.ToBinary<DateTime>(date));
+ Assert.AreEqual(date, api.ToBinary<IBinaryObject>(date).Deserialize<DateTime>());
Assert.AreEqual(guid, api.ToBinary<Guid>(guid));
Assert.AreEqual(TestEnumRegistered.One, api.ToBinary<IBinaryObject>(TestEnumRegistered.One)
.Deserialize<TestEnumRegistered>());
@@ -231,7 +239,8 @@ namespace Apache.Ignite.Core.Tests.Binary
Assert.AreEqual(new[] { 'a' }, api.ToBinary<char[]>(new[] { 'a' }));
Assert.AreEqual(new[] { "a" }, api.ToBinary<string[]>(new[] { "a" }));
- Assert.AreEqual(new[] { date }, api.ToBinary<DateTime[]>(new[] { date }));
+ Assert.AreEqual(new[] {date}, api.ToBinary<IBinaryObject[]>(new[] {date})
+ .Select(x => x.Deserialize<DateTime>()));
Assert.AreEqual(new[] { guid }, api.ToBinary<Guid[]>(new[] { guid }));
Assert.AreEqual(new[] { TestEnumRegistered.One},
api.ToBinary<IBinaryObject[]>(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<string>("fStr"));
- Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, binObj.GetField<IBinaryObject>("fNDate").Deserialize<DateTime?>());
Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, binObj.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.One, binObj.GetField<IBinaryObject>("fEnum").Deserialize<TestEnum>());
Assert.AreEqual(new[] {"str"}, binObj.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, binObj.GetField<IBinaryObject[]>("fDateArr")
+ .Select(x => x.Deserialize<DateTime?>()));
Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fTimestampArr"));
Assert.AreEqual(new[] {nGuid}, binObj.GetField<Guid?[]>("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<string>("fStr"));
- Assert.AreEqual(nDate, builder.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, builder.GetField<IBinaryObjectBuilder>("fNDate").Build().Deserialize<DateTime?>());
Assert.AreEqual(nDate, builder.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, builder.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.One, builder.GetField<IBinaryObject>("fEnum").Deserialize<TestEnum>());
Assert.AreEqual(new[] {"str"}, builder.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] {nDate}, builder.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, builder.GetField<IBinaryObjectBuilder[]>("fDateArr")
+ .Select(x => x.Build().Deserialize<DateTime?>()));
Assert.AreEqual(new[] {nDate}, builder.GetField<DateTime?[]>("fTimestampArr"));
Assert.AreEqual(new[] {nGuid}, builder.GetField<Guid?[]>("fGuidArr"));
Assert.AreEqual(new[] {TestEnum.One},
@@ -1043,12 +1069,13 @@ namespace Apache.Ignite.Core.Tests.Binary
binObj = builder.Build();
Assert.AreEqual("str", binObj.GetField<string>("fStr"));
- Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, binObj.GetField<IBinaryObject>("fNDate").Deserialize<DateTime?>());
Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, binObj.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.One, binObj.GetField<IBinaryObject>("fEnum").Deserialize<TestEnum>());
Assert.AreEqual(new[] {"str"}, binObj.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, binObj.GetField<IBinaryObject[]>("fDateArr")
+ .Select(x => x.Deserialize<DateTime?>()));
Assert.AreEqual(new[] {nDate}, binObj.GetField<DateTime?[]>("fTimestampArr"));
Assert.AreEqual(new[] {nGuid}, binObj.GetField<Guid?[]>("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<string>("fStr"));
- Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNDate"));
+ Assert.AreEqual(nDate, binObj.GetField<IBinaryObject>("fNDate").Deserialize<DateTime?>());
Assert.AreEqual(nDate, binObj.GetField<DateTime?>("fNTimestamp"));
Assert.AreEqual(nGuid, binObj.GetField<Guid?>("fNGuid"));
Assert.AreEqual(TestEnum.Two, binObj.GetField<IBinaryObject>("fEnum").Deserialize<TestEnum>());
Assert.AreEqual(new[] { "str2" }, binObj.GetField<string[]>("fStrArr"));
- Assert.AreEqual(new[] { nDate }, binObj.GetField<DateTime?[]>("fDateArr"));
+ Assert.AreEqual(new[] {nDate}, binObj.GetField<IBinaryObject[]>("fDateArr")
+ .Select(x => x.Deserialize<DateTime?>()));
Assert.AreEqual(new[] { nDate }, binObj.GetField<DateTime?[]>("fTimestampArr"));
Assert.AreEqual(new[] { nGuid }, binObj.GetField<Guid?[]>("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;
+
+ /// <summary>
+ /// Binary builder self test with dynamic type registration.
+ /// </summary>
+ public class BinaryBuilderSelfTestDynamicRegistration : BinaryBuilderSelfTest
+ {
+ /** <inheritdoc /> */
+ protected override ICollection<BinaryTypeConfiguration> 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 @@
+\ufeff/*
+ * 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;
+
+ /// <summary>
+ /// Tests the dynamic type registration.
+ /// </summary>
+ public class BinaryDynamicRegistrationTest
+ {
+ /// <summary>
+ /// Executes before each test.
+ /// </summary>
+ [SetUp]
+ public void SetUp()
+ {
+ ClearMarshallerWorkDir();
+ }
+
+ /// <summary>
+ /// Tests the failed registration.
+ /// </summary>
+ [Test]
+ public void TestFailedRegistration()
+ {
+ TestFailedRegistration<Foo>(false, false);
+ TestFailedRegistration<Bin>(true, false);
+ TestFailedRegistration<BinRaw>(true, true);
+ }
+
+ /// <summary>
+ /// Tests the failed registration, when we write type name after the header.
+ /// </summary>
+ private static void TestFailedRegistration<T>(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<T>(bytes);
+
+ Assert.AreEqual(1, res.Int);
+ Assert.AreEqual("2", res.Str);
+
+ // Check binary mode
+ var bin = new Marshaller(cfg).Unmarshal<IBinaryObject>(bytes, BinaryMode.ForceBinary);
+
+ if (!rawStr)
+ Assert.AreEqual("2", bin.GetField<string>("Str"));
+
+ if (!rawInt)
+ Assert.AreEqual(1, bin.GetField<int>("Int"));
+
+ res = bin.Deserialize<T>();
+
+ Assert.AreEqual(1, res.Int);
+ Assert.AreEqual("2", res.Str);
+ }
+
+ /// <summary>
+ /// Tests the store with node restart to make sure type names are persisted to disk properly.
+ /// </summary>
+ [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<int, Foo>(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<int, Foo>(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<int, Foo>(null);
+ staticCache[1] = new Foo {Str = "test", Int = 2};
+ }
+
+ using (var ignite = Ignition.Start(cfg))
+ {
+ var foo = ignite.GetCache<int, Foo>(null)[1];
+ var foo2 = ignite.GetCache<int, Foo>(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<int, Foo>(null)[1];
+ var fooClient2 = igniteClient.GetCache<int, Foo>(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<BinaryObjectException>(() => ignite.GetCache<int, Foo>(null).Get(1));
+
+ Assert.IsTrue(ex.Message.Contains("Unknown pair"));
+ }
+ }
+
+ /// <summary>
+ /// Tests the store factory property propagation.
+ /// </summary>
+ [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);
+ }
+ }
+
+ /// <summary>
+ /// Tests the single grid scenario.
+ /// </summary>
+ [Test]
+ public void TestSingleGrid()
+ {
+ using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration()))
+ {
+ Test(ignite, ignite);
+ }
+ }
+
+ /// <summary>
+ /// Tests the two grid scenario.
+ /// </summary>
+ [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);
+ }
+ }
+ }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ [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<int, object>(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<PlatformComputeBinarizable>(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<IList>(
+ BinaryCompactFooterInteropTest.PlatformSqlQueryTask, "Field < 10");
+
+ Assert.AreEqual(7, qryRes.OfType<PlatformComputeBinarizable>().Single().Field);
+ }
+ }
+
+ /// <summary>
+ /// Tests the type registration.
+ /// </summary>
+ private static void Test(IIgnite ignite1, IIgnite ignite2)
+ {
+ const string cacheName = "cache";
+
+ // Put on one grid.
+ var cache1 = ignite1.CreateCache<int, object>(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<int, Foo>(cacheName);
+ var foo = cache2[1];
+
+ Assert.AreEqual(1, foo.Int);
+ Assert.AreEqual("1", foo.Str);
+
+ var bar = cache2.WithKeepBinary<int, IBinaryObject>()[2];
+
+ Assert.AreEqual("s", bar.GetField<string>("Str"));
+ Assert.AreEqual(5, bar.GetField<int>("Int"));
+
+ var bar0 = bar.Deserialize<Bar>();
+
+ 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>(() => DateTime.Now));
+ Assert.AreEqual(serverNodeCount, res.Count);
+
+ // Variable capture.
+ var res2 = ignite1.GetCompute().Broadcast(new CompFn<string>(() => bar0.Str));
+ Assert.AreEqual(Enumerable.Repeat(bar0.Str, serverNodeCount), res2);
+ }
+
+ /// <summary>
+ /// Clears the marshaller work dir.
+ /// </summary>
+ 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<ICacheStore>
+ {
+ 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<object, object>
+ {
+ private static readonly Dictionary<object, object> Dict = new Dictionary<object, object>();
+
+ 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<T> : IComputeFunc<T>
+ {
+ private readonly Func<T> _func;
+
+ public CompFn(Func<T> 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()});
}
/// <summary>
/// Gets the binary configuration.
/// </summary>
/// <returns></returns>
- 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<PrimitiveFieldType, SerializableObject>))
- }
+ },
+ CompactFooter = GetCompactFooter()
});
var obj = new GenericCollectionsType<PrimitiveFieldType, SerializableObject>
@@ -721,6 +722,52 @@ namespace Apache.Ignite.Core.Tests.Binary
CollectionAssert.AreEquivalent(obj.Objects, result.Objects);
}
+ /// <summary>
+ /// Tests the circular reference handling with List.
+ /// </summary>
+ [Test]
+ public void TestListCircularReference()
+ {
+ var list1 = new List<object> {1};
+ var list2 = new List<object> {2};
+
+ list1.Add(list2);
+ list2.Add(list1);
+
+ var data = _marsh.Marshal(list1);
+
+ var resList1 = _marsh.Unmarshal<List<object>>(data);
+ Assert.AreEqual(1, resList1[0]);
+
+ var resList2 = (List<object>) resList1[1];
+ Assert.AreEqual(2, resList2[0]);
+ Assert.AreEqual(resList1, resList2[1]);
+ }
+
+ /// <summary>
+ /// 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.
+ /// </summary>
+ [Test]
+ public void TestDictionaryCircularReference()
+ {
+ var dict1 = new Dictionary<object, object> {{0, 1}};
+ var dict2 = new Dictionary<object, object> {{0, 2}};
+
+ dict1[1] = dict2;
+ dict2[1] = dict1;
+
+ var data = _marsh.Marshal(dict1);
+
+ var resDict1 = _marsh.Unmarshal<Dictionary<object, object>>(data);
+ Assert.AreEqual(1, resDict1[0]);
+
+ var resDict2 = (Dictionary<object, object>) resDict1[1];
+ Assert.AreEqual(2, resDict2[0]);
+ Assert.AreEqual(resDict1, resDict2[1]);
+ }
+
/**
* <summary>Check property read.</summary>
*/
@@ -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);
}
- /**
- * <summary>Check write of primitive fields through binary interface.</summary>
- */
+ /// <summary>
+ /// Check write of primitive fields through binary interface.
+ /// </summary>
[Test]
public void TestPrimitiveFieldsBinary()
{
- ICollection<BinaryTypeConfiguration> typeCfgs =
- new List<BinaryTypeConfiguration>();
-
- 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);
}
- /**
- * <summary>Check write of primitive fields through binary interface.</summary>
- */
+ /// <summary>
+ /// Check write of primitive fields through binary interface.
+ /// </summary>
[Test]
public void TestPrimitiveFieldsRawBinary()
{
- ICollection<BinaryTypeConfiguration> typeCfgs =
- new List<BinaryTypeConfiguration>();
-
- 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);
}
- /**
- * <summary>Check write of primitive fields through binary interface.</summary>
- */
+ /// <summary>
+ /// Check write of primitive fields through binary interface.
+ /// </summary>
[Test]
public void TestPrimitiveFieldsSerializer()
{
- var typeCfgs = new List<BinaryTypeConfiguration>
+ 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<DecimalMarshalAware>().RawValArr);
}
- /**
- * <summary>Check write of primitive fields through raw serializer.</summary>
- */
+ /// <summary>
+ /// Check write of primitive fields through raw serializer.
+ /// </summary>
[Test]
public void TestPrimitiveFieldsRawSerializer()
{
- ICollection<BinaryTypeConfiguration> typeCfgs =
- new List<BinaryTypeConfiguration>();
-
- 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<IBinaryObject>();
+ outerObj = reader.DetachNext().Deserialize<IBinaryObject>();
}
else
outerObj = marsh.Unmarshal<IBinaryObject>(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<Guid[]>("guidArr"));
Assert.AreEqual(nGuidArr, portObj.GetField<Guid?[]>("nGuidArr"));
- Assert.AreEqual(dateArr, portObj.GetField<DateTime[]>("dateArr"));
- Assert.AreEqual(nDateArr, portObj.GetField<DateTime?[]>("nDateArr"));
+ Assert.AreEqual(dateArr, portObj.GetField<IBinaryObject[]>("dateArr")
+ .Select(x => x.Deserialize<DateTime>()));
+ Assert.AreEqual(nDateArr, portObj.GetField<IBinaryObject[]>("nDateArr")
+ .Select(x => x.Deserialize<DateTime?>()));
obj1 = portObj.Deserialize<SpecialArray>();
@@ -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<Guid[]>("a"));
Assert.AreEqual(nGuidArr, portObj.GetField<Guid?[]>("b"));
- Assert.AreEqual(dateArr, portObj.GetField<DateTime[]>("c"));
- Assert.AreEqual(nDateArr, portObj.GetField<DateTime?[]>("d"));
+ Assert.AreEqual(dateArr, portObj.GetField<IBinaryObject[]>("c").Select(x => x.Deserialize<DateTime>()));
+ Assert.AreEqual(nDateArr, portObj.GetField<IBinaryObject[]>("d").Select(x => x.Deserialize<DateTime?>()));
obj2 = portObj.Deserialize<SpecialArrayMarshalAware>();
@@ -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;
/// <summary>
@@ -27,9 +26,9 @@ namespace Apache.Ignite.Core.Tests.Binary
public class BinarySelfTestFullFooter : BinarySelfTest
{
/** <inheritdoc /> */
- 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 @@
+\ufeff/*
+ * 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;
+
+ /// <summary>
+ /// Tests binary type interoperability between .NET and Java code.
+ /// </summary>
+ public class JavaBinaryInteropTest
+ {
+ /// <summary>
+ /// Tests that all kinds of values from .NET can be handled properly on Java side.
+ /// </summary>
+ [Test]
+ public void TestValueRoundtrip()
+ {
+ using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration()))
+ {
+ ignite.CreateCache<int, object>((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<Foo>(GetFoo()));
+ CheckValueCaching(new List<Bar>(GetBar()));
+
+ CheckValueCaching(new HashSet<Foo>(GetFoo()));
+ CheckValueCaching(new HashSet<Bar>(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);
+ }
+ }
+
+ /// <summary>
+ /// Checks caching of a value with generic cache.
+ /// </summary>
+ private static void CheckValueCaching<T>(T val, bool asObject = true, bool asArray = true)
+ {
+ var cache = Ignition.GetIgnite(null).GetCache<int, T>(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);
+ }
+ }
+
+ /// <summary>
+ /// Checks caching of a value with object cache.
+ /// </summary>
+ private static void CheckValueCachingAsObject<T>(T val)
+ {
+ var cache = Ignition.GetIgnite(null).GetCache<int, object>(null);
+
+ cache[1] = val;
+ Assert.AreEqual(val, (T) cache[1]);
+ }
+
+ /// <summary>
+ /// Gets Foo collection.
+ /// </summary>
+ private static IEnumerable<Foo> GetFoo()
+ {
+ return Enumerable.Range(-50, 100).Select(x => new Foo {X = x});
+ }
+
+ /// <summary>
+ /// Gets Bar collection.
+ /// </summary>
+ private static IEnumerable<Bar> GetBar()
+ {
+ return Enumerable.Range(-50, 100).Select(x => new Bar {X = x});
+ }
+
+ /// <summary>
+ /// Test custom class.
+ /// </summary>
+ 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;
+ }
+ }
+
+ /// <summary>
+ /// Test custom struct.
+ /// </summary>
+ 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;
+
+ /// <summary>
+ /// Tests additional [Serializable] scenarios.
+ /// </summary>
+ public class AdvancedSerializationTest
+ {
+ /// <summary>
+ /// Set up routine.
+ /// </summary>
+ [TestFixtureSetUp]
+ public void SetUp()
+ {
+ Ignition.Start(TestUtils.GetTestConfiguration());
+ }
+
+ /// <summary>
+ /// Tear down routine.
+ /// </summary>
+ [TestFixtureTearDown]
+ public void TearDown()
+ {
+ Ignition.StopAll(true);
+ }
+
+ /// <summary>
+ /// Test complex file serialization.
+ /// </summary>
+ [Test]
+ public void TestSerializableXmlDoc()
+ {
+ var grid = Ignition.GetIgnite(null);
+ var cache = grid.GetOrCreateCache<int, SerializableXmlDoc>("cache");
+
+ var doc = new SerializableXmlDoc();
+
+ doc.LoadXml("<document><test1>val</test1><test2 attr=\"x\" /></document>");
+
+ 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);
+ }
+ }
+
+ /// <summary>
+ /// Checks task execution.
+ /// </summary>
+ /// <param name="grid">Grid.</param>
+ /// <param name="arg">Task arg.</param>
+ 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);
+ }
+
+ /// <summary>
+ /// Tests custom serialization binder.
+ /// </summary>
+ [Test]
+ public void TestSerializationBinder()
+ {
+ const int count = 50;
+
+ var cache = Ignition.GetIgnite(null).GetOrCreateCache<int, object>("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);
+ }
+ }
+
+ /// <summary>
+ /// Generates a Type in runtime, puts it into a dynamic assembly.
+ /// </summary>
+ /// <returns></returns>
+ 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
+ {
+ /// <summary>
+ /// Default ctor.
+ /// </summary>
+ public SerializableXmlDoc()
+ {
+ // No-op
+ }
+
+ /// <summary>
+ /// Serialization ctor.
+ /// </summary>
+ private SerializableXmlDoc(SerializationInfo info, StreamingContext context)
+ {
+ LoadXml(info.GetString("xmlDocument"));
+ }
+
+ /** <inheritdoc /> */
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ info.AddValue("xmlDocument", OuterXml, typeof(string));
+ }
+ }
+
+ [Serializable]
+ public class CombineStringsTask : IComputeTask<object, string, SerializableXmlDoc>
+ {
+ public IDictionary<IComputeJob<string>, IClusterNode> Map(IList<IClusterNode> subgrid, object arg)
+ {
+ return subgrid.ToDictionary(x => (IComputeJob<string>) new ToStringJob {Arg = arg}, x => x);
+ }
+
+ public ComputeJobResultPolicy OnResult(IComputeJobResult<string> res, IList<IComputeJobResult<string>> rcvd)
+ {
+ return ComputeJobResultPolicy.Wait;
+ }
+
+ public SerializableXmlDoc Reduce(IList<IComputeJobResult<string>> results)
+ {
+ var result = new SerializableXmlDoc();
+
+ result.LoadXml(CombineStrings(results.Select(x => x.Data)));
+
+ return result;
+ }
+
+ public static string CombineStrings(IEnumerable<string> strings)
+ {
+ var text = string.Concat(strings.Select(x => string.Format("<val>{0}</val>", x)));
+
+ return string.Format("<document>{0}</document>", text);
+ }
+ }
+
+ [Serializable]
+ public class ToStringJob : IComputeJob<string>
+ {
+ /// <summary>
+ /// Job argument.
+ /// </summary>
+ public object Arg { get; set; }
+
+ /** <inheritdoc /> */
+ public string Execute()
+ {
+ return Arg.ToString();
+ }
+
+ /** <inheritdoc /> */
+ 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 @@
+\ufeff/*
+ * 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;
+
+ /// <summary>
+ /// Tests basic ISerializable scenarios.
+ /// </summary>
+ public class BasicSerializableObjectsTest
+ {
+ /// <summary>
+ /// Tests the object with no fields.
+ /// </summary>
+ [Test]
+ public void TestEmptyObject()
+ {
+ var res = TestUtils.SerializeDeserialize(new EmptyObject());
+
+ Assert.IsNotNull(res);
+ }
+
+ /// <summary>
+ /// Tests the object with no fields.
+ /// </summary>
+ [Test]
+ public void TestEmptyObjectOnline()
+ {
+ using (var ignite = Ignition.Start(TestUtils.GetTestConfiguration()))
+ {
+ var cache = ignite.CreateCache<int, EmptyObject>("c");
+
+ cache[1] = new EmptyObject();
+
+ var res = cache[1];
+
+ Assert.IsNotNull(res);
+ }
+ }
+
+ /// <summary>
+ /// Tests ISerializable without serialization ctor.
+ /// </summary>
+ [Test]
+ public void TestMissingCtor()
+ {
+ var ex = Assert.Throws<SerializationException>(() => TestUtils.SerializeDeserialize(new MissingCtor()));
+ Assert.AreEqual(string.Format("The constructor to deserialize an object of type '{0}' was not found.",
+ typeof(MissingCtor)), ex.Message);
+ }
+
+ /// <summary>
+ /// Tests <see cref="Type"/> serialization.
+ /// </summary>
+ [Test]
+ public void TestTypes()
+ {
+ var type = GetType();
+
+ var res = TestUtils.SerializeDeserialize(type);
+
+ Assert.AreEqual(type, res);
+ }
+
+ /// <summary>
+ /// Missing serialization ctor.
+ /// </summary>
+ private class MissingCtor : ISerializable
+ {
+ /** <inheritdoc /> */
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ // No-op.
+ }
+ }
+
+ /// <summary>
+ /// Object with no fields.
+ /// </summary>
+ [Serializable]
+ private class EmptyObject : ISerializable
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EmptyObject"/> class.
+ /// </summary>
+ public EmptyObject()
+ {
+ // No-op.
+ }
+
+ /// <summary>
+ /// Initializes a new instance of the <see cref="EmptyObject"/> class.
+ /// </summary>
+ private EmptyObject(SerializationInfo info, StreamingContext context)
+ {
+ Assert.IsInstanceOf<IBinaryReader>(context.Context);
+ }
+
+ /** <inheritdoc /> */
+ public void GetObjectData(SerializationInfo info, StreamingContext context)
+ {
+ Assert.IsInstanceOf<IBinaryWriter>(context.Context);
+ }
+ }
+ }
+}