Remove dead dialect methods; unblock explicit-creds tag-metadata path
Two cleanups from the post-EnsureTagAsync punch list — both isolated, no protocol discovery required. #89 dead code in Historian2020ProtocolDialect: - BrowseTagNamesAsync and GetTagMetadataAsync on the dialect both threw ProtocolEvidenceMissingException, but HistorianClient routes those calls directly to HistorianWcfTagClient — the dialect overrides were never reached. Removed both methods. ReadBlocksAsync stays (it's a deliberate guardrailed entry on the public surface). #90 explicit-creds tag-metadata path: - HistorianWcfTagClient.WcfRetrievalSession.ValidateSupportedAuth threw ProtocolEvidenceMissingException whenever IntegratedSecurity=false AND UserName/Password were supplied. But the surrounding code already wires those creds through ApplyWindowsCredential -> factory.Credentials.Windows.ClientCredential — the validator was just being conservative about an untested combination. - Inverted the check: now only rejects the no-auth-at-all combination (IntegratedSecurity=false + no UserName + no Password). The other three valid auth shapes pass through to WCF. Tests: 161 -> 163 (+2). New unit test verifies the no-auth case still throws; new gated live integration test GetTagMetadataAsync_ExplicitCredentials_AgainstLocalHistorian exercises the explicit-creds path when HISTORIAN_USER+HISTORIAN_PASSWORD are set, skips cleanly otherwise. CLAUDE.md updated: removed the two now-resolved entries from "Remaining gaps"; explicit-creds line refined to note the live-verification env-var requirement. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -313,6 +313,55 @@ public sealed class HistorianClientIntegrationTests
|
||||
Assert.Equal(host, status.ServerName);
|
||||
}
|
||||
|
||||
// The validator inside HistorianWcfTagClient now allows IntegratedSecurity=false WHEN
|
||||
// explicit UserName + Password are provided (NTLM/Kerberos with non-current-user creds).
|
||||
// It still rejects the no-credentials-at-all case since there's no way to authenticate
|
||||
// against /Hist-Integrated.
|
||||
[Fact]
|
||||
public async Task GetTagMetadataAsync_NoAuthAndNoCredentials_Throws()
|
||||
{
|
||||
HistorianClient client = new(new HistorianClientOptions
|
||||
{
|
||||
Host = "localhost",
|
||||
IntegratedSecurity = false,
|
||||
UserName = string.Empty,
|
||||
Password = string.Empty,
|
||||
});
|
||||
await Assert.ThrowsAsync<ProtocolEvidenceMissingException>(
|
||||
() => client.GetTagMetadataAsync("anytag", CancellationToken.None));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetTagMetadataAsync_ExplicitCredentials_AgainstLocalHistorian()
|
||||
{
|
||||
// Live verification of the explicit-creds tag-metadata path. Gated on
|
||||
// HISTORIAN_USER + HISTORIAN_PASSWORD being set; skips cleanly otherwise. The path
|
||||
// routes through WCF Windows transport security with Credentials.Windows.ClientCredential.
|
||||
string? host = Environment.GetEnvironmentVariable("HISTORIAN_HOST");
|
||||
string? testTag = Environment.GetEnvironmentVariable("HISTORIAN_TEST_TAG");
|
||||
string? user = Environment.GetEnvironmentVariable("HISTORIAN_USER");
|
||||
string? password = Environment.GetEnvironmentVariable("HISTORIAN_PASSWORD");
|
||||
if (string.IsNullOrWhiteSpace(host) || string.IsNullOrWhiteSpace(testTag)
|
||||
|| string.IsNullOrWhiteSpace(user) || string.IsNullOrWhiteSpace(password)
|
||||
|| !OperatingSystem.IsWindows())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
HistorianClient client = new(new HistorianClientOptions
|
||||
{
|
||||
Host = host,
|
||||
IntegratedSecurity = false,
|
||||
UserName = user,
|
||||
Password = password,
|
||||
});
|
||||
|
||||
AVEVA.Historian.Client.Models.HistorianTagMetadata? metadata =
|
||||
await client.GetTagMetadataAsync(testTag, CancellationToken.None);
|
||||
Assert.NotNull(metadata);
|
||||
Assert.Equal(testTag, metadata.Name);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetTagMetadataAsync_ReturnsConfiguredTestTagMetadata()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user