Skip to content

Commit

Permalink
Avoid allocating sub-arrays in ContainInOrder
Browse files Browse the repository at this point in the history
The added tests are only to ensure behavior has not changed.
  • Loading branch information
jnyrup committed Jul 21, 2022
1 parent 1f4db92 commit 47f9dd1
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 34 deletions.
73 changes: 39 additions & 34 deletions Src/FluentAssertions/Collections/GenericCollectionAssertions.cs
Expand Up @@ -920,16 +920,26 @@ public AndConstraint<TAssertions> ContainInOrder(params T[] expected)
IList<T> expectedItems = expected.ConvertOrCastToList();
IList<T> actualItems = Subject.ConvertOrCastToList();

int subjectIndex = 0;

Func<T, T, bool> areSameOrEqual = ObjectExtensions.GetComparer<T>();
for (int index = 0; index < expectedItems.Count; index++)
{
T expectedItem = expectedItems[index];
actualItems = actualItems.SkipWhile(actualItem => !areSameOrEqual(actualItem, expectedItem)).ToArray();
if (actualItems.Any())

bool foundExpectedItem = false;
for (; subjectIndex < actualItems.Count; subjectIndex++)
{
actualItems = actualItems.Skip(1).ToArray();
T actualItem = actualItems[subjectIndex];
if (areSameOrEqual(actualItem, expectedItem))
{
foundExpectedItem = true;
subjectIndex++;
break;
}
}
else

if (!foundExpectedItem)
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
Expand Down Expand Up @@ -2261,43 +2271,38 @@ public AndConstraint<TAssertions> NotContainInOrder(params T[] unexpected)
}

IList<T> unexpectedItems = unexpected.ConvertOrCastToList();
IList<T> actualItems = Subject.ConvertOrCastToList();

if (unexpectedItems.Count > actualItems.Count)
if (unexpectedItems.Any())
{
return new AndConstraint<TAssertions>((TAssertions)this);
}

var actualItemsSkipped = 0;
Func<T, T, bool> areSameOrEqual = ObjectExtensions.GetComparer<T>();
for (int index = 0; index < unexpectedItems.Count; index++)
{
T unexpectedItem = unexpectedItems[index];

actualItems = actualItems.SkipWhile(actualItem =>
{
actualItemsSkipped++;
return !areSameOrEqual(actualItem, unexpectedItem);
}).ToArray();
IList<T> actualItems = Subject.ConvertOrCastToList();
int subjectIndex = 0;

if (actualItems.Any())
Func<T, T, bool> areSameOrEqual = ObjectExtensions.GetComparer<T>();
foreach (var unexpectedItem in unexpectedItems)
{
if (index == unexpectedItems.Count - 1)
bool foundExpectedItem = false;
for (; subjectIndex < actualItems.Count; subjectIndex++)
{
Execute.Assertion
.BecauseOf(because, becauseArgs)
.FailWith(
"Expected {context:collection} {0} to not contain items {1} in order{reason}, " +
"but items appeared in order ending at index {2}.",
Subject, unexpected, actualItemsSkipped - 1);
T actualItem = actualItems[subjectIndex];
if (areSameOrEqual(actualItem, unexpectedItem))
{
foundExpectedItem = true;
subjectIndex++;
break;
}
}

actualItems = actualItems.Skip(1).ToArray();
}
else
{
return new AndConstraint<TAssertions>((TAssertions)this);
if (!foundExpectedItem)
{
return new AndConstraint<TAssertions>((TAssertions)this);
}
}

Execute.Assertion
.BecauseOf(because, becauseArgs)
.FailWith(
"Expected {context:collection} {0} to not contain items {1} in order{reason}, " +
"but items appeared in order ending at index {2}.",
Subject, unexpected, subjectIndex - 1);
}

return new AndConstraint<TAssertions>((TAssertions)this);
Expand Down
Expand Up @@ -100,6 +100,20 @@ public void When_passing_in_null_while_checking_for_ordered_containment_it_shoul
"Cannot verify ordered containment against a <null> collection.*");
}

[Fact]
public void Collections_contain_the_empty_sequence()
{
// Assert
new[] { 1 }.Should().ContainInOrder(new int[0]);
}

[Fact]
public void Collections_do_not_not_contain_the_empty_sequence()
{
// Assert
new[] { 1 }.Should().NotContainInOrder(new int[0]);
}

[Fact]
public void When_asserting_collection_contains_some_values_in_order_but_collection_is_null_it_should_throw()
{
Expand Down

0 comments on commit 47f9dd1

Please sign in to comment.