//
using System;
+using System.Text;
using System.Runtime.InteropServices;
+using System.Threading;
public class Tests {
return 0;
}
+ public static int delegate_test_struct_in (int a, [In] ref SimpleStruct ss, int b)
+ {
+ if (a == 1 && b == 2 && ss.a && !ss.b && ss.c && ss.d == "TEST2") {
+ ss.a = true;
+ ss.b = true;
+ ss.c = true;
+ ss.d = "TEST3";
+ return 0;
+ }
+
+ return 1;
+ }
+
public static SimpleClass delegate_test_class (SimpleClass ss)
{
if (ss == null)
return s == "ABC" ? 0 : 1;
}
+ public static int delegate_test_string_builder_marshalling (StringBuilder s)
+ {
+ if (s == null)
+ return 2;
+ else
+ return s.ToString () == "ABC" ? 0 : 1;
+ }
+
[DllImport ("libtest", EntryPoint="mono_test_ref_vtype")]
public static extern int mono_test_ref_vtype (int a, ref SimpleStruct ss, int b, TestDelegate d);
public delegate int OutStructDelegate (int a, out SimpleStruct ss, int b);
+ public delegate int InStructDelegate (int a, [In] ref SimpleStruct ss, int b);
+
[DllImport ("libtest", EntryPoint="mono_test_marshal_out_struct")]
public static extern int mono_test_marshal_out_struct (int a, out SimpleStruct ss, int b, OutStructDelegate d);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_in_struct")]
+ public static extern int mono_test_marshal_in_struct (int a, ref SimpleStruct ss, int b, InStructDelegate d);
[DllImport ("libtest", EntryPoint="mono_test_marshal_delegate2")]
public static extern int mono_test_marshal_delegate2 (SimpleDelegate2 d);
[DllImport ("libtest", EntryPoint="mono_test_marshal_delegate10")]
public static extern int mono_test_marshal_delegate10 (SimpleDelegate9 d);
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate8")]
+ public static extern int mono_test_marshal_delegate11 (SimpleDelegate11 d, string s);
+
[DllImport ("libtest", EntryPoint="mono_test_marshal_primitive_byref_delegate")]
public static extern int mono_test_marshal_primitive_byref_delegate (PrimitiveByrefDelegate d);
[DllImport ("libtest", EntryPoint="mono_test_marshal_return_delegate_delegate")]
public static extern int mono_test_marshal_return_delegate_delegate (ReturnDelegateDelegate d);
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_delegate_ref_delegate")]
+ public static extern int mono_test_marshal_delegate_ref_delegate (DelegateByrefDelegate del);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_virtual_delegate")]
+ public static extern int mono_test_marshal_virtual_delegate (VirtualDelegate del);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_icall_delegate")]
+ public static extern int mono_test_marshal_icall_delegate (IcallDelegate del);
+
+ public delegate string IcallDelegate (IntPtr p);
+
public delegate int TestDelegate (int a, ref SimpleStruct ss, int b);
public delegate SimpleStruct SimpleDelegate2 (SimpleStruct ss);
public delegate int SimpleDelegate9 (return_int_delegate del);
+ public delegate int SimpleDelegate11 (StringBuilder s1);
+
public delegate int PrimitiveByrefDelegate (ref int i);
public delegate return_int_delegate ReturnDelegateDelegate ();
+ public delegate int DelegateByrefDelegate (ref return_int_delegate del);
+
+ public delegate int VirtualDelegate (int i);
+
public static int Main () {
return TestDriver.RunTests (typeof (Tests));
}
return mono_test_marshal_out_struct (1, out ss, 2, d);
}
+ /* Test structures as in arguments of delegates */
+ public static int test_0_marshal_in_struct_delegate () {
+ SimpleStruct ss = new SimpleStruct () { a = true, b = false, c = true, d = "TEST2" };
+ InStructDelegate d = new InStructDelegate (delegate_test_struct_in);
+
+ return mono_test_marshal_in_struct (1, ref ss, 2, d);
+ }
+
/* Test classes as arguments and return values of delegates */
public static int test_0_marshal_class_delegate () {
SimpleDelegate4 d = new SimpleDelegate4 (delegate_test_class);
return mono_test_marshal_delegate8 (d, "ABC");
}
+ /* Test string builder marshalling with delegates */
+ public static int test_0_marshal_string_builder_delegate () {
+ SimpleDelegate11 d = new SimpleDelegate11 (delegate_test_string_builder_marshalling);
+
+ if (mono_test_marshal_delegate11 (d, null) != 2)
+ return 2;
+
+ return mono_test_marshal_delegate11 (d, "ABC");
+ }
+
/* Test that the delegate wrapper correctly catches null byref arguments */
public static int test_0_marshal_byref_class_delegate_null () {
SimpleDelegate5 d = new SimpleDelegate5 (delegate_test_class_byref);
return mono_test_marshal_return_delegate_delegate (new ReturnDelegateDelegate (return_delegate));
}
+ public static int return_plus_1 (int i) {
+ return i + 1;
+ }
+
+ public static int ref_delegate_delegate (ref return_int_delegate del) {
+ del = return_plus_1;
+ return 0;
+ }
+
+ public static int test_55_marshal_delegate_ref_delegate () {
+ var del = new DelegateByrefDelegate (ref_delegate_delegate);
+ return mono_test_marshal_delegate_ref_delegate (del);
+ }
+
/* Passing and returning strings */
public delegate String ReturnStringDelegate (String s);
return mono_test_marshal_array_delegate1 (null, 0, new ArrayDelegate1 (array_delegate2));
}
+ public delegate int ArrayDelegateBlittable (int i, string j,
+ [In, MarshalAs(UnmanagedType.LPArray,
+ ArraySubType=UnmanagedType.LPStr, SizeParamIndex=0)] int[] arr);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
+ public static extern int mono_test_marshal_array_delegate1 (string[] arr, int len, ArrayDelegateBlittable d);
+
+ public static int array_delegate_null_blittable (int i, string j, int[] arr) {
+ return (arr == null) ? 0 : 1;
+ }
+
+ public static int test_0_marshal_array_delegate_null_blittable () {
+ return mono_test_marshal_array_delegate1 (null, 0, new ArrayDelegateBlittable (array_delegate_null_blittable));
+ }
+
public delegate int ArrayDelegate3 (int i,
string j,
[In, MarshalAs(UnmanagedType.LPArray,
}
}
+ public delegate int ArrayDelegate4_2 (int i,
+ string j,
+ string[] arr);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
+ public static extern int mono_test_marshal_array_delegate4_2 (string[] arr, int len, ArrayDelegate4_2 d);
+
+ public static int array_delegate4_2 (int i, string j, string[] arr) {
+ return (arr == null) ? 0 : 1;
+ }
+
+ public static int test_0_marshal_array_delegate_no_marshal_directive () {
+ try {
+ mono_test_marshal_array_delegate4_2 (null, 0, new ArrayDelegate4_2 (array_delegate4_2));
+ return 1;
+ }
+ catch (MarshalDirectiveException) {
+ return 0;
+ }
+ }
+
+ public delegate int ArrayDelegate4_3 (int i,
+ string j,
+ string[] arr);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate")]
+ public static extern int mono_test_marshal_array_delegate4_3 (string[] arr, int len, ArrayDelegate4_3 d);
+
+ public int array_delegate4_3 (int i, string j, string[] arr) {
+ return (arr == null) ? 0 : 1;
+ }
+
+ public static int test_0_marshal_array_delegate_no_marshal_directive_instance () {
+ try {
+ Tests t = new Tests ();
+ mono_test_marshal_array_delegate4_3 (null, 0, new ArrayDelegate4_3 (t.array_delegate4_3));
+ return 1;
+ }
+ catch (MarshalDirectiveException) {
+ return 0;
+ }
+ }
+
public delegate int ArrayDelegate5 (int i,
string j,
[In, MarshalAs(UnmanagedType.LPArray,
return mono_test_marshal_array_delegate8 (arr, 2, new ArrayDelegate8 (array_delegate8));
}
+ /* Array with size param of type long */
+
+ public delegate int ArrayDelegate8_2 (long i,
+ string j,
+ [In, MarshalAs(UnmanagedType.LPArray,
+ ArraySubType=UnmanagedType.LPStr, SizeParamIndex=0)] string[] arr);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_array_delegate_long")]
+ public static extern int mono_test_marshal_array_delegate8_2 (string[] arr, long len, ArrayDelegate8_2 d);
+
+ public static int array_delegate8_2 (long i, string j, string[] arr) {
+ if (arr.Length != 2)
+ return 1;
+ if ((arr [0] != "ABC") || (arr [1] != "DEF"))
+ return 2;
+ return 0;
+ }
+
+ public static int test_0_marshal_array_delegate_long_param () {
+ string[] arr = new string [] { "ABC", "DEF" };
+ return mono_test_marshal_array_delegate8_2 (arr, arr.Length, new ArrayDelegate8_2 (array_delegate8_2));
+ }
+
+
/*
* [Out] blittable arrays
*/
return mono_test_marshal_inout_byval_class_delegate (new InOutByvalClassDelegate (delegate_test_byval_class_inout));
}
+ /*
+ * Returning unicode strings
+ */
+ [return: MarshalAs(UnmanagedType.LPWStr)]
+ public delegate string ReturnUnicodeStringDelegate([MarshalAs(UnmanagedType.LPWStr)] string message);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_return_unicode_string_delegate")]
+ public static extern int mono_test_marshal_return_unicode_string_delegate (ReturnUnicodeStringDelegate d);
+
+ public static String return_unicode_string_delegate (string message) {
+ return message;
+ }
+
+ public static int test_0_marshal_return_unicode_string_delegate () {
+ return mono_test_marshal_return_unicode_string_delegate (new ReturnUnicodeStringDelegate (return_unicode_string_delegate));
+ }
+
/*
* Returning string arrays
*/
return mono_test_marshal_return_string_array_delegate (new ReturnArrayDelegate (return_array_delegate_null));
}
+ /*
+ * Byref string marshalling
+ */
+ public delegate int ByrefStringDelegate (ref string s);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_byref_string_delegate")]
+ public static extern int mono_test_marshal_byref_string_delegate (ByrefStringDelegate d);
+
+ public static int byref_string_delegate (ref string s) {
+ if (s != "ABC")
+ return 1;
+
+ s = "DEF";
+
+ return 0;
+ }
+
+ public static int test_0_marshal_byref_string_delegate () {
+ return mono_test_marshal_byref_string_delegate (new ByrefStringDelegate (byref_string_delegate));
+ }
+
+ /*
+ * Thread attach
+ */
+
+ public delegate int SimpleDelegate (int i);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_thread_attach")]
+ public static extern int mono_test_marshal_thread_attach (SimpleDelegate d);
+
+ public static int test_43_thread_attach () {
+ int res = mono_test_marshal_thread_attach (delegate (int i) {
+ if (!Thread.CurrentThread.IsBackground)
+ return 0;
+ return i + 1;
+ });
+ return res;
+ }
+
+ class Worker {
+ volatile bool stop = false;
+ public void Stop () {
+ stop = true;
+ }
+
+ public void Work () {
+ while (!stop) {
+ for (int i = 0; i < 100; i++) {
+ var a = new double[80000];
+ Thread.Sleep (0);
+ }
+ GC.Collect ();
+ }
+ }
+ }
+
+ public static int test_43_thread_attach_detach_contested () {
+ // Test plan: we want to create a race between the GC
+ // and native threads detaching. When a native thread
+ // calls a managed delegate, it's attached to the
+ // runtime by the wrapper. It is detached when the
+ // thread is destroyed and the TLS key destructor for
+ // MonoThreadInfo runs. That destructor wants to take
+ // the GC lock. So we create a lot of native threads
+ // while at the same time running a worker that
+ // allocates garbage and invokes the collector.
+ var w = new Worker ();
+ Thread t = new Thread(new ThreadStart (w.Work));
+ t.Start ();
+
+ for (int count = 0; count < 500; count++) {
+ int res = mono_test_marshal_thread_attach (delegate (int i) {
+ Thread.Sleep (0);
+ return i + 1;
+ });
+ }
+ Thread.Sleep (1000);
+ w.Stop ();
+ t.Join ();
+ return 43;
+
+ }
+ /*
+ * Appdomain save/restore
+ */
+ static Func<int> callback;
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_set_callback")]
+ public static extern int mono_test_marshal_set_callback (Func<int> a);
+
+ [DllImport ("libtest", EntryPoint="mono_test_marshal_call_callback")]
+ public static extern int mono_test_marshal_call_callback ();
+
+ public static int test_0_appdomain_switch () {
+ // FIXME: The appdomain unload hangs
+ //return 0;
+ AppDomain ad = AppDomain.CreateDomain ("foo");
+ var c = (CallbackClass)ad.CreateInstanceAndUnwrap (
+ typeof (CallbackClass).Assembly.FullName, "Tests/CallbackClass");
+ c.SetCallback ();
+ int domain_id = AppDomain.CurrentDomain.Id;
+ int new_id = mono_test_marshal_call_callback ();
+ int res = 0;
+ if (new_id == domain_id)
+ res = 1;
+ if (AppDomain.CurrentDomain.Id != domain_id)
+ res = 2;
+ AppDomain.Unload (ad);
+ return res;
+ }
+
+ static int domain_callback () {
+ return AppDomain.CurrentDomain.Id;
+ }
+
+ class CallbackClass : MarshalByRefObject {
+ public int SetCallback () {
+ mono_test_marshal_set_callback (domain_callback);
+ return 0;
+ }
+ }
+
+ class Base {
+ public VirtualDelegate get_del () {
+ return delegate_test;
+ }
+
+ public virtual int delegate_test (int i) {
+ return i;
+ }
+ }
+
+ class Derived : Base {
+ public override int delegate_test (int i) {
+ return i + 1;
+ }
+ }
+
+ public static int test_43_virtual () {
+ Base b = new Derived ();
+
+ return mono_test_marshal_virtual_delegate (b.get_del ());
+ }
+
+ public static int test_0_icall_delegate () {
+ var m = typeof (Marshal).GetMethod ("PtrToStringAnsi", new Type[] { typeof (IntPtr) });
+
+ return mono_test_marshal_icall_delegate ((IcallDelegate)Delegate.CreateDelegate (typeof (IcallDelegate), m));
+ }
}