1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-16 15:24:10 +02:00
Beef/IDEHelper/Tests/src/Reflection.bf

623 lines
15 KiB
Beef
Raw Normal View History

2020-07-18 06:51:33 -07:00
#pragma warning disable 168
2019-08-23 11:56:54 -07:00
using System;
2020-08-24 10:19:17 -07:00
using System.Reflection;
2019-08-23 11:56:54 -07:00
namespace Tests
{
class Reflection
{
[AttributeUsage(.Field, .ReflectAttribute)]
struct AttrAAttribute : Attribute
{
public int32 mA;
public float mB;
public String mC;
public String mD;
public bool mE;
2019-08-23 11:56:54 -07:00
public this(int32 a, float b, String c, String d = "D", bool e = true)
2019-08-23 11:56:54 -07:00
{
//PrintF("this: %p A: %d B: %f", this, a, (double)b);
2019-08-23 11:56:54 -07:00
mA = a;
mB = b;
mC = c;
mD = d;
mE = e;
2019-08-23 11:56:54 -07:00
}
}
[AttributeUsage(.Field)]
struct AttrBAttribute : Attribute
{
public int32 mA;
public float mB;
public this(int32 a, float b)
{
mA = a;
mB = b;
}
}
[AttributeUsage(.Class | .Method, .ReflectAttribute)]
struct AttrCAttribute : Attribute
{
public int32 mA;
public float mB;
2019-08-23 11:56:54 -07:00
public this(int32 a, float b)
{
mA = a;
mB = b;
}
}
2020-07-18 05:27:09 -07:00
[AttributeUsage(.Class | .Method, ReflectUser=.All)]
struct AttrDAttribute : Attribute
{
}
2019-08-23 11:56:54 -07:00
[Reflect]
class ClassA
{
2020-07-06 09:55:19 -07:00
public int32 mA = 123;
public String mStr = "A";
public static int32 sA = 234;
public static String sStr = "AA";
[AlwaysInclude, AttrC(71, 72)]
static float StaticMethodA(int32 a, int32 b, float c, ref int32 d, ref StructA sa)
2019-08-23 11:56:54 -07:00
{
d += a + b;
sa.mA += a;
sa.mB += b;
2019-08-23 11:56:54 -07:00
return a + b + c;
}
[AlwaysInclude]
static StructA StaticMethodB(ref int32 a, ref String b)
{
a += 1000;
b = "B";
StructA sa;
sa.mA = 12;
sa.mB = 34;
return sa;
}
2019-08-23 11:56:54 -07:00
[AlwaysInclude]
float MemberMethodA(int32 a, int32 b, float c)
{
return a + b + c;
}
public virtual int GetA(int32 a)
{
return a + 1000;
}
public virtual int GetB(int32 a)
{
return a + 3000;
}
}
[Reflect, AlwaysInclude(IncludeAllMethods=true)]
interface IFaceA
{
void MethodA0();
int MethodA1(int a, float b);
}
[Reflect, AlwaysInclude(IncludeAllMethods=true)]
struct StructA : IFaceA
{
public int mA;
public int mB;
int GetA(int a)
{
return a + mA * 100;
}
int GetB(int a) mut
{
mB += a;
return a + mA * 100;
}
public void MethodA0()
{
}
public int MethodA1(int a, float b)
{
return mA + a + (int)b;
}
}
2020-08-25 07:08:44 -07:00
struct StructC
{
public float mA;
public float mB;
}
2020-08-24 10:19:17 -07:00
[Reflect, AlwaysInclude(AssumeInstantiated=true, IncludeAllMethods=true)]
struct StructB
{
public int mA;
public String mB;
2020-08-25 07:08:44 -07:00
public StructC mC;
2020-08-24 10:19:17 -07:00
}
2019-08-23 11:56:54 -07:00
class ClassA2 : ClassA
{
public override int GetA(int32 a)
{
return a + 2000;
}
public override int GetB(int32 a)
{
return a + 4000;
}
}
[Reflect(.All), AttrC(1, 2)]
2019-08-23 11:56:54 -07:00
class ClassB
{
2020-07-18 05:27:09 -07:00
[AttrA(11, 22, "StrA")]
2019-11-29 09:22:18 -08:00
public int mA = 1;
2019-08-23 11:56:54 -07:00
[AttrB(44, 55)]
2019-11-29 09:22:18 -08:00
public int mB = 2;
public int mC = 3;
2020-05-13 15:07:03 -07:00
public String mStr = "ABC";
2019-08-23 11:56:54 -07:00
}
2020-07-18 05:27:09 -07:00
[AttrD]
2019-08-23 11:56:54 -07:00
class ClassC
{
2019-11-29 09:22:18 -08:00
public int mA = 1;
public int mB = 2;
2020-07-18 05:27:09 -07:00
}
class ClassD
{
public int mA = 1;
public int mB = 2;
[AttrD]
public void MethodA()
{
}
}
class ClassE
{
public int mA = 1;
public int mB = 2;
[AttrD]
public void MethodA()
{
}
2019-08-23 11:56:54 -07:00
}
[Test]
static void TestTypes()
{
Type t = typeof(int32);
Test.Assert(t.InstanceSize == 4);
t = typeof(int64);
Test.Assert(t.InstanceSize == 8);
}
2019-08-23 11:56:54 -07:00
[Test]
static void TestA()
{
2020-07-21 13:14:20 -07:00
ClassA ca = (ClassA)typeof(ClassA).CreateObject().Value;
defer delete ca;
Test.Assert(ca.mA == 123);
Test.Assert(ca.mStr === "A");
2019-08-23 11:56:54 -07:00
ClassA2 ca2 = scope ClassA2();
2019-08-23 11:56:54 -07:00
Test.Assert(ca2.GetA(9) == 2009);
int methodIdx = 0;
var typeInfo = typeof(ClassA);
for (let methodInfo in typeInfo.GetMethods())
{
switch (methodIdx)
{
case 0:
2021-02-25 10:14:22 -08:00
Test.Assert(methodInfo.Name == "__BfCtor");
Test.Assert(methodInfo.IsConstructor);
case 1:
Test.Assert(methodInfo.Name == "__BfStaticCtor");
Test.Assert(methodInfo.IsConstructor);
case 2:
Test.Assert(methodInfo.Name == "GetA");
var result = methodInfo.Invoke(ca, 123).Get();
Test.Assert(result.Get<int>() == 1123);
result.Dispose();
result = methodInfo.Invoke(ca2, 123).Get();
Test.Assert(result.Get<int>() == 2123);
result.Dispose();
result = methodInfo.Invoke(.Create(ca2), .Create(123)).Get();
Test.Assert(result.Get<int>() == 2123);
result.Dispose();
case 3:
Test.Assert(methodInfo.Name == "MemberMethodA");
var result = methodInfo.Invoke(ca, 100, (int32)20, 3.0f).Get();
Test.Assert(result.Get<float>() == 123);
result.Dispose();
result = methodInfo.Invoke(.Create(ca), .Create(100), .Create((int32)20), .Create(3.0f)).Get();
Test.Assert(result.Get<float>() == 123);
result.Dispose();
case 4:
StructA sa = .() { mA = 1, mB = 2 };
2019-08-23 11:56:54 -07:00
Test.Assert(methodInfo.Name == "StaticMethodA");
int32 a = 0;
var result = methodInfo.Invoke(null, 100, (int32)20, 3.0f, &a, &sa).Get();
Test.Assert(a == 120);
Test.Assert(sa.mA == 101);
Test.Assert(sa.mB == 22);
2019-08-23 11:56:54 -07:00
Test.Assert(result.Get<float>() == 123);
result.Dispose();
Object aObj = a;
Object saObj = sa;
Test.Assert(methodInfo.Name == "StaticMethodA");
result = methodInfo.Invoke(null, 100, (int32)20, 3.0f, aObj, saObj).Get();
Test.Assert(a == 120);
Test.Assert(sa.mA == 101);
Test.Assert(sa.mB == 22);
int32 a2 = (int32)aObj;
StructA sa2 = (StructA)saObj;
Test.Assert(a2 == 240);
Test.Assert(sa2.mA == 201);
Test.Assert(sa2.mB == 42);
Test.Assert(result.Get<float>() == 123);
result.Dispose();
result = methodInfo.Invoke(.(), .Create(100), .Create((int32)20), .Create(3.0f), .Create(&a), .Create(&sa)).Get();
Test.Assert(a == 240);
Test.Assert(sa.mA == 201);
Test.Assert(sa.mB == 42);
Test.Assert(result.Get<float>() == 123);
result.Dispose();
Variant aV = .CreateOwned(a);
Variant saV = .CreateOwned(sa);
result = methodInfo.Invoke(.(), .Create(100), .Create((int32)20), .Create(3.0f), aV, saV).Get();
Test.Assert(a == 240);
Test.Assert(sa.mA == 201);
Test.Assert(sa.mB == 42);
a2 = aV.Get<int32>();
sa2 = saV.Get<StructA>();
Test.Assert(a2 == 360);
Test.Assert(sa2.mA == 301);
Test.Assert(sa2.mB == 62);
Test.Assert(result.Get<float>() == 123);
aV.Dispose();
saV.Dispose();
result.Dispose();
let attrC = methodInfo.GetCustomAttribute<AttrCAttribute>().Get();
Test.Assert(attrC.mA == 71);
Test.Assert(attrC.mB == 72);
2021-02-25 10:14:22 -08:00
case 5:
Test.Assert(methodInfo.Name == "StaticMethodB");
var fieldA = typeInfo.GetField("mA").Value;
var fieldStr = typeInfo.GetField("mStr").Value;
var fieldAV = fieldA.GetValueReference(ca).Value;
var fieldStrV = fieldStr.GetValueReference(ca).Value;
Test.Assert(fieldAV.Get<int32>() == 123);
Test.Assert(fieldStrV.Get<String>() == "A");
var res = methodInfo.Invoke(.(), fieldAV, fieldStrV).Value;
2020-07-06 09:55:19 -07:00
Test.Assert(ca.mA == 1123);
2020-07-06 12:26:06 -07:00
Test.Assert(ca.mStr == "B");
var sa = res.Get<StructA>();
Test.Assert(sa.mA == 12);
Test.Assert(sa.mB == 34);
res.Dispose();
Test.Assert(fieldAV.Get<int32>() == 1123);
Test.Assert(fieldStrV.Get<String>() == "B");
fieldAV.Dispose();
fieldStrV.Dispose();
fieldAV = fieldA.GetValue(ca).Value;
fieldStrV = fieldStr.GetValue(ca).Value;
Test.Assert(fieldAV.Get<int32>() == 1123);
Test.Assert(fieldStrV.Get<String>() == "B");
fieldAV.Dispose();
fieldStrV.Dispose();
2020-07-06 09:55:19 -07:00
var fieldSA = typeInfo.GetField("sA").Value;
var fieldSStr = typeInfo.GetField("sStr").Value;
var fieldSAV = fieldSA.GetValueReference(null).Value;
var fieldSStrV = fieldSStr.GetValueReference(null).Value;
Test.Assert(fieldSAV.Get<int32>() == 234);
Test.Assert(fieldSStrV.Get<String>() == "AA");
res = methodInfo.Invoke(.(), fieldSAV, fieldSStrV).Value;
Test.Assert(fieldSAV.Get<int32>() == 1234);
Test.Assert(fieldSStrV.Get<String>() == "B");
Test.Assert(ClassA.sA == 1234);
Test.Assert(ClassA.sStr == "B");
res.Dispose();
fieldSAV.Dispose();
fieldSStrV.Dispose();
2020-07-06 12:26:06 -07:00
case 6:
2019-08-23 11:56:54 -07:00
Test.FatalError(); // Shouldn't have any more
}
methodIdx++;
}
}
[Test]
static void TestB()
{
ClassB cb = scope ClassB();
int fieldIdx = 0;
for (let fieldInfo in cb.GetType().GetFields())
{
switch (fieldIdx)
{
case 0:
Test.Assert(fieldInfo.Name == "mA");
var attrA = fieldInfo.GetCustomAttribute<AttrAAttribute>().Get();
Test.Assert(attrA.mA == 11);
Test.Assert(attrA.mB == 22);
Test.Assert(attrA.mC == "StrA");
2020-07-18 05:27:09 -07:00
Test.Assert(attrA.mD == "D");
Test.Assert(attrA.mE == true);
2019-08-23 11:56:54 -07:00
}
fieldIdx++;
}
2019-11-29 09:22:18 -08:00
2020-07-18 05:27:09 -07:00
Test.Assert(fieldIdx == 4);
2020-05-13 15:07:03 -07:00
var fieldInfo = cb.GetType().GetField("mC").Value;
2019-11-29 09:22:18 -08:00
int cVal = 0;
fieldInfo.GetValue(cb, out cVal);
fieldInfo.SetValue(cb, cVal + 1000);
Test.Assert(cb.mC == 1003);
Variant variantVal = Variant.Create(123);
fieldInfo.SetValue(cb, variantVal);
Test.Assert(cb.mC == 123);
2020-05-13 15:07:03 -07:00
fieldInfo = cb.GetType().GetField("mStr").Value;
String str = null;
fieldInfo.GetValue(cb, out str);
Test.Assert(str == "ABC");
fieldInfo.SetValue(cb, "DEF");
Test.Assert(cb.mStr == "DEF");
2019-08-23 11:56:54 -07:00
}
[Test]
static void TestC()
{
let attrC = typeof(ClassB).GetCustomAttribute<AttrCAttribute>().Get();
Test.Assert(attrC.mA == 1);
Test.Assert(attrC.mB == 2);
2020-07-18 05:27:09 -07:00
ClassC c = scope .();
Test.Assert(typeof(ClassC).GetField("mA").Value.Name == "mA");
Test.Assert(typeof(ClassC).GetField("mB").Value.Name == "mB");
ClassD cd = scope .();
Test.Assert(typeof(ClassD).GetField("mA") case .Err);
// Should this reified call cause fields to be reflected?
/*ClassE ce = scope .();
ce.MethodA();
Test.Assert(typeof(ClassE).GetField("mA").Value.Name == "mA");*/
}
[Test]
2020-07-18 05:27:09 -07:00
static void TestStructA()
{
StructA sa = .() { mA = 12, mB = 23 };
var typeInfo = typeof(StructA);
int methodIdx = 0;
for (let methodInfo in typeInfo.GetMethods())
{
switch (methodIdx)
{
case 0:
2021-02-25 10:14:22 -08:00
Test.Assert(methodInfo.Name == "__BfCtor");
case 1:
Test.Assert(methodInfo.Name == "GetA");
var result = methodInfo.Invoke(sa, 34).Get();
Test.Assert(result.Get<int32>() == 1234);
result.Dispose();
result = methodInfo.Invoke(&sa, 34).Get();
Test.Assert(result.Get<int32>() == 1234);
result.Dispose();
Variant saV = .Create(sa);
defer saV.Dispose();
result = methodInfo.Invoke(saV, .Create(34));
Test.Assert(result.Get<int32>() == 1234);
result.Dispose();
result = methodInfo.Invoke(.Create(&sa), .Create(34));
Test.Assert(result.Get<int32>() == 1234);
result.Dispose();
2021-02-25 10:14:22 -08:00
case 2:
Test.Assert(methodInfo.Name == "GetB");
var result = methodInfo.Invoke(sa, 34).Get();
Test.Assert(result.Get<int32>() == 1234);
Test.Assert(sa.mB == 23);
result.Dispose();
result = methodInfo.Invoke(&sa, 34).Get();
Test.Assert(result.Get<int32>() == 1234);
Test.Assert(sa.mB == 57);
result.Dispose();
Variant saV = .Create(sa);
defer saV.Dispose();
result = methodInfo.Invoke(saV, .Create(34));
Test.Assert(result.Get<int32>() == 1234);
Test.Assert(sa.mB == 57);
result.Dispose();
result = methodInfo.Invoke(.Create(&sa), .Create(34));
Test.Assert(result.Get<int32>() == 1234);
Test.Assert(sa.mB == 91);
result.Dispose();
case 3:
2021-02-25 10:14:22 -08:00
Test.Assert(methodInfo.Name == "MethodA0");
case 4:
2021-02-25 10:14:22 -08:00
Test.Assert(methodInfo.Name == "MethodA1");
case 5:
Test.Assert(methodInfo.Name == "__Equals");
case 6:
Test.Assert(methodInfo.Name == "__StrictEquals");
2021-02-25 10:14:22 -08:00
default:
Test.FatalError(); // Shouldn't have any more
}
methodIdx++;
}
let ifaceType = typeof(IFaceA);
let methodA1 = ifaceType.GetMethod("MethodA1").Value;
var saVariant = Variant.Create(sa);
defer saVariant.Dispose();
var result = methodA1.Invoke(saVariant, .Create(1000), .Create(2000.f)).Value;
Test.Assert(result.Get<int>() == 3012);
result = methodA1.Invoke(.Create(&sa), .Create(1000), .Create(2000.f)).Value;
Test.Assert(result.Get<int>() == 3012);
}
2020-08-24 10:19:17 -07:00
[Test]
static void TestStructB()
{
StructB sb;
sb.mA = 25;
sb.mB = "Struct B";
2020-08-25 07:08:44 -07:00
sb.mC = .() { mA = 1.2f, mB = 2.3f };
2020-08-24 10:19:17 -07:00
Variant sbVariant = .Create(sb);
defer sbVariant.Dispose();
2020-08-24 10:19:17 -07:00
let type = sb.GetType() as TypeInstance;
let fields = type.GetFields();
int fieldIdx = 0;
for (let field in fields)
{
2020-08-25 08:02:55 -07:00
var fieldVal = field.GetValue(sb).Value;
defer fieldVal.Dispose();
2020-08-25 08:02:55 -07:00
var fieldVal2 = field.GetValue(&sb).Value;
defer fieldVal2.Dispose();
var fieldVal3 = field.GetValue(sbVariant).Value;
defer fieldVal3.Dispose();
2020-08-24 10:19:17 -07:00
switch (fieldIdx)
{
case 0:
2020-08-25 08:02:55 -07:00
Test.Assert(fieldVal.Get<int>() == 25);
2020-08-25 07:08:44 -07:00
Variant newVal = Variant.Create<int>(32);
field.SetValue(sb, newVal);
Test.Assert(sb.mA == 25);
2020-08-25 08:02:55 -07:00
Test.Assert(fieldVal2.Get<int>() == 25);
2020-08-25 07:08:44 -07:00
field.SetValue(&sb, newVal);
Test.Assert(sb.mA == 32);
Test.Assert(fieldVal3.Get<int>() == 25);
field.SetValue(&sb, newVal);
Test.Assert(sb.mA == 32);
field.SetValue(sbVariant, 34);
fieldVal3.Dispose();
fieldVal3 = field.GetValue(sbVariant).Value;
Test.Assert(fieldVal3.Get<int>() == 34);
Variant varInt = .Create(45);
field.SetValue(sbVariant, varInt);
fieldVal3.Dispose();
fieldVal3 = field.GetValue(sbVariant).Value;
Test.Assert(fieldVal3.Get<int>() == 45);
field.SetValue(&sb, varInt);
fieldVal2.Dispose();
fieldVal2 = field.GetValue(&sb).Value;
Test.Assert(fieldVal2.Get<int>() == 45);
2020-08-24 10:19:17 -07:00
case 1:
2020-08-25 08:02:55 -07:00
Test.Assert(fieldVal.Get<String>() === "Struct B");
2020-08-25 07:08:44 -07:00
field.SetValue(&sb, "Struct C");
Test.Assert(sb.mB == "Struct C");
2020-08-24 10:19:17 -07:00
case 2:
2020-08-25 07:08:44 -07:00
StructC sc = .() { mA = 1.2f, mB = 2.3f };
2020-08-25 08:02:55 -07:00
Test.Assert(fieldVal.Get<StructC>() == sc);
Test.Assert(fieldVal2.Get<StructC>() == sc);
2020-08-25 07:08:44 -07:00
sc.mA += 100;
sc.mB += 100;
field.SetValue(&sb, sc);
Test.Assert(sb.mC.mA == 101.2f);
Test.Assert(sb.mC.mB == 102.3f);
sc.mA += 100;
sc.mB += 100;
field.SetValue(&sb, &sc);
Test.Assert(sb.mC.mA == 201.2f);
Test.Assert(sb.mC.mB == 202.3f);
sc.mA += 100;
sc.mB += 100;
Variant newVariant = Variant.Create(sc);
field.SetValue(&sb, newVariant);
2020-08-25 08:02:55 -07:00
newVariant.Dispose();
2020-08-25 07:08:44 -07:00
Test.Assert(sb.mC.mA == 301.2f);
Test.Assert(sb.mC.mB == 302.3f);
sc.mA += 100;
sc.mB += 100;
newVariant.Dispose();
newVariant = Variant.Create(&sc);
field.SetValue(&sb, newVariant);
2020-08-25 08:02:55 -07:00
newVariant.Dispose();
2020-08-25 07:08:44 -07:00
Test.Assert(sb.mC.mA == 401.2f);
Test.Assert(sb.mC.mB == 402.3f);
sc.mA += 100;
sc.mB += 100;
newVariant = Variant.CreateReference(typeof(StructC), &sc);
field.SetValue(&sb, newVariant);
2020-08-25 08:02:55 -07:00
newVariant.Dispose();
2020-08-25 07:08:44 -07:00
Test.Assert(sb.mC.mA == 501.2f);
Test.Assert(sb.mC.mB == 502.3f);
case 3:
2020-08-24 10:19:17 -07:00
Test.FatalError();
}
fieldIdx++;
}
}
2019-08-23 11:56:54 -07:00
}
}