diff options
author | Larry Ewing <lewing@microsoft.com> | 2022-04-16 02:55:38 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-16 02:55:38 +0300 |
commit | 1e81682d7eed05b5bcdda00f757f485bf8a02e80 (patch) | |
tree | 139defedcc2ec199d87ca42e06a9b837a565aa01 /src/tests/Loader | |
parent | d386b72ef72192692b21abed1aaedda10edd2e1f (diff) | |
parent | 736883624a7ef175729cf082e12ce18f236d8524 (diff) |
Merge branch 'main' into darc-main-31d4c308-6782-4440-8589-61f58f239059
Diffstat (limited to 'src/tests/Loader')
-rw-r--r-- | src/tests/Loader/classloader/generics/Pointers/Pointers.cs | 220 | ||||
-rw-r--r-- | src/tests/Loader/classloader/generics/Pointers/Pointers.csproj | 12 |
2 files changed, 232 insertions, 0 deletions
diff --git a/src/tests/Loader/classloader/generics/Pointers/Pointers.cs b/src/tests/Loader/classloader/generics/Pointers/Pointers.cs new file mode 100644 index 00000000000..99d1dc2e838 --- /dev/null +++ b/src/tests/Loader/classloader/generics/Pointers/Pointers.cs @@ -0,0 +1,220 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +using Xunit; + +unsafe class Pointers +{ + private struct Struct { public int Num; } + + private class Test<T> where T : unmanaged + { + public T Pointer(T* pointer) => *pointer; + + public T[] PointerArray(T*[] array) + { + T[] res = new T[array.Length]; + for (int i = 0; i < array.Length; i++) + res[i] = *array[i]; + + return res; + } + + public void FunctionPointer(delegate*<T, void> func) => func(default); + + public void FunctionPointerArray(delegate*<T, void>[] array) + { + foreach (var func in array) + func(default); + } + } + + private class TestTwoParams<T, U> where T : unmanaged where U : unmanaged + { + public (T, U) Pointer(T* pointer1, U* pointer2) => (*pointer1, *pointer2); + + public (T[], U[]) PointerArray(T*[] array1, U*[] array2) + { + T[] res1 = new T[array1.Length]; + for (int i = 0; i < array1.Length; i++) + res1[i] = *array1[i]; + + U[] res2 = new U[array2.Length]; + for (int i = 0; i < array2.Length; i++) + res2[i] = *array2[i]; + + return (res1, res2); + } + + public void FunctionPointer(delegate*<T, void> func1, delegate*<U, void> func2) + { + func1(default); + func2(default); + } + + public void FunctionPointerArray(delegate*<T, void>[] array1, delegate*<U, void>[] array2) + { + foreach (var func in array1) + func(default); + + foreach (var func in array2) + func(default); + } + } + + [Fact] + public static void Pointer() + { + Console.WriteLine($"Validating {nameof(Pointer)}..."); + PointerImpl(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void PointerImpl() + { + int i = 0; + Struct s = default; + { + var t = new Test<int>(); + int res = t.Pointer(&i); + Assert.Equal(i, res); + } + { + var t = new Test<Struct>(); + Struct res = t.Pointer(&s); + Assert.Equal(s, res); + } + { + var t = new TestTwoParams<int, Struct>(); + (int res1, Struct res2) = t.Pointer(&i, &s); + Assert.Equal(i, res1); + Assert.Equal(s, res2); + } + } + + [Fact] + public static void PointerArray() + { + Console.WriteLine($"Validating {nameof(PointerArray)}..."); + PointerArrayImpl(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void PointerArrayImpl() + { + int*[] intPtrArray = new int*[5]; + Span<int> intSpan = stackalloc int[intPtrArray.Length]; + int* intArray = (int*)Unsafe.AsPointer(ref intSpan.GetPinnableReference()); + for (int i = 0; i < intPtrArray.Length; i++) + { + intArray[i] = i; + intPtrArray[i] = &intArray[i]; + } + + Struct*[] structPtrArray = new Struct*[5]; + Span<Struct> structSpan = stackalloc Struct[structPtrArray.Length]; + Struct* structArray = (Struct*)Unsafe.AsPointer(ref structSpan.GetPinnableReference()); + for (int i = 0; i < structPtrArray.Length; i++) + { + structArray[i] = new Struct() { Num = i }; + structPtrArray[i] = &structArray[i]; + } + + { + var t = new Test<int>(); + int[] res = t.PointerArray(intPtrArray); + Assert.True(intSpan.SequenceEqual(res)); + } + { + var t = new Test<Struct>(); + Struct[] res = t.PointerArray(structPtrArray); + Assert.True(structSpan.SequenceEqual(res)); + } + { + var t = new TestTwoParams<int, Struct>(); + (int[] res1, Struct[] res2) = t.PointerArray(intPtrArray, structPtrArray); + Assert.True(intSpan.SequenceEqual(res1)); + Assert.True(structSpan.SequenceEqual(res2)); + } + } + + [Fact] + public static void FunctionPointer() + { + Console.WriteLine($"Validating {nameof(FunctionPointer)}..."); + FunctionPointerImpl(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void FunctionPointerImpl() + { + s_takeIntCallCount = 0; + s_takeStructCallCount = 0; + { + var t = new Test<int>(); + t.FunctionPointer(&TakeInt); + Assert.Equal(1, s_takeIntCallCount); + } + { + var t = new Test<Struct>(); + t.FunctionPointer(&TakeStruct); + Assert.Equal(1, s_takeStructCallCount); + } + { + var t = new TestTwoParams<int, Struct>(); + t.FunctionPointer(&TakeInt, &TakeStruct); + Assert.Equal(2, s_takeIntCallCount); + Assert.Equal(2, s_takeStructCallCount); + } + + } + + [Fact] + public static void FunctionPointerArray() + { + Console.WriteLine($"Validating {nameof(FunctionPointerArray)}..."); + FunctionPointerArrayImpl(); + } + + [MethodImpl(MethodImplOptions.NoInlining)] + private static void FunctionPointerArrayImpl() + { + int length = 5; + delegate*<int, void>[] intFuncArray = new delegate*<int, void>[length]; + delegate*<Struct, void>[] structFuncArray = new delegate*<Struct, void>[length]; + for (int i = 0; i < length; i++) + { + intFuncArray[i] = &TakeInt; + structFuncArray[i] = &TakeStruct; + } + + s_takeIntCallCount = 0; + s_takeStructCallCount = 0; + { + var t = new Test<int>(); + t.FunctionPointerArray(intFuncArray); + Assert.Equal(length, s_takeIntCallCount); + } + { + var t = new Test<Struct>(); + t.FunctionPointerArray(structFuncArray); + Assert.Equal(length, s_takeStructCallCount); + } + { + var t = new TestTwoParams<int, Struct>(); + t.FunctionPointerArray(intFuncArray, structFuncArray); + Assert.Equal(length * 2, s_takeIntCallCount); + Assert.Equal(length * 2, s_takeStructCallCount); + } + } + + static int s_takeIntCallCount = 0; + private static void TakeInt(int _) => s_takeIntCallCount++; + + static int s_takeStructCallCount = 0; + private static void TakeStruct(Struct _) => s_takeStructCallCount++; +} diff --git a/src/tests/Loader/classloader/generics/Pointers/Pointers.csproj b/src/tests/Loader/classloader/generics/Pointers/Pointers.csproj new file mode 100644 index 00000000000..160aa059d73 --- /dev/null +++ b/src/tests/Loader/classloader/generics/Pointers/Pointers.csproj @@ -0,0 +1,12 @@ +<Project Sdk="Microsoft.NET.Sdk"> + + <PropertyGroup> + <OutputType>Exe</OutputType> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + + <ItemGroup> + <Compile Include="Pointers.cs" /> + </ItemGroup> + +</Project> |