/// <summary>
        /// This pipeline has 2 MockProcessor1's in it, both binding their inputs to the pipeline's 'intValue'.
        /// The pipeline has 2 outputs, one bound to each processor's.
        /// </summary>
        /// <returns></returns>
        public static MockPipeline CreateDoubleMockProcessor1Pipeline()
        {
            Processor processor1 = new MockProcessor1();
            Processor processor2 = new MockProcessor1();
            MockPipeline pipeline = new MockPipeline(
                                    new[] { processor1, processor2 },
                                    new[] { new ProcessorArgument("intValue", typeof(int), new object[0]) },
                                    new[] { new ProcessorArgument("theResult1", typeof(string), new object[0]),
                                            new ProcessorArgument("theResult2", typeof(string), new object[0])}
                                    );

            // Pipeline["intValue"] --> Processor1[0]
            pipeline.BindArgumentToPipelineInput("intValue", processor1.InArguments[0]);

            // Pipeline["intValue"] --> Processor2[0]
            pipeline.BindArgumentToPipelineInput("intValue", processor2.InArguments[0]);

            // Processor1[0] --> Pipeline["theResult1"]
            pipeline.BindArgumentToPipelineOutput(processor1.OutArguments[0], "theResult1");

            // Processor2[0] --> Pipeline["theResult2"]
            pipeline.BindArgumentToPipelineOutput(processor2.OutArguments[0], "theResult2");
            pipeline.Initialize();
            return pipeline;
        }
        /// <summary>
        /// Creates an uninitialized Pipeline with a single MockProcessor1 in it, binding its inputs to the pipeline inputs
        /// and its outputs to the pipeline outputs.
        /// </summary>
        /// <returns></returns>
        public static MockPipeline CreateMockProcessor1PipelineUninitialized()
        {
            Processor processor = new MockProcessor1();
            MockPipeline pipeline = new MockPipeline(
                                    new[] { processor },
                                    new[] { new ProcessorArgument("intValue", typeof(int), new object[0]) },
                                    new[] { new ProcessorArgument("theResult", typeof(string), new object[0]) }
                                    );

            pipeline.BindArgumentToPipelineInput("intValue", processor.InArguments[0]);
            pipeline.BindArgumentToPipelineOutput(processor.OutArguments[0], "theResult");
            return pipeline;
        }
        public void Pipeline_BindArgumentToPipelineOutput_By_Bad_Name_Throws()
        {
            MockProcessor1 processor = new MockProcessor1();
            MockPipeline pipeline = new MockPipeline(
                new Processor[] { processor },
                Enumerable.Empty<ProcessorArgument>(),
                new ProcessorArgument[] { new ProcessorArgument("PipelineOutput", typeof(string)) });

            ExceptionAssert.Throws(
                typeof(ArgumentException),
                "BindArgumentToPipelineOutput should throw with null name",
                () => pipeline.BindArgumentToPipelineOutput(processor.OutArguments[0], null),
                "pipelineOutputArgumentName"
                );

            ExceptionAssert.Throws(
                typeof(ArgumentException),
                "BindArgumentToPipelineOutput should throw with empty name",
                () => pipeline.BindArgumentToPipelineOutput(processor.OutArguments[0], string.Empty),
                "pipelineOutputArgumentName"
                );

            ExceptionAssert.Throws(
                typeof(ArgumentException),
                "BindArgumentToPipelineOutput should throw with whitespace name",
                () => pipeline.BindArgumentToPipelineOutput(processor.OutArguments[0], "   "),
                "pipelineOutputArgumentName"
                );

            ExceptionAssert.ThrowsInvalidOperation(
                "BindArgumentToPipelineInput should throw with non-existent name",
                () => pipeline.BindArgumentToPipelineOutput(processor.OutArguments[0], "NotAName")
                );
        }
        public void Pipeline_BindArgumentToPipelineOutput_By_Name()
        {
            MockProcessor1 processor = new MockProcessor1();
            MockPipeline pipeline = new MockPipeline(
                new Processor[] { processor },
                Enumerable.Empty<ProcessorArgument>(),
                new ProcessorArgument[] { new ProcessorArgument("PipelineOutput", typeof(string)) });

            BindArgumentsEventArgs eventArgs = null;
            ProcessorArgument inArgFromBind = null;
            ProcessorArgument outArgFromBind = null;

            pipeline.OnBindArgumentsCalled = (outArg, inArg) =>
            {
                inArgFromBind = inArg;
                outArgFromBind = outArg;
            };

            pipeline.BoundArguments = (s, a) => { eventArgs = a as BindArgumentsEventArgs; };
            pipeline.BindArgumentToPipelineOutput(processor.OutArguments[0], "PipelineOutput");
            Assert.IsNotNull(eventArgs, "Did not receive OnBoundArguments callback");
            Assert.AreSame(pipeline.Processors[1].OutArguments[0], outArgFromBind, "Did not receive correct outArg in OnBind virtual");
            Assert.AreSame(pipeline.Processors[2].InArguments[0], inArgFromBind, "Did not receive correct inArg in OnBind virtual");
            Assert.IsTrue(pipeline.GetBoundToArguments(pipeline.Processors[1].OutArguments[0]).Contains(pipeline.Processors[2].InArguments[0]),
                            "Failed to find exit processor in argument in bindings for processor 1");
        }
        public void Pipeline_BindArgumentToPipelineOutput_By_Bad_Index_Throws()
        {
            MockProcessor1 processor = new MockProcessor1();
            MockPipeline pipeline = new MockPipeline(
                new Processor[] { processor },
                Enumerable.Empty<ProcessorArgument>(),
                new ProcessorArgument[] { new ProcessorArgument("PipelineOutput", typeof(string)) });

            ExceptionAssert.Throws(
                typeof(ArgumentOutOfRangeException),
                "BindArgumentToPipelineOutput should throw with negative index",
                () => pipeline.BindArgumentToPipelineOutput(processor.OutArguments[0], -1),
                "pipelineOutputArgumentIndex"
                );

            ExceptionAssert.Throws(
                typeof(ArgumentOutOfRangeException),
                "BindArgumentToPipelineOutput should throw with too large an index",
                () => pipeline.BindArgumentToPipelineOutput(processor.OutArguments[0], 1),
                "pipelineOutputArgumentIndex"
                );
        }