public void Pipeline_UnbindArgument_Succeeds() { MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); Pipeline pipeline = new Pipeline( new Processor[] { processor1, processor2 }, Enumerable.Empty <ProcessorArgument>(), Enumerable.Empty <ProcessorArgument>()); pipeline.BindArguments(processor1.OutArguments[0], processor2.InArguments[0]); Assert.IsTrue( pipeline.GetBoundToArguments(processor1.OutArguments[0]).Contains(processor2.InArguments[0]), "Expected GetBoundTo(out) to show we bound out to in"); Assert.IsTrue( pipeline.GetBoundToArguments(processor2.InArguments[0]).Contains(processor1.OutArguments[0]), "Expected GetBoundTo(in) to show we bound out to in"); pipeline.UnbindArguments(processor1.OutArguments[0], processor2.InArguments[0]); Assert.IsFalse( pipeline.GetBoundToArguments(processor1.OutArguments[0]).Contains(processor2.InArguments[0]), "Expected GetBoundTo(out) to show we unbound out to in"); Assert.IsFalse( pipeline.GetBoundToArguments(processor2.InArguments[0]).Contains(processor1.OutArguments[0]), "Expected GetBoundTo(in) to show we unbound out to in"); }
public void PipelineBuilder_Build_Binds_By_Name_And_Executes() { MockPipelineBuilder pb = new MockPipelineBuilder(); MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); // Rename processor inputs and outputs to bind by name to pipeline arguments and to each other: // pipeline[intInput] --> [intInput]p1[echoInput] --> [echoInput]p2[stringOutput] --> [stringOutput]pipeline processor1.InArguments[0].Name = "intInput"; processor2.InArguments[0].Name = processor1.OutArguments[0].Name = "echoInput"; processor2.OutArguments[0].Name = "stringOutput"; Pipeline pipeline = pb.Build( new Processor[] { processor1, processor2 }, new ProcessorArgument[] { new ProcessorArgument("intInput", typeof(int)) }, new ProcessorArgument[] { new ProcessorArgument("stringOutput", typeof(string)) } ); Assert.IsNotNull(pipeline, "Build should produce non-null pipeline"); ProcessorResult result = pipeline.Execute(new object[] { 9 }); Assert.IsNotNull(result, "Null result from execute"); Assert.AreEqual(ProcessorStatus.Ok, result.Status, "Expected OK result status"); Assert.IsNotNull(result.Output, "Expected non-null output"); Assert.AreEqual(1, result.Output.Length, "Expected 1 output value"); Assert.AreEqual(9.ToString(), result.Output[0], "Wrong output value"); }
public void PipelineBuilder_Build_Binds_By_Name() { MockPipelineBuilder pb = new MockPipelineBuilder(); MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); // Rename processor inputs and outputs to bind by name to pipeline arguments and to each other: // pipeline[intInput] --> [intInput]p1[echoInput] --> [echoInput]p2[stringOutput] --> [stringOutput]pipeline processor1.InArguments[0].Name = "intInput"; processor2.InArguments[0].Name = processor1.OutArguments[0].Name = "echoInput"; processor2.OutArguments[0].Name = "stringOutput"; Pipeline pipeline = pb.Build( new Processor[] { processor1, processor2 }, new ProcessorArgument[] { new ProcessorArgument("intInput", typeof(int)) }, new ProcessorArgument[] { new ProcessorArgument("stringOutput", typeof(string)) } ); Assert.IsNotNull(pipeline, "Build should produce non-null pipeline"); ProcessorArgument[] boundArgs = pipeline.GetBoundToArguments(pipeline.Processors[0].OutArguments[0]).ToArray(); Assert.AreEqual(1, boundArgs.Length, "Expected 1 parameter bound to entry processor output"); Assert.AreSame(processor1.InArguments[0], boundArgs[0], "Expected entry processor output to bind to processor 1 input"); boundArgs = pipeline.GetBoundToArguments(pipeline.Processors[1].OutArguments[0]).ToArray(); Assert.AreEqual(1, boundArgs.Length, "Expected 1 parameter bound to first processor output"); Assert.AreSame(processor2.InArguments[0], boundArgs[0], "Expected first processor output to bind to second processor input"); boundArgs = pipeline.GetBoundToArguments(pipeline.Processors[2].OutArguments[0]).ToArray(); Assert.AreEqual(1, boundArgs.Length, "Expected 1 parameter bound to second processor output"); Assert.AreSame(pipeline.Processors[3].InArguments[0], boundArgs[0], "Expected second processor output to bind to exit processor input"); }
public void Pipeline_Bind_OnBinding_OnBind_OnBound_Callbacks() { MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); MockPipeline pipeline = new MockPipeline( new Processor[] { processor1, processor2 }, Enumerable.Empty <ProcessorArgument>(), Enumerable.Empty <ProcessorArgument>()); BindArgumentsEventArgs bindingEventArgs = null; BindArgumentsEventArgs boundEventArgs = null; ProcessorArgument inArgFromBind = null; ProcessorArgument outArgFromBind = null; pipeline.OnBindArgumentsCalled = (outArg, inArg) => { inArgFromBind = inArg; outArgFromBind = outArg; }; pipeline.BindingArguments = (s, a) => { bindingEventArgs = a as BindArgumentsEventArgs; }; pipeline.BoundArguments = (s, a) => { boundEventArgs = a as BindArgumentsEventArgs; }; pipeline.BindArguments(processor1.OutArguments[0], processor2.InArguments[0]); Assert.IsNotNull(bindingEventArgs, "Did not receive BindingArguments callback"); Assert.AreSame(processor1.OutArguments[0], bindingEventArgs.OutArgument, "Did not receive correct outArg in BindingArgument callback"); Assert.AreSame(processor2.InArguments[0], bindingEventArgs.InArgument, "Did not receive correct inArg in BindingArgument callback"); Assert.IsNotNull(boundEventArgs, "Did not receive BoundArguments callback"); Assert.AreSame(processor1.OutArguments[0], boundEventArgs.OutArgument, "Did not receive correct outArg in BoundArgument callback"); Assert.AreSame(processor2.InArguments[0], boundEventArgs.InArgument, "Did not receive correct inArg in BoundArgument callback"); Assert.AreSame(processor1.OutArguments[0], outArgFromBind, "Did not receive correct outArg in OnBind virtual"); Assert.AreSame(processor2.InArguments[0], inArgFromBind, "Did not receive correct inArg in OnBind virtual"); }
private void PipelineBuilder_Ordering_Random(Random random) { int nProcessors = (random.Next() % 10) + 1; System.Diagnostics.Debug.WriteLine("Number processors this pass: "******"Processor" + (i + 1) }; p.OutArguments[0].Name = p.Name + "Out"; processors[i] = p; } for (int i = 0; i < nProcessors; ++i) { if (i == 0) { processors[i].InArguments[0].Name = "PipeIn"; } else { processors[i].InArguments[0].Name = processors[i - 1].OutArguments[0].Name; } } Processor[] origProcessors = new Processor[nProcessors]; Array.Copy(processors, origProcessors, nProcessors); // Now randomly scramble the processor order for (int i = 0; i < nProcessors; ++i) { int iSrc = random.Next() % nProcessors; int iDst = random.Next() % nProcessors; var temp = processors[iSrc]; processors[iSrc] = processors[iDst]; processors[iDst] = temp; } MockPipelineBuilder builder = new MockPipelineBuilder(); Pipeline pipeline = builder.Build( processors, new ProcessorArgument[] { new ProcessorArgument("PipeIn", typeof(string)) }, new ProcessorArgument[0] ); for (int i = 0; i < nProcessors; ++i) { Assert.AreSame(origProcessors[i], pipeline.Processors[i + 1], "Slot " + i + " had " + ((MockProcessorEchoString)pipeline.Processors[i + 1]).Name + " but expected " + ((MockProcessorEchoString)origProcessors[i]).Name); } }
public void PipelineBuilder_OnGetRelativeExecutionOrder_Virtual_IsCalled() { Processor processor1 = new MockProcessor1(); Processor processor2 = new MockProcessorEchoString(); Processor processor3 = new MockProcessorNoArgs(); Processor[] processors = new Processor[] { processor1, processor2, processor3 }; ProcessorArgument[] inArgs = new[] { new ProcessorArgument("intValue", typeof(int)) }; ProcessorArgument[] outArgs = new ProcessorArgument[0]; // Bind input of echo processor to mock proc 1 processor2.InArguments[0].Name = processor1.OutArguments[0].Name; bool firstOrderSet = false; bool secondOrderSet = false; bool thirdOrderSet = false; ProcessorExecutionOrder firstOrder = default(ProcessorExecutionOrder); ProcessorExecutionOrder secondOrder = default(ProcessorExecutionOrder); ProcessorExecutionOrder thirdOrder = default(ProcessorExecutionOrder); // Get a new pipeline because the prior one is now in a damaged state MockPipelineBuilder pb = new MockPipelineBuilder(); pb.OnGetRelativeExecutionOrderCalled = (p1, p2, order) => { if (p1 == processors[0] && p2 == processors[1]) { firstOrder = order; firstOrderSet = true; } if (p1 == processors[1] && p2 == processors[0]) { secondOrder = order; secondOrderSet = true; } if (p1 == processors[2] && p2 == processors[0]) { thirdOrder = order; thirdOrderSet = true; } return(order); }; Pipeline pipeline = pb.Build(processors, inArgs, outArgs); Assert.IsTrue(firstOrderSet, "OnGetRelativeExecutionOrder virtual was not called for (p1,p2)"); Assert.IsTrue(secondOrderSet, "OnGetRelativeExecutionOrder virtual was not called for (p2,p1)"); Assert.IsTrue(thirdOrderSet, "OnGetRelativeExecutionOrder virtual was not called for (p3,p1)"); Assert.AreEqual(ProcessorExecutionOrder.Before, firstOrder, "The (p1,p2) call should have yielded 'before'"); Assert.AreEqual(ProcessorExecutionOrder.After, secondOrder, "The (p2, p1) call should have yielded 'after'"); Assert.AreEqual(ProcessorExecutionOrder.Impartial, thirdOrder, "The (p3, p1) call should have yielded 'impartial'"); }
public void Pipeline_UnbindArgument_Throws_After_Initialize() { MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); Pipeline pipeline = new Pipeline( new Processor[] { processor1, processor2 }, Enumerable.Empty <ProcessorArgument>(), Enumerable.Empty <ProcessorArgument>()); pipeline.Initialize(); ExceptionAssert.ThrowsInvalidOperation( "UnbindArgument should throw if called after initialize", () => pipeline.UnbindArguments(processor1.OutArguments[0], processor2.InArguments[0]) ); }
public void Pipeline_Executes_With_No_Bindings() { MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); MockPipeline pipeline = new MockPipeline( new Processor[] { processor1, processor2 }, Enumerable.Empty <ProcessorArgument>(), Enumerable.Empty <ProcessorArgument>()); pipeline.Initialize(); ProcessorResult result = pipeline.Execute(new object[0]); Assert.IsNotNull(result, "Expected non-null ProcessorResult"); Assert.IsNotNull(result.Output, "Expected non-null output from unbound pipeline"); Assert.AreEqual(0, result.Output.Length, "Expected empty array from unbound pipeline"); Assert.AreEqual(ProcessorStatus.Ok, result.Status, "Expected OK status from pipeline"); }
public void Pipeline_Executes_With_No_Bindings_To_Pipeline() { MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); MockPipeline pipeline = new MockPipeline( new Processor[] { processor1, processor2 }, Enumerable.Empty <ProcessorArgument>(), Enumerable.Empty <ProcessorArgument>()); pipeline.BindArguments(processor1.OutArguments[0], processor2.InArguments[0]); pipeline.Initialize(); ProcessorResult result = pipeline.Execute(new object[0]); Assert.IsNotNull(result, "Expected non-null ProcessorResult"); Assert.IsNotNull(result.Output, "Expected non-null output from unbound pipeline"); Assert.AreEqual(0, result.Output.Length, "Expected empty array from unbound pipeline"); // Verify processor1 pushed default(int) through to processor2 object value = pipeline.Context.ReadInput(processor2.InArguments[0]); Assert.IsNotNull(value); Assert.AreEqual(default(int).ToString(), value, "Expected default(int) to be passed from processor1 to processor2"); }
public void PipelineBuilder_Validate_Throws_Input_Before_Output() { MockPipelineBuilder pb = new MockPipelineBuilder(); MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); // Rename processor inputs and outputs to bind by name to pipeline arguments and to each other: // pipeline[intInput] --> [intInput]p1[echoInput] --> [echoInput]p2[stringOutput] --> [stringOutput]pipeline processor1.InArguments[0].Name = "intInput"; processor2.InArguments[0].Name = processor1.OutArguments[0].Name = "echoInput"; processor2.OutArguments[0].Name = "stringOutput"; // Defeat normal ordering pb.OnOrderCalled = p => p; ExceptionAssert.ThrowsInvalidOperation( "PipelineBuilder should throw when required input occurs before output", () => pb.Build( new Processor[] { processor2, processor1 }, // <<<<<<<<< notice the order is flipped new ProcessorArgument[] { new ProcessorArgument("intInput", typeof(int)) }, new ProcessorArgument[] { new ProcessorArgument("stringOutput", typeof(string)) } ) ); }
public void PipelineBuilder_Build_Invokes_All_Virtuals() { MockPipelineBuilder pb = new MockPipelineBuilder(); bool onOrderCalled = false; bool onFilterCalled = false; bool onCreatePipelineCalled = false; bool onInitializeCalled = false; bool onValidateCalled = false; bool onShouldBindCalled = false; MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); pb.OnFilterCalled = p => { onFilterCalled = true; Assert.IsFalse(onOrderCalled || onInitializeCalled || onCreatePipelineCalled || onValidateCalled || onShouldBindCalled, "OnFilter should be called before OnOrder, OnInitialize, OnCreatePipeline, OnValidate, and OnShouldBind"); return(p); }; pb.OnOrderCalled = p => { onOrderCalled = true; Assert.IsTrue(onFilterCalled, "OnOrder should be called after OnFilter"); Assert.IsFalse(onInitializeCalled || onCreatePipelineCalled || onValidateCalled || onShouldBindCalled, "OnOrder should be called before OnInitialize, OnCreatePipeline, OnValidate, and OnShouldBind"); return(p); }; pb.OnCreatePipelineCalled = (p, aIn, aOut) => { onCreatePipelineCalled = true; Assert.IsTrue(onFilterCalled && onOrderCalled, "OnCreatePipeline should be called after OnFilter and OnOrder"); Assert.IsFalse(onInitializeCalled || onValidateCalled || onShouldBindCalled, "OnCreatePipeline should be called before OnInitialize, OnValidate, and OnShouldBind"); return(new Pipeline(p, aIn, aOut)); }; pb.OnInitializeCalled = p => { onInitializeCalled = true; Assert.IsNotNull(p, "Oninitialize passed null pipeline"); Assert.IsTrue(onFilterCalled && onOrderCalled && onCreatePipelineCalled, "OnInitialize should be called after OnFilter, OnCreatePipeline and OnOrder"); Assert.IsFalse(onValidateCalled || onShouldBindCalled, "OnInitialize should be called before OnValidate and OnShouldBind"); return(p); }; pb.OnShouldArgumentBindCalled = (aOut, aIn) => { onShouldBindCalled = true; Assert.IsTrue(onFilterCalled && onOrderCalled && onInitializeCalled && onCreatePipelineCalled, "OnInitialize should be called after OnFilter, OnCreatePipeline, OnOrder and OnInitialize"); Assert.IsFalse(onValidateCalled, "OnShouldArgmentBind should be called before OnValidate"); return(null); }; pb.OnValidateCalled = p => { Assert.IsTrue(onFilterCalled && onOrderCalled && onInitializeCalled && onShouldBindCalled && onCreatePipelineCalled, "OnInitialize should be called after OnFilter, OnOrder, OnInitialize, OnCreatePipeline and OnShouldBind"); onValidateCalled = true; return(true); // call base.validate }; // Rename processor inputs and outputs to bind by name to pipeline arguments and to each other: // pipeline[intInput] --> [intInput]p1[echoInput] --> [echoInput]p2[stringOutput] --> [stringOutput]pipeline processor1.InArguments[0].Name = "intInput"; // same as pipeline input processor2.InArguments[0].Name = processor1.OutArguments[0].Name = "echoInput"; processor2.OutArguments[0].Name = "stringOutput"; // same as pipeline output Pipeline pipeline = pb.Build( new Processor[] { processor1, processor2 }, new ProcessorArgument[] { new ProcessorArgument("intInput", typeof(int)) }, new ProcessorArgument[] { new ProcessorArgument("stringOutput", typeof(string)) } ); Assert.IsNotNull(pipeline, "Build should produce non-null pipeline"); Assert.IsTrue(onFilterCalled, "OnFilter was not called"); Assert.IsTrue(onOrderCalled, "OnOrder was not called"); Assert.IsTrue(onInitializeCalled, "OnInitialize was not called"); Assert.IsTrue(onShouldBindCalled, "OnShouldBind was not called"); Assert.IsTrue(onValidateCalled, "OnValidate was not called"); }
public void Pipeline_Executes_With_No_Bindings_To_Pipeline() { MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); MockPipeline pipeline = new MockPipeline( new Processor[] { processor1, processor2 }, Enumerable.Empty<ProcessorArgument>(), Enumerable.Empty<ProcessorArgument>()); pipeline.BindArguments(processor1.OutArguments[0], processor2.InArguments[0]); pipeline.Initialize(); ProcessorResult result = pipeline.Execute(new object[0]); Assert.IsNotNull(result, "Expected non-null ProcessorResult"); Assert.IsNotNull(result.Output, "Expected non-null output from unbound pipeline"); Assert.AreEqual(0, result.Output.Length, "Expected empty array from unbound pipeline"); // Verify processor1 pushed default(int) through to processor2 object value = pipeline.Context.ReadInput(processor2.InArguments[0]); Assert.IsNotNull(value); Assert.AreEqual(default(int).ToString(), value, "Expected default(int) to be passed from processor1 to processor2"); }
public void Pipeline_Executes_With_No_Bindings() { MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); MockPipeline pipeline = new MockPipeline( new Processor[] { processor1, processor2 }, Enumerable.Empty<ProcessorArgument>(), Enumerable.Empty<ProcessorArgument>()); pipeline.Initialize(); ProcessorResult result = pipeline.Execute(new object[0]); Assert.IsNotNull(result, "Expected non-null ProcessorResult"); Assert.IsNotNull(result.Output, "Expected non-null output from unbound pipeline"); Assert.AreEqual(0, result.Output.Length, "Expected empty array from unbound pipeline"); Assert.AreEqual(ProcessorStatus.Ok, result.Status, "Expected OK status from pipeline"); }
public void Pipeline_UnbindArgument_Throws_After_Initialize() { MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); Pipeline pipeline = new Pipeline( new Processor[] { processor1, processor2 }, Enumerable.Empty<ProcessorArgument>(), Enumerable.Empty<ProcessorArgument>()); pipeline.Initialize(); ExceptionAssert.ThrowsInvalidOperation( "UnbindArgument should throw if called after initialize", () => pipeline.UnbindArguments(processor1.OutArguments[0], processor2.InArguments[0]) ); }
public void Pipeline_UnbindArgument_Succeeds() { MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); Pipeline pipeline = new Pipeline( new Processor[] { processor1, processor2 }, Enumerable.Empty<ProcessorArgument>(), Enumerable.Empty<ProcessorArgument>()); pipeline.BindArguments(processor1.OutArguments[0], processor2.InArguments[0]); Assert.IsTrue( pipeline.GetBoundToArguments(processor1.OutArguments[0]).Contains(processor2.InArguments[0]), "Expected GetBoundTo(out) to show we bound out to in"); Assert.IsTrue( pipeline.GetBoundToArguments(processor2.InArguments[0]).Contains(processor1.OutArguments[0]), "Expected GetBoundTo(in) to show we bound out to in"); pipeline.UnbindArguments(processor1.OutArguments[0], processor2.InArguments[0]); Assert.IsFalse( pipeline.GetBoundToArguments(processor1.OutArguments[0]).Contains(processor2.InArguments[0]), "Expected GetBoundTo(out) to show we unbound out to in"); Assert.IsFalse( pipeline.GetBoundToArguments(processor2.InArguments[0]).Contains(processor1.OutArguments[0]), "Expected GetBoundTo(in) to show we unbound out to in"); }
public void Pipeline_Bind_OnBinding_OnBind_OnBound_Callbacks() { MockProcessor1 processor1 = new MockProcessor1(); MockProcessorEchoString processor2 = new MockProcessorEchoString(); MockPipeline pipeline = new MockPipeline( new Processor[] { processor1, processor2 }, Enumerable.Empty<ProcessorArgument>(), Enumerable.Empty<ProcessorArgument>()); BindArgumentsEventArgs bindingEventArgs = null; BindArgumentsEventArgs boundEventArgs = null; ProcessorArgument inArgFromBind = null; ProcessorArgument outArgFromBind = null; pipeline.OnBindArgumentsCalled = (outArg, inArg) => { inArgFromBind = inArg; outArgFromBind = outArg; }; pipeline.BindingArguments = (s, a) => { bindingEventArgs = a as BindArgumentsEventArgs; }; pipeline.BoundArguments = (s, a) => { boundEventArgs = a as BindArgumentsEventArgs; }; pipeline.BindArguments(processor1.OutArguments[0], processor2.InArguments[0]); Assert.IsNotNull(bindingEventArgs, "Did not receive BindingArguments callback"); Assert.AreSame(processor1.OutArguments[0], bindingEventArgs.OutArgument, "Did not receive correct outArg in BindingArgument callback"); Assert.AreSame(processor2.InArguments[0], bindingEventArgs.InArgument, "Did not receive correct inArg in BindingArgument callback"); Assert.IsNotNull(boundEventArgs, "Did not receive BoundArguments callback"); Assert.AreSame(processor1.OutArguments[0], boundEventArgs.OutArgument, "Did not receive correct outArg in BoundArgument callback"); Assert.AreSame(processor2.InArguments[0], boundEventArgs.InArgument, "Did not receive correct inArg in BoundArgument callback"); Assert.AreSame(processor1.OutArguments[0], outArgFromBind, "Did not receive correct outArg in OnBind virtual"); Assert.AreSame(processor2.InArguments[0], inArgFromBind, "Did not receive correct inArg in OnBind virtual"); }