2018-02-07 23:40:46 +03:00
|
|
|
using System;
|
2017-02-27 04:54:57 +03:00
|
|
|
using System.IO;
|
2017-02-21 21:04:26 +03:00
|
|
|
using System.Runtime.Serialization;
|
2015-12-16 02:57:52 +03:00
|
|
|
using System.Runtime.Serialization.Formatters.Binary;
|
|
|
|
using System.Threading.Tasks;
|
2017-06-02 02:41:14 +03:00
|
|
|
using Newtonsoft.Json;
|
2015-12-16 02:57:52 +03:00
|
|
|
using Orleans;
|
2020-06-11 20:00:05 +03:00
|
|
|
using Orleans.Concurrency;
|
2017-02-27 04:54:57 +03:00
|
|
|
using Orleans.Runtime;
|
2017-02-21 21:04:26 +03:00
|
|
|
using Orleans.Serialization;
|
2017-02-27 04:54:57 +03:00
|
|
|
using Orleans.Storage;
|
2016-10-20 06:33:02 +03:00
|
|
|
using TestExtensions;
|
2015-12-16 02:57:52 +03:00
|
|
|
using UnitTests.GrainInterfaces;
|
2016-07-06 00:50:27 +03:00
|
|
|
using Xunit;
|
2020-06-11 20:00:05 +03:00
|
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
|
|
using Orleans.Runtime.Placement;
|
|
|
|
using Orleans.TestingHost;
|
2015-12-16 02:57:52 +03:00
|
|
|
|
2016-12-14 01:19:54 +03:00
|
|
|
namespace DefaultCluster.Tests.General
|
2015-12-16 02:57:52 +03:00
|
|
|
{
|
2020-06-11 20:00:05 +03:00
|
|
|
public interface IFooGrain : IGrain { }
|
|
|
|
|
|
|
|
[GrainType("foo`1")]
|
|
|
|
[StatelessWorker]
|
|
|
|
public class FooGrain : Grain, IFooGrain { }
|
2018-02-07 23:40:46 +03:00
|
|
|
|
2015-12-16 02:57:52 +03:00
|
|
|
/// <summary>
|
|
|
|
/// Summary description for GrainReferenceTest
|
|
|
|
/// </summary>
|
2019-10-03 00:11:51 +03:00
|
|
|
[TestCategory("BVT"), TestCategory("GrainReference")]
|
2016-01-10 04:06:20 +03:00
|
|
|
public class GrainReferenceTest : HostedTestClusterEnsureDefaultStarted
|
2015-12-16 02:57:52 +03:00
|
|
|
{
|
2017-01-19 00:39:41 +03:00
|
|
|
public GrainReferenceTest(DefaultClusterFixture fixture) : base(fixture)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2020-10-28 01:15:44 +03:00
|
|
|
[Fact]
|
|
|
|
public void GrainReferenceComparison_ShouldProduceUniformHashCode()
|
|
|
|
{
|
|
|
|
var simpleGrain = this.GrainFactory.GetGrain<ISimpleGrain>(1234L, UnitTests.Grains.SimpleGrain.SimpleGrainNamePrefix);
|
|
|
|
var r = simpleGrain as GrainReference;
|
|
|
|
Assert.NotNull(r);
|
|
|
|
|
|
|
|
// Hey there stranger. So the test failed here?
|
|
|
|
// It's probably because the way hash codes are generated for the GrainReference
|
|
|
|
// have changed. If you are sure the new code is repeatable, then it's fine to
|
|
|
|
// update the expected value here. Good luck, friend.
|
|
|
|
Assert.Equal(2223355815u, r.GetUniformHashCode());
|
|
|
|
}
|
|
|
|
|
2017-02-27 04:54:57 +03:00
|
|
|
[Fact]
|
2015-12-16 02:57:52 +03:00
|
|
|
public void GrainReferenceComparison_DifferentReference()
|
|
|
|
{
|
2017-01-19 00:39:41 +03:00
|
|
|
ISimpleGrain ref1 = this.GrainFactory.GetGrain<ISimpleGrain>(random.Next(), UnitTests.Grains.SimpleGrain.SimpleGrainNamePrefix);
|
|
|
|
ISimpleGrain ref2 = this.GrainFactory.GetGrain<ISimpleGrain>(random.Next(), UnitTests.Grains.SimpleGrain.SimpleGrainNamePrefix);
|
2016-07-15 21:48:37 +03:00
|
|
|
Assert.True(ref1 != ref2);
|
|
|
|
Assert.True(ref2 != ref1);
|
|
|
|
Assert.False(ref1 == ref2);
|
|
|
|
Assert.False(ref2 == ref1);
|
|
|
|
Assert.False(ref1.Equals(ref2));
|
|
|
|
Assert.False(ref2.Equals(ref1));
|
2015-12-16 02:57:52 +03:00
|
|
|
}
|
|
|
|
|
2019-10-03 00:11:51 +03:00
|
|
|
[Fact, TestCategory("BVT"), TestCategory("AsynchronyPrimitives")]
|
2015-12-16 02:57:52 +03:00
|
|
|
public void TaskCompletionSource_Resolve()
|
|
|
|
{
|
|
|
|
string str = "Hello TaskCompletionSource";
|
|
|
|
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
|
|
|
|
Task task = tcs.Task;
|
2016-07-15 21:48:37 +03:00
|
|
|
Assert.False(task.IsCompleted, "TCS.Task not yet completed");
|
2015-12-16 02:57:52 +03:00
|
|
|
tcs.SetResult(str);
|
2016-07-15 21:48:37 +03:00
|
|
|
Assert.True(task.IsCompleted, "TCS.Task is now completed");
|
|
|
|
Assert.False(task.IsFaulted, "TCS.Task should not be in faulted state: " + task.Exception);
|
|
|
|
Assert.Equal(str, tcs.Task.Result);
|
2015-12-16 02:57:52 +03:00
|
|
|
}
|
|
|
|
|
2017-02-27 04:54:57 +03:00
|
|
|
[Fact]
|
2015-12-16 02:57:52 +03:00
|
|
|
public void GrainReference_Pass_this()
|
|
|
|
{
|
2017-01-19 00:39:41 +03:00
|
|
|
IChainedGrain g1 = this.GrainFactory.GetGrain<IChainedGrain>(GetRandomGrainId());
|
|
|
|
IChainedGrain g2 = this.GrainFactory.GetGrain<IChainedGrain>(GetRandomGrainId());
|
2020-10-28 01:15:44 +03:00
|
|
|
|
2015-12-16 02:57:52 +03:00
|
|
|
g1.PassThis(g2).Wait();
|
|
|
|
}
|
|
|
|
|
2017-02-27 04:54:57 +03:00
|
|
|
[Fact]
|
2016-11-18 01:52:23 +03:00
|
|
|
public void GrainReference_Pass_this_Nested()
|
|
|
|
{
|
2017-01-19 00:39:41 +03:00
|
|
|
IChainedGrain g1 = this.GrainFactory.GetGrain<IChainedGrain>(GetRandomGrainId());
|
|
|
|
IChainedGrain g2 = this.GrainFactory.GetGrain<IChainedGrain>(GetRandomGrainId());
|
2016-11-18 01:52:23 +03:00
|
|
|
|
|
|
|
g1.PassThisNested(new ChainGrainHolder { Next = g2 }).Wait();
|
|
|
|
}
|
|
|
|
|
2017-02-27 04:54:57 +03:00
|
|
|
[Fact]
|
2017-02-22 08:52:28 +03:00
|
|
|
public async Task GrainReference_Pass_Null()
|
|
|
|
{
|
|
|
|
IChainedGrain g1 = this.GrainFactory.GetGrain<IChainedGrain>(GetRandomGrainId());
|
|
|
|
IChainedGrain g2 = this.GrainFactory.GetGrain<IChainedGrain>(GetRandomGrainId());
|
|
|
|
|
|
|
|
// g1 will pass a null reference to g2
|
|
|
|
await g1.PassNullNested(new ChainGrainHolder { Next = g2 });
|
|
|
|
Assert.Null(await g2.GetNext());
|
|
|
|
await g1.PassNull(g2);
|
|
|
|
Assert.Null(await g2.GetNext());
|
|
|
|
}
|
|
|
|
|
2017-02-27 04:54:57 +03:00
|
|
|
[Fact, TestCategory("Serialization")]
|
2015-12-16 02:57:52 +03:00
|
|
|
public void GrainReference_DotNet_Serialization()
|
|
|
|
{
|
|
|
|
int id = random.Next();
|
|
|
|
TestGrainReferenceSerialization(id, false, false);
|
|
|
|
}
|
|
|
|
|
2017-02-27 04:54:57 +03:00
|
|
|
[Fact, TestCategory("Serialization")]
|
2015-12-16 02:57:52 +03:00
|
|
|
public void GrainReference_DotNet_Serialization_Unresolved()
|
|
|
|
{
|
|
|
|
int id = random.Next();
|
|
|
|
TestGrainReferenceSerialization(id, false, false);
|
|
|
|
}
|
|
|
|
|
2017-02-27 04:54:57 +03:00
|
|
|
[Fact, TestCategory("Serialization"), TestCategory("JSON")]
|
2015-12-16 02:57:52 +03:00
|
|
|
public void GrainReference_Json_Serialization()
|
|
|
|
{
|
|
|
|
int id = random.Next();
|
|
|
|
TestGrainReferenceSerialization(id, true, true);
|
|
|
|
}
|
|
|
|
|
2017-06-02 02:41:14 +03:00
|
|
|
[Fact, TestCategory("Serialization"), TestCategory("JSON")]
|
|
|
|
public async Task GrainReference_Json_Serialization_Nested()
|
|
|
|
{
|
2020-06-11 20:00:05 +03:00
|
|
|
var settings = OrleansJsonSerializer.GetDefaultSerializerSettings(this.HostedCluster.Client.ServiceProvider);
|
2020-10-28 01:15:44 +03:00
|
|
|
|
2017-06-02 02:41:14 +03:00
|
|
|
var grain = HostedCluster.GrainFactory.GetGrain<ISimpleGrain>(GetRandomGrainId());
|
|
|
|
await grain.SetA(56820);
|
|
|
|
var input = new GenericGrainReferenceHolder
|
|
|
|
{
|
|
|
|
Reference = grain as GrainReference
|
|
|
|
};
|
|
|
|
|
|
|
|
var json = JsonConvert.SerializeObject(input, settings);
|
|
|
|
var output = JsonConvert.DeserializeObject<GenericGrainReferenceHolder>(json, settings);
|
|
|
|
|
|
|
|
Assert.Equal(input.Reference, output.Reference);
|
|
|
|
var reference = output.Reference;
|
|
|
|
Assert.Equal(56820, await ((ISimpleGrain)reference).GetA());
|
|
|
|
}
|
|
|
|
|
|
|
|
[Serializable]
|
|
|
|
public class GenericGrainReferenceHolder
|
|
|
|
{
|
|
|
|
[JsonProperty]
|
|
|
|
public GrainReference Reference { get; set; }
|
|
|
|
}
|
|
|
|
|
2017-02-27 04:54:57 +03:00
|
|
|
[Fact, TestCategory("Serialization"), TestCategory("JSON")]
|
2015-12-16 02:57:52 +03:00
|
|
|
public void GrainReference_Json_Serialization_Unresolved()
|
|
|
|
{
|
|
|
|
int id = random.Next();
|
|
|
|
TestGrainReferenceSerialization(id, false, true);
|
|
|
|
}
|
|
|
|
|
2017-02-27 04:54:57 +03:00
|
|
|
[Fact(Skip = "GrainReference interning is not currently implemented."), TestCategory("Serialization"), TestCategory("Interner")]
|
|
|
|
public void GrainReference_Interning_Sys_StoreGrain()
|
|
|
|
{
|
|
|
|
var g1 = (GrainReference)this.GrainFactory.GetGrain<IMemoryStorageGrain>(0);
|
|
|
|
var g2 = (GrainReference)this.GrainFactory.GetGrain<IMemoryStorageGrain>(0);
|
|
|
|
Assert.Equal(g1, g2); // Should be equal GrainReferences.
|
|
|
|
Assert.Same(g1, g2); // Should be same / interned GrainReference object
|
|
|
|
|
|
|
|
// Round-trip through Serializer
|
|
|
|
var g3 = this.HostedCluster.SerializationManager.RoundTripSerializationForTesting(g1);
|
|
|
|
Assert.Equal(g3, g1);
|
|
|
|
Assert.Equal(g3, g2);
|
|
|
|
Assert.Same(g3, g1);
|
|
|
|
Assert.Same(g3, g2);
|
|
|
|
}
|
|
|
|
|
2017-02-07 02:21:32 +03:00
|
|
|
private void TestGrainReferenceSerialization(int id, bool resolveBeforeSerialize, bool useJson)
|
2015-12-16 02:57:52 +03:00
|
|
|
{
|
|
|
|
// Make sure grain references serialize well through .NET serializer.
|
2017-02-07 02:21:32 +03:00
|
|
|
var grain = this.GrainFactory.GetGrain<ISimpleGrain>(random.Next(), UnitTests.Grains.SimpleGrain.SimpleGrainNamePrefix);
|
2015-12-16 02:57:52 +03:00
|
|
|
|
|
|
|
if (resolveBeforeSerialize)
|
|
|
|
{
|
|
|
|
grain.SetA(id).Wait(); // Resolve GR
|
|
|
|
}
|
|
|
|
|
2017-02-07 02:21:32 +03:00
|
|
|
ISimpleGrain other;
|
2015-12-16 02:57:52 +03:00
|
|
|
if (useJson)
|
|
|
|
{
|
2017-02-07 02:21:32 +03:00
|
|
|
// Serialize + Deserialize through Json serializer
|
2017-02-24 04:30:08 +03:00
|
|
|
other = NewtonsoftJsonSerializeRoundtrip(grain);
|
2015-12-16 02:57:52 +03:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2017-02-07 02:21:32 +03:00
|
|
|
// Serialize + Deserialize through .NET serializer
|
2017-02-24 04:30:08 +03:00
|
|
|
other = DotNetSerializeRoundtrip(grain);
|
2015-12-16 02:57:52 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
if (!resolveBeforeSerialize)
|
|
|
|
{
|
|
|
|
grain.SetA(id).Wait(); // Resolve GR
|
|
|
|
}
|
|
|
|
|
2016-07-15 21:48:37 +03:00
|
|
|
Assert.IsAssignableFrom(grain.GetType(), other);
|
2017-02-07 02:21:32 +03:00
|
|
|
Assert.NotNull(other);
|
|
|
|
Assert.Equal(grain, other); // "Deserialized grain reference equality is preserved"
|
|
|
|
int res = other.GetA().Result;
|
2016-07-15 21:48:37 +03:00
|
|
|
Assert.Equal(id, res); // "Returned values from call to deserialized grain reference"
|
2015-12-16 02:57:52 +03:00
|
|
|
}
|
|
|
|
|
2017-02-24 04:30:08 +03:00
|
|
|
private T DotNetSerializeRoundtrip<T>(T obj)
|
2015-12-16 02:57:52 +03:00
|
|
|
{
|
2017-02-07 02:21:32 +03:00
|
|
|
T other;
|
2015-12-16 02:57:52 +03:00
|
|
|
using (var memoryStream = new MemoryStream())
|
|
|
|
{
|
2017-02-21 21:04:26 +03:00
|
|
|
var formatter = new BinaryFormatter
|
|
|
|
{
|
2020-06-11 20:00:05 +03:00
|
|
|
Context = new StreamingContext(StreamingContextStates.All, new SerializationContext(this.HostedCluster.SerializationManager)),
|
|
|
|
SurrogateSelector = this.HostedCluster.Client.ServiceProvider.GetRequiredService<BinaryFormatterGrainReferenceSurrogateSelector>()
|
2017-02-21 21:04:26 +03:00
|
|
|
};
|
2015-12-16 02:57:52 +03:00
|
|
|
formatter.Serialize(memoryStream, obj);
|
|
|
|
memoryStream.Flush();
|
|
|
|
memoryStream.Position = 0; // Reset to start
|
2017-02-07 02:21:32 +03:00
|
|
|
other = (T)formatter.Deserialize(memoryStream);
|
2015-12-16 02:57:52 +03:00
|
|
|
}
|
|
|
|
return other;
|
|
|
|
}
|
|
|
|
|
2017-02-24 04:30:08 +03:00
|
|
|
private T NewtonsoftJsonSerializeRoundtrip<T>(T obj)
|
2015-12-16 02:57:52 +03:00
|
|
|
{
|
2020-06-11 20:00:05 +03:00
|
|
|
var settings = OrleansJsonSerializer.GetDefaultSerializerSettings(this.HostedCluster.Client.ServiceProvider);
|
2015-12-16 02:57:52 +03:00
|
|
|
// http://james.newtonking.com/json/help/index.html?topic=html/T_Newtonsoft_Json_JsonConvert.htm
|
2017-06-02 02:41:14 +03:00
|
|
|
string json = JsonConvert.SerializeObject(obj, settings);
|
|
|
|
object other = JsonConvert.DeserializeObject(json, typeof(T), settings);
|
2017-02-07 02:21:32 +03:00
|
|
|
return (T)other;
|
2015-12-16 02:57:52 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|