/// <summary> /// Check that an exception being thrown by a flow element will /// result in the AddError method being called on FlowData. /// </summary> public void ParallelElements_ExceptionDuringProcessing() { var element1 = new Mock <IFlowElement>(); var element2 = new Mock <IFlowElement>(); var data = new Mock <IFlowData>(); // Configure element 2 to throw an exception. element2.Setup(e => e.Process(It.IsAny <IFlowData>())) .Throws(new Exception("TEST")); _parallelElements = new ParallelElements(_logger.Object, element1.Object, element2.Object); // Start processing _parallelElements.Process(data.Object); // Check that add error was called with the expected exception // and flow element. data.Verify(d => d.AddError( It.Is <Exception>(ex => ex.Message == "TEST"), element2.Object), Times.Once()); }
public void ParallelElements_ThreeElements_ValidateParallel() { if (Environment.ProcessorCount < 4) { Assert.Inconclusive("This test cannot be run on a machine with less that 4 processing cores"); } // Arrange var element1 = new Mock <IFlowElement>(); var element2 = new Mock <IFlowElement>(); var element3 = new Mock <IFlowElement>(); element1.Setup(e => e.Process(It.IsAny <IFlowData>())).Callback((IFlowData d) => { var tempdata = d.GetOrAdd("element1", (p) => new TestElementData(p)); tempdata["start"] = DateTime.UtcNow; DateTime end = DateTime.UtcNow.AddSeconds(1); SpinWait.SpinUntil(() => DateTime.UtcNow >= end); tempdata["end"] = DateTime.UtcNow; }); element2.Setup(e => e.Process(It.IsAny <IFlowData>())).Callback((IFlowData d) => { var tempdata = d.GetOrAdd("element2", (p) => new TestElementData(p)); tempdata["start"] = DateTime.UtcNow; DateTime end = DateTime.UtcNow.AddSeconds(1); SpinWait.SpinUntil(() => DateTime.UtcNow >= end); tempdata["end"] = DateTime.UtcNow; }); element3.Setup(e => e.Process(It.IsAny <IFlowData>())).Callback((IFlowData d) => { var tempdata = d.GetOrAdd("element3", (p) => new TestElementData(p)); tempdata["start"] = DateTime.UtcNow; DateTime end = DateTime.UtcNow.AddSeconds(1); SpinWait.SpinUntil(() => DateTime.UtcNow >= end); tempdata["end"] = DateTime.UtcNow; }); _parallelElements = new ParallelElements(_logger.Object, element1.Object, element2.Object, element3.Object); IFlowData data = StaticFactories.CreateFlowData(_pipeline.Object); data.Process(); // Act _parallelElements.Process(data); List <DateTime> startTimes = new List <DateTime>(); startTimes.Add((DateTime)data.Get("element1")["start"]); startTimes.Add((DateTime)data.Get("element2")["start"]); startTimes.Add((DateTime)data.Get("element3")["start"]); List <DateTime> endTimes = new List <DateTime>(); endTimes.Add((DateTime)data.Get("element1")["end"]); endTimes.Add((DateTime)data.Get("element2")["end"]); endTimes.Add((DateTime)data.Get("element3")["end"]); // Assert Assert.IsTrue(data.Errors == null || data.Errors.Count == 0, "Expected no errors"); Assert.IsTrue(startTimes.TrueForAll(dtStart => endTimes.TrueForAll(dtEnd => dtEnd > dtStart)), $"Start times [{string.Join(",", startTimes.Select(t => t.ToString("HH:mm:ss.ffffff")))}] " + $"not before end times [" + $"{string.Join(",", endTimes.Select(t => t.ToString("HH:mm:ss.ffffff")))}]"); for (int i = 0; i < 3; i++) { double ms = endTimes[i].Subtract(startTimes[i]).TotalMilliseconds; Assert.IsTrue(ms < 1100 && ms > 1000, $"Element {i} total time taken was {ms}ms, " + $"which is outside the expected range of 1000-1100"); } }