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:
Joseph Doherty
2026-05-17 01:55:28 -04:00
parent 69f02fed7f
commit a25593a9c6
1044 changed files with 365 additions and 343 deletions

View File

@@ -0,0 +1,72 @@
using Shouldly;
using Xunit;
namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.Tests;
[Trait("Category", "Unit")]
public sealed class AbCipUdtMemberLayoutTests
{
[Fact]
public void Packed_Atomics_Get_Natural_Alignment_Offsets()
{
// DInt (4 align) + Real (4) + Int (2) + LInt (8 — forces 2-byte pad before it)
var members = new[]
{
new AbCipStructureMember("A", AbCipDataType.DInt),
new AbCipStructureMember("B", AbCipDataType.Real),
new AbCipStructureMember("C", AbCipDataType.Int),
new AbCipStructureMember("D", AbCipDataType.LInt),
};
var offsets = AbCipUdtMemberLayout.TryBuild(members);
offsets.ShouldNotBeNull();
offsets!["A"].ShouldBe(0);
offsets["B"].ShouldBe(4);
offsets["C"].ShouldBe(8);
// cursor at 10 after Int; LInt needs 8-byte alignment → pad to 16
offsets["D"].ShouldBe(16);
}
[Fact]
public void SInt_Packed_Without_Padding()
{
var members = new[]
{
new AbCipStructureMember("X", AbCipDataType.SInt),
new AbCipStructureMember("Y", AbCipDataType.SInt),
new AbCipStructureMember("Z", AbCipDataType.SInt),
};
var offsets = AbCipUdtMemberLayout.TryBuild(members);
offsets!["X"].ShouldBe(0);
offsets["Y"].ShouldBe(1);
offsets["Z"].ShouldBe(2);
}
[Fact]
public void Returns_Null_When_Member_Is_Bool()
{
// BOOL storage in Logix UDTs is packed into a hidden host byte; declaration-only
// layout can't place it. Grouping opts out; per-tag read path handles the member.
var members = new[]
{
new AbCipStructureMember("A", AbCipDataType.DInt),
new AbCipStructureMember("Flag", AbCipDataType.Bool),
};
AbCipUdtMemberLayout.TryBuild(members).ShouldBeNull();
}
[Fact]
public void Returns_Null_When_Member_Is_String_Or_Structure()
{
AbCipUdtMemberLayout.TryBuild(
new[] { new AbCipStructureMember("Name", AbCipDataType.String) }).ShouldBeNull();
AbCipUdtMemberLayout.TryBuild(
new[] { new AbCipStructureMember("Nested", AbCipDataType.Structure) }).ShouldBeNull();
}
[Fact]
public void Returns_Null_On_Empty_Members()
{
AbCipUdtMemberLayout.TryBuild(Array.Empty<AbCipStructureMember>()).ShouldBeNull();
}
}