From af44a85cfdb505e1806762564b1541cd701263ba Mon Sep 17 00:00:00 2001 From: YoshiRulz Date: Sun, 4 Dec 2022 06:25:59 +1000 Subject: [PATCH] Add unit tests for `IMemoryApi.{Read,Write}ByteRange` --- .../Api/Classes/MemoryApi.cs | 2 +- .../Client.Common/Api/MemoryApiTests.cs | 110 ++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/BizHawk.Tests/Client.Common/Api/MemoryApiTests.cs diff --git a/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs b/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs index 0cfc267379..b3a3fd202d 100644 --- a/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs +++ b/src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs @@ -13,7 +13,7 @@ namespace BizHawk.Client.Common private IEmulator Emulator { get; set; } [OptionalService] - private IMemoryDomains MemoryDomainCore { get; set; } + public IMemoryDomains MemoryDomainCore { get; set; } private readonly Action LogCallback; diff --git a/src/BizHawk.Tests/Client.Common/Api/MemoryApiTests.cs b/src/BizHawk.Tests/Client.Common/Api/MemoryApiTests.cs new file mode 100644 index 0000000000..b127bd8fc6 --- /dev/null +++ b/src/BizHawk.Tests/Client.Common/Api/MemoryApiTests.cs @@ -0,0 +1,110 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; + +using BizHawk.Client.Common; +using BizHawk.Emulation.Common; + +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace BizHawk.Tests.Client.Common.Api +{ + [TestClass] + public sealed class MemoryApiTests + { + /// and its overloads can't take -_- + private static void AssertAreSequenceEqual(IReadOnlyList expected, IReadOnlyList actual, string message) + => Assert.IsTrue(actual.SequenceEqual(expected), message); + + private IMemoryApi CreateDummyApi(byte[] memDomainContents) + => new MemoryApi(Console.WriteLine) //TODO capture and check for error messages? + { + MemoryDomainCore = new MemoryDomainList(new MemoryDomain[] + { + new MemoryDomainByteArray("ADomain", MemoryDomain.Endian.Little, memDomainContents, writable: true, wordSize: 1), + }), + }; + + [TestMethod] + public void TestBulkPeek() + { + var memApi = CreateDummyApi(new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }); + AssertAreSequenceEqual( + new byte[] { default, default, default }, + memApi.ReadByteRange(addr: -5, length: 3), + "fully below lower boundary"); + AssertAreSequenceEqual( + new byte[] { default, default, 0x01, 0x23 }, + memApi.ReadByteRange(addr: -2, length: 4), + "crosses lower boundary"); + AssertAreSequenceEqual( + new byte[] { default, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, default }, + memApi.ReadByteRange(addr: -1, length: 10), + "crosses both boundaries"); + AssertAreSequenceEqual( + new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + memApi.ReadByteRange(addr: 0, length: 8), + "whole domain"); + AssertAreSequenceEqual( + new byte[] { 0x23, 0x45, 0x67, 0x89, 0xAB }, + memApi.ReadByteRange(addr: 1, length: 5), + "strict contains"); + AssertAreSequenceEqual( + Array.Empty(), + memApi.ReadByteRange(addr: 3, length: 0), + "empty"); + AssertAreSequenceEqual( + new byte[] { 0xCD, 0xEF, default }, + memApi.ReadByteRange(addr: 6, length: 3), + "crosses upper boundary"); + AssertAreSequenceEqual( + new byte[] { default, default, default, default }, + memApi.ReadByteRange(addr: 9, length: 4), + "fully above upper boundary"); + } + + [TestMethod] + public void TestBulkPoke() + { + void TestCase(IReadOnlyList expected, Action action, string message) + { + var memDomainContents = new byte[8]; + action(CreateDummyApi(memDomainContents)); + AssertAreSequenceEqual(expected, memDomainContents, message); + } + TestCase( + new byte[8], + memApi => memApi.WriteByteRange(-5, new byte[] { 0x01, 0x23, 0x45 }), + "fully below lower boundary"); + TestCase( + new byte[] { 0x45, 0x67, default, default, default, default, default, default }, + memApi => memApi.WriteByteRange(-2, new byte[] { 0x01, 0x23, 0x45, 0x67 }), + "crosses lower boundary"); + TestCase( + new byte[] { 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE }, + memApi => memApi.WriteByteRange(-1, new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC }), + "crosses both boundaries"); + TestCase( + new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + memApi => memApi.WriteByteRange(0, new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }), + "whole domain"); + TestCase( + new byte[] { default, 0x01, 0x23, 0x45, 0x67, 0x89, default, default }, + memApi => memApi.WriteByteRange(1, new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89 }), + "strict contains"); + TestCase( + new byte[8], + memApi => memApi.WriteByteRange(3, Array.Empty()), + "empty"); + TestCase( + new byte[] { default, default, default, default, default, default, 0x01, 0x23 }, + memApi => memApi.WriteByteRange(6, new byte[] { 0x01, 0x23, 0x45 }), + "crosses upper boundary"); + TestCase( + new byte[8], + memApi => memApi.WriteByteRange(9, new byte[] { 0x01, 0x23, 0x45, 0x67 }), + "fully above upper boundary"); + } + } +}