Added Mono.Tasklets test
[mono.git] / mono / tests / marshal9.cs
1 //
2 // marshal9.cs: tests for custom marshalling
3 //
4
5 using System;
6 using System.Runtime.InteropServices;
7
8 public class Marshal1 : ICustomMarshaler
9 {
10         int param;
11
12         public static int cleanup_managed_count = 0;
13
14         public static int cleanup_native_count = 0;
15
16         public static int native_to_managed_count = 0;
17
18         public static object native_to_managed_result = null;
19
20         public Marshal1 (int param) {
21                 this.param = param;
22         }
23
24         public static ICustomMarshaler GetInstance (string s) {
25                 int param = Int32.Parse (s);
26                 return new Marshal1 (param);
27         }
28
29         public void CleanUpManagedData (object managedObj)
30         {
31                 //Console.WriteLine ("CleanUpManagedData called");
32                 cleanup_managed_count ++;
33         }
34
35         public void CleanUpNativeData (IntPtr pNativeData)
36         {
37                 //Console.WriteLine("CleanUpNativeData:" + pNativeData);
38                 /* Might be allocated in libtest.c using g_new0 so dont free it */
39                 int alloc_type = Marshal.ReadInt32 (pNativeData);
40                 if (alloc_type == 1)
41                         Marshal.FreeHGlobal (pNativeData);
42                 cleanup_native_count ++;
43         }
44
45         // I really do not understand the purpose of this method
46         // or when it would be called. In fact, Rotor never seems
47         // to call it.
48         public int GetNativeDataSize ()
49         {
50                 //Console.WriteLine("GetNativeDataSize() called");
51                 return 4;
52         }
53
54         public IntPtr MarshalManagedToNative (object managedObj)
55         {
56                 int number;
57                 IntPtr ptr;
58
59                 number = Convert.ToInt32 (managedObj);
60                 ptr = Marshal.AllocHGlobal (8);
61                 Marshal.WriteInt32 (ptr, 1);  /* Allocated by AllocHGlobal */
62                 Marshal.WriteInt32(new IntPtr (ptr.ToInt64 () + 4), number);
63
64                 //Console.WriteLine ("ToNative: " + ptr);
65                 return ptr;
66         }
67
68         public object MarshalNativeToManaged (IntPtr pNativeData)
69         {
70                 //Console.WriteLine ("ToManaged: " + pNativeData);
71                 native_to_managed_count ++;
72                 native_to_managed_result = param + Marshal.ReadInt32 (new IntPtr (pNativeData.ToInt64 () + 4));
73                 return native_to_managed_result;
74         }
75 }
76
77 public class Tests
78 {
79         public static int Main (string[] args) {
80                 return TestDriver.RunTests (typeof (Tests));
81         return 0;
82         }
83
84         [DllImport ("libtest")]
85         [return : MarshalAs(UnmanagedType.CustomMarshaler,MarshalTypeRef = typeof
86                                                 (Marshal1), MarshalCookie = "5")]
87         private static extern object mono_test_marshal_pass_return_custom (int i,  
88                                                                                                                                         [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal1), MarshalCookie = "5")] object number, int j);
89
90         public static int test_0_pass_return () {
91
92                 Marshal1.cleanup_managed_count = 0;
93                 Marshal1.cleanup_native_count = 0;
94                 Marshal1.native_to_managed_count = 0;
95
96                 int res = (int)mono_test_marshal_pass_return_custom (5, 10, 5);
97
98                 if (Marshal1.cleanup_managed_count != 0)
99                         return 1;
100                 if (Marshal1.cleanup_native_count != 2)
101                         return 2;
102                 if (Marshal1.native_to_managed_count != 1)
103                         return 3;
104
105                 return res == 15 ? 0 : 3;
106         }
107
108         [DllImport ("libtest")]
109         private static extern int mono_test_marshal_pass_out_custom (int i,  
110                                                                                                                         [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal1), MarshalCookie = "5"), Out] out object number, int j);
111
112         public static int test_0_pass_out () {
113
114                 Marshal1.cleanup_managed_count = 0;
115                 Marshal1.cleanup_native_count = 0;
116
117                 object o = 0;
118                 int res = mono_test_marshal_pass_out_custom (5, out o, 5);
119
120                 /* 10 + 5 + 5 + 5 */
121                 if ((int)o != 25)
122                         return 1;
123
124                 if (Marshal1.cleanup_managed_count != 0)
125                         return 2;
126                 if (Marshal1.cleanup_native_count != 1)
127                         return 3;
128
129                 return 0;
130         }
131
132         [DllImport ("libtest")]
133         private static extern int mono_test_marshal_pass_inout_custom (int i,
134                                                                                                                         [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal1), MarshalCookie = "5"), In, Out] object number, int j);
135
136         public static int test_0_pass_inout () {
137                 Marshal1.cleanup_managed_count = 0;
138                 Marshal1.cleanup_native_count = 0;
139                 Marshal1.native_to_managed_result = null;
140
141                 int res = mono_test_marshal_pass_inout_custom (5, 5, 5);
142
143                 // The changes made by the [Out] custom marshaller are not visible to the caller
144                 if ((int)Marshal1.native_to_managed_result != 20)
145                         return 1;
146
147                 if (Marshal1.cleanup_managed_count != 0)
148                         return 2;
149                 if (Marshal1.cleanup_native_count != 1)
150                         return 3;
151
152                 return 0;
153         }
154
155         [DllImport ("libtest")]
156         private static extern int mono_test_marshal_pass_out_byval_custom (int i,
157                                                                                                                         [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal1), MarshalCookie = "5"), Out] object number, int j);
158
159         public static int test_0_pass_out_byval () {
160                 Marshal1.cleanup_managed_count = 0;
161                 Marshal1.cleanup_native_count = 0;
162                 Marshal1.native_to_managed_result = null;
163
164                 // MS.NET passes NULL and does no marshalling in this case
165                 int res = mono_test_marshal_pass_out_byval_custom (5, 5, 5);
166
167                 if (res != 0)
168                         return 1;
169
170                 if (Marshal1.native_to_managed_result != null)
171                         return 2;
172
173                 if (Marshal1.cleanup_managed_count != 0)
174                         return 3;
175                 if (Marshal1.cleanup_native_count != 0)
176                         return 4;
177
178                 return 0;
179         }
180
181         [DllImport ("libtest")]
182         private static extern int mono_test_marshal_pass_byref_custom (int i,  
183                                                                                                                         [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal1), MarshalCookie = "5")] ref object number, int j);
184
185         public static int test_0_pass_ref () {
186
187                 Marshal1.cleanup_managed_count = 0;
188                 Marshal1.cleanup_native_count = 0;
189
190                 object o = 10;
191                 int res = mono_test_marshal_pass_byref_custom (5, ref o, 5);
192
193                 /* 10 + 5 + 5 + 5 */
194                 if ((int)o != 25)
195                         return 1;
196
197                 if (Marshal1.cleanup_managed_count != 0)
198                         return 2;
199                 if (Marshal1.cleanup_native_count != 1)
200                         return 3;
201
202                 return 0;
203         }
204
205         [DllImport ("libtest")]
206         [return : MarshalAs(UnmanagedType.CustomMarshaler,MarshalTypeRef = typeof
207                                                 (Marshal1), MarshalCookie = "5")]
208         private static extern object mono_test_marshal_pass_return_custom_null (int i,  
209                                                                                                                                         [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal1), MarshalCookie = "5")] object number, int j);
210
211         public static int test_0_pass_return_null () {
212
213                 Marshal1.cleanup_managed_count = 0;
214                 Marshal1.cleanup_native_count = 0;
215
216                 object o = mono_test_marshal_pass_return_custom_null (5, null, 5);
217
218                 if (Marshal1.cleanup_managed_count != 0)
219                         return 1;
220                 if (Marshal1.cleanup_native_count != 0)
221                         return 2;
222
223                 return (o == null) ? 0 : 1;
224         }
225
226         [return : MarshalAs(UnmanagedType.CustomMarshaler,MarshalTypeRef = typeof
227 (Marshal1), MarshalCookie = "5")] public delegate object pass_return_int_delegate ([MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal1), MarshalCookie = "5")] object o);
228
229         [DllImport ("libtest")]
230         private static extern int mono_test_marshal_pass_return_custom_in_delegate (pass_return_int_delegate del);
231
232         [DllImport ("libtest")]
233         private static extern int mono_test_marshal_pass_return_custom_null_in_delegate (pass_return_int_delegate del);
234
235         private static object pass_return_int (object i) {
236                 return (int)i;
237         }
238
239         private static object pass_return_null (object i) {
240                 return (i == null) ? null : new Object ();
241         }
242
243         public static int test_0_pass_return_delegate () {
244
245                 Marshal1.cleanup_managed_count = 0;
246                 Marshal1.cleanup_native_count = 0;
247
248                 int res = mono_test_marshal_pass_return_custom_in_delegate (new pass_return_int_delegate (pass_return_int));
249
250                 if (Marshal1.cleanup_managed_count != 2)
251                         return 1;
252                 if (Marshal1.cleanup_native_count != 0)
253                         return 2;
254
255                 return res == 15 ? 0 : 3;
256         }
257
258         public static int test_0_pass_return_null_delegate () {
259
260                 Marshal1.cleanup_managed_count = 0;
261                 Marshal1.cleanup_native_count = 0;
262
263                 int res = mono_test_marshal_pass_return_custom_null_in_delegate (new pass_return_int_delegate (pass_return_null));
264
265                 if (Marshal1.cleanup_managed_count != 0)
266                         return 1;
267                 if (Marshal1.cleanup_native_count != 0)
268                         return 2;
269
270                 return res == 15 ? 0 : 3;
271         }
272
273         /*
274          * Test custom marshaller class not implementing ICustomMarshaler
275          */
276
277         public class Marshal2 {
278         }
279
280         [DllImport ("libtest")]
281         private static extern IntPtr mono_test_marshal_pass_return_custom2 (int i,  
282                                                                                                                                         [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal3), MarshalCookie = "5")] object number, int j);
283
284         public static int test_0_not_icustommarshaller () {
285                 try {
286                         mono_test_marshal_pass_return_custom2 (5, 10, 5);
287                 }
288                 catch (ApplicationException) {
289                         return 0;
290                 }
291                 return 1;
292         }
293
294
295         /*
296          * Test custom marshaller class missing GetInstance method
297          */
298
299         public class Marshal3 : ICustomMarshaler {
300                 public void CleanUpManagedData (object managedObj)
301                 {
302                 }
303
304                 public void CleanUpNativeData (IntPtr pNativeData)
305                 {
306                 }
307
308                 public int GetNativeDataSize ()
309                 {
310                         return 4;
311                 }
312
313                 public IntPtr MarshalManagedToNative (object managedObj)
314                 {
315                         return IntPtr.Zero;
316                 }
317
318                 public object MarshalNativeToManaged (IntPtr pNativeData)
319                 {
320                         return null;
321                 }
322         }
323
324         public class Marshal4 : Marshal3 {
325                 public static object GetInstance (string s) {
326                         return null;
327                 }
328         }
329
330         public class Marshal5 : Marshal3 {
331                 public static ICustomMarshaler GetInstance (object s) {
332                         return null;
333                 }
334         }
335
336         [DllImport ("libtest", EntryPoint = "mono_test_marshal_pass_return_custom2")]
337         private static extern IntPtr mono_test_marshal_pass_return_custom3 (int i,  
338                                                                                                                                         [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal3), MarshalCookie = "5")] object number, int j);
339
340         [DllImport ("libtest", EntryPoint = "mono_test_marshal_pass_return_custom2")]
341         private static extern IntPtr mono_test_marshal_pass_return_custom4 (int i,  
342                                                                                                                                         [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal4), MarshalCookie = "5")] object number, int j);
343
344         [DllImport ("libtest", EntryPoint = "mono_test_marshal_pass_return_custom2")]
345         private static extern IntPtr mono_test_marshal_pass_return_custom5 (int i,  
346                                                                                                                                         [MarshalAs( UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal5), MarshalCookie = "5")] object number, int j);
347
348         public static int test_0_missing_getinstance1 () {
349                 try {
350                         mono_test_marshal_pass_return_custom3 (5, 10, 5);
351                 }
352                 catch (ApplicationException) {
353                         return 0;
354                 }
355                 return 1;
356         }
357
358         public static int test_0_missing_getinstance2 () {
359                 try {
360                         mono_test_marshal_pass_return_custom4 (5, 10, 5);
361                 }
362                 catch (ApplicationException) {
363                         return 0;
364                 }
365                 return 1;
366         }
367
368         public static int test_0_missing_getinstance3 () {
369                 try {
370                         mono_test_marshal_pass_return_custom5 (5, 10, 5);
371                 }
372                 catch (ApplicationException) {
373                         return 0;
374                 }
375                 return 1;
376         }
377
378         public class Marshal6 : ICustomMarshaler {
379                 public static int managed_to_native_count = 0;
380                 public static int native_to_managed_count = 0;
381
382                 public static ICustomMarshaler GetInstance (string s) 
383                 {
384                         return new Marshal6 ();
385                 }
386
387                 public void CleanUpManagedData (object managedObj)
388                 {
389                 }
390
391                 public void CleanUpNativeData (IntPtr pNativeData)
392                 {
393                 }
394
395                 public int GetNativeDataSize ()
396                 {
397                         return 4;
398                 }
399
400                 public IntPtr MarshalManagedToNative (object managedObj)
401                 {
402                         managed_to_native_count++;
403                         return IntPtr.Zero;
404                 }
405
406                 public object MarshalNativeToManaged (IntPtr pNativeData)
407                 {
408                         native_to_managed_count++;
409                         return null;
410                 }
411         }
412
413         public delegate void custom_out_param_delegate ([MarshalAs (UnmanagedType.CustomMarshaler, MarshalTypeRef = typeof (Marshal6), MarshalCookie = "5")] out object o);
414
415         [DllImport ("libtest")]
416         private static extern int mono_test_marshal_custom_out_param_delegate (custom_out_param_delegate del);
417
418         // ICustomMarshaler.MarshalNativeToManaged should not be called when the 
419         // parameter is marked as an out.
420         public static int test_0_native_to_managed_custom_parameter () 
421         {
422                 Marshal6.managed_to_native_count = 0;
423                 Marshal6.native_to_managed_count = 0;
424
425                 int res = mono_test_marshal_custom_out_param_delegate (new custom_out_param_delegate (custom_out_param));
426
427                 if (Marshal6.managed_to_native_count != 1)
428                         return 1;
429                 if (Marshal6.native_to_managed_count != 0)
430                         return 2;
431
432                 return 0;
433         }
434         
435         private static void custom_out_param (out object i) 
436         {
437                 i = new object();       
438         }
439
440 }