diff --git a/platform/android/java/app/src/androidTestInstrumented/java/com/godot/game/GodotAppTest.kt b/platform/android/java/app/src/androidTestInstrumented/java/com/godot/game/GodotAppTest.kt
index a0333deccf..383154e75e 100644
--- a/platform/android/java/app/src/androidTestInstrumented/java/com/godot/game/GodotAppTest.kt
+++ b/platform/android/java/app/src/androidTestInstrumented/java/com/godot/game/GodotAppTest.kt
@@ -113,6 +113,28 @@ class GodotAppTest {
}
}
+ /**
+ * Runs test to validate android plugin signals.
+ */
+ @Test
+ fun runPluginSignalTests() {
+ ActivityScenario.launch(GodotApp::class.java).use { scenario ->
+ scenario.onActivity { activity ->
+ val testPlugin = getTestPlugin()
+ assertNotNull(testPlugin)
+
+ Log.d(TAG, "Waiting for the Godot main loop to start...")
+ testPlugin.waitForGodotMainLoopStarted()
+
+ Log.d(TAG, "Running Android plugin signal tests...")
+ val result = testPlugin.runPluginSignalTests()
+ assertNotNull(result)
+ result.exceptionOrNull()?.let { throw it }
+ assertTrue(result.isSuccess)
+ }
+ }
+ }
+
/**
* Test implicit launch of the Godot app, and validates this resolves to the `GodotAppLauncher` activity alias.
*/
diff --git a/platform/android/java/app/src/instrumented/AndroidManifest.xml b/platform/android/java/app/src/instrumented/AndroidManifest.xml
index 863ec4c09f..23606f6a66 100644
--- a/platform/android/java/app/src/instrumented/AndroidManifest.xml
+++ b/platform/android/java/app/src/instrumented/AndroidManifest.xml
@@ -4,6 +4,10 @@
+
+
diff --git a/platform/android/java/app/src/instrumented/assets/.godot/global_script_class_cache.cfg b/platform/android/java/app/src/instrumented/assets/.godot/global_script_class_cache.cfg
index 1f8f066232..080d225fc5 100644
--- a/platform/android/java/app/src/instrumented/assets/.godot/global_script_class_cache.cfg
+++ b/platform/android/java/app/src/instrumented/assets/.godot/global_script_class_cache.cfg
@@ -1,5 +1,21 @@
list=[{
"base": &"BaseTest",
+"class": &"AndroidPluginSignalTests",
+"icon": "",
+"is_abstract": false,
+"is_tool": false,
+"language": &"GDScript",
+"path": "res://test/android_plugin/signal_tests.gd"
+}, {
+"base": &"RefCounted",
+"class": &"BaseTest",
+"icon": "",
+"is_abstract": true,
+"is_tool": false,
+"language": &"GDScript",
+"path": "res://test/base_test.gd"
+}, {
+"base": &"BaseTest",
"class": &"FileAccessTests",
"icon": "",
"is_abstract": false,
@@ -14,12 +30,4 @@ list=[{
"is_tool": false,
"language": &"GDScript",
"path": "res://test/javaclasswrapper/java_class_wrapper_tests.gd"
-}, {
-"base": &"RefCounted",
-"class": &"BaseTest",
-"icon": "",
-"is_abstract": true,
-"is_tool": false,
-"language": &"GDScript",
-"path": "res://test/base_test.gd"
}]
diff --git a/platform/android/java/app/src/instrumented/assets/.godot/uid_cache.bin b/platform/android/java/app/src/instrumented/assets/.godot/uid_cache.bin
index 9b97586fb9..44db24797c 100644
Binary files a/platform/android/java/app/src/instrumented/assets/.godot/uid_cache.bin and b/platform/android/java/app/src/instrumented/assets/.godot/uid_cache.bin differ
diff --git a/platform/android/java/app/src/instrumented/assets/main.gd b/platform/android/java/app/src/instrumented/assets/main.gd
index 54d8106edd..4b95069836 100644
--- a/platform/android/java/app/src/instrumented/assets/main.gd
+++ b/platform/android/java/app/src/instrumented/assets/main.gd
@@ -3,13 +3,22 @@ extends Node2D
var _plugin_name = "GodotAppInstrumentedTestPlugin"
var _android_plugin
-func _ready():
+var _signal_test_plugin_name = "SignalTestPlugin"
+var _signal_test_plugin
+
+func _init():
+ # Verify plugin singleton in _init, since plugins should already be registered at this point.
if Engine.has_singleton(_plugin_name):
_android_plugin = Engine.get_singleton(_plugin_name)
_android_plugin.connect("launch_tests", _launch_tests)
_android_plugin.connect("update_quit_on_go_back", _update_quit_on_go_back)
- else:
- printerr("Couldn't find plugin " + _plugin_name)
+
+ if Engine.has_singleton(_signal_test_plugin_name):
+ _signal_test_plugin = Engine.get_singleton(_signal_test_plugin_name)
+
+func _ready() -> void:
+ if not _android_plugin:
+ printerr("ERROR: Couldn't find plugin " + _plugin_name)
get_tree().quit()
func _launch_tests(test_label: String) -> void:
@@ -19,10 +28,12 @@ func _launch_tests(test_label: String) -> void:
test_instance = JavaClassWrapperTests.new()
"file_access_tests":
test_instance = FileAccessTests.new()
+ "android_plugin_signal_tests":
+ test_instance = AndroidPluginSignalTests.new(_signal_test_plugin)
if test_instance:
test_instance.__reset_tests()
- test_instance.run_tests()
+ await test_instance.run_tests()
var incomplete_tests = test_instance._test_started - test_instance._test_completed
_android_plugin.onTestsCompleted(test_label, test_instance._test_completed, test_instance._test_assert_failures + incomplete_tests)
else:
diff --git a/platform/android/java/app/src/instrumented/assets/project.godot b/platform/android/java/app/src/instrumented/assets/project.godot
index 68bc653c43..9d168beb45 100644
--- a/platform/android/java/app/src/instrumented/assets/project.godot
+++ b/platform/android/java/app/src/instrumented/assets/project.godot
@@ -16,7 +16,7 @@ compatibility/default_parent_skeleton_in_mesh_instance_3d=true
config/name="Godot App Instrumentation Tests"
run/main_scene="res://main.tscn"
-config/features=PackedStringArray("4.6", "GL Compatibility")
+config/features=PackedStringArray("4.7", "GL Compatibility")
config/icon="res://icon.svg"
[debug]
diff --git a/platform/android/java/app/src/instrumented/assets/test/android_plugin/signal_tests.gd b/platform/android/java/app/src/instrumented/assets/test/android_plugin/signal_tests.gd
new file mode 100644
index 0000000000..74f5b1bb76
--- /dev/null
+++ b/platform/android/java/app/src/instrumented/assets/test/android_plugin/signal_tests.gd
@@ -0,0 +1,60 @@
+class_name AndroidPluginSignalTests
+extends BaseTest
+
+var _plugin: JNISingleton
+const emission_test_signal = "emission_test_signal"
+const launch_test_signal = "launch_tests"
+
+signal emission_test_signal_emitted
+
+func _init(plugin: JNISingleton) -> void:
+ _plugin = plugin
+
+func run_tests():
+ print("Android plugin signal tests starting...")
+
+ __exec_test(test_plugin_exists)
+ __exec_test(test_signal_registration)
+ await __exec_test(test_signal_emission)
+
+ print("Android plugin signal tests completed.")
+
+func test_plugin_exists() -> bool:
+ if _plugin == null:
+ printerr("ERROR: Couldn't find SignalTestPlugin plugin; _plugin is null")
+ return false
+
+ return true
+
+func test_signal_registration() -> bool:
+ var signal_registered = _plugin.has_signal(emission_test_signal)
+ assert_true(signal_registered)
+
+ var launch_signal_registered = _plugin.has_signal(launch_test_signal)
+ assert_true(launch_signal_registered)
+
+ return true
+
+func test_signal_emission() -> bool:
+ var err1 = _plugin.connect(emission_test_signal, _on_emission_test_signal_emitted)
+ assert_equal(err1, OK)
+ _plugin.triggerTestSignal1()
+ await emission_test_signal_emitted
+
+ # Test case: Same signal name, but different type and number of parameters
+ # The "launch_tests" signal is registered by both GodotAppInstrumentedTestPlugin and SignalTestPlugin.
+ # SignalTestPlugin emits it with a boolean and a string arguments, while GodotAppInstrumentedTestPlugin emits it with one string.
+ var err2 = _plugin.connect(launch_test_signal, _on_launch_tests_emitted)
+ assert_equal(err2, OK)
+ _plugin.triggerLaunchTestSignal()
+ await emission_test_signal_emitted
+
+ return true
+
+func _on_emission_test_signal_emitted() -> void:
+ emission_test_signal_emitted.emit()
+
+func _on_launch_tests_emitted(param1: bool, param2: String) -> void:
+ assert_true(param1)
+ assert_equal(param2, "second message")
+ emission_test_signal_emitted.emit()
diff --git a/platform/android/java/app/src/instrumented/assets/test/android_plugin/signal_tests.gd.uid b/platform/android/java/app/src/instrumented/assets/test/android_plugin/signal_tests.gd.uid
new file mode 100644
index 0000000000..74d8150d08
--- /dev/null
+++ b/platform/android/java/app/src/instrumented/assets/test/android_plugin/signal_tests.gd.uid
@@ -0,0 +1 @@
+uid://cq0mxqlbbug6r
diff --git a/platform/android/java/app/src/instrumented/assets/test/base_test.gd b/platform/android/java/app/src/instrumented/assets/test/base_test.gd
index d4d333505b..6c62263024 100644
--- a/platform/android/java/app/src/instrumented/assets/test/base_test.gd
+++ b/platform/android/java/app/src/instrumented/assets/test/base_test.gd
@@ -9,7 +9,7 @@ var _test_assert_failures := 0
func __exec_test(test_func: Callable):
_test_started += 1
- var ret = test_func.call()
+ var ret = await test_func.call()
if ret == true:
_test_completed += 1
diff --git a/platform/android/java/app/src/instrumented/java/com/godot/game/test/GodotAppInstrumentedTestPlugin.kt b/platform/android/java/app/src/instrumented/java/com/godot/game/test/GodotAppInstrumentedTestPlugin.kt
index c5c243e159..c92dbc8455 100644
--- a/platform/android/java/app/src/instrumented/java/com/godot/game/test/GodotAppInstrumentedTestPlugin.kt
+++ b/platform/android/java/app/src/instrumented/java/com/godot/game/test/GodotAppInstrumentedTestPlugin.kt
@@ -52,6 +52,7 @@ class GodotAppInstrumentedTestPlugin(godot: Godot) : GodotPlugin(godot) {
private const val JAVACLASSWRAPPER_TESTS = "javaclasswrapper_tests"
private const val FILE_ACCESS_TESTS = "file_access_tests"
+ private const val PLUGIN_SIGNAL_TESTS = "android_plugin_signal_tests"
private val LAUNCH_TESTS_SIGNAL = SignalInfo("launch_tests", String::class.java)
private val UPDATE_QUIT_ON_GO_BACK_SIGNAL = SignalInfo("update_quit_on_go_back", java.lang.Boolean::class.java)
@@ -126,6 +127,10 @@ class GodotAppInstrumentedTestPlugin(godot: Godot) : GodotPlugin(godot) {
return launchTests(FILE_ACCESS_TESTS)
}
+ internal fun runPluginSignalTests(): Result? {
+ return launchTests(PLUGIN_SIGNAL_TESTS)
+ }
+
private fun launchTests(testLabel: String): Result? {
val latch = latches.getOrPut(testLabel) { CountDownLatch(1) }
emitSignal(LAUNCH_TESTS_SIGNAL, testLabel)
diff --git a/platform/android/java/app/src/instrumented/java/com/godot/game/test/SignalTestPlugin.kt b/platform/android/java/app/src/instrumented/java/com/godot/game/test/SignalTestPlugin.kt
new file mode 100644
index 0000000000..80e6aacd79
--- /dev/null
+++ b/platform/android/java/app/src/instrumented/java/com/godot/game/test/SignalTestPlugin.kt
@@ -0,0 +1,35 @@
+package com.godot.game.test
+
+import android.util.Log
+import org.godotengine.godot.Dictionary
+import org.godotengine.godot.Godot
+import org.godotengine.godot.plugin.GodotPlugin
+import org.godotengine.godot.plugin.SignalInfo
+import org.godotengine.godot.plugin.UsedByGodot
+
+class SignalTestPlugin(godot: Godot) : GodotPlugin(godot) {
+
+ companion object {
+ private val EMISSION_TEST_SIGNAL = SignalInfo("emission_test_signal")
+ private val LAUNCH_TESTS_SIGNAL = SignalInfo("launch_tests", java.lang.Boolean::class.java, String::class.java)
+ }
+
+ override fun getPluginName() = "SignalTestPlugin"
+
+ override fun getPluginSignals(): Set {
+ return setOf(
+ EMISSION_TEST_SIGNAL,
+ LAUNCH_TESTS_SIGNAL
+ )
+ }
+
+ @UsedByGodot
+ fun triggerTestSignal1() {
+ emitSignal(EMISSION_TEST_SIGNAL)
+ }
+
+ @UsedByGodot
+ fun triggerLaunchTestSignal() {
+ emitSignal(LAUNCH_TESTS_SIGNAL, true, "second message")
+ }
+}