Auto: s7-d1 — TIA Portal CSV + STEP 7 Classic AWL symbol import
Closes #299
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
using System.IO;
|
||||
using Shouldly;
|
||||
using Xunit;
|
||||
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests.S7_1500;
|
||||
using ZB.MOM.WW.OtOpcUa.Driver.S7.SymbolImport;
|
||||
|
||||
namespace ZB.MOM.WW.OtOpcUa.Driver.S7.IntegrationTests.SymbolImport;
|
||||
|
||||
/// <summary>
|
||||
/// PR-S7-D1 / #299 — golden-fixture integration test. Loads the canonical TIA Portal
|
||||
/// CSV export shipped under <c>Fixtures/sample_tia_export.csv</c>, materialises a
|
||||
/// driver-options object via <c>AddTiaCsvImport</c>, then exercises the runtime read
|
||||
/// path against the python-snap7 simulator.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The fixture's address layout (<c>%MW0</c>, <c>%DB1.DBW10</c>, <c>%DB1.DBD20</c>,
|
||||
/// <c>%DB1.DBD30</c>, <c>%DB1.DBX50.3</c>) is deliberately aligned with the seed
|
||||
/// offsets baked into the snap7 S7-1500 profile (<see cref="S7_1500Profile"/>) so
|
||||
/// a successful round-trip proves the importer's address normalisation lands at
|
||||
/// exactly the offsets the simulator seeds — a regression in <c>%</c>-stripping or
|
||||
/// decimal-comma rewriting surfaces here as a read-mismatch, not a flaky timeout.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The test is build-only by default (the assertions run only when the simulator
|
||||
/// fixture reports <c>SkipReason is null</c>) — local dev invokes it with snap7
|
||||
/// running; CI relies on the fixture's auto-skip when no simulator is reachable.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[Collection(Snap7ServerCollection.Name)]
|
||||
[Trait("Category", "Integration")]
|
||||
[Trait("Device", "S7_1500")]
|
||||
public sealed class TiaCsvImportIntegrationTests(Snap7ServerFixture sim)
|
||||
{
|
||||
private static string FixturePath(string name) =>
|
||||
Path.Combine(AppContext.BaseDirectory, "Fixtures", name);
|
||||
|
||||
[Fact]
|
||||
public async Task Driver_imports_csv_then_reads_seeded_tags()
|
||||
{
|
||||
if (sim.SkipReason is not null) Assert.Skip(sim.SkipReason);
|
||||
|
||||
// Start with an empty options object pinned at the simulator's endpoint, then
|
||||
// layer the fixture CSV's tags on top via AddTiaCsvImport. The merge keeps the
|
||||
// endpoint config (Host, Port, CpuType) untouched and adds the imported tags.
|
||||
var baseOptions = new S7DriverOptions
|
||||
{
|
||||
Host = sim.Host,
|
||||
Port = sim.Port,
|
||||
CpuType = global::S7.Net.CpuType.S71500,
|
||||
Timeout = TimeSpan.FromSeconds(5),
|
||||
Probe = new S7ProbeOptions { Enabled = false },
|
||||
Tags = [],
|
||||
};
|
||||
|
||||
var options = baseOptions.AddTiaCsvImport(FixturePath("sample_tia_export.csv"), out var importResult);
|
||||
|
||||
// Fixture has 8 rows: 6 importable + 1 UDT placeholder + 1 HMI-hidden (skipped).
|
||||
importResult.ParsedCount.ShouldBe(7);
|
||||
importResult.SkippedCount.ShouldBe(1);
|
||||
importResult.UdtPlaceholderCount.ShouldBe(1);
|
||||
options.Tags.Count.ShouldBe(7);
|
||||
|
||||
await using var drv = new S7Driver(options, driverInstanceId: "s7-tia-import");
|
||||
await drv.InitializeAsync("{}", TestContext.Current.CancellationToken);
|
||||
|
||||
// Read the seed-aligned tags by their browse-name references. ProbeWord at MW0
|
||||
// doesn't have a snap7 seed (the simulator profile seeds DB1.DBW0 instead), so
|
||||
// we focus on the DB-anchored tags whose offsets match the S7_1500Profile seeds.
|
||||
var snapshots = await drv.ReadAsync(
|
||||
["SmokeI16", "SmokeI32", "SmokeF32", "SmokeBool"],
|
||||
TestContext.Current.CancellationToken);
|
||||
|
||||
snapshots.Count.ShouldBe(4);
|
||||
foreach (var s in snapshots) s.StatusCode.ShouldBe(0u, "imported-then-read must succeed end-to-end");
|
||||
|
||||
Convert.ToInt32(snapshots[0].Value).ShouldBe((int)S7_1500Profile.SmokeI16SeedValue);
|
||||
Convert.ToInt32(snapshots[1].Value).ShouldBe(S7_1500Profile.SmokeI32SeedValue);
|
||||
Convert.ToSingle(snapshots[2].Value).ShouldBe(S7_1500Profile.SmokeF32SeedValue, tolerance: 0.0001f);
|
||||
Convert.ToBoolean(snapshots[3].Value).ShouldBeTrue();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user