using System.Linq; using System.Text.RegularExpressions; using Xunit; namespace TeslaConsole.DiffTests { /// /// Structural equivalence: every public type and public member exposed by the /// original TeslaConsole.exe must also be exposed, with the same signature, by the /// recovered build. This is a strong "same program" contract that catches any /// dropped, renamed, or re-signatured member introduced during reconstruction. /// /// The enumeration runs inside each assembly's own AppDomain (see DifferentialFixture) /// because the two files share identical assembly identity and cannot coexist in one /// domain. Compiler-generated members are excluded — the README notes those legitimately /// differ between a decompilation and the lost original sources. /// public class PublicApiSurfaceTests : IClassFixture { private readonly DifferentialFixture _fx; public PublicApiSurfaceTests(DifferentialFixture fx) => _fx = fx; [Fact] public void Recovered_Exposes_All_Original_Public_Types() { var original = _fx.Original.GetPublicTypeNames(); var recovered = _fx.Recovered.GetPublicTypeNames(); // Sanity: the original actually yielded a non-trivial surface to compare. Assert.True(original.Length > 20, "Only " + original.Length + " public types enumerated from the original; " + "dependency resolution likely failed."); var missing = original.Except(recovered).OrderBy(s => s).ToArray(); Assert.True(missing.Length == 0, "Public types present in the original but missing from the recovered build:\n " + string.Join("\n ", missing)); } // The recovered build is intentionally a newer assembly version than the // original baseline. A member signature that references a TeslaConsole type as a // generic argument embeds that type's assembly-qualified name — including the // version — so strip Version= stamps before comparing. We compare type NAMES, // not versions. private static string StripVersion(string sig) => Regex.Replace(sig, @", Version=\d+\.\d+\.\d+\.\d+", ""); [Fact] public void Recovered_Exposes_All_Original_Public_Members() { var original = _fx.Original.GetPublicMemberSignatures().Select(StripVersion).ToArray(); var recovered = _fx.Recovered.GetPublicMemberSignatures().Select(StripVersion).ToArray(); Assert.True(original.Length > 100, "Only " + original.Length + " public members enumerated from the original; " + "dependency resolution likely failed."); var missing = original.Except(recovered).OrderBy(s => s).ToArray(); Assert.True(missing.Length == 0, missing.Length + " public member(s) present in the original but missing from the recovered build:\n " + string.Join("\n ", missing.Take(80))); } } }