using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Azimuth; namespace Foundations.UnitTests { public class ProtectedLoopTests : UnitTestSharp.TestFixture { public void CallsAction() { bool called = false; Func action = () => { called = true; return LoopState.Done; }; var loop = new ProtectedLoop(action, exception => false); loop.Iterate(); Check(called); } public void ReturnsTrueOnBusy() { var loop = new ProtectedLoop(() => LoopState.Busy, exception => false); CheckTrue(loop.Iterate()); } public void ReturnsTrueOnIdle() { var loop = new ProtectedLoop(() => LoopState.Idle, exception => false); CheckTrue(loop.Iterate()); } public void ReturnsFalseOnDone() { var loop = new ProtectedLoop(() => LoopState.Done, exception => false); CheckFalse(loop.Iterate()); } public void TimingsUpdatedOnBusy() { var loop = new ProtectedLoop(() => LoopState.Busy, exception => false); loop.Iterate(); CheckNotEqual(0, loop.WeightedCycleTimes); } public void TimingsNotUpdatedOnIdle() { var loop = new ProtectedLoop(() => LoopState.Idle, exception => false); loop.Iterate(); CheckEqual(0, loop.WeightedCycleTimes); } public void TimingsUpdatedOnDone() { var loop = new ProtectedLoop(() => LoopState.Done, exception => false); loop.Iterate(); CheckNotEqual(0, loop.WeightedCycleTimes); } public void ThreadRespondsToAbort() { bool ready = false; Func action = () => { ready = true; System.Threading.Thread.Sleep(10000); return LoopState.Busy; }; var loop = new ProtectedLoop(action, exception => true); var thread = new System.Threading.Thread(() => { while (loop.Iterate()); }); thread.Start(); System.Threading.SpinWait.SpinUntil(() => ready); thread.Abort(); thread.Join(); } public void PulseChangeEventFiresPauseEvent() { bool? value = null; var loop = new ProtectedLoop(() => LoopState.Busy, exception => true); loop.Paused.OnChanged += newValue => { value = newValue; }; loop.PulseChangeEvents(); CheckEqual(false, value); } public void PulseChangeEventFiresPauseEventWithCorrectValue() { bool? value = null; var loop = new ProtectedLoop(() => LoopState.Busy, exception => true); loop.Paused.Set(true); loop.Paused.OnChanged += newValue => { value = newValue; }; loop.PulseChangeEvents(); CheckEqual(true, value); } public void ForceCrashForwardsToExceptionHandler() { Exception localException = null; ProtectedLoop.TryHandleExceptionDelegate exceptionHandler = exception => { localException = exception; return false; }; var loop = new ProtectedLoop(() => LoopState.Done, exceptionHandler); loop.ForceCrash(); loop.Iterate(); CheckNotNull(localException); } public void ThreadAbortDoesNotForwardToExceptionHandler() { Exception localException = null; ProtectedLoop.TryHandleExceptionDelegate exceptionHandler = exception => { localException = exception; return false; }; var loop = new ProtectedLoop(() => LoopState.Done, exceptionHandler); var thread = new System.Threading.Thread(() => { while (loop.Iterate()); }); thread.Start(); thread.Abort(); thread.Join(); CheckNull(localException); } public void CrashPausesIteration() { Exception localException = null; ProtectedLoop.TryHandleExceptionDelegate exceptionHandler = exception => { localException = exception; return false; }; var loop = new ProtectedLoop(() => LoopState.Done, exceptionHandler); loop.ForceCrash(); loop.Iterate(); CheckTrue(loop.Paused); } public void CrashCallsOnChangedOnPause() { bool? invoked = null; var loop = new ProtectedLoop(() => LoopState.Done, exception => true); loop.Paused.OnChanged += value => invoked = value; loop.ForceCrash(); loop.Iterate(); CheckEqual(invoked, true); } public void CrashReturnsExceptionHandlerState_True() { var loop = new ProtectedLoop(() => LoopState.Done, exception => true); loop.ForceCrash(); CheckTrue(loop.Iterate()); } public void CrashReturnsExceptionHandlerState_False() { var loop = new ProtectedLoop(() => LoopState.Done, exception => false); loop.ForceCrash(); CheckFalse(loop.Iterate()); } public void LoopTimingWeightOfZeroDoesNotUpdate() { var loop = new ProtectedLoop(() => LoopState.Busy, exception => false); loop.LoopTimingWeight = 0; loop.Iterate(); CheckEqual(0, loop.WeightedCycleTimes); } public void LoopTimingWeightOfOneIsMostRecentTimings() { var loop = new ProtectedLoop(() => { Thread.Sleep(2); return LoopState.Busy; }, exception => false); loop.LoopTimingWeight = 1; loop.Iterate(); CheckGreater((double)loop.WeightedCycleTimes, 1 / 1000d); } public void DoesNotCallActionWhenPaused() { bool called = false; Func action = () => { called = true; return LoopState.Busy; }; var loop = new ProtectedLoop(action, exception => false); loop.Paused.Set(true); loop.Iterate(); CheckFalse(called); } public void DoesNotUpdateTimingsWhenPaused() { var loop = new ProtectedLoop(() => LoopState.Busy, exception => false); loop.Paused.Set(true); loop.Iterate(); CheckEqual(0, loop.WeightedCycleTimes); } public void CanStillForceCrashWhenPaused() { Exception localException = null; ProtectedLoop.TryHandleExceptionDelegate exceptionHandler = exception => { localException = exception; return false; }; var loop = new ProtectedLoop(() => LoopState.Done, exceptionHandler); loop.Paused.Set(true); loop.ForceCrash(); loop.Iterate(); CheckNotNull(localException); } public void ReturnsTrueWhenPaused() { var loop = new ProtectedLoop(() => LoopState.Done, exception => true); loop.Paused.Set(true); CheckTrue(loop.Iterate()); } public void SingleStepLeavesSimulationPaused() { var loop = new ProtectedLoop(() => LoopState.Busy, exception => true); loop.Paused.Set(false); loop.SingleStep(); CheckTrue(loop.Paused); } public void SingleStepIteratesAtLeastOnce() { int callCount = 0; var loop = new ProtectedLoop(() => { ++callCount; return LoopState.Busy; }, exception => true); loop.SingleStep(); loop.Iterate(); CheckEqual(1, callCount); } public void SingleStepIteratesNoMoreThanOnce() { int callCount = 0; var loop = new ProtectedLoop(() => { ++callCount; return LoopState.Busy; }, exception => true); loop.SingleStep(); loop.Iterate(); loop.Iterate(); CheckEqual(1, callCount); } public void MultipleSingleStepsIterateThatManyTimes() { int callCount = 0; var loop = new ProtectedLoop(() => { ++callCount; return LoopState.Busy; }, exception => true); loop.SingleStep(); loop.Iterate(); loop.SingleStep(); loop.Iterate(); CheckEqual(2, callCount); } } }