feat: verify Tornado PGM KTAP connection

This commit is contained in:
2026-07-10 14:28:45 +09:00
parent b113830c14
commit 930424b752
22 changed files with 3474 additions and 67 deletions

View File

@@ -7,7 +7,8 @@ internal enum SmokeCommandKind
DryRun,
TestPlan,
TestConnect,
TestSequence
TestSequence,
PgmConnectDiagnostic
}
internal sealed record SmokeCommandInvocation(
@@ -15,7 +16,10 @@ internal sealed record SmokeCommandInvocation(
string? ConfigPath = null,
string? PrepareSceneCode = null,
string? NextSceneCode = null,
int? ObservationMilliseconds = null);
int? ObservationMilliseconds = null,
string? Host = null,
int? Port = null,
string? ExpectedPgmWindowTitle = null);
internal sealed record SmokeCommandParseResult(
bool IsValid,
@@ -26,6 +30,8 @@ internal static class SmokeCommandLine
{
internal const string AcknowledgementFlag =
"--acknowledge-isolated-non-program-test-output";
internal const string PgmConnectAcknowledgementFlag =
"--i-understand-this-will-contact-current-pgm-tornado-via-ktap-connect-and-disconnect-only";
public static SmokeCommandParseResult Parse(IReadOnlyList<string> arguments)
{
@@ -50,6 +56,7 @@ internal static class SmokeCommandLine
"--test-plan" => SmokeCommandKind.TestPlan,
"--test-connect" => SmokeCommandKind.TestConnect,
"--test-sequence" => SmokeCommandKind.TestSequence,
"--pgm-connect-diagnostic" => SmokeCommandKind.PgmConnectDiagnostic,
_ => SmokeCommandKind.Invalid
};
if (kind == SmokeCommandKind.Invalid)
@@ -61,6 +68,9 @@ internal static class SmokeCommandLine
string? prepareSceneCode = null;
string? nextSceneCode = null;
int? observationMilliseconds = null;
string? host = null;
int? port = null;
string? expectedPgmWindowTitle = null;
var acknowledged = false;
for (var index = 1; index < arguments.Count; index++)
@@ -68,7 +78,8 @@ internal static class SmokeCommandLine
var argument = arguments[index];
switch (argument)
{
case AcknowledgementFlag:
case AcknowledgementFlag when kind != SmokeCommandKind.PgmConnectDiagnostic:
case PgmConnectAcknowledgementFlag when kind == SmokeCommandKind.PgmConnectDiagnostic:
if (acknowledged)
{
return Invalid("duplicate-option");
@@ -77,7 +88,54 @@ internal static class SmokeCommandLine
acknowledged = true;
break;
case "--config":
case "--host" when kind == SmokeCommandKind.PgmConnectDiagnostic:
if (host is not null)
{
return Invalid("duplicate-option");
}
if (!TryReadValue(arguments, ref index, out host))
{
return Invalid("missing-option-value");
}
break;
case "--port" when kind == SmokeCommandKind.PgmConnectDiagnostic:
if (port is not null)
{
return Invalid("duplicate-option");
}
if (!TryReadValue(arguments, ref index, out var portText) ||
!int.TryParse(
portText,
System.Globalization.NumberStyles.None,
System.Globalization.CultureInfo.InvariantCulture,
out var parsedPort) ||
parsedPort is < 1 or > 65_535)
{
return Invalid("invalid-port");
}
port = parsedPort;
break;
case "--expected-pgm-window-title"
when kind == SmokeCommandKind.PgmConnectDiagnostic:
if (expectedPgmWindowTitle is not null)
{
return Invalid("duplicate-option");
}
if (!TryReadValue(arguments, ref index, out expectedPgmWindowTitle))
{
return Invalid("missing-option-value");
}
break;
case "--config" when kind != SmokeCommandKind.PgmConnectDiagnostic:
if (configPath is not null)
{
return Invalid("duplicate-option");
@@ -146,6 +204,22 @@ internal static class SmokeCommandLine
return Invalid("missing-acknowledgement");
}
if (kind == SmokeCommandKind.PgmConnectDiagnostic)
{
if (string.IsNullOrWhiteSpace(host) ||
port is null ||
string.IsNullOrWhiteSpace(expectedPgmWindowTitle))
{
return Invalid("missing-required-option");
}
return Valid(new SmokeCommandInvocation(
kind,
Host: host,
Port: port,
ExpectedPgmWindowTitle: expectedPgmWindowTitle));
}
if (string.IsNullOrWhiteSpace(configPath))
{
return Invalid("missing-required-option");
@@ -177,7 +251,10 @@ internal static class SmokeCommandLine
configPath,
prepareSceneCode,
nextSceneCode,
observationMilliseconds));
observationMilliseconds,
host,
port,
expectedPgmWindowTitle));
}
internal static bool IsSafeSceneCode(string value)