feat(mtconnect): parse the write.enabled config block

This commit is contained in:
Joseph Doherty
2026-08-05 06:13:30 -04:00
parent e784545844
commit b5e39e1f32
4 changed files with 94 additions and 0 deletions
@@ -56,6 +56,20 @@ public sealed class MTConnectDriverOptionsTests
reconnect.BackoffMultiplier.ShouldBeGreaterThan(1.0);
}
/// <summary>
/// Write-back is <b>off unless authored</b>: the driver shipped read-only, and the agent's
/// PUT surface is itself off by default, so a deployment that never mentions <c>write</c>
/// must keep exactly today's behaviour.
/// </summary>
[Fact]
public void Write_defaults_to_disabled()
{
var write = new MTConnectDriverOptions { AgentUri = "http://agent:5000" }.Write;
write.ShouldNotBeNull();
write.Enabled.ShouldBeFalse();
}
/// <summary>
/// <see cref="MTConnectDriverOptions.Tags"/> defaults to an <i>empty</i> collection, never
/// <c>null</c> — a null collection here is an operator-authorable NullReferenceException at
@@ -349,4 +349,51 @@ public sealed class MTConnectFactoryTests
// above) hold for both entry points.
MTConnectDriverFactoryExtensions.CreateInstance("mt1", json).DriverInstanceId.ShouldBe("mt1");
}
/// <summary>
/// The <c>write</c> block reaches the options — the opt-in half of the two-layer gate on
/// write-back (the agent's own <c>AllowPut</c> is the other). Authored <c>true</c> arms it;
/// an authored <c>false</c> and an omitted block are the same thing, and both leave the
/// driver read-only.
/// </summary>
[Fact]
public void Write_section_round_trips_and_defaults_to_disabled_when_absent()
{
MTConnectDriver.ParseOptions(
"mt1", """{ "agentUri": "http://x:5000", "write": { "enabled": true } }""")
.Write.Enabled.ShouldBeTrue();
MTConnectDriver.ParseOptions(
"mt1", """{ "agentUri": "http://x:5000", "write": { "enabled": false } }""")
.Write.Enabled.ShouldBeFalse();
MTConnectDriver.ParseOptions("mt1", """{ "agentUri": "http://x:5000" }""")
.Write.Enabled.ShouldBeFalse();
// The factory shares that parse, so an armed instance is authorable through it too.
MTConnectDriverFactoryExtensions.CreateInstance(
"mt1", """{ "agentUri": "http://x:5000", "write": { "enabled": true } }""")
.DriverInstanceId.ShouldBe("mt1");
}
/// <summary>
/// A malformed <c>write</c> block fails <b>exactly as its siblings do</b> — the whole
/// document is one <c>JsonSerializer.Deserialize</c>, so a non-boolean <c>enabled</c> faults
/// the parse rather than silently defaulting to off. The <c>probe</c> leg is the control: it
/// pins that this is the surrounding convention and not stricter behaviour invented here.
/// </summary>
[Fact]
public void Malformed_write_block_faults_exactly_like_the_sibling_probe_block()
{
Should.Throw<InvalidOperationException>(() => MTConnectDriver.ParseOptions(
"mt1", """{ "agentUri": "http://x:5000", "probe": { "enabled": "yes" } }"""));
Should.Throw<InvalidOperationException>(() => MTConnectDriver.ParseOptions(
"mt1", """{ "agentUri": "http://x:5000", "write": { "enabled": "yes" } }"""));
// A null block is not malformed — the same "omitted means default" reading the sibling
// blocks get, since every DTO property is nullable.
MTConnectDriver.ParseOptions("mt1", """{ "agentUri": "http://x:5000", "write": null }""")
.Write.Enabled.ShouldBeFalse();
}
}