Skip to content

Commit 47f9dd1

Browse files
committed
Avoid allocating sub-arrays in ContainInOrder
The added tests are only to ensure behavior has not changed.
1 parent 1f4db92 commit 47f9dd1

File tree

2 files changed

+53
-34
lines changed

2 files changed

+53
-34
lines changed

Src/FluentAssertions/Collections/GenericCollectionAssertions.cs

Lines changed: 39 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -920,16 +920,26 @@ public AndConstraint<TAssertions> ContainInOrder(IEnumerable<T> expected, string
920920
IList<T> expectedItems = expected.ConvertOrCastToList();
921921
IList<T> actualItems = Subject.ConvertOrCastToList();
922922

923+
int subjectIndex = 0;
924+
923925
Func<T, T, bool> areSameOrEqual = ObjectExtensions.GetComparer<T>();
924926
for (int index = 0; index < expectedItems.Count; index++)
925927
{
926928
T expectedItem = expectedItems[index];
927-
actualItems = actualItems.SkipWhile(actualItem => !areSameOrEqual(actualItem, expectedItem)).ToArray();
928-
if (actualItems.Any())
929+
930+
bool foundExpectedItem = false;
931+
for (; subjectIndex < actualItems.Count; subjectIndex++)
929932
{
930-
actualItems = actualItems.Skip(1).ToArray();
933+
T actualItem = actualItems[subjectIndex];
934+
if (areSameOrEqual(actualItem, expectedItem))
935+
{
936+
foundExpectedItem = true;
937+
subjectIndex++;
938+
break;
939+
}
931940
}
932-
else
941+
942+
if (!foundExpectedItem)
933943
{
934944
Execute.Assertion
935945
.BecauseOf(because, becauseArgs)
@@ -2261,43 +2271,38 @@ public AndConstraint<TAssertions> NotContainInOrder(IEnumerable<T> unexpected, s
22612271
}
22622272

22632273
IList<T> unexpectedItems = unexpected.ConvertOrCastToList();
2264-
IList<T> actualItems = Subject.ConvertOrCastToList();
2265-
2266-
if (unexpectedItems.Count > actualItems.Count)
2274+
if (unexpectedItems.Any())
22672275
{
2268-
return new AndConstraint<TAssertions>((TAssertions)this);
2269-
}
2270-
2271-
var actualItemsSkipped = 0;
2272-
Func<T, T, bool> areSameOrEqual = ObjectExtensions.GetComparer<T>();
2273-
for (int index = 0; index < unexpectedItems.Count; index++)
2274-
{
2275-
T unexpectedItem = unexpectedItems[index];
2276-
2277-
actualItems = actualItems.SkipWhile(actualItem =>
2278-
{
2279-
actualItemsSkipped++;
2280-
return !areSameOrEqual(actualItem, unexpectedItem);
2281-
}).ToArray();
2276+
IList<T> actualItems = Subject.ConvertOrCastToList();
2277+
int subjectIndex = 0;
22822278

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

2295-
actualItems = actualItems.Skip(1).ToArray();
2296-
}
2297-
else
2298-
{
2299-
return new AndConstraint<TAssertions>((TAssertions)this);
2294+
if (!foundExpectedItem)
2295+
{
2296+
return new AndConstraint<TAssertions>((TAssertions)this);
2297+
}
23002298
}
2299+
2300+
Execute.Assertion
2301+
.BecauseOf(because, becauseArgs)
2302+
.FailWith(
2303+
"Expected {context:collection} {0} to not contain items {1} in order{reason}, " +
2304+
"but items appeared in order ending at index {2}.",
2305+
Subject, unexpected, subjectIndex - 1);
23012306
}
23022307

23032308
return new AndConstraint<TAssertions>((TAssertions)this);

Tests/FluentAssertions.Specs/Collections/CollectionAssertionSpecs.ContainInOrder.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,20 @@ public void When_passing_in_null_while_checking_for_ordered_containment_it_shoul
100100
"Cannot verify ordered containment against a <null> collection.*");
101101
}
102102

103+
[Fact]
104+
public void Collections_contain_the_empty_sequence()
105+
{
106+
// Assert
107+
new[] { 1 }.Should().ContainInOrder(new int[0]);
108+
}
109+
110+
[Fact]
111+
public void Collections_do_not_not_contain_the_empty_sequence()
112+
{
113+
// Assert
114+
new[] { 1 }.Should().NotContainInOrder(new int[0]);
115+
}
116+
103117
[Fact]
104118
public void When_asserting_collection_contains_some_values_in_order_but_collection_is_null_it_should_throw()
105119
{

0 commit comments

Comments
 (0)