Skip to content

Commit

Permalink
Merge pull request #47 from OData/users/TehWardy/foundations-expressi…
Browse files Browse the repository at this point in the history
…on-apply

FOUNDATIONS: Apply Expression to Source
  • Loading branch information
TehWardy authored Feb 16, 2024
2 parents 7c6c8e4 + 0847439 commit f03206f
Show file tree
Hide file tree
Showing 61 changed files with 1,141 additions and 332 deletions.
1 change: 0 additions & 1 deletion OData.Neo.Core.Tests.Unit/OData.Neo.Core.Tests.Unit.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
<ItemGroup>
<PackageReference Include="CompareNETObjects" Version="4.77.0" />
<PackageReference Include="FluentAssertions" Version="6.6.0" />
<PackageReference Include="InternalMock" Version="0.2.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.1.0" />
<PackageReference Include="Moq" Version="4.18.1" />
<PackageReference Include="Tynamix.ObjectFiller" Version="1.5.7" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
using FluentAssertions;
using Moq;
using OData.Neo.Core.Models.Coordinations.OQueries.Exceptions;
using OData.Neo.Core.Models.Orchestrations.Coordinates.Exceptions;
using Xeptions;
using Xunit;

Expand Down Expand Up @@ -99,7 +98,7 @@ public async Task ShouldThrowServiceExceptionOnProcessIfServiceErrorOccursAsync(
// given
string someOQueryExpression = GetRandomODataQuery();
var exception = new Exception();

var failedOQueryCoordinationServiceException =
new FailedOQueryCoordinationServiceException(
exception);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@
// See License.txt in the project root for license information.
//-----------------------------------------------------------------------

using System.Linq.Expressions;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using OData.Neo.Core.Models.OExpressions;
using OData.Neo.Core.Models.OTokens;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Xunit;

namespace OData.Neo.Core.Tests.Unit.Services.Coordinations.OQueries
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public OQueryCoordinationServiceTests()
{
this.oTokenizationOrchestrationServiceMock =
new Mock<IOTokenizationOrchestrationService>();

this.oQueryOrchestrationServiceMock =
new Mock<IOQueryOrchestrationService>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
Expand All @@ -19,7 +21,7 @@ public partial class OExpressionServiceTests
{
[Theory]
[MemberData(nameof(DependencyExceptions))]
public async Task ShouldThrowDependencyExceptionOnGenerateIfDependencyErrorOcurrsAndLogitAsync(
public async Task ShouldThrowDependencyExceptionOnGenerateIfDependencyErrorOccursAsync(
Exception dependencyException)
{
// given
Expand Down Expand Up @@ -59,7 +61,7 @@ await Assert.ThrowsAsync<OExpressionDependencyException>(
}

[Fact]
public async Task ShouldThrowServiceExceptionOnGenerateIfServiceErrorOcurrsAndLogitAsync()
public async Task ShouldThrowServiceExceptionOnGenerateIfServiceErrorOccursAsync()
{
// given
OExpression someOExpression = CreateRandomOExpression();
Expand Down Expand Up @@ -98,5 +100,54 @@ await Assert.ThrowsAsync<OExpressionServiceException>(

this.expressionBrokerMock.VerifyNoOtherCalls();
}


[Theory]
[MemberData(nameof(ApplyDependencyExceptions))]
public void ShouldThrowDependencyExceptionOnApplyIfDependencyErrorOccurs(
Exception dependencyException)
{
// given
IQueryable<object> someSource = CreateRandomSource();
ConstantExpression someExpression = Expression.Constant(value: default);
var someOExpression = new OExpression();
someOExpression.Expression = someExpression;

var failedOExpressionException =
new FailedOExpressionDependencyException(
dependencyException);

var expectedOExpressionDependencyException =
new OExpressionDependencyException(
failedOExpressionException);

this.expressionBrokerMock.Setup(broker =>
broker.ApplyExpression(
It.IsAny<IQueryable<object>>(),
It.IsAny<Expression>()))
.Throws(dependencyException);

// when
Action applyExpressionAction = () =>
this.oExpressionService.ApplyExpression(
someSource,
someOExpression);

OExpressionDependencyException actualOExpressionDependencyException =
Assert.Throws<OExpressionDependencyException>(
applyExpressionAction);

// then
actualOExpressionDependencyException.Should().BeEquivalentTo(
expectedOExpressionDependencyException);

this.expressionBrokerMock.Verify(broker =>
broker.ApplyExpression(
It.IsAny<IQueryable<object>>(),
It.IsAny<Expression>()),
Times.Once);

this.expressionBrokerMock.VerifyNoOtherCalls();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ public partial class OExpressionServiceTests
public async Task ShouldGenerateOExpressionAsync()
{
// given
(List<OToken> randomPropertyOTokens, string allRawValues) =
(List<OToken> randomPropertyOTokens, string allRawValues) =
CreateRandomPropertyOTokens();

(List<OToken> randomNonPropertyOTokens, _) =
Expand All @@ -41,8 +41,8 @@ public async Task ShouldGenerateOExpressionAsync()
RawValue = "$select",
Type = OTokenType.Select,
ProjectedType = ProjectedTokenType.Keyword,
Children =

Children =
randomPropertyOTokens.Concat(randomNonPropertyOTokens)
.ToList()
}
Expand Down Expand Up @@ -77,5 +77,38 @@ await this.oExpressionService.GenerateOExpressionAsync<object>(

this.expressionBrokerMock.VerifyNoOtherCalls();
}

[Fact]
public void ShouldApplyExpressionToSource()
{
// given
var randomSource = CreateRandomSource();
var randomExpression = Expression.Constant(value: default);
IQueryable<object> inputSource = CreateRandomSource();
Expression inputExpression = randomExpression;
IQueryable randomSourceAfterExpression = CreateRandomSource();
IQueryable expectedSource = randomSourceAfterExpression;
var inputOExpression = new OExpression();
inputOExpression.Expression = inputExpression;

this.expressionBrokerMock.Setup(broker =>
broker.ApplyExpression(inputSource, inputExpression))
.Returns(expectedSource);

// when
IQueryable actualSource =
this.oExpressionService.ApplyExpression(
inputSource,
inputOExpression);

// then
actualSource.Should().BeEquivalentTo(expectedSource);

this.expressionBrokerMock.Verify(broker =>
broker.ApplyExpression(inputSource, inputExpression),
Times.Once);

this.expressionBrokerMock.VerifyNoOtherCalls();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
//-----------------------------------------------------------------------
// Copyright (c) .NET Foundation and Contributors. All rights reserved.
// See License.txt in the project root for license information.
//-----------------------------------------------------------------------

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using FluentAssertions;
using Moq;
using OData.Neo.Core.Models.OExpressions;
using OData.Neo.Core.Models.OExpressions.Exceptions;
using Xunit;

namespace OData.Neo.Core.Tests.Unit.Services.Foundations.OExpressions
{
public partial class OExpressionServiceTests
{
[Fact]
public void ShouldThrowValidationExceptionOnApplyIfSourceIsNull()
{
// given
OExpression someOExpression = CreateRandomOExpression();
IQueryable<object> nullSource = null;

var nullSourceOExpressionException =
new NullSourceOExpressionException();

var expectedOExpressionValidationException =
new OExpressionValidationException(
nullSourceOExpressionException);

// when
Action applyExpressionAction = () =>
this.oExpressionService.ApplyExpression(
nullSource,
someOExpression);

OExpressionValidationException actualOExpressionValidationException =
Assert.Throws<OExpressionValidationException>(
applyExpressionAction);

// then
actualOExpressionValidationException.Should().BeEquivalentTo(
expectedOExpressionValidationException);

this.expressionBrokerMock.Verify(broker =>
broker.ApplyExpression<object>(
It.IsAny<IQueryable<object>>(),
It.IsAny<Expression>()),
Times.Never);

this.expressionBrokerMock.VerifyNoOtherCalls();
}

[Fact]
public void ShouldThrowValidationExceptionOnApplyIfOexpressionIsNull()
{
// given
OExpression nullOExpression = null;
IQueryable<object> someSource = CreateRandomSource();

var nullOExpressionException =
new NullOExpressionException();

var expectedOExpressionValidationException =
new OExpressionValidationException(
nullOExpressionException);

// when
Action applyExpressionAction = () =>
this.oExpressionService.ApplyExpression(
someSource,
nullOExpression);

OExpressionValidationException actualOExpressionValidationException =
Assert.Throws<OExpressionValidationException>(
applyExpressionAction);

// then
actualOExpressionValidationException.Should().BeEquivalentTo(
expectedOExpressionValidationException);

this.expressionBrokerMock.Verify(broker =>
broker.ApplyExpression<object>(
It.IsAny<IQueryable<object>>(),
It.IsAny<Expression>()),
Times.Never);

this.expressionBrokerMock.VerifyNoOtherCalls();
}

[Fact]
public void ShouldThrowValidationExceptionOnApplyIfExpressionIsNull()
{
// given
OExpression randomOExpression = CreateRandomOExpression();
IQueryable<object> someSource = CreateRandomSource();
OExpression invalidOExpression = randomOExpression;
invalidOExpression.Expression = null;

var invalidOExpressionException =
new InvalidOExpressionException();

invalidOExpressionException.AddData(
key: nameof(OExpression.Expression),
values: "Value is required");

var expectedOExpressionValidationException =
new OExpressionValidationException(
invalidOExpressionException);

// when
Action applyExpressionAction = () =>
this.oExpressionService.ApplyExpression(
someSource,
invalidOExpression);

OExpressionValidationException actualOExpressionValidationException =
Assert.Throws<OExpressionValidationException>(
applyExpressionAction);

// then
actualOExpressionValidationException.Should().BeEquivalentTo(
expectedOExpressionValidationException);

this.expressionBrokerMock.Verify(broker =>
broker.ApplyExpression<object>(
It.IsAny<IQueryable<object>>(),
It.IsAny<Expression>()),
Times.Never);

this.expressionBrokerMock.VerifyNoOtherCalls();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@
using System.Collections.Immutable;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection.Metadata.Ecma335;
using System.Text;
using System.Reflection;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Scripting;
using Moq;
Expand Down Expand Up @@ -51,6 +50,31 @@ public static TheoryData<Exception> DependencyExceptions()
};
}

public static TheoryData<Exception> ApplyDependencyExceptions()
{
var someInnerException = new Exception();

return new TheoryData<Exception>
{
new TargetException(),
new TargetParameterCountException(),
new MethodAccessException(),
new TargetInvocationException(someInnerException),
new NotSupportedException()
};
}

public static TheoryData<Exception> ApplyDependencyValidationExceptions()
{
return new TheoryData<Exception>
{
new InvalidCastException(),
new ArgumentNullException(),
new ArgumentOutOfRangeException(),
new InvalidOperationException()
};
}

private static (List<OToken>, string) CreateRandomPropertyOTokens()
{
var randomOTokens = new List<OToken>();
Expand Down Expand Up @@ -108,7 +132,7 @@ private static T GetEnumThatIsNot<T>(T notThisValue) where T : Enum

int randomNumber = new Random()
.Next(
minValue: 0,
minValue: 0,
maxValue: allValues.Length);

return allValues[randomNumber];
Expand All @@ -123,6 +147,18 @@ private static int GetRandomNumber() =>
private static string CreateRandomString() =>
new MnemonicString().GetValue();

private static IQueryable<object> CreateRandomSource()
{
var filler = new Filler<object>();

filler.Setup()
.OnType<object>().Use(CreateRandomString());

return filler
.Create(count: GetRandomNumber())
.AsQueryable<object>();
}

private static Filler<OExpression> CreateOExpressionFiller()
{
var filler = new Filler<OExpression>();
Expand Down
Loading

0 comments on commit f03206f

Please sign in to comment.