mirror of
https://github.com/patchzyy/wiicompiled
synced 2026-09-10 17:16:47 -04:00
152 lines
5.9 KiB
C#
152 lines
5.9 KiB
C#
using Translator.Core.Mods;
|
|
|
|
namespace Translator.Tests;
|
|
|
|
public sealed class ModDataPatchWriterTests
|
|
{
|
|
[Fact]
|
|
public void WriteEmitsBinaryBlobsAndStableAssemblyWithoutHexArrays()
|
|
{
|
|
var root = Path.Combine(Path.GetTempPath(), "mkw-mod-data-" + Guid.NewGuid().ToString("N"));
|
|
try
|
|
{
|
|
var cppPath = Path.Combine(root, "cpp", "mod_data_patches.cpp");
|
|
var moduleImage = Enumerable.Range(0, 257).Select(i => (byte)(i * 37)).ToArray();
|
|
var digest = Enumerable.Range(0, 20).Select(i => (byte)(0xA0 + i)).ToArray();
|
|
|
|
Write(cppPath, moduleImage, digest);
|
|
|
|
var blobRoot = Path.Combine(root, "cpp", "mod_data_patches_blobs");
|
|
Assert.Equal(moduleImage, File.ReadAllBytes(Path.Combine(blobRoot, "module_image.bin")));
|
|
Assert.Equal(digest, File.ReadAllBytes(Path.Combine(blobRoot, "kamek_code_sha1.bin")));
|
|
|
|
var cpp = File.ReadAllText(cppPath);
|
|
Assert.Contains("extern const uint8_t kModuleImage[];", cpp, StringComparison.Ordinal);
|
|
Assert.Contains("Memory::GetPointer(kModuleGuestBase, kModuleImageSize), kModuleImage, kModuleImageSize", cpp, StringComparison.Ordinal);
|
|
Assert.DoesNotContain("alignas(16) const uint8_t", cpp, StringComparison.Ordinal);
|
|
Assert.DoesNotContain("0x00, 0x25,", cpp, StringComparison.Ordinal);
|
|
|
|
var assemblyPath = Path.Combine(root, "cpp", "mod_data_patches_blobs.S");
|
|
var assembly = File.ReadAllText(assemblyPath);
|
|
Assert.Contains(".globl kModuleImage", assembly, StringComparison.Ordinal);
|
|
Assert.Contains(".globl kKamekCodeSha1Digest", assembly, StringComparison.Ordinal);
|
|
Assert.Contains(".incbin", assembly, StringComparison.Ordinal);
|
|
|
|
var timestamps = new[] { cppPath, assemblyPath }
|
|
.Concat(Directory.GetFiles(blobRoot, "*.bin"))
|
|
.ToDictionary(path => path, File.GetLastWriteTimeUtc);
|
|
Write(cppPath, moduleImage, digest);
|
|
foreach (var (path, timestamp) in timestamps)
|
|
{
|
|
Assert.Equal(timestamp, File.GetLastWriteTimeUtc(path));
|
|
}
|
|
}
|
|
finally
|
|
{
|
|
if (Directory.Exists(root))
|
|
{
|
|
Directory.Delete(root, recursive: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void WritePrunesOptionalDigestWhenItDisappears()
|
|
{
|
|
var root = Path.Combine(Path.GetTempPath(), "mkw-mod-data-" + Guid.NewGuid().ToString("N"));
|
|
try
|
|
{
|
|
var cppPath = Path.Combine(root, "mod_data_patches.cpp");
|
|
Write(cppPath, [1, 2, 3, 4], new byte[20]);
|
|
Write(cppPath, [1, 2, 3, 4], null);
|
|
|
|
var blobRoot = Path.Combine(root, "mod_data_patches_blobs");
|
|
Assert.Equal(["module_image.bin"], Directory.GetFiles(blobRoot, "*.bin").Select(Path.GetFileName).ToArray());
|
|
var assembly = File.ReadAllText(Path.Combine(root, "mod_data_patches_blobs.S"));
|
|
Assert.DoesNotContain("kKamekCodeSha1Digest", assembly, StringComparison.Ordinal);
|
|
}
|
|
finally
|
|
{
|
|
if (Directory.Exists(root))
|
|
{
|
|
Directory.Delete(root, recursive: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteCanReferencePublishedBlobsFromTransactionalStaging()
|
|
{
|
|
var root = Path.Combine(Path.GetTempPath(), "mkw-mod-data-" + Guid.NewGuid().ToString("N"));
|
|
try
|
|
{
|
|
var stagingCpp = Path.Combine(root, ".staging", "cpp", "mod_data_patches.cpp");
|
|
var publishedBlobs = Path.Combine(root, "published", "cpp", "mod_data_patches_blobs");
|
|
Write(stagingCpp, [1, 2, 3, 4], null, publishedBlobDirectory: publishedBlobs);
|
|
|
|
var assembly = File.ReadAllText(Path.Combine(root, ".staging", "cpp", "mod_data_patches_blobs.S"));
|
|
var expected = Path.GetFullPath(Path.Combine(publishedBlobs, "module_image.bin")).Replace('\\', '/');
|
|
Assert.Contains($".incbin \"{expected}\"", assembly, StringComparison.Ordinal);
|
|
Assert.DoesNotContain(".staging", assembly, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
finally
|
|
{
|
|
if (Directory.Exists(root))
|
|
{
|
|
Directory.Delete(root, recursive: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
[Fact]
|
|
public void WriteChangesAssemblyWhenSameSizeBlobContentChanges()
|
|
{
|
|
var root = Path.Combine(Path.GetTempPath(), "mkw-mod-data-" + Guid.NewGuid().ToString("N"));
|
|
try
|
|
{
|
|
var cppPath = Path.Combine(root, "mod_data_patches.cpp");
|
|
Write(cppPath, [1, 2, 3, 4], null);
|
|
var assemblyPath = Path.Combine(root, "mod_data_patches_blobs.S");
|
|
var before = File.ReadAllText(assemblyPath);
|
|
|
|
Write(cppPath, [1, 2, 3, 5], null);
|
|
var after = File.ReadAllText(assemblyPath);
|
|
|
|
Assert.NotEqual(before, after);
|
|
Assert.Contains("sha256=", after, StringComparison.Ordinal);
|
|
}
|
|
finally
|
|
{
|
|
if (Directory.Exists(root))
|
|
{
|
|
Directory.Delete(root, recursive: true);
|
|
}
|
|
}
|
|
}
|
|
|
|
private static void Write(
|
|
string path,
|
|
byte[] moduleImage,
|
|
byte[]? digest,
|
|
string? publishedBlobDirectory = null)
|
|
{
|
|
var plan = new KamekPatchPlan { ModuleGuestBase = 0x81700000u, Classifications = [] };
|
|
var manifest = new BaseManifest("test", 1, "RMCP01", "P", "hash", 0, [], [], "ranges.json");
|
|
ModDataPatchWriter.Write(
|
|
path,
|
|
plan,
|
|
0x803992E0u,
|
|
manifest,
|
|
[],
|
|
moduleImage,
|
|
digest,
|
|
null,
|
|
(uint)moduleImage.Length,
|
|
0x40u,
|
|
0x81700000u,
|
|
0x81700000u,
|
|
false,
|
|
publishedBlobDirectory: publishedBlobDirectory);
|
|
}
|
|
}
|