mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
test(server): fix and wire up the two unrun Python suites
test_contracts.py required operation ID `recordPlayerConnected`, but
openapi.json names that endpoint `claimPlayerConnection` — the accurate
name, since POST /servers/{id}/connect claims a connection lease and
returns a generation. Align the test on the document and assert the set
difference, so a future mismatch names the missing operation instead of
reporting "False is not true".
test_observability_manifests.py copied only two of the four files the
checker reads, so it died on a missing kustomization.yaml before ever
reaching the mutated namespace. Copy the full fixture, split the
namespace and scrape-path mutations into separate cases so either
defect produces its own diagnostic, and add an unmutated-copy case so a
broken fixture can't make the mutation cases pass vacuously.
Neither suite was invoked by any Make target or workflow, which is why
both could sit red. Add them, plus test_threat_model.py, to
verify_multiplayer_local.sh.
This commit is contained in:
@@ -50,12 +50,21 @@ run_godot_harness
|
||||
|
||||
echo "local multiplayer gate: contracts and manifests"
|
||||
python3 -m json.tool "$root_dir/server/contracts/v1/openapi.json" >/dev/null
|
||||
# json.tool only proves the contract parses. test_contracts.py is what actually
|
||||
# checks the operation IDs, envelopes and state vocabulary generated clients
|
||||
# bind to; it was previously not run by any target, so a real mismatch between
|
||||
# openapi.json and the suite sat undetected.
|
||||
python3 "$root_dir/server/contracts/v1/test_contracts.py"
|
||||
python3 "$root_dir/server/migrations/test_migration.py"
|
||||
python3 "$root_dir/server/security/test_fleet_manifests.py"
|
||||
python3 "$root_dir/server/security/test_compose_manifests.py"
|
||||
python3 "$root_dir/server/security/test_kubernetes_policies.py"
|
||||
python3 "$root_dir/server/security/test_supply_chain.py"
|
||||
python3 "$root_dir/server/security/test_threat_model.py"
|
||||
python3 "$root_dir/scripts/verify_observability_manifests.py"
|
||||
# The checker above validates the checked-in manifests; this validates the
|
||||
# checker itself still rejects a widened scrape scope.
|
||||
python3 "$root_dir/server/security/test_observability_manifests.py"
|
||||
python3 -m unittest "$root_dir/scripts/test_verify_agones_allocation_response.py"
|
||||
|
||||
echo "LOCAL MULTIPLAYER GATE PASS"
|
||||
|
||||
@@ -23,12 +23,17 @@ class ContractTest(unittest.TestCase):
|
||||
for operation in path.values()
|
||||
if isinstance(operation, dict) and "operationId" in operation
|
||||
}
|
||||
self.assertTrue({
|
||||
# These are the operation IDs generated clients bind to, so a rename
|
||||
# here is a breaking change for every consumer. Assert the difference
|
||||
# rather than a bare subset check: a plain assertTrue reports only
|
||||
# "False is not true" and hides which operation went missing.
|
||||
required = {
|
||||
"createSteamSession", "getProfile", "createQueueTicket",
|
||||
"heartbeatQueueTicket", "cancelQueueTicket", "acceptProposal",
|
||||
"declineProposal", "getAssignment", "registerServer",
|
||||
"recordPlayerConnected", "submitMatchResult", "getRankedProfile",
|
||||
} <= operations)
|
||||
"claimPlayerConnection", "submitMatchResult", "getRankedProfile",
|
||||
}
|
||||
self.assertEqual(set(), required - operations)
|
||||
|
||||
def test_ranked_profile_contract_is_authoritative_and_optional_season_metadata(self):
|
||||
schema = self.openapi["components"]["schemas"]["RankedProfile"]
|
||||
|
||||
@@ -20,17 +20,50 @@ class ObservabilityManifestTest(unittest.TestCase):
|
||||
result = self.run_checker()
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
|
||||
def test_checker_rejects_wrong_namespace_and_broad_scrape(self):
|
||||
# Every file the checker opens, in the order it opens them. Copying only a
|
||||
# subset makes it die on a missing file before it reaches the assertion
|
||||
# under test, so the mutation is never actually exercised.
|
||||
FIXTURE = (
|
||||
"kustomization.yaml",
|
||||
"prometheus-service-monitor.yaml",
|
||||
"prometheus-allocator-service-monitor.yaml",
|
||||
"prometheus-rules.yaml",
|
||||
)
|
||||
|
||||
def build_fixture(self, target, mutate=None):
|
||||
for name in self.FIXTURE:
|
||||
text = (ROOT / "deploy/observability" / name).read_text()
|
||||
if mutate is not None and name == "prometheus-service-monitor.yaml":
|
||||
text = mutate(text)
|
||||
(target / name).write_text(text)
|
||||
|
||||
def test_unmutated_fixture_copy_passes(self):
|
||||
# Guards the two mutation tests below: if this fails, their non-zero
|
||||
# exit proves nothing, because the fixture itself is broken.
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
target = Path(directory)
|
||||
for name in ("prometheus-service-monitor.yaml", "prometheus-rules.yaml"):
|
||||
(target / name).write_text((ROOT / "deploy/observability" / name).read_text())
|
||||
monitor = target / "prometheus-service-monitor.yaml"
|
||||
monitor.write_text(monitor.read_text().replace("path: /metrics", "path: /").replace("- cosmic-clash", "- default"))
|
||||
self.build_fixture(target)
|
||||
result = self.run_checker(target)
|
||||
self.assertEqual(result.returncode, 0, result.stderr)
|
||||
|
||||
def test_checker_rejects_wrong_namespace(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
target = Path(directory)
|
||||
# Widen the namespaceSelector only; metadata.namespace stays put so
|
||||
# this isolates the scrape-scope check from the placement check.
|
||||
self.build_fixture(target, lambda text: text.replace(" - cosmic-clash", " - default"))
|
||||
result = self.run_checker(target)
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("namespace", result.stderr)
|
||||
|
||||
def test_checker_rejects_broad_scrape_path(self):
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
target = Path(directory)
|
||||
self.build_fixture(target, lambda text: text.replace(" path: /metrics", " path: /"))
|
||||
result = self.run_checker(target)
|
||||
self.assertNotEqual(result.returncode, 0)
|
||||
self.assertIn("path", result.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
Reference in New Issue
Block a user