fix(ablegacy): refuse status-bit writes, decode status bits as 0/1, reject over-long replies, global TNS
This commit is contained in:
+55
-1
@@ -255,7 +255,7 @@ public sealed class NativeAbLegacyTagRuntimeTests
|
||||
await using var h = new Harness("slc500", "N7:0").Replies(Words(1));
|
||||
await h.Runtime.ReadAsync(CancellationToken.None);
|
||||
await h.Runtime.ReadAsync(CancellationToken.None);
|
||||
((ushort)(TnsOf(h.Channel.Sent[1]) - TnsOf(h.Channel.Sent[0]))).ShouldBe((ushort)1);
|
||||
TnsOf(h.Channel.Sent[1]).ShouldNotBe(TnsOf(h.Channel.Sent[0]));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -359,6 +359,60 @@ public sealed class NativeAbLegacyTagRuntimeTests
|
||||
ex.Status.ShouldBe(AbStatus.BadReply);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task An_over_long_data_reply_is_TooLarge()
|
||||
{
|
||||
await using var h = new Harness("slc500", "N7:0").Replies(Words(1, 2));
|
||||
var ex = await Should.ThrowAsync<AbTransportException>(() => h.Runtime.ReadAsync(CancellationToken.None));
|
||||
ex.Status.ShouldBe(AbStatus.TooLarge);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("T4:0.DN")]
|
||||
[InlineData("C5:0.CU")]
|
||||
[InlineData("R6:0.EN")]
|
||||
public async Task A_write_to_a_status_bit_sub_element_is_Unsupported_and_sends_nothing(string tag)
|
||||
{
|
||||
await using var h = new Harness("slc500", tag).Replies([]);
|
||||
h.Runtime.EncodeValue(AbLegacyDataType.Bit, null, true);
|
||||
var ex = await Should.ThrowAsync<AbTransportException>(() => h.Runtime.WriteAsync(CancellationToken.None));
|
||||
ex.Status.ShouldBe(AbStatus.Unsupported);
|
||||
h.Channel.SentCount.ShouldBe(0);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("T4:0.PRE")]
|
||||
[InlineData("T4:0.ACC")]
|
||||
[InlineData("R6:0.LEN")]
|
||||
[InlineData("R6:0.POS")]
|
||||
public async Task A_write_to_a_word_sub_element_still_works(string tag)
|
||||
{
|
||||
await using var h = new Harness("slc500", tag).Replies([]);
|
||||
h.Runtime.EncodeValue(AbLegacyDataType.Int, null, 9);
|
||||
await h.Runtime.WriteAsync(CancellationToken.None);
|
||||
h.Channel.SentCount.ShouldBe(1);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(AbLegacyDataType.Bit)]
|
||||
[InlineData(AbLegacyDataType.Int)]
|
||||
[InlineData(AbLegacyDataType.AnalogInt)]
|
||||
[InlineData(AbLegacyDataType.Long)]
|
||||
[InlineData(AbLegacyDataType.TimerElement)]
|
||||
[InlineData(AbLegacyDataType.CounterElement)]
|
||||
[InlineData(AbLegacyDataType.ControlElement)]
|
||||
public async Task Every_scalar_type_decodes_a_status_bit_sub_element_as_that_bit(AbLegacyDataType type)
|
||||
{
|
||||
foreach (var (word, expectSet) in new[] { ((ushort)0xE000, true), ((ushort)0x0000, false) })
|
||||
{
|
||||
await using var h = new Harness("slc500", "T4:0.DN").Replies(Words(word));
|
||||
await h.Runtime.ReadAsync(CancellationToken.None);
|
||||
var v = h.Runtime.DecodeValue(type, null);
|
||||
if (type == AbLegacyDataType.Bit) v.ShouldBe(expectSet);
|
||||
else v.ShouldBe(expectSet ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task A_short_data_reply_is_BadReply()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user