Imported Upstream version 5.20.0.180

Former-commit-id: ff953ca879339fe1e1211f7220f563e1342e66cb
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-02-04 20:11:37 +00:00
parent 0e2d47d1c8
commit 0510252385
3360 changed files with 83827 additions and 39243 deletions

View File

@@ -10,6 +10,7 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Reflection;
[assembly: TestAssembly]
@@ -43,6 +44,7 @@ internal class ReflectionTest
TestCreateDelegate.Run();
TestInstanceFields.Run();
TestReflectionInvoke.Run();
TestByRefReturnInvoke.Run();
return 100;
}
@@ -89,9 +91,34 @@ internal class ReflectionTest
{
return "Hello " + _world;
}
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
#endif
public static unsafe string GetHelloPointer(char* ptr)
{
return "Hello " + unchecked((int)ptr);
}
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
#endif
public static unsafe string GetHelloPointerToo(char** ptr)
{
return "Hello " + unchecked((int)ptr);
}
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
#endif
public static unsafe bool* GetPointer(void* ptr, object dummyJustToMakeThisUseSharedThunk)
{
return (bool*)ptr;
}
}
public static void Run()
public static unsafe void Run()
{
Console.WriteLine(nameof(TestReflectionInvoke));
@@ -102,6 +129,9 @@ internal class ReflectionTest
InvokeTests.GetHello(null);
InvokeTests.GetHelloGeneric<int>(0);
InvokeTests.GetHelloGeneric<double>(0);
InvokeTests.GetHelloPointer(null);
InvokeTests.GetHelloPointerToo(null);
InvokeTests.GetPointer(null, null);
string unused;
InvokeTests.GetHelloByRef(null, out unused);
unused.ToString();
@@ -128,6 +158,31 @@ internal class ReflectionTest
if ((string)args[1] != "Hello world")
throw new Exception();
}
{
MethodInfo helloPointerMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHelloPointer");
string resultNull = (string)helloPointerMethod.Invoke(null, new object[] { null });
if (resultNull != "Hello 0")
throw new Exception();
string resultVal = (string)helloPointerMethod.Invoke(null, new object[] { Pointer.Box((void*)42, typeof(char*)) });
if (resultVal != "Hello 42")
throw new Exception();
}
{
MethodInfo helloPointerTooMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetHelloPointerToo");
string result = (string)helloPointerTooMethod.Invoke(null, new object[] { Pointer.Box((void*)85, typeof(char**)) });
if (result != "Hello 85")
throw new Exception();
}
{
MethodInfo getPointerMethod = typeof(InvokeTests).GetTypeInfo().GetDeclaredMethod("GetPointer");
object result = getPointerMethod.Invoke(null, new object[] { Pointer.Box((void*)2018, typeof(void*)), null });
if (Pointer.Unbox(result) != (void*)2018)
throw new Exception();
}
}
}
@@ -384,7 +439,23 @@ internal class ReflectionTest
}
}
ref struct ByRefLike<T>
{
public readonly T Value;
public ByRefLike(T value)
{
Value = value;
}
public override string ToString()
{
return Value.ToString() + " " + typeof(T).ToString();
}
}
delegate string ToStringDelegate(ref ByRefLike thisObj);
delegate string ToStringDelegate<T>(ref ByRefLike<T> thisObj);
public static void Run()
{
@@ -396,15 +467,40 @@ internal class ReflectionTest
default(ByRefLike).ToString();
ToStringDelegate s = null;
s = s.Invoke;
default(ByRefLike<object>).ToString();
ToStringDelegate<object> s2 = null;
s2 = s2.Invoke;
}
Type byRefLikeType = GetTestType(nameof(TestByRefLikeTypeMethod), nameof(ByRefLike));
MethodInfo toStringMethod = byRefLikeType.GetMethod("ToString");
var toString = (ToStringDelegate)toStringMethod.CreateDelegate(typeof(ToStringDelegate));
{
Type byRefLikeType = GetTestType(nameof(TestByRefLikeTypeMethod), nameof(ByRefLike));
MethodInfo toStringMethod = byRefLikeType.GetMethod("ToString");
var toString = (ToStringDelegate)toStringMethod.CreateDelegate(typeof(ToStringDelegate));
ByRefLike foo = new ByRefLike(123);
if (toString(ref foo) != "123")
throw new Exception();
ByRefLike foo = new ByRefLike(123);
if (toString(ref foo) != "123")
throw new Exception();
}
{
Type byRefLikeGenericType = typeof(ByRefLike<string>);
MethodInfo toStringGenericMethod = byRefLikeGenericType.GetMethod("ToString");
var toStringGeneric = (ToStringDelegate<string>)toStringGenericMethod.CreateDelegate(typeof(ToStringDelegate<string>));
ByRefLike<string> fooGeneric = new ByRefLike<string>("Hello");
if (toStringGeneric(ref fooGeneric) != "Hello System.String")
throw new Exception();
}
{
Type byRefLikeGenericType = typeof(ByRefLike<object>);
MethodInfo toStringGenericMethod = byRefLikeGenericType.GetMethod("ToString");
var toStringGeneric = (ToStringDelegate<object>)toStringGenericMethod.CreateDelegate(typeof(ToStringDelegate<object>));
ByRefLike<object> fooGeneric = new ByRefLike<object>("Hello");
if (toStringGeneric(ref fooGeneric) != "Hello System.Object")
throw new Exception();
}
}
}
@@ -501,6 +597,203 @@ internal class ReflectionTest
}
}
class TestByRefReturnInvoke
{
enum Mine { One = 2018 }
[StructLayout(LayoutKind.Sequential)]
struct BigStruct { public ulong X, Y, Z, W, A, B, C, D; }
public ref struct ByRefLike { }
private sealed class TestClass<T>
{
private T _value;
public TestClass(T value) { _value = value; }
public ref T RefReturningProp
{
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
get => ref _value;
}
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
public static unsafe ref ByRefLike ByRefLikeRefReturningMethod(ByRefLike* a) => ref *a;
}
private sealed unsafe class TestClassIntPointer
{
private int* _value;
public TestClassIntPointer(int* value) { _value = value; }
public ref int* RefReturningProp
{
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
get => ref _value;
}
public unsafe ref int* NullRefReturningProp
{
#if OPTIMIZED_MODE_WITHOUT_SCANNER
[MethodImpl(MethodImplOptions.NoInlining)]
#endif
get => ref *(int**)null;
}
}
public static void TestRefReturnPropertyGetValue()
{
TestRefReturnInvoke('a', (p, t) => p.GetValue(t));
TestRefReturnInvoke(Mine.One, (p, t) => p.GetValue(t));
TestRefReturnInvoke("Hello", (p, t) => p.GetValue(t));
TestRefReturnInvoke(new BigStruct { X = 123, D = 456 }, (p, t) => p.GetValue(t));
TestRefReturnInvoke(new object(), (p, t) => p.GetValue(t));
TestRefReturnInvoke((object)null, (p, t) => p.GetValue(t));
}
public static void TestRefReturnMethodInvoke()
{
TestRefReturnInvoke(Mine.One, (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
TestRefReturnInvoke("Hello", (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
TestRefReturnInvoke(new BigStruct { X = 123, D = 456 }, (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
TestRefReturnInvoke(new object(), (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
TestRefReturnInvoke((object)null, (p, t) => p.GetGetMethod().Invoke(t, Array.Empty<object>()));
}
public static void TestRefReturnNullable()
{
TestRefReturnInvokeNullable<int>(42);
TestRefReturnInvokeNullable<Mine>(Mine.One);
TestRefReturnInvokeNullable<BigStruct>(new BigStruct { X = 987, D = 543 });
}
public static void TestRefReturnNullableNoValue()
{
TestRefReturnInvokeNullable<int>(default(int?));
TestRefReturnInvokeNullable<Mine>(default(Mine?));
TestRefReturnInvokeNullable<BigStruct>(default(BigStruct?));
}
public static unsafe void TestRefReturnOfPointer()
{
int* expected = (int*)0x1122334455667788;
TestClassIntPointer tc = new TestClassIntPointer(expected);
if (string.Empty.Length > 0)
{
((IntPtr)tc.RefReturningProp).ToString();
}
PropertyInfo p = typeof(TestClassIntPointer).GetProperty(nameof(TestClassIntPointer.RefReturningProp));
object rv = p.GetValue(tc);
Assert.True(rv is Pointer);
int* actual = (int*)(Pointer.Unbox(rv));
Assert.Equal((IntPtr)expected, (IntPtr)actual);
}
public static unsafe void TestNullRefReturnOfPointer()
{
TestClassIntPointer tc = new TestClassIntPointer(null);
if (string.Empty.Length > 0)
{
((IntPtr)tc.NullRefReturningProp).ToString();
}
PropertyInfo p = typeof(TestClassIntPointer).GetProperty(nameof(TestClassIntPointer.NullRefReturningProp));
Assert.NotNull(p);
Assert.Throws<NullReferenceException>(() => p.GetValue(tc));
}
public static unsafe void TestByRefLikeRefReturn()
{
if (string.Empty.Length > 0)
{
TestClass<int>.ByRefLikeRefReturningMethod(null);
}
ByRefLike brl = new ByRefLike();
ByRefLike* pBrl = &brl;
MethodInfo mi = typeof(TestClass<int>).GetMethod(nameof(TestClass<int>.ByRefLikeRefReturningMethod));
try
{
// Don't use Assert.Throws because that will make a lambda and invalidate the pointer
object o = mi.Invoke(null, new object[] { Pointer.Box(pBrl, typeof(ByRefLike*)) });
Assert.Fail();
}
catch (NotSupportedException)
{
}
}
private static void TestRefReturnInvoke<T>(T value, Func<PropertyInfo, TestClass<T>, object> invoker)
{
TestClass<T> tc = new TestClass<T>(value);
if (String.Empty.Length > 0)
{
tc.RefReturningProp.ToString();
}
PropertyInfo p = typeof(TestClass<T>).GetProperty(nameof(TestClass<T>.RefReturningProp));
object rv = invoker(p, tc);
if (rv != null)
{
Assert.Equal(typeof(T), rv.GetType());
}
if (typeof(T).IsValueType)
{
Assert.Equal(value, rv);
}
else
{
Assert.Same(value, rv);
}
}
private static void TestRefReturnInvokeNullable<T>(T? nullable) where T : struct
{
TestClass<T?> tc = new TestClass<T?>(nullable);
if (string.Empty.Length > 0)
{
tc.RefReturningProp.ToString();
}
PropertyInfo p = typeof(TestClass<T?>).GetProperty(nameof(TestClass<T?>.RefReturningProp));
object rv = p.GetValue(tc);
if (rv != null)
{
Assert.Equal(typeof(T), rv.GetType());
}
if (nullable.HasValue)
{
Assert.Equal(nullable.Value, rv);
}
else
{
Assert.Null(rv);
}
}
public static void Run()
{
Console.WriteLine(nameof(TestByRefReturnInvoke));
TestRefReturnPropertyGetValue();
TestRefReturnMethodInvoke();
TestRefReturnNullable();
TestRefReturnNullableNoValue();
TestRefReturnOfPointer();
TestNullRefReturnOfPointer();
TestByRefLikeRefReturn();
}
}
#region Helpers
private static Type GetTestType(string testName, string typeName)
@@ -534,6 +827,66 @@ internal class ReflectionTest
return true;
}
class Assert
{
public static void Equal<T>(T expected, T actual)
{
if (object.ReferenceEquals(expected, actual))
return;
if ((object)expected == null || (object)actual == null)
throw new Exception();
if (!expected.Equals(actual))
throw new Exception();
}
public static void Same<T>(T expected, T actual)
{
if (!object.ReferenceEquals(expected, actual))
throw new Exception();
}
public static void Null(object x)
{
if (x != null)
throw new Exception();
}
public static void NotNull(object x)
{
if (x == null)
throw new Exception();
}
public static void True(bool x)
{
if (!x)
throw new Exception();
}
public static void Fail()
{
throw new Exception();
}
public static void Throws<T>(Action a)
{
try
{
a();
}
catch (Exception ex)
{
if (ex.GetType() != typeof(T))
throw new Exception();
return;
}
throw new Exception();
}
}
#endregion
}