From a6ae2fa2a32bb314a7e6129e5c7235c0cd96ae56 Mon Sep 17 00:00:00 2001 From: Ahson Khan Date: Fri, 30 Mar 2018 21:24:49 -0700 Subject: [PATCH] Add tests for calling Span APIs via reflection to verify graceful failures. (dotnet/corefx#28674) * Add tests for calling Span APIs via reflection to verify graceful failures. * Add Span reflection tests to verify graceful failures * Address PR feedback (test cleanup and rename) * Fix up some test names * Minor tweak: Reorder the tests * Exclude running the reflection tests for portable span (netfx) * Remove unused constant from csproj Commit migrated from https://github.com/dotnet/corefx/commit/a7b59b08f3f92038011ff967efcc250fc305c925 --- .../System.Memory/tests/Span/Reflection.cs | 186 ++++++++++++++++++ .../tests/System.Memory.Tests.csproj | 1 + 2 files changed, 187 insertions(+) create mode 100644 src/libraries/System.Memory/tests/Span/Reflection.cs diff --git a/src/libraries/System.Memory/tests/Span/Reflection.cs b/src/libraries/System.Memory/tests/Span/Reflection.cs new file mode 100644 index 00000000000000..652e0f161e2d0f --- /dev/null +++ b/src/libraries/System.Memory/tests/Span/Reflection.cs @@ -0,0 +1,186 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using Xunit; +using System.Buffers; +using System.Buffers.Binary; +using System.Reflection; +using System.Runtime.InteropServices; +using System.MemoryTests; + +namespace System.SpanTests +{ + public static partial class SpanTests + { + // Calling Span APIs via Reflection is not supported yet. + // These tests check that using reflection results in graceful failures. See https://github.com/dotnet/coreclr/issues/17296 + // These tests are only relevant for fast span. + + [Fact] + public static void MemoryExtensions_StaticReturningReadOnlySpan() + { + Type type = typeof(MemoryExtensions); + + MethodInfo method = type.GetMethod(nameof(MemoryExtensions.AsSpan), new Type[] { typeof(string) }); + Assert.Throws(() => method.Invoke(null, new object[] { "Hello" })); + + method = type.GetMethod(nameof(MemoryExtensions.AsSpan), new Type[] { typeof(string), typeof(int), typeof(int) }); + Assert.Throws(() => method.Invoke(null, new object[] { "Hello", 1, 1 })); + } + + [Fact] + public static void MemoryExtensions_StaticWithSpanArguments() + { + Type type = typeof(MemoryExtensions); + + MethodInfo method = type.GetMethod(nameof(MemoryExtensions.CompareTo)); + + int result = (int)method.Invoke(null, new object[] { default, default, StringComparison.Ordinal }); + Assert.Equal(0, result); + } + + [Fact] + public static void BinaryPrimitives_StaticWithSpanArgument() + { + Type type = typeof(BinaryPrimitives); + + MethodInfo method = type.GetMethod(nameof(BinaryPrimitives.ReadInt16LittleEndian)); + Assert.Throws(() => method.Invoke(null, new object[] { default })); + + method = type.GetMethod(nameof(BinaryPrimitives.TryReadInt16LittleEndian)); + bool result = (bool)method.Invoke(null, new object[] { default, null }); + Assert.False(result); + } + + [Fact] + public static void MemoryMarshal_GenericStaticReturningSpan() + { + Type type = typeof(MemoryMarshal); + + int value = 0; + ref int refInt = ref value; + + MethodInfo method = type.GetMethod(nameof(MemoryMarshal.CreateSpan)).MakeGenericMethod((refInt.GetType())); + Assert.Throws(() => method.Invoke(null, new object[] { null, 0 })); + } + + [Fact] + public static void Span_Constructor() + { + Type type = typeof(Span); + + ConstructorInfo ctor = type.GetConstructor(new Type[] { typeof(int[]) }); + Assert.Throws(() => ctor.Invoke(new object[] { new int[10] })); + + ctor = type.GetConstructor(new Type[] { typeof(int[]), typeof(int), typeof(int) }); + Assert.Throws(() => ctor.Invoke(new object[] { new int[10], 1, 1 })); + + ctor = type.GetConstructor(new Type[] { typeof(void*), typeof(int) }); + Assert.Throws(() => ctor.Invoke(new object[] { null, 1 })); + } + + [Fact] + public static void Span_Property() + { + Type type = typeof(Span); + + PropertyInfo property = type.GetProperty(nameof(Span.Empty)); + Assert.Throws(() => property.GetValue(default)); + } + + [Fact] + public static void Span_StaticOperator() + { + Type type = typeof(Span); + + MethodInfo method = type.GetMethod("op_Equality"); + Assert.Throws(() => method.Invoke(null, new object[] { default, default })); + + method = type.GetMethod("op_Inequality"); + Assert.Throws(() => method.Invoke(null, new object[] { default, default })); + } + + [Fact] + public static void Span_InstanceMethod() + { + Type type = typeof(Span); + + MethodInfo method = type.GetMethod(nameof(Span.CopyTo), new Type[] { typeof(Span) }); + Assert.Throws(() => method.Invoke(default, new object[] { default })); + } + + [Fact] + public static void ReadOnlySpan_Constructor() + { + Type type = typeof(ReadOnlySpan); + + ConstructorInfo ctor = type.GetConstructor(new Type[] { typeof(int[]) }); + Assert.Throws(() => ctor.Invoke(new object[] { new int[10] })); + + ctor = type.GetConstructor(new Type[] { typeof(int[]), typeof(int), typeof(int) }); + Assert.Throws(() => ctor.Invoke(new object[] { new int[10], 1, 1 })); + + ctor = type.GetConstructor(new Type[] { typeof(void*), typeof(int) }); + Assert.Throws(() => ctor.Invoke(new object[] { null, 1 })); + } + + [Fact] + public static void ReadOnlySpan_Property() + { + Type type = typeof(ReadOnlySpan); + + PropertyInfo property = type.GetProperty(nameof(ReadOnlySpan.Empty)); + Assert.Throws(() => property.GetValue(default)); + } + + [Fact] + public static void ReadOnlySpan_Operator() + { + Type type = typeof(ReadOnlySpan); + + MethodInfo method = type.GetMethod("op_Equality"); + Assert.Throws(() => method.Invoke(null, new object[] { default, default })); + + method = type.GetMethod("op_Inequality"); + Assert.Throws(() => method.Invoke(null, new object[] { default, default })); + } + + [Fact] + public static void ReadOnlySpan_InstanceMethod() + { + Type type = typeof(ReadOnlySpan); + + MethodInfo method = type.GetMethod(nameof(ReadOnlySpan.CopyTo), new Type[] { typeof(Span) }); + Assert.Throws(() => method.Invoke(default, new object[] { default })); + } + + [Fact] + public static void Memory_PropertyReturningSpan() + { + Type type = typeof(Memory); + + PropertyInfo property = type.GetProperty(nameof(Memory.Span)); + Assert.Throws(() => property.GetValue(null)); + } + + [Fact] + public static void ReadOnlyMemory_PropertyReturningReadOnlySpan() + { + Type type = typeof(ReadOnlyMemory); + + PropertyInfo property = type.GetProperty(nameof(ReadOnlyMemory.Span)); + Assert.Throws(() => property.GetValue(null)); + } + + [Fact] + public static void MemoryManager_MethodReturningSpan() + { + Type type = typeof(MemoryManager); + + MemoryManager manager = new CustomMemoryForTest(new int[10]); + MethodInfo method = type.GetMethod(nameof(MemoryManager.GetSpan), BindingFlags.Public | BindingFlags.Instance); + Assert.Throws(() => method.Invoke(manager, null)); + } + } +} diff --git a/src/libraries/System.Memory/tests/System.Memory.Tests.csproj b/src/libraries/System.Memory/tests/System.Memory.Tests.csproj index 0236ab3c259b7f..19c6e3377b74e3 100644 --- a/src/libraries/System.Memory/tests/System.Memory.Tests.csproj +++ b/src/libraries/System.Memory/tests/System.Memory.Tests.csproj @@ -16,6 +16,7 @@ +