浏览代码

Merge pull request #1101 from dsnopek/better-tests

Add automated tests that run a GDExtension (rather than just building it)
David Snopek 2 年之前
父节点
当前提交
2e45bd8373

+ 32 - 0
.github/workflows/ci.yml

@@ -22,6 +22,7 @@ jobs:
             platform: linux
             platform: linux
             artifact-name: godot-cpp-linux-glibc2.27-x86_64-release
             artifact-name: godot-cpp-linux-glibc2.27-x86_64-release
             artifact-path: bin/libgodot-cpp.linux.template_release.x86_64.a
             artifact-path: bin/libgodot-cpp.linux.template_release.x86_64.a
+            run-tests: true
             cache-name: linux-x86_64
             cache-name: linux-x86_64
 
 
           - name: 🐧 Linux (GCC, Double Precision)
           - name: 🐧 Linux (GCC, Double Precision)
@@ -30,6 +31,7 @@ jobs:
             artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release
             artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release
             artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a
             artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a
             flags: precision=double
             flags: precision=double
+            run-tests: false
             cache-name: linux-x86_64-f64
             cache-name: linux-x86_64-f64
 
 
           - name: 🏁 Windows (x86_64, MSVC)
           - name: 🏁 Windows (x86_64, MSVC)
@@ -37,6 +39,7 @@ jobs:
             platform: windows
             platform: windows
             artifact-name: godot-cpp-windows-msvc2019-x86_64-release
             artifact-name: godot-cpp-windows-msvc2019-x86_64-release
             artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.lib
             artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.lib
+            run-tests: false
             cache-name: windows-x86_64-msvc
             cache-name: windows-x86_64-msvc
 
 
           - name: 🏁 Windows (x86_64, MinGW)
           - name: 🏁 Windows (x86_64, MinGW)
@@ -45,6 +48,7 @@ jobs:
             artifact-name: godot-cpp-linux-mingw-x86_64-release
             artifact-name: godot-cpp-linux-mingw-x86_64-release
             artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.a
             artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.a
             flags: use_mingw=yes
             flags: use_mingw=yes
+            run-tests: false
             cache-name: windows-x86_64-mingw
             cache-name: windows-x86_64-mingw
 
 
           - name: 🍎 macOS (universal)
           - name: 🍎 macOS (universal)
@@ -53,6 +57,7 @@ jobs:
             artifact-name: godot-cpp-macos-universal-release
             artifact-name: godot-cpp-macos-universal-release
             artifact-path: bin/libgodot-cpp.macos.template_release.universal.a
             artifact-path: bin/libgodot-cpp.macos.template_release.universal.a
             flags: arch=universal
             flags: arch=universal
+            run-tests: false
             cache-name: macos-universal
             cache-name: macos-universal
 
 
           - name: 🤖 Android (arm64)
           - name: 🤖 Android (arm64)
@@ -61,6 +66,7 @@ jobs:
             artifact-name: godot-cpp-android-arm64-release
             artifact-name: godot-cpp-android-arm64-release
             artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
             artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
             flags: ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME arch=arm64
             flags: ANDROID_NDK_ROOT=$ANDROID_NDK_LATEST_HOME arch=arm64
+            run-tests: false
             cache-name: android-arm64
             cache-name: android-arm64
 
 
           - name: 🍏 iOS (arm64)
           - name: 🍏 iOS (arm64)
@@ -69,6 +75,7 @@ jobs:
             artifact-name: godot-cpp-ios-arm64-release
             artifact-name: godot-cpp-ios-arm64-release
             artifact-path: bin/libgodot-cpp.ios.template_release.arm64.a
             artifact-path: bin/libgodot-cpp.ios.template_release.arm64.a
             flags: arch=arm64
             flags: arch=arm64
+            run-tests: false
             cache-name: ios-arm64
             cache-name: ios-arm64
 
 
     env:
     env:
@@ -124,6 +131,31 @@ jobs:
           cd test
           cd test
           scons platform=${{ matrix.platform }} target=template_release ${{ matrix.flags }}
           scons platform=${{ matrix.platform }} target=template_release ${{ matrix.flags }}
 
 
+      - name: Download latest Godot artifacts
+        uses: dsnopek/action-download-artifact@1322f74e2dac9feed2ee76a32d9ae1ca3b4cf4e9
+        if: ${{ matrix.run-tests }}
+        with:
+          repo: godotengine/godot
+          branch: master
+          event: push
+          workflow: linux_builds.yml
+          workflow_conclusion: success
+          name: linux-editor-mono
+          search_artifacts: true
+          check_artifacts: true
+          ensure_latest: true
+          path: godot-artifacts
+
+      - name: Run tests
+        if: ${{ matrix.run-tests }}
+        run: |
+          chmod +x ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono
+          ./godot-artifacts/godot.linuxbsd.editor.x86_64.mono --headless --version
+          cd test
+          # Need to run the editor so .godot is generated... but it crashes! Ignore that :-)
+          (cd project && (../../godot-artifacts/godot.linuxbsd.editor.x86_64.mono --editor --headless --quit >/dev/null 2>&1 || true))
+          GODOT=../godot-artifacts/godot.linuxbsd.editor.x86_64.mono ./run-tests.sh
+
       - name: Upload artifact
       - name: Upload artifact
         uses: actions/upload-artifact@v3
         uses: actions/upload-artifact@v3
         with:
         with:

+ 1 - 4
test/README.md

@@ -1,11 +1,8 @@
-# godot-cpp example / integration test
+# godot-cpp integration test
 
 
 This project is used to perform integration testing of the godot-cpp
 This project is used to perform integration testing of the godot-cpp
 extension, to validate PRs and implemented APIs.
 extension, to validate PRs and implemented APIs.
 
 
-It can also be used as a quick example of how to set up a godot-cpp
-project, both on the C++ side and in the Godot project itself.
-
 ## License
 ## License
 
 
 This is free and unencumbered software released into the public domain.
 This is free and unencumbered software released into the public domain.

+ 2 - 2
test/SConstruct

@@ -18,14 +18,14 @@ sources = Glob("src/*.cpp")
 
 
 if env["platform"] == "macos":
 if env["platform"] == "macos":
     library = env.SharedLibrary(
     library = env.SharedLibrary(
-        "demo/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format(
+        "project/bin/libgdexample.{}.{}.framework/libgdexample.{}.{}".format(
             env["platform"], env["target"], env["platform"], env["target"]
             env["platform"], env["target"], env["platform"], env["target"]
         ),
         ),
         source=sources,
         source=sources,
     )
     )
 else:
 else:
     library = env.SharedLibrary(
     library = env.SharedLibrary(
-        "demo/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
+        "project/bin/libgdexample{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
         source=sources,
         source=sources,
     )
     )
 
 

+ 0 - 80
test/demo/main.gd

@@ -1,80 +0,0 @@
-extends Node
-
-func _ready():
-	# Bind signals
-	prints("Signal bind")
-	$Button.button_up.connect($Example.emit_custom_signal.bind("Button", 42))
-
-	prints("")
-
-	# To string.
-	prints("To string")
-	prints("  Example --> ", $Example.to_string())
-	prints("  ExampleMin --> ", $Example/ExampleMin.to_string())
-
-	# Call static methods.
-	prints("Static method calls")
-	prints("  static (109)", Example.test_static(9, 100));
-	Example.test_static2();
-
-	# Property list.
-	prints("Property list")
-	$Example.property_from_list = Vector3(100, 200, 300)
-	prints("  property value ", $Example.property_from_list)
-
-	# Call methods.
-	prints("Instance method calls")
-	$Example.simple_func()
-	($Example as Example).simple_const_func() # Force use of ptrcall
-	prints("  returned", $Example.return_something("some string"))
-	prints("  returned const", $Example.return_something_const())
-	var null_ref = $Example.return_empty_ref()
-	prints("  returned empty ref", null_ref)
-	var ret_ref = $Example.return_extended_ref()
-	prints("  returned ref", ret_ref.get_instance_id(), ", id:", ret_ref.get_id())
-	prints("  returned ", $Example.get_v4())
-	prints("  test node argument", $Example.test_node_argument($Example))
-
-	prints("VarArg method calls")
-	var ref = ExampleRef.new()
-	prints("  sending ref: ", ref.get_instance_id(), "returned ref: ", $Example.extended_ref_checks(ref).get_instance_id())
-	prints("  vararg args", $Example.varargs_func("some", "arguments", "to", "test"))
-	prints("  vararg_nv ret", $Example.varargs_func_nv("some", "arguments", "to", "test"))
-	$Example.varargs_func_void("some", "arguments", "to", "test")
-
-	prints("Method calls with default values")
-	prints("  defval (300)", $Example.def_args())
-	prints("  defval (250)", $Example.def_args(50))
-	prints("  defval (150)", $Example.def_args(50, 100))
-
-	prints("Array and Dictionary")
-	prints("  test array", $Example.test_array())
-	prints("  test tarray", $Example.test_tarray())
-	prints("  test dictionary", $Example.test_dictionary())
-	var array: Array[int] = [1, 2, 3]
-	$Example.test_tarray_arg(array)
-
-	prints("String += operator")
-	prints("  test string +=", $Example.test_string_ops())
-
-	prints("PackedArray iterators")
-	prints("  test packed array iterators", $Example.test_vector_ops())
-
-	prints("Properties")
-	prints("  custom position is", $Example.group_subgroup_custom_position)
-	$Example.group_subgroup_custom_position = Vector2(50, 50)
-	prints("  custom position now is", $Example.group_subgroup_custom_position)
-
-	prints("Constants")
-	prints("  FIRST", $Example.FIRST)
-	prints("  ANSWER_TO_EVERYTHING", $Example.ANSWER_TO_EVERYTHING)
-	prints("  CONSTANT_WITHOUT_ENUM", $Example.CONSTANT_WITHOUT_ENUM)
-
-	prints("BitFields")
-	prints("  FLAG_ONE", Example.FLAG_ONE)
-	prints("  FLAG_TWO", Example.FLAG_TWO)
-	prints("  returned BitField", $Example.test_bitfield(0))
-	prints("  returned BitField", $Example.test_bitfield(Example.FLAG_ONE | Example.FLAG_TWO))
-
-func _on_Example_custom_signal(signal_name, value):
-	prints("Example emitted:", signal_name, value)

+ 0 - 0
test/demo/bin/libgdexample.osx.template_debug.framework/Resources/Info.plist → test/project/bin/libgdexample.osx.template_debug.framework/Resources/Info.plist


+ 0 - 0
test/demo/bin/libgdexample.osx.template_release.framework/Resources/Info.plist → test/project/bin/libgdexample.osx.template_release.framework/Resources/Info.plist


+ 1 - 1
test/demo/default_env.tres → test/project/default_env.tres

@@ -4,4 +4,4 @@
 
 
 [resource]
 [resource]
 background_mode = 2
 background_mode = 2
-sky = SubResource( "1" )
+sky = SubResource("1")

+ 0 - 0
test/demo/example.gdextension → test/project/example.gdextension


+ 0 - 0
test/demo/icon.png → test/project/icon.png


+ 1 - 1
test/demo/icon.png.import → test/project/icon.png.import

@@ -16,9 +16,9 @@ dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.cte
 [params]
 [params]
 
 
 compress/mode=0
 compress/mode=0
+compress/high_quality=false
 compress/lossy_quality=0.7
 compress/lossy_quality=0.7
 compress/hdr_compression=1
 compress/hdr_compression=1
-compress/bptc_ldr=0
 compress/normal_map=0
 compress/normal_map=0
 compress/channel_pack=0
 compress/channel_pack=0
 mipmaps/generate=false
 mipmaps/generate=false

+ 102 - 0
test/project/main.gd

@@ -0,0 +1,102 @@
+extends "res://test_base.gd"
+
+var custom_signal_emitted = null
+
+
+func _ready():
+	# Signal.
+	$Example.emit_custom_signal("Button", 42)
+	assert_equal(custom_signal_emitted, ["Button", 42])
+
+	# To string.
+	assert_equal($Example.to_string(),'Example:[ GDExtension::Example <--> Instance ID:%s ]' % $Example.get_instance_id())
+	# It appears there's a bug with instance ids :-(
+	#assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:[Wrapped:%s]' % $Example/ExampleMin.get_instance_id())
+
+	# Call static methods.
+	assert_equal($Example.test_static(9, 100), 109);
+	# It's void and static, so all we know is that it didn't crash.
+	$Example.test_static2()
+
+	# Property list.
+	$Example.property_from_list = Vector3(100, 200, 300)
+	assert_equal($Example.property_from_list, Vector3(100, 200, 300))
+
+	# Call simple methods.
+	$Example.simple_func()
+	assert_equal(custom_signal_emitted, ['simple_func', 3])
+	($Example as Example).simple_const_func() # Force use of ptrcall
+	assert_equal(custom_signal_emitted, ['simple_const_func', 4])
+
+	# Pass custom reference.
+	assert_equal($Example.custom_ref_func(null), -1)
+	var ref1 = ExampleRef.new()
+	ref1.id = 27
+	assert_equal($Example.custom_ref_func(ref1), 27)
+	ref1.id += 1;
+	assert_equal($Example.custom_const_ref_func(ref1), 28)
+
+	# Pass core reference.
+	assert_equal($Example.image_ref_func(null), "invalid")
+	assert_equal($Example.image_const_ref_func(null), "invalid")
+	var image = Image.new()
+	assert_equal($Example.image_ref_func(image), "valid")
+	assert_equal($Example.image_const_ref_func(image), "valid")
+
+	# Return values.
+	assert_equal($Example.return_something("some string"), "some string42")
+	assert_equal($Example.return_something_const(), get_viewport())
+	var null_ref = $Example.return_empty_ref()
+	assert_equal(null_ref, null)
+	var ret_ref = $Example.return_extended_ref()
+	assert_not_equal(ret_ref.get_instance_id(), 0)
+	assert_equal(ret_ref.get_id(), 0)
+	assert_equal($Example.get_v4(), Vector4(1.2, 3.4, 5.6, 7.8))
+	assert_equal($Example.test_node_argument($Example), $Example)
+
+	# VarArg method calls.
+	var var_ref = ExampleRef.new()
+	assert_not_equal($Example.extended_ref_checks(var_ref).get_instance_id(), var_ref.get_instance_id())
+	assert_equal($Example.varargs_func("some", "arguments", "to", "test"), 4)
+	assert_equal($Example.varargs_func_nv("some", "arguments", "to", "test"), 46)
+	$Example.varargs_func_void("some", "arguments", "to", "test")
+	assert_equal(custom_signal_emitted, ["varargs_func_void", 5])
+
+	# Method calls with default values.
+	assert_equal($Example.def_args(), 300)
+	assert_equal($Example.def_args(50), 250)
+	assert_equal($Example.def_args(50, 100), 150)
+
+	# Array and Dictionary
+	assert_equal($Example.test_array(), [1, 2])
+	assert_equal($Example.test_tarray(), [ Vector2(1, 2), Vector2(2, 3) ])
+	assert_equal($Example.test_dictionary(), {"hello": "world", "foo": "bar"})
+	var array: Array[int] = [1, 2, 3]
+	assert_equal($Example.test_tarray_arg(array), 6)
+
+	# String += operator
+	assert_equal($Example.test_string_ops(), "ABCĎE")
+
+	# PackedArray iterators
+	assert_equal($Example.test_vector_ops(), 105)
+
+	# Properties.
+	assert_equal($Example.group_subgroup_custom_position, Vector2(0, 0))
+	$Example.group_subgroup_custom_position = Vector2(50, 50)
+	assert_equal($Example.group_subgroup_custom_position, Vector2(50, 50))
+
+	# Constants.
+	assert_equal($Example.FIRST, 0)
+	assert_equal($Example.ANSWER_TO_EVERYTHING, 42)
+	assert_equal($Example.CONSTANT_WITHOUT_ENUM, 314)
+
+	# BitFields.
+	assert_equal(Example.FLAG_ONE, 1)
+	assert_equal(Example.FLAG_TWO, 2)
+	assert_equal($Example.test_bitfield(0), 0)
+	assert_equal($Example.test_bitfield(Example.FLAG_ONE | Example.FLAG_TWO), 3)
+
+	exit_with_status()
+
+func _on_Example_custom_signal(signal_name, value):
+	custom_signal_emitted = [signal_name, value]

+ 0 - 0
test/demo/main.tscn → test/project/main.tscn


+ 0 - 0
test/demo/project.godot → test/project/project.godot


+ 59 - 0
test/project/test_base.gd

@@ -0,0 +1,59 @@
+extends Node
+
+var test_passes := 0
+var test_failures := 0
+
+func __get_stack_frame():
+	var me = get_script()
+	for s in get_stack():
+		if s.source == me.resource_path:
+			return s
+	return null
+
+func __assert_pass():
+	test_passes += 1
+
+func __assert_fail():
+	test_failures += 1
+	var s = __get_stack_frame()
+	if s != null:
+		print_rich ("[color=red] == FAILURE: In function %s() from '%s' on line %s[/color]" % [s.function, s.source, s.line])
+	else:
+		print_rich ("[color=red] == FAILURE (run with --debug to get more information!) ==[/color]")
+
+func assert_equal(actual, expected):
+	if actual == expected:
+		__assert_pass()
+	else:
+		__assert_fail()
+		print ("    |-> Expected '%s' but got '%s'" % [expected, actual])
+
+func assert_true(v):
+	assert_equal(v, true)
+
+func assert_false(v):
+	assert_equal(v, false)
+
+func assert_not_equal(actual, expected):
+	if actual != expected:
+		__assert_pass()
+	else:
+		__assert_fail()
+		print ("    |-> Expected '%s' NOT to equal '%s'" % [expected, actual])
+
+func exit_with_status() -> void:
+	var success: bool = (test_failures == 0)
+	print ("")
+	print_rich ("[color=%s] ==== TESTS FINISHED ==== [/color]" % ("green" if success else "red"))
+	print ("")
+	print_rich ("   PASSES: [color=green]%s[/color]" % test_passes)
+	print_rich ("   FAILURES: [color=red]%s[/color]" % test_failures)
+	print ("")
+
+	if success:
+		print_rich("[color=green] ******** PASSED ******** [/color]")
+	else:
+		print_rich("[color=red] ******** FAILED ********[/color]")
+	print("")
+
+	get_tree().quit(0 if success else 1)

+ 24 - 0
test/run-tests.sh

@@ -0,0 +1,24 @@
+#!/bin/bash
+
+GODOT=${GODOT:-godot}
+
+END_STRING="==== TESTS FINISHED ===="
+FAILURE_STRING="******** FAILED ********"
+
+OUTPUT=$($GODOT --path project --debug --headless --quit)
+ERRCODE=$?
+
+echo "$OUTPUT"
+echo
+
+if ! echo "$OUTPUT" | grep -e "$END_STRING" >/dev/null; then
+    echo "ERROR: Tests failed to complete"
+    exit 1
+fi
+
+if echo "$OUTPUT" | grep -e "$FAILURE_STRING" >/dev/null; then
+    exit 1
+fi
+
+# Success!
+exit 0

+ 44 - 31
test/src/example.cpp

@@ -13,27 +13,26 @@
 
 
 using namespace godot;
 using namespace godot;
 
 
-int ExampleRef::instance_count = 0;
-int ExampleRef::last_id = 0;
+void ExampleRef::set_id(int p_id) {
+	id = p_id;
+}
 
 
 int ExampleRef::get_id() const {
 int ExampleRef::get_id() const {
 	return id;
 	return id;
 }
 }
 
 
 void ExampleRef::_bind_methods() {
 void ExampleRef::_bind_methods() {
+	ClassDB::bind_method(D_METHOD("set_id", "id"), &ExampleRef::set_id);
 	ClassDB::bind_method(D_METHOD("get_id"), &ExampleRef::get_id);
 	ClassDB::bind_method(D_METHOD("get_id"), &ExampleRef::get_id);
+
+	ADD_PROPERTY(PropertyInfo(Variant::INT, "id"), "set_id", "get_id");
 }
 }
 
 
 ExampleRef::ExampleRef() {
 ExampleRef::ExampleRef() {
-	id = ++last_id;
-	instance_count++;
-
-	UtilityFunctions::print("ExampleRef ", itos(id), " created, current instance count: ", itos(instance_count));
+	id = 0;
 }
 }
 
 
 ExampleRef::~ExampleRef() {
 ExampleRef::~ExampleRef() {
-	instance_count--;
-	UtilityFunctions::print("ExampleRef ", itos(id), " destroyed, current instance count: ", itos(instance_count));
 }
 }
 
 
 int Example::test_static(int p_a, int p_b) {
 int Example::test_static(int p_a, int p_b) {
@@ -41,7 +40,7 @@ int Example::test_static(int p_a, int p_b) {
 }
 }
 
 
 void Example::test_static2() {
 void Example::test_static2() {
-	UtilityFunctions::print("  void static");
+	//UtilityFunctions::print("  void static");
 }
 }
 
 
 int Example::def_args(int p_a, int p_b) {
 int Example::def_args(int p_a, int p_b) {
@@ -49,7 +48,7 @@ int Example::def_args(int p_a, int p_b) {
 }
 }
 
 
 void Example::_notification(int p_what) {
 void Example::_notification(int p_what) {
-	UtilityFunctions::print("Notification: ", String::num(p_what));
+	//UtilityFunctions::print("Notification: ", String::num(p_what));
 }
 }
 
 
 bool Example::_set(const StringName &p_name, const Variant &p_value) {
 bool Example::_set(const StringName &p_name, const Variant &p_value) {
@@ -112,6 +111,10 @@ void Example::_bind_methods() {
 	// Methods.
 	// Methods.
 	ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func);
 	ClassDB::bind_method(D_METHOD("simple_func"), &Example::simple_func);
 	ClassDB::bind_method(D_METHOD("simple_const_func"), &Example::simple_const_func);
 	ClassDB::bind_method(D_METHOD("simple_const_func"), &Example::simple_const_func);
+	ClassDB::bind_method(D_METHOD("custom_ref_func", "ref"), &Example::custom_ref_func);
+	ClassDB::bind_method(D_METHOD("custom_const_ref_func", "ref"), &Example::custom_const_ref_func);
+	ClassDB::bind_method(D_METHOD("image_ref_func", "image"), &Example::image_ref_func);
+	ClassDB::bind_method(D_METHOD("image_const_ref_func", "image"), &Example::image_const_ref_func);
 	ClassDB::bind_method(D_METHOD("return_something"), &Example::return_something);
 	ClassDB::bind_method(D_METHOD("return_something"), &Example::return_something);
 	ClassDB::bind_method(D_METHOD("return_something_const"), &Example::return_something_const);
 	ClassDB::bind_method(D_METHOD("return_something_const"), &Example::return_something_const);
 	ClassDB::bind_method(D_METHOD("return_empty_ref"), &Example::return_empty_ref);
 	ClassDB::bind_method(D_METHOD("return_empty_ref"), &Example::return_empty_ref);
@@ -179,29 +182,43 @@ void Example::_bind_methods() {
 }
 }
 
 
 Example::Example() {
 Example::Example() {
-	UtilityFunctions::print("Constructor.");
+	//UtilityFunctions::print("Constructor.");
 }
 }
 
 
 Example::~Example() {
 Example::~Example() {
-	UtilityFunctions::print("Destructor.");
+	//UtilityFunctions::print("Destructor.");
 }
 }
 
 
 // Methods.
 // Methods.
 void Example::simple_func() {
 void Example::simple_func() {
-	UtilityFunctions::print("  Simple func called.");
+	emit_custom_signal("simple_func", 3);
 }
 }
 
 
 void Example::simple_const_func() const {
 void Example::simple_const_func() const {
-	UtilityFunctions::print("  Simple const func called.");
+	((Example *)this)->emit_custom_signal("simple_const_func", 4);
+}
+
+int Example::custom_ref_func(Ref<ExampleRef> p_ref) {
+	return p_ref.is_valid() ? p_ref->get_id() : -1;
+}
+
+int Example::custom_const_ref_func(const Ref<ExampleRef> &p_ref) {
+	return p_ref.is_valid() ? p_ref->get_id() : -1;
+}
+
+String Example::image_ref_func(Ref<Image> p_image) {
+	return p_image.is_valid() ? String("valid") : String("invalid");
+}
+
+String Example::image_const_ref_func(const Ref<Image> &p_image) {
+	return p_image.is_valid() ? String("valid") : String("invalid");
 }
 }
 
 
 String Example::return_something(const String &base) {
 String Example::return_something(const String &base) {
-	UtilityFunctions::print("  Return something called.");
-	return base;
+	return base + String("42");
 }
 }
 
 
 Viewport *Example::return_something_const() const {
 Viewport *Example::return_something_const() const {
-	UtilityFunctions::print("  Return something const called.");
 	if (is_inside_tree()) {
 	if (is_inside_tree()) {
 		Viewport *result = get_viewport();
 		Viewport *result = get_viewport();
 		return result;
 		return result;
@@ -221,32 +238,23 @@ ExampleRef *Example::return_extended_ref() const {
 	return memnew(ExampleRef());
 	return memnew(ExampleRef());
 }
 }
 
 
-Example *Example::test_node_argument(Example *p_node) const {
-	UtilityFunctions::print("  Test node argument called with ", p_node ? String::num(p_node->get_instance_id()) : "null");
-	return p_node;
-}
-
 Ref<ExampleRef> Example::extended_ref_checks(Ref<ExampleRef> p_ref) const {
 Ref<ExampleRef> Example::extended_ref_checks(Ref<ExampleRef> p_ref) const {
 	// This is therefor the prefered way of instancing and returning a refcounted object:
 	// This is therefor the prefered way of instancing and returning a refcounted object:
 	Ref<ExampleRef> ref;
 	Ref<ExampleRef> ref;
 	ref.instantiate();
 	ref.instantiate();
-
-	UtilityFunctions::print("  Example ref checks called with value: ", p_ref->get_instance_id(), ", returning value: ", ref->get_instance_id());
 	return ref;
 	return ref;
 }
 }
 
 
 Variant Example::varargs_func(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
 Variant Example::varargs_func(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
-	UtilityFunctions::print("  Varargs (Variant return) called with ", String::num((double)arg_count), " arguments");
 	return arg_count;
 	return arg_count;
 }
 }
 
 
 int Example::varargs_func_nv(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
 int Example::varargs_func_nv(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
-	UtilityFunctions::print("  Varargs (int return) called with ", String::num((double)arg_count), " arguments");
-	return 42;
+	return 42 + arg_count;
 }
 }
 
 
 void Example::varargs_func_void(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
 void Example::varargs_func_void(const Variant **args, GDExtensionInt arg_count, GDExtensionCallError &error) {
-	UtilityFunctions::print("  Varargs (no return) called with ", String::num((double)arg_count), " arguments");
+	emit_custom_signal("varargs_func_void", arg_count + 1);
 }
 }
 
 
 void Example::emit_custom_signal(const String &name, int value) {
 void Example::emit_custom_signal(const String &name, int value) {
@@ -285,10 +293,12 @@ int Example::test_vector_ops() const {
 	return ret;
 	return ret;
 }
 }
 
 
-void Example::test_tarray_arg(const TypedArray<int64_t> &p_array) {
+int Example::test_tarray_arg(const TypedArray<int64_t> &p_array) {
+	int sum = 0;
 	for (int i = 0; i < p_array.size(); i++) {
 	for (int i = 0; i < p_array.size(); i++) {
-		UtilityFunctions::print(p_array[i]);
+		sum += (int)p_array[i];
 	}
 	}
+	return sum;
 }
 }
 
 
 TypedArray<Vector2> Example::test_tarray() const {
 TypedArray<Vector2> Example::test_tarray() const {
@@ -310,8 +320,11 @@ Dictionary Example::test_dictionary() const {
 	return dict;
 	return dict;
 }
 }
 
 
+Example *Example::test_node_argument(Example *p_node) const {
+	return p_node;
+}
+
 BitField<Example::Flags> Example::test_bitfield(BitField<Flags> flags) {
 BitField<Example::Flags> Example::test_bitfield(BitField<Flags> flags) {
-	UtilityFunctions::print("  Got BitField: ", String::num_int64(flags));
 	return flags;
 	return flags;
 }
 }
 
 

+ 8 - 1
test/src/example.h

@@ -16,6 +16,7 @@
 
 
 #include <godot_cpp/classes/control.hpp>
 #include <godot_cpp/classes/control.hpp>
 #include <godot_cpp/classes/global_constants.hpp>
 #include <godot_cpp/classes/global_constants.hpp>
+#include <godot_cpp/classes/image.hpp>
 #include <godot_cpp/classes/viewport.hpp>
 #include <godot_cpp/classes/viewport.hpp>
 
 
 #include <godot_cpp/core/binder_common.hpp>
 #include <godot_cpp/core/binder_common.hpp>
@@ -38,6 +39,7 @@ public:
 	ExampleRef();
 	ExampleRef();
 	~ExampleRef();
 	~ExampleRef();
 
 
+	void set_id(int p_id);
 	int get_id() const;
 	int get_id() const;
 };
 };
 
 
@@ -90,8 +92,13 @@ public:
 	// Functions.
 	// Functions.
 	void simple_func();
 	void simple_func();
 	void simple_const_func() const;
 	void simple_const_func() const;
+	int custom_ref_func(Ref<ExampleRef> p_ref);
+	int custom_const_ref_func(const Ref<ExampleRef> &p_ref);
+	String image_ref_func(Ref<Image> p_image);
+	String image_const_ref_func(const Ref<Image> &p_image);
 	String return_something(const String &base);
 	String return_something(const String &base);
 	Viewport *return_something_const() const;
 	Viewport *return_something_const() const;
+	Ref<ExampleRef> return_ref() const;
 	Ref<ExampleRef> return_empty_ref() const;
 	Ref<ExampleRef> return_empty_ref() const;
 	ExampleRef *return_extended_ref() const;
 	ExampleRef *return_extended_ref() const;
 	Ref<ExampleRef> extended_ref_checks(Ref<ExampleRef> p_ref) const;
 	Ref<ExampleRef> extended_ref_checks(Ref<ExampleRef> p_ref) const;
@@ -102,7 +109,7 @@ public:
 	int def_args(int p_a = 100, int p_b = 200);
 	int def_args(int p_a = 100, int p_b = 200);
 
 
 	Array test_array() const;
 	Array test_array() const;
-	void test_tarray_arg(const TypedArray<int64_t> &p_array);
+	int test_tarray_arg(const TypedArray<int64_t> &p_array);
 	TypedArray<Vector2> test_tarray() const;
 	TypedArray<Vector2> test_tarray() const;
 	Dictionary test_dictionary() const;
 	Dictionary test_dictionary() const;
 	Example *test_node_argument(Example *p_node) const;
 	Example *test_node_argument(Example *p_node) const;