R0.1 browse probe: StartTagQuery over gRPC takes an OData filter (live)
Probes the 2023 R2 gRPC browse path and records the finding. The front door does NOT hit the 2020 WCF metadata-server-pipe wall. - RetrievalService.StartTagQuery is cracked: the server (CMdServer::StartActiveTagnamesQuery over \.\pipe\aahMetadataServer\console) parses the filter as OData. startswith()/ contains()/eq/empty succeed and return the 8-byte (queryHandle, tagCount); SQL-LIKE "%" and glob "*" fail with "ODataFilter: bad token". Live: 220 Sys* tags counted. - QueryTag (paging) remains: every guessed btRequest returns a constant native error type 4 / code 72 (content-independent) -> framing needs a native capture, not guessing. Adds RE probe helpers Grpc/HistorianGrpcTagClient.ProbeStartTagQuery + ProbeTagQuerySequence, a gated StartTagQuery_OverGrpc_AcceptsODataFilter test, and the finding doc docs/reverse-engineering/grpc-tag-query-odata.md. Browse is not yet wired (QueryTag open). 217 unit tests pass; 5/5 live gRPC tests pass. No tag names/identities committed. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B6mcaT2PjRFKcogzp9UkfC
This commit is contained in:
@@ -86,6 +86,30 @@ public sealed class HistorianGrpcIntegrationTests
|
||||
Assert.True(Enum.IsDefined(metadata.DataType));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task StartTagQuery_OverGrpc_AcceptsODataFilter()
|
||||
{
|
||||
string? host = Environment.GetEnvironmentVariable("HISTORIAN_GRPC_HOST");
|
||||
if (string.IsNullOrWhiteSpace(host) || string.IsNullOrEmpty(Environment.GetEnvironmentVariable("HISTORIAN_USER")))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// R0.1 finding (2026-06-21): on the 2023 R2 gRPC front door the metadata-server pipe IS
|
||||
// reachable (unlike 2020 WCF) and StartActiveTagnamesQuery parses the filter as OData —
|
||||
// startswith/contains/eq succeed; SQL-LIKE "%"/glob "*" fail with "ODataFilter: bad token".
|
||||
// StartTagQuery returns the 8-byte (queryHandle, tagCount) response. The follow-on QueryTag
|
||||
// paging request format is not yet captured (see roadmap R0.1), so browse is not yet wired.
|
||||
HistorianClientOptions options = BuildOptions(host);
|
||||
var result = await Task.Run(() =>
|
||||
AVEVA.Historian.Client.Grpc.HistorianGrpcTagClient.ProbeStartTagQuery(options, "startswith(TagName,'Sys')", CancellationToken.None));
|
||||
|
||||
Assert.True(result.Success,
|
||||
$"StartTagQuery(OData) should succeed; errLen={result.ErrorLength} " +
|
||||
$"err=\"{System.Text.Encoding.ASCII.GetString(result.Error).Replace('\0', '.')}\"");
|
||||
Assert.Equal(8, result.ResponseLength); // (queryHandle, tagCount)
|
||||
}
|
||||
|
||||
private static HistorianClientOptions BuildOptions(string host)
|
||||
{
|
||||
string? user = Environment.GetEnvironmentVariable("HISTORIAN_USER");
|
||||
|
||||
Reference in New Issue
Block a user