File: CollectionAssertsTests.cs
Web Access
Project: src\src\Microsoft.DotNet.XUnitAssert\tests\Microsoft.DotNet.XUnitAssert.Tests.csproj (Microsoft.DotNet.XUnitAssert.Tests)
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using Xunit;
using Xunit.Sdk;
 
#if XUNIT_VALUETASK
using System.Threading.Tasks;
#endif
 
public class CollectionAssertsTests
{
	public class All
	{
		[Fact]
		public static void NullCollectionThrows()
		{
			Assert.Throws<ArgumentNullException>(() => Assert.All<object>(null!, _ => { }));
		}
 
		[Fact]
		public static void NullActionThrows()
		{
			Assert.Throws<ArgumentNullException>(() => Assert.All(new object[0], (Action<object>)null!));
			Assert.Throws<ArgumentNullException>(() => Assert.All(new object[0], (Action<object, int>)null!));
		}
 
		[Fact]
		public static void ActionWhereSomeFail()
		{
			var items = new[] { 1, 1, 2, 2, 1, 1 };
 
			var ex = Assert.Throws<AllException>(() => Assert.All(items, x => Assert.Equal(1, x)));
 
			Assert.Equal(2, ex.Failures.Count);
			Assert.All(ex.Failures, x => Assert.IsType<EqualException>(x));
		}
 
		[Fact]
		public static void ActionWhereNoneFail()
		{
			var items = new[] { 1, 1, 1, 1, 1, 1 };
 
			var ex = Record.Exception(() => Assert.All(items, x => Assert.Equal(1, x)));
 
			Assert.Null(ex);
		}
 
		[Fact]
		public static void ActionWhereAllFail()
		{
			var items = new[] { 1, 1, 2, 2, 1, 1 };
 
			var ex = Assert.Throws<AllException>(() => Assert.All(items, x => Assert.Equal(0, x)));
 
			Assert.Equal(6, ex.Failures.Count);
			Assert.All(ex.Failures, x => Assert.IsType<EqualException>(x));
		}
 
		[Fact]
		public static void ActionCanReceiveIndex()
		{
			var items = new[] { 1, 1, 2, 2, 1, 1 };
			var indices = new List<int>();
 
			Assert.All(items, (x, idx) => indices.Add(idx));
 
			Assert.Equal(new[] { 0, 1, 2, 3, 4, 5 }, indices);
		}
 
		[Fact]
		public static void CollectionWithNullThrowsAllException()
		{
			var collection = new object?[]
			{
				new object(),
				null
			};
 
			var ex = Assert.Throws<AllException>(() => Assert.All(collection, Assert.NotNull));
			Assert.Contains("[1]: Item: ", ex.Message);
		}
	}
 
#if XUNIT_VALUETASK
	public class AllAsync
	{
		[Fact]
		public static async ValueTask NullCollectionThrows()
		{
			await Assert.ThrowsAsync<ArgumentNullException>(() => Assert.AllAsync<object>(null!, async _ => await Task.Yield()));
		}
 
		[Fact]
		public static async ValueTask NullActionThrows()
		{
			await Assert.ThrowsAsync<ArgumentNullException>(() => Assert.AllAsync(new object[0], (Func<object, ValueTask>)null!));
			await Assert.ThrowsAsync<ArgumentNullException>(() => Assert.AllAsync(new object[0], (Func<object, int, ValueTask>)null!));
		}
 
		[Fact]
		public static async ValueTask ActionWhereSomeFail()
		{
			var items = new[] { 1, 1, 2, 2, 1, 1 };
 
			var ex = await Assert.ThrowsAsync<AllException>(() => Assert.AllAsync(items, async x =>
			{
				await Task.Yield();
				Assert.Equal(1, x);
			}));
 
			Assert.Equal(2, ex.Failures.Count);
			Assert.All(ex.Failures, x => Assert.IsType<EqualException>(x));
		}
 
		[Fact]
		public static async ValueTask ActionWhereNoneFail()
		{
			var items = new[] { 1, 1, 1, 1, 1, 1 };
 
			var ex = await Record.ExceptionAsync(() => Assert.AllAsync(items, async x =>
			{
				await Task.Yield();
				Assert.Equal(1, x);
			}));
 
			Assert.Null(ex);
		}
 
		[Fact]
		public static async ValueTask ActionWhereAllFail()
		{
			var items = new[] { 1, 1, 2, 2, 1, 1 };
 
			var ex = await Assert.ThrowsAsync<AllException>(() => Assert.AllAsync(items, async x =>
			{
				await Task.Yield();
				Assert.Equal(0, x);
			}));
 
			Assert.Equal(6, ex.Failures.Count);
			Assert.All(ex.Failures, x => Assert.IsType<EqualException>(x));
		}
 
		[Fact]
		public static async ValueTask ActionCanReceiveIndex()
		{
			var items = new[] { 1, 1, 2, 2, 1, 1 };
			var indices = new List<int>();
 
			await Assert.AllAsync(items, async (x, idx) =>
			{
				await Task.Yield();
				indices.Add(idx);
			});
 
			Assert.Equal(new[] { 0, 1, 2, 3, 4, 5 }, indices);
		}
 
		[Fact]
		public static async ValueTask CollectionWithNullThrowsAllException()
		{
			var collection = new object?[]
			{
				new object(),
				null
			};
 
			var ex = await Assert.ThrowsAsync<AllException>(() => Assert.AllAsync(collection, async x =>
			{
				await Task.Yield();
				Assert.NotNull(x);
			}));
			Assert.Contains("[1]: Item: ", ex.Message);
		}
	}
#endif
 
	public class Collection
	{
		[Fact]
		public static void EmptyCollection()
		{
			var list = new List<int>();
 
			Assert.Collection(list);
		}
 
		[Fact]
		public static void MismatchedElementCount()
		{
			var list = new List<int>();
 
			var ex = Record.Exception(
				() => Assert.Collection(list,
					item => Assert.True(false)
				)
			);
 
			var collEx = Assert.IsType<CollectionException>(ex);
			Assert.Equal(1, collEx.ExpectedCount);
			Assert.Equal(0, collEx.ActualCount);
			Assert.Equal(
				"Assert.Collection() Failure" + Environment.NewLine +
				"Collection: []" + Environment.NewLine +
				"Expected item count: 1" + Environment.NewLine +
				"Actual item count:   0",
				collEx.Message
			);
			Assert.Null(collEx.InnerException);
		}
 
		[Fact]
		public static void NonEmptyCollection()
		{
			var list = new List<int> { 42, 2112 };
 
			Assert.Collection(list,
				item => Assert.Equal(42, item),
				item => Assert.Equal(2112, item)
			);
		}
 
		[Fact]
		public static void MismatchedElement()
		{
			var list = new List<int> { 42, 2112 };
 
			var ex = Record.Exception(() =>
				Assert.Collection(list,
					item => Assert.Equal(42, item),
					item => Assert.Equal(2113, item)
				)
			);
 
			var collEx = Assert.IsType<CollectionException>(ex);
			Assert.Equal(1, collEx.IndexFailurePoint);
			Assert.Equal(
				"Assert.Collection() Failure" + Environment.NewLine +
				"Collection: [42, 2112]" + Environment.NewLine +
				"Error during comparison of item at index 1" + Environment.NewLine +
				"Inner exception: Assert.Equal() Failure" + Environment.NewLine +
				"        Expected: 2113" + Environment.NewLine +
				"        Actual:   2112",
				ex.Message
			);
		}
	}
 
#if XUNIT_VALUETASK
	public class CollectionAsync
	{
		[Fact]
		public static async ValueTask EmptyCollection()
		{
			var list = new List<int>();
 
			await Assert.CollectionAsync(list);
		}
 
		[Fact]
		public static async ValueTask MismatchedElementCountAsync()
		{
			var list = new List<int>();
 
			var ex = await Record.ExceptionAsync(
				() => Assert.CollectionAsync(list,
					async item => await Task.Yield()
				)
			);
 
			var collEx = Assert.IsType<CollectionException>(ex);
			Assert.Equal(1, collEx.ExpectedCount);
			Assert.Equal(0, collEx.ActualCount);
			Assert.Equal(
				"Assert.Collection() Failure" + Environment.NewLine +
				"Collection: []" + Environment.NewLine +
				"Expected item count: 1" + Environment.NewLine +
				"Actual item count:   0",
				collEx.Message
			);
			Assert.Null(collEx.InnerException);
		}
 
		[Fact]
		public static async ValueTask NonEmptyCollectionAsync()
		{
			var list = new List<int> { 42, 2112 };
 
			await Assert.CollectionAsync(list,
				async item =>
				{
					await Task.Yield();
					Assert.Equal(42, item);
				},
				async item =>
				{
					await Task.Yield();
					Assert.Equal(2112, item);
				}
			);
		}
 
		[Fact]
		public static async ValueTask MismatchedElementAsync()
		{
			var list = new List<int> { 42, 2112 };
 
			var ex = await Record.ExceptionAsync(() =>
				 Assert.CollectionAsync(list,
				 async item =>
				 {
					 await Task.Yield();
					 Assert.Equal(42, item);
				 },
				 async item =>
				 {
					 await Task.Yield();
					 Assert.Equal(2113, item);
				 }
				 )
			);
 
			var collEx = Assert.IsType<CollectionException>(ex);
			Assert.Equal(1, collEx.IndexFailurePoint);
			Assert.Equal(
				"Assert.Collection() Failure" + Environment.NewLine +
				"Collection: [42, 2112]" + Environment.NewLine +
				"Error during comparison of item at index 1" + Environment.NewLine +
				"Inner exception: Assert.Equal() Failure" + Environment.NewLine +
				"        Expected: 2113" + Environment.NewLine +
				"        Actual:   2112",
				ex.Message
			);
		}
	}
#endif
 
	public class Contains
	{
		[Fact]
		public static void GuardClause()
		{
			Assert.Throws<ArgumentNullException>("collection", () => Assert.Contains(14, (ICollection<int>)null!));
		}
 
		[Fact]
		public static void CanFindNullInContainer()
		{
			var list = new List<object?> { 16, null, "Hi there" };
 
			Assert.Contains(null, list);
		}
 
		[Fact]
		public static void ItemInContainer()
		{
			var list = new List<int> { 42 };
 
			Assert.Contains(42, list);
		}
 
		[Fact]
		public static void ItemNotInContainer()
		{
			var list = new List<int> { 41, 43 };
 
			var ex = Assert.Throws<ContainsException>(() => Assert.Contains(42, list));
 
			Assert.Equal(
				"Assert.Contains() Failure" + Environment.NewLine +
				"Not found: 42" + Environment.NewLine +
				"In value:  List<Int32> [41, 43]",
				ex.Message
			);
		}
 
		[Fact]
		public static void NullsAllowedInContainer()
		{
			var list = new List<object?> { null, 16, "Hi there" };
 
			Assert.Contains("Hi there", list);
		}
 
		[Fact]
		public static void ICollectionContainsIsTrueButContainsWithDefaultComparerIsFalse()
		{
			var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Hi there" };
 
			// ICollection<T>.Contains is called if the container implements ICollection<T>.
			// If either ICollection<T>.Contains or the default equality comparer report that
			// the collection has the item, the assert should pass.
			Assert.Contains("HI THERE", set);
		}
 
		[Fact]
		public static void ICollectionContainsIsFalseButContainsWithDefaultComparerIsTrue()
		{
			var collections = new[]
			{
				new[] { 1, 2, 3, 4 }
			};
 
			// ICollection<T>.Contains is called if the container implements ICollection<T>.
			// If either ICollection<T>.Contains or the default equality comparer report that
			// the collection has the item, the assert should pass.
			Assert.Contains(new[] { 1, 2, 3, 4 }, collections);
		}
 
		[Fact]
		public static void KeyInDictionary()
		{
			IDictionary<string, int> dictionary = new Dictionary<string, int>
			{
				["forty-two"] = 42
			};
 
			var actual = Assert.Contains("forty-two", dictionary);
			Assert.Equal(42, actual);
		}
 
		[Fact]
		public static void KeyNotInDictionary()
		{
			IDictionary<string, int> dictionary = new Dictionary<string, int>
			{
				["eleventeen"] = 110
			};
 
			var actual = Record.Exception(() => Assert.Contains("forty-two", dictionary));
 
			var ex = Assert.IsType<ContainsException>(actual);
			Assert.Equal(
				"Assert.Contains() Failure" + Environment.NewLine +
				"Not found: forty-two" + Environment.NewLine +
				@"In value:  KeyCollection<String, Int32> [""eleventeen""]",
				ex.Message
			);
		}
 
		[Fact]
		public static void KeyInReadOnlyDictionary()
		{
			IReadOnlyDictionary<string, int> dictionary = new Dictionary<string, int>
			{
				["forty-two"] = 42
			};
 
			var actual = Assert.Contains("forty-two", dictionary);
			Assert.Equal(42, actual);
		}
 
		[Fact]
		public static void KeyNotInReadOnlyDictionary()
		{
			IReadOnlyDictionary<string, int> dictionary = new Dictionary<string, int>
			{
				["eleventeen"] = 110
			};
 
			var actual = Record.Exception(() => Assert.Contains("forty-two", dictionary));
 
			var ex = Assert.IsType<ContainsException>(actual);
			Assert.Equal(
				"Assert.Contains() Failure" + Environment.NewLine +
				"Not found: forty-two" + Environment.NewLine +
				@"In value:  KeyCollection<String, Int32> [""eleventeen""]",
				ex.Message
			);
		}
	}
 
	public class Contains_WithComparer
	{
		[Fact]
		public static void CanUseComparer()
		{
			var list = new List<int> { 42 };
 
			Assert.Contains(43, list, new MyComparer());
		}
 
		[Fact]
		public static void DoesNotTryToCallICollectionContains()
		{
			var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Hi there" };
 
			// ICollection<T>.Contains would return true, but we're passing in a custom comparer to Assert.Contains
			// (and ICollection<T>.Contains does not accept a comparer) so we should not attempt to use that result.
			var ex = Assert.Throws<ContainsException>(() => Assert.Contains("HI THERE", set, StringComparer.Ordinal));
 
			Assert.Equal(
				"Assert.Contains() Failure" + Environment.NewLine +
				"Not found: HI THERE" + Environment.NewLine +
				@"In value:  HashSet<String> [""Hi there""]",
				ex.Message
			);
		}
 
		class MyComparer : IEqualityComparer<int>
		{
			public bool Equals(int x, int y) => true;
 
			public int GetHashCode(int obj) => throw new NotImplementedException();
		}
	}
 
	public class Contains_WithPredicate
	{
		[Fact]
		public static void GuardClauses()
		{
			Assert.Throws<ArgumentNullException>("collection", () => Assert.Contains<int>(null!, item => true));
			Assert.Throws<ArgumentNullException>("filter", () => Assert.Contains(new int[0], (Predicate<int>)null!));
		}
 
		[Fact]
		public static void ItemFound_DoesNotThrow()
		{
			var list = new[] { "Hello", "world" };
 
			Assert.Contains(list, item => item.StartsWith("w"));
		}
 
		[Fact]
		public static void ItemNotFound_Throws()
		{
			var list = new[] { "Hello", "world" };
 
			Assert.Throws<ContainsException>(() => Assert.Contains(list, item => item.StartsWith("q")));
		}
	}
 
	public class Distinct
	{
		[Fact]
		public static void GuardClauses()
		{
			Assert.Throws<ArgumentNullException>("collection", () => Assert.Distinct<int>(null!));
			Assert.Throws<ArgumentNullException>("comparer", () => Assert.Distinct(new object[0], null!));
		}
 
		[Fact]
		public static void WithNull()
		{
			var list = new List<object?> { 16, "Hi there", null };
 
			Assert.Distinct(list);
		}
 
		[Fact]
		public static void TwoItems()
		{
			var list = new List<int> { 42, 42 };
 
			var ex = Assert.Throws<ContainsDuplicateException>(() => Assert.Distinct(list));
 
			Assert.Equal(
				"Assert.Distinct() Failure: The item 42 occurs multiple times in [42, 42].",
				ex.Message
			);
		}
 
		[Fact]
		public static void TwoNulls()
		{
			var list = new List<string?> { "a", null, "b", null };
 
			var ex = Assert.Throws<ContainsDuplicateException>(() => Assert.Distinct(list));
 
			Assert.Equal(
				"Assert.Distinct() Failure: The item null occurs multiple times in [\"a\", null, \"b\", null].",
				ex.Message
			);
		}
 
		[Fact]
		public static void CaseSensitiveStrings()
		{
			var list = new string[] { "a", "b", "A" };
 
			Assert.Distinct(list);
			Assert.Distinct(list, StringComparer.Ordinal);
		}
 
		[Fact]
		public static void CaseInsensitiveStrings()
		{
			var list = new string[] { "a", "b", "A" };
 
			var ex = Assert.Throws<ContainsDuplicateException>(() => Assert.Distinct(list, StringComparer.OrdinalIgnoreCase));
 
			Assert.Equal(
				"Assert.Distinct() Failure: The item \"A\" occurs multiple times in [\"a\", \"b\", \"A\"].",
				ex.Message
			);
		}
	}
 
	public class DoesNotContain
	{
		[Fact]
		public static void GuardClause()
		{
			Assert.Throws<ArgumentNullException>("collection", () => Assert.DoesNotContain(14, (ICollection<int>)null!));
		}
 
		[Fact]
		public static void CanSearchForNullInContainer()
		{
			var list = new List<object?> { 16, "Hi there" };
 
			Assert.DoesNotContain(null, list);
		}
 
		[Fact]
		public static void ItemInContainer()
		{
			var list = new List<int> { 42 };
 
			DoesNotContainException ex =
				Assert.Throws<DoesNotContainException>(() => Assert.DoesNotContain(42, list));
 
			Assert.Equal(
				"Assert.DoesNotContain() Failure" + Environment.NewLine +
				"Found:    42" + Environment.NewLine +
				"In value: List<Int32> [42]",
				ex.Message
			);
		}
 
		[Fact]
		public static void ItemNotInContainer()
		{
			var list = new List<int>();
 
			Assert.DoesNotContain(42, list);
		}
 
		[Fact]
		public static void NullsAllowedInContainer()
		{
			var list = new List<object?> { null, 16, "Hi there" };
 
			Assert.DoesNotContain(42, list);
		}
 
		[Fact]
		public static void ICollectionContainsIsTrueButContainsWithDefaultComparerIsFalse()
		{
			var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Hi there" };
 
			// ICollection<T>.Contains is called if the container implements ICollection<T>.
			// If either ICollection<T>.Contains or the default equality comparer report that
			// the collection has the item, the assert should fail.
			var ex = Assert.Throws<DoesNotContainException>(() => Assert.DoesNotContain("HI THERE", set));
 
			Assert.Equal(
				"Assert.DoesNotContain() Failure" + Environment.NewLine +
				"Found:    HI THERE" + Environment.NewLine +
				@"In value: HashSet<String> [""Hi there""]",
				ex.Message
			);
		}
 
		[Fact]
		public static void ICollectionContainsIsFalseButContainsWithDefaultComparerIsTrue()
		{
			var collections = new[]
			{
				new[] { 1, 2, 3, 4 }
			};
 
			// ICollection<T>.Contains is called if the container implements ICollection<T>.
			// If either ICollection<T>.Contains or the default equality comparer report that
			// the collection has the item, the assert should fail.
			var ex = Assert.Throws<DoesNotContainException>(() => Assert.DoesNotContain(new[] { 1, 2, 3, 4 }, collections));
 
			Assert.Equal(
				"Assert.DoesNotContain() Failure" + Environment.NewLine +
				"Found:    Int32[] [1, 2, 3, 4]" + Environment.NewLine +
				"In value: Int32[][] [[1, 2, 3, 4]]",
				ex.Message
			);
		}
 
		[Fact]
		public static void KeyNotInDictionary()
		{
			var dictionary = (IDictionary<string, int>)new Dictionary<string, int>
			{
				["eleventeen"] = 110
			};
 
			var actual = Record.Exception(() => Assert.DoesNotContain("forty-two", dictionary));
 
			Assert.Null(actual);
		}
 
		[Fact]
		public static void KeyInDictionary()
		{
			var dictionary = (IDictionary<string, int>)new Dictionary<string, int>
			{
				["forty-two"] = 42
			};
 
			var actual = Record.Exception(() => Assert.DoesNotContain("forty-two", dictionary));
 
			var ex = Assert.IsType<DoesNotContainException>(actual);
			Assert.Equal(
				"Assert.DoesNotContain() Failure" + Environment.NewLine +
				"Found:    forty-two" + Environment.NewLine +
				@"In value: KeyCollection<String, Int32> [""forty-two""]",
				ex.Message
			);
		}
 
		[Fact]
		public static void KeyNotInReadOnlyDictionary()
		{
			var dictionary = (IReadOnlyDictionary<string, int>)new Dictionary<string, int>
			{
				["eleventeen"] = 110
			};
 
			var actual = Record.Exception(() => Assert.DoesNotContain("forty-two", dictionary));
 
			Assert.Null(actual);
		}
 
		[Fact]
		public static void KeyInReadOnlyDictionary()
		{
			var dictionary = (IReadOnlyDictionary<string, int>)new Dictionary<string, int>
			{
				["forty-two"] = 42
			};
 
			var actual = Record.Exception(() => Assert.DoesNotContain("forty-two", dictionary));
 
			var ex = Assert.IsType<DoesNotContainException>(actual);
			Assert.Equal(
				"Assert.DoesNotContain() Failure" + Environment.NewLine +
				"Found:    forty-two" + Environment.NewLine +
				@"In value: KeyCollection<String, Int32> [""forty-two""]",
				ex.Message
			);
		}
	}
 
	public class DoesNotContain_WithComparer
	{
		[Fact]
		public static void CanUseComparer()
		{
			var list = new List<int> { 42 };
 
			Assert.DoesNotContain(42, list, new MyComparer());
		}
 
		[Fact]
		public static void DoesNotTryToCallICollectionContains()
		{
			var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "Hi there" };
 
			// ICollection<T>.Contains would return true, but we're passing in a custom comparer to Assert.DoesNotContain
			// (and ICollection<T>.Contains does not accept a comparer) so we should not attempt to use that result.
			Assert.DoesNotContain("HI THERE", set, StringComparer.Ordinal);
		}
 
		class MyComparer : IEqualityComparer<int>
		{
			public bool Equals(int x, int y) => false;
 
			public int GetHashCode(int obj) => throw new NotImplementedException();
		}
	}
 
	public class DoesNotContain_WithPredicate
	{
		[Fact]
		public static void GuardClauses()
		{
			Assert.Throws<ArgumentNullException>("collection", () => Assert.DoesNotContain((List<int>)null!, item => true));
			Assert.Throws<ArgumentNullException>("filter", () => Assert.DoesNotContain(new int[0], (Predicate<int>)null!));
		}
 
		[Fact]
		public static void ItemFound_Throws()
		{
			var list = new[] { "Hello", "world" };
 
			Assert.Throws<DoesNotContainException>(() => Assert.DoesNotContain(list, item => item.StartsWith("w")));
		}
 
		[Fact]
		public static void ItemNotFound_DoesNotThrow()
		{
			var list = new[] { "Hello", "world" };
 
			Assert.DoesNotContain(list, item => item.StartsWith("q"));
		}
	}
 
	public class Empty
	{
		[Fact]
		public static void GuardClauses()
		{
			Assert.Throws<ArgumentNullException>(() => Assert.Empty(null!));
		}
 
		[Fact]
		public static void EmptyContainer()
		{
			var list = new List<int>();
 
			Assert.Empty(list);
		}
 
		[Fact]
		public static void NonEmptyContainerThrows()
		{
			var list = new List<int> { 42 };
 
			EmptyException ex = Assert.Throws<EmptyException>(() => Assert.Empty(list));
 
			Assert.Equal($"Assert.Empty() Failure{Environment.NewLine}Expected: <empty>{Environment.NewLine}Actual:   [42]", ex.Message);
		}
 
		[Fact]
		public static void EnumeratorDisposed()
		{
			var enumerator = new SpyEnumerator<int>(Enumerable.Empty<int>());
 
			Assert.Empty(enumerator);
 
			Assert.True(enumerator.IsDisposed);
		}
 
		[Fact]
		public static void EmptyString()
		{
			Assert.Empty("");
		}
 
		[Fact]
		public static void NonEmptyStringThrows()
		{
			EmptyException ex = Assert.Throws<EmptyException>(() => Assert.Empty("Foo"));
 
			Assert.Equal($"Assert.Empty() Failure{Environment.NewLine}Expected: <empty>{Environment.NewLine}Actual:   \"Foo\"", ex.Message);
		}
	}
 
	public class Equal
	{
		[Fact]
		public static void Array()
		{
			string[] expected = { "@", "a", "ab", "b" };
			string[] actual = { "@", "a", "ab", "b" };
 
			Assert.Equal(expected, actual);
			Assert.Throws<NotEqualException>(() => Assert.NotEqual(expected, actual));
		}
 
		[Fact]
		public static void ArrayInsideArray()
		{
			string[][] expected = { new[] { "@", "a" }, new[] { "ab", "b" } };
			string[][] actual = { new[] { "@", "a" }, new[] { "ab", "b" } };
 
			Assert.Equal(expected, actual);
			Assert.Throws<NotEqualException>(() => Assert.NotEqual(expected, actual));
		}
 
		[Fact]
		public static void ArraysOfDifferentLengthsAreNotEqual()
		{
			string[] expected = { "@", "a", "ab", "b", "c" };
			string[] actual = { "@", "a", "ab", "b" };
 
			Assert.Throws<EqualException>(() => Assert.Equal(expected, actual));
			Assert.NotEqual(expected, actual);
		}
 
		[Fact]
		public static void ArrayValuesAreDifferentNotEqual()
		{
			string[] expected = { "@", "d", "v", "d" };
			string[] actual = { "@", "a", "ab", "b" };
 
			Assert.Throws<EqualException>(() => Assert.Equal(expected, actual));
			Assert.NotEqual(expected, actual);
		}
 
		[Fact]
		public static void Equivalence()
		{
			var expected = new[] { 1, 2, 3, 4, 5 };
			var actual = new List<int>(expected);
 
			Assert.Equal(expected, actual);
		}
 
		[Fact]
		public static void EnumeratesOnlyOnce()
		{
			var expected = new[] { 1, 2, 3, 4, 5 };
			var actual = new RunOnceEnumerable<int>(expected);
			Assert.Equal(expected, actual);
		}
	}
 
	public class EqualDictionary
	{
		[Fact]
		public static void InOrderDictionary()
		{
			var expected = new Dictionary<string, int> { { "a", 1 }, { "b", 2 }, { "c", 3 } };
			var actual = new Dictionary<string, int> { { "a", 1 }, { "b", 2 }, { "c", 3 } };
 
			Assert.Equal(expected, actual);
			Assert.Throws<NotEqualException>(() => Assert.NotEqual(expected, actual));
		}
 
		[Fact]
		public static void OutOfOrderDictionary()
		{
			var expected = new Dictionary<string, int> { { "a", 1 }, { "b", 2 }, { "c", 3 } };
			var actual = new Dictionary<string, int> { { "b", 2 }, { "c", 3 }, { "a", 1 } };
 
			Assert.Equal(expected, actual);
			Assert.Throws<NotEqualException>(() => Assert.NotEqual(expected, actual));
		}
 
		[Fact]
		public static void ExpectedLarger()
		{
			var expected = new Dictionary<string, int> { { "a", 1 }, { "b", 2 }, { "c", 3 } };
			var actual = new Dictionary<string, int> { { "a", 1 }, { "b", 2 } };
 
			Assert.NotEqual(expected, actual);
			Assert.Throws<EqualException>(() => Assert.Equal(expected, actual));
		}
 
		[Fact]
		public static void ActualLarger()
		{
			var expected = new Dictionary<string, int> { { "a", 1 }, { "b", 2 } };
			var actual = new Dictionary<string, int> { { "a", 1 }, { "b", 2 }, { "c", 3 } };
 
			Assert.NotEqual(expected, actual);
			Assert.Throws<EqualException>(() => Assert.Equal(expected, actual));
		}
 
		[Fact]
		public static void SomeKeysDiffer()
		{
			var expected = new Dictionary<string, int>
			{
				["a"] = 1,
				["be"] = 2,
				["c"] = 3,
				["d"] = 4,
				["e"] = 5,
				["f"] = 6,
			};
			var actual = new Dictionary<string, int>
			{
				["a"] = 1,
				["ba"] = 2,
				["c"] = 3,
				["d"] = 4,
				["e"] = 5,
				["f"] = 6,
			};
 
			Assert.NotEqual(expected, actual);
			var ex = Assert.Throws<EqualException>(() => Assert.Equal(expected, actual));
			Assert.Equal(
				"Assert.Equal() Failure" + Environment.NewLine +
				"Expected: Dictionary<String, Int32> [[\"a\"] = 1, [\"be\"] = 2, [\"c\"] = 3, [\"d\"] = 4, [\"e\"] = 5, ...]" + Environment.NewLine +
				"Actual:   Dictionary<String, Int32> [[\"a\"] = 1, [\"ba\"] = 2, [\"c\"] = 3, [\"d\"] = 4, [\"e\"] = 5, ...]",
				ex.Message
			);
		}
	}
 
	public class EqualSet
	{
		[Fact]
		public static void InOrderSet()
		{
			var expected = new HashSet<int> { 1, 2, 3 };
			var actual = new HashSet<int> { 1, 2, 3 };
 
			Assert.Equal(expected, actual);
			Assert.Throws<NotEqualException>(() => Assert.NotEqual(expected, actual));
		}
 
		[Fact]
		public static void OutOfOrderSet()
		{
			var expected = new HashSet<int> { 1, 2, 3 };
			var actual = new HashSet<int> { 2, 3, 1 };
 
			Assert.Equal(expected, actual);
			Assert.Throws<NotEqualException>(() => Assert.NotEqual(expected, actual));
		}
 
		[Fact]
		public static void ExpectedLarger()
		{
			var expected = new HashSet<int> { 1, 2, 3 };
			var actual = new HashSet<int> { 1, 2 };
 
			Assert.NotEqual(expected, actual);
			Assert.Throws<EqualException>(() => Assert.Equal(expected, actual));
		}
 
		[Fact]
		public static void ActualLarger()
		{
			var expected = new HashSet<int> { 1, 2 };
			var actual = new HashSet<int> { 1, 2, 3 };
 
			Assert.NotEqual(expected, actual);
			Assert.Throws<EqualException>(() => Assert.Equal(expected, actual));
		}
	}
 
	public class Equal_WithComparer
	{
		[Fact]
		public static void EquivalenceWithComparer()
		{
			var expected = new[] { 1, 2, 3, 4, 5 };
			var actual = new List<int>(new int[] { 0, 0, 0, 0, 0 });
 
			Assert.Equal(expected, actual, new IntComparer(true));
		}
 
		class IntComparer : IEqualityComparer<int>
		{
			readonly bool answer;
 
			public IntComparer(bool answer)
			{
				this.answer = answer;
			}
 
			public bool Equals(int x, int y) => answer;
 
			public int GetHashCode(int obj) => throw new NotImplementedException();
		}
	}
 
	public class NotEmpty
	{
		[Fact]
		public static void EmptyContainer()
		{
			var list = new List<int>();
 
			var ex = Assert.Throws<NotEmptyException>(() => Assert.NotEmpty(list));
 
			Assert.Equal("Assert.NotEmpty() Failure", ex.Message);
		}
 
		[Fact]
		public static void NonEmptyContainer()
		{
			var list = new List<int> { 42 };
 
			Assert.NotEmpty(list);
		}
 
		[Fact]
		public static void EnumeratorDisposed()
		{
			var enumerator = new SpyEnumerator<int>(Enumerable.Range(0, 1));
 
			Assert.NotEmpty(enumerator);
 
			Assert.True(enumerator.IsDisposed);
		}
	}
 
	public class NotEqual
	{
		[Fact]
		public static void EnumerableInequivalence()
		{
			var expected = new[] { 1, 2, 3, 4, 5 };
			var actual = new List<int>(new[] { 1, 2, 3, 4, 6 });
 
			Assert.NotEqual(expected, actual);
		}
 
		[Fact]
		public static void EnumerableEquivalence()
		{
			var expected = new[] { 1, 2, 3, 4, 5 };
			var actual = new List<int>(expected);
 
			Assert.Throws<NotEqualException>(() => Assert.NotEqual(expected, actual));
		}
	}
 
	public class NotEqual_WithComparer
	{
		[Fact]
		public static void EnumerableInequivalenceWithFailedComparer()
		{
			var expected = new[] { 1, 2, 3, 4, 5 };
			var actual = new List<int>(new int[] { 1, 2, 3, 4, 5 });
 
			Assert.NotEqual(expected, actual, new IntComparer(false));
		}
 
		[Fact]
		public static void EnumerableEquivalenceWithSuccessfulComparer()
		{
			var expected = new[] { 1, 2, 3, 4, 5 };
			var actual = new List<int>(new int[] { 0, 0, 0, 0, 0 });
 
			Assert.Throws<NotEqualException>(() => Assert.NotEqual(expected, actual, new IntComparer(true)));
		}
 
		class IntComparer : IEqualityComparer<int>
		{
			readonly bool answer;
 
			public IntComparer(bool answer)
			{
				this.answer = answer;
			}
 
			public bool Equals(int x, int y) => answer;
 
			public int GetHashCode(int obj) => throw new NotImplementedException();
		}
	}
 
	public class Single_NonGeneric
	{
		[Fact]
		public static void NullCollectionThrows()
		{
			Assert.Throws<ArgumentNullException>(() => Assert.Single((IEnumerable)null!));
			Assert.Throws<ArgumentNullException>(() => Assert.Single((IEnumerable<object>)null!));
		}
 
		[Fact]
		public static void EmptyCollectionThrows()
		{
			var collection = new ArrayList();
 
			var ex = Record.Exception(() => Assert.Single(collection));
 
			Assert.IsType<SingleException>(ex);
			Assert.Equal("The collection was expected to contain a single element, but it was empty.", ex.Message);
		}
 
		[Fact]
		public static void MultiItemCollectionThrows()
		{
			var collection = new ArrayList { "Hello", "World" };
 
			var ex = Record.Exception(() => Assert.Single(collection));
 
			Assert.IsType<SingleException>(ex);
			Assert.Equal("The collection was expected to contain a single element, but it contained 2 elements.", ex.Message);
		}
 
		[Fact]
		public static void SingleItemCollectionDoesNotThrow()
		{
			var collection = new ArrayList { "Hello" };
 
			var ex = Record.Exception(() => Assert.Single(collection));
 
			Assert.Null(ex);
		}
 
		[Fact]
		public static void SingleItemCollectionReturnsTheItem()
		{
			var collection = new ArrayList { "Hello" };
 
			var result = Assert.Single(collection);
 
			Assert.Equal("Hello", result);
		}
	}
 
	public class Single_NonGeneric_WithObject
	{
		[Fact]
		public static void NullCollectionThrows()
		{
			Assert.Throws<ArgumentNullException>(() => Assert.Single(null!, null));
		}
 
		[Fact]
		public static void ObjectSingleMatch()
		{
			IEnumerable collection = new[] { "Hello", "World!" };
 
			Assert.Single(collection, "Hello");
		}
 
		[Fact]
		public static void NullSingleMatch()
		{
			IEnumerable collection = new[] { "Hello", "World!", null };
 
			Assert.Single(collection, null);
		}
 
		[Fact]
		public static void ObjectNoMatch()
		{
			IEnumerable collection = new[] { "Hello", "World!" };
 
			var ex = Record.Exception(() => Assert.Single(collection, "foo"));
 
			Assert.IsType<SingleException>(ex);
			Assert.Equal("The collection was expected to contain a single element matching \"foo\", but it contained no matching elements.", ex.Message);
		}
 
		[Fact]
		public static void PredicateTooManyMatches()
		{
			var collection = new[] { "Hello", "World!", "Hello" };
 
			var ex = Record.Exception(() => Assert.Single(collection, "Hello"));
 
			Assert.IsType<SingleException>(ex);
			Assert.Equal("The collection was expected to contain a single element matching \"Hello\", but it contained 2 matching elements.", ex.Message);
		}
	}
 
	public class Single_Generic
	{
		[Fact]
		public static void NullCollectionThrows()
		{
			Assert.Throws<ArgumentNullException>(() => Assert.Single<object>(null!));
		}
 
		[Fact]
		public static void EmptyCollectionThrows()
		{
			var collection = new object[0];
 
			var ex = Record.Exception(() => Assert.Single(collection));
 
			Assert.IsType<SingleException>(ex);
			Assert.Equal("The collection was expected to contain a single element, but it was empty.", ex.Message);
		}
 
		[Fact]
		public static void MultiItemCollectionThrows()
		{
			var collection = new[] { "Hello", "World!" };
 
			var ex = Record.Exception(() => Assert.Single(collection));
 
			Assert.IsType<SingleException>(ex);
			Assert.Equal("The collection was expected to contain a single element, but it contained 2 elements.", ex.Message);
		}
 
		[Fact]
		public static void SingleItemCollectionDoesNotThrow()
		{
			var collection = new[] { "Hello" };
 
			var ex = Record.Exception(() => Assert.Single(collection));
 
			Assert.Null(ex);
		}
 
		[Fact]
		public static void SingleItemCollectionReturnsTheItem()
		{
			var collection = new[] { "Hello" };
 
			var result = Assert.Single(collection);
 
			Assert.Equal("Hello", result);
		}
	}
 
	public class Single_Generic_WithPredicate
	{
		[Fact]
		public static void GuardClauses()
		{
			Assert.Throws<ArgumentNullException>(() => Assert.Single<object>(null!, _ => true));
			Assert.Throws<ArgumentNullException>(() => Assert.Single<object>(new object[0], null!));
		}
 
		[Fact]
		public static void PredicateSingleMatch()
		{
			var collection = new[] { "Hello", "World!" };
 
			var result = Assert.Single(collection, item => item.StartsWith("H"));
 
			Assert.Equal("Hello", result);
		}
 
		[Fact]
		public static void PredicateNoMatch()
		{
			var collection = new[] { "Hello", "World!" };
 
			var ex = Record.Exception(() => Assert.Single(collection, item => false));
 
			Assert.IsType<SingleException>(ex);
			Assert.Equal("The collection was expected to contain a single element matching (filter expression), but it contained no matching elements.", ex.Message);
		}
 
		[Fact]
		public static void PredicateTooManyMatches()
		{
			var collection = new[] { "Hello", "World!" };
 
			var ex = Record.Exception(() => Assert.Single(collection, item => true));
 
			Assert.IsType<SingleException>(ex);
			Assert.Equal("The collection was expected to contain a single element matching (filter expression), but it contained 2 matching elements.", ex.Message);
		}
	}
 
	sealed class RunOnceEnumerable<T> : IEnumerable<T>
	{
		private readonly IEnumerable<T> _source;
		private bool _called;
 
		public RunOnceEnumerable(IEnumerable<T> source)
		{
			_source = source;
		}
 
		public IEnumerator<T> GetEnumerator()
		{
			Assert.False(_called, "GetEnumerator() was called more than once");
			_called = true;
			return _source.GetEnumerator();
		}
 
		IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
	}
 
	sealed class SpyEnumerator<T> : IEnumerable<T>, IEnumerator<T>
	{
		IEnumerator<T>? innerEnumerator;
 
		public SpyEnumerator(IEnumerable<T> enumerable)
		{
			innerEnumerator = enumerable.GetEnumerator();
		}
 
		public T Current =>
			GuardNotNull("Tried to get Current on a disposed enumerator", innerEnumerator).Current;
 
		object? IEnumerator.Current =>
			GuardNotNull("Tried to get Current on a disposed enumerator", innerEnumerator).Current;
 
		public bool IsDisposed => innerEnumerator == null;
 
		public IEnumerator<T> GetEnumerator() => this;
 
		IEnumerator IEnumerable.GetEnumerator() => this;
 
		public bool MoveNext() =>
			GuardNotNull("Tried to call MoveNext() on a disposed enumerator", innerEnumerator).MoveNext();
 
		public void Reset() => throw new NotImplementedException();
 
		public void Dispose()
		{
			innerEnumerator?.Dispose();
			innerEnumerator = null;
		}
 
		/// <summary/>
		static T2 GuardNotNull<T2>(
			string message,
			[NotNull] T2? value)
				where T2 : class
		{
			if (value == null)
				throw new InvalidOperationException(message);
 
			return value;
		}
	}
}