using System; using Xunit; namespace TeslaConsole.DiffTests { /// /// For every input below, the original and the recovered build must return the /// exact same result. Each [Theory] case runs the same method in both assemblies /// (in their own AppDomains) and asserts byte-for-byte string equality. /// public class BehavioralEquivalenceTests : IClassFixture { private readonly DifferentialFixture _fx; public BehavioralEquivalenceTests(DifferentialFixture fx) => _fx = fx; private void AssertSame(string caseName, params string[] args) { var (original, recovered) = _fx.RunBoth(caseName, args); Assert.Equal(original, recovered); // Guard against both silently throwing the same way for a case that should succeed. Assert.False(original == null, $"{caseName}({string.Join(",", args)}) returned null from both assemblies"); } [Fact] public void Harness_Distinguishes_Different_Outputs() { // Negative control: a passing suite must be capable of seeing a difference. // Same method, different inputs, must yield different results in each assembly. string ninetySec = (90L * TimeSpan.TicksPerSecond).ToString(); var zero = _fx.Original.Run("GetTimeString", new[] { "0" }); var ninety = _fx.Original.Run("GetTimeString", new[] { ninetySec }); Assert.NotEqual(zero, ninety); var rZero = _fx.Recovered.Run("GetTimeString", new[] { "0" }); var rNinety = _fx.Recovered.Run("GetTimeString", new[] { ninetySec }); Assert.NotEqual(rZero, rNinety); } [Fact] public void Loaded_Assemblies_Are_The_Expected_Builds() { // The original is the untouched 4.11.3.37076 baseline; the recovered build is // the modernized line, intentionally bumped to 4.11.4.x (same assembly name, // new version). Both must be TeslaConsole — guards against testing the wrong files. Assert.Contains("TeslaConsole", _fx.Original.AssemblyFullName); Assert.Contains("TeslaConsole", _fx.Recovered.AssemblyFullName); Assert.Contains("4.11.3.37076", _fx.Original.AssemblyFullName); Assert.Contains("4.11.4.3", _fx.Recovered.AssemblyFullName); } // ---- RPStrings.GetTimeString: mm:ss formatting with 0.5s rounding ---- [Theory] [InlineData(0L)] // 0s -> 00:00 [InlineData(4_000_000L)] // 0.4s -> rounds down [InlineData(5_000_000L)] // 0.5s -> rounds up to 1s [InlineData(6_000_000L)] // 0.6s [InlineData(595_000_000L)] // 59.5s -> rolls to 01:00 [InlineData(600_000_000L)] // 60s -> 01:00 [InlineData(900_000_000L)] // 90s -> 01:30 [InlineData(5_990_000_000L)] // 599s [InlineData(6_000_000_000L)] // 600s -> 10:00 [InlineData(36_000_000_000L)] // 3600s -> 60:00 [InlineData(-50_000_000L)] // negative [InlineData(864_000_000_000L)] // 1 day public void GetTimeString_Matches(long ticks) => AssertSame("GetTimeString", ticks.ToString()); // ---- HostTypeHelper.Parse(...).ToString() including invalid input ---- [Theory] [InlineData("Game Machine")] [InlineData("Mission Review")] [InlineData("Console")] [InlineData("GameMachineHostType")] [InlineData("MissionReviewHostType")] [InlineData("ConsoleHostType")] [InlineData("console")] // case-sensitive: should throw in both [InlineData("Nonsense")] // invalid: ArgumentException in both [InlineData("")] // empty public void HostTypeParse_Matches(string input) => AssertSame("HostTypeParse", input); // ---- PlasmaBitmaps.ConvertBitmap: 1bpp packing of a known pixel pattern ---- [Theory] [InlineData(8, 8, 0)] [InlineData(8, 8, 1)] [InlineData(8, 8, 2)] [InlineData(16, 16, 0)] [InlineData(16, 16, 3)] [InlineData(32, 8, 5)] [InlineData(7, 8, 0)] // width not multiple of 8 -> throws in both [InlineData(8, 7, 0)] // height not multiple of 8 -> throws in both public void ConvertBitmap_Matches(int width, int height, int seed) => AssertSame("ConvertBitmap", width.ToString(), height.ToString(), seed.ToString()); // ---- PlasmaBitmaps.GenerateString: full GDI text -> 1bpp pipeline ---- [Theory] [InlineData(128, 32, "Microsoft Sans Serif", "RED")] [InlineData(64, 16, "Microsoft Sans Serif", "RED")] [InlineData(128, 32, "Microsoft Sans Serif", "1")] [InlineData(128, 32, "Microsoft Sans Serif", "ABCDEFGH")] [InlineData(128, 32, "Microsoft Sans Serif", "")] [InlineData(128, 32, "Arial", "GO")] public void GenerateString_Matches(int width, int height, string font, string text) => AssertSame("GenerateString", width.ToString(), height.ToString(), font, text); // ---- RedPlanet RPMap / RPVehicle XML parsing ---- [Theory] [InlineData("")] [InlineData("")] // no image attr [InlineData("")] // empty values public void RPMapParse_Matches(string xml) => AssertSame("RPMapParse", xml); [Theory] [InlineData("")] [InlineData("")] public void RPVehicleParse_Matches(string xml) => AssertSame("RPVehicleParse", xml); // ---- SiteManagement well-known application GUIDs (constants) ---- [Theory] [InlineData("RPAppGuid")] [InlineData("RPMRAppGuid")] [InlineData("RPLCAppGuid")] [InlineData("MW4AppGuid")] [InlineData("MW4LCAppGuid")] public void SiteManagementGuid_Matches(string fieldName) => AssertSame("SiteManagementGuid", fieldName); // ---- Tuple.Create generic factory ---- [Theory] [InlineData("1", "alpha")] [InlineData("-7", "")] public void TupleCreate_Matches(string a, string b) => AssertSame("TupleCreate", a, b); } }