public async Task Exceptions_Are_Handled_When_Thrown_While_Producing_Requests_From_A_Stage() { var data = new Dictionary <int, int> { { 2, 3 }, { 3, 4 } }; var keys = data.Keys.Concat(new[] { 1, 4, 5 }).ToArray(); var completionSource = new TaskCompletionSource <IEnumerable <IRequest <int, int> > >(); var completionException = new ArgumentException(); var stageException = new InvalidOperationException(); var source = new StaticDataSource <int, int>(data); var stage = new Mock <IStage <int, int> >(); IEnumerable <IRequest <int, int> > Process(Query <int, int> request, CancellationToken token) { yield return(new Async <int, int>(request.Metadata, completionSource.Task)); yield return(new Query <int, int>(request.Metadata, request.Ids.Take(request.Ids.Count / 2).ToArray())); throw stageException; } completionSource.SetException(completionException); stage.Setup(s => s.Process(It.IsAny <Query <int, int> >(), It.IsAny <CancellationToken>())) .Returns <Query <int, int>, CancellationToken>(Process); var pipeline = new Pipeline <int, int>(source, stage.Object); var exception = await Assert.ThrowsAnyAsync <PipelineException <int, int> >(() => pipeline.GetAsync(keys)); Assert.Equal(data, exception.Results); Assert.Equal(2, exception.InnerExceptions.Count); Assert.Contains(completionException, exception.InnerExceptions); Assert.Contains(stageException, exception.InnerExceptions); }
public async Task ArgumentNullException_Is_Throw_For_Any_Null_Ids_Passed_To_GetAsync() { var source = new StaticDataSource <int?, int>(); var pipeline = new Pipeline <int?, int>(source); await Assert.ThrowsAsync <ArgumentNullException>(() => pipeline.GetAsync(new int?[] { 1, null })); }
public async Task Results_From_Stages_And_Source_Are_Combined() { var data = new Dictionary <int, int> { { 1, 4 }, { 2, 3 }, { 5, 9 } }; var stage = new StaticDataStage <int, int>(data.Where(pair => pair.Key % 2 != 0).ToDictionary(pair => pair.Key, pair => pair.Value)); var source = new StaticDataSource <int, int>(data.Where(pair => pair.Key % 2 == 0).ToDictionary(pair => pair.Key, pair => pair.Value)); var pipeline = new Pipeline <int, int>(source, stage); var results = await pipeline.GetAsync(data.Keys); Assert.Equal(data, results); }
public static IEnumerable <object[]> GetPossibleConstructorCalls() { var config = new PipelineConfig <int, int>(); var source = new StaticDataSource <int, int>(); var stage = new StaticDataStage <int, int>(); yield return(new object[] { null, config, new IStage <int, int>[] { stage } }); yield return(new object[] { source, null, new IStage <int, int>[] { stage } }); yield return(new object[] { source, config, new IStage <int, int>[] { stage, null } }); yield return(new object[] { source, config, null }); }
public async Task Custom_Signals_Can_Be_Sent_Between_Stages() { var source = new StaticDataSource <int, int> { { 1, 1 }, { 2, 2 } }; var stageOne = new Mock <IStage <int, int> >(); var stageTwo = new Mock <IStage <int, int> >(); stageOne.Setup(s => s.Process(It.IsAny <IRequest <int, int> >(), It.IsAny <CancellationToken>())) .Returns(new IRequest <int, int>[] { new CustomSignal <int, int>() }); await new Pipeline <int, int>(source, stageOne.Object, stageTwo.Object) .GetAsync(source.Keys.ToArray()); stageTwo.Verify(s => s.SignalAsync(It.IsAny <CustomSignal <int, int> >(), It.IsAny <CancellationToken>()), Times.Once); }
public async Task Exceptions_Are_Handled_From_Custom_State_Machines() { var source = new StaticDataSource <int, int> { { 1, 1 }, { 2, 2 } }; var machine = new Mock <IStateMachine <int, int> >(); machine.Setup(m => m.Handle(It.IsAny <State <int, int> >(), It.IsAny <IRequest <int, int> >())) .Throws <NotImplementedException>(); var pipeline = new Pipeline <int, int>(source, new PipelineConfig <int, int> { InitialStateMachine = machine.Object }); var exception = await Assert.ThrowsAnyAsync <PipelineException <int, int> >(() => pipeline.GetAsync(source.Keys.ToArray())); Assert.Collection(exception.InnerExceptions, ex => Assert.IsType <NotImplementedException>(ex)); }
public async Task Requests_For_Data_Pass_Through_Configured_Stages() { var data = new Dictionary <int, int> { { 1, 1 } }; var source = new StaticDataSource <int, int>(data); var stage = new Mock <IStage <int, int> >(); stage.Setup(s => s.Process(It.IsAny <DataSet <int, int> >(), It.IsAny <CancellationToken>())) .Returns <DataSet <int, int>, CancellationToken>((r, t) => new[] { r }); stage.Setup(s => s.Process(It.IsAny <Query <int, int> >(), It.IsAny <CancellationToken>())) .Returns <Query <int, int>, CancellationToken>((r, t) => new[] { r }); await new Pipeline <int, int>(source, stage.Object).GetAsync(data.Keys); stage.Verify(s => s.Process(It.IsAny <Query <int, int> >(), It.IsAny <CancellationToken>()), Times.Once); stage.Verify(s => s.Process(It.IsAny <DataSet <int, int> >(), It.IsAny <CancellationToken>()), Times.Once); }
public async Task InvalidOperationException_Is_Thrown_If_State_Has_Invalid_Index(int index) { var source = new StaticDataSource <int, int> { { 1, 1 }, { 2, 2 } }; var stage = new StaticDataStage <int, int>(); var machine = new Mock <IStateMachine <int, int> >(); machine.Setup(m => m.Handle(It.IsAny <State <int, int> >(), It.IsAny <IRequest <int, int> >())) .Returns <State <int, int>, IRequest <int, int> >((s, t) => { s.Index = index; return(s); }); var pipeline = new Pipeline <int, int>(source, new PipelineConfig <int, int> { InitialStateMachine = machine.Object }, stage); var exception = await Assert.ThrowsAnyAsync <PipelineException <int, int> >(() => pipeline.GetAsync(source.Keys.ToArray())); Assert.Collection(exception.InnerExceptions, ex => Assert.IsType <InvalidOperationException>(ex)); }
public async Task Async_Requests_Can_Be_Used_To_Delay_Return_Of_Requests() { var data = new Dictionary <int, int> { { 1, 1 }, { 6, 1 }, { 7, 9 } }; var source = new StaticDataSource <int, int>(data); var stage = new Mock <IStage <int, int> >(); async Task <IEnumerable <IRequest <int, int> > > Process(IRequest <int, int> request) { await Task.Delay(1); return(new[] { request }); } stage.Setup(s => s.Process(It.IsAny <Query <int, int> >(), It.IsAny <CancellationToken>())) .Returns <Query <int, int>, CancellationToken>((r, t) => new[] { new Async <int, int>(r.Metadata, Process(r)) }); var pipeline = new Pipeline <int, int>(source, stage.Object); var results = await pipeline.GetAsync(data.Keys); Assert.Equal(data, results); }
public async Task SourceRead_And_PipelineComplete_Signals_Are_Sent_To_Stages() { var source = new StaticDataSource <int, int> { { 1, 1 }, { 2, 2 } }; var stage = new Mock <IStage <int, int> >(); stage.Setup(s => s.Process(It.IsAny <IRequest <int, int> >(), It.IsAny <CancellationToken>())) .Returns <IRequest <int, int>, CancellationToken>((r, t) => new[] { r }); var callOrder = 0; stage.Setup(s => s.SignalAsync(It.IsAny <SourceRead <int, int> >(), It.IsAny <CancellationToken>())) .Returns(Task.CompletedTask).Callback(() => Assert.Equal(0, callOrder++)); stage.Setup(s => s.SignalAsync(It.IsAny <PipelineComplete <int, int> >(), It.IsAny <CancellationToken>())) .Returns(Task.CompletedTask).Callback(() => Assert.Equal(1, callOrder++)); await new Pipeline <int, int>(source, stage.Object) .GetAsync(source.Keys.ToArray()); stage.Verify(s => s.SignalAsync(It.IsAny <SourceRead <int, int> >(), It.IsAny <CancellationToken>()), Times.Once); stage.Verify(s => s.SignalAsync(It.IsAny <PipelineComplete <int, int> >(), It.IsAny <CancellationToken>()), Times.Once); }
// This method gets called by the runtime. Use this method to add services to the container. public void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); StaticDataSource.Initialize(); }