Skip to content

Updated interop testing to support EVERY API extended by LibLLVM #248

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions IgnoredWords.dic
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ Llilum
llvm
llvmversion
LValue
malloc
marshallers
marshalling
memcopy
Expand Down
62 changes: 62 additions & 0 deletions src/Interop/InteropTests/ABI/libllvm-c/AnalysisBindingsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;

using static Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.AnalysisBindings;
using static Ubiquity.NET.Llvm.Interop.ABI.llvm_c.Core;

namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.UT
{
[TestClass]
public class AnalysisBindingsTests
{
[TestMethod]
public void LibLLVMVerifyFunctionExTest( )
{
using LLVMContextRef ctx = LLVMContextCreate();
using LLVMModuleRef module = LLVMModuleCreateWithNameInContext("testModule"u8, ctx);
LLVMTypeRef intType = LLVMInt32TypeInContext(ctx);
LLVMTypeRef funcType = LLVMFunctionType(intType, [], 0, false);

// declare a test func to work with and create an entry block for it...
LLVMValueRef goodFunc = LLVMAddFunction(module, "goodfunc"u8, funcType);
ImplementFunction(goodFunc, intType, createBroken: false);
LLVMStatus goodStatus = LibLLVMVerifyFunctionEx(goodFunc, llvm_c.LLVMVerifierFailureAction.LLVMPrintMessageAction, out string goodmsg);
Assert.AreEqual(0, goodStatus.ErrorCode);
Assert.IsFalse(goodStatus.Failed);
Assert.IsTrue(goodStatus.Succeeded);
// test for each state of a string in order to produce a distinct failure point for each condition
Assert.IsNotNull(goodmsg, "Error message should not be null");
Assert.IsTrue(string.IsNullOrEmpty(goodmsg), "Error message should be empty, for successful validation");

LLVMValueRef badFunc = LLVMAddFunction(module, "badfunc"u8, funcType);
ImplementFunction(badFunc, intType, createBroken: true);
LLVMStatus badStatus = LibLLVMVerifyFunctionEx(badFunc, llvm_c.LLVMVerifierFailureAction.LLVMPrintMessageAction, out string badmsg);
Assert.AreNotEqual(0, badStatus.ErrorCode);
Assert.IsTrue(badStatus.Failed);
Assert.IsFalse(badStatus.Succeeded);
// test for each state of a string in order to produce a distinct failure point for each condition
Assert.IsNotNull(badmsg, "Error message should not be null");
Assert.IsFalse(string.IsNullOrEmpty(badmsg), "Error message should not be empty");
Assert.IsFalse(string.IsNullOrWhiteSpace(badmsg), "Error message should not be all whitespace");
}

private static void ImplementFunction(LLVMValueRef func, LLVMTypeRef intType, bool createBroken = false)
{
LLVMContextRefAlias ctx = LLVMGetValueContext(func);

// Create an instruction builder to work with and connect it to
// a new entry block for the test function
using LLVMBuilderRef testBuilder = LLVMCreateBuilderInContext(ctx);
LLVMPositionBuilderAtEnd(testBuilder, LLVMAppendBasicBlockInContext(ctx, func, "entry"u8));

// Now build out some code...
LLVMValueRef constOne = LLVMConstInt(intType, 1, false);
LLVMValueRef r0 = LLVMBuildAdd(testBuilder, constOne, constOne, string.Empty);

// BB without terminator is a good example of a bad function
if (!createBroken)
{
LLVMBuildRet(testBuilder, r0);
}
}
}
}
288 changes: 288 additions & 0 deletions src/Interop/InteropTests/ABI/libllvm-c/AttributeBindingsTests.cs

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions src/Interop/InteropTests/ABI/libllvm-c/ContextBindingsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
using System;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Ubiquity.NET.Llvm.Interop.UT;

using static Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.ContextBindings;
using static Ubiquity.NET.Llvm.Interop.ABI.llvm_c.Core;

namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.UT
{
[TestClass]
public class ContextBindingsTests
{
[TestMethod]
public void LibLLVMContextGetIsODRUniquingDebugTypesTest( )
{
using LLVMContextRef ctx = LLVMContextCreate();
Assert.IsFalse(LibLLVMContextGetIsODRUniquingDebugTypes(ctx));
}

[TestMethod]
public void LibLLVMContextSetIsODRUniquingDebugTypesTest( )
{
using LLVMContextRef ctx = LLVMContextCreate();
LibLLVMContextSetIsODRUniquingDebugTypes(ctx, true);
Assert.IsTrue(LibLLVMContextGetIsODRUniquingDebugTypes(ctx));
}
}
}
62 changes: 62 additions & 0 deletions src/Interop/InteropTests/ABI/libllvm-c/DataLayoutBindingsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using System;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Ubiquity.NET.InteropHelpers;
using Ubiquity.NET.Llvm.Interop.UT;

using static Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.DataLayoutBindings;

namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.UT
{
[TestClass]
public class DataLayoutBindingsTests
{
[TestMethod]
public void LibLLVMParseDataLayoutTest( )
{
using(var errorRef = LibLLVMParseDataLayout("badlayout"u8, out LLVMTargetDataRef retVal))
using(retVal)
{
Assert.IsTrue(retVal.IsInvalid);
Assert.IsTrue(errorRef.Failed);
string errMsg = errorRef.ToString();
Assert.IsFalse(string.IsNullOrWhiteSpace(errMsg), "Failure should have an error message");
}

// should match SPARC but as long as it is valid syntax the semantics don't matter.
LazyEncodedString goodLayout = "E-p:32:32-f128:128:128"u8;
using(var errorRef = LibLLVMParseDataLayout(goodLayout, out LLVMTargetDataRef retVal))
using(retVal)
{
Assert.IsFalse(errorRef.Failed);
Assert.IsTrue(errorRef.Success);
Assert.IsFalse(retVal.IsInvalid);
string errMsg = errorRef.ToString();
Assert.IsTrue(string.IsNullOrWhiteSpace(errMsg), "Valid layout should NOT have an error message");
}
}

[TestMethod]
public void LibLLVMGetDataLayoutStringTest( )
{
// should match SPARC but as long as it is valid syntax the semantics don't matter.
LazyEncodedString goodLayout = "E-p:32:32-f128:128:128"u8;
using(var errorRef = LibLLVMParseDataLayout(goodLayout, out LLVMTargetDataRef retVal))
using(retVal)
{
// status of parse assumed correct, behavior is validated in LibLLVMParseDataLayoutTest()

LazyEncodedString? retrievedLayout = LibLLVMGetDataLayoutString(retVal);
Assert.IsNotNull(retrievedLayout);
Assert.IsFalse(LazyEncodedString.IsNullOrEmpty(retrievedLayout));
Assert.IsFalse(LazyEncodedString.IsNullOrWhiteSpace(retrievedLayout));

// This assert is a bit dodgy, as there's no formal canonicalization of the layout strings
// and multiple strings can describe the same layout... BUT, the retrieval returns the
// EXACT string used to create the layout, thus, for this test it is a legit thing to do.
Assert.AreEqual(goodLayout, retrievedLayout);
}
}
}
}
22 changes: 22 additions & 0 deletions src/Interop/InteropTests/ABI/libllvm-c/IRBindingsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
using Microsoft.VisualStudio.TestTools.UnitTesting;

using Ubiquity.NET.Llvm.Interop.UT;

using static Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.IRBindings;
using static Ubiquity.NET.Llvm.Interop.ABI.llvm_c.Core;

namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.UT
{
[TestClass]
public class IRBindingsTests
{
[SkipTestMethod]
public void LibLLVMHasUnwindDestTest( )
{
// As of this writing, the only implemented instructions that might contain an unwind dest are a CleanupReturn and
// CatchSwitchInst, all other instructions result in a 0;
// TODO: Figure out minimum API calls needed to build a valid case for each type and at least one for the "negative"
// then validate the API returns the correct value.
}
}
}
186 changes: 186 additions & 0 deletions src/Interop/InteropTests/ABI/libllvm-c/MetadataBindingsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
using System;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using Ubiquity.NET.Llvm.Interop.UT;

namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.UT
{
[TestClass]
public class MetadataBindingsTests
{
[SkipTestMethod]
public void LibLLVMDIBasicTypeGetEncodingTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMGetNodeContextTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMDiCompileUnitGetEmissionKindTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMDIBuilderCreateTempFunctionFwdDeclTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMDIBuilderFinalizeSubProgramTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMDIDescriptorGetTagTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMDILocationGetInlinedAtScopeTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMMetadataAsStringTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMMDNodeGetNumOperandsTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMMDNodeGetOperandTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMMDNodeReplaceOperandTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMGetOperandNodeTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMNamedMetadataGetParentModuleTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMNamedMetadataEraseFromParentTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMGetMetadataIDTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMNamedMDNodeGetNumOperandsTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMNamedMDNodeGetOperandTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMNamedMDNodeSetOperandTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMNamedMDNodeAddOperandTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMNamedMDNodeClearOperandsTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMConstantAsMetadataTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMGetMDStringTextTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMAddNamedMetadataOperand2Test( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMSetMetadata2Test( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMIsTemporaryTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMIsResolvedTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMIsUniquedTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMIsDistinctTest( )
{
throw new NotImplementedException();
}

[SkipTestMethod]
public void LibLLVMDISubRangeGetLowerBoundsTest( )
{
throw new NotImplementedException();
}
}
}
Loading
Loading