summaryrefslogtreecommitdiff
path: root/addons/gdUnit4/src/core/thread
diff options
context:
space:
mode:
Diffstat (limited to 'addons/gdUnit4/src/core/thread')
-rw-r--r--addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd70
-rw-r--r--addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd.uid1
-rw-r--r--addons/gdUnit4/src/core/thread/GdUnitThreadManager.gd69
-rw-r--r--addons/gdUnit4/src/core/thread/GdUnitThreadManager.gd.uid1
4 files changed, 141 insertions, 0 deletions
diff --git a/addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd b/addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd
new file mode 100644
index 0000000..402199b
--- /dev/null
+++ b/addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd
@@ -0,0 +1,70 @@
+class_name GdUnitThreadContext
+extends RefCounted
+
+var _thread: Thread
+var _thread_name: String
+var _thread_id: int
+var _signal_collector: GdUnitSignalCollector
+var _execution_context: GdUnitExecutionContext
+var _asserts := []
+
+
+func _init(thread: Thread = null) -> void:
+ if thread != null:
+ _thread = thread
+ _thread_name = thread.get_meta("name")
+ _thread_id = thread.get_id() as int
+ else:
+ _thread_name = "main"
+ _thread_id = OS.get_main_thread_id()
+ _signal_collector = GdUnitSignalCollector.new()
+
+
+func dispose() -> void:
+ clear_assert()
+ if is_instance_valid(_signal_collector):
+ _signal_collector.clear()
+ _signal_collector = null
+ _execution_context = null
+ _thread = null
+
+
+func terminate() -> void:
+ _execution_context.terminate()
+
+
+func clear_assert() -> void:
+ _asserts.clear()
+
+
+func set_assert(value: GdUnitAssert) -> void:
+ if value != null:
+ _asserts.append(value)
+
+
+func get_assert() -> GdUnitAssert:
+ return null if _asserts.is_empty() else _asserts[-1]
+
+
+func set_execution_context(context: GdUnitExecutionContext) -> void:
+ _execution_context = context
+
+
+func get_execution_context() -> GdUnitExecutionContext:
+ return _execution_context
+
+
+func get_execution_context_id() -> int:
+ return _execution_context.get_instance_id()
+
+
+func get_signal_collector() -> GdUnitSignalCollector:
+ return _signal_collector
+
+
+func thread_id() -> int:
+ return _thread_id
+
+
+func _to_string() -> String:
+ return "ThreadContext <%s>: %s " % [_thread_name, _thread_id]
diff --git a/addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd.uid b/addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd.uid
new file mode 100644
index 0000000..01dc8f6
--- /dev/null
+++ b/addons/gdUnit4/src/core/thread/GdUnitThreadContext.gd.uid
@@ -0,0 +1 @@
+uid://c8t88hv3p8rvu
diff --git a/addons/gdUnit4/src/core/thread/GdUnitThreadManager.gd b/addons/gdUnit4/src/core/thread/GdUnitThreadManager.gd
new file mode 100644
index 0000000..2e694e2
--- /dev/null
+++ b/addons/gdUnit4/src/core/thread/GdUnitThreadManager.gd
@@ -0,0 +1,69 @@
+## A manager to run new thread and crate a ThreadContext shared over the actual test run
+class_name GdUnitThreadManager
+extends Object
+
+## { <thread_id> = <GdUnitThreadContext> }
+var _thread_context_by_id: Dictionary[int, GdUnitThreadContext] = {}
+## holds the current thread id
+var _current_thread_id :int = -1
+
+func _init() -> void:
+ # add initail the main thread
+ _current_thread_id = OS.get_thread_caller_id()
+ _thread_context_by_id[OS.get_main_thread_id()] = GdUnitThreadContext.new()
+
+
+static func instance() -> GdUnitThreadManager:
+ return GdUnitSingleton.instance("GdUnitThreadManager", func() -> GdUnitThreadManager: return GdUnitThreadManager.new())
+
+
+## Runs a new thread by given name and Callable.[br]
+## A new GdUnitThreadContext is created, which is used for the actual test execution.[br]
+## We need this custom implementation while this bug is not solved
+## Godot issue https://github.com/godotengine/godot/issues/79637
+static func run(name :String, cb :Callable) -> Variant:
+ return await instance()._run(name, cb)
+
+
+static func interrupt() -> void:
+ for thread_context: GdUnitThreadContext in instance()._thread_context_by_id.values():
+ thread_context.terminate()
+
+
+## Returns the current valid thread context
+static func get_current_context() -> GdUnitThreadContext:
+ return instance()._get_current_context()
+
+
+func _run(name :String, cb :Callable) -> Variant:
+ # we do this hack because of `OS.get_thread_caller_id()` not returns the current id
+ # when await process_frame is called inside the fread
+ var save_current_thread_id := _current_thread_id
+ var thread := Thread.new()
+ thread.set_meta("name", name)
+ @warning_ignore("return_value_discarded")
+ thread.start(cb)
+ _current_thread_id = thread.get_id() as int
+ _register_thread(thread, _current_thread_id)
+ var result :Variant = await thread.wait_to_finish()
+ _unregister_thread(_current_thread_id)
+ # restore original thread id
+ _current_thread_id = save_current_thread_id
+ return result
+
+
+func _register_thread(thread :Thread, thread_id :int) -> void:
+ var context := GdUnitThreadContext.new(thread)
+ _thread_context_by_id[thread_id] = context
+
+
+func _unregister_thread(thread_id :int) -> void:
+ var context: GdUnitThreadContext = _thread_context_by_id.get(thread_id)
+ if context:
+ @warning_ignore("return_value_discarded")
+ _thread_context_by_id.erase(thread_id)
+ context.dispose()
+
+
+func _get_current_context() -> GdUnitThreadContext:
+ return _thread_context_by_id.get(_current_thread_id)
diff --git a/addons/gdUnit4/src/core/thread/GdUnitThreadManager.gd.uid b/addons/gdUnit4/src/core/thread/GdUnitThreadManager.gd.uid
new file mode 100644
index 0000000..b943f92
--- /dev/null
+++ b/addons/gdUnit4/src/core/thread/GdUnitThreadManager.gd.uid
@@ -0,0 +1 @@
+uid://7j6xocp0kaix