using System;
using JetBrains.Collections.Viewable;
using JetBrains.Diagnostics;
using JetBrains.Lifetimes;
using JetBrains.Rd;
using JetBrains.Rd.Base;
using JetBrains.Rd.Impl;
using NUnit.Framework;
using Test.Lifetimes;
using Test.RdFramework.Components;
namespace Test.RdFramework.Contexts
{
///
/// This test replicates a case that happens often in real world: one end is created,
/// and starts sending messages way before the other end is created/ready to receive messages
///
public class RdContextEarlyDeliveryTest : LifetimesTestBase
{
[Datapoint]
public static bool TrueDataPoint = true;
[Datapoint]
public static bool FalseDataPoint = false;
private IProtocol myClientProtocol;
private IProtocol myServerProtocol;
private TestWire myClientWire;
private TestWire myServerWire;
private IScheduler CreateScheduler()
{
var dispatcher = SynchronousScheduler.Instance;
dispatcher.SetActive(LifetimeDefinition.Lifetime);
return dispatcher;
}
private Serializers CreateSerializers()
{
return new Serializers();
}
public override void TearDown()
{
if (myServerWire.HasMessages)
throw new InvalidOperationException("There is messages in ServerWire");
if (myClientWire.HasMessages)
throw new InvalidOperationException("There is messages in ClientWire");
base.TearDown();
}
private T BindToClient(Lifetime lf, T x, int staticId) where T : IRdReactive
{
var reactive = x.Static(staticId);
reactive.BindTopLevel(lf, myClientProtocol, "client");
return x;
}
private T BindToServer(Lifetime lf, T x, int staticId) where T : IRdReactive
{
var reactive = x.Static(staticId);
reactive.BindTopLevel(lf, myServerProtocol, "server");
return x;
}
public class TestKeyHeavy : ThreadLocalRdContext
{
private TestKeyHeavy() : base("test-key", true, Serializers.ReadString, Serializers.WriteString)
{
}
public static readonly TestKeyHeavy Instance = new TestKeyHeavy();
protected internal override void RegisterOn(ISerializers serializers)
{
serializers.Register((_, __) => Instance, (_, __, ___) => { });
}
}
public class TestKeyLight : ThreadLocalRdContext
{
private TestKeyLight() : base("test-key", false, Serializers.ReadString, Serializers.WriteString)
{
}
public static readonly TestKeyLight Instance = new TestKeyLight();
protected internal override void RegisterOn(ISerializers serializers)
{
serializers.Register((_, __) => Instance, (_, __, ___) => { });
}
}
[Theory]
public void TestEarlyDelivery(bool heavy)
{
var key = heavy ? TestKeyHeavy.Instance : (RdContext) TestKeyLight.Instance;
var identities = new Identities(IdKind.Server);
var serverDispatcher = CreateScheduler();
var clientDispatcher = CreateScheduler();
var serverR = "Server (R#)";
myServerProtocol = new Protocol(serverR, CreateSerializers(), identities, serverDispatcher, new TestWire(serverDispatcher, serverR, true), LifetimeDefinition.Lifetime, key);
myServerWire = (myServerProtocol.Wire as TestWire).NotNull();
var clientIdea = "Client (IDEA)";
var clientWire = new TestWire(clientDispatcher, clientIdea, false);
myClientWire = clientWire;
myClientWire.Connection = myServerWire;
myServerWire.Connection = myClientWire;
myClientProtocol = new Protocol(clientIdea, CreateSerializers(), identities, clientDispatcher, clientWire, LifetimeDefinition.Lifetime, key);
myServerWire.AutoTransmitMode = true;
myClientWire.AutoTransmitMode = true;
var serverSignal = BindToServer(LifetimeDefinition.Lifetime, NewRdSignal(), 1);
using var _ = key.UpdateValue("1");
serverSignal.Fire("");
var clientSignal = BindToClient(LifetimeDefinition.Lifetime, NewRdSignal(), 1);
Lifetime.Using(lt =>
{
var fired = false;
clientSignal.Advise(lt, s =>
{
Assert.AreEqual("1", key.Value);
fired = true;
});
serverSignal.Fire("");
Assert.True(fired, "fired");
});
Assert.AreEqual("1", key.Value);
Lifetime.Using(lt =>
{
var fired = false;
serverSignal.Advise(lt, s =>
{
Assert.AreEqual("1", key.Value);
fired = true;
});
clientSignal.Fire("");
Assert.True(fired, "fired");
});
Assert.AreEqual("1", key.Value);
}
}
}