public void ShouldHandleSlaveTimeSourceWithNotAlignedQuantum() { using (var timeSource = new MasterTimeSource { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) using (var timeSlave = new SlaveTimeSource(null) { Quantum = TimeInterval.FromTicks(3), AdvanceImmediately = true }) { var timeSink = new SimpleTimeSink(1.0); timeSource.RegisterSink(timeSlave); timeSlave.RegisterSink(timeSink); // the first round does not increment the time - it just triggers a sync point timeSource.Run(1); Assert.AreEqual(1, timeSource.NumberOfSyncPoints); Assert.AreEqual(0, timeSlave.NumberOfSyncPoints); Assert.AreEqual(0, timeSink.NumberOfRounds); Assert.AreEqual(0, timeSource.ElapsedVirtualTime.Ticks); Assert.AreEqual(0, timeSlave.ElapsedVirtualTime.Ticks); Assert.AreEqual(0, timeSink.ElapsedVirtualTime.Ticks); timeSource.Run(1); Assert.AreEqual(2, timeSource.NumberOfSyncPoints); Assert.AreEqual(4, timeSlave.NumberOfSyncPoints); Assert.AreEqual(3, timeSink.NumberOfRounds); Assert.AreEqual(10, timeSource.ElapsedVirtualTime.Ticks); Assert.AreEqual(9, timeSlave.ElapsedVirtualTime.Ticks); Assert.AreEqual(9, timeSink.ElapsedVirtualTime.Ticks); timeSource.Run(1); Assert.AreEqual(3, timeSource.NumberOfSyncPoints); Assert.AreEqual(7, timeSlave.NumberOfSyncPoints); Assert.AreEqual(6, timeSink.NumberOfRounds); Assert.AreEqual(20, timeSource.ElapsedVirtualTime.Ticks); Assert.AreEqual(18, timeSlave.ElapsedVirtualTime.Ticks); Assert.AreEqual(18, timeSink.ElapsedVirtualTime.Ticks); timeSource.Run(1); Assert.AreEqual(4, timeSource.NumberOfSyncPoints); Assert.AreEqual(11, timeSlave.NumberOfSyncPoints); Assert.AreEqual(10, timeSink.NumberOfRounds); Assert.AreEqual(30, timeSource.ElapsedVirtualTime.Ticks); Assert.AreEqual(30, timeSlave.ElapsedVirtualTime.Ticks); Assert.AreEqual(30, timeSink.ElapsedVirtualTime.Ticks); } }
public void ShouldSleep() { const int slavesCount = 5; const int roundsCount = 3; using (var timeSource = new MasterTimeSource() { Quantum = TimeInterval.FromMilliseconds(1000), AdvanceImmediately = false }) { var timeSinks = new SimpleTimeSink[slavesCount]; for (int i = 0; i < slavesCount; i++) { timeSinks[i] = new SimpleTimeSink(double.MaxValue); timeSource.RegisterSink(timeSinks[i]); } var sw = Stopwatch.StartNew(); // the first round does not increment the time - it just triggers a sync point timeSource.Run(roundsCount + 1); var after = sw.Elapsed; Assert.IsTrue(after.TotalSeconds > roundsCount); } }
public void ShouldExecuteDelayedActionAddedLaterInNearestSyncedState() { var time = TimeInterval.Empty; using (var master = new MasterTimeSource { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) using (var timeSlave = new SlaveTimeSource(null) { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) { var timeSink = new SimpleTimeSink(1.0, (sts, th, ti) => { if (sts.NumberOfRounds == 10) { timeSlave.ExecuteInNearestSyncedState(ts => { time = ts.TimeElapsed; }); } return(true); }); master.RegisterSink(timeSlave); timeSlave.RegisterSink(timeSink); // the first round does not increment the time - it just triggers a sync point master.Run(10 + 1); Assert.AreEqual(100, time.Ticks); } }
public void ShouldHandleMultipleSinks() { const int slavesCount = 5; const int roundsCount = 3; using (var masterTimeSource = new MasterTimeSource()) { var timeSinks = new SimpleTimeSink[slavesCount]; for (int i = 0; i < slavesCount; i++) { timeSinks[i] = new SimpleTimeSink(double.MaxValue); masterTimeSource.RegisterSink(timeSinks[i]); } // the first round does not increment the time - it just triggers a sync point masterTimeSource.Run(roundsCount + 1); Assert.AreEqual(roundsCount + 1, masterTimeSource.NumberOfSyncPoints); for (int i = 0; i < slavesCount; i++) { Assert.AreEqual(roundsCount * masterTimeSource.Quantum.Ticks, timeSinks[i].ElapsedVirtualTime.Ticks); Assert.AreEqual(roundsCount, timeSinks[i].NumberOfRounds); } } }
public void ShouldHandleSlaveTimeSourceWithDifferentQuantum() { const int roundsCount = 3; using (var timeSource = new MasterTimeSource { Quantum = TimeInterval.FromTicks(100), AdvanceImmediately = true }) using (var timeSlave = new SlaveTimeSource(null) { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) { var timeSink = new SimpleTimeSink(1.0); timeSource.RegisterSink(timeSlave); timeSlave.RegisterSink(timeSink); // the first round does not increment the time - it just triggers a sync point timeSource.Run(roundsCount + 1); Assert.AreEqual(roundsCount + 1, timeSource.NumberOfSyncPoints); Assert.AreEqual(10 * roundsCount + 1, timeSlave.NumberOfSyncPoints); Assert.AreEqual(10 * roundsCount, timeSink.NumberOfRounds); Assert.AreEqual(roundsCount * timeSource.Quantum.Ticks, timeSource.ElapsedVirtualTime.Ticks); Assert.AreEqual(roundsCount * timeSource.Quantum.Ticks, timeSlave.ElapsedVirtualTime.Ticks); Assert.AreEqual(roundsCount * timeSource.Quantum.Ticks, timeSink.ElapsedVirtualTime.Ticks); } }
public void ShouldExecuteDelayedActionInNearestSyncedStateExactlyOnce() { var time = TimeInterval.Empty; var alreadyDone = false; using (var master = new MasterTimeSource { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) using (var timeSlave = new SlaveTimeSource(null) { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) { var timeSink = new SimpleTimeSink(1.0, (sts, th, ti) => { if (alreadyDone) { return(true); } timeSlave.ExecuteInNearestSyncedState(ts => { time = ts.TimeElapsed; }); alreadyDone = true; return(true); }); master.RegisterSink(timeSlave); timeSlave.RegisterSink(timeSink); master.Run(1); Assert.AreEqual(0, time.Ticks); Assert.AreEqual(false, alreadyDone); // here we must run 2 rounds as delayed actions are executed at the beginning of each round master.Run(1); Assert.AreEqual(true, alreadyDone); Assert.AreEqual(10, time.Ticks); master.Run(1); Assert.AreEqual(10, time.Ticks); } }
public void RunToNearestSyncPoint() { if (IsStarted) { throw new RecoverableException("This action is not available when emulation is already started"); } InnerStartAll(); MasterTimeSource.Run(); InnerPauseAll(); }
public void ShouldNotTickDisconnectedSlaveTimeSource() { using (var master = new MasterTimeSource { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) using (var timeSlave = new SlaveTimeSource(null) { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) { var timeSink = new SimpleTimeSink(1.0); master.RegisterSink(timeSlave); timeSlave.RegisterSink(timeSink); // the first round does not increment the time - it just triggers a sync point master.Run(1 + 1); Assert.AreEqual(2, master.NumberOfSyncPoints); Assert.AreEqual(2, timeSlave.NumberOfSyncPoints); Assert.AreEqual(1, timeSink.NumberOfRounds); Assert.AreEqual(10, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(10, timeSlave.ElapsedVirtualTime.Ticks); Assert.AreEqual(10, timeSink.ElapsedVirtualTime.Ticks); timeSlave.TimeHandle.Dispose(); master.Run(1); Assert.AreEqual(3, master.NumberOfSyncPoints); Assert.AreEqual(2, timeSlave.NumberOfSyncPoints); Assert.AreEqual(1, timeSink.NumberOfRounds); Assert.AreEqual(20, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(10, timeSlave.ElapsedVirtualTime.Ticks); Assert.AreEqual(10, timeSink.ElapsedVirtualTime.Ticks); } }
public void ShouldExecuteNonAlignedDelayedActionInSyncedStateExactlyOnce() { var time = TimeInterval.Empty; using (var master = new MasterTimeSource { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) using (var timeSlave = new SlaveTimeSource(null) { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) { var timeSink = new SimpleTimeSink(1.0, (sts, th, ti) => { if (sts.NumberOfRounds != 1) { return(true); } timeSlave.ExecuteInSyncedState(ts => { time = timeSlave.ElapsedVirtualTime; }, new TimeStamp(TimeInterval.FromTicks(31), master.Domain)); return(true); }); master.RegisterSink(timeSlave); timeSlave.RegisterSink(timeSink); master.Run(4); Assert.AreEqual(0, time.Ticks); master.Run(1); Assert.AreEqual(40, time.Ticks); master.Run(1); Assert.AreEqual(40, time.Ticks); } }
public void ShouldCalculateCumulativeLoadForLowPerformance() { const int slavesCount = 5; const int roundsCount = 3; using (var timeSource = new MasterTimeSource() { Quantum = TimeInterval.FromTicks(1000000), AdvanceImmediately = false }) { var timeSinks = new SimpleTimeSink[slavesCount]; for (int i = 0; i < slavesCount; i++) { timeSinks[i] = new SimpleTimeSink(0.1); timeSource.RegisterSink(timeSinks[i]); } timeSource.Run(roundsCount); Assert.AreEqual(10.0, timeSource.CumulativeLoad, 0.05); } }
public void ShouldCalculateCumulativeLoadForIndefinitePerformance() { const int slavesCount = 5; const int roundsCount = 3; using (var timeSource = new MasterTimeSource() { Quantum = TimeInterval.FromTicks(1000000), AdvanceImmediately = true }) { var timeSinks = new SimpleTimeSink[slavesCount]; for (int i = 0; i < slavesCount; i++) { timeSinks[i] = new SimpleTimeSink(double.MaxValue); timeSource.RegisterSink(timeSinks[i]); } timeSource.Run(roundsCount); Assert.IsTrue(timeSource.CumulativeLoad < 0.1); } }
public void ShouldHandleBlockingAtTheEndOfGrantedInterval() { var indicator = false; using (var master = new MasterTimeSource { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) using (var timeSlave = new SlaveTimeSource(null) { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) using (var timeSink = new MoreComplicatedTimeSink("A")) { // tester thread new Thread(() => { this.Trace(); timeSink.ExecuteOnDispatcherThread((ts, ti) => { this.Trace(); Assert.AreEqual(10, ti.Ticks); ts.TimeHandle.ReportBackAndBreak(TimeInterval.Empty); }); this.Trace(); // here we sleep to make sure that master won't go further Thread.Sleep(5000); this.Trace(); Assert.AreEqual(10, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(10, timeSlave.ElapsedVirtualTime.Ticks); indicator = true; this.Trace(); timeSink.ExecuteOnDispatcherThread((ts, ti) => { this.Trace(); Assert.AreEqual(0, ti.Ticks); ts.TimeHandle.ReportBackAndContinue(TimeInterval.Empty); }); timeSink.ExecuteOnDispatcherThread((ts, ti) => { this.Trace(); Assert.AreEqual(10, ti.Ticks); ts.TimeHandle.ReportBackAndContinue(TimeInterval.Empty); }); }) { Name = "tester thread" }.Start(); master.RegisterSink(timeSlave); timeSlave.RegisterSink(timeSink); // just to pass the first syncpoint master.Run(1); this.Trace(); master.Run(1); this.Trace(); Assert.IsTrue(indicator); Assert.AreEqual(10, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(10, timeSlave.ElapsedVirtualTime.Ticks); master.Run(1); Assert.AreEqual(20, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(20, timeSlave.ElapsedVirtualTime.Ticks); } }
public void ShouldHandleTwoBlockingSinks() { var indicator = false; using (var master = new MasterTimeSource { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) using (var timeSlave = new SlaveTimeSource(null) { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) using (var timeSinkA2 = new MoreComplicatedTimeSink("A")) using (var timeSinkB2 = new MoreComplicatedTimeSink("B")) { var ttt = new Thread(() => { Parallel( () => { timeSinkA2.ExecuteOnDispatcherThread((sts, ti) => { this.Trace(); Assert.AreEqual(10, ti.Ticks); var timeUsed = TimeInterval.FromTicks(4); var timeLeft = ti - timeUsed; sts.TimeHandle.ReportBackAndBreak(timeLeft); }); }, () => { timeSinkB2.ExecuteOnDispatcherThread((sts, ti) => { this.Trace(); Assert.AreEqual(10, ti.Ticks); var timeUsed = TimeInterval.FromTicks(6); var timeLeft = ti - timeUsed; sts.TimeHandle.ReportBackAndBreak(timeLeft); }); } ); // here we sleep to make sure that master won't go further this.Trace(); Thread.Sleep(5000); this.Trace(); Assert.AreEqual(4, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(4, timeSlave.ElapsedVirtualTime.Ticks); Parallel( () => { timeSinkA2.ExecuteOnDispatcherThread((sts, ti) => { this.Trace(); Assert.AreEqual(6, ti.Ticks); var timeUsed = TimeInterval.FromTicks(4); var timeLeft = ti - timeUsed; sts.TimeHandle.ReportBackAndBreak(timeLeft); }); }, () => { timeSinkB2.ExecuteOnDispatcherThread((sts, ti) => { this.Trace(); Assert.AreEqual(4, ti.Ticks); sts.TimeHandle.ReportBackAndBreak(ti); }); } ); // here we sleep to make sure that master won't go further this.Trace(); Thread.Sleep(5000); this.Trace(); Assert.AreEqual(6, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(6, timeSlave.ElapsedVirtualTime.Ticks); Parallel( () => { timeSinkA2.ExecuteOnDispatcherThread((sts, ti) => { this.Trace(); Assert.AreEqual(2, ti.Ticks); sts.TimeHandle.ReportBackAndBreak(ti); }); }, () => { timeSinkB2.ExecuteOnDispatcherThread((sts, ti) => { this.Trace(); Assert.AreEqual(4, ti.Ticks); sts.TimeHandle.ReportBackAndContinue(TimeInterval.Empty); }); } ); // here we sleep to make sure that master won't go further this.Trace(); Thread.Sleep(5000); this.Trace(); Assert.AreEqual(8, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(8, timeSlave.ElapsedVirtualTime.Ticks); Parallel( () => { timeSinkA2.ExecuteOnDispatcherThread((sts, ti) => { this.Trace(); Assert.AreEqual(2, ti.Ticks); indicator = true; sts.TimeHandle.ReportBackAndContinue(TimeInterval.Empty); }); }, () => { timeSinkB2.ExecuteOnDispatcherThread((sts, ti) => { this.Trace(); Assert.Fail(); }, false); // do not wait for finish Thread.Sleep(10000); // wait for 10s and check if Fail() is called } ); }) { Name = "tester thread" }; ttt.Start(); master.RegisterSink(timeSlave); timeSlave.RegisterSink(timeSinkA2); timeSlave.RegisterSink(timeSinkB2); // just to pass the first syncpoint master.Run(1); master.Run(1); Assert.IsTrue(indicator); this.Trace(); Assert.AreEqual(10, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(10, timeSlave.ElapsedVirtualTime.Ticks); ttt.Join(); } }
public void ShouldUpdateExecutedTimeAfterBlocking() { var indicator = false; var firstTime = true; var threadToSinkSync = new ManualResetEvent(false); var sinkToThreadSync = new ManualResetEvent(false); using (var master = new MasterTimeSource { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) using (var timeSlave = new SlaveTimeSource(null) { Quantum = TimeInterval.FromTicks(10), AdvanceImmediately = true }) { var timeSink = new SimpleTimeSink(1.0, (sts, th, ti) => { if (firstTime) { Assert.AreEqual(10, ti.Ticks); firstTime = false; var timeUsed = TimeInterval.FromTicks(ti.Ticks / 2); var timeLeft = ti - timeUsed; sts.ElapsedVirtualTime += timeUsed; th.ReportBackAndBreak(timeLeft); sinkToThreadSync.Set(); threadToSinkSync.WaitOne(); } else { Assert.AreEqual(5, ti.Ticks); sts.ElapsedVirtualTime += ti; th.ReportBackAndContinue(TimeInterval.Empty); } return(false); }); // tester thread new Thread(() => { // wait for the pause sinkToThreadSync.WaitOne(); // here we sleep to make sure that master won't go further Thread.Sleep(5000); Assert.AreEqual(5, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(5, timeSlave.ElapsedVirtualTime.Ticks); indicator = true; threadToSinkSync.Set(); }).Start(); master.RegisterSink(timeSlave); timeSlave.RegisterSink(timeSink); // just to pass the first syncpoint master.Run(1); master.Run(1); Assert.IsTrue(indicator); Assert.AreEqual(10, master.ElapsedVirtualTime.Ticks); Assert.AreEqual(10, timeSlave.ElapsedVirtualTime.Ticks); Assert.AreEqual(10, timeSink.ElapsedVirtualTime.Ticks); } }