Skip to content

Commit

Permalink
#2872: Expand special handling for sets in Assert.Contains/DoesNotCon…
Browse files Browse the repository at this point in the history
…tain (v2)
  • Loading branch information
bradwilson committed Feb 4, 2024
1 parent 203b4d9 commit 13bb60b
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/xunit.assert/Asserts
Submodule Asserts updated 1 files
+38 −14 CollectionAsserts.cs
39 changes: 31 additions & 8 deletions test/test.xunit.assert/Asserts/CollectionAssertsTests.cs
Expand Up @@ -324,15 +324,22 @@ public static void NullsAllowedInContainer()
}

[Fact]
public static void HashSetIsTreatedSpecially()
public static void SetsAreTreatedSpecially()
{
// HashSet.Contains() is a custom implementation since the comparer is passed
// to the constructor. If this comes in via the IEnumerable<T> overload, we want
// to make sure it still gets treated like a HashSet.
IEnumerable<string> set = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Hi there" };

Assert.Contains("HI THERE", set);
}

#if NET5_0_OR_GREATER
[Fact]
public static void ReadOnlySetsAreTreatedSpecially()
{
IEnumerable<string> set = new ReadOnlySet<string>(StringComparer.OrdinalIgnoreCase, "Hi there");

Assert.Contains("HI THERE", set);
}
#endif
}

public class Contains_Comparer
Expand Down Expand Up @@ -536,11 +543,8 @@ public static void NullsAllowedInContainer()
}

[Fact]
public static void HashSetIsTreatedSpecially()
public static void SetsAreTreatedSpecially()
{
// HashSet.Contains() is a custom implementation since the comparer is passed
// to the constructor. If this comes in via the IEnumerable<T> overload, we want
// to make sure it still gets treated like a HashSet.
IEnumerable<string> set = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Hi there" };

var ex = Record.Exception(() => Assert.DoesNotContain("HI THERE", set));
Expand All @@ -554,6 +558,25 @@ public static void HashSetIsTreatedSpecially()
ex.Message
);
}

#if NET5_0_OR_GREATER
[Fact]
public static void ReadOnlySetsAreTreatedSpecially()
{
IEnumerable<string> set = new ReadOnlySet<string>(StringComparer.OrdinalIgnoreCase, "Hi there");

var ex = Record.Exception(() => Assert.DoesNotContain("HI THERE", set));

Assert.IsType<DoesNotContainException>(ex);
// Note: There is no pointer for sets, unlike other collections
Assert.Equal(
"Assert.DoesNotContain() Failure: Item found in set" + Environment.NewLine +
"Set: [\"Hi there\"]" + Environment.NewLine +
"Found: \"HI THERE\"",
ex.Message
);
}
#endif
}

public class DoesNotContain_Comparer
Expand Down
28 changes: 28 additions & 0 deletions test/test.xunit.assert/Utility/ReadOnlySet.cs
@@ -0,0 +1,28 @@
#if NET5_0_OR_GREATER

using System.Collections;
using System.Collections.Generic;

public class ReadOnlySet<T> : IReadOnlySet<T>
{
readonly HashSet<T> hashSet;

public ReadOnlySet(
IEqualityComparer<T> comparer,
params T[] items) =>
hashSet = new HashSet<T>(items, comparer);

public int Count => hashSet.Count;

public bool Contains(T item) => hashSet.Contains(item);
public IEnumerator<T> GetEnumerator() => hashSet.GetEnumerator();
public bool IsProperSubsetOf(IEnumerable<T> other) => hashSet.IsProperSubsetOf(other);
public bool IsProperSupersetOf(IEnumerable<T> other) => hashSet.IsProperSupersetOf(other);
public bool IsSubsetOf(IEnumerable<T> other) => hashSet.IsSubsetOf(other);
public bool IsSupersetOf(IEnumerable<T> other) => hashSet.IsSupersetOf(other);
public bool Overlaps(IEnumerable<T> other) => hashSet.Overlaps(other);
public bool SetEquals(IEnumerable<T> other) => hashSet.SetEquals(other);
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
}

#endif

0 comments on commit 13bb60b

Please sign in to comment.