Adding log.gd

This commit is contained in:
Dan Baker 2024-05-02 09:36:31 +01:00
parent eb32d6614e
commit 4522259397
547 changed files with 46844 additions and 0 deletions

View file

@ -0,0 +1,41 @@
class_name GdUnitCommand
extends RefCounted
func _init(p_name :String, p_is_enabled: Callable, p_runnable: Callable, p_shortcut :GdUnitShortcut.ShortCut = GdUnitShortcut.ShortCut.NONE):
assert(p_name != null, "(%s) missing parameter 'name'" % p_name)
assert(p_is_enabled != null, "(%s) missing parameter 'is_enabled'" % p_name)
assert(p_runnable != null, "(%s) missing parameter 'runnable'" % p_name)
assert(p_shortcut != null, "(%s) missing parameter 'shortcut'" % p_name)
self.name = p_name
self.is_enabled = p_is_enabled
self.shortcut = p_shortcut
self.runnable = p_runnable
var name: String:
set(value):
name = value
get:
return name
var shortcut: GdUnitShortcut.ShortCut:
set(value):
shortcut = value
get:
return shortcut
var is_enabled: Callable:
set(value):
is_enabled = value
get:
return is_enabled
var runnable: Callable:
set(value):
runnable = value
get:
return runnable

View file

@ -0,0 +1,357 @@
class_name GdUnitCommandHandler
extends RefCounted
signal gdunit_runner_start()
signal gdunit_runner_stop(client_id :int)
const GdUnitTools := preload("res://addons/gdUnit4/src/core/GdUnitTools.gd")
const CMD_RUN_OVERALL = "Debug Overall TestSuites"
const CMD_RUN_TESTCASE = "Run TestCases"
const CMD_RUN_TESTCASE_DEBUG = "Run TestCases (Debug)"
const CMD_RUN_TESTSUITE = "Run TestSuites"
const CMD_RUN_TESTSUITE_DEBUG = "Run TestSuites (Debug)"
const CMD_RERUN_TESTS = "ReRun Tests"
const CMD_RERUN_TESTS_DEBUG = "ReRun Tests (Debug)"
const CMD_STOP_TEST_RUN = "Stop Test Run"
const CMD_CREATE_TESTCASE = "Create TestCase"
const SETTINGS_SHORTCUT_MAPPING := {
"N/A" : GdUnitShortcut.ShortCut.NONE,
GdUnitSettings.SHORTCUT_INSPECTOR_RERUN_TEST : GdUnitShortcut.ShortCut.RERUN_TESTS,
GdUnitSettings.SHORTCUT_INSPECTOR_RERUN_TEST_DEBUG : GdUnitShortcut.ShortCut.RERUN_TESTS_DEBUG,
GdUnitSettings.SHORTCUT_INSPECTOR_RUN_TEST_OVERALL : GdUnitShortcut.ShortCut.RUN_TESTS_OVERALL,
GdUnitSettings.SHORTCUT_INSPECTOR_RUN_TEST_STOP : GdUnitShortcut.ShortCut.STOP_TEST_RUN,
GdUnitSettings.SHORTCUT_EDITOR_RUN_TEST : GdUnitShortcut.ShortCut.RUN_TESTCASE,
GdUnitSettings.SHORTCUT_EDITOR_RUN_TEST_DEBUG : GdUnitShortcut.ShortCut.RUN_TESTCASE_DEBUG,
GdUnitSettings.SHORTCUT_EDITOR_CREATE_TEST : GdUnitShortcut.ShortCut.CREATE_TEST,
GdUnitSettings.SHORTCUT_FILESYSTEM_RUN_TEST : GdUnitShortcut.ShortCut.RUN_TESTCASE,
GdUnitSettings.SHORTCUT_FILESYSTEM_RUN_TEST_DEBUG : GdUnitShortcut.ShortCut.RUN_TESTCASE_DEBUG
}
var _editor_interface :EditorInterface
# the current test runner config
var _runner_config := GdUnitRunnerConfig.new()
# holds the current connected gdUnit runner client id
var _client_id :int
# if no debug mode we have an process id
var _current_runner_process_id :int = 0
# hold is current an test running
var _is_running :bool = false
# holds if the current running tests started in debug mode
var _running_debug_mode :bool
var _commands := {}
var _shortcuts := {}
static func instance() -> GdUnitCommandHandler:
return GdUnitSingleton.instance("GdUnitCommandHandler", func(): return GdUnitCommandHandler.new())
func _init():
assert_shortcut_mappings(SETTINGS_SHORTCUT_MAPPING)
if Engine.is_editor_hint():
var editor :EditorPlugin = Engine.get_meta("GdUnitEditorPlugin")
_editor_interface = editor.get_editor_interface()
GdUnitSignals.instance().gdunit_event.connect(_on_event)
GdUnitSignals.instance().gdunit_client_connected.connect(_on_client_connected)
GdUnitSignals.instance().gdunit_client_disconnected.connect(_on_client_disconnected)
GdUnitSignals.instance().gdunit_settings_changed.connect(_on_settings_changed)
# preload previous test execution
_runner_config.load_config()
init_shortcuts()
var is_running = func(_script :Script) : return _is_running
var is_not_running = func(_script :Script) : return !_is_running
register_command(GdUnitCommand.new(CMD_RUN_OVERALL, is_not_running, cmd_run_overall.bind(true), GdUnitShortcut.ShortCut.RUN_TESTS_OVERALL))
register_command(GdUnitCommand.new(CMD_RUN_TESTCASE, is_not_running, cmd_editor_run_test.bind(false), GdUnitShortcut.ShortCut.RUN_TESTCASE))
register_command(GdUnitCommand.new(CMD_RUN_TESTCASE_DEBUG, is_not_running, cmd_editor_run_test.bind(true), GdUnitShortcut.ShortCut.RUN_TESTCASE_DEBUG))
register_command(GdUnitCommand.new(CMD_RUN_TESTSUITE, is_not_running, cmd_run_test_suites.bind(false)))
register_command(GdUnitCommand.new(CMD_RUN_TESTSUITE_DEBUG, is_not_running, cmd_run_test_suites.bind(true)))
register_command(GdUnitCommand.new(CMD_RERUN_TESTS, is_not_running, cmd_run.bind(false), GdUnitShortcut.ShortCut.RERUN_TESTS))
register_command(GdUnitCommand.new(CMD_RERUN_TESTS_DEBUG, is_not_running, cmd_run.bind(true), GdUnitShortcut.ShortCut.RERUN_TESTS_DEBUG))
register_command(GdUnitCommand.new(CMD_CREATE_TESTCASE, is_not_running, cmd_create_test, GdUnitShortcut.ShortCut.CREATE_TEST))
register_command(GdUnitCommand.new(CMD_STOP_TEST_RUN, is_running, cmd_stop.bind(_client_id), GdUnitShortcut.ShortCut.STOP_TEST_RUN))
func _notification(what):
if what == NOTIFICATION_PREDELETE:
_commands.clear()
_shortcuts.clear()
func _do_process() -> void:
check_test_run_stopped_manually()
# is checking if the user has press the editor stop scene
func check_test_run_stopped_manually():
if is_test_running_but_stop_pressed():
if GdUnitSettings.is_verbose_assert_warnings():
push_warning("Test Runner scene was stopped manually, force stopping the current test run!")
cmd_stop(_client_id)
func is_test_running_but_stop_pressed():
return _editor_interface and _running_debug_mode and _is_running and not _editor_interface.is_playing_scene()
func assert_shortcut_mappings(mappings :Dictionary) -> void:
for shortcut in GdUnitShortcut.ShortCut.values():
assert(mappings.values().has(shortcut), "missing settings mapping for shortcut '%s'!" % GdUnitShortcut.ShortCut.keys()[shortcut])
func init_shortcuts() -> void:
for shortcut in GdUnitShortcut.ShortCut.values():
if shortcut == GdUnitShortcut.ShortCut.NONE:
continue
var property_name :String = SETTINGS_SHORTCUT_MAPPING.find_key(shortcut)
var property := GdUnitSettings.get_property(property_name)
var keys := GdUnitShortcut.default_keys(shortcut)
if property != null:
keys = property.value()
var inputEvent := create_shortcut_input_even(keys)
register_shortcut(shortcut, inputEvent)
func create_shortcut_input_even(key_codes : PackedInt32Array) -> InputEventKey:
var inputEvent :InputEventKey = InputEventKey.new()
inputEvent.pressed = true
for key_code in key_codes:
match key_code:
KEY_ALT:
inputEvent.alt_pressed = true
KEY_SHIFT:
inputEvent.shift_pressed = true
KEY_CTRL:
inputEvent.ctrl_pressed = true
_:
inputEvent.keycode = key_code as Key
inputEvent.physical_keycode = key_code as Key
return inputEvent
func register_shortcut(p_shortcut :GdUnitShortcut.ShortCut, p_input_event :InputEvent) -> void:
GdUnitTools.prints_verbose("register shortcut: '%s' to '%s'" % [GdUnitShortcut.ShortCut.keys()[p_shortcut], p_input_event.as_text()])
var shortcut := Shortcut.new()
shortcut.set_events([p_input_event])
var command_name :String = get_shortcut_command(p_shortcut)
_shortcuts[p_shortcut] = GdUnitShortcutAction.new(p_shortcut, shortcut, command_name)
func get_shortcut(shortcut_type :GdUnitShortcut.ShortCut) -> Shortcut:
return get_shortcut_action(shortcut_type).shortcut
func get_shortcut_action(shortcut_type :GdUnitShortcut.ShortCut) -> GdUnitShortcutAction:
return _shortcuts.get(shortcut_type)
func get_shortcut_command(p_shortcut :GdUnitShortcut.ShortCut) -> String:
return GdUnitShortcut.CommandMapping.get(p_shortcut, "unknown command")
func register_command(p_command :GdUnitCommand) -> void:
_commands[p_command.name] = p_command
func command(cmd_name :String) -> GdUnitCommand:
return _commands.get(cmd_name)
func cmd_run_test_suites(test_suite_paths :PackedStringArray, debug :bool, rerun := false) -> void:
# create new runner runner_config for fresh run otherwise use saved one
if not rerun:
var result := _runner_config.clear()\
.add_test_suites(test_suite_paths)\
.save_config()
if result.is_error():
push_error(result.error_message())
return
cmd_run(debug)
func cmd_run_test_case(test_suite_resource_path :String, test_case :String, test_param_index :int, debug :bool, rerun := false) -> void:
# create new runner config for fresh run otherwise use saved one
if not rerun:
var result := _runner_config.clear()\
.add_test_case(test_suite_resource_path, test_case, test_param_index)\
.save_config()
if result.is_error():
push_error(result.error_message())
return
cmd_run(debug)
func cmd_run_overall(debug :bool) -> void:
var test_suite_paths :PackedStringArray = GdUnitCommandHandler.scan_test_directorys("res://" , GdUnitSettings.test_root_folder(), [])
var result := _runner_config.clear()\
.add_test_suites(test_suite_paths)\
.save_config()
if result.is_error():
push_error(result.error_message())
return
cmd_run(debug)
func cmd_run(debug :bool) -> void:
# don't start is already running
if _is_running:
return
# save current selected excution config
var result := _runner_config.set_server_port(Engine.get_meta("gdunit_server_port")).save_config()
if result.is_error():
push_error(result.error_message())
return
# before start we have to save all changes
ScriptEditorControls.save_all_open_script()
gdunit_runner_start.emit()
_current_runner_process_id = -1
_running_debug_mode = debug
if debug:
run_debug_mode()
else:
run_release_mode()
func cmd_stop(client_id :int) -> void:
# don't stop if is already stopped
if not _is_running:
return
_is_running = false
gdunit_runner_stop.emit(client_id)
if _running_debug_mode:
_editor_interface.stop_playing_scene()
else: if _current_runner_process_id > 0:
var result = OS.kill(_current_runner_process_id)
if result != OK:
push_error("ERROR checked stopping GdUnit Test Runner. error code: %s" % result)
_current_runner_process_id = -1
func cmd_editor_run_test(debug :bool):
var cursor_line := active_base_editor().get_caret_line()
#run test case?
var regex := RegEx.new()
regex.compile("(^func[ ,\t])(test_[a-zA-Z0-9_]*)")
var result := regex.search(active_base_editor().get_line(cursor_line))
if result:
var func_name := result.get_string(2).strip_edges()
prints("Run test:", func_name, "debug", debug)
if func_name.begins_with("test_"):
cmd_run_test_case(active_script().resource_path, func_name, -1, debug)
return
# otherwise run the full test suite
var selected_test_suites := [active_script().resource_path]
cmd_run_test_suites(selected_test_suites, debug)
func cmd_create_test() -> void:
var cursor_line := active_base_editor().get_caret_line()
var result := GdUnitTestSuiteBuilder.create(active_script(), cursor_line)
if result.is_error():
# show error dialog
push_error("Failed to create test case: %s" % result.error_message())
return
var info := result.value() as Dictionary
ScriptEditorControls.edit_script(info.get("path"), info.get("line"))
static func scan_test_directorys(base_directory :String, test_directory: String, test_suite_paths :PackedStringArray) -> PackedStringArray:
print_verbose("Scannning for test directory '%s' at %s" % [test_directory, base_directory])
for directory in DirAccess.get_directories_at(base_directory):
if directory.begins_with("."):
continue
var current_directory := normalize_path(base_directory + "/" + directory)
if GdUnitTestSuiteScanner.exclude_scan_directories.has(current_directory):
continue
if match_test_directory(directory, test_directory):
prints("Collect tests at:", current_directory)
test_suite_paths.append(current_directory)
else:
scan_test_directorys(current_directory, test_directory, test_suite_paths)
return test_suite_paths
static func normalize_path(path :String) -> String:
return path.replace("///", "//")
static func match_test_directory(directory :String, test_directory: String) -> bool:
return directory == test_directory or test_directory.is_empty() or test_directory == "/" or test_directory == "res://"
func run_debug_mode():
_editor_interface.play_custom_scene("res://addons/gdUnit4/src/core/GdUnitRunner.tscn")
_is_running = true
func run_release_mode():
var arguments := Array()
if OS.is_stdout_verbose():
arguments.append("--verbose")
arguments.append("--no-window")
arguments.append("--path")
arguments.append(ProjectSettings.globalize_path("res://"))
arguments.append("res://addons/gdUnit4/src/core/GdUnitRunner.tscn")
_current_runner_process_id = OS.create_process(OS.get_executable_path(), arguments, false);
_is_running = true
func script_editor() -> ScriptEditor:
return _editor_interface.get_script_editor()
func active_base_editor() -> TextEdit:
return script_editor().get_current_editor().get_base_editor()
func active_script() -> Script:
return script_editor().get_current_script()
################################################################################
# signals handles
################################################################################
func _on_event(event :GdUnitEvent):
if event.type() == GdUnitEvent.STOP:
cmd_stop(_client_id)
func _on_stop_pressed():
cmd_stop(_client_id)
func _on_run_pressed(debug := false):
cmd_run(debug)
func _on_run_overall_pressed(_debug := false):
cmd_run_overall(true)
func _on_settings_changed(property :GdUnitProperty):
if SETTINGS_SHORTCUT_MAPPING.has(property.name()):
var shortcut :GdUnitShortcut.ShortCut = SETTINGS_SHORTCUT_MAPPING.get(property.name())
var input_event := create_shortcut_input_even(property.value())
prints("Shortcut changed: '%s' to '%s'" % [GdUnitShortcut.ShortCut.keys()[shortcut], input_event.as_text()])
register_shortcut(shortcut, input_event)
################################################################################
# Network stuff
################################################################################
func _on_client_connected(client_id :int) -> void:
_client_id = client_id
func _on_client_disconnected(client_id :int) -> void:
# only stops is not in debug mode running and the current client
if not _running_debug_mode and _client_id == client_id:
cmd_stop(client_id)
_client_id = -1

View file

@ -0,0 +1,58 @@
class_name GdUnitShortcut
extends RefCounted
enum ShortCut {
NONE,
RUN_TESTS_OVERALL,
RUN_TESTCASE,
RUN_TESTCASE_DEBUG,
RERUN_TESTS,
RERUN_TESTS_DEBUG,
STOP_TEST_RUN,
CREATE_TEST,
}
const CommandMapping = {
ShortCut.RUN_TESTS_OVERALL: GdUnitCommandHandler.CMD_RUN_OVERALL,
ShortCut.RUN_TESTCASE: GdUnitCommandHandler.CMD_RUN_TESTCASE,
ShortCut.RUN_TESTCASE_DEBUG: GdUnitCommandHandler.CMD_RUN_TESTCASE_DEBUG,
ShortCut.RERUN_TESTS: GdUnitCommandHandler.CMD_RERUN_TESTS,
ShortCut.RERUN_TESTS_DEBUG: GdUnitCommandHandler.CMD_RERUN_TESTS_DEBUG,
ShortCut.STOP_TEST_RUN: GdUnitCommandHandler.CMD_STOP_TEST_RUN,
ShortCut.CREATE_TEST: GdUnitCommandHandler.CMD_CREATE_TESTCASE,
}
const DEFAULTS_MACOS := {
ShortCut.NONE : [],
ShortCut.RUN_TESTCASE : [Key.KEY_META, Key.KEY_ALT, Key.KEY_F5],
ShortCut.RUN_TESTCASE_DEBUG : [Key.KEY_META, Key.KEY_ALT, Key.KEY_F6],
ShortCut.RUN_TESTS_OVERALL : [Key.KEY_META, Key.KEY_F7],
ShortCut.STOP_TEST_RUN : [Key.KEY_META, Key.KEY_F8],
ShortCut.RERUN_TESTS : [Key.KEY_META, Key.KEY_F5],
ShortCut.RERUN_TESTS_DEBUG : [Key.KEY_META, Key.KEY_F6],
ShortCut.CREATE_TEST : [Key.KEY_META, Key.KEY_ALT, Key.KEY_F10],
}
const DEFAULTS_WINDOWS := {
ShortCut.NONE : [],
ShortCut.RUN_TESTCASE : [Key.KEY_CTRL, Key.KEY_ALT, Key.KEY_F5],
ShortCut.RUN_TESTCASE_DEBUG : [Key.KEY_CTRL,Key.KEY_ALT, Key.KEY_F6],
ShortCut.RUN_TESTS_OVERALL : [Key.KEY_CTRL, Key.KEY_F7],
ShortCut.STOP_TEST_RUN : [Key.KEY_CTRL, Key.KEY_F8],
ShortCut.RERUN_TESTS : [Key.KEY_CTRL, Key.KEY_F5],
ShortCut.RERUN_TESTS_DEBUG : [Key.KEY_CTRL, Key.KEY_F6],
ShortCut.CREATE_TEST : [Key.KEY_CTRL, Key.KEY_ALT, Key.KEY_F10],
}
static func default_keys(shortcut :ShortCut) -> PackedInt32Array:
match OS.get_name().to_lower():
'windows':
return DEFAULTS_WINDOWS[shortcut]
'macos':
return DEFAULTS_MACOS[shortcut]
_:
return DEFAULTS_WINDOWS[shortcut]

View file

@ -0,0 +1,36 @@
class_name GdUnitShortcutAction
extends RefCounted
func _init(p_type :GdUnitShortcut.ShortCut, p_shortcut :Shortcut, p_command :String):
assert(p_type != null, "missing parameter 'type'")
assert(p_shortcut != null, "missing parameter 'shortcut'")
assert(p_command != null, "missing parameter 'command'")
self.type = p_type
self.shortcut = p_shortcut
self.command = p_command
var type: GdUnitShortcut.ShortCut:
set(value):
type = value
get:
return type
var shortcut: Shortcut:
set(value):
shortcut = value
get:
return shortcut
var command: String:
set(value):
command = value
get:
return command
func _to_string() -> String:
return "GdUnitShortcutAction: %s (%s) -> %s" % [GdUnitShortcut.ShortCut.keys()[type], shortcut.get_as_text(), command]