Add unit test to verify LibraryImport attributes usage for proper bindings

This commit is contained in:
Wojciech Figat
2023-01-24 09:25:39 +01:00
parent 405ae519dd
commit f1f5dacb6f
4 changed files with 61 additions and 1 deletions

View File

@@ -1036,7 +1036,7 @@ namespace FlaxEngine
private static Dictionary<Assembly, ManagedHandle> assemblyHandles = new();
private static Dictionary<string, IntPtr> loadedNativeLibraries = new();
private static Dictionary<string, string> nativeLibraryPaths = new();
internal static Dictionary<string, string> nativeLibraryPaths = new();
private static Dictionary<Assembly, string> assemblyOwnedNativeLibraries = new();
internal static AssemblyLoadContext scriptingAssemblyLoadContext;

View File

@@ -1,5 +1,6 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
#include "Engine/Platform/Platform.h"
#include "Engine/Animations/Graph/AnimGraph.h"
#include "Engine/Scripting/InternalCalls.h"
#include "Engine/Scripting/MException.h"

View File

@@ -2,6 +2,9 @@
#include "TestScripting.h"
#include "Engine/Scripting/Scripting.h"
#include "Engine/Scripting/ManagedCLR/MClass.h"
#include "Engine/Scripting/ManagedCLR/MMethod.h"
#include "Engine/Scripting/ManagedCLR/MUtils.h"
#include <ThirdParty/catch2/catch.hpp>
TestClassNative::TestClassNative(const SpawnParams& params)
@@ -11,6 +14,18 @@ TestClassNative::TestClassNative(const SpawnParams& params)
TEST_CASE("Scripting")
{
SECTION("Test Library Imports")
{
MClass* klass = Scripting::FindClass("FlaxEngine.Tests.TestScripting");
CHECK(klass);
MMethod* method = klass->GetMethod("TestLibraryImports");
CHECK(method);
MObject* result = method->Invoke(nullptr, nullptr, nullptr);
CHECK(result);
int32 resultValue = MUtils::Unbox<int32>(result);
CHECK(resultValue == 0);
}
SECTION("Test Class")
{
// Test native class

View File

@@ -1,5 +1,49 @@
// Copyright (c) 2012-2023 Wojciech Figat. All rights reserved.
using System;
using System.Reflection;
using System.Runtime.InteropServices;
namespace FlaxEngine.Tests
{
/// <summary>
/// Tests for scripting.
/// </summary>
public class TestScripting
{
/// <summary>
/// Tests all <see cref="LibraryImportAttribute"/> usages in the engine to verify all bindigns are correct to work with P/Invoke.
/// </summary>
public static int TestLibraryImports()
{
var result = 0;
var libraryName = "FlaxEngine";
var library = NativeLibrary.Load(NativeInterop.nativeLibraryPaths[libraryName]);
if (library == IntPtr.Zero)
return -1;
var types = typeof(FlaxEngine.Object).Assembly.GetTypes();
foreach (var type in types)
{
var methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
foreach (var method in methods)
{
var libraryImport = method.GetCustomAttribute<LibraryImportAttribute>();
if (libraryImport == null || libraryImport.LibraryName != libraryName || libraryImport.EntryPoint == null)
continue;
bool found = NativeLibrary.TryGetExport(library, libraryImport.EntryPoint, out var addr);
if (!found)
{
Debug.LogError("Missing library import: " + libraryImport.EntryPoint);
result++;
}
}
}
NativeLibrary.Free(library);
return result;
}
}
}
namespace FlaxEngine
{
partial struct TestStruct : System.IEquatable<TestStruct>