Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,16 @@
shapeList.OfType<Square>().PrintList();

Console.WriteLine("\nFilter Is Not Null");
shapeList.FilterNotNull().PrintList();
shapeList.FilterNotNull().PrintList();

Console.WriteLine("\n--------------------Query Syntax--------------------\n");

Console.WriteLine("orderby ShapeType, ShapeId descending");
var byTypeThenId =
from s in shapeList
orderby s?.ShapeType, s?.ShapeId descending
select s;
byTypeThenId.PrintList();

Console.WriteLine("\nOfType<Shape>");
shapeList.OfType<Shape>().PrintList();
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,6 @@ public abstract record Shape : IComparable<Shape>
public int Height { get; init; }
public bool Is3D { get; protected init; }

public override string ToString() =>
$"ShapeId: {ShapeId} ShapeType: {ShapeType} ShapeWidth: {Width} ShapeHeight: {Height} is3D: {Is3D}";

public int CompareTo(Shape? other)
{
if (ReferenceEquals(this, other)) return 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

Expand All @@ -10,14 +10,13 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="FluentAssertions" Version="6.12.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.2" />
<PackageReference Include="xunit" Version="2.5.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.1">
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.11.0" />
<PackageReference Include="xunit" Version="2.9.3" />
<PackageReference Include="xunit.runner.visualstudio" Version="4.0.1">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0">
<PackageReference Include="coverlet.collector" Version="10.1.0">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,50 +2,58 @@

public class LinqFilteringMethodsTests
{
private readonly List<Shape?> _shapes = new()
{
new Cone {ShapeId = 1, Height = 3, Width = 2},
new Rectangle {ShapeId = 2, Height = 5, Width = 3},
new Square {ShapeId = 3, Height = 1, Width = 1},
new Cone {ShapeId = 4, Height = 4, Width = 3},
private readonly List<Shape?> _shapes =
[
new Cone { ShapeId = 1, Height = 3, Width = 2 },
new Rectangle { ShapeId = 2, Height = 5, Width = 3 },
new Square { ShapeId = 3, Height = 1, Width = 1 },
new Cone { ShapeId = 4, Height = 4, Width = 3 },
null
};
];

[Fact]
public void GivenShapeList_WhenFilterWhereCalled_ThenOnlyShapesWithHeightLessThan4AreReturned()
public void GivenShapeList_WhenFilterWhereCalled_ThenOnlyShapesWithHeightGreaterThan4AreReturned()
{
var result = _shapes.Where(s => s?.Height > 4).ToArray();

result.Should().ContainSingle();
result.First()!.Height.Should().BeGreaterThan(4);
var shape = Assert.Single(result);
Assert.True(shape!.Height > 4);
}

[Fact]
public void GivenShapeList_WhenFilterWhereVerboseCalled_ThenOnlyShapeThatPassCheckShapeAreReturned()
{
var result = _shapes.Where(LinqFilteringMethods.FilterIs3DAndWidthLessThan3).ToArray();

result.Should().ContainSingle();
result.First().Should().BeOfType<Cone>();
result.First()!.Width.Should().BeLessThan(3);
var shape = Assert.Single(result);
Assert.IsType<Cone>(shape);
Assert.True(shape!.Width < 3);
}

[Fact]
public void GivenShapeList_WhenFilterOfTypeCalled_ThenOnlyExpectedTypesAreReturned()
{
var result = _shapes.OfType<Square>().ToArray();

result.Should().ContainSingle();
result.First().Should().BeOfType<Square>();
result.First()!.ShapeId.Should().Be(3);
var square = Assert.Single(result);
Assert.Equal(3, square.ShapeId);
}

[Fact]
public void GivenShapeList_WhenFilterNullExtensionCalled_ThenNullShapesAreRemoved()
{
var result = _shapes.FilterNotNull().ToArray();

result.Should().HaveSameCount(_shapes.Where(x => x is not null));
result.Should().NotContainNulls();
Assert.Equal(_shapes.Count(x => x is not null), result.Length);
Assert.All(result, shape => Assert.NotNull(shape));
}

[Fact]
public void GivenShapeList_WhenOfTypeBaseType_ThenSameResultAsFilterNotNull()
{
var ofType = _shapes.OfType<Shape>();
var filterNotNull = _shapes.FilterNotNull();

Assert.Equal(filterNotNull, ofType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,137 +2,176 @@ namespace LINQSortingAndFilteringTests;

public class LinqSortingMethodsTests
{
private readonly List<Shape> _shapes = new()
{
new Rectangle {ShapeId = 2, Height = 4, Width = 2},
new Square {ShapeId = 1, Height = 2, Width = 2},
new Cone {ShapeId = 3, Height = 1, Width = 3}
};
private readonly List<Shape> _shapes =
[
new Rectangle { ShapeId = 2, Height = 4, Width = 2 },
new Square { ShapeId = 1, Height = 2, Width = 2 },
new Cone { ShapeId = 3, Height = 1, Width = 3 }
];

[Fact]
public void GivenObjectWithoutDefaultOrderer_WhenCallOrder_ThenThrowsInvalidOperationException()
{
var list = Enumerable.Range(0, 10).Select(_ => new SampleNoOrderer()).ToList();

var action = () => list.Order();
var ordered = list.Order();

action.Enumerating().Should().Throw<InvalidOperationException>();
Assert.Throws<InvalidOperationException>(() => ordered.ToList());
}

[Fact]
public void GivenObjectWithoutDefaultOrderer_WhenCallOrderByWithPropertyWithOrder_ThenExecutesWithoutException()
{
var list = Enumerable.Range(0, 10).Select(_ => new SampleNoOrderer()).ToList();

var action = () => list.OrderBy(x => x.Id);
var result = list.OrderBy(x => x.Id).ToList();

action.Enumerating().Should().NotThrow();
Assert.Equal(list.Count, result.Count);
}

[Fact]
public void
GivenMemberPropertyWithNoDefaultOrderer_WhenOrderByProperty_ThenThrowsInvalidOperationException()
public void GivenMemberPropertyWithNoDefaultOrderer_WhenOrderByProperty_ThenThrowsInvalidOperationException()
{
var list = Enumerable.Range(0, 10).Select(_ => new SampleMemberWithNoOrderer()).ToList();

var action = () => list.OrderBy(x => x.IdHolder);
var ordered = list.OrderBy(x => x.IdHolder);

action.Enumerating().Should().Throw<InvalidOperationException>();
Assert.Throws<InvalidOperationException>(() => ordered.ToList());
}

[Fact]
public void GivenObjectWithMemberHavingNoDefaultOrderer_WhenCallOrderByOtherProperty_ThenExecutesWithoutException()
{
var list = Enumerable.Range(0, 10).Select(_ => new SampleMemberWithNoOrderer()).ToList();

var sortByAAction = () => list.OrderBy(x => x.A);
var sortByBAction = () => list.OrderBy(x => x.B);
var byA = list.OrderBy(x => x.A).ToList();
var byB = list.OrderBy(x => x.B).ToList();

sortByAAction.Enumerating().Should().NotThrow();
sortByBAction.Enumerating().Should().NotThrow();
Assert.Equal(list.Count, byA.Count);
Assert.Equal(list.Count, byB.Count);
}

[Fact]
public void GivenShapeList_WhenCallingOrder_ThenSortedByDefaultOrdererShapeId()
{
var result = _shapes.Order().ToArray();
var result = _shapes.Order().Select(s => s.ShapeId).ToArray();

result.Should().HaveSameCount(_shapes);
result.Should().BeInAscendingOrder(s => s.ShapeId);
Assert.Equal([1, 2, 3], result);
}

[Fact]
public void GivenShapeList_WhenCallingOrderDescending_ThenSortedByDefaultOrdererShapeId()
{
var result = _shapes.OrderDescending().ToArray();
var result = _shapes.OrderDescending().Select(s => s.ShapeId).ToArray();

result.Should().HaveSameCount(_shapes);
result.Should().BeInDescendingOrder(s => s.ShapeId);
Assert.Equal([3, 2, 1], result);
}

[Fact]
public void GivenShapeList_WhenOrderByShapeType_ThenSortedByShapeType()
{
var result = _shapes.OrderBy(x => x.ShapeType).ToArray();

result.Should().HaveSameCount(_shapes);
result.First().Should().BeOfType<Cone>();
result.Last().Should().BeOfType<Square>();
result.Should().BeInAscendingOrder(s => s.ShapeType);
Assert.Equal(_shapes.Count, result.Length);
Assert.IsType<Cone>(result.First());
Assert.IsType<Square>(result.Last());
Assert.Equal(["Cone", "Rectangle", "Square"], result.Select(s => s.ShapeType));
}

[Fact]
public void GivenShapeList_WhenOrderByDescending_ThenSortedByShapeIdInDescendingOrder()
{
var result = _shapes.OrderByDescending(x => x.ShapeId).ToArray();
var result = _shapes.OrderByDescending(x => x.ShapeId).Select(s => s.ShapeId).ToArray();

result.Should().HaveSameCount(_shapes);
result.Should().BeInDescendingOrder(s => s.ShapeId);
Assert.Equal([3, 2, 1], result);
}

[Fact]
public void GivenShapeList_WhenOrderByIs3DThenByShapeId_ThenSortedByIs3DAndThenShapeId()
{
var result = _shapes.OrderBy(sl => sl.Is3D).ThenBy(sl => sl.ShapeId).ToArray();

result.Should().HaveSameCount(_shapes);
result[0].Is3D.Should().BeFalse();
result[1].Is3D.Should().BeFalse();
result[2].Is3D.Should().BeTrue();
result[0].ShapeId.Should().Be(1);
result[^1].ShapeId.Should().Be(3);
Assert.False(result[0].Is3D);
Assert.False(result[1].Is3D);
Assert.True(result[2].Is3D);
Assert.Equal(1, result[0].ShapeId);
Assert.Equal(3, result[^1].ShapeId);
}

[Fact]
public void GivenShapeList_WhenOrderByDescendingIs3DAndThenShapeIdDescending_ThenInDescendingOrder()
{
// Act
var result = _shapes.OrderByDescending(sl => sl.Is3D).ThenByDescending(sl => sl.ShapeId).ToArray();

// Assert
result.Should().HaveSameCount(_shapes);
result[0].Is3D.Should().BeTrue();
result[1].Is3D.Should().BeFalse();
result[2].Is3D.Should().BeFalse();
result[0].ShapeId.Should().Be(3);
result[^1].ShapeId.Should().Be(1);
Assert.True(result[0].Is3D);
Assert.False(result[1].Is3D);
Assert.False(result[2].Is3D);
Assert.Equal(3, result[0].ShapeId);
Assert.Equal(1, result[^1].ShapeId);
}

[Fact]
public void GivenShapeList_WhenReverse_ThenListIsReversed()
{
// Arrange
var listCopy = new List<Shape?>(_shapes);
listCopy.Reverse();

// Act
var result = _shapes.AsEnumerable().Reverse().ToArray();

// Assert
result.Should().HaveSameCount(_shapes);
result[0].Should().Be(_shapes[^1]);
result[1].Should().Be(_shapes[^2]);
result[2].Should().Be(_shapes[^3]);
Assert.Equal(_shapes.Count, result.Length);
Assert.Equal(_shapes[^1], result[0]);
Assert.Equal(_shapes[^2], result[1]);
Assert.Equal(_shapes[^3], result[2]);
}

[Fact]
public void GivenEqualKeys_WhenOrderByAndOrderByDescending_ThenOriginalOrderIsKept()
{
List<Shape> shapes =
[
new Square { ShapeId = 7, Height = 1, Width = 1 },
new Cone { ShapeId = 5, Height = 1, Width = 1 },
new Square { ShapeId = 2, Height = 1, Width = 1 },
new Square { ShapeId = 9, Height = 1, Width = 1 }
];

var ascending = shapes.OrderBy(s => s.ShapeType).Select(s => s.ShapeId);
var descending = shapes.OrderByDescending(s => s.ShapeType).Select(s => s.ShapeId);

Assert.Equal([5, 7, 2, 9], ascending);
Assert.Equal([7, 2, 9, 5], descending);
}

[Fact]
public void GivenQuerySyntax_WhenOrderByTwoKeys_ThenSameAsOrderByThenByDescending()
{
List<Shape?> shapes = [.. _shapes, null, new Square { ShapeId = 0, Height = 1, Width = 1 }];

var querySyntax =
from s in shapes
orderby s?.ShapeType, s?.ShapeId descending
select s;
var methodSyntax = shapes.OrderBy(s => s?.ShapeType).ThenByDescending(s => s?.ShapeId);

Assert.Equal(methodSyntax, querySyntax);
}

[Fact]
public void GivenShapeList_WhenSorted_ThenSourceListIsUnchanged()
{
var before = _shapes.ToArray();

_ = _shapes.OrderByDescending(s => s.ShapeId).ToList();

Assert.Equal(before, _shapes);
}

[Fact]
public void GivenSortedQuery_WhenSourceChangesBeforeEnumeration_ThenResultIncludesNewItem()
{
var shapes = new List<Shape>(_shapes);
var ordered = shapes.OrderBy(s => s.ShapeId);

shapes.Add(new Square { ShapeId = 0, Height = 1, Width = 1 });

Assert.Equal([0, 1, 2, 3], ordered.Select(s => s.ShapeId));
}

private sealed class SampleNoOrderer
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
global using Xunit;
global using LINQSortingAndFiltering;
global using FluentAssertions;
global using LINQSortingAndFiltering;
Loading