chore: organize solution into module folders (Core/Server/Drivers/Client/Tooling)
Group all 69 projects into category subfolders under src/ and tests/ so the Rider Solution Explorer mirrors the module structure. Folders: Core, Server, Drivers (with a nested Driver CLIs subfolder), Client, Tooling. - Move every project folder on disk with git mv (history preserved as renames). - Recompute relative paths in 57 .csproj files: cross-category ProjectReferences, the lib/ HintPath+None refs in Driver.Historian.Wonderware, and the external mxaccessgw refs in Driver.Galaxy and its test project. - Rebuild ZB.MOM.WW.OtOpcUa.slnx with nested solution folders. - Re-prefix project paths in functional scripts (e2e, compliance, smoke SQL, integration, install). Build green (0 errors); unit tests pass. Docs left for a separate pass. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Entities;
|
||||
using ZB.MOM.WW.OtOpcUa.Configuration.Enums;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.OpcUa;
|
||||
using ZB.MOM.WW.OtOpcUa.Server.Phase7;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Server.Tests.Phase7;
|
||||
|
||||
/// <summary>
|
||||
/// Task #246 — covers the deterministic mapping inside <see cref="Phase7Composer"/>
|
||||
/// that turns <see cref="EquipmentNamespaceContent"/> into the path → fullRef map
|
||||
/// <see cref="DriverFeed.PathToFullRef"/> consumes. Pure function; no DI / DB needed.
|
||||
/// </summary>
|
||||
[Trait("Category", "Unit")]
|
||||
public sealed class Phase7ComposerMappingTests
|
||||
{
|
||||
private static UnsArea Area(string id, string name) =>
|
||||
new() { UnsAreaId = id, ClusterId = "c", Name = name, GenerationId = 1 };
|
||||
|
||||
private static UnsLine Line(string id, string areaId, string name) =>
|
||||
new() { UnsLineId = id, UnsAreaId = areaId, Name = name, GenerationId = 1 };
|
||||
|
||||
private static Equipment Eq(string id, string lineId, string name) => new()
|
||||
{
|
||||
EquipmentRowId = Guid.NewGuid(), GenerationId = 1, EquipmentId = id,
|
||||
EquipmentUuid = Guid.NewGuid(), DriverInstanceId = "drv",
|
||||
UnsLineId = lineId, Name = name, MachineCode = "m",
|
||||
};
|
||||
|
||||
private static Tag T(string id, string name, string fullRef, string equipmentId) => new()
|
||||
{
|
||||
TagRowId = Guid.NewGuid(), GenerationId = 1, TagId = id,
|
||||
DriverInstanceId = "drv", EquipmentId = equipmentId,
|
||||
Name = name, DataType = "Float32",
|
||||
AccessLevel = TagAccessLevel.Read, TagConfig = fullRef,
|
||||
};
|
||||
|
||||
[Fact]
|
||||
public void Maps_tag_to_UNS_path_walker_emits()
|
||||
{
|
||||
var content = new EquipmentNamespaceContent(
|
||||
Areas: [Area("a1", "warsaw")],
|
||||
Lines: [Line("l1", "a1", "oven-line")],
|
||||
Equipment: [Eq("e1", "l1", "oven-3")],
|
||||
Tags: [T("t1", "Temp", "DR.Temp", "e1")]);
|
||||
|
||||
var map = Phase7Composer.MapPathsToFullRefs(content);
|
||||
|
||||
map.ShouldContainKeyAndValue("/warsaw/oven-line/oven-3/Temp", "DR.Temp");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skips_tag_with_null_EquipmentId()
|
||||
{
|
||||
var content = new EquipmentNamespaceContent(
|
||||
[Area("a1", "warsaw")], [Line("l1", "a1", "ol")], [Eq("e1", "l1", "ov")],
|
||||
[T("t1", "Bare", "DR.Bare", null!)]); // SystemPlatform-style orphan
|
||||
|
||||
Phase7Composer.MapPathsToFullRefs(content).ShouldBeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Skips_tag_pointing_at_unknown_Equipment()
|
||||
{
|
||||
var content = new EquipmentNamespaceContent(
|
||||
[Area("a1", "warsaw")], [Line("l1", "a1", "ol")], [Eq("e1", "l1", "ov")],
|
||||
[T("t1", "Lost", "DR.Lost", "e-missing")]);
|
||||
|
||||
Phase7Composer.MapPathsToFullRefs(content).ShouldBeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Maps_multiple_tags_under_same_equipment_distinctly()
|
||||
{
|
||||
var content = new EquipmentNamespaceContent(
|
||||
[Area("a1", "site")], [Line("l1", "a1", "line1")], [Eq("e1", "l1", "cell")],
|
||||
[T("t1", "Temp", "DR.T", "e1"), T("t2", "Pressure", "DR.P", "e1")]);
|
||||
|
||||
var map = Phase7Composer.MapPathsToFullRefs(content);
|
||||
|
||||
map.Count.ShouldBe(2);
|
||||
map["/site/line1/cell/Temp"].ShouldBe("DR.T");
|
||||
map["/site/line1/cell/Pressure"].ShouldBe("DR.P");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Empty_content_yields_empty_map()
|
||||
{
|
||||
Phase7Composer.MapPathsToFullRefs(new EquipmentNamespaceContent([], [], [], []))
|
||||
.ShouldBeEmpty();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user