From 3e61d5fbfea629cbc805f1ff4c07501363bc8322 Mon Sep 17 00:00:00 2001 From: Stef Heyenrath Date: Tue, 24 Dec 2024 16:23:47 +0100 Subject: [PATCH] Add OrderBy NullPropagation tests --- .../EntitiesTests.OrderBy.cs | 22 ++ .../Helpers/Models/User.cs | 2 + .../QueryableTests.OrderBy.cs | 334 +++++++++++------- 3 files changed, 224 insertions(+), 134 deletions(-) diff --git a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.OrderBy.cs b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.OrderBy.cs index 6355b188b..013244246 100644 --- a/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.OrderBy.cs +++ b/test/System.Linq.Dynamic.Core.Tests/EntitiesTests.OrderBy.cs @@ -51,4 +51,26 @@ public void Entities_OrderBy_RestrictOrderByIsTrue_InvalidExpressionShouldThrow( // Assert action.Should().Throw().WithMessage("No property or field 'IIF' exists in type 'Blog'"); } + + [Fact] + public void Entities_OrderBy_NullPropagation_Int() + { + // Arrange + var resultBlogs = _context.Blogs.OrderBy(b => b.NullableInt ?? -1).ToArray(); + var dynamicResultBlogs = _context.Blogs.OrderBy("np(NullableInt, -1)").ToArray(); + + // Assert + Assert.Equal(resultBlogs, dynamicResultBlogs); + } + + [Fact] + public void Entities_OrderBy_NullPropagation_String() + { + // Arrange + var resultBlogs = _context.Blogs.OrderBy(b => b.X ?? "_").ToArray(); + var dynamicResultBlogs = _context.Blogs.OrderBy("np(X, \"_\")").ToArray(); + + // Assert + Assert.Equal(resultBlogs, dynamicResultBlogs); + } } \ No newline at end of file diff --git a/test/System.Linq.Dynamic.Core.Tests/Helpers/Models/User.cs b/test/System.Linq.Dynamic.Core.Tests/Helpers/Models/User.cs index 9621d472f..dfe5b52d9 100644 --- a/test/System.Linq.Dynamic.Core.Tests/Helpers/Models/User.cs +++ b/test/System.Linq.Dynamic.Core.Tests/Helpers/Models/User.cs @@ -24,6 +24,8 @@ public class User public int? NullableInt { get; set; } + public string? NullableString { get; set; } + public int Income { get; set; } public char C { get; set; } diff --git a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.OrderBy.cs b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.OrderBy.cs index 5d85502f5..a02661e66 100644 --- a/test/System.Linq.Dynamic.Core.Tests/QueryableTests.OrderBy.cs +++ b/test/System.Linq.Dynamic.Core.Tests/QueryableTests.OrderBy.cs @@ -4,172 +4,238 @@ using System.Linq.Dynamic.Core.Tests.Helpers.Models; using Xunit; -namespace System.Linq.Dynamic.Core.Tests +namespace System.Linq.Dynamic.Core.Tests; + +public partial class QueryableTests { - public partial class QueryableTests + public class IntComparerT : IComparer { - public class IntComparerT : IComparer + public int Compare(int x, int y) { - public int Compare(int x, int y) - { - return new CaseInsensitiveComparer().Compare(y, x); - } + return new CaseInsensitiveComparer().Compare(y, x); } + } - public class StringComparerT : IComparer + public class StringComparerT : IComparer + { + public int Compare(string? x, string? y) { - public int Compare(string x, string y) - { - return new CaseInsensitiveComparer().Compare(y, x); - } + return new CaseInsensitiveComparer().Compare(y, x); } + } - public class ObjectComparer : IComparer + public class ObjectComparer : IComparer + { + public int Compare(object? x, object? y) { - public int Compare(object x, object y) - { - return new CaseInsensitiveComparer().Compare(y, x); - } + return new CaseInsensitiveComparer().Compare(y, x); } + } - [Fact] - public void OrderBy_Dynamic_IComparer_StringComparer() - { - // Arrange - var testList = User.GenerateSampleModels(2); - var qry = testList.AsQueryable(); + [Fact] + public void OrderBy_Dynamic_NullPropagation_Int() + { + // Arrange + var testList = User.GenerateSampleModels(2); + var qry = testList.AsQueryable(); - // Act - var orderBy = testList.OrderBy(x => x.UserName, StringComparer.OrdinalIgnoreCase).ToArray(); - var orderByDynamic = qry.OrderBy("UserName", StringComparer.OrdinalIgnoreCase).ToArray(); + // Act + var orderBy = testList.OrderBy(x => x.NullableInt ?? -1).ToArray(); + var orderByDynamic = qry.OrderBy("np(NullableInt, -1)").ToArray(); - // Assert - Assert.Equal(orderBy, orderByDynamic); - } + // Assert + Assert.Equal(orderBy, orderByDynamic); + } - [Fact] - public void OrderBy_Dynamic_IComparer_ObjectComparer_Int() - { - // Arrange - var testList = User.GenerateSampleModels(3); - var qry = testList.AsQueryable(); + [Fact] + public void OrderBy_Dynamic_NullPropagation_String() + { + // Arrange + var testList = User.GenerateSampleModels(2); + var qry = testList.AsQueryable(); - // Act - var orderBy = testList.OrderBy(x => x.Income, new IntComparerT()).ToArray(); - var orderByDynamic = qry.OrderBy("Income", new ObjectComparer()).ToArray(); + // Act + var orderBy = testList.OrderBy(x => x.NullableString ?? "_").ToArray(); + var orderByDynamic = qry.OrderBy("np(NullableString, \"_\")").ToArray(); - // Assert - Assert.Equal(orderBy, orderByDynamic); - } + // Assert + Assert.Equal(orderBy, orderByDynamic); + } - [Fact] - public void OrderBy_Dynamic_IComparer_ObjectComparer_String() - { - // Arrange - var testList = User.GenerateSampleModels(3); - var qry = testList.AsQueryable(); + [Fact] + public void OrderBy_Dynamic_NullPropagation_NestedObject() + { + // Arrange + var testList = User.GenerateSampleModels(2); + var qry = testList.AsQueryable(); - // Act - var orderBy = testList.OrderBy(x => x.UserName, new StringComparerT()).ToArray(); - var orderByDynamic = qry.OrderBy("UserName", new ObjectComparer()).ToArray(); + // Act + var orderBy = testList.OrderBy(x => x.Profile?.Age ?? -1).ToArray(); + var orderByDynamic = qry.OrderBy("np(Profile.Age, -1)").ToArray(); - // Assert - Assert.Equal(orderBy, orderByDynamic); - } + // Assert + Assert.Equal(orderBy, orderByDynamic); + } - [Fact] - public void OrderBy_Dynamic_IComparer_IntComparerT() - { - // Arrange - var testList = User.GenerateSampleModels(3); - var qry = testList.AsQueryable(); + [Fact] + public void OrderBy_Dynamic_NullPropagation_NestedObject_Query() + { + // Arrange + var qry = User.GenerateSampleModels(2) + .Select(u => new + { + u.UserName, + X = new + { + u.Profile?.Age + } + }) + .AsQueryable(); + + // Act + var orderByDynamic = qry.OrderBy("np(X.Age, -1)").ToArray(); + + // Assert + Assert.NotNull(orderByDynamic); + } - // Act - var orderBy = testList.OrderBy(x => x.Income, new IntComparerT()).ToArray(); - var orderByDynamic = qry.OrderBy("Income", new IntComparerT()).ToArray(); + [Fact] + public void OrderBy_Dynamic_IComparer_StringComparer() + { + // Arrange + var testList = User.GenerateSampleModels(2); + var qry = testList.AsQueryable(); - // Assert - Assert.Equal(orderBy, orderByDynamic); - } + // Act + var orderBy = testList.OrderBy(x => x.UserName, StringComparer.OrdinalIgnoreCase).ToArray(); + var orderByDynamic = qry.OrderBy("UserName", StringComparer.OrdinalIgnoreCase).ToArray(); - [Fact] - public void OrderBy_Dynamic_IComparer_IntComparerT_Asc() - { - // Arrange - var testList = User.GenerateSampleModels(2); - var qry = testList.AsQueryable(); + // Assert + Assert.Equal(orderBy, orderByDynamic); + } - // Act - var orderBy = testList.OrderBy(x => x.Income, new IntComparerT()).ToArray(); - var orderByDynamic = qry.OrderBy("Income asc", new IntComparerT()).ToArray(); + [Fact] + public void OrderBy_Dynamic_IComparer_ObjectComparer_Int() + { + // Arrange + var testList = User.GenerateSampleModels(3); + var qry = testList.AsQueryable(); - // Assert - Assert.Equal(orderBy, orderByDynamic); - } + // Act + var orderBy = testList.OrderBy(x => x.Income, new IntComparerT()).ToArray(); + var orderByDynamic = qry.OrderBy("Income", new ObjectComparer()).ToArray(); - [Fact] - public void OrderBy_Dynamic_IComparer_IntComparerT_Desc() - { - // Arrange - var testList = User.GenerateSampleModels(2); - var qry = testList.AsQueryable(); + // Assert + Assert.Equal(orderBy, orderByDynamic); + } - // Act - var orderBy = testList.OrderByDescending(x => x.Income, new IntComparerT()).ToArray(); - var orderByDynamic = qry.OrderBy("Income desc", new IntComparerT()).ToArray(); + [Fact] + public void OrderBy_Dynamic_IComparer_ObjectComparer_String() + { + // Arrange + var testList = User.GenerateSampleModels(3); + var qry = testList.AsQueryable(); - // Assert - Assert.Equal(orderBy, orderByDynamic); - } + // Act + var orderBy = testList.OrderBy(x => x.UserName, new StringComparerT()).ToArray(); + var orderByDynamic = qry.OrderBy("UserName", new ObjectComparer()).ToArray(); - [Fact] - public void OrderBy_Dynamic() - { - // Arrange - var testList = User.GenerateSampleModels(100); - var qry = testList.AsQueryable(); - - // Act - var orderById = qry.OrderBy("Id"); - var orderByAge = qry.OrderBy("Profile.Age"); - var orderByComplex1 = qry.OrderBy("Profile.Age, Id"); - - // Assert - Assert.Equal(testList.OrderBy(x => x.Id).ToArray(), orderById.ToArray()); - Assert.Equal(testList.OrderBy(x => x.Profile.Age).ToArray(), orderByAge.ToArray()); - Assert.Equal(testList.OrderBy(x => x.Profile.Age).ThenBy(x => x.Id).ToArray(), orderByComplex1.ToArray()); - } + // Assert + Assert.Equal(orderBy, orderByDynamic); + } - [Fact] - public void OrderBy_Dynamic_AsStringExpression() - { - // Arrange - var testList = User.GenerateSampleModels(100); - var qry = testList.AsQueryable(); + [Fact] + public void OrderBy_Dynamic_IComparer_IntComparerT() + { + // Arrange + var testList = User.GenerateSampleModels(3); + var qry = testList.AsQueryable(); - // Act - var expected = qry.SelectMany(x => x.Roles.OrderBy(y => y.Name)).Select(x => x.Name); - var orderById = qry.SelectMany("Roles.OrderBy(Name)").Select("Name"); + // Act + var orderBy = testList.OrderBy(x => x.Income, new IntComparerT()).ToArray(); + var orderByDynamic = qry.OrderBy("Income", new IntComparerT()).ToArray(); - // Assert - Assert.Equal(expected.ToArray(), orderById.Cast().ToArray()); - } + // Assert + Assert.Equal(orderBy, orderByDynamic); + } - [Fact] - public void OrderBy_Dynamic_Exceptions() - { - // Arrange - var testList = User.GenerateSampleModels(100, allowNullableProfiles: true); - var qry = testList.AsQueryable(); - - // Act - Assert.Throws(() => qry.OrderBy("Bad=3")); - Assert.Throws(() => qry.Where("Id=123")); - - Assert.Throws(() => DynamicQueryableExtensions.OrderBy(null, "Id")); - Assert.Throws(() => qry.OrderBy(null)); - Assert.Throws(() => qry.OrderBy("")); - Assert.Throws(() => qry.OrderBy(" ")); - } + [Fact] + public void OrderBy_Dynamic_IComparer_IntComparerT_Asc() + { + // Arrange + var testList = User.GenerateSampleModels(2); + var qry = testList.AsQueryable(); + + // Act + var orderBy = testList.OrderBy(x => x.Income, new IntComparerT()).ToArray(); + var orderByDynamic = qry.OrderBy("Income asc", new IntComparerT()).ToArray(); + + // Assert + Assert.Equal(orderBy, orderByDynamic); + } + + [Fact] + public void OrderBy_Dynamic_IComparer_IntComparerT_Desc() + { + // Arrange + var testList = User.GenerateSampleModels(2); + var qry = testList.AsQueryable(); + + // Act + var orderBy = testList.OrderByDescending(x => x.Income, new IntComparerT()).ToArray(); + var orderByDynamic = qry.OrderBy("Income desc", new IntComparerT()).ToArray(); + + // Assert + Assert.Equal(orderBy, orderByDynamic); + } + + [Fact] + public void OrderBy_Dynamic() + { + // Arrange + var testList = User.GenerateSampleModels(100); + var qry = testList.AsQueryable(); + + // Act + var orderById = qry.OrderBy("Id"); + var orderByAge = qry.OrderBy("Profile.Age"); + var orderByComplex1 = qry.OrderBy("Profile.Age, Id"); + + // Assert + Assert.Equal(testList.OrderBy(x => x.Id).ToArray(), orderById.ToArray()); + Assert.Equal(testList.OrderBy(x => x.Profile.Age).ToArray(), orderByAge.ToArray()); + Assert.Equal(testList.OrderBy(x => x.Profile.Age).ThenBy(x => x.Id).ToArray(), orderByComplex1.ToArray()); + } + + [Fact] + public void OrderBy_Dynamic_AsStringExpression() + { + // Arrange + var testList = User.GenerateSampleModels(100); + var qry = testList.AsQueryable(); + + // Act + var expected = qry.SelectMany(x => x.Roles.OrderBy(y => y.Name)).Select(x => x.Name); + var orderById = qry.SelectMany("Roles.OrderBy(Name)").Select("Name"); + + // Assert + Assert.Equal(expected.ToArray(), orderById.Cast().ToArray()); + } + + [Fact] + public void OrderBy_Dynamic_Exceptions() + { + // Arrange + var testList = User.GenerateSampleModels(100, allowNullableProfiles: true); + var qry = testList.AsQueryable(); + + // Act + Assert.Throws(() => qry.OrderBy("Bad=3")); + Assert.Throws(() => qry.Where("Id=123")); + + Assert.Throws(() => DynamicQueryableExtensions.OrderBy(null, "Id")); + Assert.Throws(() => qry.OrderBy(null)); + Assert.Throws(() => qry.OrderBy("")); + Assert.Throws(() => qry.OrderBy(" ")); } } \ No newline at end of file