Skip to content

Made pipelines more flexible. #9

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Open
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ bld/
[Bb]in/
[Oo]bj/
[Ll]og/
**/obj/
**/bin/
# Vs code settings
**/.vscode/

# Visual Studio 2015 cache/options directory
.vs/
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using PipelineNet.ChainsOfResponsibility;
using PipelineNet.Middleware;
using PipelineNet.MiddlewareResolver;
using System;
using System.Threading.Tasks;
using Xunit;
Expand Down Expand Up @@ -93,7 +92,7 @@ public async Task<bool> Run(Exception exception, Func<Exception, Task<bool>> exe
[Fact]
public async Task Execute_CreateChainOfMiddlewareToHandleException_TheRightMiddleHandlesTheException()
{
var responsibilityChain = new AsyncResponsibilityChain<Exception, bool>(new ActivatorMiddlewareResolver())
var responsibilityChain = new AsyncResponsibilityChain<Exception, bool>()
.Chain<UnavailableResourcesExceptionHandler>()
.Chain<InvalidateDataExceptionHandler>()
.Chain<MyExceptionHandler>();
Expand All @@ -113,7 +112,7 @@ public async Task Execute_CreateChainOfMiddlewareToHandleException_TheRightMiddl
[Fact]
public async Task Execute_ChainOfMiddlewareThatDoesNotHandleTheException_ChainReturnsDefaultValue()
{
var responsibilityChain = new AsyncResponsibilityChain<Exception, bool>(new ActivatorMiddlewareResolver())
var responsibilityChain = new AsyncResponsibilityChain<Exception, bool>()
.Chain<UnavailableResourcesExceptionHandler>()
.Chain<InvalidateDataExceptionHandler>()
.Chain<MyExceptionHandler>();
Expand All @@ -127,54 +126,13 @@ public async Task Execute_ChainOfMiddlewareThatDoesNotHandleTheException_ChainRe
Assert.Equal(default(bool), result);
}

[Fact]
public async Task Execute_ChainOfMiddlewareWithFinallyFunc_FinallyFuncIsExecuted()
{
const string ExceptionSource = "EXCEPTION_SOURCE";

var responsibilityChain = new AsyncResponsibilityChain<Exception, bool>(new ActivatorMiddlewareResolver())
.Chain<UnavailableResourcesExceptionHandler>()
.Chain(typeof(InvalidateDataExceptionHandler))
.Chain<MyExceptionHandler>()
.Finally((ex) =>
{
ex.Source = ExceptionSource;
return Task.FromResult(true);
});

// Creates an ArgumentNullException, that will not be handled by any middleware.
var exception = new ArgumentNullException();

// The result should true, since the finally function will be executed.
var result = await responsibilityChain.Execute(exception);

Assert.True(result);

Assert.Equal(ExceptionSource, exception.Source);
}

/// <summary>
/// Tests the <see cref="ResponsibilityChain{TParameter, TReturn}.Chain(Type)"/> method.
/// </summary>
[Fact]
public void Chain_AddTypeThatIsNotAMiddleware_ThrowsException()
{
var responsibilityChain = new AsyncResponsibilityChain<Exception, bool>(new ActivatorMiddlewareResolver());
Assert.Throws<ArgumentException>(() =>
{
responsibilityChain.Chain(typeof(ResponsibilityChainTests));
});
}



/// <summary>
/// Try to generate a deadlock in synchronous middleware.
/// </summary>
[Fact]
public void Execute_SynchronousChainOfResponsibility_SuccessfullyExecute()
{
var responsibilityChain = new AsyncResponsibilityChain<string, string>(new ActivatorMiddlewareResolver())
var responsibilityChain = new AsyncResponsibilityChain<string, string>()
.Chain<SyncReplaceNewLineMiddleware>()
.Chain<SyncTrimMiddleware>()
.Finally(input => Task.FromResult(input));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using PipelineNet.ChainsOfResponsibility;
using PipelineNet.Middleware;
using PipelineNet.MiddlewareResolver;
using System;
using Xunit;

Expand Down Expand Up @@ -68,7 +67,7 @@ public bool Run(Exception exception, Func<Exception, bool> executeNext)
[Fact]
public void Execute_CreateChainOfMiddlewareToHandleException_TheRightMiddleHandlesTheException()
{
var responsibilityChain = new ResponsibilityChain<Exception, bool>(new ActivatorMiddlewareResolver())
var responsibilityChain = new ResponsibilityChain<Exception, bool>()
.Chain<UnavailableResourcesExceptionHandler>()
.Chain<InvalidateDataExceptionHandler>()
.Chain<MyExceptionHandler>();
Expand All @@ -88,7 +87,7 @@ public void Execute_CreateChainOfMiddlewareToHandleException_TheRightMiddleHandl
[Fact]
public void Execute_ChainOfMiddlewareThatDoesNotHandleTheException_ChainReturnsDefaultValue()
{
var responsibilityChain = new ResponsibilityChain<Exception, bool>(new ActivatorMiddlewareResolver())
var responsibilityChain = new ResponsibilityChain<Exception, bool>()
.Chain<UnavailableResourcesExceptionHandler>()
.Chain<InvalidateDataExceptionHandler>()
.Chain<MyExceptionHandler>();
Expand All @@ -101,44 +100,5 @@ public void Execute_ChainOfMiddlewareThatDoesNotHandleTheException_ChainReturnsD

Assert.Equal(default(bool), result);
}

[Fact]
public void Execute_ChainOfMiddlewareWithFinallyFunc_FinallyFuncIsExecuted()
{
const string ExceptionSource = "EXCEPTION_SOURCE";

var responsibilityChain = new ResponsibilityChain<Exception, bool>(new ActivatorMiddlewareResolver())
.Chain<UnavailableResourcesExceptionHandler>()
.Chain(typeof(InvalidateDataExceptionHandler))
.Chain<MyExceptionHandler>()
.Finally((ex) =>
{
ex.Source = ExceptionSource;
return true;
});

// Creates an ArgumentNullException, that will not be handled by any middleware.
var exception = new ArgumentNullException();

// The result should true, since the finally function will be executed.
var result = responsibilityChain.Execute(exception);

Assert.True(result);

Assert.Equal(ExceptionSource, exception.Source);
}

/// <summary>
/// Tests the <see cref="ResponsibilityChain{TParameter, TReturn}.Chain(Type)"/> method.
/// </summary>
[Fact]
public void Chain_AddTypeThatIsNotAMiddleware_ThrowsException()
{
var responsibilityChain = new ResponsibilityChain<Exception, bool>(new ActivatorMiddlewareResolver());
Assert.Throws<ArgumentException>(() =>
{
responsibilityChain.Chain(typeof(ResponsibilityChainTests));
});
}
}
}
50 changes: 50 additions & 0 deletions src/PipelineNet.Tests/MethodsChains/MethodsChain.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using PipelineNet.MethodsChains;
using Xunit;

namespace PipelineNet.Tests.MethodsChains{
public class MethodsChainsTests{
[Fact]
public void NumberTransform(){
var chain = MethodsChain<int,string>
.Chain(num=>(1+num).ToString())
.Chain(numStr=>numStr+"2")
.Chain(int.Parse);
var expected = 12352;
var actual = chain.Run(1234);
Assert.Equal(expected,actual);
}
[Fact]
public void MethodAbortion(){
bool reachedEnd = false;
var chain = MethodsChain<int,int>
.Chain(num=>num+1)
.Chain(num=>num % 3 == 0 ? num/3 - 1 : throw new Exception())
.Chain(num=>{
reachedEnd = true;
return num+1 % 2 == 0 ? "yes" : "no";
});
Assert.Throws<Exception>(()=>chain.Run(25));
Assert.False(reachedEnd);
}
[Fact]
public void WithoutReturnType(){
var result = new List<int>();
var doubleResult = new List<int>();
var chain = MethodsChain<int,string>
.Chain(num=>(1+num).ToString())
.Chain(numStr=>numStr+"2")
.Chain(int.Parse)
.Chain(result.Add)
.Chain(x=>doubleResult.Add(x*2));

chain.Run(10);
chain.Run(20);
chain.Run(30);

Assert.Equal(new[]{112,212,312},result);
Assert.Equal(new[]{2*112,2*212,2*312},doubleResult);
}
}
}
19 changes: 7 additions & 12 deletions src/PipelineNet.Tests/PipelineNet.Tests.csproj
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp2.1</TargetFramework>

<TargetFramework>net7.0</TargetFramework>
<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
<PackageReference Include="xunit" Version="2.4.0" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0"/>
<PackageReference Include="xunit" Version="2.4.1"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\PipelineNet\PipelineNet.csproj" />
<ProjectReference Include="..\PipelineNet\PipelineNet.csproj"/>
</ItemGroup>

</Project>
</Project>
39 changes: 2 additions & 37 deletions src/PipelineNet.Tests/Pipelines/AsyncPipelineTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using PipelineNet.Middleware;
using PipelineNet.MiddlewareResolver;
using PipelineNet.Pipelines;
using System;
using System.Text.RegularExpressions;
Expand Down Expand Up @@ -76,7 +75,7 @@ public async Task Run(PersonModel context, Func<PersonModel, Task> executeNext)
[Fact]
public async Task Execute_RunSeveralMiddleware_SuccessfullyExecute()
{
var pipeline = new AsyncPipeline<PersonModel>(new ActivatorMiddlewareResolver())
var pipeline = new AsyncPipeline<PersonModel>()
.Add<PersonWithEvenId>()
.Add<PersonWithOddId>()
.Add<PersonWithEmailName>()
Expand All @@ -97,7 +96,7 @@ public async Task Execute_RunSeveralMiddleware_SuccessfullyExecute()
[Fact]
public async Task Execute_RunSamePipelineTwice_SuccessfullyExecute()
{
var pipeline = new AsyncPipeline<PersonModel>(new ActivatorMiddlewareResolver())
var pipeline = new AsyncPipeline<PersonModel>()
.Add<PersonWithEvenId>()
.Add<PersonWithOddId>()
.Add<PersonWithEmailName>()
Expand Down Expand Up @@ -128,39 +127,5 @@ public async Task Execute_RunSamePipelineTwice_SuccessfullyExecute()
// Check if the level of 'personModel' is 4, which is configured by 'PersonWithGenderProperty' middleware.
Assert.Equal(4, personModel.Level);
}

[Fact]
public async Task Execute_RunSeveralMiddlewareWithTwoBeingDynamiccalyAdded_SuccessfullyExecute()
{
var pipeline = new AsyncPipeline<PersonModel>(new ActivatorMiddlewareResolver())
.Add<PersonWithEvenId>()
.Add(typeof(PersonWithOddId))
.Add<PersonWithEmailName>()
.Add(typeof(PersonWithGenderProperty));

// This person model has a gender, so the last middleware will be the one handling the input.
var personModel = new PersonModel
{
Gender = Gender.Female
};

await pipeline.Execute(personModel);

// Check if the level of 'personModel' is 4, which is configured by 'PersonWithGenderProperty' middleware.
Assert.Equal(4, personModel.Level);
}

/// <summary>
/// Tests the <see cref="AsyncPipeline{TParameter}.Add(Type)"/> method.
/// </summary>
[Fact]
public void Add_AddTypeThatIsNotAMiddleware_ThrowsException()
{
var pipeline = new AsyncPipeline<PersonModel>(new ActivatorMiddlewareResolver());
Assert.Throws<ArgumentException>(() =>
{
pipeline.Add(typeof(AsyncPipelineTests));
});
}
}
}
43 changes: 5 additions & 38 deletions src/PipelineNet.Tests/Pipelines/PipelineTests.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
using PipelineNet.Middleware;
using PipelineNet.MiddlewareResolver;
using PipelineNet.Pipelines;
using System;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using Xunit;

Expand Down Expand Up @@ -72,7 +74,7 @@ public void Run(PersonModel context, Action<PersonModel> executeNext)
[Fact]
public void Execute_RunSeveralMiddleware_SuccessfullyExecute()
{
var pipeline = new Pipeline<PersonModel>(new ActivatorMiddlewareResolver())
var pipeline = new Pipeline<PersonModel>()
.Add<PersonWithEvenId>()
.Add<PersonWithOddId>()
.Add<PersonWithEmailName>()
Expand All @@ -93,7 +95,7 @@ public void Execute_RunSeveralMiddleware_SuccessfullyExecute()
[Fact]
public void Execute_RunSamePipelineTwice_SuccessfullyExecute()
{
var pipeline = new Pipeline<PersonModel>(new ActivatorMiddlewareResolver())
var pipeline = new Pipeline<PersonModel>()
.Add<PersonWithEvenId>()
.Add<PersonWithOddId>()
.Add<PersonWithEmailName>()
Expand All @@ -104,7 +106,6 @@ public void Execute_RunSamePipelineTwice_SuccessfullyExecute()
{
Name = "[email protected]"
};

pipeline.Execute(personModel);

// Check if the level of 'personModel' is 3, which is configured by 'PersonWithEmailName' middleware.
Expand All @@ -124,39 +125,5 @@ public void Execute_RunSamePipelineTwice_SuccessfullyExecute()
// Check if the level of 'personModel' is 4, which is configured by 'PersonWithGenderProperty' middleware.
Assert.Equal(4, personModel.Level);
}

[Fact]
public void Execute_RunSeveralMiddlewareWithTwoBeingDynamiccalyAdded_SuccessfullyExecute()
{
var pipeline = new Pipeline<PersonModel>(new ActivatorMiddlewareResolver())
.Add<PersonWithEvenId>()
.Add(typeof(PersonWithOddId))
.Add<PersonWithEmailName>()
.Add(typeof(PersonWithGenderProperty));

// This person model has a gender, so the last middleware will be the one handling the input.
var personModel = new PersonModel
{
Gender = Gender.Female
};

pipeline.Execute(personModel);

// Check if the level of 'personModel' is 4, which is configured by 'PersonWithGenderProperty' middleware.
Assert.Equal(4, personModel.Level);
}

/// <summary>
/// Tests the <see cref="Pipeline{TParameter}.Add(Type)"/> method.
/// </summary>
[Fact]
public void Add_AddTypeThatIsNotAMiddleware_ThrowsException()
{
var pipeline = new Pipeline<PersonModel>(new ActivatorMiddlewareResolver());
Assert.Throws<ArgumentException>(() =>
{
pipeline.Add(typeof(PipelineTests));
});
}
}
}
Loading