0
mirror of https://github.com/sampletext32/ParkanPlayground.git synced 2025-05-19 11:51:17 +03:00
ParkanPlayground/X86DisassemblerTests/RawFromFileDisassemblyTests.cs

137 lines
4.4 KiB
C#
Raw Normal View History

2025-04-13 17:02:46 +03:00
using X86Disassembler.X86;
using Xunit.Abstractions;
namespace X86DisassemblerTests;
2025-04-15 22:20:46 +03:00
/// <summary>
/// Tests for disassembling raw bytes from CSV test files
/// </summary>
2025-04-13 17:02:46 +03:00
public class RawFromFileDisassemblyTests(ITestOutputHelper output)
{
[Theory]
2025-04-15 22:20:46 +03:00
[ClassData(typeof(TestDataProvider))]
public void RunTests(string f, int idx, TestFromFileEntry test)
2025-04-13 17:02:46 +03:00
{
Printer.WriteLine = output.WriteLine;
2025-04-15 22:20:46 +03:00
// Convert hex string to byte array
byte[] code = HexStringToByteArray(test.RawBytes);
2025-04-13 17:02:46 +03:00
2025-04-15 22:20:46 +03:00
// Create a disassembler with the code
Disassembler disassembler = new Disassembler(code, 0x1000);
// Disassemble the code
var disassembledInstructions = disassembler.Disassemble();
// Verify the number of instructions
if (test.Instructions.Count != disassembledInstructions.Count)
2025-04-13 17:02:46 +03:00
{
2025-04-15 22:20:46 +03:00
AssertFailWithReason(
idx,
f,
test,
disassembledInstructions,
"Instruction count mismatch"
);
2025-04-13 17:02:46 +03:00
}
2025-04-15 22:20:46 +03:00
// Verify each instruction
for (int i = 0; i < test.Instructions.Count; i++)
2025-04-13 17:02:46 +03:00
{
2025-04-15 22:20:46 +03:00
var expected = test.Instructions[i];
var actual = disassembledInstructions[i];
2025-04-13 17:02:46 +03:00
2025-04-15 22:20:46 +03:00
// Compare instruction type instead of mnemonic
if (expected.Type != actual.Type)
2025-04-13 17:02:46 +03:00
{
AssertFailWithReason(
2025-04-15 22:20:46 +03:00
idx,
f,
2025-04-13 17:02:46 +03:00
test,
disassembledInstructions,
2025-04-15 22:20:46 +03:00
$"Type mismatch: Expected {expected.Type}, got {actual.Type}"
2025-04-13 17:02:46 +03:00
);
}
2025-04-15 22:20:46 +03:00
// Compare operands
if (!CompareOperands(expected.Operands, actual.StructuredOperands))
2025-04-13 17:02:46 +03:00
{
2025-04-15 22:20:46 +03:00
AssertFailWithReason(
idx,
f,
test,
disassembledInstructions,
$"Operands mismatch: \n" +
$"Expected: {string.Join(", ", expected.Operands)}.\n" +
$"Actual: {string.Join(", ", actual.StructuredOperands.Select(x => $"{x.GetType().Name}({x})"))}"
);
2025-04-13 17:02:46 +03:00
}
}
}
2025-04-15 22:20:46 +03:00
/// <summary>
/// Compare operands with some flexibility since the string representation might be slightly different
/// </summary>
private bool CompareOperands(string[] expectedOperands, List<Operand> actualOperands)
2025-04-13 17:02:46 +03:00
{
2025-04-15 22:20:46 +03:00
// Check if the number of operands matches
if (expectedOperands.Length != actualOperands.Count)
{
return false;
}
// Initialize result to true and set to false if any operand doesn't match
bool result = true;
// Compare each operand
for (var i = 0; i < expectedOperands.Length; i++)
{
var expected = expectedOperands[i];
var actual = actualOperands[i];
if (expected == actual.ToString()) continue;
result = false;
break;
}
return result;
2025-04-14 23:08:52 +03:00
}
private void AssertFailWithReason(int index, string file, TestFromFileEntry test, List<Instruction> disassembledInstructions, string reason)
{
output.WriteLine($"Test {index} in {file} failed: {reason}");
output.WriteLine($"Raw bytes: {test.RawBytes}");
output.WriteLine("Expected instructions:");
foreach (var instruction in test.Instructions)
{
2025-04-15 22:20:46 +03:00
output.WriteLine($" {instruction.Type:G} {string.Join(",", instruction.Operands)}");
2025-04-14 23:08:52 +03:00
}
output.WriteLine("Actual instructions:");
foreach (var instruction in disassembledInstructions)
{
output.WriteLine($" {instruction.Type} {string.Join(", ", instruction.StructuredOperands)}");
}
2025-04-15 22:20:46 +03:00
Assert.Fail(reason);
2025-04-13 17:02:46 +03:00
}
2025-04-15 22:20:46 +03:00
/// <summary>
/// Converts a hexadecimal string to a byte array
/// </summary>
2025-04-13 17:02:46 +03:00
private static byte[] HexStringToByteArray(string hex)
{
2025-04-14 23:08:52 +03:00
// Remove any spaces or other formatting characters
hex = hex.Replace(" ", "").Replace("-", "").Replace("0x", "");
2025-04-13 17:02:46 +03:00
2025-04-14 23:08:52 +03:00
// Create a byte array that will hold the converted hex string
2025-04-13 17:02:46 +03:00
byte[] bytes = new byte[hex.Length / 2];
2025-04-14 23:08:52 +03:00
// Convert each pair of hex characters to a byte
for (int i = 0; i < hex.Length; i += 2)
2025-04-13 17:02:46 +03:00
{
2025-04-14 23:08:52 +03:00
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
2025-04-13 17:02:46 +03:00
}
return bytes;
}
}