using ZB.MOM.WW.ScadaBridge.Transport.Import;
using ZB.MOM.WW.ScadaBridge.Transport.Serialization;
namespace ZB.MOM.WW.ScadaBridge.Transport.Tests.Import;
///
/// ScadaBridge#118 — orders a bundle's derived templates
/// after their owner and base whatever the bundle order, and reports cycles and malformed
/// derivations as errors.
///
public sealed class DerivedTemplatePlanTests
{
private static TemplateDto Base(string name) =>
new(name, null, null, null, Array.Empty(), Array.Empty(),
Array.Empty(), Array.Empty());
private static TemplateDto Derived(string owner, string[] slots, string baseName, params string[] baseSlots) =>
Base(slots[^1]) with { Derivation = new TemplateDerivationDto(owner, slots, baseName, baseSlots) };
/// Nested slots and cascade slots come after their owner and their (derived) base.
[Fact]
public void Orders_owner_and_base_before_the_derived_template()
{
var plan = DerivedTemplatePlan.Build(new[]
{
Derived("Station", new[] { "P", "M1" }, "Pump", "M1"), // owner Station.P, base Pump.M1
Base("Station"),
Derived("Station", new[] { "P" }, "Pump"),
Derived("Pump", new[] { "M1" }, "Motor"),
});
Assert.Empty(plan.Errors);
var order = plan.Ordered.Select(DerivedTemplatePlan.Key).ToList();
Assert.Equal(3, order.Count);
Assert.True(order.IndexOf("Station.P") < order.IndexOf("Station.P.M1"));
Assert.True(order.IndexOf("Pump.M1") < order.IndexOf("Station.P.M1"));
}
/// A two-node and a one-node cycle are both reported, naming the templates.
[Fact]
public void Cycles_are_errors()
{
var two = DerivedTemplatePlan.Build(new[]
{
Derived("Pump", new[] { "X" }, "Pump", "Y"),
Derived("Pump", new[] { "Y" }, "Pump", "X"),
});
var error = Assert.Single(two.Errors);
Assert.Contains("cycle", error, StringComparison.Ordinal);
Assert.Contains("Pump.X", error, StringComparison.Ordinal);
Assert.Contains("Pump.Y", error, StringComparison.Ordinal);
var self = DerivedTemplatePlan.Build(new[] { Derived("Pump", new[] { "X" }, "Pump", "X") });
Assert.Contains("cycle", Assert.Single(self.Errors), StringComparison.Ordinal);
}
/// Malformed derivations and duplicate identities are errors; base templates are ignored.
[Fact]
public void Malformed_and_duplicate_derivations_are_errors()
{
var plan = DerivedTemplatePlan.Build(new[]
{
Base("Pump"),
Base("M1") with { Derivation = new TemplateDerivationDto("Pump", Array.Empty(), "Motor", Array.Empty()) },
Derived("Pump", new[] { "M2" }, "Motor"),
Derived("Pump", new[] { "M2" }, "Motor"),
});
Assert.Equal(2, plan.Errors.Count);
Assert.Contains(plan.Errors, e => e.Contains("malformed", StringComparison.Ordinal));
Assert.Contains(plan.Errors, e => e.Contains("more than once", StringComparison.Ordinal));
Assert.Equal("Pump", DerivedTemplatePlan.Key(Base("Pump")));
}
}