Add better coverage for Marshal.GetDelegateForFunctionPointer (#15339)
authorVitek Karas <vitek-karas@users.noreply.github.com>
Sat, 21 Apr 2018 03:22:13 +0000 (20:22 -0700)
committerJan Kotas <jkotas@microsoft.com>
Sat, 21 Apr 2018 03:22:13 +0000 (20:22 -0700)
Also fixes the test Main to correctly collect result codes from all 3 subtests.

tests/src/Interop/MarshalAPI/FunctionPointer/GetDelForFcnPtr_Negative_Catchable.cs
tests/src/Interop/MarshalAPI/FunctionPointer/GetFcnPtrForDel_Negative_Catchable.cs

index 9fddac1..f649c61 100644 (file)
@@ -54,7 +54,7 @@ public partial class FunctionPtr
         }
         catch (ArgumentException e)
         {
-             Console.WriteLine("Fail - passing a null type received the right exception type, wrong message, message was '{0}'", e.Message);
+             Console.WriteLine("Pass - passing a null type received the right exception type, wrong message, message was '{0}'", e.Message);
         }
         catch (Exception e)
         {
@@ -71,7 +71,7 @@ public partial class FunctionPtr
         }
         catch (ArgumentException e)
         {
-            Console.WriteLine("Faile - threw the right exception passing a non-delegate type, but a wrong message, message was '{0}'", e.Message);
+            Console.WriteLine("Pass - threw the right exception passing a non-delegate type, but a wrong message, message was '{0}'", e.Message);
         }
         catch (Exception e)
         {
@@ -80,6 +80,81 @@ public partial class FunctionPtr
             Console.WriteLine(e);
         }
 
+        // Delegate -> FcnPtr -> Delegate
+        try
+        {
+            VoidDelegate del = (VoidDelegate)Marshal.GetDelegateForFunctionPointer(fcnptr, typeof(VoidDelegate));
+            if (del.Target != md.Target)
+            {
+                retVal = 0;
+                Console.WriteLine("Failure - the Target of the funcptr->delegate should be equal to the original method.");
+                Console.WriteLine(del.Target);
+            }
+
+            if (del.Method != md.Method)
+            {
+                retVal = 0;
+                Console.WriteLine("Failure - The Method of the funcptr->delegate should be equal to the MethodInfo of the original method.");
+                Console.WriteLine(del.Method);
+            }
+
+            // Try to call it
+            del();
+
+            Console.WriteLine("Pass - got a delegate for the function pointer.");
+        }
+        catch (Exception e)
+        {
+            retVal = 0;
+            Console.WriteLine("Failure - received exception while converting funcptr to delegate.");
+            Console.WriteLine(e);
+        }
+
+        // Native FcnPtr -> Delegate
+        IntPtr pNativeMemory = IntPtr.Zero;
+        try
+        {
+            // Allocate a piece of native memory which in no way resembles valid function entry point.
+            // CLR will read the first couple of bytes and try to match it to known patterns. We need something
+            // which doesn't look like a reverse pinvoke thunk.
+            pNativeMemory = Marshal.AllocCoTaskMem(64);
+            Marshal.WriteInt32(pNativeMemory, 0);
+            Marshal.WriteInt32(pNativeMemory + 4, 0);
+
+            VoidDelegate del = (VoidDelegate)Marshal.GetDelegateForFunctionPointer(pNativeMemory, typeof(VoidDelegate));
+            if (del.Target != null)
+            {
+                retVal = 0;
+                Console.WriteLine("Failure - the Target of the funcptr->delegate should be null since we provided native funcptr.");
+                Console.WriteLine(del.Target);
+            }
+
+            if (del.Method.Name != "Invoke")
+            {
+                retVal = 0;
+                Console.WriteLine("Failure - The Method of the native funcptr->delegate should be the Invoke method.");
+                Console.WriteLine(del.Method);
+            }
+
+            // Don't try to call it - it's a random address.
+
+            Console.WriteLine("Pass - got a delegate for the function pointer.");
+        }
+        catch (Exception e)
+        {
+            retVal = 0;
+            Console.WriteLine("Failure - received exception while converting funcptr to delegate.");
+            Console.WriteLine(e);
+        }
+        finally
+        {
+            if (pNativeMemory != IntPtr.Zero)
+            {
+                Marshal.FreeCoTaskMem(pNativeMemory);
+            }
+        }
+
+
         Console.WriteLine(retVal == 100 ? "Done - PASSED" : "Done - FAILED");
         return retVal;
     }
@@ -89,4 +164,4 @@ public partial class FunctionPtr
         Console.WriteLine("Simple method to get a delegate for");
     }
 }
-#pragma warning restore 618
\ No newline at end of file
+#pragma warning restore 618
index e4b5c2d..01fc898 100644 (file)
@@ -13,16 +13,16 @@ public partial class FunctionPtr
 
     public static int Main()
     {
-        RunGetFncSecTest();
+        int retVal1 = RunGetFncSecTest();
 
-        int retVal = 100;
+        int retVal2 = 100;
         VoidDelegate md = new VoidDelegate(FunctionPtr.Method);
         Console.WriteLine("\r\nTesting Marshal.GetFunctionPointerForDelegate().");
 
         try
         {
             Marshal.GetFunctionPointerForDelegate<Object>(null);
-            retVal = 0;
+            retVal2 = 0;
             Console.WriteLine("Failure - did not receive an exception while passing null as the delegate");
         }
         catch (ArgumentNullException e)
@@ -31,13 +31,19 @@ public partial class FunctionPtr
         }
         catch (Exception e)
         {
-            retVal = 0;
+            retVal2 = 0;
             Console.WriteLine("Failure - receive an incorrect exception while passing null as the delegate");
             Console.WriteLine(e);
         }
-        RunGetDelForFcnPtrTest();
-        return retVal;
+
+        int retVal3 = RunGetDelForFcnPtrTest();
+
+        if (retVal1 != 100)
+            return retVal1;
+        if (retVal2 != 100)
+            return retVal2;
+        return retVal3;
     }
   
 }
-#pragma warning restore 618
\ No newline at end of file
+#pragma warning restore 618