mirror of
https://github.com/jcreek/CosmicClash.git
synced 2026-09-10 16:04:04 +00:00
97 lines
4.2 KiB
GDScript
97 lines
4.2 KiB
GDScript
extends "res://tests/test_case.gd"
|
|
|
|
# Guards the project settings that are load-bearing but easy to destroy
|
|
# silently. Godot's ConfigFile writer does not round-trip comments in
|
|
# project.godot: it drops `;` blocks outright, and a `#` block sitting directly
|
|
# above a setting can be spliced onto that setting's own line on rewrite, which
|
|
# comments the setting out. A dedicated build would then boot the interactive
|
|
# main menu instead of the server, and nothing would fail until someone noticed
|
|
# a server process rendering a menu.
|
|
#
|
|
# The explanations that used to live as comments beside these settings are now
|
|
# in the code that owns them — server_boot.gd and video_settings.gd.
|
|
#
|
|
# The feature-override assertions read project.godot as TEXT rather than through
|
|
# ProjectSettings. Godot resolves `key.<feature>` overrides at load time against
|
|
# the running build's own feature tags and does not expose the suffixed key, so
|
|
# get_setting("run/main_scene.dedicated_server") returns "" in a normal editor/
|
|
# headless run even when the line is perfectly intact. Reading the file also
|
|
# matches the actual threat, which is textual corruption of the file.
|
|
|
|
|
|
func _project_godot_lines() -> PackedStringArray:
|
|
var file := FileAccess.open("res://project.godot", FileAccess.READ)
|
|
if file == null:
|
|
return PackedStringArray()
|
|
return file.get_as_text().split("\n")
|
|
|
|
|
|
# True only if `key="value"` appears as a real, uncommented assignment. A line
|
|
# that got spliced into a `#`/`;` comment is deliberately NOT a match — that is
|
|
# precisely the corruption being guarded against.
|
|
func _has_setting_line(key: String, value: String) -> bool:
|
|
var wanted := "%s=\"%s\"" % [key, value]
|
|
for raw_line in _project_godot_lines():
|
|
var line := raw_line.strip_edges()
|
|
if line.begins_with("#") or line.begins_with(";"):
|
|
continue
|
|
if line == wanted:
|
|
return true
|
|
return false
|
|
|
|
|
|
func test_project_godot_is_readable() -> void:
|
|
# Everything below is vacuously true if the file could not be opened.
|
|
assert_true(not _project_godot_lines().is_empty(), "project.godot readable and non-empty")
|
|
|
|
|
|
func test_dedicated_server_feature_override_is_set() -> void:
|
|
# Consumed by dedicated exports; see server_boot.gd.
|
|
assert_true(
|
|
_has_setting_line("run/main_scene.dedicated_server", "res://scenes/server_boot.tscn"),
|
|
"run/main_scene.dedicated_server present and uncommented"
|
|
)
|
|
|
|
|
|
func test_training_feature_override_is_set() -> void:
|
|
assert_true(
|
|
_has_setting_line("run/main_scene.training", "res://scenes/training.tscn"),
|
|
"run/main_scene.training present and uncommented"
|
|
)
|
|
|
|
|
|
func test_physics_engine_is_jolt() -> void:
|
|
# The whole flight model and every trained policy assume Jolt. Silently
|
|
# reverting to Godot Physics would change ship/ball behaviour under bots
|
|
# trained against Jolt, without any other test failing on its own.
|
|
var engine: String = ProjectSettings.get_setting("physics/3d/physics_engine", "")
|
|
assert_eq(engine, "Jolt Physics", "3D physics engine")
|
|
|
|
|
|
func test_required_autoloads_are_registered() -> void:
|
|
# NetworkManager in particular is reached by name from many scripts; losing
|
|
# it from [autoload] fails only at the point of use, deep in a smoke test.
|
|
for autoload_name in ["GameSettings", "ControlPlaneClient", "VideoSettings", "NetworkManager", "MatchNet", "MatchSim"]:
|
|
assert_true(
|
|
ProjectSettings.has_setting("autoload/" + autoload_name),
|
|
"autoload/%s registered" % autoload_name
|
|
)
|
|
|
|
|
|
func test_matchmaking_scene_is_the_control_plane_entry_point() -> void:
|
|
var scene := load("res://scenes/matchmaking.tscn")
|
|
assert_true(scene != null, "matchmaking scene exists")
|
|
assert_true(FileAccess.file_exists("res://scripts/matchmaking.gd"), "matchmaking controller exists")
|
|
|
|
|
|
func test_test_hook_autoloads_are_not_shipped() -> void:
|
|
# main_menu_test_hooks / lobby_test_hooks are added to [autoload] by hand
|
|
# when running those scene-level smoke tests, and must be removed again —
|
|
# see CLAUDE.md. Shipping one registered would run test code in the real
|
|
# game, so fail here rather than discovering it in a build.
|
|
for hook_name in ["MainMenuTestHooks", "LobbyTestHooks", "NetworkedMatchTestHooks"]:
|
|
assert_true(
|
|
not ProjectSettings.has_setting("autoload/" + hook_name),
|
|
"test hook autoload/%s must not be registered" % hook_name
|
|
)
|