Merge pull request #5428 from kumpera/wasm-support-p2
[mono.git] / mono / tests / marshal9.cs
index ad8479df9ff1c2084ccd843846d0bc15a679a493..f19059435939a60dfc0eafec50e2c05d152b8594 100644 (file)
@@ -5,6 +5,11 @@
 using System;
 using System.Runtime.InteropServices;
 
+[AttributeUsage (AttributeTargets.Method)]
+sealed class MonoPInvokeCallbackAttribute : Attribute {
+       public MonoPInvokeCallbackAttribute (Type t) {}
+}
+
 public class Marshal1 : ICustomMarshaler
 {
        int param;
@@ -13,6 +18,10 @@ public class Marshal1 : ICustomMarshaler
 
        public static int cleanup_native_count = 0;
 
+       public static int native_to_managed_count = 0;
+
+       public static object native_to_managed_result = null;
+
        public Marshal1 (int param) {
                this.param = param;
        }
@@ -39,7 +48,7 @@ public class Marshal1 : ICustomMarshaler
        }
 
        // I really do not understand the purpose of this method
-       // or went it would be called. In fact, Rotor never seems
+       // or when it would be called. In fact, Rotor never seems
        // to call it.
        public int GetNativeDataSize ()
        {
@@ -64,7 +73,9 @@ public class Marshal1 : ICustomMarshaler
        public object MarshalNativeToManaged (IntPtr pNativeData)
        {
                //Console.WriteLine ("ToManaged: " + pNativeData);
-               return param + Marshal.ReadInt32 (new IntPtr (pNativeData.ToInt64 () + 4));
+               native_to_managed_count ++;
+               native_to_managed_result = param + Marshal.ReadInt32 (new IntPtr (pNativeData.ToInt64 () + 4));
+               return native_to_managed_result;
        }
 }
 
@@ -72,6 +83,7 @@ public class Tests
 {
        public static int Main (string[] args) {
                return TestDriver.RunTests (typeof (Tests));
+       return 0;
        }
 
        [DllImport ("libtest")]
@@ -84,6 +96,7 @@ public class Tests
 
                Marshal1.cleanup_managed_count = 0;
                Marshal1.cleanup_native_count = 0;
+               Marshal1.native_to_managed_count = 0;
 
                int res = (int)mono_test_marshal_pass_return_custom (5, 10, 5);
 
@@ -91,6 +104,8 @@ public class Tests
                        return 1;
                if (Marshal1.cleanup_native_count != 2)
                        return 2;
+               if (Marshal1.native_to_managed_count != 1)
+                       return 3;
 
                return res == 15 ? 0 : 3;
        }
@@ -119,6 +134,54 @@ public class Tests
                return 0;
        }
 
+       [DllImport ("libtest")]
+       private static extern int mono_test_marshal_pass_inout_custom (int i,
+                                                                                                                       [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal1), MarshalCookie = "5"), In, Out] object number, int j);
+
+       public static int test_0_pass_inout () {
+               Marshal1.cleanup_managed_count = 0;
+               Marshal1.cleanup_native_count = 0;
+               Marshal1.native_to_managed_result = null;
+
+               int res = mono_test_marshal_pass_inout_custom (5, 5, 5);
+
+               // The changes made by the [Out] custom marshaller are not visible to the caller
+               if ((int)Marshal1.native_to_managed_result != 20)
+                       return 1;
+
+               if (Marshal1.cleanup_managed_count != 0)
+                       return 2;
+               if (Marshal1.cleanup_native_count != 1)
+                       return 3;
+
+               return 0;
+       }
+
+       [DllImport ("libtest")]
+       private static extern int mono_test_marshal_pass_out_byval_custom (int i,
+                                                                                                                       [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal1), MarshalCookie = "5"), Out] object number, int j);
+
+       public static int test_0_pass_out_byval () {
+               Marshal1.cleanup_managed_count = 0;
+               Marshal1.cleanup_native_count = 0;
+               Marshal1.native_to_managed_result = null;
+
+               // MS.NET passes NULL and does no marshalling in this case
+               int res = mono_test_marshal_pass_out_byval_custom (5, 5, 5);
+
+               if (res != 0)
+                       return 1;
+
+               if (Marshal1.native_to_managed_result != null)
+                       return 2;
+
+               if (Marshal1.cleanup_managed_count != 0)
+                       return 3;
+               if (Marshal1.cleanup_native_count != 0)
+                       return 4;
+
+               return 0;
+       }
 
        [DllImport ("libtest")]
        private static extern int mono_test_marshal_pass_byref_custom (int i,  
@@ -174,10 +237,12 @@ public class Tests
        [DllImport ("libtest")]
        private static extern int mono_test_marshal_pass_return_custom_null_in_delegate (pass_return_int_delegate del);
 
+       [MonoPInvokeCallback (typeof (pass_return_int_delegate))]
        private static object pass_return_int (object i) {
                return (int)i;
        }
 
+       [MonoPInvokeCallback (typeof (pass_return_int_delegate))]
        private static object pass_return_null (object i) {
                return (i == null) ? null : new Object ();
        }
@@ -317,4 +382,67 @@ public class Tests
                return 1;
        }
 
+       public class Marshal6 : ICustomMarshaler {
+               public static int managed_to_native_count = 0;
+               public static int native_to_managed_count = 0;
+
+               public static ICustomMarshaler GetInstance (string s) 
+               {
+                       return new Marshal6 ();
+               }
+
+               public void CleanUpManagedData (object managedObj)
+               {
+               }
+
+               public void CleanUpNativeData (IntPtr pNativeData)
+               {
+               }
+
+               public int GetNativeDataSize ()
+               {
+                       return 4;
+               }
+
+               public IntPtr MarshalManagedToNative (object managedObj)
+               {
+                       managed_to_native_count++;
+                       return IntPtr.Zero;
+               }
+
+               public object MarshalNativeToManaged (IntPtr pNativeData)
+               {
+                       native_to_managed_count++;
+                       return null;
+               }
+       }
+
+       public delegate void custom_out_param_delegate ([MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal6), MarshalCookie = "5")] out object o);
+
+       [DllImport ("libtest")]
+       private static extern int mono_test_marshal_custom_out_param_delegate (custom_out_param_delegate del);
+
+       // ICustomMarshaler.MarshalNativeToManaged should not be called when the 
+       // parameter is marked as an out.
+       public static int test_0_native_to_managed_custom_parameter () 
+       {
+               Marshal6.managed_to_native_count = 0;
+               Marshal6.native_to_managed_count = 0;
+
+               int res = mono_test_marshal_custom_out_param_delegate (new custom_out_param_delegate (custom_out_param));
+
+               if (Marshal6.managed_to_native_count != 1)
+                       return 1;
+               if (Marshal6.native_to_managed_count != 0)
+                       return 2;
+
+               return 0;
+       }
+
+       [MonoPInvokeCallback (typeof (custom_out_param_delegate))]
+       private static void custom_out_param (out object i) 
+       {
+               i = new object();       
+       }
+
 }