Clean up how collections are asserted on in unit tests

This commit is contained in:
YoshiRulz 2025-03-21 08:58:08 +10:00
parent c391c6ff58
commit aad3c90a5e
No known key found for this signature in database
GPG Key ID: C4DE31C245353FB7
11 changed files with 147 additions and 76 deletions

View File

@ -14,6 +14,7 @@
<!-- CHECKME: Does liblua5.4.so from a Linux host get picked up correctly? -->
<None Include="$(ProjectDir)../../Assets/dll/libbizhash.*" CopyToOutputDirectory="PreserveNewest" />
<None Include="$(ProjectDir)../../Assets/dll/libzstd.*" CopyToOutputDirectory="PreserveNewest" />
<Using Include="BizHawk.Tests" />
</ItemGroup>
<PropertyGroup>
<!-- Works around weird issue with IsExternalInit specifically, cause is likely related to https://github.com/Sergio0694/PolySharp/issues/48? -->

View File

@ -1,6 +1,4 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Common;
using BizHawk.Client.Common;
@ -11,15 +9,6 @@ namespace BizHawk.Tests.Client.Common.Api
[TestClass]
public sealed class MemoryApiTests
{
/// <remarks><see cref="CollectionAssert.AreEqual(ICollection, ICollection)"/> and its overloads can't take <see cref="IReadOnlyCollection{T}"/> -_-</remarks>
private static void AssertAreSequenceEqual<T>(IReadOnlyList<T> expected, IReadOnlyList<T> actual, string message)
{
if (actual.SequenceEqual(expected)) return;
Console.WriteLine($"ex[{expected.Count}]: {string.Join(", ", expected.Select(static o => o?.ToString() ?? "null"))}");
Console.WriteLine($"ac[{actual.Count}]: {string.Join(", ", actual.Select(static o => o?.ToString() ?? "null"))}");
Assert.Fail(message);
}
private IMemoryApi CreateDummyApi(byte[] memDomainContents)
=> new MemoryApi(Console.WriteLine) //TODO capture and check for error messages?
{
@ -33,35 +22,35 @@ namespace BizHawk.Tests.Client.Common.Api
public void TestBulkPeek()
{
var memApi = CreateDummyApi(new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF });
AssertAreSequenceEqual(
CollectionAssert.That.AreEqual(
new byte[] { default, default, default },
memApi.ReadByteRange(addr: -5, length: 3),
"fully below lower boundary");
AssertAreSequenceEqual(
CollectionAssert.That.AreEqual(
new byte[] { default, default, 0x01, 0x23 },
memApi.ReadByteRange(addr: -2, length: 4),
"crosses lower boundary");
AssertAreSequenceEqual(
CollectionAssert.That.AreEqual(
new byte[] { default, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, default },
memApi.ReadByteRange(addr: -1, length: 10),
"crosses both boundaries");
AssertAreSequenceEqual(
CollectionAssert.That.AreEqual(
new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
memApi.ReadByteRange(addr: 0, length: 8),
"whole domain");
AssertAreSequenceEqual(
CollectionAssert.That.AreEqual(
new byte[] { 0x23, 0x45, 0x67, 0x89, 0xAB },
memApi.ReadByteRange(addr: 1, length: 5),
"strict contains");
AssertAreSequenceEqual(
CollectionAssert.That.AreEqual(
Array.Empty<byte>(),
memApi.ReadByteRange(addr: 3, length: 0),
"empty");
AssertAreSequenceEqual(
CollectionAssert.That.AreEqual(
new byte[] { 0xCD, 0xEF, default },
memApi.ReadByteRange(addr: 6, length: 3),
"crosses upper boundary");
AssertAreSequenceEqual(
CollectionAssert.That.AreEqual(
new byte[] { default, default, default, default },
memApi.ReadByteRange(addr: 9, length: 4),
"fully above upper boundary");
@ -74,7 +63,7 @@ namespace BizHawk.Tests.Client.Common.Api
{
var memDomainContents = new byte[8];
action(CreateDummyApi(memDomainContents));
AssertAreSequenceEqual(expected, memDomainContents, message);
CollectionAssert.That.AreEqual(expected, memDomainContents, message);
}
TestCase(
new byte[8],

View File

@ -3,7 +3,6 @@ using System.Linq;
using BizHawk.Client.Common;
using BizHawk.Common;
using BizHawk.Common.CollectionExtensions;
using BizHawk.Emulation.Cores;
namespace BizHawk.Tests.Client.Common.config
@ -21,13 +20,14 @@ namespace BizHawk.Tests.Client.Common.config
.ToHashSet();
foreach (var sysID in DefaultCorePrefDict.Keys)
{
Assert.IsTrue(multiCoreSystems.Contains(sysID), $"a default core preference exists for {sysID} but that system doesn't have alternate cores");
CollectionAssert.That.Contains(multiCoreSystems, sysID, $"a default core preference exists for {sysID} but that system doesn't have alternate cores");
}
foreach (var (appliesTo, _) in Config.CorePickerUIData)
{
Assert.IsTrue(
appliesTo.All(multiCoreSystems.Contains),
appliesTo.Length is 1
CollectionAssert.That.IsSubsetOf(
superset: multiCoreSystems,
subset: appliesTo,
message: appliesTo.Length is 1
? $"core picker has submenu for {appliesTo[0]}, but that system doesn't have alternate cores"
#pragma warning disable MA0089 // CI build this for .NET Core where there's a `char` overload for `string.Join`
: $"core picker has submenu for {appliesTo[0]} ({string.Join("/", appliesTo)}), but none of those systems have alternate cores");
@ -41,11 +41,11 @@ namespace BizHawk.Tests.Client.Common.config
var allCoreNames = CoreInventory.Instance.SystemsFlat.Select(coreInfo => coreInfo.Name).ToHashSet();
foreach (var (sysID, coreName) in DefaultCorePrefDict)
{
Assert.IsTrue(allCoreNames.Contains(coreName), $"default core preference for {sysID} is \"{coreName}\", which doesn't exist");
CollectionAssert.That.Contains(allCoreNames, coreName, $"default core preference for {sysID} is \"{coreName}\", which doesn't exist");
}
foreach (var (appliesTo, coreNames) in Config.CorePickerUIData) foreach (var coreName in coreNames)
{
Assert.IsTrue(allCoreNames.Contains(coreName), $"core picker includes nonexistant core \"{coreName}\" under {appliesTo[0]} group");
CollectionAssert.That.Contains(allCoreNames, coreName, $"core picker includes nonexistant core \"{coreName}\" under {appliesTo[0]} group");
}
}
@ -55,8 +55,8 @@ namespace BizHawk.Tests.Client.Common.config
var multiCoreSystems = CoreInventory.Instance.AllCores.Where(kvp => kvp.Value.Count != 1).ToArray();
foreach (var (sysID, cores) in multiCoreSystems)
{
Assert.IsTrue(DefaultCorePrefDict.ContainsKey(sysID), $"missing default core preference for {sysID} with {cores.Count} core choices");
Assert.IsTrue(Config.CorePickerUIData.Any(item => item.AppliesTo.Contains(sysID)), $"missing core picker submenu for {sysID} with {cores.Count} core choices");
CollectionAssert.That.ContainsKey(DefaultCorePrefDict, sysID, $"missing default core preference for {sysID} with {cores.Count} core choices");
CollectionAssert.That.Contains(Config.CorePickerUIData.SelectMany(static item => item.AppliesTo), sysID, $"missing core picker submenu for {sysID} with {cores.Count} core choices");
}
}
}

View File

@ -44,7 +44,7 @@ namespace BizHawk.Tests.Client.Common.Dearchive
using MemoryStream ms = new((int) items[0].Size);
af.ExtractFile(items[0].ArchiveIndex, ms);
ms.Seek(0L, SeekOrigin.Begin);
Assert.IsTrue(ms.ReadAllBytes().SequenceEqual(Rom), $"the file extracted from {filename} doesn't match the uncompressed file");
CollectionAssert.AreEqual(Rom, ms.ReadAllBytes(), $"the file extracted from {filename} doesn't match the uncompressed file");
}
}
}

View File

@ -1,6 +1,5 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using BizHawk.Common.CollectionExtensions;
@ -66,22 +65,22 @@ namespace BizHawk.Tests.Common.CollectionExtensions
{
var a123 = new[] { 1, 2, 3 };
var a456 = new[] { 4, 5, 6 };
Assert.IsTrue(a123.ConcatArray(a456).SequenceEqual(new[] { 1, 2, 3, 4, 5, 6 }));
CollectionAssert.AreEqual(new[] { 1, 2, 3, 4, 5, 6 }, a123.ConcatArray(a456));
Assert.AreSame(a123, a123.ConcatArray(Array.Empty<int>()));
Assert.AreSame(a456, Array.Empty<int>().ConcatArray(a456));
Assert.AreEqual(0, Array.Empty<int>().ConcatArray(Array.Empty<int>()).Length);
CollectionAssert.That.IsEmpty(Array.Empty<int>().ConcatArray(Array.Empty<int>()));
}
[TestMethod]
public void TestConcatArrays()
{
Assert.IsTrue(
CE.ConcatArrays([ [ 1, 2 ], [ 3 ], [ ], [ 4, 5, 6 ] ])
.SequenceEqual([ 1, 2, 3, 4, 5, 6 ]),
CollectionAssert.AreEqual(
new[] { 1, 2, 3, 4, 5, 6 },
CE.ConcatArrays([ [ 1, 2 ], [ 3 ], [ ], [ 4, 5, 6 ] ]),
"array");
Assert.IsTrue(
CE.ConcatArrays([ new ArraySegment<int>([ 1, 2 ]), new ArraySegment<int>([ 3 ]), [ ], new ArraySegment<int>([ 4, 5, 6 ]) ])
.SequenceEqual([ 1, 2, 3, 4, 5, 6 ]),
CollectionAssert.AreEqual(
new[] { 1, 2, 3, 4, 5, 6 },
CE.ConcatArrays([ new ArraySegment<int>([ 1, 2 ]), new ArraySegment<int>([ 3 ]), [ ], new ArraySegment<int>([ 4, 5, 6 ]) ]),
"ArraySegment");
}

View File

@ -1,6 +1,4 @@
using System.Linq;
using BizHawk.Common;
using BizHawk.Common;
namespace BizHawk.Tests.Common.CustomCollections
{
@ -14,7 +12,7 @@ namespace BizHawk.Tests.Common.CustomCollections
list.Add(5); // `Insert` when `BinarySearch` returns negative
list.Add(8); // `Insert` when `BinarySearch` returns non-negative
list.Remove(3); // `Remove` when `BinarySearch` returns non-negative
Assert.IsTrue(list.ToArray().SequenceEqual(new[] { 1, 4, 5, 7, 8, 8, 9, 11 }));
CollectionAssert.AreEqual(new[] { 1, 4, 5, 7, 8, 8, 9, 11 }, list);
Assert.IsFalse(list.Remove(10)); // `Remove` when `BinarySearch` returns negative
}
@ -22,8 +20,8 @@ namespace BizHawk.Tests.Common.CustomCollections
public void TestSortedListContains()
{
var list = new SortedList<int>(new[] { 1, 3, 4, 7, 8, 9, 11 });
Assert.IsFalse(list.Contains(6)); // `Contains` when `BinarySearch` returns negative
Assert.IsTrue(list.Contains(11)); // `Contains` when `BinarySearch` returns non-negative
CollectionAssert.DoesNotContain(list, 6, "`Contains` when `BinarySearch` returns negative");
CollectionAssert.Contains(list, 11, "`Contains` when `BinarySearch` returns non-negative");
}
[TestMethod]
@ -32,16 +30,16 @@ namespace BizHawk.Tests.Common.CustomCollections
SortedList<int> list = new([ 1, 4, 7 ]);
Assert.ThrowsException<NotSupportedException>(() => list.Insert(index: 3, item: 0), "setting [^0] (appending) out-of-order should throw");
list.Insert(index: 3, item: 10);
Assert.IsTrue(list.SequenceEqual([ 1, 4, 7, 10 ]), "expecting [ 1, 4, 7, 10 ]");
CollectionAssert.AreEqual(new[] { 1, 4, 7, 10 }, list, "expecting [ 1, 4, 7, 10 ]");
Assert.ThrowsException<NotSupportedException>(() => list.Insert(index: 3, item: 0), "setting [^1] out-of-order should throw");
list.Insert(index: 3, item: 9);
Assert.IsTrue(list.SequenceEqual([ 1, 4, 7, 9, 10 ]), "expecting [ 1, 4, 7, 9, 10 ]");
CollectionAssert.AreEqual(new[] { 1, 4, 7, 9, 10 }, list, "expecting [ 1, 4, 7, 9, 10 ]");
Assert.ThrowsException<NotSupportedException>(() => list.Insert(index: 1, item: 9), "setting [1] out-of-order should throw");
list.Insert(index: 1, item: 3);
Assert.IsTrue(list.SequenceEqual([ 1, 3, 4, 7, 9, 10 ]), "expecting [ 1, 3, 4, 7, 9, 10 ]");
CollectionAssert.AreEqual(new[] { 1, 3, 4, 7, 9, 10 }, list, "expecting [ 1, 3, 4, 7, 9, 10 ]");
Assert.ThrowsException<NotSupportedException>(() => list.Insert(index: 0, item: 9), "setting [0] out-of-order should throw");
list.Insert(index: 0, item: 0);
Assert.IsTrue(list.SequenceEqual([ 0, 1, 3, 4, 7, 9, 10 ]), "expecting [ 0, 1, 3, 4, 7, 9, 10 ]");
CollectionAssert.AreEqual(new[] { 0, 1, 3, 4, 7, 9, 10 }, list, "expecting [ 0, 1, 3, 4, 7, 9, 10 ]");
}
[TestMethod]
@ -52,7 +50,7 @@ namespace BizHawk.Tests.Common.CustomCollections
{
var sortlist = new SortedList<int>(before);
sortlist.RemoveAfter(removeItem);
Assert.IsTrue(sortlist.ToArray().SequenceEqual(after));
CollectionAssert.AreEqual(after, sortlist);
}
[TestMethod]
@ -61,14 +59,14 @@ namespace BizHawk.Tests.Common.CustomCollections
SortedList<int> list = new([ 1, 3, 4 ]);
Assert.ThrowsException<NotSupportedException>(() => list[1] = 9, "setting [1] out-of-order should throw");
list[1] = 2;
Assert.IsTrue(list.SequenceEqual([ 1, 2, 4 ]), "expecting [ 1, 2, 4 ]");
CollectionAssert.AreEqual(new[] { 1, 2, 4 }, list, "expecting [ 1, 2, 4 ]");
Assert.ThrowsException<NotSupportedException>(() => list[0] = 9, "setting [0] out-of-order should throw");
list[0] = 0;
Assert.ThrowsException<NotSupportedException>(() => list[2] = 0, "setting [^1] out-of-order should throw");
list[2] = 9;
Assert.ThrowsException</*NotSupportedException*/ArgumentOutOfRangeException>(() => list[3] = 0, "setting [^0] (appending) out-of-order should throw");
Assert.ThrowsException<ArgumentOutOfRangeException>(() => list[3] = 10, "setting [^0] (appending) properly should throw"); // to match BCL `List<T>`
Assert.IsTrue(list.SequenceEqual([ 0, 2, 9 ]), "expecting [ 0, 2, 9 ]");
CollectionAssert.AreEqual(new[] { 0, 2, 9 }, list, "expecting [ 0, 2, 9 ]");
}
}
}

View File

@ -13,9 +13,9 @@ namespace BizHawk.Tests.Common
var b = new byte[] { 0x23, 0x01, 0x67, 0x45, 0xAB, 0x89, 0xEF, 0xCD }.AsSpan();
var a = b.ToArray().AsSpan();
EndiannessUtils.MutatingByteSwap16(a);
Assert.IsTrue(a.SequenceEqual(expected));
CollectionAssert.That.AreEqual(expected, a);
EndiannessUtils.MutatingByteSwap16(a);
Assert.IsTrue(a.SequenceEqual(b));
CollectionAssert.That.AreEqual(b, a);
}
[TestMethod]
@ -24,9 +24,9 @@ namespace BizHawk.Tests.Common
var b = new byte[] { 0x67, 0x45, 0x23, 0x01, 0xEF, 0xCD, 0xAB, 0x89 }.AsSpan();
var a = b.ToArray().AsSpan();
EndiannessUtils.MutatingByteSwap32(a);
Assert.IsTrue(a.SequenceEqual(expected));
CollectionAssert.That.AreEqual(expected, a);
EndiannessUtils.MutatingByteSwap32(a);
Assert.IsTrue(a.SequenceEqual(b));
CollectionAssert.That.AreEqual(b, a);
}
[TestMethod]
@ -35,9 +35,9 @@ namespace BizHawk.Tests.Common
var b = new byte[] { 0x45, 0x67, 0x01, 0x23, 0xCD, 0xEF, 0x89, 0xAB }.AsSpan();
var a = b.ToArray().AsSpan();
EndiannessUtils.MutatingShortSwap32(a);
Assert.IsTrue(a.SequenceEqual(expected));
CollectionAssert.That.AreEqual(expected, a);
EndiannessUtils.MutatingShortSwap32(a);
Assert.IsTrue(a.SequenceEqual(b));
CollectionAssert.That.AreEqual(b, a);
}
}
}

View File

@ -14,19 +14,17 @@ namespace BizHawk.Tests.Common.MultiPredicateSort
private static readonly (int X, string Y)[] SortedByYDescThenXDesc = { (2, "b"), (1, "b"), (2, "a"), (1, "a") };
private static void AssertSequenceEqual<T>(IEnumerable<T> expected, IEnumerable<T> actual) => Assert.IsTrue(expected.SequenceEqual(actual));
[TestMethod]
public void SanityCheck()
{
AssertSequenceEqual(
CollectionAssert.AreEqual(
SortedByYDescThenXDesc,
Unsorted.OrderByDescending(t => t.Y).ThenByDescending(t => t.X)
Unsorted.OrderByDescending(t => t.Y).ThenByDescending(t => t.X).ToArray()
);
#pragma warning disable MA0030
AssertSequenceEqual(
CollectionAssert.AreEqual(
SortedByYDescThenXDesc,
Unsorted.OrderByDescending(t => t.X).OrderByDescending(t => t.Y)
Unsorted.OrderByDescending(t => t.X).OrderByDescending(t => t.Y).ToArray()
);
#pragma warning restore MA0030
}
@ -39,7 +37,7 @@ namespace BizHawk.Tests.Common.MultiPredicateSort
["by_x"] = t => t.X,
["by_y"] = t => t.Y
});
AssertSequenceEqual(
CollectionAssert.AreEqual(
SortedByXThenYDesc,
sorts.AppliedTo(
Unsorted,
@ -47,7 +45,7 @@ namespace BizHawk.Tests.Common.MultiPredicateSort
new Dictionary<string, bool> { ["by_x"] = false, ["by_y"] = true }
)
);
AssertSequenceEqual(
CollectionAssert.AreEqual(
SortedByYDescThenXDesc,
sorts.AppliedTo(
Unsorted,

View File

@ -1,7 +1,6 @@
using System.Text;
using BizHawk.Common;
using BizHawk.Common.CollectionExtensions;
namespace BizHawk.Tests.Common.checksums
{
@ -15,7 +14,7 @@ namespace BizHawk.Tests.Common.checksums
byte[] data = [ ]; // empty data
byte[] expectedSha = [ 0xDA, 0x39, 0xA3, 0xEE, 0x5E, 0x6B, 0x4B, 0x0D, 0x32, 0x55, 0xBF, 0xEF, 0x95, 0x60, 0x18, 0x90, 0xAF, 0xD8, 0x07, 0x09 ];
Assert.IsTrue(expectedSha.SequenceEqual(SHA1Checksum.Compute(data)));
CollectionAssert.AreEqual(expectedSha, SHA1Checksum.Compute(data));
}
[TestMethod]
@ -24,14 +23,14 @@ namespace BizHawk.Tests.Common.checksums
byte[] data = "hash"u8.ToArray(); // random short data
byte[] expectedSha = [ 0x23, 0x46, 0xAD, 0x27, 0xD7, 0x56, 0x8B, 0xA9, 0x89, 0x6F, 0x1B, 0x7D, 0xA6, 0xB5, 0x99, 0x12, 0x51, 0xDE, 0xBD, 0xF2 ];
Assert.IsTrue(expectedSha.SequenceEqual(SHA1Checksum.Compute(data)));
Assert.IsTrue(expectedSha.SequenceEqual(SHA1Checksum.ComputeConcat(Array.Empty<byte>(), data)));
Assert.IsTrue(expectedSha.SequenceEqual(SHA1Checksum.ComputeConcat(data, Array.Empty<byte>())));
CollectionAssert.AreEqual(expectedSha, SHA1Checksum.Compute(data), "direct");
CollectionAssert.AreEqual(expectedSha, SHA1Checksum.ComputeConcat(Array.Empty<byte>(), data), "prepend nothing");
CollectionAssert.AreEqual(expectedSha, SHA1Checksum.ComputeConcat(data, Array.Empty<byte>()), "append nothing");
data = "ha"u8.ToArray();
byte[] data2 = "sh"u8.ToArray();
Assert.IsTrue(expectedSha.SequenceEqual(SHA1Checksum.ComputeConcat(data, data2)));
CollectionAssert.AreEqual(expectedSha, SHA1Checksum.ComputeConcat(data, data2), "halved and recombined");
}
[TestMethod]
@ -41,16 +40,16 @@ namespace BizHawk.Tests.Common.checksums
byte[] data = Encoding.ASCII.GetBytes(testString);
byte[] expectedSha1 = [ 0x40, 0x8D, 0x94, 0x38, 0x42, 0x16, 0xF8, 0x90, 0xFF, 0x7A, 0x0C, 0x35, 0x28, 0xE8, 0xBE, 0xD1, 0xE0, 0xB0, 0x16, 0x21 ];
Assert.IsTrue(expectedSha1.SequenceEqual(SHA1Checksum.Compute(data)));
CollectionAssert.AreEqual(expectedSha1, SHA1Checksum.Compute(data), "first");
data = new byte[65];
Encoding.ASCII.GetBytes(testString).CopyTo(data, 0);
byte[] expectedSha2 = [ 0x65, 0x87, 0x84, 0xE2, 0x68, 0xBF, 0xB1, 0x67, 0x94, 0x7B, 0xB7, 0xF3, 0xFB, 0x76, 0x69, 0x62, 0x79, 0x3E, 0x8C, 0x46 ];
Assert.IsTrue(expectedSha2.SequenceEqual(SHA1Checksum.Compute(data.AsSpan(0, 64))));
CollectionAssert.AreEqual(expectedSha2, SHA1Checksum.Compute(data.AsSpan(0, 64)), "second");
byte[] expectedSha3 = [ 0x34, 0xF3, 0xA2, 0x57, 0xBD, 0x12, 0x5E, 0x6E, 0x0E, 0x28, 0xD0, 0xE5, 0xDA, 0xBE, 0x22, 0x28, 0x97, 0xFA, 0x69, 0x55 ];
Assert.IsTrue(expectedSha3.SequenceEqual(SHA1Checksum.Compute(data)));
CollectionAssert.AreEqual(expectedSha3, SHA1Checksum.Compute(data), "third");
}
}
}

View File

@ -15,7 +15,10 @@ namespace BizHawk.Tests.Emulation.Common
[TestMethod]
public void CheckFilesInOptions()
{
foreach (var fo in FirmwareDatabase.FirmwareOptions) Assert.IsTrue(FirmwareDatabase.FirmwareFilesByHash.ContainsKey(fo.Hash), $"option {fo.ID} references unknown file {fo.Hash}");
foreach (var fo in FirmwareDatabase.FirmwareOptions)
{
CollectionAssert.That.ContainsKey(FirmwareDatabase.FirmwareFilesByHash, fo.Hash, $"option {fo.ID} references unknown file {fo.Hash}");
}
}
[TestMethod]

View File

@ -0,0 +1,84 @@
using System.Collections.Generic;
using System.Linq;
namespace BizHawk.Tests
{
public static class TestAssertions
{
public static void AreEqual<T>(
this CollectionAssert assert,
ICollection<T> expected,
ICollection<T> actual,
string? message = null)
{
if (actual.SequenceEqual(expected)) return;
Console.WriteLine($"ex{PrettyPrint(expected)}\nac{PrettyPrint(actual)}");
Assert.Fail(message);
}
public static void AreEqual<T>(
this CollectionAssert assert,
IReadOnlyCollection<T> expected,
IReadOnlyCollection<T> actual,
string? message = null)
{
if (actual.SequenceEqual(expected)) return;
Console.WriteLine($"ex{PrettyPrint(expected)}\nac{PrettyPrint(actual)}");
Assert.Fail(message);
}
public static void AreEqual<T>(
this CollectionAssert assert,
ReadOnlySpan<T> expected,
ReadOnlySpan<T> actual,
string? message = null)
where T : IEquatable<T>
{
if (actual.SequenceEqual(expected)) return;
Console.WriteLine($"ex{PrettyPrint((ICollection<T>) expected.ToArray())}\nac{PrettyPrint((ICollection<T>) actual.ToArray())}");
Assert.Fail(message);
}
public static void AreEqual<T>(
this CollectionAssert assert,
Span<T> expected,
Span<T> actual,
string? message = null)
where T : IEquatable<T>
=> assert.AreEqual((ReadOnlySpan<T>) expected, actual, message);
public static void Contains<T>(
this CollectionAssert assert,
IEnumerable<T> collection,
T element,
string? message = null)
=> Assert.IsTrue(collection.Contains(element), message);
public static void ContainsKey<TKey, TValue>(
this CollectionAssert assert,
IReadOnlyDictionary<TKey, TValue> dict,
TKey key,
string? message = null)
=> Assert.IsTrue(dict.ContainsKey(key), message);
public static void IsEmpty<T>(
this CollectionAssert assert,
IReadOnlyCollection<T> collection,
string? message = null)
=> Assert.IsTrue(collection.Count is 0, message);
/// <remarks>dumb param order matches predefined method</remarks>
public static void IsSubsetOf<T>(
this CollectionAssert assert,
ICollection<T> subset,
ICollection<T> superset,
string? message = null)
=> Assert.IsTrue(subset.All(superset.Contains), message);
private static string PrettyPrint<T>(ICollection<T> collection)
=> $"[{collection.Count}]: {string.Join(", ", collection.Select(static o => o?.ToString() ?? "null"))}";
private static string PrettyPrint<T>(IReadOnlyCollection<T> collection)
=> $"[{collection.Count}]: {string.Join(", ", collection.Select(static o => o?.ToString() ?? "null"))}";
}
}