Merge pull request #5714 from alexischr/update_bockbuild
[mono.git] / mono / tests / marshal2.cs
1 //
2 // Tests for Marshal.StructureToPtr and PtrToStructure
3 //
4
5 using System;
6 using System.Text;
7 using System.Runtime.InteropServices;
8
9 public class Tests {
10
11
12         [StructLayout (LayoutKind.Sequential)]
13         public class SimpleObj {
14                 public int a;
15                 public int b;
16
17                 public void test () {}
18         }
19
20         [StructLayout (LayoutKind.Sequential)]
21         public struct SimpleStruct2 {
22                 public int a;
23                 public int b;
24         }
25         
26         [StructLayout (LayoutKind.Sequential, CharSet=CharSet.Ansi)]
27         public struct SimpleStruct {
28                 public int a;
29                 public bool bool1;
30                 public bool bool2;
31                 public int b;
32                 [MarshalAs (UnmanagedType.ByValArray, SizeConst=2)] public short[] a1;
33                 [MarshalAs (UnmanagedType.ByValTStr, SizeConst=4)] public string s1;
34                 public SimpleStruct2 emb1;
35                 public SimpleObj emb2;
36                 public string s2;
37                 public double x;
38                 [MarshalAs (UnmanagedType.ByValArray, SizeConst=2)] public char[] a2;
39         }
40
41         [StructLayout (LayoutKind.Sequential, CharSet=CharSet.Ansi)]
42         public struct ByValTStrStruct {
43                 [MarshalAs (UnmanagedType.ByValTStr, SizeConst=4)] public string s1;
44                 public int i;
45         }
46
47         [StructLayout (LayoutKind.Sequential, CharSet=CharSet.Unicode)]
48         public struct ByValWStrStruct {
49                 [MarshalAs (UnmanagedType.ByValTStr, SizeConst=4)] public string s1;
50                 public int i;
51         }
52
53         [StructLayout (LayoutKind.Sequential, Pack=1)]
54         public struct PackStruct1 {
55                 float f;
56         }
57
58         [StructLayout (LayoutKind.Sequential)]
59         public struct PackStruct2 {
60                 byte b;
61                 PackStruct1 s;
62         }
63         
64         public unsafe static int Main (String[] args) {
65                 if (TestDriver.RunTests (typeof (Tests), args) != 0)
66                         return 34;
67                 return 0;
68         }
69
70         public static int test_0_structure_to_ptr () {
71                 SimpleStruct ss = new SimpleStruct ();
72                 int size = Marshal.SizeOf (typeof (SimpleStruct));
73                 
74                 //if (size != 52)
75                 //return 1;
76                 
77                 IntPtr p = Marshal.AllocHGlobal (size);
78                 ss.a = 1;
79                 ss.bool1 = true;
80                 ss.bool2 = false;
81                 ss.b = 2;
82                 ss.a1 = new short [2];
83                 ss.a1 [0] = 6;
84                 ss.a1 [1] = 5;
85                 ss.s1 = "abcd";
86                 ss.emb1 = new SimpleStruct2 ();
87                 ss.emb1.a = 3;
88                 ss.emb1.b = 4;
89                 ss.emb2 = new SimpleObj ();
90                 ss.emb2.a = 10;
91                 ss.emb2.b = 11;
92                 ss.s2 = "just a test";
93                 ss.x = 1.5;
94                 ss.a2 = new char [2];
95                 ss.a2 [0] = 'a';
96                 ss.a2 [1] = 'b';
97                 
98                 Marshal.StructureToPtr (ss, p, false);
99                 Type t = ss.GetType ();
100                 
101                 if (Marshal.ReadInt32 (p, (int)Marshal.OffsetOf (t, "a")) != 1)
102                         return 1;
103                 if (Marshal.ReadInt32 (p, (int)Marshal.OffsetOf (t, "bool1")) != 1)
104                         return 2;
105                 if (Marshal.ReadInt32 (p, (int)Marshal.OffsetOf (t, "bool2")) != 0)
106                         return 3;
107                 if (Marshal.ReadInt32 (p, (int)Marshal.OffsetOf (t, "b")) != 2)
108                         return 4;
109                 if (Marshal.ReadInt16 (p, 16) != 6)
110                         return 5;
111                 if (Marshal.ReadInt16 (p, 18) != 5)
112                         return 6;
113                 if (Marshal.ReadByte (p, 20) != 97)
114                         return 7;
115                 if (Marshal.ReadByte (p, 21) != 98)
116                         return 8;
117                 if (Marshal.ReadByte (p, 22) != 99)
118                         return 9;
119                 if (Marshal.ReadByte (p, 23) != 0)
120                         return 10;
121                 if (Marshal.ReadInt32 (p, 24) != 3)
122                         return 11;
123                 if (Marshal.ReadInt32 (p, 28) != 4)
124                         return 12;
125                 if (Marshal.ReadInt32 (p, 32) != 10)
126                         return 13;
127                 if (Marshal.ReadInt32 (p, 36) != 11)
128                         return 14;
129                 if (Marshal.ReadByte (p, (int)Marshal.OffsetOf (t, "a2")) != 97)
130                         return 15;
131                 if (Marshal.ReadByte (p, (int)Marshal.OffsetOf (t, "a2") + 1) != 98)
132                         return 16;
133
134                 SimpleStruct cp = (SimpleStruct)Marshal.PtrToStructure (p, ss.GetType ());
135
136                 if (cp.a != 1)
137                         return 16;
138
139                 if (cp.bool1 != true)
140                         return 17;
141
142                 if (cp.bool2 != false)
143                         return 18;
144
145                 if (cp.b != 2)
146                         return 19;
147
148                 if (cp.a1 [0] != 6)
149                         return 20;
150                 
151                 if (cp.a1 [1] != 5)
152                         return 21;
153
154                 if (cp.s1 != "abc")
155                         return 22;
156                 
157                 if (cp.emb1.a != 3)
158                         return 23;
159
160                 if (cp.emb1.b != 4)
161                         return 24;
162
163                 if (cp.emb2.a != 10)
164                         return 25;
165
166                 if (cp.emb2.b != 11)
167                         return 26;
168
169                 if (cp.s2 != "just a test")
170                         return 27;
171
172                 if (cp.x != 1.5)
173                         return 28;
174
175                 if (cp.a2 [0] != 'a')
176                         return 29;
177
178                 if (cp.a2 [1] != 'b')
179                         return 30;
180                 return 0;
181         }
182
183         [StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Unicode)]
184         public struct Struct1
185         {
186                 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)]
187         public string Field1;
188                 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
189         public string Field2;
190                 [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 14)]
191         public string Field3;
192         }
193
194         public static int test_0_byvaltstr () {
195                 ByValTStrStruct s = new ByValTStrStruct ();
196
197                 IntPtr p2 = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (ByValTStrStruct)));
198                 Marshal.StructureToPtr(s, p2, false);
199
200                 /* Check that the ByValTStr is initialized correctly */
201                 for (int i = 0; i < 4; ++i)
202                         if (Marshal.ReadByte (p2, i) != 0)
203                                 return 31;
204
205                 s.s1 = "ABCD";
206                 s.i = 55;
207
208                 Marshal.StructureToPtr(s, p2, false);
209
210                 ByValTStrStruct s2 = (ByValTStrStruct)Marshal.PtrToStructure (p2, typeof (ByValTStrStruct));
211
212                 /* The fourth char is lost because of null-termination */
213                 if (s2.s1 != "ABC")
214                         return 32;
215
216                 if (s2.i != 55)
217                         return 33;
218
219                 // Check that decoding also respects the size, even when there is no null terminator
220                 byte[] data = Encoding.ASCII.GetBytes ("ABCDXXXX");
221                 int size = Marshal.SizeOf (typeof (ByValTStrStruct));
222                 IntPtr buffer = Marshal.AllocHGlobal (size);
223                 Marshal.Copy (data, 0, buffer, size);
224
225                 s2 = (ByValTStrStruct)Marshal.PtrToStructure (buffer, typeof (ByValTStrStruct));
226                 if (s2.s1 != "ABC")
227                         return 34;
228
229                 return 0;
230         }
231
232         public static int test_0_byvaltstr_unicode () {
233                 ByValWStrStruct s = new ByValWStrStruct ();
234
235                 IntPtr p2 = Marshal.AllocHGlobal (Marshal.SizeOf (typeof (ByValWStrStruct)));
236                 Marshal.StructureToPtr(s, p2, false);
237
238                 /* Check that the ByValWStr is initialized correctly */
239                 for (int i = 0; i < 8; ++i)
240                         if (Marshal.ReadByte (p2, i) != 0)
241                                 return 31;
242
243                 s.s1 = "ABCD";
244                 s.i = 55;
245
246                 Marshal.StructureToPtr(s, p2, false);
247
248                 ByValWStrStruct s2 = (ByValWStrStruct)Marshal.PtrToStructure (p2, typeof (ByValWStrStruct));
249
250                 /* The fourth char is lost because of null-termination */
251                 if (s2.s1 != "ABC")
252                         return 32;
253
254                 if (s2.i != 55)
255                         return 33;
256                 return 0;
257         }
258
259         public static int test_0_byvaltstr_max_size () {
260                 string buffer = "12345678123456789012345678901234";
261
262                 IntPtr ptr = Marshal.StringToBSTR (buffer);
263
264                 Struct1 data = (Struct1)Marshal.PtrToStructure (ptr, typeof (Struct1));
265                 if (data.Field1 != "12345678")
266                         return 1;
267                 if (data.Field2 != "1234567890")
268                         return 2;
269                 if (data.Field3 != "12345678901234")
270                         return 3;
271                 return 0;
272         }
273
274         // Check that the 'Pack' directive on a struct changes the min alignment of the struct as well (#12110)
275         public static int test_0_struct_pack () {
276                 if (Marshal.OffsetOf (typeof (PackStruct2), "s") != new IntPtr (1))
277                         return 1;
278                 return 0;
279         }
280
281         public static int test_0_generic_ptr_to_struct () {
282                 int size = Marshal.SizeOf (typeof (SimpleStruct2));
283                 IntPtr p = Marshal.AllocHGlobal (size);
284
285                 Marshal.WriteInt32 (p, 0, 1); //a
286                 Marshal.WriteInt32 (p, 4, 2); //a
287
288                 var s = Marshal.PtrToStructure<SimpleStruct2> (p);
289
290                 if (s.a != 1)
291                         return 1;
292                 if (s.b != 2)
293                         return 2;
294                 return 0;
295         }
296 }