feat(transport): import name-map plumbing via CLI + ManagementActor (M8 D3)

This commit is contained in:
Joseph Doherty
2026-06-18 07:08:33 -04:00
parent d974477e87
commit 565d53d0fe
5 changed files with 721 additions and 7 deletions
@@ -137,4 +137,100 @@ public class BundleCommandsStreamingTests : IDisposable
Assert.Empty(parse.Errors);
}
// ---- M8 (D3): --map-site / --map-connection spec parsing ----------------
[Fact]
public void ParseSiteMappings_Null_ReturnsEmpty()
{
Assert.Empty(BundleCommands.ParseSiteMappings(null));
}
[Fact]
public void ParseSiteMappings_SrcEqualsDst_MapsToExisting()
{
var specs = BundleCommands.ParseSiteMappings(new[] { "NORTH-01=PLANT-A" });
var spec = Assert.Single(specs);
Assert.Equal("NORTH-01", spec.SourceSiteIdentifier);
Assert.Equal("PLANT-A", spec.TargetSiteIdentifier);
}
[Theory]
[InlineData("NORTH-01")] // no '=' part -> create-new
[InlineData("NORTH-01=")] // empty rhs -> create-new
[InlineData("NORTH-01= ")] // whitespace rhs -> create-new
public void ParseSiteMappings_NoTarget_MeansCreateNew(string token)
{
var specs = BundleCommands.ParseSiteMappings(new[] { token });
var spec = Assert.Single(specs);
Assert.Equal("NORTH-01", spec.SourceSiteIdentifier);
Assert.Null(spec.TargetSiteIdentifier);
}
[Fact]
public void ParseSiteMappings_Repeated_AccumulatesAll()
{
var specs = BundleCommands.ParseSiteMappings(new[] { "A=X", "B" });
Assert.Equal(2, specs.Count);
Assert.Equal("X", specs[0].TargetSiteIdentifier);
Assert.Null(specs[1].TargetSiteIdentifier);
}
[Fact]
public void ParseSiteMappings_EmptySource_Throws()
{
Assert.Throws<FormatException>(() => BundleCommands.ParseSiteMappings(new[] { "=PLANT-A" }));
}
[Fact]
public void ParseConnectionMappings_SrcEqualsDst_MapsToExisting()
{
var specs = BundleCommands.ParseConnectionMappings(new[] { "NORTH-01/OpcA=OpcLive" });
var spec = Assert.Single(specs);
Assert.Equal("NORTH-01", spec.SourceSiteIdentifier);
Assert.Equal("OpcA", spec.SourceConnectionName);
Assert.Equal("OpcLive", spec.TargetConnectionName);
}
[Theory]
[InlineData("NORTH-01/OpcA")] // no '=' part -> create-new
[InlineData("NORTH-01/OpcA=")] // empty rhs -> create-new
public void ParseConnectionMappings_NoTarget_MeansCreateNew(string token)
{
var specs = BundleCommands.ParseConnectionMappings(new[] { token });
var spec = Assert.Single(specs);
Assert.Equal("NORTH-01", spec.SourceSiteIdentifier);
Assert.Equal("OpcA", spec.SourceConnectionName);
Assert.Null(spec.TargetConnectionName);
}
[Theory]
[InlineData("OpcA")] // missing site/name shape
[InlineData("NORTH-01/")] // empty connection name
[InlineData("/OpcA")] // empty site
public void ParseConnectionMappings_MalformedSource_Throws(string token)
{
Assert.Throws<FormatException>(() => BundleCommands.ParseConnectionMappings(new[] { token }));
}
[Fact]
public void BundleImport_MapAndCreateMissingFlags_ParseWithoutError()
{
var url = new Option<string>("--url") { Recursive = true };
var format = new Option<string>("--format") { Recursive = true };
var username = new Option<string>("--username") { Recursive = true };
var password = new Option<string>("--password") { Recursive = true };
var bundle = BundleCommands.Build(url, format, username, password);
var parse = bundle.Parse(new[]
{
"import", "--input", "/tmp/in.scadabundle",
"--map-site", "NORTH-01=PLANT-A",
"--map-connection", "NORTH-01/OpcA=OpcLive",
"--create-missing-sites",
"--create-missing-connections",
});
Assert.Empty(parse.Errors);
}
}