From de376f24594f2a4478928ed8e4b93bc3aaa3fdce Mon Sep 17 00:00:00 2001 From: PascalSenn Date: Sat, 21 Nov 2020 09:08:28 +0100 Subject: [PATCH] fixed list visitor did not pop instance (#2628) --- .../List/QueryableListOperationHandlerBase.cs | 3 +- .../QueryableFilterVisitorListTests.cs | 163 ++++++++++++++---- 2 files changed, 135 insertions(+), 31 deletions(-) diff --git a/src/HotChocolate/Data/src/Data/Filters/Expressions/Handlers/List/QueryableListOperationHandlerBase.cs b/src/HotChocolate/Data/src/Data/Filters/Expressions/Handlers/List/QueryableListOperationHandlerBase.cs index 8f20c2dba87..36606fc3718 100644 --- a/src/HotChocolate/Data/src/Data/Filters/Expressions/Handlers/List/QueryableListOperationHandlerBase.cs +++ b/src/HotChocolate/Data/src/Data/Filters/Expressions/Handlers/List/QueryableListOperationHandlerBase.cs @@ -67,6 +67,7 @@ public abstract class QueryableListOperationHandlerBase if (context.TryCreateLambda(out LambdaExpression? lambda)) { context.Scopes.Pop(); + Expression instance = context.PopInstance(); Expression expression = HandleListOperation( context, field, @@ -77,7 +78,7 @@ public abstract class QueryableListOperationHandlerBase if (context.InMemory) { expression = FilterExpressionBuilder.NotNullAndAlso( - context.GetInstance(), expression); + instance, expression); } context.GetLevel().Enqueue(expression); } diff --git a/src/HotChocolate/Data/test/Data.Filters.Tests/Expression/QueryableFilterVisitorListTests.cs b/src/HotChocolate/Data/test/Data.Filters.Tests/Expression/QueryableFilterVisitorListTests.cs index 195f0eeeb3a..5adc3b52ace 100644 --- a/src/HotChocolate/Data/test/Data.Filters.Tests/Expression/QueryableFilterVisitorListTests.cs +++ b/src/HotChocolate/Data/test/Data.Filters.Tests/Expression/QueryableFilterVisitorListTests.cs @@ -13,12 +13,12 @@ public class QueryableFilterVisitorListTests public void Create_ArraySomeStringEqual_Expression() { // arrange - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ bar: {some: { eq: \"a\" }}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooSimpleFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooSimpleFilterType()); // act - Func? func = tester.Build(value); + Func func = tester.Build(value); // assert var a = new FooSimple { Bar = new[] { "c", "d", "a" } }; @@ -32,12 +32,12 @@ public void Create_ArraySomeStringEqual_Expression() public void Create_ArrayAnyStringEqual_Expression() { // arrange - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ bar: {any: true}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooSimpleFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooSimpleFilterType()); // act - Func? func = tester.Build(value); + Func func = tester.Build(value); // assert var a = new FooSimple { Bar = new[] { "c", "d", "a" } }; @@ -54,12 +54,12 @@ public void Create_ArrayAnyStringEqual_Expression() public void Create_ArraySomeStringEqualWithNull_Expression() { // arrange - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ bar: {some: { eq: \"a\" }}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooSimpleFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooSimpleFilterType()); // act - Func? func = tester.Build(value); + Func func = tester.Build(value); // assert var a = new FooSimple { Bar = new[] { "c", null, "a" } }; @@ -76,9 +76,9 @@ public void Create_ArraySomeStringEqualWithNull_Expression() public void Create_ArraySomeObjectStringEqualWithNull_Expression() { // arrange - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ fooNested: {some: {bar: { eq: \"a\" }}}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooFilterType()); // act Func? func = tester.Build(value); @@ -109,9 +109,9 @@ public void Create_ArraySomeObjectStringEqualWithNull_Expression() [Fact] public void Create_ArraySomeObjectStringEqual_Expression() { - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ fooNested: {some: {bar: { eq: \"a\" }}}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooFilterType()); // act Func? func = tester.Build(value); @@ -155,9 +155,9 @@ public void Create_ArraySomeObjectStringEqual_Expression() [Fact] public void Create_ArrayNoneObjectStringEqual_Expression() { - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ fooNested: {none: {bar: { eq: \"a\" }}}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooFilterType()); // act Func? func = tester.Build(value); @@ -201,9 +201,9 @@ public void Create_ArrayNoneObjectStringEqual_Expression() public void Create_ArrayAllObjectStringEqual_Expression() { // arrange - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ fooNested: {all: { bar: {eq: \"a\" }}}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooFilterType()); // act Func? func = tester.Build(value); @@ -270,9 +270,9 @@ public void Create_ArrayAllObjectStringEqual_Expression() public void Create_ArrayAnyObjectStringEqual_Expression() { // arrange - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ fooNested: {any: true}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooFilterType()); // act Func? func = tester.Build(value); @@ -301,9 +301,9 @@ public void Create_ArrayAnyObjectStringEqual_Expression() public void Create_ArrayNotAnyObjectStringEqual_Expression() { // arrange - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ fooNested: {any: false}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooFilterType()); // act Func? func = tester.Build(value); @@ -334,12 +334,12 @@ public void Create_ArrayNotAnyObjectStringEqual_Expression() public void Create_ArraySomeStringEqual_Expression_Null() { // arrange - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ bar: {some: { eq: null }}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooSimpleFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooSimpleFilterType()); // act - Func? func = tester.Build(value); + Func func = tester.Build(value); // assert var a = new FooSimple { Bar = new[] { "c", null, "a" } }; @@ -353,12 +353,12 @@ public void Create_ArraySomeStringEqual_Expression_Null() public void Create_ArrayNoneStringEqual_Expression_Null() { // arrange - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ bar: {none: { eq: null }}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooSimpleFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooSimpleFilterType()); // act - Func? func = tester.Build(value); + Func func = tester.Build(value); // assert var a = new FooSimple { Bar = new[] { "c", "d", "a" } }; @@ -372,12 +372,12 @@ public void Create_ArrayNoneStringEqual_Expression_Null() public void Create_ArrayAllStringEqual_Expression_Null() { // arrange - IValueNode? value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( "{ bar: {all: { eq: null }}}"); - ExecutorBuilder? tester = CreateProviderTester(new FooSimpleFilterType()); + ExecutorBuilder tester = CreateProviderTester(new FooSimpleFilterType()); // act - Func? func = tester.Build(value); + Func func = tester.Build(value); // assert var a = new FooSimple { Bar = new string[] { null, null, null } }; @@ -385,17 +385,120 @@ public void Create_ArrayAllStringEqual_Expression_Null() var b = new FooSimple { Bar = new[] { "c", "d", "b" } }; Assert.False(func(b)); + } + + [Fact] + public void Create_ArraySomeStringEqual_Multiple() + { + // arrange + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + "{ bar: {some: { eq: \"a\" }} otherProperty: {eq:null}}"); + ExecutorBuilder tester = CreateProviderTester(new FooSimpleFilterType()); + + // act + Func func = tester.Build(value); + + // assert + var a = new FooSimple { Bar = new[] { "c", "d", "a" } }; + Assert.True(func(a)); + var b = new FooSimple { Bar = new[] { "c", "d", "b" } }; + Assert.False(func(b)); + } + + [Fact] + public void Create_ArraySomeObjectEqual_Multiple() + { + // arrange + IValueNode value = Utf8GraphQLParser.Syntax.ParseValueLiteral( + "{ fooNested: {some: {bar: { eq: \"a\" }}} otherProperty: {eq:null}}"); + ExecutorBuilder tester = CreateProviderTester(new FooFilterType()); + + // act + Func? func = tester.Build(value); + + // assert + var a = new Foo + { + FooNested = new[] + { + new FooNested { Bar = "a" }, + new FooNested { Bar = "a" }, + new FooNested { Bar = "a" } + } + }; + Assert.True(func(a)); + + var b = new Foo + { + FooNested = new[] + { + new FooNested { Bar = "c" }, + new FooNested { Bar = "a" }, + new FooNested { Bar = "a" } + } + }; + Assert.True(func(b)); + + var c = new Foo + { + FooNested = new[] + { + new FooNested { Bar = "a" }, + new FooNested { Bar = "d" }, + new FooNested { Bar = "b" } + } + }; + Assert.True(func(c)); + + var d = new Foo + { + FooNested = new[] + { + new FooNested { Bar = "c" }, + new FooNested { Bar = "d" }, + new FooNested { Bar = "b" } + } + }; + Assert.False(func(d)); + + var e = new Foo + { + FooNested = new[] + { + null, + new FooNested { Bar = null }, + new FooNested { Bar = "d" }, + new FooNested { Bar = "b" } + } + }; + Assert.False(func(e)); + + var f = new Foo + { + OtherProperty = "ShouldBeNull", + FooNested = new[] + { + new FooNested { Bar = "c" }, + new FooNested { Bar = "a" }, + new FooNested { Bar = "a" } + } + }; + Assert.False(func(f)); } public class Foo { public IEnumerable? FooNested { get; set; } + + public string? OtherProperty { get; set; } } public class FooSimple { public IEnumerable? Bar { get; set; } + + public string? OtherProperty { get; set; } } public class FooNested