Mock game: drive input/focus/MKB hooks + window title; add DetourGate test

- poll_input() each frame (XInputGetState / GetAsyncKeyState / GetKeyboardState /
  GetForegroundWindow), like a real game, so mock_game_test's hook/unhook storm
  actually exercises removing the input/focus/MKB hooks while their detours are in
  flight -- the coverage gap that let those removal races go untested.
- Window title shows the backend + a once-per-second-smoothed fps.
- A vectored-exception crash logger prints the faulting module+offset (named the
  storm's intermittent crashes during this work; inert otherwise).
- detour_gate_test: fast, deterministic guard for DetourGate -- drain() must block
  while a Guard is in flight and return promptly otherwise, plus a concurrency
  stress that asserts no body runs against freed state. (A synthetic install-race
  unit test was tried but flaked on SafetyHook's own enable/disable atomicity under
  ~30M calls/s, unrelated to our code, so the storm is the install/remove guard.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-23 11:17:34 +02:00
parent 79582f9fa6
commit 0e58902438
4 changed files with 200 additions and 1 deletions

View File

@@ -13,7 +13,8 @@ add_executable(coop_mock_game
# Reuses the shared ToneSource (also used by coop_tone + the audio hook self-test).
target_include_directories(coop_mock_game PRIVATE ${CMAKE_SOURCE_DIR}/tools/audio_tone)
target_link_libraries(coop_mock_game PRIVATE d3d11 d3d12 d3d10 d3d9 dxgi ole32 opengl32 gdi32 volk)
target_link_libraries(coop_mock_game PRIVATE d3d11 d3d12 d3d10 d3d9 dxgi ole32 opengl32 gdi32 volk
xinput user32) # xinput/user32: poll the input + focus APIs the hook intercepts (storm coverage)
set_target_properties(coop_mock_game PROPERTIES OUTPUT_NAME "coop_mock_game")
# Test fixture -> stage next to the tests (alongside coop_tone), not in the deployable root.