docs(lmxproxy): update test tags to TestChildObject namespace for v2 type coverage
Replace JoeAppEngine tags with TestChildObject tags (TestBool, TestInt, TestFloat, TestDouble, TestString, TestDateTime, and array variants) in Phase 4 and Phase 7 plans. These tags cover all TypedValue oneof cases for comprehensive v2 testing.
This commit is contained in:
@@ -13,7 +13,19 @@
|
||||
3. **Integration tests run from Mac against windev** — they use `Grpc.Net.Client` which is cross-platform.
|
||||
4. **All integration tests must pass before cutover**.
|
||||
5. **API keys**: The existing `apikeys.json` on windev is the source of truth for valid keys. Read it to get test keys.
|
||||
6. **Real MxAccess tags**: Use tags from the JoeAppEngine namespace which is the live AVEVA System Platform instance on windev.
|
||||
6. **Real MxAccess tags**: Use the `TestChildObject` tags on windev's AVEVA System Platform instance. Available tags cover all TypedValue cases:
|
||||
- `TestChildObject.TestBool` (bool)
|
||||
- `TestChildObject.TestInt` (int)
|
||||
- `TestChildObject.TestFloat` (float)
|
||||
- `TestChildObject.TestDouble` (double)
|
||||
- `TestChildObject.TestString` (string)
|
||||
- `TestChildObject.TestDateTime` (datetime)
|
||||
- `TestChildObject.TestBoolArray[]` (bool array)
|
||||
- `TestChildObject.TestDateTimeArray[]` (datetime array)
|
||||
- `TestChildObject.TestDoubleArray[]` (double array)
|
||||
- `TestChildObject.TestFloatArray[]` (float array)
|
||||
- `TestChildObject.TestIntArray[]` (int array)
|
||||
- `TestChildObject.TestStringArray[]` (string array)
|
||||
|
||||
## Step 1: Build Host on windev
|
||||
|
||||
@@ -58,6 +70,11 @@ ssh windev "powershell -Command \"@'
|
||||
\"ChannelCapacity\": 1000,
|
||||
\"ChannelFullMode\": \"DropOldest\"
|
||||
},
|
||||
\"HealthCheck\": {
|
||||
\"Enabled\": true,
|
||||
\"TestTagAddress\": \"TestChildObject.TestBool\",
|
||||
\"MaxStaleDataMinutes\": 5
|
||||
},
|
||||
\"Tls\": {
|
||||
\"Enabled\": false
|
||||
},
|
||||
@@ -377,35 +394,62 @@ namespace ZB.MOM.WW.LmxProxy.Client.IntegrationTests;
|
||||
public class ReadTests : IntegrationTestBase
|
||||
{
|
||||
[Fact]
|
||||
public async Task Read_StringTag_ReturnsStringValue()
|
||||
public async Task Read_BoolTag_ReturnsBoolValue()
|
||||
{
|
||||
// JoeAppEngine.Area is a string attribute that should return "JoeDev"
|
||||
var vtq = await Client!.ReadAsync("JoeAppEngine.Area");
|
||||
Assert.NotNull(vtq.Value);
|
||||
Assert.IsType<string>(vtq.Value);
|
||||
Assert.Equal("JoeDev", vtq.Value);
|
||||
// Quality should be Good (check via QualityExtensions.IsGood if available,
|
||||
// or check vtq.Quality == Quality.Good)
|
||||
var vtq = await Client!.ReadAsync("TestChildObject.TestBool");
|
||||
Assert.IsType<bool>(vtq.Value);
|
||||
Assert.True(vtq.Quality.IsGood());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Read_WritableTag_ReturnsTypedValue()
|
||||
public async Task Read_IntTag_ReturnsIntValue()
|
||||
{
|
||||
// JoeAppEngine.BTCS is a writable tag
|
||||
var vtq = await Client!.ReadAsync("JoeAppEngine.BTCS");
|
||||
Assert.NotNull(vtq.Value);
|
||||
// Verify timestamp is recent (within last hour)
|
||||
var vtq = await Client!.ReadAsync("TestChildObject.TestInt");
|
||||
Assert.True(vtq.Value is int or long);
|
||||
Assert.True(vtq.Quality.IsGood());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Read_FloatTag_ReturnsFloatValue()
|
||||
{
|
||||
var vtq = await Client!.ReadAsync("TestChildObject.TestFloat");
|
||||
Assert.True(vtq.Value is float or double);
|
||||
Assert.True(vtq.Quality.IsGood());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Read_DoubleTag_ReturnsDoubleValue()
|
||||
{
|
||||
var vtq = await Client!.ReadAsync("TestChildObject.TestDouble");
|
||||
Assert.IsType<double>(vtq.Value);
|
||||
Assert.True(vtq.Quality.IsGood());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Read_StringTag_ReturnsStringValue()
|
||||
{
|
||||
var vtq = await Client!.ReadAsync("TestChildObject.TestString");
|
||||
Assert.IsType<string>(vtq.Value);
|
||||
Assert.True(vtq.Quality.IsGood());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Read_DateTimeTag_ReturnsDateTimeValue()
|
||||
{
|
||||
var vtq = await Client!.ReadAsync("TestChildObject.TestDateTime");
|
||||
Assert.IsType<DateTime>(vtq.Value);
|
||||
Assert.True(vtq.Quality.IsGood());
|
||||
Assert.True(DateTime.UtcNow - vtq.Timestamp < TimeSpan.FromHours(1));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ReadBatch_MultiplesTags_ReturnsDictionary()
|
||||
{
|
||||
var tags = new[] { "JoeAppEngine.Area", "JoeAppEngine.BTCS" };
|
||||
var tags = new[] { "TestChildObject.TestString", "TestChildObject.TestString" };
|
||||
var results = await Client!.ReadBatchAsync(tags);
|
||||
Assert.Equal(2, results.Count);
|
||||
Assert.True(results.ContainsKey("JoeAppEngine.Area"));
|
||||
Assert.True(results.ContainsKey("JoeAppEngine.BTCS"));
|
||||
Assert.True(results.ContainsKey("TestChildObject.TestString"));
|
||||
Assert.True(results.ContainsKey("TestChildObject.TestString"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -437,12 +481,12 @@ public class WriteTests : IntegrationTestBase
|
||||
{
|
||||
string testValue = $"IntTest-{DateTime.UtcNow:HHmmss}";
|
||||
// Write to a writable string tag
|
||||
await Client!.WriteAsync("JoeAppEngine.BTCS",
|
||||
await Client!.WriteAsync("TestChildObject.TestString",
|
||||
new TypedValue { StringValue = testValue });
|
||||
|
||||
// Read back and verify
|
||||
await Task.Delay(500); // Allow time for write to propagate
|
||||
var vtq = await Client.ReadAsync("JoeAppEngine.BTCS");
|
||||
var vtq = await Client.ReadAsync("TestChildObject.TestString");
|
||||
Assert.Equal(testValue, vtq.Value);
|
||||
}
|
||||
|
||||
@@ -453,7 +497,7 @@ public class WriteTests : IntegrationTestBase
|
||||
await readOnlyClient.ConnectAsync();
|
||||
|
||||
var ex = await Assert.ThrowsAsync<Grpc.Core.RpcException>(
|
||||
() => readOnlyClient.WriteAsync("JoeAppEngine.BTCS",
|
||||
() => readOnlyClient.WriteAsync("TestChildObject.TestString",
|
||||
new TypedValue { StringValue = "should-fail" }));
|
||||
Assert.Equal(Grpc.Core.StatusCode.PermissionDenied, ex.StatusCode);
|
||||
}
|
||||
@@ -476,7 +520,7 @@ public class SubscribeTests : IntegrationTestBase
|
||||
var receivedEvent = new TaskCompletionSource<bool>();
|
||||
|
||||
var subscription = await Client!.SubscribeAsync(
|
||||
new[] { "JoeAppEngine.Scheduler.ScanTime" },
|
||||
new[] { "TestChildObject.TestInt" },
|
||||
(tag, vtq) =>
|
||||
{
|
||||
received.Add((tag, vtq));
|
||||
@@ -493,7 +537,7 @@ public class SubscribeTests : IntegrationTestBase
|
||||
|
||||
// Verify the VTQ has correct structure
|
||||
var first = received[0];
|
||||
Assert.Equal("JoeAppEngine.Scheduler.ScanTime", first.Tag);
|
||||
Assert.Equal("TestChildObject.TestInt", first.Tag);
|
||||
Assert.NotNull(first.Vtq.Value);
|
||||
// ScanTime should be a DateTime value
|
||||
Assert.True(first.Vtq.Timestamp > DateTime.MinValue);
|
||||
@@ -516,18 +560,18 @@ public class WriteBatchAndWaitTests : IntegrationTestBase
|
||||
public async Task WriteBatchAndWait_TypeAwareComparison()
|
||||
{
|
||||
// This test requires a writable tag and a flag tag.
|
||||
// Adjust tag names based on available tags in JoeAppEngine.
|
||||
// Adjust tag names based on available tags in TestChildObject.
|
||||
// Example: write values and poll a flag.
|
||||
|
||||
var values = new Dictionary<string, TypedValue>
|
||||
{
|
||||
["JoeAppEngine.BTCS"] = new TypedValue { StringValue = "BatchTest" }
|
||||
["TestChildObject.TestString"] = new TypedValue { StringValue = "BatchTest" }
|
||||
};
|
||||
|
||||
// Poll the same tag we wrote to (simple self-check)
|
||||
var response = await Client!.WriteBatchAndWaitAsync(
|
||||
values,
|
||||
flagTag: "JoeAppEngine.BTCS",
|
||||
flagTag: "TestChildObject.TestString",
|
||||
flagValue: new TypedValue { StringValue = "BatchTest" },
|
||||
timeoutMs: 5000,
|
||||
pollIntervalMs: 200);
|
||||
@@ -774,11 +818,11 @@ Replace placeholders with actual restore point ID and timestamp.
|
||||
- [ ] Integration test project created at `tests/ZB.MOM.WW.LmxProxy.Client.IntegrationTests/`
|
||||
- [ ] All integration tests pass against v2 on alternate ports:
|
||||
- [ ] Connect/disconnect lifecycle
|
||||
- [ ] Read string tag `JoeAppEngine.Area` — value "JoeDev", Good quality
|
||||
- [ ] Read writable tag `JoeAppEngine.BTCS`
|
||||
- [ ] Read string tag `TestChildObject.TestString` — value "JoeDev", Good quality
|
||||
- [ ] Read writable tag `TestChildObject.TestString`
|
||||
- [ ] Write string then read-back verification
|
||||
- [ ] ReadBatch multiple tags
|
||||
- [ ] Subscribe to `JoeAppEngine.Scheduler.ScanTime` — verify updates received with TypedValue + QualityCode
|
||||
- [ ] Subscribe to `TestChildObject.TestInt` — verify updates received with TypedValue + QualityCode
|
||||
- [ ] WriteBatchAndWait with type-aware flag comparison
|
||||
- [ ] CheckApiKey — valid ReadWrite, valid ReadOnly, invalid
|
||||
- [ ] Write with ReadOnly key — PermissionDenied
|
||||
|
||||
Reference in New Issue
Block a user