feat(server): complete phase 6 local verification

This commit is contained in:
Josh Creek
2026-08-21 18:38:30 +01:00
parent ec896b27ac
commit f2b72394de
21 changed files with 604 additions and 4 deletions
+60
View File
@@ -0,0 +1,60 @@
extends "res://tests/test_case.gd"
# Task 6.5. "The server cycles arenas" has to be an assertable claim rather
# than an observation about luck, which is why sequential rotation is a pure
# function of the completed-match count.
func test_sequential_rotation_visits_every_arena_before_repeating() -> void:
var paths := ArenaRegistry.rotation_paths()
assert_true(paths.size() >= 2, "rotation needs at least two arenas to mean anything")
var seen := {}
for i in paths.size():
seen[ArenaRegistry.path_for_match(i, "sequential")] = true
assert_eq(seen.size(), paths.size(), "every rotation arena appears in the first cycle")
func test_sequential_rotation_wraps_rather_than_running_out() -> void:
var paths := ArenaRegistry.rotation_paths()
var first: String = ArenaRegistry.path_for_match(0, "sequential")
var wrapped: String = ArenaRegistry.path_for_match(paths.size(), "sequential")
assert_eq(wrapped, first, "match N wraps back to the first arena")
# And a long-running server must not drift or fault at large counts.
assert_eq(ArenaRegistry.path_for_match(paths.size() * 1000, "sequential"), first, "still correct after a thousand cycles")
func test_consecutive_matches_are_never_the_same_arena_in_sequential_mode() -> void:
# The point of rotation is that players do not play the same arena twice in
# a row; wrapping must not produce a repeat at the seam either.
var paths := ArenaRegistry.rotation_paths()
for i in paths.size() * 2:
var current: String = ArenaRegistry.path_for_match(i, "sequential")
var next: String = ArenaRegistry.path_for_match(i + 1, "sequential")
assert_true(current != next, "match %d and %d differ" % [i, i + 1])
func test_rotation_never_offers_an_arena_bots_cannot_score_in() -> void:
# Elevated-goal variants are Free-Play-only until a checkpoint trained on
# them is promoted. A server rotating onto one would hand every bot-filled
# slot an arena it cannot score in.
var rotation := ArenaRegistry.rotation_paths()
for arena in ArenaRegistry.ARENAS:
if not arena["random"]:
assert_true(not (arena["path"] in rotation), "%s is excluded from rotation" % arena["name"])
assert_true(rotation.size() > 0, "and something is left to rotate through")
func test_random_mode_stays_inside_the_rotation_set() -> void:
for i in 50:
var path: String = ArenaRegistry.path_for_match(i, "random")
assert_true(path in ArenaRegistry.rotation_paths(), "random picks are still rotation-eligible")
func test_an_unknown_mode_falls_back_to_sequential_rather_than_faulting() -> void:
# The CLI already rejects an undeclared mode, so this is the belt to that's
# braces — but a server must not crash between matches over a string.
assert_eq(
ArenaRegistry.path_for_match(1, "spiral"),
ArenaRegistry.path_for_match(1, "sequential"),
"an unrecognised mode behaves as sequential"
)