Add unit test for scripting interface to ensure generated bindings code works fine

This commit is contained in:
Wojtek Figat
2022-12-31 13:10:19 +01:00
parent 0ca8fe2f45
commit a10fb703fc
4 changed files with 92 additions and 6 deletions

View File

@@ -119,6 +119,11 @@ public:
// Tries to cast native interface object to scripting object instance. Returns null if fails.
static ScriptingObject* FromInterface(void* interfaceObj, const ScriptingTypeHandle& interfaceType);
template<typename T>
static ScriptingObject* FromInterface(T* interfaceObj)
{
return FromInterface(interfaceObj, T::TypeInitializer);
}
static void* ToInterface(ScriptingObject* obj, const ScriptingTypeHandle& interfaceType);
template<typename T>
static T* ToInterface(ScriptingObject* obj)

View File

@@ -65,4 +65,51 @@ TEST_CASE("Scripting")
CHECK(arr2[1].Vector == testClass->SimpleStruct.Vector);
CHECK(arr2[1].Object == testClass);
}
SECTION("Test Interface")
{
// Test native interface implementation
ScriptingTypeHandle type = Scripting::FindScriptingType("FlaxEngine.TestClassNative");
CHECK(type);
ScriptingObject* object = Scripting::NewObject(type.GetType().ManagedClass);
CHECK(object);
TestClassNative* testClass = (TestClassNative*)object;
int32 methodResult = testClass->TestInterfaceMethod(TEXT("123"));
CHECK(methodResult == 3);
ITestInterface* interface = ScriptingObject::ToInterface<ITestInterface>(object);
CHECK(interface);
methodResult = interface->TestInterfaceMethod(TEXT("1234"));
CHECK(methodResult == 4);
ScriptingObject* interfaceObject = ScriptingObject::FromInterface<ITestInterface>(interface);
CHECK(interfaceObject);
CHECK(interfaceObject == object);
// Test managed interface override
type = Scripting::FindScriptingType("FlaxEngine.TestClassManaged");
CHECK(type);
object = Scripting::NewObject(type.GetType().ManagedClass);
CHECK(object);
testClass = (TestClassNative*)object;
methodResult = testClass->TestInterfaceMethod(TEXT("123"));
CHECK(methodResult == 6);
interface = ScriptingObject::ToInterface<ITestInterface>(object);
CHECK(interface);
methodResult = interface->TestInterfaceMethod(TEXT("1234"));
CHECK(methodResult == 8);
interfaceObject = ScriptingObject::FromInterface<ITestInterface>(interface);
CHECK(interfaceObject);
CHECK(interfaceObject == object);
// Test managed interface implementation
type = Scripting::FindScriptingType("FlaxEngine.TestInterfaceManaged");
CHECK(type);
object = Scripting::NewObject(type.GetType().ManagedClass);
CHECK(object);
interface = ScriptingObject::ToInterface<ITestInterface>(object);
CHECK(interface);
methodResult = interface->TestInterfaceMethod(TEXT("1234"));
CHECK(methodResult == 4);
interfaceObject = ScriptingObject::FromInterface<ITestInterface>(interface);
CHECK(interfaceObject);
CHECK(interfaceObject == object);
}
}

View File

@@ -69,14 +69,21 @@ namespace FlaxEngine
return str.Length + base.TestMethod(str);
}
/// <inheritdoc />
public override int TestInterfaceMethod(string str)
{
// Test C++ base method invocation
return str.Length + base.TestInterfaceMethod(str);
}
private void OnSimpleEvent(int arg1, Float3 arg2, string arg3, ref string arg4, TestStruct[] arg5, ref TestStruct[] arg6)
{
// Verify that C++ passed proper data to C# via event bindings
if (arg1 == 1 &&
arg2 == Float3.One &&
arg3 == "1" &&
arg4 == "2" &&
arg5 != null && arg5.Length == 1 && arg5[0] == SimpleStruct &&
if (arg1 == 1 &&
arg2 == Float3.One &&
arg3 == "1" &&
arg4 == "2" &&
arg5 != null && arg5.Length == 1 && arg5[0] == SimpleStruct &&
arg6 != null && arg6.Length == 1 && arg6[0] == SimpleStruct)
{
// Test passing data back from C# to C++
@@ -94,5 +101,17 @@ namespace FlaxEngine
}
}
}
/// <summary>
/// Test interface in C#.
/// </summary>
public class TestInterfaceManaged : Object, ITestInterface
{
/// <inheritdoc />
public int TestInterfaceMethod(string str)
{
return str.Length;
}
}
}
#endif

View File

@@ -19,8 +19,18 @@ API_STRUCT(NoDefault) struct TestStruct : public ISerializable
API_FIELD() ScriptingObject* Object = nullptr;
};
// Test interface.
API_INTERFACE() class ITestInterface
{
DECLARE_SCRIPTING_TYPE_MINIMAL(ITestInterface);
~ITestInterface() = default;
// Test abstract method
API_FUNCTION() virtual int32 TestInterfaceMethod(const String& str) = 0;
};
// Test class.
API_CLASS() class TestClassNative : public ScriptingObject, public ISerializable
API_CLASS() class TestClassNative : public ScriptingObject, public ISerializable, public ITestInterface
{
API_AUTO_SERIALIZATION();
DECLARE_SCRIPTING_TYPE(TestClassNative);
@@ -40,4 +50,9 @@ public:
{
return str.Length();
}
int32 TestInterfaceMethod(const String& str) override
{
return str.Length();
}
};