using System; using System.IO; using System.Reflection; using Xunit; namespace TeslaConsole.DiffTests { /// /// Shared per-test-class fixture that spins up one child AppDomain per assembly /// (original + recovered), each rooted at that assembly's own directory so the CLR /// probes for any dependencies next to it. The Invoker proxy in each domain loads /// and exercises that assembly. /// public sealed class DifferentialFixture : IDisposable { private readonly AppDomain _originalDomain; private readonly AppDomain _recoveredDomain; public Invoker Original { get; } public Invoker Recovered { get; } public DifferentialFixture() { Assert.True(File.Exists(AssemblyPaths.OriginalExe), "Original baseline not found: " + AssemblyPaths.OriginalExe); Assert.True(File.Exists(AssemblyPaths.RecoveredExe), "Recovered build not found (build TeslaConsole.csproj -c Release first): " + AssemblyPaths.RecoveredExe); _originalDomain = CreateDomain("Original", AssemblyPaths.OriginalExe); _recoveredDomain = CreateDomain("Recovered", AssemblyPaths.RecoveredExe); Original = CreateInvoker(_originalDomain, AssemblyPaths.OriginalExe); Recovered = CreateInvoker(_recoveredDomain, AssemblyPaths.RecoveredExe); } private static AppDomain CreateDomain(string name, string exePath) { var setup = new AppDomainSetup { ApplicationBase = Path.GetDirectoryName(exePath), }; return AppDomain.CreateDomain("TeslaDiff_" + name, null, setup); } private static Invoker CreateInvoker(AppDomain domain, string exePath) { // Probe directory = recovered output, which ships every dependency DLL. string probeDir = Path.GetDirectoryName(AssemblyPaths.RecoveredExe); return (Invoker)domain.CreateInstanceFromAndUnwrap( typeof(Invoker).Assembly.Location, typeof(Invoker).FullName, false, BindingFlags.Default, null, new object[] { exePath, probeDir }, null, null); } /// Run a case in both domains and return (original, recovered). public (string Original, string Recovered) RunBoth(string caseName, params string[] args) { return (Original.Run(caseName, args), Recovered.Run(caseName, args)); } public void Dispose() { if (_originalDomain != null) AppDomain.Unload(_originalDomain); if (_recoveredDomain != null) AppDomain.Unload(_recoveredDomain); } } }