public override void Loop() { DebugTools.AddEvent("StepperInternalLoop.Loop", "Loop Start. Signalling and waiting on " + (SyncContext?.GetNumberOfRemainingParticipants() - 1) + ". Total participants = " + SyncContext?.GetNumberOfTotalParticipants() + " : " + this.Name); SyncContext?.SignalAndWait(); //DebugTools.AddEvent("StepperInternalLoop.Loop", "Loop Start. Signal received. Continuing: " + this.Name); while (true) { if (CurrentStep + 1 > EndStep) { CurrentStep = StartStep; break; } else { CurrentStep++; } while (PauseForTest) { Thread.Sleep(1); } DebugTools.AddEvent("StepperInternalLoop.Loop", "In While. Signalling and waiting on " + (SyncContext?.GetNumberOfRemainingParticipants() - 1) + ". Total participants = " + SyncContext?.GetNumberOfTotalParticipants() + " : " + this.Name); SyncContext?.SignalAndWait(); //DebugTools.AddEvent("StepperInternalLoop.Loop", "In While. Signal received. Continuing: " + this.Name); } DebugTools.AddEvent("StepperInternalLoop.Loop", "Loop End. Signalling and waiting on " + (SyncContext?.GetNumberOfRemainingParticipants() - 1) + ". Total participants = " + SyncContext?.GetNumberOfTotalParticipants() + " : " + this.Name); SyncContext?.SignalAndWait(); //DebugTools.AddEvent("StepperInternalLoop.Loop", "Loop End. Signal received. Continuing: " + this.Name); }
/// <summary> /// Requests the program to pause when it's at its synchronizable state. /// </summary> /// <returns></returns> public void RequestSyncState() { lock (SyncStateRequestLock) { IsSyncStateRequested = true; DebugTools.AddEvent("LoopingZoneProgram.RequestSyncState", "IsSyncStateRequested = true: " + Name); } }
public static void Sync_ThreeStepperSyncingWithOne_Consecutive_Works(int numberOfChecks) { DebugTools.AddEvent("Sync_ThreeStepperSyncingWithOne_Works", "START"); //create a sync context to conduct the test with var testContext = new SyncContext(); //create two programs to be synced var stepperA = new StepperInternalLoop("A"); var stepperB = new StepperInternalLoop("B"); var stepperC = new StepperInternalLoop("C"); var stepperD = new StepperInternalLoop("D"); IStepper[] steppers = { stepperA, stepperB, stepperC, stepperD }; //sync and start A DebugTools.AddEvent("Sync_ThreeStepperSyncingWithOne_Works", "Sync-Starting Stepper A"); testContext.Sync(stepperA); testContext.SyncFinished.WaitForFire(); //start BCD in sync with testContext when steppers A is back to the beginning DebugTools.AddEvent("Sync_ThreeStepperSyncingWithOne_Works", "Syncing Stepper B"); testContext.Sync(stepperB); testContext.SyncFinished.WaitForFire(); DebugTools.AddEvent("Sync_ThreeStepperSyncingWithOne_Works", "Syncing Stepper C"); testContext.Sync(stepperC); testContext.SyncFinished.WaitForFire(); DebugTools.AddEvent("Sync_ThreeStepperSyncingWithOne_Works", "Syncing Stepper D"); testContext.Sync(stepperD); testContext.SyncFinished.WaitForFire(); int[,] stepperSteps; DebugTools.AddEvent("Sync_ThreeStepperSyncingWithOne_Works", "Validating Sync Phases"); var invalidStepIndex = ValidateStepperSyncPhase(steppers, out stepperSteps, numberOfChecks); var result = invalidStepIndex.Length == 0; //cleanup DebugTools.AddEvent("Sync_ThreeStepperSyncingWithOne_Works", "Disposing Stepper A"); stepperA.Dispose(true); DebugTools.AddEvent("Sync_ThreeStepperSyncingWithOne_Works", "Disposing Stepper B"); stepperB.Dispose(true); DebugTools.AddEvent("Sync_ThreeStepperSyncingWithOne_Works", "Disposing Stepper C"); stepperC.Dispose(true); DebugTools.AddEvent("Sync_ThreeStepperSyncingWithOne_Works", "Disposing Stepper D"); stepperD.Dispose(true); testContext.Dispose(); //assert if (result) { Assert.Pass(); } else { var failStringBuilder = BuildFailString(invalidStepIndex, steppers, stepperSteps); Assert.Fail(failStringBuilder.ToString()); } }
protected override void StopCore(bool force) { //subclass processing PreStop(force); DebugTools.AddEvent("LoopingZoneProgram.StopCore", "STOP " + Name); //DebugTools.AddEvent("LoopingZoneProgram.StopCore", "Canceling Sync-State on Program " + Name); //cancel sync state req and release from sync state CancelSyncState(); //DebugTools.AddEvent("LoopingZoneProgram.Stop", "START Stopping BG Program"); if (Running) { //DebugTools.AddEvent("LoopingZoneProgram.Stop", "Running = TRUE"); if (force) { if (RunProgramThread != null) { //DebugTools.AddEvent("LoopingZoneProgram.Stop", "START Force aborting BG Program thread"); RunProgramThread.Abort(); StopTrigger.WaitForFire(); //DebugTools.AddEvent("LoopingZoneProgram.Stop", "END Force aborting BG Program thread"); } else { //DebugTools.AddEvent("LoopingZoneProgram.Stop", "RunProgramThread was null"); //DebugTools.Print(); } } else { LoopCTS.Cancel(); if (!StopTrigger.WaitForFire()) { //DebugTools.AddEvent("LoopingZoneProgram.Stop", "Loop did not cancel cooperatively."); //DebugTools.Print(); } } } PostStop(force); //DebugTools.AddEvent("LoopingZoneProgram.Stop", "END Stopping BG Program"); StopTestingTrigger.Fire(this, null); }
public static void Sync_FourSteppers_Simultaneous_Works(int numberOfChecks) { DebugTools.AddEvent("Sync_FourSteppers_Works", "START"); //create a sync context to conduct the test with var testContext = new SyncContext(); //create two programs to be synced var stepperA = new Stepper("A"); var stepperB = new Stepper("B"); var stepperC = new Stepper("C"); var stepperD = new Stepper("D"); IStepper[] steppers = { stepperA, stepperB, stepperC, stepperD }; //sync and start testContext.Sync(stepperA, stepperB, stepperC, stepperD); testContext.SyncFinished.WaitForFire(); int[,] stepperSteps; var invalidStepIndex = ValidateStepperSyncPhase(steppers, out stepperSteps, numberOfChecks); var result = invalidStepIndex.Length == 0; PrintStepperSteps(steppers, stepperSteps); //cleanup stepperA.Dispose(true); stepperB.Dispose(true); stepperC.Dispose(true); stepperD.Dispose(true); testContext.Dispose(); //assert if (result) { Assert.Pass(); } else { var failStringBuilder = BuildFailString(invalidStepIndex, steppers, stepperSteps); Assert.Fail(failStringBuilder.ToString()); } }
public static void PrintStepperSteps(IStepper[] steppers, int[,] stepperSteps) { //output stepperSteps StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(Environment.NewLine); stringBuilder.Append(Environment.NewLine); foreach (var stepper in steppers) { stringBuilder.Append(" "); stringBuilder.Append(((ZoneProgram)stepper).Name); stringBuilder.Append(" "); stringBuilder.Append("|"); } stringBuilder.Append(Environment.NewLine); stringBuilder.Append(Environment.NewLine); foreach (var stepper in steppers) { stringBuilder.Append("--------"); } stringBuilder.Append(Environment.NewLine); stringBuilder.Append(Environment.NewLine); for (var i = 0; i < stepperSteps.GetLength(0); i++) { for (var j = 0; j < stepperSteps.GetLength(1); j++) { stringBuilder.Append(" "); stringBuilder.Append(stepperSteps[i, j]); stringBuilder.Append(" "); stringBuilder.Append("|"); } stringBuilder.Append(Environment.NewLine); } DebugTools.AddEvent("Sync_TwoSteppers_Works", stringBuilder.ToString()); }
public static void CooperativeStop_Works() { DebugTools.AddEvent("Test.CooperativeStop_Works", "START CooperativeStop_Works Test"); //arrange var zoneScaffolder = new ZoneScaffolder(); zoneScaffolder.Initialize(ConfigurationManager.AppSettings["TestProgramModuleDirectory"]); var leftWing = new FadeCandyZone(FadeCandyController.Instance, "LeftWing"); leftWing.AddFadeCandyLights(PixelType.FadeCandyWS2812Pixel, 6, 1); dynamic scrollDotDictionary = new ISV(); scrollDotDictionary.DelayTime = 30; scrollDotDictionary.DotColor = (Color?)Color.Red; FadeCandyController.Instance.Initialize(); //needs to be faked somehow leftWing.Run(new ScrollDot(), scrollDotDictionary); //this is to fix the race condition that sometimes causes this test to fail - since this test //is not designed to test race conditions, just whether cooperative stop works in normal conditions Thread.Sleep(100); //act -- cooperative stop leftWing.ZoneProgram.Stop(false); //assert var result = leftWing.ZoneProgram.StopTestingTrigger.WaitForFire(1000); //cleanup leftWing.Dispose(); FadeCandyController.Instance.Dispose(); DebugTools.AddEvent("Test.CooperativeStop_Works", "END CooperativeStop_Works Test"); Assert.True(result); }
public static void Sync_OneStepper_Works(int numberOfChecks) { DebugTools.AddEvent("Sync_OneStepperSyncingWithThree_Works", "START"); //create a sync context to conduct the test with var testContext = new SyncContext(); //create two programs to be synced var stepperA = new StepperInternalLoop("A"); IStepper[] steppers = { stepperA }; //sync and start ABC DebugTools.AddEvent("Sync_OneStepperSyncingWithThree_Works", "Sync-Starting Stepper A, B, C"); testContext.Sync(stepperA); testContext.SyncFinished.WaitForFire(); int[,] stepperSteps; var invalidStepIndex = ValidateStepperSyncPhase(steppers, out stepperSteps, numberOfChecks); var result = invalidStepIndex.Length == 0 && stepperSteps.Length != 0; //cleanup DebugTools.AddEvent("Sync_OneStepperSyncingWithThree_Works", "Disposing Stepper A"); stepperA.Dispose(true); testContext.Dispose(); if (result) { Assert.Pass(); } else { var failStringBuilder = BuildFailString(invalidStepIndex, steppers, stepperSteps); Assert.Fail(failStringBuilder.ToString()); } }
private void SetupRunProgramTask() { LoopCTS.Dispose(); LoopCTS = new CancellationTokenSource(); try { LoopingTask?.Dispose(); } catch (Exception ex) { } LoopingTask = new Task(() => { try { RunProgramThread = Thread.CurrentThread; while (true) { //if sync is requested, go into synchronizable state if (SyncContext != null) { lock (SyncStateRequestLock) { if (IsSyncStateRequested) { DebugTools.AddEvent("LoopingZoneProgram.LoopingTask", "Entering Sync-State: " + Name); IsSynchronizable.Fire(this, null); DebugTools.AddEvent("LoopingZoneProgram.LoopingTask", "In Sync-State - Waiting for Signal from SyncContext: " + Name); WaitForSync.WaitForFire(); DebugTools.AddEvent("LoopingZoneProgram.LoopingTask", "Leaving Sync-State: " + Name); IsSyncStateRequested = false; DebugTools.AddEvent("LoopingZoneProgram.LoopingTask", "IsSyncStateRequested = false: " + Name); } } } //this is currently not doing anything LeftSyncTrigger.Fire(this, null); DebugTools.AddEvent("LoopingZoneProgram.LoopingTask", "Starting Loop: " + Name); //start loop Loop(); DebugTools.AddEvent("LoopingZoneProgram.LoopingTask", "Finished Loop: " + Name); //if cancellation is requested, break out of loop after setting notification parameters for the consumer if (LoopCTS.IsCancellationRequested) { Running = false; StopTrigger.Fire(this, null); break; } //this makes the CPU consumption way lesser Thread.Sleep(LoopWaitTime); } } catch (ThreadAbortException ex) { //DebugTools.AddEvent("LoopingZoneProgram.LoopingTask.Method", "LoopingTask thread aborted"); //DebugTools.AddEvent("LoopingZoneProgram.Stop", "START Setting Running = false"); Running = false; StopTrigger.Fire(this, null); //DebugTools.AddEvent("LoopingZoneProgram.Stop", "END Setting Running = false"); } catch (Exception ex) { Running = false; StopTrigger.Fire(this, null); DebugTools.AddEvent("LoopingZoneProgram.LoopingTask.Method", "Unexpected exception in LoopingTask: " + ex.Message + " | StackTrace: " + ex.StackTrace); } }, LoopCTS.Token); }
/// <summary> /// Checks to make sure that the steppers provided are in within 1 step of each other. /// </summary> /// <returns>Array of steps that were out of sync.</returns> public static int[] ValidateStepperSyncPhase(IStepper[] steppers, out int[,] stepperSteps, int numberOfChecks = 30, int msToWaitBeforeStart = 10, int msToWaitBetweenChecks = 1) { //sleep cuz we want the programs to get going Thread.Sleep(msToWaitBeforeStart); DebugTools.AddEvent("ValidateStepperSyncPhase", "START"); List <int> invalidStepIndex = new List <int>(); stepperSteps = new int[numberOfChecks, steppers.Length]; for (var i = 0; i < numberOfChecks; i++) { for (var j = 0; j < steppers.Length; j++) { stepperSteps[i, j] = 0; } } //every time we check the step, it should be within 1 for both programs //because they should have been synced and then started - one program may be ahead of //another because this test may read in between the transactions (since this test is not //aware of the sync itself, it's reading values intermittently, so being off by one //does not imply that the programs are out of sync. if the programs do go out of sync, //with enough repetitions they will go out of sync even more, which means their steps //will eventually differ by more than 1, which is what this for loop is testing. therefore, //the higher the number of checks, the higher the chance of failure if the programs are out of sync, OR //if the sync algorithm has a race condition or some other kind of flaw. for (var i = 0; i < numberOfChecks; i++) { foreach (var stepper in steppers) { stepper.PauseForTest = true; } for (var j = 0; j < steppers.Length; j++) { stepperSteps[i, j] = steppers[j].CurrentStep; } foreach (var stepper in steppers) { stepper.PauseForTest = false; } //check to make sure the difference in steps in no more than 1 (and check for wrapping) for (int comparisonSource = 0; comparisonSource < steppers.Length; comparisonSource++) { for (int comparisonTarget = 0; comparisonTarget < steppers.Length; comparisonTarget++) { if (Math.Abs(stepperSteps[i, comparisonSource] - stepperSteps[i, comparisonTarget]) > 1 && !(stepperSteps[i, comparisonSource] == steppers[comparisonSource].EndStep && stepperSteps[i, comparisonTarget] == steppers[comparisonTarget].StartStep) && !(stepperSteps[i, comparisonSource] == steppers[comparisonSource].EndStep && stepperSteps[i, comparisonTarget] == steppers[comparisonTarget].StartStep + 1) && !(stepperSteps[i, comparisonSource] == steppers[comparisonSource].StartStep && stepperSteps[i, comparisonTarget] == steppers[comparisonTarget].EndStep) && !(stepperSteps[i, comparisonSource] == steppers[comparisonSource].StartStep + 1 && stepperSteps[i, comparisonTarget] == steppers[comparisonTarget].EndStep)) { if (!invalidStepIndex.Contains(i)) { invalidStepIndex.Add(i); } } } } //sleep cuz we want some cycles to execute if (msToWaitBetweenChecks > 0) { Thread.Sleep(msToWaitBetweenChecks); } } DebugTools.AddEvent("ValidateStepperSyncPhase", "END result: " + (!invalidStepIndex.Any())); return(invalidStepIndex.ToArray()); }