Skip to content

Commit af44a85

Browse files
committed
Add unit tests for IMemoryApi.{Read,Write}ByteRange
1 parent dc4efc3 commit af44a85

File tree

2 files changed

+111
-1
lines changed

2 files changed

+111
-1
lines changed

src/BizHawk.Client.Common/Api/Classes/MemoryApi.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ public sealed class MemoryApi : IMemoryApi
1313
private IEmulator Emulator { get; set; }
1414

1515
[OptionalService]
16-
private IMemoryDomains MemoryDomainCore { get; set; }
16+
public IMemoryDomains MemoryDomainCore { get; set; }
1717

1818
private readonly Action<string> LogCallback;
1919

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
using System;
2+
using System.Collections;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
6+
using BizHawk.Client.Common;
7+
using BizHawk.Emulation.Common;
8+
9+
using Microsoft.VisualStudio.TestTools.UnitTesting;
10+
11+
namespace BizHawk.Tests.Client.Common.Api
12+
{
13+
[TestClass]
14+
public sealed class MemoryApiTests
15+
{
16+
/// <remarks><see cref="CollectionAssert.AreEqual(ICollection, ICollection)"/> and its overloads can't take <see cref="IReadOnlyCollection{T}"/> -_-</remarks>
17+
private static void AssertAreSequenceEqual<T>(IReadOnlyList<T> expected, IReadOnlyList<T> actual, string message)
18+
=> Assert.IsTrue(actual.SequenceEqual(expected), message);
19+
20+
private IMemoryApi CreateDummyApi(byte[] memDomainContents)
21+
=> new MemoryApi(Console.WriteLine) //TODO capture and check for error messages?
22+
{
23+
MemoryDomainCore = new MemoryDomainList(new MemoryDomain[]
24+
{
25+
new MemoryDomainByteArray("ADomain", MemoryDomain.Endian.Little, memDomainContents, writable: true, wordSize: 1),
26+
}),
27+
};
28+
29+
[TestMethod]
30+
public void TestBulkPeek()
31+
{
32+
var memApi = CreateDummyApi(new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF });
33+
AssertAreSequenceEqual(
34+
new byte[] { default, default, default },
35+
memApi.ReadByteRange(addr: -5, length: 3),
36+
"fully below lower boundary");
37+
AssertAreSequenceEqual(
38+
new byte[] { default, default, 0x01, 0x23 },
39+
memApi.ReadByteRange(addr: -2, length: 4),
40+
"crosses lower boundary");
41+
AssertAreSequenceEqual(
42+
new byte[] { default, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, default },
43+
memApi.ReadByteRange(addr: -1, length: 10),
44+
"crosses both boundaries");
45+
AssertAreSequenceEqual(
46+
new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
47+
memApi.ReadByteRange(addr: 0, length: 8),
48+
"whole domain");
49+
AssertAreSequenceEqual(
50+
new byte[] { 0x23, 0x45, 0x67, 0x89, 0xAB },
51+
memApi.ReadByteRange(addr: 1, length: 5),
52+
"strict contains");
53+
AssertAreSequenceEqual(
54+
Array.Empty<byte>(),
55+
memApi.ReadByteRange(addr: 3, length: 0),
56+
"empty");
57+
AssertAreSequenceEqual(
58+
new byte[] { 0xCD, 0xEF, default },
59+
memApi.ReadByteRange(addr: 6, length: 3),
60+
"crosses upper boundary");
61+
AssertAreSequenceEqual(
62+
new byte[] { default, default, default, default },
63+
memApi.ReadByteRange(addr: 9, length: 4),
64+
"fully above upper boundary");
65+
}
66+
67+
[TestMethod]
68+
public void TestBulkPoke()
69+
{
70+
void TestCase(IReadOnlyList<byte> expected, Action<IMemoryApi> action, string message)
71+
{
72+
var memDomainContents = new byte[8];
73+
action(CreateDummyApi(memDomainContents));
74+
AssertAreSequenceEqual(expected, memDomainContents, message);
75+
}
76+
TestCase(
77+
new byte[8],
78+
memApi => memApi.WriteByteRange(-5, new byte[] { 0x01, 0x23, 0x45 }),
79+
"fully below lower boundary");
80+
TestCase(
81+
new byte[] { 0x45, 0x67, default, default, default, default, default, default },
82+
memApi => memApi.WriteByteRange(-2, new byte[] { 0x01, 0x23, 0x45, 0x67 }),
83+
"crosses lower boundary");
84+
TestCase(
85+
new byte[] { 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE },
86+
memApi => memApi.WriteByteRange(-1, new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0xFE, 0xDC }),
87+
"crosses both boundaries");
88+
TestCase(
89+
new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF },
90+
memApi => memApi.WriteByteRange(0, new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }),
91+
"whole domain");
92+
TestCase(
93+
new byte[] { default, 0x01, 0x23, 0x45, 0x67, 0x89, default, default },
94+
memApi => memApi.WriteByteRange(1, new byte[] { 0x01, 0x23, 0x45, 0x67, 0x89 }),
95+
"strict contains");
96+
TestCase(
97+
new byte[8],
98+
memApi => memApi.WriteByteRange(3, Array.Empty<byte>()),
99+
"empty");
100+
TestCase(
101+
new byte[] { default, default, default, default, default, default, 0x01, 0x23 },
102+
memApi => memApi.WriteByteRange(6, new byte[] { 0x01, 0x23, 0x45 }),
103+
"crosses upper boundary");
104+
TestCase(
105+
new byte[8],
106+
memApi => memApi.WriteByteRange(9, new byte[] { 0x01, 0x23, 0x45, 0x67 }),
107+
"fully above upper boundary");
108+
}
109+
}
110+
}

0 commit comments

Comments
 (0)