Skip to content

Commit

Permalink
Added PatchBySequence tests; fixed sequence not found
Browse files Browse the repository at this point in the history
  • Loading branch information
TomRichter committed Jan 6, 2019
1 parent f5da4e7 commit 3657d52
Show file tree
Hide file tree
Showing 7 changed files with 238 additions and 23 deletions.
18 changes: 0 additions & 18 deletions PulsarPluginLoader.Tests/PatchBySequenceTests.cs

This file was deleted.

214 changes: 214 additions & 0 deletions PulsarPluginLoader.Tests/Patches/PatchBySequenceTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
using Harmony;
using NUnit.Framework;
using System.Collections.Generic;
using System.Linq;
using System.Reflection.Emit;
using static PulsarPluginLoader.Patches.HarmonyHelpers;

namespace PulsarPluginLoader.Tests.Patches
{
[TestFixture]
class PatchBySequenceTests
{
private static bool AreEqualSequences(IEnumerable<CodeInstruction> first, IEnumerable<CodeInstruction> second)
{
if (first.Count() != second.Count())
{
return false;
}

for (int i = 0; i < first.Count(); i++)
{
CodeInstruction a = first.ElementAt(i);
CodeInstruction b = second.ElementAt(i);

if (!a.opcode.Equals(b.opcode) && a.operand.Equals(b.operand))
{
return false;
}

}

return true;
}

[Test]
public void CanInsert_Before()
{
List<CodeInstruction> original = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

List<CodeInstruction> targetSequence = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

List<CodeInstruction> patchSequence = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldc_R4, 12),
new CodeInstruction(OpCodes.Ldc_R4, 18),
};

List<CodeInstruction> actual = PatchBySequence(original, targetSequence, patchSequence, PatchMode.BEFORE).ToList();

List<CodeInstruction> expected = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldc_R4, 12),
new CodeInstruction(OpCodes.Ldc_R4, 18),
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

Assert.IsTrue(AreEqualSequences(expected, actual));
}

[Test]
public void CanInsert_After()
{
List<CodeInstruction> original = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

List<CodeInstruction> targetSequence = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

List<CodeInstruction> patchSequence = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldc_R4, 12),
new CodeInstruction(OpCodes.Ldc_R4, 18),
};

List<CodeInstruction> actual = PatchBySequence(original, targetSequence, patchSequence, PatchMode.AFTER).ToList();

List<CodeInstruction> expected = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
new CodeInstruction(OpCodes.Ldc_R4, 12),
new CodeInstruction(OpCodes.Ldc_R4, 18),
};

Assert.IsTrue(AreEqualSequences(expected, actual));
}

[Test]
public void CanReplace_SameLength()
{
List<CodeInstruction> original = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

List<CodeInstruction> targetSequence = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

List<CodeInstruction> patchSequence = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldc_R4, 12),
new CodeInstruction(OpCodes.Ldc_R4, 18),
};

List<CodeInstruction> actual = PatchBySequence(original, targetSequence, patchSequence, PatchMode.REPLACE).ToList();

List<CodeInstruction> expected = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Nop),
new CodeInstruction(OpCodes.Ldc_R4, 12),
new CodeInstruction(OpCodes.Ldc_R4, 18),
};

Assert.IsTrue(AreEqualSequences(expected, actual));
}

[Test]
public void CanReplace_SmallerInsert()
{
List<CodeInstruction> original = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

List<CodeInstruction> targetSequence = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

List<CodeInstruction> patchSequence = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldc_R4, 12)
};

List<CodeInstruction> actual = PatchBySequence(original, targetSequence, patchSequence, PatchMode.REPLACE).ToList();

List<CodeInstruction> expected = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Nop),
new CodeInstruction(OpCodes.Ldc_R4, 12)
};

Assert.IsTrue(AreEqualSequences(expected, actual));
}

[Test]
public void CanReplace_LargerInsert()
{
List<CodeInstruction> original = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

List<CodeInstruction> targetSequence = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldc_R4, 0),
new CodeInstruction(OpCodes.Ldc_R4, 6),
};

List<CodeInstruction> patchSequence = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldc_R4, 12),
new CodeInstruction(OpCodes.Ldc_R4, 18),
new CodeInstruction(OpCodes.Ldc_R4, 24),
};

List<CodeInstruction> actual = PatchBySequence(original, targetSequence, patchSequence, PatchMode.REPLACE).ToList();

List<CodeInstruction> expected = new List<CodeInstruction>()
{
new CodeInstruction(OpCodes.Ldfld, AccessTools.Field(typeof(SampleClass), "IntField")),
new CodeInstruction(OpCodes.Nop),
new CodeInstruction(OpCodes.Ldc_R4, 12),
new CodeInstruction(OpCodes.Ldc_R4, 18),
new CodeInstruction(OpCodes.Ldc_R4, 24),
};

Assert.IsTrue(AreEqualSequences(expected, actual));
}
}
}
18 changes: 18 additions & 0 deletions PulsarPluginLoader.Tests/Patches/SampleClass.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace PulsarPluginLoader.Tests.Patches
{
class SampleClass
{
public static int StaticIntField = 11;

public int IntField = 36;

public void VoidMethod() { }

public static void StaticVoidMethod() { }
}
}
3 changes: 2 additions & 1 deletion PulsarPluginLoader.Tests/PulsarPluginLoader.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="PatchBySequenceTests.cs" />
<Compile Include="Patches\PatchBySequenceTests.cs" />
<Compile Include="Patches\SampleClass.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
Expand Down
1 change: 0 additions & 1 deletion PulsarPluginLoader/Patches/GameVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,5 @@ static void Postfix(PLNetworkManager __instance)

__instance.VersionString = $"{__instance.VersionString}\nPPL {fvi.FileVersion}i";
}

}
}
5 changes: 3 additions & 2 deletions PulsarPluginLoader/Patches/HarmonyHelpers.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Harmony;
using Harmony.ILCopying;
using PulsarPluginLoader.Utils;
using System;
using System.Collections.Generic;
Expand Down Expand Up @@ -28,8 +29,8 @@ public static IEnumerable<CodeInstruction> PatchBySequence(IEnumerable<CodeInstr

for (int x = 1; x < targetSize && foundTargetSequence; x++)
{
foundTargetSequence = newInstructions[i + x].opcode == targetSequence.ElementAt(x).opcode
&& newInstructions[i + x].operand == targetSequence.ElementAt(x).operand;
foundTargetSequence = newInstructions[i + x].opcode.Equals(targetSequence.ElementAt(x).opcode)
&& newInstructions[i + x].operand.Equals(targetSequence.ElementAt(x).operand);
}

if (foundTargetSequence)
Expand Down
2 changes: 1 addition & 1 deletion PulsarPluginLoader/Patches/PhotonProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstructi
new CodeInstruction(OpCodes.Call, AccessTools.Method(typeof(PhotonProperties), "UpdatePlayerList")),
};

return HarmonyHelpers.PatchBySequence(instructions, targetSequence, injectedSequence).ToList();
return HarmonyHelpers.PatchBySequence(instructions, targetSequence, injectedSequence);
}
}

Expand Down

0 comments on commit 3657d52

Please sign in to comment.