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>
53 lines
2.6 KiB
C#
53 lines
2.6 KiB
C#
using Xunit;
|
|
|
|
namespace ZB.MOM.WW.OtOpcUa.Driver.AbCip.IntegrationTests;
|
|
|
|
/// <summary>
|
|
/// Runtime gate that lets an integration-test class declare which target-server tier
|
|
/// it requires. Reads <c>AB_SERVER_PROFILE</c> from the environment; tests call
|
|
/// <see cref="SkipUnless"/> with the profile names they support + skip otherwise.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>Two tiers today:</para>
|
|
/// <list type="bullet">
|
|
/// <item><c>abserver</c> (default) — the Dockerized libplctag <c>ab_server</c>
|
|
/// simulator. Covers atomic reads / writes / basic discovery across the four
|
|
/// families (ControlLogix / CompactLogix / Micro800 / GuardLogix).</item>
|
|
/// <item><c>emulate</c> — Rockwell Studio 5000 Logix Emulate on an operator's
|
|
/// Windows box, exposed via <c>AB_SERVER_ENDPOINT</c>. Adds real UDT / ALMD /
|
|
/// AOI / Program-scoped-tag coverage that ab_server can't emulate. Tier-gated
|
|
/// because Emulate is per-seat licensed + Windows-only + manually launched;
|
|
/// a stock `dotnet test` run against ab_server must skip Emulate-only classes
|
|
/// cleanly.</item>
|
|
/// </list>
|
|
/// <para>Tests assert their target tier at the top of each <c>[Fact]</c> /
|
|
/// <c>[Theory]</c> body, mirroring the <c>MODBUS_SIM_PROFILE</c> gate pattern in
|
|
/// <c>tests/.../Modbus.IntegrationTests/DL205/DL205StringQuirkTests.cs</c>.</para>
|
|
/// </remarks>
|
|
public static class AbServerProfileGate
|
|
{
|
|
public const string Default = "abserver";
|
|
public const string Emulate = "emulate";
|
|
|
|
/// <summary>Active profile from <c>AB_SERVER_PROFILE</c>; defaults to <see cref="Default"/>.</summary>
|
|
public static string CurrentProfile =>
|
|
Environment.GetEnvironmentVariable("AB_SERVER_PROFILE") is { Length: > 0 } raw
|
|
? raw.Trim().ToLowerInvariant()
|
|
: Default;
|
|
|
|
/// <summary>
|
|
/// Skip the calling test via <c>Assert.Skip</c> when <see cref="CurrentProfile"/>
|
|
/// isn't in <paramref name="requiredProfiles"/>. Case-insensitive match.
|
|
/// </summary>
|
|
public static void SkipUnless(params string[] requiredProfiles)
|
|
{
|
|
foreach (var p in requiredProfiles)
|
|
if (string.Equals(p, CurrentProfile, StringComparison.OrdinalIgnoreCase))
|
|
return;
|
|
Assert.Skip(
|
|
$"Test requires AB_SERVER_PROFILE in {{{string.Join(", ", requiredProfiles)}}}; " +
|
|
$"current value is '{CurrentProfile}'. " +
|
|
$"Set AB_SERVER_PROFILE=emulate + point AB_SERVER_ENDPOINT at a Logix Emulate instance to run the golden-box-tier tests.");
|
|
}
|
|
}
|