using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Sandbox.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame.Utilities;
using Xunit;
using P = AutoMiningScript.Program;
namespace AutoMiningScript.Tests
{
public class RuntimeBudgetTests
{
sealed class Rig
{
public readonly P Program = TestRig.Program();
public readonly Stub<IMyGridProgramRuntimeInfo> Runtime = new Stub<IMyGridProgramRuntimeInfo>();
public readonly Queue<MyIGCMessage> Incoming = new Queue<MyIGCMessage>();
public readonly List<P.Packet> Sent = new List<P.Packet>();
public Rig()
{
Runtime.Set("MaxInstructionCount", 50000).Set("CurrentInstructionCount", 0).Set("TimeSinceLastRun", TimeSpan.FromSeconds(1.0 / 60));
TestRig.SetBase(Program, "Runtime", Runtime.Value);
var broadcast = new Stub<IMyBroadcastListener>();
var unicast = new Stub<IMyUnicastListener>().Method("get_HasPendingMessage", a => Incoming.Count > 0)
.Method("AcceptMessage", a => Incoming.Dequeue());
var igc = new Stub<IMyIntergridCommunicationSystem>().Set("UnicastListener", unicast.Value)
.Method("RegisterBroadcastListener", a => broadcast.Value)
.Method("SendBroadcastMessage", a => Capture(a[1] as string))
.Method("SendUnicastMessage", a => { Capture(a[2] as string); return true; });
TestRig.SetBase(Program, "IGC", igc.Value); Program.Bus = new P.Wire(Program);
}
object Capture(string value) { P.Packet packet; Assert.True(P.Packet.TryDecode(value, "mining", out packet)); Sent.Add(packet); return null; }
public void Add(string session, long seq, string kind = "TELEMETRY",string peer="peer",long address=123)
{
var packet = new P.Packet { From = peer, Session = session, Seq = seq, Kind = kind, Id = session + seq, Body = new MyIni() };
Incoming.Enqueue(new MyIGCMessage(packet.Encode("mining"), "AMS2/mining", address));
}
}
sealed class BusyRole : P.RoleLogic
{
readonly Rig rig;
public bool Busy = true;
public int Ticks, Received;
public readonly List<P.Job> Jobs = new List<P.Job> { new P.Job { Id = "active", Owner = "miner-1", Progress = 12 } };
public BusyRole(Rig r) : base(r.Program) { rig = r; }
public override void Tick(double dt) { Ticks++; if (Busy) rig.Runtime.Set("CurrentInstructionCount", 34000); }
public override void Receive(P.Packet packet) { Received++; }
public override List<P.Job> GetJobs() { return Jobs; }
}
static void Set(P p, string name, object value) { typeof(P).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(p, value); }
[Fact]
public void BusyFrameDefersBackgroundWithoutErasingActiveProgressAndNextFrameContinues()
{
var rig = new Rig(); var role = new BusyRole(rig);
Set(rig.Program, "role", role); Set(rig.Program, "dashboard", new P.Dashboard(rig.Program));
Set(rig.Program, "nextDraw", double.MaxValue); Set(rig.Program, "nextSave", double.MaxValue);
rig.Add("session", 1); rig.Program.Main("", UpdateType.Update1);
Assert.Equal(1, role.Ticks); Assert.Equal(0, role.Received); Assert.Single(rig.Incoming);
Assert.Equal(1, rig.Program.BudgetDeferrals); Assert.Equal(12, role.Jobs[0].Progress); Assert.Equal("miner-1", role.Jobs[0].Owner);
role.Busy = false; rig.Runtime.Set("CurrentInstructionCount", 0);
rig.Program.Main("", UpdateType.Update1);
Assert.Equal(2, role.Ticks); Assert.Equal(1, role.Received); Assert.Empty(rig.Incoming);
}
[Fact]
public void IncomingBurstIsBoundedAndUnprocessedPacketsStayQueued()
{
var rig = new Rig(); for (int n = 1; n <= 10; n++) rig.Add("session", n);
int received = 0; rig.Program.Bus.Drain(p => received++);
Assert.Equal(4, received); Assert.Equal(6, rig.Incoming.Count);
rig.Runtime.Set("CurrentInstructionCount", 28000); rig.Program.Bus.Drain(p => received++);
Assert.Equal(4, received); Assert.Equal(6, rig.Incoming.Count);
rig.Runtime.Set("CurrentInstructionCount", 0); rig.Program.Bus.Drain(p => received++); rig.Program.Bus.Drain(p => received++);
Assert.Equal(10, received); Assert.Empty(rig.Incoming);
}
[Fact]
public void ReceiverCostStopsFurtherProcessingInTheSameFrame()
{
var rig = new Rig(); rig.Add("s", 1); rig.Add("s", 2);
int received = 0; rig.Program.Bus.Drain(p => { received++; rig.Runtime.Set("CurrentInstructionCount", 28000); });
Assert.Equal(1, received); Assert.Single(rig.Incoming);
}
[Fact]
public void RetriesAreLimitedPerFrameWithoutDroppingPendingMessages()
{
var rig = new Rig(); for (int n = 0; n < 8; n++) rig.Program.Bus.Send("JOB", "peer", new MyIni(), true, 123);
rig.Sent.Clear(); rig.Program.Now = 2;
rig.Program.Bus.Tick(); Assert.Equal(2, rig.Sent.Count); Assert.Equal(8, rig.Program.Bus.PendingCount);
rig.Program.Bus.Tick(); rig.Program.Bus.Tick(); rig.Program.Bus.Tick();
Assert.Equal(8, rig.Sent.Count); Assert.Equal(8, rig.Program.Bus.PendingCount);
}
[Fact]
public void ForgettingPeerStopsRetriesAndDuplicatesButPermitsFreshReconnection()
{
var rig=new Rig();int received=0;rig.Add("old",1,"HELLO");rig.Program.Bus.Drain(p=>received++);
rig.Program.Bus.Send("JOB","peer",new MyIni(),true);rig.Program.Bus.Send("COMMAND","peer",new MyIni(),true);
rig.Program.Bus.ForgetPeer("peer");Assert.Equal(0,rig.Program.Bus.PendingCount);
var peers=(IDictionary)typeof(P.Wire).GetField("peers",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.Empty(peers);rig.Add("old",1,"HELLO");rig.Program.Bus.Drain(p=>received++);Assert.Equal(1,received);Assert.Empty(peers);
rig.Add("old",2,"HELLO");rig.Program.Bus.Drain(p=>received++);Assert.Equal(2,received);Assert.Single(peers);
rig.Program.Bus.ForgetPeer("peer");rig.Add("replacement",1,"HELLO","peer",456);rig.Program.Bus.Drain(p=>received++);Assert.Equal(3,received);
Assert.Equal(456L,peers["peer"]);
}
[Fact]
public void DelayedAckCannotRecreateAForgottenAddressBinding()
{
var rig=new Rig();int received=0;rig.Add("original",1,"HELLO");rig.Program.Bus.Drain(p=>received++);
rig.Program.Bus.ForgetPeer("peer");rig.Add("original",2,"ACK");rig.Program.Bus.Drain(p=>received++);
var peers=(IDictionary)typeof(P.Wire).GetField("peers",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.Empty(peers);rig.Add("replacement",1,"HELLO","peer",456);rig.Program.Bus.Drain(p=>received++);Assert.Equal(2,received);
}
[Fact]
public void AckRequiresTheExpectedAddressAndDoesNotRegisterAPeer()
{
var rig=new Rig();rig.Program.Bus.Send("COMMAND","peer",new MyIni(),true,123);P.Packet sent=rig.Sent[0];
var body=new MyIni();body.Set("ack","Id",sent.Id);var ack=new P.Packet {From="peer",Session="s",Seq=1,Kind="ACK",Body=body};
rig.Incoming.Enqueue(new MyIGCMessage(ack.Encode("mining"),"AMS2/mining",456));rig.Program.Bus.Drain(p=>{});Assert.Equal(1,rig.Program.Bus.PendingCount);
rig.Incoming.Enqueue(new MyIGCMessage(ack.Encode("mining"),"AMS2/mining",123));rig.Program.Bus.Drain(p=>{});Assert.Equal(0,rig.Program.Bus.PendingCount);
var peers=(IDictionary)typeof(P.Wire).GetField("peers",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.Empty(peers);
}
[Fact]
public void RepeatedCleanupReleasesPeerLimitAndBoundsRetainedReplayStreams()
{
var rig=new Rig();int received=0;
for(int n=0;n<300;n++)
{
string name="renamed-"+n;rig.Add("session",1,"HELLO",name);rig.Program.Bus.Drain(p=>received++);rig.Program.Bus.ForgetPeer(name);
}
Assert.Equal(300,received);
var peers=(IDictionary)typeof(P.Wire).GetField("peers",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
var streams=(IDictionary)typeof(P.Wire).GetField("streams",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.Empty(peers);Assert.InRange(streams.Count,1,128);
}
[Fact]
public void RepeatedSessionChangesAndCleanupKeepRetiredSessionsBounded()
{
var rig=new Rig();int received=0;
for(int n=0;n<1300;n++) {rig.Add("s"+n,1);rig.Program.Bus.Drain(p=>received++);rig.Program.Bus.ForgetPeer("peer");}
Assert.Equal(1300,received);
var retired=(ICollection<string>)typeof(P.Wire).GetField("retired",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.InRange(retired.Count,1,1024);
rig.Add("s1298",2);rig.Program.Bus.Drain(p=>received++);Assert.Equal(1300,received);
}
[Fact]
public void ProtectedOccupantRejectsReusedIdBeforeRetiringItsRealSession()
{
var rig=new Rig();int received=0;rig.Add("original",1);rig.Program.Bus.Drain(p=>received++);
rig.Program.Bus.ProtectPeer("peer",123);rig.Program.Bus.ForgetPeer("peer");
rig.Add("replacement",1,"TELEMETRY","peer",456);rig.Program.Bus.Drain(p=>received++);Assert.Equal(1,received);
rig.Add("original",2);rig.Program.Bus.Drain(p=>received++);Assert.Equal(2,received);
rig.Program.Bus.ProtectPeer("peer",0);rig.Program.Bus.ForgetPeer("peer");rig.Add("replacement",2,"TELEMETRY","peer",456);rig.Program.Bus.Drain(p=>received++);Assert.Equal(3,received);
}
[Fact]
public void SessionCacheAutomaticallyReplacesOldStreamsButRejectsRetiredSessionReplay()
{
var rig = new Rig(); int received = 0;
for (int session = 0; session < 80; session++)
{
for (int kind = 0; kind < 32; kind++)
{
rig.Add("s" + session, kind + 1, "K" + kind);
rig.Program.Bus.Drain(p => received++);
}
}
Assert.Equal(2560, received);
var streams = (IDictionary)typeof(P.Wire).GetField("streams", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.Single(streams); Assert.Equal(32, ((IDictionary)streams["peer"]).Count);
rig.Add("s0", 1000, "K0"); rig.Program.Bus.Drain(p => received++); Assert.Equal(2560, received);
rig.Add("s79", 32, "K31"); rig.Program.Bus.Drain(p => received++); Assert.Equal(2560, received);
rig.Add("s80", 1, "K0"); rig.Program.Bus.Drain(p => received++); Assert.Equal(2561, received);
}
[Fact]
public void ClearingAndReplacingTasksDropsAnUnfinishedMapAndPublishedTotals()
{
var rig=new Rig();var role=new BusyRole(rig);role.Jobs.Clear();
for(int n=0;n<128;n++)role.Jobs.Add(new P.Job {Id="old"+n,RegionId="old-region",Outcome="Complete"});
var dashboard=new P.Dashboard(rig.Program);dashboard.Update(role);
role.Jobs.Clear();role.Jobs.Add(new P.Job {Id="new",RegionId="new-region",Outcome="Complete"});dashboard.Update(role);
var count=typeof(P.Dashboard).GetField("completedJobs",BindingFlags.Instance|BindingFlags.NonPublic);
Assert.Equal(1,(int)count.GetValue(dashboard));
role.Jobs.Clear();dashboard.Update(role);Assert.Equal(0,(int)count.GetValue(dashboard));
}
[Fact]
public void DisplayBuildsLargeMapAcrossFramesAndKeepsJobsUntouched()
{
var rig = new Rig(); var role = new BusyRole(rig); role.Jobs.Clear();
for (int n = 0; n < 2048; n++) role.Jobs.Add(new P.Job { Id = "job" + n, RegionId = "r", Outcome = "Complete" });
var dashboard = new P.Dashboard(rig.Program);
var count = typeof(P.Dashboard).GetField("completedJobs", BindingFlags.Instance | BindingFlags.NonPublic);
dashboard.Update(role); Assert.Equal(0, (int)count.GetValue(dashboard));
for (int n = 0; n < 31; n++) dashboard.Update(role);
Assert.Equal(2048, (int)count.GetValue(dashboard)); Assert.Equal(2048, role.Jobs.Count);
rig.Runtime.Set("CurrentInstructionCount", 30000); dashboard.ClearTransientCache(); dashboard.Update(role);
Assert.Equal(2048, (int)count.GetValue(dashboard));
}
}
}
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using Sandbox.ModAPI.Ingame;
using VRage.Game.ModAPI.Ingame.Utilities;
using Xunit;
using P = AutoMiningScript.Program;
namespace AutoMiningScript.Tests
{
public class RuntimeBudgetTests
{
sealed class Rig
{
public readonly P Program = TestRig.Program();
public readonly Stub<IMyGridProgramRuntimeInfo> Runtime = new Stub<IMyGridProgramRuntimeInfo>();
public readonly Queue<MyIGCMessage> Incoming = new Queue<MyIGCMessage>();
public readonly List<P.Packet> Sent = new List<P.Packet>();
public Rig()
{
Runtime.Set("MaxInstructionCount", 50000).Set("CurrentInstructionCount", 0).Set("TimeSinceLastRun", TimeSpan.FromSeconds(1.0 / 60));
TestRig.SetBase(Program, "Runtime", Runtime.Value);
var broadcast = new Stub<IMyBroadcastListener>();
var unicast = new Stub<IMyUnicastListener>().Method("get_HasPendingMessage", a => Incoming.Count > 0)
.Method("AcceptMessage", a => Incoming.Dequeue());
var igc = new Stub<IMyIntergridCommunicationSystem>().Set("UnicastListener", unicast.Value)
.Method("RegisterBroadcastListener", a => broadcast.Value)
.Method("SendBroadcastMessage", a => Capture(a[1] as string))
.Method("SendUnicastMessage", a => { Capture(a[2] as string); return true; });
TestRig.SetBase(Program, "IGC", igc.Value); Program.Bus = new P.Wire(Program);
}
object Capture(string value) { P.Packet packet; Assert.True(P.Packet.TryDecode(value, "mining", out packet)); Sent.Add(packet); return null; }
public void Add(string session, long seq, string kind = "TELEMETRY",string peer="peer",long address=123)
{
var packet = new P.Packet { From = peer, Session = session, Seq = seq, Kind = kind, Id = session + seq, Body = new MyIni() };
Incoming.Enqueue(new MyIGCMessage(packet.Encode("mining"), "AMS2/mining", address));
}
}
sealed class BusyRole : P.RoleLogic
{
readonly Rig rig;
public bool Busy = true;
public int Ticks, Received;
public readonly List<P.Job> Jobs = new List<P.Job> { new P.Job { Id = "active", Owner = "miner-1", Progress = 12 } };
public BusyRole(Rig r) : base(r.Program) { rig = r; }
public override void Tick(double dt) { Ticks++; if (Busy) rig.Runtime.Set("CurrentInstructionCount", 34000); }
public override void Receive(P.Packet packet) { Received++; }
public override List<P.Job> GetJobs() { return Jobs; }
}
static void Set(P p, string name, object value) { typeof(P).GetField(name, BindingFlags.Instance | BindingFlags.NonPublic).SetValue(p, value); }
[Fact]
public void BusyFrameDefersBackgroundWithoutErasingActiveProgressAndNextFrameContinues()
{
var rig = new Rig(); var role = new BusyRole(rig);
Set(rig.Program, "role", role); Set(rig.Program, "dashboard", new P.Dashboard(rig.Program));
Set(rig.Program, "nextDraw", double.MaxValue); Set(rig.Program, "nextSave", double.MaxValue);
rig.Add("session", 1); rig.Program.Main("", UpdateType.Update1);
Assert.Equal(1, role.Ticks); Assert.Equal(0, role.Received); Assert.Single(rig.Incoming);
Assert.Equal(1, rig.Program.BudgetDeferrals); Assert.Equal(12, role.Jobs[0].Progress); Assert.Equal("miner-1", role.Jobs[0].Owner);
role.Busy = false; rig.Runtime.Set("CurrentInstructionCount", 0);
rig.Program.Main("", UpdateType.Update1);
Assert.Equal(2, role.Ticks); Assert.Equal(1, role.Received); Assert.Empty(rig.Incoming);
}
[Fact]
public void IncomingBurstIsBoundedAndUnprocessedPacketsStayQueued()
{
var rig = new Rig(); for (int n = 1; n <= 10; n++) rig.Add("session", n);
int received = 0; rig.Program.Bus.Drain(p => received++);
Assert.Equal(4, received); Assert.Equal(6, rig.Incoming.Count);
rig.Runtime.Set("CurrentInstructionCount", 28000); rig.Program.Bus.Drain(p => received++);
Assert.Equal(4, received); Assert.Equal(6, rig.Incoming.Count);
rig.Runtime.Set("CurrentInstructionCount", 0); rig.Program.Bus.Drain(p => received++); rig.Program.Bus.Drain(p => received++);
Assert.Equal(10, received); Assert.Empty(rig.Incoming);
}
[Fact]
public void ReceiverCostStopsFurtherProcessingInTheSameFrame()
{
var rig = new Rig(); rig.Add("s", 1); rig.Add("s", 2);
int received = 0; rig.Program.Bus.Drain(p => { received++; rig.Runtime.Set("CurrentInstructionCount", 28000); });
Assert.Equal(1, received); Assert.Single(rig.Incoming);
}
[Fact]
public void RetriesAreLimitedPerFrameWithoutDroppingPendingMessages()
{
var rig = new Rig(); for (int n = 0; n < 8; n++) rig.Program.Bus.Send("JOB", "peer", new MyIni(), true, 123);
rig.Sent.Clear(); rig.Program.Now = 2;
rig.Program.Bus.Tick(); Assert.Equal(2, rig.Sent.Count); Assert.Equal(8, rig.Program.Bus.PendingCount);
rig.Program.Bus.Tick(); rig.Program.Bus.Tick(); rig.Program.Bus.Tick();
Assert.Equal(8, rig.Sent.Count); Assert.Equal(8, rig.Program.Bus.PendingCount);
}
[Fact]
public void ForgettingPeerStopsRetriesAndDuplicatesButPermitsFreshReconnection()
{
var rig=new Rig();int received=0;rig.Add("old",1,"HELLO");rig.Program.Bus.Drain(p=>received++);
rig.Program.Bus.Send("JOB","peer",new MyIni(),true);rig.Program.Bus.Send("COMMAND","peer",new MyIni(),true);
rig.Program.Bus.ForgetPeer("peer");Assert.Equal(0,rig.Program.Bus.PendingCount);
var peers=(IDictionary)typeof(P.Wire).GetField("peers",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.Empty(peers);rig.Add("old",1,"HELLO");rig.Program.Bus.Drain(p=>received++);Assert.Equal(1,received);Assert.Empty(peers);
rig.Add("old",2,"HELLO");rig.Program.Bus.Drain(p=>received++);Assert.Equal(2,received);Assert.Single(peers);
rig.Program.Bus.ForgetPeer("peer");rig.Add("replacement",1,"HELLO","peer",456);rig.Program.Bus.Drain(p=>received++);Assert.Equal(3,received);
Assert.Equal(456L,peers["peer"]);
}
[Fact]
public void DelayedAckCannotRecreateAForgottenAddressBinding()
{
var rig=new Rig();int received=0;rig.Add("original",1,"HELLO");rig.Program.Bus.Drain(p=>received++);
rig.Program.Bus.ForgetPeer("peer");rig.Add("original",2,"ACK");rig.Program.Bus.Drain(p=>received++);
var peers=(IDictionary)typeof(P.Wire).GetField("peers",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.Empty(peers);rig.Add("replacement",1,"HELLO","peer",456);rig.Program.Bus.Drain(p=>received++);Assert.Equal(2,received);
}
[Fact]
public void AckRequiresTheExpectedAddressAndDoesNotRegisterAPeer()
{
var rig=new Rig();rig.Program.Bus.Send("COMMAND","peer",new MyIni(),true,123);P.Packet sent=rig.Sent[0];
var body=new MyIni();body.Set("ack","Id",sent.Id);var ack=new P.Packet {From="peer",Session="s",Seq=1,Kind="ACK",Body=body};
rig.Incoming.Enqueue(new MyIGCMessage(ack.Encode("mining"),"AMS2/mining",456));rig.Program.Bus.Drain(p=>{});Assert.Equal(1,rig.Program.Bus.PendingCount);
rig.Incoming.Enqueue(new MyIGCMessage(ack.Encode("mining"),"AMS2/mining",123));rig.Program.Bus.Drain(p=>{});Assert.Equal(0,rig.Program.Bus.PendingCount);
var peers=(IDictionary)typeof(P.Wire).GetField("peers",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.Empty(peers);
}
[Fact]
public void RepeatedCleanupReleasesPeerLimitAndBoundsRetainedReplayStreams()
{
var rig=new Rig();int received=0;
for(int n=0;n<300;n++)
{
string name="renamed-"+n;rig.Add("session",1,"HELLO",name);rig.Program.Bus.Drain(p=>received++);rig.Program.Bus.ForgetPeer(name);
}
Assert.Equal(300,received);
var peers=(IDictionary)typeof(P.Wire).GetField("peers",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
var streams=(IDictionary)typeof(P.Wire).GetField("streams",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.Empty(peers);Assert.InRange(streams.Count,1,128);
}
[Fact]
public void RepeatedSessionChangesAndCleanupKeepRetiredSessionsBounded()
{
var rig=new Rig();int received=0;
for(int n=0;n<1300;n++) {rig.Add("s"+n,1);rig.Program.Bus.Drain(p=>received++);rig.Program.Bus.ForgetPeer("peer");}
Assert.Equal(1300,received);
var retired=(ICollection<string>)typeof(P.Wire).GetField("retired",BindingFlags.Instance|BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.InRange(retired.Count,1,1024);
rig.Add("s1298",2);rig.Program.Bus.Drain(p=>received++);Assert.Equal(1300,received);
}
[Fact]
public void ProtectedOccupantRejectsReusedIdBeforeRetiringItsRealSession()
{
var rig=new Rig();int received=0;rig.Add("original",1);rig.Program.Bus.Drain(p=>received++);
rig.Program.Bus.ProtectPeer("peer",123);rig.Program.Bus.ForgetPeer("peer");
rig.Add("replacement",1,"TELEMETRY","peer",456);rig.Program.Bus.Drain(p=>received++);Assert.Equal(1,received);
rig.Add("original",2);rig.Program.Bus.Drain(p=>received++);Assert.Equal(2,received);
rig.Program.Bus.ProtectPeer("peer",0);rig.Program.Bus.ForgetPeer("peer");rig.Add("replacement",2,"TELEMETRY","peer",456);rig.Program.Bus.Drain(p=>received++);Assert.Equal(3,received);
}
[Fact]
public void SessionCacheAutomaticallyReplacesOldStreamsButRejectsRetiredSessionReplay()
{
var rig = new Rig(); int received = 0;
for (int session = 0; session < 80; session++)
{
for (int kind = 0; kind < 32; kind++)
{
rig.Add("s" + session, kind + 1, "K" + kind);
rig.Program.Bus.Drain(p => received++);
}
}
Assert.Equal(2560, received);
var streams = (IDictionary)typeof(P.Wire).GetField("streams", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(rig.Program.Bus);
Assert.Single(streams); Assert.Equal(32, ((IDictionary)streams["peer"]).Count);
rig.Add("s0", 1000, "K0"); rig.Program.Bus.Drain(p => received++); Assert.Equal(2560, received);
rig.Add("s79", 32, "K31"); rig.Program.Bus.Drain(p => received++); Assert.Equal(2560, received);
rig.Add("s80", 1, "K0"); rig.Program.Bus.Drain(p => received++); Assert.Equal(2561, received);
}
[Fact]
public void ClearingAndReplacingTasksDropsAnUnfinishedMapAndPublishedTotals()
{
var rig=new Rig();var role=new BusyRole(rig);role.Jobs.Clear();
for(int n=0;n<128;n++)role.Jobs.Add(new P.Job {Id="old"+n,RegionId="old-region",Outcome="Complete"});
var dashboard=new P.Dashboard(rig.Program);dashboard.Update(role);
role.Jobs.Clear();role.Jobs.Add(new P.Job {Id="new",RegionId="new-region",Outcome="Complete"});dashboard.Update(role);
var count=typeof(P.Dashboard).GetField("completedJobs",BindingFlags.Instance|BindingFlags.NonPublic);
Assert.Equal(1,(int)count.GetValue(dashboard));
role.Jobs.Clear();dashboard.Update(role);Assert.Equal(0,(int)count.GetValue(dashboard));
}
[Fact]
public void DisplayBuildsLargeMapAcrossFramesAndKeepsJobsUntouched()
{
var rig = new Rig(); var role = new BusyRole(rig); role.Jobs.Clear();
for (int n = 0; n < 2048; n++) role.Jobs.Add(new P.Job { Id = "job" + n, RegionId = "r", Outcome = "Complete" });
var dashboard = new P.Dashboard(rig.Program);
var count = typeof(P.Dashboard).GetField("completedJobs", BindingFlags.Instance | BindingFlags.NonPublic);
dashboard.Update(role); Assert.Equal(0, (int)count.GetValue(dashboard));
for (int n = 0; n < 31; n++) dashboard.Update(role);
Assert.Equal(2048, (int)count.GetValue(dashboard)); Assert.Equal(2048, role.Jobs.Count);
rig.Runtime.Set("CurrentInstructionCount", 30000); dashboard.ClearTransientCache(); dashboard.Update(role);
Assert.Equal(2048, (int)count.GetValue(dashboard));
}
}
}