Skip to content

Commit c5c16d1

Browse files
authored
Updated interop testing to support EVERY API extended by LibLLVM (UbiquityDotNET#248)
* NOTE: Not all APIs are explicitly tested yet. - Most are not. * Added SkipTestMethod attribute to support marking a test as skipped -This acknowledges the intent to test, but that it isn't yet implemented. - Basically avoids the "Oh, I forgot..." * Moved string marshallingTests to the interop helpers UT as that's where the implementation now lives. * Corrected `LibLLVMGetDataLayoutString` to hide the unsafe import. * Added Interop wrapper around `LLVMCreateConstantRangeAttribute` so that the length of the input array comes from the parameters. Co-authored-by: smaillet <[email protected]>
1 parent e7d50f7 commit c5c16d1

26 files changed

+1375
-122
lines changed

IgnoredWords.dic

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ Llilum
7575
llvm
7676
llvmversion
7777
LValue
78+
malloc
7879
marshallers
7980
marshalling
8081
memcopy
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
3+
using static Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.AnalysisBindings;
4+
using static Ubiquity.NET.Llvm.Interop.ABI.llvm_c.Core;
5+
6+
namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.UT
7+
{
8+
[TestClass]
9+
public class AnalysisBindingsTests
10+
{
11+
[TestMethod]
12+
public void LibLLVMVerifyFunctionExTest( )
13+
{
14+
using LLVMContextRef ctx = LLVMContextCreate();
15+
using LLVMModuleRef module = LLVMModuleCreateWithNameInContext("testModule"u8, ctx);
16+
LLVMTypeRef intType = LLVMInt32TypeInContext(ctx);
17+
LLVMTypeRef funcType = LLVMFunctionType(intType, [], 0, false);
18+
19+
// declare a test func to work with and create an entry block for it...
20+
LLVMValueRef goodFunc = LLVMAddFunction(module, "goodfunc"u8, funcType);
21+
ImplementFunction(goodFunc, intType, createBroken: false);
22+
LLVMStatus goodStatus = LibLLVMVerifyFunctionEx(goodFunc, llvm_c.LLVMVerifierFailureAction.LLVMPrintMessageAction, out string goodmsg);
23+
Assert.AreEqual(0, goodStatus.ErrorCode);
24+
Assert.IsFalse(goodStatus.Failed);
25+
Assert.IsTrue(goodStatus.Succeeded);
26+
// test for each state of a string in order to produce a distinct failure point for each condition
27+
Assert.IsNotNull(goodmsg, "Error message should not be null");
28+
Assert.IsTrue(string.IsNullOrEmpty(goodmsg), "Error message should be empty, for successful validation");
29+
30+
LLVMValueRef badFunc = LLVMAddFunction(module, "badfunc"u8, funcType);
31+
ImplementFunction(badFunc, intType, createBroken: true);
32+
LLVMStatus badStatus = LibLLVMVerifyFunctionEx(badFunc, llvm_c.LLVMVerifierFailureAction.LLVMPrintMessageAction, out string badmsg);
33+
Assert.AreNotEqual(0, badStatus.ErrorCode);
34+
Assert.IsTrue(badStatus.Failed);
35+
Assert.IsFalse(badStatus.Succeeded);
36+
// test for each state of a string in order to produce a distinct failure point for each condition
37+
Assert.IsNotNull(badmsg, "Error message should not be null");
38+
Assert.IsFalse(string.IsNullOrEmpty(badmsg), "Error message should not be empty");
39+
Assert.IsFalse(string.IsNullOrWhiteSpace(badmsg), "Error message should not be all whitespace");
40+
}
41+
42+
private static void ImplementFunction(LLVMValueRef func, LLVMTypeRef intType, bool createBroken = false)
43+
{
44+
LLVMContextRefAlias ctx = LLVMGetValueContext(func);
45+
46+
// Create an instruction builder to work with and connect it to
47+
// a new entry block for the test function
48+
using LLVMBuilderRef testBuilder = LLVMCreateBuilderInContext(ctx);
49+
LLVMPositionBuilderAtEnd(testBuilder, LLVMAppendBasicBlockInContext(ctx, func, "entry"u8));
50+
51+
// Now build out some code...
52+
LLVMValueRef constOne = LLVMConstInt(intType, 1, false);
53+
LLVMValueRef r0 = LLVMBuildAdd(testBuilder, constOne, constOne, string.Empty);
54+
55+
// BB without terminator is a good example of a bad function
56+
if (!createBroken)
57+
{
58+
LLVMBuildRet(testBuilder, r0);
59+
}
60+
}
61+
}
62+
}

src/Interop/InteropTests/ABI/libllvm-c/AttributeBindingsTests.cs

Lines changed: 288 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System;
2+
3+
using Microsoft.VisualStudio.TestTools.UnitTesting;
4+
5+
using Ubiquity.NET.Llvm.Interop.UT;
6+
7+
using static Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.ContextBindings;
8+
using static Ubiquity.NET.Llvm.Interop.ABI.llvm_c.Core;
9+
10+
namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.UT
11+
{
12+
[TestClass]
13+
public class ContextBindingsTests
14+
{
15+
[TestMethod]
16+
public void LibLLVMContextGetIsODRUniquingDebugTypesTest( )
17+
{
18+
using LLVMContextRef ctx = LLVMContextCreate();
19+
Assert.IsFalse(LibLLVMContextGetIsODRUniquingDebugTypes(ctx));
20+
}
21+
22+
[TestMethod]
23+
public void LibLLVMContextSetIsODRUniquingDebugTypesTest( )
24+
{
25+
using LLVMContextRef ctx = LLVMContextCreate();
26+
LibLLVMContextSetIsODRUniquingDebugTypes(ctx, true);
27+
Assert.IsTrue(LibLLVMContextGetIsODRUniquingDebugTypes(ctx));
28+
}
29+
}
30+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
using System;
2+
3+
using Microsoft.VisualStudio.TestTools.UnitTesting;
4+
5+
using Ubiquity.NET.InteropHelpers;
6+
using Ubiquity.NET.Llvm.Interop.UT;
7+
8+
using static Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.DataLayoutBindings;
9+
10+
namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.UT
11+
{
12+
[TestClass]
13+
public class DataLayoutBindingsTests
14+
{
15+
[TestMethod]
16+
public void LibLLVMParseDataLayoutTest( )
17+
{
18+
using(var errorRef = LibLLVMParseDataLayout("badlayout"u8, out LLVMTargetDataRef retVal))
19+
using(retVal)
20+
{
21+
Assert.IsTrue(retVal.IsInvalid);
22+
Assert.IsTrue(errorRef.Failed);
23+
string errMsg = errorRef.ToString();
24+
Assert.IsFalse(string.IsNullOrWhiteSpace(errMsg), "Failure should have an error message");
25+
}
26+
27+
// should match SPARC but as long as it is valid syntax the semantics don't matter.
28+
LazyEncodedString goodLayout = "E-p:32:32-f128:128:128"u8;
29+
using(var errorRef = LibLLVMParseDataLayout(goodLayout, out LLVMTargetDataRef retVal))
30+
using(retVal)
31+
{
32+
Assert.IsFalse(errorRef.Failed);
33+
Assert.IsTrue(errorRef.Success);
34+
Assert.IsFalse(retVal.IsInvalid);
35+
string errMsg = errorRef.ToString();
36+
Assert.IsTrue(string.IsNullOrWhiteSpace(errMsg), "Valid layout should NOT have an error message");
37+
}
38+
}
39+
40+
[TestMethod]
41+
public void LibLLVMGetDataLayoutStringTest( )
42+
{
43+
// should match SPARC but as long as it is valid syntax the semantics don't matter.
44+
LazyEncodedString goodLayout = "E-p:32:32-f128:128:128"u8;
45+
using(var errorRef = LibLLVMParseDataLayout(goodLayout, out LLVMTargetDataRef retVal))
46+
using(retVal)
47+
{
48+
// status of parse assumed correct, behavior is validated in LibLLVMParseDataLayoutTest()
49+
50+
LazyEncodedString? retrievedLayout = LibLLVMGetDataLayoutString(retVal);
51+
Assert.IsNotNull(retrievedLayout);
52+
Assert.IsFalse(LazyEncodedString.IsNullOrEmpty(retrievedLayout));
53+
Assert.IsFalse(LazyEncodedString.IsNullOrWhiteSpace(retrievedLayout));
54+
55+
// This assert is a bit dodgy, as there's no formal canonicalization of the layout strings
56+
// and multiple strings can describe the same layout... BUT, the retrieval returns the
57+
// EXACT string used to create the layout, thus, for this test it is a legit thing to do.
58+
Assert.AreEqual(goodLayout, retrievedLayout);
59+
}
60+
}
61+
}
62+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
3+
using Ubiquity.NET.Llvm.Interop.UT;
4+
5+
using static Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.IRBindings;
6+
using static Ubiquity.NET.Llvm.Interop.ABI.llvm_c.Core;
7+
8+
namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.UT
9+
{
10+
[TestClass]
11+
public class IRBindingsTests
12+
{
13+
[SkipTestMethod]
14+
public void LibLLVMHasUnwindDestTest( )
15+
{
16+
// As of this writing, the only implemented instructions that might contain an unwind dest are a CleanupReturn and
17+
// CatchSwitchInst, all other instructions result in a 0;
18+
// TODO: Figure out minimum API calls needed to build a valid case for each type and at least one for the "negative"
19+
// then validate the API returns the correct value.
20+
}
21+
}
22+
}
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
using System;
2+
3+
using Microsoft.VisualStudio.TestTools.UnitTesting;
4+
5+
using Ubiquity.NET.Llvm.Interop.UT;
6+
7+
namespace Ubiquity.NET.Llvm.Interop.ABI.libllvm_c.UT
8+
{
9+
[TestClass]
10+
public class MetadataBindingsTests
11+
{
12+
[SkipTestMethod]
13+
public void LibLLVMDIBasicTypeGetEncodingTest( )
14+
{
15+
throw new NotImplementedException();
16+
}
17+
18+
[SkipTestMethod]
19+
public void LibLLVMGetNodeContextTest( )
20+
{
21+
throw new NotImplementedException();
22+
}
23+
24+
[SkipTestMethod]
25+
public void LibLLVMDiCompileUnitGetEmissionKindTest( )
26+
{
27+
throw new NotImplementedException();
28+
}
29+
30+
[SkipTestMethod]
31+
public void LibLLVMDIBuilderCreateTempFunctionFwdDeclTest( )
32+
{
33+
throw new NotImplementedException();
34+
}
35+
36+
[SkipTestMethod]
37+
public void LibLLVMDIBuilderFinalizeSubProgramTest( )
38+
{
39+
throw new NotImplementedException();
40+
}
41+
42+
[SkipTestMethod]
43+
public void LibLLVMDIDescriptorGetTagTest( )
44+
{
45+
throw new NotImplementedException();
46+
}
47+
48+
[SkipTestMethod]
49+
public void LibLLVMDILocationGetInlinedAtScopeTest( )
50+
{
51+
throw new NotImplementedException();
52+
}
53+
54+
[SkipTestMethod]
55+
public void LibLLVMMetadataAsStringTest( )
56+
{
57+
throw new NotImplementedException();
58+
}
59+
60+
[SkipTestMethod]
61+
public void LibLLVMMDNodeGetNumOperandsTest( )
62+
{
63+
throw new NotImplementedException();
64+
}
65+
66+
[SkipTestMethod]
67+
public void LibLLVMMDNodeGetOperandTest( )
68+
{
69+
throw new NotImplementedException();
70+
}
71+
72+
[SkipTestMethod]
73+
public void LibLLVMMDNodeReplaceOperandTest( )
74+
{
75+
throw new NotImplementedException();
76+
}
77+
78+
[SkipTestMethod]
79+
public void LibLLVMGetOperandNodeTest( )
80+
{
81+
throw new NotImplementedException();
82+
}
83+
84+
[SkipTestMethod]
85+
public void LibLLVMNamedMetadataGetParentModuleTest( )
86+
{
87+
throw new NotImplementedException();
88+
}
89+
90+
[SkipTestMethod]
91+
public void LibLLVMNamedMetadataEraseFromParentTest( )
92+
{
93+
throw new NotImplementedException();
94+
}
95+
96+
[SkipTestMethod]
97+
public void LibLLVMGetMetadataIDTest( )
98+
{
99+
throw new NotImplementedException();
100+
}
101+
102+
[SkipTestMethod]
103+
public void LibLLVMNamedMDNodeGetNumOperandsTest( )
104+
{
105+
throw new NotImplementedException();
106+
}
107+
108+
[SkipTestMethod]
109+
public void LibLLVMNamedMDNodeGetOperandTest( )
110+
{
111+
throw new NotImplementedException();
112+
}
113+
114+
[SkipTestMethod]
115+
public void LibLLVMNamedMDNodeSetOperandTest( )
116+
{
117+
throw new NotImplementedException();
118+
}
119+
120+
[SkipTestMethod]
121+
public void LibLLVMNamedMDNodeAddOperandTest( )
122+
{
123+
throw new NotImplementedException();
124+
}
125+
126+
[SkipTestMethod]
127+
public void LibLLVMNamedMDNodeClearOperandsTest( )
128+
{
129+
throw new NotImplementedException();
130+
}
131+
132+
[SkipTestMethod]
133+
public void LibLLVMConstantAsMetadataTest( )
134+
{
135+
throw new NotImplementedException();
136+
}
137+
138+
[SkipTestMethod]
139+
public void LibLLVMGetMDStringTextTest( )
140+
{
141+
throw new NotImplementedException();
142+
}
143+
144+
[SkipTestMethod]
145+
public void LibLLVMAddNamedMetadataOperand2Test( )
146+
{
147+
throw new NotImplementedException();
148+
}
149+
150+
[SkipTestMethod]
151+
public void LibLLVMSetMetadata2Test( )
152+
{
153+
throw new NotImplementedException();
154+
}
155+
156+
[SkipTestMethod]
157+
public void LibLLVMIsTemporaryTest( )
158+
{
159+
throw new NotImplementedException();
160+
}
161+
162+
[SkipTestMethod]
163+
public void LibLLVMIsResolvedTest( )
164+
{
165+
throw new NotImplementedException();
166+
}
167+
168+
[SkipTestMethod]
169+
public void LibLLVMIsUniquedTest( )
170+
{
171+
throw new NotImplementedException();
172+
}
173+
174+
[SkipTestMethod]
175+
public void LibLLVMIsDistinctTest( )
176+
{
177+
throw new NotImplementedException();
178+
}
179+
180+
[SkipTestMethod]
181+
public void LibLLVMDISubRangeGetLowerBoundsTest( )
182+
{
183+
throw new NotImplementedException();
184+
}
185+
}
186+
}

0 commit comments

Comments
 (0)