Files
ScadaBridge/tests/ZB.MOM.WW.ScadaBridge.Transport.Tests/Import/TemplateReferenceResolutionTests.cs
T
Joseph Doherty a13aabc7c3 fix(transport): base-first template reference resolution on import (ScadaBridge#100 item 1)
TemplateLibrary.GetIdByNameAsync was first-row-wins, so a derived slot template
could shadow a same-named base. Now: exact name, base first, derived-only name
only when unique, otherwise unresolved (composition audit says ambiguous).
Tracked-template indexes are base-first too.

Claude-Session: https://claude.ai/code/session_01GT67AEHd2Acv1YPwGfXEoV
2026-11-10 04:38:05 -05:00

71 lines
2.6 KiB
C#

using ZB.MOM.WW.ScadaBridge.Transport.Import;
namespace ZB.MOM.WW.ScadaBridge.Transport.Tests.Import;
/// <summary>
/// ScadaBridge#100 item 1: how a bundle's by-name template reference (composed, base or
/// instance template name) resolves against target templates the import did not stage.
/// Derived (composition-slot) templates carry their slot name and sit outside the filtered
/// unique index, so a name can be held by a base template and any number of derived ones.
/// </summary>
public class TemplateReferenceResolutionTests
{
/// <summary>A base template wins even when a same-named derived slot template has a lower id
/// (the old first-row-wins rule bound the reference to the derived row).</summary>
[Fact]
public void Base_template_wins_over_a_lower_id_derived_template_of_the_same_name()
{
var ids = BundleImporter.ResolveTemplateReferenceIds(new[]
{
(Id: 3, Name: "Motor", IsDerived: true),
(Id: 7, Name: "Motor", IsDerived: false),
(Id: 9, Name: "Motor", IsDerived: true),
});
Assert.Equal(7, ids["Motor"]);
}
/// <summary>A name held by exactly one derived template and no base still resolves to it —
/// composition targets may legitimately be derived templates.</summary>
[Fact]
public void A_unique_derived_only_name_resolves()
{
var ids = BundleImporter.ResolveTemplateReferenceIds(new[]
{
(Id: 4, Name: "Slot1", IsDerived: true),
(Id: 5, Name: "Pump", IsDerived: false),
});
Assert.Equal(4, ids["Slot1"]);
Assert.Equal(5, ids["Pump"]);
}
/// <summary>Several derived templates sharing a name with no base is ambiguous: the name is
/// left unresolved rather than bound to an arbitrary slot owned by another composition.</summary>
[Fact]
public void Several_derived_templates_and_no_base_is_ambiguous_and_unresolved()
{
var ids = BundleImporter.ResolveTemplateReferenceIds(new[]
{
(Id: 2, Name: "Motor", IsDerived: true),
(Id: 6, Name: "Motor", IsDerived: true),
});
Assert.False(ids.ContainsKey("Motor"));
}
/// <summary>References stay exact-name: a case variant is a different key (case-insensitive
/// matching of references is outside this rule).</summary>
[Fact]
public void Matching_is_exact_name()
{
var ids = BundleImporter.ResolveTemplateReferenceIds(new[]
{
(Id: 1, Name: "Pump", IsDerived: false),
});
Assert.False(ids.ContainsKey("pump"));
Assert.Equal(1, ids["Pump"]);
}
}