Skip to content
Open
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 @@ -1010,25 +1010,48 @@ private static bool IsSubsetOf(IEnumerable<T> other, MutationInput origin)
return true;
}

// To determine whether everything we have is also in another sequence,
// we enumerate the sequence and "tag" whether it's in this collection,
// then consider whether every element in this collection was tagged.
// Since this collection is immutable we cannot directly tag. So instead
// we simply count how many "hits" we have and ensure it's equal to the
// size of this collection. Of course for this to work we need to ensure
// the uniqueness of items in the given sequence, so we create a set based
// on the sequence first.
switch (other)
{
case ImmutableHashSet<T> otherAsImmutableHashSet:
if (otherAsImmutableHashSet.Count < origin.Count)
{
return false;
}

if (EqualityComparer<IEqualityComparer<T>>.Default.Equals(origin.EqualityComparer, otherAsImmutableHashSet.KeyComparer))
{
return SetEqualsWithImmutableHashset(otherAsImmutableHashSet, origin);
}
break;

case HashSet<T> otherAsHashset:
if (otherAsHashset.Count < origin.Count)
{
return false;
}

if (EqualityComparer<IEqualityComparer<T>>.Default.Equals(origin.EqualityComparer, otherAsHashset.Comparer))
{
return SetEqualsWithHashset(otherAsHashset, origin);
}
break;

case ICollection<T> otherAsICollectionGeneric:
// We check for < instead of != because other is not guaranteed to be a set, it could be a collection with duplicates.
if (otherAsICollectionGeneric.Count < origin.Count)
{
return false;
}
break;
}

var otherSet = new HashSet<T>(other, origin.EqualityComparer);
int matches = 0;
foreach (T item in otherSet)
if (otherSet.Count < origin.Count)
{
if (Contains(item, origin))
{
matches++;
}
return false;
}

return matches == origin.Count;
return SetEqualsWithHashset(otherSet, origin);
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,106 @@ public void SetEqualsMismatchedComparersOtherIsLarger()
Assert.False(origin.SetEquals(other));
}

[Fact]
public void IsSubsetOfMismatchedComparersLargerCountMissingElement()
{
var origin = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "A");
var other = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "a", "b", "c", "d");

Assert.False(origin.IsSubsetOf(other));
}

[Fact]
public void IsSubsetOfICollectionLargeCountSmallUniqueSet()
{
var origin = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "b");
var other = new List<string> { "a", "b", "b", "b" };

Assert.True(origin.IsSubsetOf(other));
}

[Fact]
public void IsSubsetOfEmptyAgainstAnything()
{
var empty = ImmutableHashSet<string>.Empty;
var other = ImmutableHashSet.Create("any");

Assert.True(empty.IsSubsetOf(other));
Assert.True(empty.IsSubsetOf(new List<string>()));
}

[Fact]
public void IsSubsetOfSensitiveOriginInsensitiveOther()
{
var origin = ImmutableHashSet.Create(StringComparer.Ordinal, "a");
var other = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "A", "b");

Assert.False(origin.IsSubsetOf(other));
}

[Fact]
public void IsSubsetOfMismatchedLogicallyEqual()
{
var origin = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "a");
var other = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "A");

Assert.True(origin.IsSubsetOf(other));
}

[Fact]
public void IsSubsetOfInsensitiveOriginSensitiveOther()
{
var origin = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "a", "b");
var other = ImmutableHashSet.Create(StringComparer.Ordinal, "A", "B", "c");

Assert.True(origin.IsSubsetOf(other));
}

[Fact]
public void IsSubsetOfAgainstBCLHashSet()
{
var origin = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "b");
var other = new HashSet<string> { "a", "b", "c" };

Assert.True(origin.IsSubsetOf(other));
}

[Fact]
public void IsSubsetOfListWithDuplicates()
{
var origin = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "b", "c");
var other = new List<string> { "a", "b", "a", "b" };

Assert.False(origin.IsSubsetOf(other));
}

[Fact]
public void IsSubsetOfListWithDuplicatesAndCountSmaller()
{
var origin = ImmutableHashSet.Create("a", "b", "c");
var other = new List<string> { "a", "b" };

Assert.False(origin.IsSubsetOf(other));
}

[Fact]
public void IsSubsetOfOtherImmutableHashSetIsSmaller()
{
var origin = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "b", "c");
var other = ImmutableHashSet.Create(StringComparer.OrdinalIgnoreCase, "a", "b");

Assert.False(origin.IsSubsetOf(other));
}

[Fact]
public void IsSubsetOfOtherHashSetIsSmaller()
{
var origin = ImmutableHashSet.Create(StringComparer.Ordinal, "a", "b", "c");
var other = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "a", "b" };

Assert.False(origin.IsSubsetOf(other));
}

[Fact]
public void ChangeUnorderedEqualityComparer()
{
Expand Down
Loading