using System; using System.IO; using System.Linq; using BizTalkPlatformManagementTool.Models; using BizTalkPlatformManagementTool.Services; namespace BizTalkPlatformManagementTool.Tests { internal static class Program { private static int _failed; private static int Main() { Run("RestoreStartsOnlyPreviouslyActiveArtifacts", RestoreStartsOnlyPreviouslyActiveArtifacts); Run("ShutdownStopsOnlyPreviouslyActiveArtifacts", ShutdownStopsOnlyPreviouslyActiveArtifacts); Run("SnapshotComparisonUsesCompositeIdentity", SnapshotComparisonUsesCompositeIdentity); Run("SnapshotServerValidationIsSafe", SnapshotServerValidationIsSafe); Run("JsonStoreReplacesAtomically", JsonStoreReplacesAtomically); Console.WriteLine(_failed == 0 ? "PASS: 5 tests" : "FAIL: " + _failed + " test(s)"); return _failed == 0 ? 0 : 1; } private static void RestoreStartsOnlyPreviouslyActiveArtifacts() { var snapshot = FullSnapshot(); var plan = new BizTalkOperationService(null).CreateRestorePlan(snapshot, "BIZ01"); AssertEqual(4, plan.Steps.Count(x => x.Execute), "restore executable step count"); Assert(plan.Steps.Any(x => x.Kind == "HostInstance" && x.Name == "HostStarted"), "started host missing"); Assert(plan.Steps.Any(x => x.Kind == "SendPort" && x.Name == "SendStarted"), "started send port missing"); Assert(plan.Steps.Any(x => x.Kind == "Orchestration" && x.Name == "OrchStarted"), "started orchestration missing"); AssertEqual("AssemblyName", plan.Steps.Single(x => x.Kind == "Orchestration").QualifierProperty, "orchestration qualifier property"); var receive = plan.Steps.Single(x => x.Kind == "ReceiveLocation"); AssertEqual("ReceivePortName", receive.QualifierProperty, "receive qualifier property"); AssertEqual("RP1", receive.QualifierValue, "receive qualifier value"); Assert(!plan.Steps.Any(x => x.Name == "SendStopped" || x.Name == "SendBound" || x.Name == "ReceiveDisabled"), "inactive artifacts must remain untouched"); } private static void ShutdownStopsOnlyPreviouslyActiveArtifacts() { var plan = new BizTalkOperationService(null).CreateShutdownPlan(FullSnapshot(), "BIZ01"); AssertEqual(4, plan.Steps.Count(x => x.Execute), "shutdown executable step count"); Assert(!plan.Steps.Any(x => x.Name == "SendStopped" || x.Name == "SendBound" || x.Name == "ReceiveDisabled"), "inactive artifacts must not be stopped"); } private static void SnapshotComparisonUsesCompositeIdentity() { var before = EmptySnapshot("BIZ01"); var after = EmptySnapshot("BIZ01"); before.Applications.Add(App("AppA", ArtifactStates.SendPortStarted)); before.Applications.Add(App("AppB", ArtifactStates.SendPortStopped)); after.Applications.Add(App("AppA", ArtifactStates.SendPortStopped)); after.Applications.Add(App("AppB", ArtifactStates.SendPortStopped)); var diff = SnapshotComparer.Compare(before, after); AssertEqual(1, diff.ArtifactDifferences.Count, "composite send port comparison"); AssertEqual("AppA", diff.ArtifactDifferences[0].Application, "changed application"); } private static void SnapshotServerValidationIsSafe() { BizTalkOperationService.ValidateSnapshot(EmptySnapshot("biz01.domain.local"), "BIZ01"); AssertThrows(() => BizTalkOperationService.ValidateSnapshot(EmptySnapshot("BIZ02"), "BIZ01"), "foreign server must be rejected"); } private static void JsonStoreReplacesAtomically() { var directory = Path.Combine(Path.GetTempPath(), "BizTalkPlatformManagementTool.Tests." + Guid.NewGuid().ToString("N")); Directory.CreateDirectory(directory); try { var path = Path.Combine(directory, "state.json"); JsonFileStore.Save(path, EmptySnapshot("BIZ01")); JsonFileStore.Save(path, EmptySnapshot("BIZ02")); var loaded = JsonFileStore.Load(path); AssertEqual("BIZ02", loaded.Server, "atomic replacement payload"); AssertEqual(0, Directory.GetFiles(directory, "*.tmp.*").Length, "temporary files"); } finally { Directory.Delete(directory, true); } } private static BizTalkSnapshot FullSnapshot() { var snapshot = EmptySnapshot("BIZ01"); var app = new ApplicationSnapshot { Application = "Orders" }; app.ReceiveLocations.Add(new ReceiveLocationState { Application = "Orders", Name = "ReceiveEnabled", ReceivePortName = "RP1", Enabled = true }); app.ReceiveLocations.Add(new ReceiveLocationState { Application = "Orders", Name = "ReceiveDisabled", ReceivePortName = "RP1", Enabled = false }); app.SendPorts.Add(new SendPortState { Application = "Orders", Name = "SendStarted", Status = ArtifactStates.SendPortStarted }); app.SendPorts.Add(new SendPortState { Application = "Orders", Name = "SendStopped", Status = ArtifactStates.SendPortStopped }); app.SendPorts.Add(new SendPortState { Application = "Orders", Name = "SendBound", Status = ArtifactStates.SendPortBound }); app.Orchestrations.Add(new OrchestrationState { Application = "Orders", Name = "OrchStarted", OrchestrationStatus = ArtifactStates.OrchestrationStarted, AssemblyName = "Orders.Processes" }); app.Orchestrations.Add(new OrchestrationState { Application = "Orders", Name = "OrchStopped", OrchestrationStatus = ArtifactStates.OrchestrationStopped }); snapshot.Applications.Add(app); snapshot.HostInstances.Add(new HostInstanceState { InstanceName = "HostStarted", Server = "BIZ01", RawState = ArtifactStates.HostStarted }); snapshot.HostInstances.Add(new HostInstanceState { InstanceName = "HostStopped", Server = "BIZ01", RawState = ArtifactStates.HostStopped }); return snapshot; } private static BizTalkSnapshot EmptySnapshot(string server) { return new BizTalkSnapshot { Server = server, CreatedAt = DateTime.Now.ToString("s"), ToolVersion = BizTalkOperationService.Version }; } private static ApplicationSnapshot App(string name, int sendStatus) { var app = new ApplicationSnapshot { Application = name }; app.SendPorts.Add(new SendPortState { Application = name, Name = "SharedName", Status = sendStatus }); return app; } private static void Run(string name, Action test) { try { test(); Console.WriteLine("PASS: " + name); } catch (Exception ex) { _failed++; Console.WriteLine("FAIL: " + name + " - " + ex.Message); } } private static void Assert(bool condition, string message) { if (!condition) throw new InvalidOperationException(message); } private static void AssertEqual(T expected, T actual, string label) { if (!object.Equals(expected, actual)) throw new InvalidOperationException(label + ": expected=" + expected + ", actual=" + actual); } private static void AssertThrows(Action action, string label) where T : Exception { try { action(); } catch (T) { return; } throw new InvalidOperationException(label); } } }