godot-cpp icon indicating copy to clipboard operation
godot-cpp copied to clipboard

Proof of concept for a hot-reload test case

Open enetheru opened this issue 2 months ago • 1 comments

This is really rough atm, its late and I just wanted to get what I had up in case its a completely wrong direction to take.

I've been trying to figure out how to test hot reloading in a headless way for CI, and after much headscratching this is what i have so far. I did initally try to incorporate it into the existing tests, but couldnt quite manage that.

I i've filtered the results of the output to clear up some editor things. I have an arbitrary wait on initial load before i trigger the reload, and I havent been able to deduce a reliable trigger.

Process:

GDEXtension first load:

  • It must run the editor, hot reloading is explicitly disabled in other modes according to the documenation.
  • During gdextenson initialisation level EDITOR, it spawns a thread to poll the editor for when it can trigger the reload
  • thread calls deferred the reload on the gdextension manager
  • creates a lock file so that when the gdextension is reloaded it doesnt re-run the thread.

Editor Load

  • the --scene reload.tscn is passed on the command line so that it is loaded
  • gdextensions run all the time, so its basically a tool script
  • on _ready() connects to the custom signal, and creates a timer for timeout

GDExtension second load:

  • checks for the lock file. and waits.

  • the Example class in the running editor receives the GDEXTENSION_RELOADED notification and fires its custom signal

  • the reload.gd script catches and quits with 0

  • if the timeout is reached exits 1

Output:

"C:/Program Files/PowerShell/7/pwsh.exe" -File C:/Godot/src/godot-cpp/test/run-tests.ps1
Godot Engine v4.5.stable.official.876b29033 - https://godotengine.org

Initializing Integration Testing Extension
ERROR: Class 'ExampleInternal' isn't exposed.
   at: _instantiate_internal (core/object/class_db.cpp:549)
   GDScript backtrace (most recent call first):
       [0] _ready (res://main.gd:292)

 ==== TESTS FINISHED ==== 

   PASSES: 131
   FAILURES: 0

 ******** PASSED ******** 

Uninitializing Integration Testing Extension

Godot Engine v4.5.stable.official.876b29033 - https://godotengine.org

Initializing Integration Testing Extension
Test Reload is enabled
Creating Timer Thread
Creating Lock File

gdscript:Reload Test is Enabled
Awaiting Custom Signal (with 10s timeout)

Simulating GDExtension reload...
Waiting for reload thread to finish...
Reload thread joined.
Uninitializing Integration Testing Extension
Initializing Integration Testing Extension
Test Reload is enabled
Lock File Exists
 ******** PASSED ******** 
Uninitializing Integration Testing Extension

enetheru avatar Oct 16 '25 14:10 enetheru

From the original upload, I've moved to using godot's threads, and removed all the remaining cruft from my investigaiton, it now compiles, but is not yet incorporated into the CI/CD. I'll try that next.

enetheru avatar Oct 17 '25 09:10 enetheru