refactor: enhance test framework with automated resource tracking and scripted error capture capabilities
This commit is contained in:
@@ -0,0 +1,119 @@
|
||||
extends GutTest
|
||||
|
||||
# =============================================================================
|
||||
# Test: Gauntlet Movement Buffer System (v2) [Gauntlet #083]
|
||||
# Hidden, decaying safe-corridor penalties layered onto candidate scoring.
|
||||
# Runs headless; elapsed_time = 0 so the final-30s window is inactive unless a
|
||||
# test sets elapsed_time directly.
|
||||
# =============================================================================
|
||||
|
||||
const GauntletManager = preload("res://scripts/managers/gauntlet_manager.gd")
|
||||
var manager
|
||||
var main_mock: Node
|
||||
var gridmap_mock: Node
|
||||
|
||||
func before_each():
|
||||
main_mock = Node.new()
|
||||
add_child(main_mock)
|
||||
gridmap_mock = Node.new()
|
||||
gridmap_mock.name = "EnhancedGridMap"
|
||||
main_mock.add_child(gridmap_mock)
|
||||
manager = GauntletManager.new()
|
||||
main_mock.add_child(manager)
|
||||
manager.initialize(main_mock, gridmap_mock)
|
||||
manager.current_phase = 0
|
||||
|
||||
func after_each():
|
||||
if main_mock:
|
||||
main_mock.queue_free()
|
||||
|
||||
# =============================================================================
|
||||
# Registration
|
||||
# =============================================================================
|
||||
|
||||
func test_register_buffer_sets_phase_base_penalty():
|
||||
manager._register_buffer(Vector2i(5, 5), 40.0)
|
||||
assert_true(manager.movement_buffers.has(Vector2i(5, 5)), "Buffer registered")
|
||||
assert_almost_eq(manager.movement_buffers[Vector2i(5, 5)]["penalty"], 40.0, 0.001, "Full penalty stored")
|
||||
|
||||
func test_register_buffer_keeps_strongest():
|
||||
manager._register_buffer(Vector2i(5, 5), 20.0)
|
||||
manager._register_buffer(Vector2i(5, 5), 40.0)
|
||||
assert_almost_eq(manager.movement_buffers[Vector2i(5, 5)]["penalty"], 40.0, 0.001, "Keeps the stronger penalty")
|
||||
manager._register_buffer(Vector2i(5, 5), 10.0)
|
||||
assert_almost_eq(manager.movement_buffers[Vector2i(5, 5)]["penalty"], 40.0, 0.001, "Weaker refresh does not lower it")
|
||||
|
||||
# =============================================================================
|
||||
# Penalty lookup (inside / adjacent / none / final-window)
|
||||
# =============================================================================
|
||||
|
||||
func test_buffer_penalty_inside_is_full_negative():
|
||||
manager._register_buffer(Vector2i(6, 6), 40.0)
|
||||
assert_almost_eq(manager._buffer_penalty_at(Vector2i(6, 6)), -40.0, 0.001, "Inside buffer = full negative")
|
||||
|
||||
func test_buffer_penalty_adjacent_is_half():
|
||||
manager._register_buffer(Vector2i(6, 6), 40.0)
|
||||
assert_almost_eq(manager._buffer_penalty_at(Vector2i(7, 6)), -20.0, 0.001, "Adjacent buffer = half penalty")
|
||||
|
||||
func test_buffer_penalty_far_is_zero():
|
||||
manager._register_buffer(Vector2i(6, 6), 40.0)
|
||||
assert_eq(manager._buffer_penalty_at(Vector2i(15, 15)), 0.0, "Far from buffer = 0")
|
||||
|
||||
func test_buffer_penalty_lifts_in_final_window():
|
||||
manager._register_buffer(Vector2i(6, 6), 40.0)
|
||||
manager.elapsed_time = manager.gauntlet_round_duration() - 5.0 # within final 30s
|
||||
assert_eq(manager._buffer_penalty_at(Vector2i(6, 6)), 0.0, "Final window lifts buffers")
|
||||
|
||||
func test_buffer_penalty_empty_is_zero():
|
||||
assert_eq(manager._buffer_penalty_at(Vector2i(6, 6)), 0.0, "No buffers = 0")
|
||||
|
||||
# =============================================================================
|
||||
# Time decay (−25% every 5s)
|
||||
# =============================================================================
|
||||
|
||||
func test_decay_reduces_penalty_after_interval():
|
||||
manager._register_buffer(Vector2i(5, 5), 40.0)
|
||||
manager._decay_movement_buffers(manager.BUFFER_DECAY_INTERVAL) # one full step
|
||||
assert_almost_eq(manager.movement_buffers[Vector2i(5, 5)]["penalty"], 30.0, 0.001, "−25% after one interval")
|
||||
|
||||
func test_decay_waits_for_full_interval():
|
||||
manager._register_buffer(Vector2i(5, 5), 40.0)
|
||||
manager._decay_movement_buffers(manager.BUFFER_DECAY_INTERVAL * 0.5) # not yet
|
||||
assert_almost_eq(manager.movement_buffers[Vector2i(5, 5)]["penalty"], 40.0, 0.001, "No decay before interval elapses")
|
||||
|
||||
func test_decay_prunes_faded_buffers():
|
||||
manager._register_buffer(Vector2i(5, 5), manager.BUFFER_MIN_PENALTY + 0.5)
|
||||
manager._decay_movement_buffers(manager.BUFFER_DECAY_INTERVAL)
|
||||
assert_false(manager.movement_buffers.has(Vector2i(5, 5)), "Faded buffer pruned below BUFFER_MIN_PENALTY")
|
||||
|
||||
# =============================================================================
|
||||
# Phase-change decay (−50%)
|
||||
# =============================================================================
|
||||
|
||||
func test_phase_change_halves_buffers():
|
||||
manager._register_buffer(Vector2i(5, 5), 40.0)
|
||||
manager._start_phase(manager.Phase.ROUTE_PRESSURE)
|
||||
assert_almost_eq(manager.movement_buffers[Vector2i(5, 5)]["penalty"], 20.0, 0.001, "Phase change halves penalty")
|
||||
|
||||
# =============================================================================
|
||||
# Scoring integration
|
||||
# =============================================================================
|
||||
|
||||
func test_score_movement_buffer_uses_detected_corridor():
|
||||
# With no players, the proximity floor is inert; a registered buffer still bites.
|
||||
manager._register_buffer(Vector2i(5, 5), 40.0)
|
||||
assert_almost_eq(manager._score_movement_buffer(Vector2i(5, 5)), -40.0, 0.001, "Score reflects buffer penalty")
|
||||
|
||||
func test_score_movement_buffer_zero_without_buffers_or_players():
|
||||
assert_eq(manager._score_movement_buffer(Vector2i(5, 5)), 0.0, "No buffers, no players = 0")
|
||||
|
||||
# =============================================================================
|
||||
# Scale helper
|
||||
# =============================================================================
|
||||
|
||||
func test_scale_all_buffers_prunes_and_scales():
|
||||
manager._register_buffer(Vector2i(1, 1), 40.0)
|
||||
manager._register_buffer(Vector2i(2, 2), manager.BUFFER_MIN_PENALTY + 0.1)
|
||||
manager._scale_all_buffers(0.5)
|
||||
assert_almost_eq(manager.movement_buffers[Vector2i(1, 1)]["penalty"], 20.0, 0.001, "Scaled by 0.5")
|
||||
assert_false(manager.movement_buffers.has(Vector2i(2, 2)), "Below-min entry pruned")
|
||||
Reference in New Issue
Block a user