Skip to content

Commit

Permalink
GD-343: Fix .NET: Failed to unload assemblies error when unload the…
Browse files Browse the repository at this point in the history
… plugin

# Why
Some GdUnit4 users reported these errors on discord -> https://discordapp.com/channels/885149082119733269/1201435634875764756

# What
* do not extend anymore from the gdunit assembly, we only load the class and use the static methods
* rename classes from `mono` to `csharp` (mono is outdated)
  • Loading branch information
Nullpointer committed Feb 10, 2024
1 parent a5509d9 commit 3cb0a7c
Show file tree
Hide file tree
Showing 15 changed files with 80 additions and 77 deletions.
4 changes: 3 additions & 1 deletion .github/workflows/ci-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@ jobs:
godot-status: ['stable']
godot-net: ['.Net', '']
include:
- godot-version: '4.2.2'
godot-status: 'rc1'
- godot-version: '4.3'
godot-status: 'dev2'
godot-status: 'dev3'

permissions:
actions: write
Expand Down
6 changes: 3 additions & 3 deletions addons/gdUnit4/bin/GdUnitCmdTool.gd
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,9 @@ class CLIRunner:
_executor = load("res://addons/gdUnit4/src/core/execution/GdUnitTestSuiteExecutor.gd").new()
# stop checked first test failure to fail fast
_executor.fail_fast(true)
if GdUnit4MonoApiLoader.is_mono_supported():
prints("GdUnit4Mono Version %s loaded." % GdUnit4MonoApiLoader.version())
_cs_executor = GdUnit4MonoApiLoader.create_executor(self)
if GdUnit4CSharpApiLoader.is_mono_supported():
prints("GdUnit4Mono Version %s loaded." % GdUnit4CSharpApiLoader.version())
_cs_executor = GdUnit4CSharpApiLoader.create_executor(self)
var err := GdUnitSignals.instance().gdunit_event.connect(_on_gdunit_event)
if err != OK:
prints("gdUnitSignals failed")
Expand Down
4 changes: 2 additions & 2 deletions addons/gdUnit4/plugin.gd
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ func _enter_tree() -> void:
if GdUnitSettings.is_update_notification_enabled():
var update_tool :Node = load("res://addons/gdUnit4/src/update/GdUnitUpdateNotify.tscn").instantiate()
Engine.get_main_loop().root.call_deferred("add_child", update_tool)
if GdUnit4MonoApiLoader.is_mono_supported():
prints("GdUnit4Mono Version %s loaded." % GdUnit4MonoApiLoader.version())
if GdUnit4CSharpApiLoader.is_mono_supported():
prints("GdUnit4Mono Version %s loaded." % GdUnit4CSharpApiLoader.version())


func _exit_tree() -> void:
Expand Down
2 changes: 1 addition & 1 deletion addons/gdUnit4/src/core/GdObjects.gd
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ static func is_script(value :Variant) -> bool:


static func is_test_suite(script :Script) -> bool:
return is_gd_testsuite(script) or GdUnit4MonoApiLoader.is_test_suite(script.resource_path)
return is_gd_testsuite(script) or GdUnit4CSharpApiLoader.is_test_suite(script.resource_path)


static func is_native_class(value :Variant) -> bool:
Expand Down
2 changes: 1 addition & 1 deletion addons/gdUnit4/src/core/GdUnitRunner.gd
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func _init() -> void:
DisplayServer.window_set_mode(DisplayServer.WINDOW_MODE_MINIMIZED)
# store current runner instance to engine meta data to can be access in as a singleton
Engine.set_meta(GDUNIT_RUNNER, self)
_cs_executor = GdUnit4MonoApiLoader.create_executor(self)
_cs_executor = GdUnit4CSharpApiLoader.create_executor(self)


func _ready() -> void:
Expand Down
2 changes: 1 addition & 1 deletion addons/gdUnit4/src/core/GdUnitTestSuiteBuilder.gd
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ static func create(source :Script, line_number :int) -> GdUnitResult:
ScriptEditorControls.save_an_open_script(source.resource_path)
ScriptEditorControls.save_an_open_script(test_suite_path, true)
if GdObjects.is_cs_script(source):
return GdUnit4MonoApiLoader.create_test_suite(source.resource_path, line_number+1, test_suite_path)
return GdUnit4CSharpApiLoader.create_test_suite(source.resource_path, line_number+1, test_suite_path)
var parser := GdScriptParser.new()
var lines := source.source_code.split("\n")
var current_line := lines[line_number]
Expand Down
6 changes: 3 additions & 3 deletions addons/gdUnit4/src/core/GdUnitTestSuiteScanner.gd
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,8 @@ static func _file(dir :DirAccess, file_name :String) -> String:
func _parse_is_test_suite(resource_path :String) -> Node:
if not GdUnitTestSuiteScanner._is_script_format_supported(resource_path):
return null
if GdUnit4MonoApiLoader.is_test_suite(resource_path):
return GdUnit4MonoApiLoader.parse_test_suite(resource_path)
if GdUnit4CSharpApiLoader.is_test_suite(resource_path):
return GdUnit4CSharpApiLoader.parse_test_suite(resource_path)
var script :Script = ResourceLoader.load(resource_path)
if not GdObjects.is_test_suite(script):
return null
Expand All @@ -93,7 +93,7 @@ static func _is_script_format_supported(resource_path :String) -> bool:
var ext := resource_path.get_extension()
if ext == "gd":
return true
return GdUnit4MonoApiLoader.is_csharp_file(resource_path)
return GdUnit4CSharpApiLoader.is_csharp_file(resource_path)


func _parse_test_suite(script :GDScript) -> GdUnitTestSuite:
Expand Down
19 changes: 19 additions & 0 deletions addons/gdUnit4/src/mono/GdUnit4CSharpApi.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Godot;
using Godot.Collections;

using GdUnit4;

// GdUnit4 GDScript - C# API wrapper
public partial class GdUnit4CSharpApi : RefCounted
{
public static string Version() => GdUnit4MonoAPI.Version();

public static bool IsTestSuite(string classPath) => GdUnit4MonoAPI.IsTestSuite(classPath);

public static RefCounted Executor(Node listener) => (RefCounted)GdUnit4MonoAPI.Executor(listener);

public static GdUnit4.CsNode? ParseTestSuite(string classPath) => GdUnit4MonoAPI.ParseTestSuite(classPath);

public static Dictionary CreateTestSuite(string sourcePath, int lineNumber, string testSuitePath) =>
GdUnit4MonoAPI.CreateTestSuite(sourcePath, lineNumber, testSuitePath);
}
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
extends RefCounted
class_name GdUnit4MonoApiLoader
class_name GdUnit4CSharpApiLoader


static func instance() -> Object:
return GdUnitSingleton.instance("GdUnit4MonoAPI", func() -> Object:
if not GdUnit4MonoApiLoader.is_mono_supported():
return GdUnitSingleton.instance("GdUnit4CSharpApi", func() -> Object:
if not GdUnit4CSharpApiLoader.is_mono_supported():
return null
var GdUnit4MonoApi := load("res://addons/gdUnit4/src/mono/GdUnit4MonoApi.cs")
return GdUnit4MonoApi.new()
return load("res://addons/gdUnit4/src/mono/GdUnit4CSharpApi.cs")
)


static func is_engine_version_supported(engine_version :int = Engine.get_version_info().hex) -> bool:
return engine_version >= 0x40100
return engine_version >= 0x40200


# test is Godot mono running
Expand All @@ -21,23 +20,24 @@ static func is_mono_supported() -> bool:


static func version() -> String:
if not GdUnit4MonoApiLoader.is_mono_supported():
if not GdUnit4CSharpApiLoader.is_mono_supported():
return "unknown"
return instance().Version()


static func create_test_suite(source_path :String, line_number :int, test_suite_path :String) -> GdUnitResult:
if not GdUnit4MonoApiLoader.is_mono_supported():
return GdUnitResult.error("Can't create test suite. No c# support found.")
if not GdUnit4CSharpApiLoader.is_mono_supported():
return GdUnitResult.error("Can't create test suite. No C# support found.")
var result := instance().CreateTestSuite(source_path, line_number, test_suite_path) as Dictionary
if result.has("error"):
return GdUnitResult.error(result.get("error"))
return GdUnitResult.success(result)


static func is_test_suite(resource_path :String) -> bool:
if not is_csharp_file(resource_path) or not GdUnit4MonoApiLoader.is_mono_supported():
if not is_csharp_file(resource_path) or not GdUnit4CSharpApiLoader.is_mono_supported():
return false

if resource_path.is_empty():
if GdUnitSettings.is_report_push_errors():
push_error("Can't create test suite. Missing resource path.")
Expand All @@ -46,19 +46,19 @@ static func is_test_suite(resource_path :String) -> bool:


static func parse_test_suite(source_path :String) -> Node:
if not GdUnit4MonoApiLoader.is_mono_supported():
if not GdUnit4CSharpApiLoader.is_mono_supported():
if GdUnitSettings.is_report_push_errors():
push_error("Can't create test suite. No c# support found.")
return null
return instance().ParseTestSuite(source_path)


static func create_executor(listener :Node) -> RefCounted:
if not GdUnit4MonoApiLoader.is_mono_supported():
if not GdUnit4CSharpApiLoader.is_mono_supported():
return null
return instance().Executor(listener)


static func is_csharp_file(resource_path :String) -> bool:
var ext := resource_path.get_extension()
return ext == "cs" and GdUnit4MonoApiLoader.is_mono_supported()
return ext == "cs" and GdUnit4CSharpApiLoader.is_mono_supported()
17 changes: 0 additions & 17 deletions addons/gdUnit4/src/mono/GdUnit4MonoApi.cs

This file was deleted.

2 changes: 1 addition & 1 deletion addons/gdUnit4/test/GdUnitScriptTypeTest.gd
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ const __source = 'res://addons/gdUnit4/src/core/GdUnitScriptType.gd'
func test_type_of() -> void:
assert_str(GdUnitScriptType.type_of(null)).is_equal(GdUnitScriptType.UNKNOWN)
assert_str(GdUnitScriptType.type_of(ClassDB.instantiate("GDScript"))).is_equal(GdUnitScriptType.GD)
#if GdUnit4MonoApiLoader.is_mono_supported():
#if GdUnit4CSharpApiLoader.is_mono_supported():
# assert_str(GdUnitScriptType.type_of(ClassDB.instantiate("CSharpScript"))).is_equal(GdUnitScriptType.CS)
#assert_str(GdUnitScriptType.type_of(ClassDB.instantiate("VisualScript"))).is_equal(GdUnitScriptType.VS)
#assert_str(GdUnitScriptType.type_of(ClassDB.instantiate("NativeScript"))).is_equal(GdUnitScriptType.NATIVE)
4 changes: 2 additions & 2 deletions addons/gdUnit4/test/GdUnitTestResourceLoader.gd
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ static func load_test_suite_gd(resource_path :String) -> GdUnitTestSuite:


static func load_test_suite_cs(resource_path :String) -> Node:
if not GdUnit4MonoApiLoader.is_mono_supported():
if not GdUnit4CSharpApiLoader.is_mono_supported():
return null
var script = ClassDB.instantiate("CSharpScript")
script.source_code = GdUnitFileAccess.resource_as_string(resource_path)
Expand All @@ -42,7 +42,7 @@ static func load_test_suite_cs(resource_path :String) -> Node:


static func load_cs_script(resource_path :String, debug_write := false) -> Script:
if not GdUnit4MonoApiLoader.is_mono_supported():
if not GdUnit4CSharpApiLoader.is_mono_supported():
return null
var script = ClassDB.instantiate("CSharpScript")
script.source_code = GdUnitFileAccess.resource_as_string(resource_path)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
# GdUnit generated TestSuite
#warning-ignore-all:unused_argument
#warning-ignore-all:return_value_discarded
class_name GdUnit4MonoApiLoaderTest
class_name GdUnit4CSharpApiLoaderTest
extends GdUnitTestSuite

# TestSuite generated from
const GdUnitTools := preload("res://addons/gdUnit4/src/core/GdUnitTools.gd")
const __source = 'res://addons/gdUnit4/src/mono/GdUnit4MonoApiLoader.gd'
const __source = 'res://addons/gdUnit4/src/mono/GdUnit4CSharpApiLoader.gd'


@warning_ignore("unused_parameter")
func before(do_skip = not GdUnit4MonoApiLoader.is_mono_supported(), skip_reason = "Do run only for Godot Mono version"):
func before(do_skip = not GdUnit4CSharpApiLoader.is_mono_supported(), skip_reason = "Do run only for Godot Mono version"):
pass


Expand All @@ -25,11 +25,11 @@ func test_is_engine_version_supported(version :int, expected :bool, test_paramet
[0x40100, true],
[0x40200, true]]) -> void:

assert_that(GdUnit4MonoApiLoader.is_engine_version_supported(version)).is_equal(expected)
assert_that(GdUnit4CSharpApiLoader.is_engine_version_supported(version)).is_equal(expected)


func test_api_version() -> void:
assert_str(GdUnit4MonoApiLoader.version()).starts_with("4.2")
assert_str(GdUnit4CSharpApiLoader.version()).starts_with("4.2")


func test_create_test_suite() -> void:
Expand All @@ -40,7 +40,7 @@ func test_create_test_suite() -> void:
var example_source_cs = result.value() as String
var source := load(example_source_cs)
var test_suite_path := GdUnitTestSuiteScanner.resolve_test_suite_path(source.resource_path, "test")
result = GdUnit4MonoApiLoader.create_test_suite(source.resource_path, 18, test_suite_path)
result = GdUnit4CSharpApiLoader.create_test_suite(source.resource_path, 18, test_suite_path)

assert_result(result).is_success()
var info := result.value() as Dictionary
Expand All @@ -49,7 +49,7 @@ func test_create_test_suite() -> void:


func test_parse_test_suite() -> void:
var test_suite := GdUnit4MonoApiLoader.parse_test_suite("res://addons/gdUnit4/test/mono/GdUnit4MonoApiTest.cs")
var test_suite := GdUnit4CSharpApiLoader.parse_test_suite("res://addons/gdUnit4/test/mono/GdUnit4CSharpApiTest.cs")
assert_that(test_suite).is_not_null()
assert_that(test_suite.get("IsCsTestSuite")).is_true()
test_suite.free()
Expand All @@ -61,10 +61,10 @@ class TestRunListener extends Node:

func test_executor() -> void:
var listener :TestRunListener = auto_free(TestRunListener.new())
var executor = GdUnit4MonoApiLoader.create_executor(listener)
var executor = GdUnit4CSharpApiLoader.create_executor(listener)
assert_that(executor).is_not_null()

var test_suite := GdUnit4MonoApiLoader.parse_test_suite("res://addons/gdUnit4/test/mono/GdUnit4MonoApiTest.cs")
var test_suite := GdUnit4CSharpApiLoader.parse_test_suite("res://addons/gdUnit4/test/mono/GdUnit4CSharpApiTest.cs")
assert_that(executor.IsExecutable(test_suite)).is_true()

test_suite.free()
22 changes: 22 additions & 0 deletions addons/gdUnit4/test/mono/GdUnit4CSharpApiTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
namespace GdUnit4
{
using static Assertions;

[TestSuite]
public partial class GdUnit4CSharpApiTest
{

[TestCase]
public void IsTestSuite()
{
AssertThat(GdUnit4CSharpApi.IsTestSuite("res://addons/gdUnit4/src/mono/GdUnit4CSharpApi.cs")).IsFalse();
AssertThat(GdUnit4CSharpApi.IsTestSuite("res://addons/gdUnit4/test/mono/ExampleTestSuite.cs")).IsTrue();
}

[TestCase]
public void GetVersion()
{
AssertThat(GdUnit4CSharpApi.Version()).IsEqual("4.2.0.0");
}
}
}
23 changes: 0 additions & 23 deletions addons/gdUnit4/test/mono/GdUnit4MonoApiTest.cs

This file was deleted.

0 comments on commit 3cb0a7c

Please sign in to comment.