From ae433e7c9d57605106ba668ba81128f5f3c457c0 Mon Sep 17 00:00:00 2001 From: grovre Date: Thu, 16 Jan 2025 00:21:42 -0600 Subject: [PATCH 1/7] .gitignore .vs\ folder --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index add57be..0976324 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ bin/ obj/ /packages/ riderModule.iml -/_ReSharper.Caches/ \ No newline at end of file +/_ReSharper.Caches/ +/.vs From d0efb84c21ae448d68399560b81d65c17f5c2719 Mon Sep 17 00:00:00 2001 From: grovre Date: Thu, 16 Jan 2025 16:15:42 -0600 Subject: [PATCH 2/7] Testing --- MemNet.sln | 16 +++++- MemNet/Wildcard.cs | 8 +++ Testing/ScanHelper.cs | 54 +++++++++++++++++++ Testing/Testing.csproj | 21 ++++++++ Testing/Tests.cs | 114 +++++++++++++++++++++++++++++++++++++++++ 5 files changed, 211 insertions(+), 2 deletions(-) create mode 100644 Testing/ScanHelper.cs create mode 100644 Testing/Testing.csproj create mode 100644 Testing/Tests.cs diff --git a/MemNet.sln b/MemNet.sln index af95f23..47a4a40 100644 --- a/MemNet.sln +++ b/MemNet.sln @@ -1,10 +1,15 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Memlib", "MemNet\MemNet.csproj", "{CA5757C4-1576-4CE1-AD33-18C0A6E3BEEF}" +# Visual Studio Version 17 +VisualStudioVersion = 17.12.35707.178 d17.12 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MemNet", "MemNet\MemNet.csproj", "{CA5757C4-1576-4CE1-AD33-18C0A6E3BEEF}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{CB0F42DE-E293-4018-8BC0-0D82721A3717}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Reader", "Examples\Pattern Scanner\Pattern Scanner.csproj", "{36FA29A7-59CB-40EA-B2D2-066D7B9F08C1}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pattern Scanner", "Examples\Pattern Scanner\Pattern Scanner.csproj", "{36FA29A7-59CB-40EA-B2D2-066D7B9F08C1}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testing", "Testing\Testing.csproj", "{24F0E9FF-1BDE-41E8-BE50-BE33D30AC3C6}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -20,6 +25,13 @@ Global {36FA29A7-59CB-40EA-B2D2-066D7B9F08C1}.Debug|Any CPU.Build.0 = Debug|Any CPU {36FA29A7-59CB-40EA-B2D2-066D7B9F08C1}.Release|Any CPU.ActiveCfg = Release|Any CPU {36FA29A7-59CB-40EA-B2D2-066D7B9F08C1}.Release|Any CPU.Build.0 = Release|Any CPU + {24F0E9FF-1BDE-41E8-BE50-BE33D30AC3C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {24F0E9FF-1BDE-41E8-BE50-BE33D30AC3C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {24F0E9FF-1BDE-41E8-BE50-BE33D30AC3C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {24F0E9FF-1BDE-41E8-BE50-BE33D30AC3C6}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(NestedProjects) = preSolution {36FA29A7-59CB-40EA-B2D2-066D7B9F08C1} = {CB0F42DE-E293-4018-8BC0-0D82721A3717} diff --git a/MemNet/Wildcard.cs b/MemNet/Wildcard.cs index 1d52d32..4586147 100644 --- a/MemNet/Wildcard.cs +++ b/MemNet/Wildcard.cs @@ -11,6 +11,14 @@ public Wildcard(string token) _lowNibble = token[1] == '?' ? null : Convert.ToInt32(token[1].ToString(), 16); } + public byte? AsByte() + { + if (!_highNibble.HasValue || !_lowNibble.HasValue) + return null; + + return (byte)((_highNibble.Value << 4) | _lowNibble.Value); + } + public bool Matches(byte b) { int high = (b >> 4) & 0xF; diff --git a/Testing/ScanHelper.cs b/Testing/ScanHelper.cs new file mode 100644 index 0000000..925bdd0 --- /dev/null +++ b/Testing/ScanHelper.cs @@ -0,0 +1,54 @@ +using Memlib; +using NUnit.Framework; +using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Testing; +internal static class ScanHelper +{ + public static byte[] GenerateBytes(int length, Random rand) + { + var bytes = new byte[length]; + rand.NextBytes(bytes); + return bytes; + } + + public static unsafe Wildcard[] GeneratePattern(ReadOnlySpan bytes, out nint start, out nint end, Random? rand = null) + { + rand ??= new Random(); + + fixed (byte* pb0 = bytes) + { + var pbn = pb0 + bytes.Length; + start = new nint(pb0); + end = new nint(pbn); + + // Sanity check + fixed (byte* endInclusive = &bytes[^1]) + Trace.Assert(pbn == endInclusive + 1); + + var pattern = new Wildcard[bytes.Length]; + var unknownChance = rand.NextSingle(); + for (var offset = 0; pb0 + offset < pbn; offset++) + { + var isUnknown = rand.NextSingle() < unknownChance; + if (isUnknown) + { + pattern[offset] = new Wildcard(); + continue; + } + + var b = pb0[offset]; + var hex = b.ToString("X2"); + pattern[offset] = new Wildcard(hex); + } + + return pattern; + } + } +} diff --git a/Testing/Testing.csproj b/Testing/Testing.csproj new file mode 100644 index 0000000..4740ea4 --- /dev/null +++ b/Testing/Testing.csproj @@ -0,0 +1,21 @@ + + + + Library + net8.0 + enable + enable + true + + + + + + + + + + + + + diff --git a/Testing/Tests.cs b/Testing/Tests.cs new file mode 100644 index 0000000..684f7a5 --- /dev/null +++ b/Testing/Tests.cs @@ -0,0 +1,114 @@ +using Memlib; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Testing; + +[TestFixture] +internal class Tests +{ + [Test] + [Repeat(5_000)] + public void AobGeneralTest() + { + const int length = 0x2000; + var pArr = Marshal.AllocHGlobal(length); + Span bytes; + unsafe + { + bytes = new Span(pArr.ToPointer(), length); + } + + var rand = new Random(); + rand.NextBytes(bytes); + + try + { + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + + var start = rand.Next(0, bytes.Length - 1); + var end = rand.Next(start + 1, bytes.Length); + Trace.Assert(end - start >= 0); // Sanity check + + var pattern = ScanHelper.GeneratePattern( + bytes[start..end], + out var pb0, + out var pbn, + rand); + + var results = mem.Search(pattern, pb0, pbn); + foreach (var address in results) + { + unsafe + { + var offset = (int)(address - pArr); + + for (var j = 0; j < pattern.Length; j++) + { + var patternByte = pattern[j].AsByte(); + var matchedByte = bytes[j + offset]; + var matches = pattern[j].Matches(matchedByte); + Assert.That(matches, Is.True); + } + } + } + } + catch (Exception) + { + throw; + } + finally + { + Marshal.FreeHGlobal(pArr); + } + } + + [Test] + public void AobFullLengthTest() + { + byte[] bytes = [0xAA, 0xBB, 0xCC, 0xDD]; + const string pattern = "AA BB ?? DD"; + + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + + unsafe + { + fixed (byte* pb0 = bytes) + { + var results = mem.Search(pattern, new nint(pb0), new nint(pb0 + bytes.Length)); + Assert.That(results, Is.Not.Null); + Assert.That(results.Count, Is.EqualTo(1)); + var pb0nint = new nint(pb0); // Can't capture fixed locals so do a little trickery + Assert.That(results.All(p => p == pb0nint), Is.True); + } + } + } + + [Test] + public unsafe void EdgeCases() + { + var rand = new Random(); + using var mem = new Memlib.Memory(Environment.ProcessId); + mem.Open(); + + var bytes = new byte[1]; + var pattern = new Wildcard[] { new("??"), new("??") }; + fixed (byte* pb0 = bytes) + { + var pb0nint = new nint(pb0); + Assert.Throws( + () => mem.Search(pattern, pb0nint, pb0nint)); + Assert.Throws(() => mem.Search(pattern, pb0nint, pb0nint + 1)); + } + } +} \ No newline at end of file From e7fc1ac1b2538124056bdac283a17ffedb6aa865 Mon Sep 17 00:00:00 2001 From: grovre Date: Thu, 16 Jan 2025 21:09:09 -0600 Subject: [PATCH 3/7] Use concrete exception in failing edge case --- Testing/Tests.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Testing/Tests.cs b/Testing/Tests.cs index 684f7a5..ab6be6a 100644 --- a/Testing/Tests.cs +++ b/Testing/Tests.cs @@ -108,7 +108,8 @@ public unsafe void EdgeCases() var pb0nint = new nint(pb0); Assert.Throws( () => mem.Search(pattern, pb0nint, pb0nint)); - Assert.Throws(() => mem.Search(pattern, pb0nint, pb0nint + 1)); + Assert.Throws( + () => mem.Search(pattern, pb0nint, pb0nint + 1)); } } } \ No newline at end of file From 4d15f51c2ce895f2478fb3012f43e33fdef1b6b4 Mon Sep 17 00:00:00 2001 From: grovre Date: Thu, 16 Jan 2025 21:41:39 -0600 Subject: [PATCH 4/7] Basic byte r/w tests --- Testing/{Tests.cs => AobTests.cs} | 21 +++++----- Testing/ReadTests.cs | 65 +++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 12 deletions(-) rename Testing/{Tests.cs => AobTests.cs} (84%) create mode 100644 Testing/ReadTests.cs diff --git a/Testing/Tests.cs b/Testing/AobTests.cs similarity index 84% rename from Testing/Tests.cs rename to Testing/AobTests.cs index ab6be6a..d888dfc 100644 --- a/Testing/Tests.cs +++ b/Testing/AobTests.cs @@ -11,11 +11,11 @@ namespace Testing; [TestFixture] -internal class Tests +internal class AobTests { [Test] [Repeat(5_000)] - public void AobGeneralTest() + public unsafe void AobGeneralTest() { const int length = 0x2000; var pArr = Marshal.AllocHGlobal(length); @@ -47,17 +47,14 @@ public void AobGeneralTest() var results = mem.Search(pattern, pb0, pbn); foreach (var address in results) { - unsafe - { - var offset = (int)(address - pArr); + var offset = (int)(address - pArr); - for (var j = 0; j < pattern.Length; j++) - { - var patternByte = pattern[j].AsByte(); - var matchedByte = bytes[j + offset]; - var matches = pattern[j].Matches(matchedByte); - Assert.That(matches, Is.True); - } + for (var j = 0; j < pattern.Length; j++) + { + var patternByte = pattern[j].AsByte(); + var matchedByte = bytes[j + offset]; + var matches = pattern[j].Matches(matchedByte); + Assert.That(matches, Is.True); } } } diff --git a/Testing/ReadTests.cs b/Testing/ReadTests.cs new file mode 100644 index 0000000..11c3a98 --- /dev/null +++ b/Testing/ReadTests.cs @@ -0,0 +1,65 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Testing; + +[TestFixture] +internal class ReadTests +{ + [Test] + public unsafe void ByteReadTest() + { + var length = sizeof(Int128); + Span bx = stackalloc byte[length]; + + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + + for (var i = 0; i < length; i++) + bx[i] = (byte)i; + + fixed (byte* pbx = bx) + { + for (var offset = 0; offset < length; offset++) + { + var addr = new nint(pbx + offset); + var b = mem.Read(addr); + Assert.That(b, Is.EqualTo(bx[offset])); + } + } + } + + [Test] + public unsafe void ByteWriteTest() + { + var length = sizeof(Int128); + Span bSrc = stackalloc byte[length]; + Span bDst = stackalloc byte[length]; + + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + + for (var i = 0; i < length; i++) + bSrc[i] = (byte)i; + + fixed (byte* pbDst = bSrc) + { + for (var offset = 0; offset < length; offset++) + { + var addr = new nint(pbDst + offset); + mem.Write(addr, bSrc[offset]); + } + } + + for (var i = 0; i < length; i++) + Assert.That(bDst[i], Is.EqualTo(bSrc[i])); + } +} From 361719874f8ac178f505a9c47f8b4e7f94ccb532 Mon Sep 17 00:00:00 2001 From: grovre Date: Sat, 18 Jan 2025 02:55:50 -0600 Subject: [PATCH 5/7] Rewrite byte tests for streamlined typing --- Testing/ReadTests.cs | 61 +++++++++++++++++++++++++++----------------- 1 file changed, 38 insertions(+), 23 deletions(-) diff --git a/Testing/ReadTests.cs b/Testing/ReadTests.cs index 11c3a98..75543f8 100644 --- a/Testing/ReadTests.cs +++ b/Testing/ReadTests.cs @@ -12,34 +12,59 @@ namespace Testing; [TestFixture] internal class ReadTests { + private unsafe void ReadTest(T src, ref T dst) where T : unmanaged + { + var defensiveSrcCopy = src; + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + + var pSrc = new nint(&src); + dst = mem.Read(pSrc); + + Assert.That(dst, Is.EqualTo(defensiveSrcCopy)); + Assert.That(dst, Is.EqualTo(src)); + } + + private unsafe void WriteTest(T src, ref T dst) where T : unmanaged + { + var defensiveSrcCopy = src; + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + + fixed (T* pDst = &dst) + { + mem.Write(new nint(pDst), src); + } + + Assert.That(dst, Is.EqualTo(defensiveSrcCopy)); + Assert.That(dst, Is.EqualTo(src)); + } + [Test] public unsafe void ByteReadTest() { - var length = sizeof(Int128); - Span bx = stackalloc byte[length]; + const int length = 0x40; + Span bSrc = stackalloc byte[length]; + Span bDst = stackalloc byte[length]; + + Random.Shared.NextBytes(bSrc); var pid = Environment.ProcessId; using var mem = new Memlib.Memory(pid); mem.Open(); for (var i = 0; i < length; i++) - bx[i] = (byte)i; - - fixed (byte* pbx = bx) { - for (var offset = 0; offset < length; offset++) - { - var addr = new nint(pbx + offset); - var b = mem.Read(addr); - Assert.That(b, Is.EqualTo(bx[offset])); - } + ReadTest(bSrc[i], ref bDst[i]); } } [Test] public unsafe void ByteWriteTest() { - var length = sizeof(Int128); + var length = 0x40; Span bSrc = stackalloc byte[length]; Span bDst = stackalloc byte[length]; @@ -48,18 +73,8 @@ public unsafe void ByteWriteTest() mem.Open(); for (var i = 0; i < length; i++) - bSrc[i] = (byte)i; - - fixed (byte* pbDst = bSrc) { - for (var offset = 0; offset < length; offset++) - { - var addr = new nint(pbDst + offset); - mem.Write(addr, bSrc[offset]); - } + WriteTest(bSrc[i], ref bDst[i]); } - - for (var i = 0; i < length; i++) - Assert.That(bDst[i], Is.EqualTo(bSrc[i])); } } From 99cf4c22d8aeb4e3b011a596db66eb03eea7a6a7 Mon Sep 17 00:00:00 2001 From: grovre Date: Sat, 18 Jan 2025 03:07:57 -0600 Subject: [PATCH 6/7] R/w tests for rest of common struct types --- Testing/ReadTests.cs | 80 --------- Testing/ReadWriteTests.cs | 353 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 353 insertions(+), 80 deletions(-) delete mode 100644 Testing/ReadTests.cs create mode 100644 Testing/ReadWriteTests.cs diff --git a/Testing/ReadTests.cs b/Testing/ReadTests.cs deleted file mode 100644 index 75543f8..0000000 --- a/Testing/ReadTests.cs +++ /dev/null @@ -1,80 +0,0 @@ -using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text; -using System.Threading.Tasks; - -namespace Testing; - -[TestFixture] -internal class ReadTests -{ - private unsafe void ReadTest(T src, ref T dst) where T : unmanaged - { - var defensiveSrcCopy = src; - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - - var pSrc = new nint(&src); - dst = mem.Read(pSrc); - - Assert.That(dst, Is.EqualTo(defensiveSrcCopy)); - Assert.That(dst, Is.EqualTo(src)); - } - - private unsafe void WriteTest(T src, ref T dst) where T : unmanaged - { - var defensiveSrcCopy = src; - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - - fixed (T* pDst = &dst) - { - mem.Write(new nint(pDst), src); - } - - Assert.That(dst, Is.EqualTo(defensiveSrcCopy)); - Assert.That(dst, Is.EqualTo(src)); - } - - [Test] - public unsafe void ByteReadTest() - { - const int length = 0x40; - Span bSrc = stackalloc byte[length]; - Span bDst = stackalloc byte[length]; - - Random.Shared.NextBytes(bSrc); - - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - - for (var i = 0; i < length; i++) - { - ReadTest(bSrc[i], ref bDst[i]); - } - } - - [Test] - public unsafe void ByteWriteTest() - { - var length = 0x40; - Span bSrc = stackalloc byte[length]; - Span bDst = stackalloc byte[length]; - - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - - for (var i = 0; i < length; i++) - { - WriteTest(bSrc[i], ref bDst[i]); - } - } -} diff --git a/Testing/ReadWriteTests.cs b/Testing/ReadWriteTests.cs new file mode 100644 index 0000000..be67e22 --- /dev/null +++ b/Testing/ReadWriteTests.cs @@ -0,0 +1,353 @@ +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Numerics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Testing; + +[TestFixture] +internal class ReadWriteTests +{ + private unsafe void ReadTest(T src, ref T dst) where T : unmanaged + { + var defensiveSrcCopy = src; + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + + var pSrc = new nint(&src); + dst = mem.Read(pSrc); + + Assert.That(dst, Is.EqualTo(defensiveSrcCopy)); + Assert.That(dst, Is.EqualTo(src)); + } + + private unsafe void WriteTest(T src, ref T dst) where T : unmanaged + { + var defensiveSrcCopy = src; + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + + fixed (T* pDst = &dst) + { + mem.Write(new nint(pDst), src); + } + + Assert.That(dst, Is.EqualTo(defensiveSrcCopy)); + Assert.That(dst, Is.EqualTo(src)); + } + + [Test] + public unsafe void ByteReadTest() + { + const int length = 0x40; + Span bSrc = stackalloc byte[length]; + Span bDst = stackalloc byte[length]; + + Random.Shared.NextBytes(bSrc); + + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + + for (var i = 0; i < length; i++) + { + ReadTest(bSrc[i], ref bDst[i]); + } + } + + [Test] + public unsafe void ByteWriteTest() + { + var length = 0x40; + Span bSrc = stackalloc byte[length]; + Span bDst = stackalloc byte[length]; + + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + + for (var i = 0; i < length; i++) + { + WriteTest(bSrc[i], ref bDst[i]); + } + } + + [Test] + public unsafe void ShortReadTest() + { + const int length = 0x40; + Span sSrc = stackalloc short[length]; + Span sDst = stackalloc short[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(sSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + ReadTest(sSrc[i], ref sDst[i]); + } + } + + [Test] + public unsafe void ShortWriteTest() + { + const int length = 0x40; + Span sSrc = stackalloc short[length]; + Span sDst = stackalloc short[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(sSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + WriteTest(sSrc[i], ref sDst[i]); + } + } + + [Test] + public unsafe void IntReadTest() + { + const int length = 0x40; + Span iSrc = stackalloc int[length]; + Span iDst = stackalloc int[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(iSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + ReadTest(iSrc[i], ref iDst[i]); + } + } + + [Test] + public unsafe void LongReadTest() + { + const int length = 0x40; + Span lSrc = stackalloc long[length]; + Span lDst = stackalloc long[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(lSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + ReadTest(lSrc[i], ref lDst[i]); + } + } + + [Test] + public unsafe void LongWriteTest() + { + const int length = 0x40; + Span lSrc = stackalloc long[length]; + Span lDst = stackalloc long[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(lSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + WriteTest(lSrc[i], ref lDst[i]); + } + } + + [Test] + public unsafe void Int128ReadTest() + { + const int length = 0x40; + Span i128Src = stackalloc Int128[length]; + Span i128Dst = stackalloc Int128[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(i128Src)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + ReadTest(i128Src[i], ref i128Dst[i]); + } + } + + [Test] + public unsafe void Int128WriteTest() + { + const int length = 0x40; + Span i128Src = stackalloc Int128[length]; + Span i128Dst = stackalloc Int128[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(i128Src)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + WriteTest(i128Src[i], ref i128Dst[i]); + } + } + + [Test] + public unsafe void FloatReadTest() + { + const int length = 0x40; + Span fSrc = stackalloc float[length]; + Span fDst = stackalloc float[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(fSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + ReadTest(fSrc[i], ref fDst[i]); + } + } + + [Test] + public unsafe void FloatWriteTest() + { + const int length = 0x40; + Span fSrc = stackalloc float[length]; + Span fDst = stackalloc float[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(fSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + WriteTest(fSrc[i], ref fDst[i]); + } + } + + [Test] + public unsafe void DoubleReadTest() + { + const int length = 0x40; + Span dSrc = stackalloc double[length]; + Span dDst = stackalloc double[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(dSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + ReadTest(dSrc[i], ref dDst[i]); + } + } + + [Test] + public unsafe void DoubleWriteTest() + { + const int length = 0x40; + Span dSrc = stackalloc double[length]; + Span dDst = stackalloc double[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(dSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + WriteTest(dSrc[i], ref dDst[i]); + } + } + + [Test] + public unsafe void DecimalReadTest() + { + const int length = 0x40; + Span decSrc = stackalloc decimal[length]; + Span decDst = stackalloc decimal[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(decSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + ReadTest(decSrc[i], ref decDst[i]); + } + } + + [Test] + public unsafe void DecimalWriteTest() + { + var length = 0x40; + Span decSrc = stackalloc decimal[length]; + Span decDst = stackalloc decimal[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(decSrc)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + WriteTest(decSrc[i], ref decDst[i]); + } + } + + [Test] + public unsafe void Vector3ReadTest() + { + const int length = 0x40; + Span v3Src = stackalloc Vector3[length]; + Span v3Dst = stackalloc Vector3[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(v3Src)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + ReadTest(v3Src[i], ref v3Dst[i]); + } + } + + [Test] + public unsafe void Vector3WriteTest() + { + const int length = 0x40; + Span v3Src = stackalloc Vector3[length]; + Span v3Dst = stackalloc Vector3[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(v3Src)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + WriteTest(v3Src[i], ref v3Dst[i]); + } + } + + [Test] + public unsafe void ManagedStructReadTest() + { + const int length = 0x40; + Span m4Src = stackalloc Matrix4x4[length]; + Span m4Dst = stackalloc Matrix4x4[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(m4Src)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + ReadTest(m4Src[i], ref m4Dst[i]); + } + } + + [Test] + public unsafe void ManagedStructWriteTest() + { + const int length = 0x40; + Span m4Src = stackalloc Matrix4x4[length]; + Span m4Dst = stackalloc Matrix4x4[length]; + Random.Shared.NextBytes(MemoryMarshal.AsBytes(m4Src)); + var pid = Environment.ProcessId; + using var mem = new Memlib.Memory(pid); + mem.Open(); + for (var i = 0; i < length; i++) + { + WriteTest(m4Src[i], ref m4Dst[i]); + } + } +} From a9f4bb15aa46a567da2760d2fafc3b60e5050c4f Mon Sep 17 00:00:00 2001 From: grovre Date: Sat, 18 Jan 2025 12:54:16 -0600 Subject: [PATCH 7/7] Shorten tests, make more readable --- Testing/ReadWriteTests.cs | 325 ++++---------------------------------- 1 file changed, 34 insertions(+), 291 deletions(-) diff --git a/Testing/ReadWriteTests.cs b/Testing/ReadWriteTests.cs index be67e22..f3981d1 100644 --- a/Testing/ReadWriteTests.cs +++ b/Testing/ReadWriteTests.cs @@ -13,7 +13,9 @@ namespace Testing; [TestFixture] internal class ReadWriteTests { - private unsafe void ReadTest(T src, ref T dst) where T : unmanaged + const int Length = 0x40; + + private static unsafe void ReadTest(T src, ref T dst) where T : unmanaged { var defensiveSrcCopy = src; var pid = Environment.ProcessId; @@ -23,11 +25,11 @@ private unsafe void ReadTest(T src, ref T dst) where T : unmanaged var pSrc = new nint(&src); dst = mem.Read(pSrc); - Assert.That(dst, Is.EqualTo(defensiveSrcCopy)); + Assert.That(src, Is.EqualTo(defensiveSrcCopy)); Assert.That(dst, Is.EqualTo(src)); } - private unsafe void WriteTest(T src, ref T dst) where T : unmanaged + private static unsafe void WriteTest(T src, ref T dst) where T : unmanaged { var defensiveSrcCopy = src; var pid = Environment.ProcessId; @@ -39,315 +41,56 @@ private unsafe void WriteTest(T src, ref T dst) where T : unmanaged mem.Write(new nint(pDst), src); } - Assert.That(dst, Is.EqualTo(defensiveSrcCopy)); + Assert.That(src, Is.EqualTo(defensiveSrcCopy)); Assert.That(dst, Is.EqualTo(src)); } - [Test] - public unsafe void ByteReadTest() - { - const int length = 0x40; - Span bSrc = stackalloc byte[length]; - Span bDst = stackalloc byte[length]; - - Random.Shared.NextBytes(bSrc); - - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - - for (var i = 0; i < length; i++) - { - ReadTest(bSrc[i], ref bDst[i]); - } - } - - [Test] - public unsafe void ByteWriteTest() - { - var length = 0x40; - Span bSrc = stackalloc byte[length]; - Span bDst = stackalloc byte[length]; - - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - - for (var i = 0; i < length; i++) - { - WriteTest(bSrc[i], ref bDst[i]); - } - } - - [Test] - public unsafe void ShortReadTest() - { - const int length = 0x40; - Span sSrc = stackalloc short[length]; - Span sDst = stackalloc short[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(sSrc)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - ReadTest(sSrc[i], ref sDst[i]); - } - } - - [Test] - public unsafe void ShortWriteTest() + private static unsafe void PerformReadWriteTest(int length, Random rand) where T : unmanaged { - const int length = 0x40; - Span sSrc = stackalloc short[length]; - Span sDst = stackalloc short[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(sSrc)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - WriteTest(sSrc[i], ref sDst[i]); - } - } + Span src = stackalloc T[length]; + Span dst = stackalloc T[length]; - [Test] - public unsafe void IntReadTest() - { - const int length = 0x40; - Span iSrc = stackalloc int[length]; - Span iDst = stackalloc int[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(iSrc)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - ReadTest(iSrc[i], ref iDst[i]); - } - } + rand.NextBytes(MemoryMarshal.AsBytes(src)); - [Test] - public unsafe void LongReadTest() - { - const int length = 0x40; - Span lSrc = stackalloc long[length]; - Span lDst = stackalloc long[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(lSrc)); var pid = Environment.ProcessId; using var mem = new Memlib.Memory(pid); mem.Open(); - for (var i = 0; i < length; i++) - { - ReadTest(lSrc[i], ref lDst[i]); - } - } - [Test] - public unsafe void LongWriteTest() - { - const int length = 0x40; - Span lSrc = stackalloc long[length]; - Span lDst = stackalloc long[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(lSrc)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); for (var i = 0; i < length; i++) { - WriteTest(lSrc[i], ref lDst[i]); + ReadTest(src[i], ref dst[i]); } - } - [Test] - public unsafe void Int128ReadTest() - { - const int length = 0x40; - Span i128Src = stackalloc Int128[length]; - Span i128Dst = stackalloc Int128[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(i128Src)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - ReadTest(i128Src[i], ref i128Dst[i]); - } - } + dst.Clear(); + rand.NextBytes(MemoryMarshal.AsBytes(src)); - [Test] - public unsafe void Int128WriteTest() - { - const int length = 0x40; - Span i128Src = stackalloc Int128[length]; - Span i128Dst = stackalloc Int128[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(i128Src)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); for (var i = 0; i < length; i++) { - WriteTest(i128Src[i], ref i128Dst[i]); + WriteTest(src[i], ref dst[i]); } } [Test] - public unsafe void FloatReadTest() + public unsafe void BasicReadWriteTest() { - const int length = 0x40; - Span fSrc = stackalloc float[length]; - Span fDst = stackalloc float[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(fSrc)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - ReadTest(fSrc[i], ref fDst[i]); - } - } - - [Test] - public unsafe void FloatWriteTest() - { - const int length = 0x40; - Span fSrc = stackalloc float[length]; - Span fDst = stackalloc float[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(fSrc)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - WriteTest(fSrc[i], ref fDst[i]); - } - } - - [Test] - public unsafe void DoubleReadTest() - { - const int length = 0x40; - Span dSrc = stackalloc double[length]; - Span dDst = stackalloc double[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(dSrc)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - ReadTest(dSrc[i], ref dDst[i]); - } - } - - [Test] - public unsafe void DoubleWriteTest() - { - const int length = 0x40; - Span dSrc = stackalloc double[length]; - Span dDst = stackalloc double[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(dSrc)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - WriteTest(dSrc[i], ref dDst[i]); - } - } - - [Test] - public unsafe void DecimalReadTest() - { - const int length = 0x40; - Span decSrc = stackalloc decimal[length]; - Span decDst = stackalloc decimal[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(decSrc)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - ReadTest(decSrc[i], ref decDst[i]); - } - } - - [Test] - public unsafe void DecimalWriteTest() - { - var length = 0x40; - Span decSrc = stackalloc decimal[length]; - Span decDst = stackalloc decimal[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(decSrc)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - WriteTest(decSrc[i], ref decDst[i]); - } - } - - [Test] - public unsafe void Vector3ReadTest() - { - const int length = 0x40; - Span v3Src = stackalloc Vector3[length]; - Span v3Dst = stackalloc Vector3[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(v3Src)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - ReadTest(v3Src[i], ref v3Dst[i]); - } - } - - [Test] - public unsafe void Vector3WriteTest() - { - const int length = 0x40; - Span v3Src = stackalloc Vector3[length]; - Span v3Dst = stackalloc Vector3[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(v3Src)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - WriteTest(v3Src[i], ref v3Dst[i]); - } - } - - [Test] - public unsafe void ManagedStructReadTest() - { - const int length = 0x40; - Span m4Src = stackalloc Matrix4x4[length]; - Span m4Dst = stackalloc Matrix4x4[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(m4Src)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - ReadTest(m4Src[i], ref m4Dst[i]); - } - } - - [Test] - public unsafe void ManagedStructWriteTest() - { - const int length = 0x40; - Span m4Src = stackalloc Matrix4x4[length]; - Span m4Dst = stackalloc Matrix4x4[length]; - Random.Shared.NextBytes(MemoryMarshal.AsBytes(m4Src)); - var pid = Environment.ProcessId; - using var mem = new Memlib.Memory(pid); - mem.Open(); - for (var i = 0; i < length; i++) - { - WriteTest(m4Src[i], ref m4Dst[i]); - } + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); + PerformReadWriteTest(Length, Random.Shared); } }