diff options
author | Jeremy Koritzinsky <jekoritz@microsoft.com> | 2022-06-22 23:06:00 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-06-22 23:06:00 +0300 |
commit | f20a046986c37201c9e64320b5a8e37581d75694 (patch) | |
tree | f27bfcbca99e82f6e5fedc2b6bd9ada64d81f600 /src/tests/baseservices | |
parent | 4388cc5bd557010b673fe307c26b4d41ecdbb6f6 (diff) |
Add exception interop test for validating native exception interop on Windows + CoreCLR. (#70110)
Diffstat (limited to 'src/tests/baseservices')
5 files changed, 172 insertions, 0 deletions
diff --git a/src/tests/baseservices/exceptions/exceptioninterop/CMakeLists.txt b/src/tests/baseservices/exceptions/exceptioninterop/CMakeLists.txt new file mode 100644 index 00000000000..a477a57c1cd --- /dev/null +++ b/src/tests/baseservices/exceptions/exceptioninterop/CMakeLists.txt @@ -0,0 +1,4 @@ + +include_directories(${INC_PLATFORM_DIR}) +add_library(ExceptionInteropNative SHARED ExceptionInteropNative.cpp) +target_link_libraries(ExceptionInteropNative PRIVATE platformdefines)
\ No newline at end of file diff --git a/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop.cs b/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop.cs new file mode 100644 index 00000000000..f9f18b91369 --- /dev/null +++ b/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop.cs @@ -0,0 +1,125 @@ +// 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; +using static ExceptionInteropNative; + +internal unsafe static class ExceptionInteropNative +{ + [DllImport(nameof(ExceptionInteropNative))] + public static extern void ThrowException(); + + [DllImport(nameof(ExceptionInteropNative))] + public static extern void NativeFunction(); + + [DllImport(nameof(ExceptionInteropNative))] + public static extern void CallCallback(delegate* unmanaged<void> cb); +} + +public unsafe static class ExceptionInterop +{ + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnMono("Exception interop not supported on Mono.")] + public static void ThrowNativeExceptionAndCatchInFrame() + { + bool caughtException = false; + try + { + ThrowException(); + } + catch + { + caughtException = true; + // Try calling another P/Invoke in the catch block to make sure we have everything set up + // to recover from the exceptional control flow. + NativeFunction(); + } + Assert.True(caughtException); + } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnMono("Exception interop not supported on Mono.")] + public static void ThrowManagedExceptionThroughNativeAndCatchInFrame() + { + bool caughtException = false; + try + { + CallCallback(&ThrowManagedException); + } + catch + { + caughtException = true; + // Try calling another P/Invoke in the catch block to make sure we have everything set up + // to recover from the exceptional control flow. + NativeFunction(); + } + Assert.True(caughtException); + + [UnmanagedCallersOnly] + static void ThrowManagedException() + { + throw new Exception(); + } + } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnMono("Exception interop not supported on Mono.")] + public static void ThrowNativeExceptionAndCatchInFrameWithFilter() + { + bool caughtException = false; + try + { + ThrowException(); + } + catch (Exception) when (Filter()) + { + caughtException = true; + // Try calling another P/Invoke in the catch block to make sure we have everything set up + // to recover from the exceptional control flow. + NativeFunction(); + } + Assert.True(caughtException); + + // Aggresively inline to make sure the call to NativeFunction is in the filter clause + [MethodImpl(MethodImplOptions.AggressiveInlining)] + bool Filter() + { + NativeFunction(); + return true; + } + } + + [Fact] + [PlatformSpecific(TestPlatforms.Windows)] + [SkipOnMono("Exception interop not supported on Mono.")] + public static void ThrowNativeExceptionAndCatchInFrameWithFinally() + { + bool caughtException = false; + try + { + try + { + ThrowException(); + } + finally + { + // Try calling another P/Invoke in the finally block before the catch + // to make sure we have everything set up + // to recover from the exceptional control flow. + NativeFunction(); + } + } + catch + { + caughtException = true; + } + + Assert.True(caughtException); + } +}
\ No newline at end of file diff --git a/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop.csproj b/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop.csproj new file mode 100644 index 00000000000..d553892a3b2 --- /dev/null +++ b/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop.csproj @@ -0,0 +1,10 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + <ItemGroup> + <CMakeProjectReference Include="CMakeLists.txt" /> + <Compile Include="ExceptionInterop.cs" /> + </ItemGroup> + </Project> +
\ No newline at end of file diff --git a/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInteropNative.cpp b/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInteropNative.cpp new file mode 100644 index 00000000000..2d141792dd7 --- /dev/null +++ b/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInteropNative.cpp @@ -0,0 +1,19 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include <exception> +#include <platformdefines.h> + +extern "C" DLL_EXPORT void STDMETHODCALLTYPE ThrowException() +{ + throw std::exception{}; +} + +extern "C" DLL_EXPORT void STDMETHODCALLTYPE NativeFunction() +{ +} + +extern "C" DLL_EXPORT void STDMETHODCALLTYPE CallCallback(void (*cb)()) +{ + cb(); +}
\ No newline at end of file diff --git a/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop_ro.csproj b/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop_ro.csproj new file mode 100644 index 00000000000..99c7f983705 --- /dev/null +++ b/src/tests/baseservices/exceptions/exceptioninterop/ExceptionInterop_ro.csproj @@ -0,0 +1,14 @@ +<Project Sdk="Microsoft.NET.Sdk"> + <PropertyGroup> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + </PropertyGroup> + <PropertyGroup> + <DebugType>None</DebugType> + <Optimize>True</Optimize> + </PropertyGroup> + <ItemGroup> + <CMakeProjectReference Include="CMakeLists.txt" /> + <Compile Include="ExceptionInterop.cs" /> + </ItemGroup> + </Project> +
\ No newline at end of file |