summaryrefslogtreecommitdiff
path: root/addons/gdUnit4/src/dotnet/GdUnit4CSharpApiLoader.gd
diff options
context:
space:
mode:
Diffstat (limited to 'addons/gdUnit4/src/dotnet/GdUnit4CSharpApiLoader.gd')
-rw-r--r--addons/gdUnit4/src/dotnet/GdUnit4CSharpApiLoader.gd114
1 files changed, 114 insertions, 0 deletions
diff --git a/addons/gdUnit4/src/dotnet/GdUnit4CSharpApiLoader.gd b/addons/gdUnit4/src/dotnet/GdUnit4CSharpApiLoader.gd
new file mode 100644
index 0000000..3d8ba25
--- /dev/null
+++ b/addons/gdUnit4/src/dotnet/GdUnit4CSharpApiLoader.gd
@@ -0,0 +1,114 @@
+## GdUnit4CSharpApiLoader
+##
+## A bridge class that handles communication between GDScript and C# for the GdUnit4 testing framework.
+## This loader acts as a compatibility layer to safely access the .NET API and ensure that calls
+## only proceed when the .NET environment is properly configured and available.
+## [br]
+## The class handles:
+## - Verification of .NET runtime availability
+## - Loading the C# wrapper script
+## - Checking for the GdUnit4Api assembly
+## - Providing proxy methods to access GdUnit4 functionality in C#
+@static_unload
+class_name GdUnit4CSharpApiLoader
+extends RefCounted
+
+## Cached reference to the loaded C# wrapper script
+static var _gdUnit4NetWrapper: Script
+
+## Cached instance of the API (singleton pattern)
+static var _api_instance: RefCounted
+
+
+class TestEventListener extends RefCounted:
+
+ func publish_event(event: Dictionary) -> void:
+ var test_event := GdUnitEvent.new().deserialize(event)
+ GdUnitSignals.instance().gdunit_event.emit(test_event)
+
+static var _test_event_listener := TestEventListener.new()
+
+
+## Returns an instance of the GdUnit4CSharpApi wrapper.[br]
+## @return Script: The loaded C# wrapper or null if .NET is not supported
+static func instance() -> Script:
+ if not GdUnit4CSharpApiLoader.is_api_loaded():
+ return null
+
+ return _gdUnit4NetWrapper
+
+
+## Returns or creates a single instance of the API [br]
+## This improves performance by reusing the same object
+static func api_instance() -> RefCounted:
+ if _api_instance == null and is_api_loaded():
+ @warning_ignore("unsafe_method_access")
+ _api_instance = instance().new()
+ return _api_instance
+
+
+static func is_engine_version_supported(engine_version: int = Engine.get_version_info().hex) -> bool:
+ return engine_version >= 0x40200
+
+
+## Checks if the .NET environment is properly configured and available.[br]
+## @return bool: True if .NET is fully supported and the assembly is found
+static func is_api_loaded() -> bool:
+ # If the wrapper is already loaded we don't need to check again
+ if _gdUnit4NetWrapper != null:
+ return true
+
+ # First we check if this is a Godot .NET runtime instance
+ if not ClassDB.class_exists("CSharpScript") or not is_engine_version_supported():
+ return false
+ # Second we check the C# project file exists
+ var assembly_name: String = ProjectSettings.get_setting("dotnet/project/assembly_name")
+ if assembly_name.is_empty() or not FileAccess.file_exists("res://%s.csproj" % assembly_name):
+ return false
+
+ # Finally load the wrapper and check if the GdUnit4 assembly can be found
+ _gdUnit4NetWrapper = load("res://addons/gdUnit4/src/dotnet/GdUnit4CSharpApi.cs")
+ @warning_ignore("unsafe_method_access")
+ return _gdUnit4NetWrapper.call("IsApiLoaded")
+
+
+## Returns the version of the GdUnit4 .NET assembly.[br]
+## @return String: The version string or "unknown" if .NET is not supported
+static func version() -> String:
+ if not GdUnit4CSharpApiLoader.is_api_loaded():
+ return "unknown"
+ @warning_ignore("unsafe_method_access")
+ return instance().Version()
+
+
+static func discover_tests(source_script: Script) -> Array[GdUnitTestCase]:
+ var tests: Array = _gdUnit4NetWrapper.call("DiscoverTests", source_script)
+
+ return Array(tests.map(GdUnitTestCase.from_dict), TYPE_OBJECT, "RefCounted", GdUnitTestCase)
+
+
+static func execute(tests: Array[GdUnitTestCase]) -> void:
+ var net_api := api_instance()
+ if net_api == null:
+ push_warning("Execute C# tests not supported!")
+ return
+ var tests_as_dict: Array[Dictionary] = Array(tests.map(GdUnitTestCase.to_dict), TYPE_DICTIONARY, "", null)
+
+ net_api.call("ExecuteAsync", tests_as_dict, _test_event_listener.publish_event)
+ @warning_ignore("unsafe_property_access")
+ await net_api.ExecutionCompleted
+
+
+static func create_test_suite(source_path: String, line_number: int, test_suite_path: String) -> GdUnitResult:
+ if not GdUnit4CSharpApiLoader.is_api_loaded():
+ return GdUnitResult.error("Can't create test suite. No .NET support found.")
+ @warning_ignore("unsafe_method_access")
+ var result: Dictionary = instance().CreateTestSuite(source_path, line_number, test_suite_path)
+ if result.has("error"):
+ return GdUnitResult.error(str(result.get("error")))
+ return GdUnitResult.success(result)
+
+
+static func is_csharp_file(resource_path: String) -> bool:
+ var ext := resource_path.get_extension()
+ return ext == "cs" and GdUnit4CSharpApiLoader.is_api_loaded()