using System.Text.Json; using System.Text.RegularExpressions; using System.Xml.Linq; namespace FinalFactory.Rendezvous.Tests.Documentation; public sealed partial class DocumentationContractTests { private static readonly string[] IncidentScenarios = [ "Abuse or authentication spike", "Signing key or issuer compromise", "Targeted listing or publisher revocation", "Planned restart or crash recovery", "Release rollback", "Capacity saturation", "Privacy or telemetry incident", "Dependency or base-image upgrade", ]; [Fact] public void TestClientGuideDocumentsTheExecutableSuccessAndFailureContracts() { string root = FindRepositoryRoot(); string guide = File.ReadAllText(Path.Combine(root, "docs", "integration", "test-client.md")); Assert.Contains("space-game --environment smoke --region local --protocol 1", guide, StringComparison.Ordinal); Assert.Contains("mint-local-publisher-credential.sh", guide, StringComparison.Ordinal); Assert.Contains("join.connected", guide, StringComparison.Ordinal); Assert.Contains("join.direct-traffic", guide, StringComparison.Ordinal); Assert.Contains("browse.completed", guide, StringComparison.Ordinal); Assert.Contains("--script --json", guide, StringComparison.Ordinal); Assert.Contains("--run-seconds 60", guide, StringComparison.Ordinal); Assert.Contains("for attempt in {1..45}", guide, StringComparison.Ordinal); Assert.Contains("before the terminal-3", guide, StringComparison.Ordinal); Assert.Contains("test \"$status\" -eq 11", guide, StringComparison.Ordinal); Assert.Contains("no relay", guide, StringComparison.OrdinalIgnoreCase); Assert.Contains("cannot guarantee", guide, StringComparison.OrdinalIgnoreCase); Assert.DoesNotMatch(ReusableCredential(), guide); } [Fact] public void LocalCredentialHelperWhitelistsProvisionedGameScopesAndSmokeDelegatesToIt() { string root = FindRepositoryRoot(); string helper = File.ReadAllText(Path.Combine(root, "scripts", "mint-local-publisher-credential.sh")); string smoke = File.ReadAllText(Path.Combine(root, "scripts", "smoke-deployment.sh")); Assert.Contains("if (( $# != 0 ));", helper, StringComparison.Ordinal); Assert.Contains("space-game)", helper, StringComparison.Ordinal); Assert.Contains("unscouted)", helper, StringComparison.Ordinal); Assert.Contains("KEY_ID=\"local-smoke-1\"", helper, StringComparison.Ordinal); Assert.Contains("KEY_ID=\"local-smoke-unscouted-1\"", helper, StringComparison.Ordinal); Assert.Contains("RENDEZVOUS_LOCAL_CREDENTIAL_GAME_ID must be space-game or unscouted", helper, StringComparison.Ordinal); Assert.Contains("\"gameId\": game_id", helper, StringComparison.Ordinal); Assert.Contains("\"environmentId\": \"smoke\"", helper, StringComparison.Ordinal); Assert.Contains("\"regions\": [\"local\"]", helper, StringComparison.Ordinal); Assert.Contains("now + 600", helper, StringComparison.Ordinal); Assert.Contains("stat.S_ISLNK", helper, StringComparison.Ordinal); Assert.Contains("parent.st_mode & 0o077", helper, StringComparison.Ordinal); Assert.Contains("metadata.st_mode & 0o077", helper, StringComparison.Ordinal); Assert.Contains("metadata.st_nlink != 1", helper, StringComparison.Ordinal); Assert.Contains("mint-local-publisher-credential.sh", smoke, StringComparison.Ordinal); Assert.DoesNotContain("hexkey:", smoke, StringComparison.Ordinal); Assert.DoesNotContain("openssl dgst", smoke, StringComparison.Ordinal); } [Fact] public void UnscoutedComposeTenantIsGameScopedAndMetadataBounded() { string root = FindRepositoryRoot(); using JsonDocument settings = JsonDocument.Parse(File.ReadAllText( Path.Combine(root, "deploy", "compose", "appsettings.Production.json"))); JsonElement provisioning = settings.RootElement.GetProperty("Rendezvous").GetProperty("Provisioning"); JsonElement game = provisioning.GetProperty("Games").EnumerateArray().Single( static item => item.GetProperty("GameId").GetString() == "unscouted"); JsonElement key = provisioning.GetProperty("SigningKeys").EnumerateArray().Single( static item => item.GetProperty("KeyId").GetString() == "local-smoke-unscouted-1"); Assert.Equal("smoke", game.GetProperty("EnvironmentId").GetString()); Assert.Equal([1], game.GetProperty("ProtocolVersions").EnumerateArray().Select(static value => value.GetInt32())); Assert.Equal(["mode", "mods", "world"], game.GetProperty("MetadataValueMaxBytes") .EnumerateObject().Select(static property => property.Name).Order(StringComparer.Ordinal)); Assert.Equal(["mode", "mods", "world"], game.GetProperty("RequiredMetadataKeys") .EnumerateArray().Select(static value => value.GetString()).Order(StringComparer.Ordinal)); Assert.Equal(3, game.GetProperty("MetadataMaxKeys").GetInt32()); Assert.Equal("DedicatedEndpointAllowed", game.GetProperty("FallbackPolicy").GetString()); Assert.Equal("unscouted", key.GetProperty("GameId").GetString()); Assert.Equal("smoke", key.GetProperty("EnvironmentId").GetString()); Assert.Equal(["DedicatedPublisher"], key.GetProperty("CredentialKinds") .EnumerateArray().Select(static value => value.GetString())); } [Fact] public void EveryIncidentRunbookHasDetectContainRecoverAndVerifyGates() { string root = FindRepositoryRoot(); string runbooks = File.ReadAllText(Path.Combine(root, "docs", "operations", "incident-runbooks.md")); for (int index = 0; index < IncidentScenarios.Length; index++) { string heading = $"## {IncidentScenarios[index]}"; int start = runbooks.IndexOf(heading, StringComparison.Ordinal); Assert.True(start >= 0, $"Missing incident runbook heading: {heading}"); int end = index + 1 < IncidentScenarios.Length ? runbooks.IndexOf($"## {IncidentScenarios[index + 1]}", start, StringComparison.Ordinal) : runbooks.Length; Assert.True(end > start, $"Could not find the end of runbook: {heading}"); string scenario = runbooks[start..end]; Assert.Contains("### Detect", scenario, StringComparison.Ordinal); Assert.Contains("### Contain", scenario, StringComparison.Ordinal); Assert.Contains("### Recover", scenario, StringComparison.Ordinal); Assert.Contains("### Verify", scenario, StringComparison.Ordinal); } Assert.DoesNotMatch(ReusableCredential(), runbooks); } [Fact] public void DocumentedOperatorOperationsAndBodiesMatchTheReleasedOpenApi() { string root = FindRepositoryRoot(); string runbooks = File.ReadAllText(Path.Combine(root, "docs", "operations", "incident-runbooks.md")); using JsonDocument openApi = JsonDocument.Parse(File.ReadAllText( Path.Combine(root, "docs", "api", "rendezvous-v1.json"))); JsonElement paths = openApi.RootElement.GetProperty("paths"); (string Method, string Path)[] documentedOperations = OperatorRoute().Matches(runbooks) .Cast() .Select(static match => ( match.Groups["method"].Value.ToLowerInvariant(), match.Groups["path"].Value)) .Distinct() .ToArray(); Assert.NotEmpty(documentedOperations); Assert.All(documentedOperations, operation => Assert.True( paths.TryGetProperty(operation.Path, out JsonElement path) && path.TryGetProperty(operation.Method, out _), $"OpenAPI does not contain {operation.Method.ToUpperInvariant()} {operation.Path}.")); Match[] actions = OperatorAction().Matches(runbooks).Cast().ToArray(); Assert.Equal(4, actions.Length); foreach (Match action in actions) { string method = action.Groups["method"].Value.ToLowerInvariant(); string path = action.Groups["path"].Value; using JsonDocument body = JsonDocument.Parse(action.Groups["body"].Value); string reference = paths.GetProperty(path) .GetProperty(method) .GetProperty("requestBody") .GetProperty("content") .GetProperty("application/json") .GetProperty("schema") .GetProperty("$ref") .GetString()!; string schemaName = reference["#/components/schemas/".Length..]; string[] required = openApi.RootElement.GetProperty("components") .GetProperty("schemas") .GetProperty(schemaName) .GetProperty("required") .EnumerateArray() .Select(static property => property.GetString()!) .Order(StringComparer.Ordinal) .ToArray(); string[] documented = body.RootElement.EnumerateObject() .Select(static property => property.Name) .Order(StringComparer.Ordinal) .ToArray(); Assert.Equal(required, documented); } } [Fact] public void SdkGuideMatchesTheReleasedPackageAndTransportMatrix() { string root = FindRepositoryRoot(); string guide = File.ReadAllText(Path.Combine(root, "docs", "integration", "sdk-seams.md")); using JsonDocument compatibility = JsonDocument.Parse(File.ReadAllText( Path.Combine(root, "docs", "releases", "compatibility.json"))); JsonElement matrix = compatibility.RootElement; JsonElement packages = matrix.GetProperty("packages"); string clientVersion = packages.GetProperty("FinalFactory.Rendezvous.Client").GetString()!; string contractsVersion = packages.GetProperty("FinalFactory.Rendezvous.Contracts").GetString()!; string liteNetLibVersion = matrix.GetProperty("transport").GetProperty("version").GetString()!; string clientFramework = XDocument.Load(Path.Combine( root, "src", "FinalFactory.Rendezvous.Client", "FinalFactory.Rendezvous.Client.csproj")) .Descendants("TargetFramework") .Single() .Value; int httpVersion = matrix.GetProperty("contracts").GetProperty("http")[0].GetInt32(); int udpVersion = matrix.GetProperty("contracts").GetProperty("udp")[0].GetInt32(); int ticketVersion = matrix.GetProperty("contracts").GetProperty("connectionTicket")[0].GetInt32(); Assert.Contains( $"FinalFactory.Rendezvous.Client\" Version=\"{clientVersion}\"", guide, StringComparison.Ordinal); Assert.Contains( $"FinalFactory.Rendezvous.Contracts\" Version=\"{contractsVersion}\"", guide, StringComparison.Ordinal); Assert.Contains($"targets `{clientFramework}`", guide, StringComparison.Ordinal); Assert.Contains($"LiteNetLib `{liteNetLibVersion}`", guide, StringComparison.Ordinal); Assert.Contains( "https://git.finalfactory.de/api/packages/HeiKyu/nuget/index.json", guide, StringComparison.Ordinal); Assert.Equal(httpVersion, udpVersion); Assert.Equal(httpVersion, ticketVersion); Assert.Contains($"contract version `{httpVersion}`", guide, StringComparison.Ordinal); Assert.Contains("gameplayNetwork.ChannelsCount = 3", guide, StringComparison.Ordinal); Assert.Contains("defaults to one QoS channel", guide, StringComparison.Ordinal); Assert.Contains("Rendezvous does not choose, remap, or reserve", guide, StringComparison.Ordinal); } [Fact] public void SpaceGamePilotEvidenceSeparatesProvenBehaviorFromOpenGates() { string root = FindRepositoryRoot(); string guide = File.ReadAllText(Path.Combine(root, "docs", "integration", "spacegame-pilot.md")); string deploymentGuide = File.ReadAllText(Path.Combine(root, "docs", "deployment", "linux.md")); using JsonDocument evidence = JsonDocument.Parse(File.ReadAllText( Path.Combine(root, "docs", "evidence", "consumers", "spacegame.json"))); JsonElement record = evidence.RootElement; Assert.Equal("checkpoint-pass-with-external-gates", record.GetProperty("result").GetString()); Assert.Equal("none", record.GetProperty("localRun").GetProperty("rendezvousGameplayPayloadPath").GetString()); Assert.Equal("caller-owned-litenetlib", record.GetProperty("localRun").GetProperty("gameplayTransport").GetString()); Assert.True(record.GetProperty("localRun").GetProperty("directGameplay").GetBoolean()); Assert.True(record.GetProperty("localRun").GetProperty("reconnected").GetBoolean()); Assert.True(record.GetProperty("linuxRun").GetProperty("freshExport").GetBoolean()); Assert.False(record.GetProperty("linuxRun").GetProperty("sourceDirty").GetBoolean()); Assert.Equal(31, record.GetProperty("verification").GetProperty("debugTests").GetProperty("passed").GetInt32()); Assert.Equal(31, record.GetProperty("verification").GetProperty("releaseTests").GetProperty("passed").GetInt32()); Assert.Contains("public-package-restore", record.GetProperty("openGates").EnumerateArray().Select(static gate => gate.GetString())); Assert.Contains("representative-external-nat", record.GetProperty("openGates").EnumerateArray().Select(static gate => gate.GetString())); Assert.DoesNotContain("actual-godot-process-integration", record.GetProperty("openGates").EnumerateArray().Select(static gate => gate.GetString())); Assert.DoesNotContain("dedicated-fallback-connection", record.GetProperty("openGates").EnumerateArray().Select(static gate => gate.GetString())); Assert.Contains("Do not mark #21 passed", guide, StringComparison.Ordinal); Assert.Contains("Rendezvous reserves no gameplay", guide, StringComparison.Ordinal); Assert.Contains("private-network service name", guide, StringComparison.Ordinal); Assert.Contains("local/private-bridge smoke", deploymentGuide, StringComparison.Ordinal); Assert.Contains("explicit `rendezvous` host name", deploymentGuide, StringComparison.Ordinal); using JsonDocument composeSettings = JsonDocument.Parse(File.ReadAllText( Path.Combine(root, "deploy", "compose", "appsettings.Production.json"))); JsonElement compose = composeSettings.RootElement; Assert.Contains("rendezvous", compose.GetProperty("AllowedHosts").GetString()!.Split(';')); JsonElement game = compose.GetProperty("Rendezvous").GetProperty("Provisioning").GetProperty("Games")[0]; Assert.Contains(2, game.GetProperty("ProtocolVersions").EnumerateArray().Select(static version => version.GetInt32())); Assert.Equal("DedicatedEndpointAllowed", game.GetProperty("FallbackPolicy").GetString()); Assert.DoesNotMatch(ReusableCredential(), guide); } [GeneratedRegex(@"rv1\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+", RegexOptions.CultureInvariant)] private static partial Regex ReusableCredential(); [GeneratedRegex(@"(?GET|POST) `?(?/v1/operator/[a-z/-]+)`?", RegexOptions.CultureInvariant)] private static partial Regex OperatorRoute(); [GeneratedRegex(@"\| `(?POST) (?/v1/operator/[a-z/-]+)` \| `(?\{[^`]+\})` \|", RegexOptions.CultureInvariant)] private static partial Regex OperatorAction(); private static string FindRepositoryRoot() { DirectoryInfo? current = new(AppContext.BaseDirectory); while (current is not null) { if (File.Exists(Path.Combine(current.FullName, "Rendezvous.slnx"))) { return current.FullName; } current = current.Parent; } throw new InvalidOperationException("Could not locate the repository root."); } }