Wed Jun 16 14:33:22 CEST 2004 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / objects.cs
1 using System;
2 using System.Reflection;
3 using System.Runtime.InteropServices;
4
5 /*
6  * Regression tests for the mono JIT.
7  *
8  * Each test needs to be of the form:
9  *
10  * static int test_<result>_<name> ();
11  *
12  * where <result> is an integer (the value that needs to be returned by
13  * the method to make it pass.
14  * <name> is a user-displayed name used to identify the test.
15  *
16  * The tests can be driven in two ways:
17  * *) running the program directly: Main() uses reflection to find and invoke
18  *      the test methods (this is useful mostly to check that the tests are correct)
19  * *) with the --regression switch of the jit (this is the preferred way since
20  *      all the tests will be run with optimizations on and off)
21  *
22  * The reflection logic could be moved to a .dll since we need at least another
23  * regression test file written in IL code to have better control on how
24  * the IL code looks.
25  */
26
27 struct Simple {
28         public int a;
29         public byte b;
30         public short c;
31         public long d;
32 }
33
34 struct Small {
35         public byte b1;
36         public byte b2;
37 }
38
39 class Sample {
40         public int a;
41         public Sample (int v) {
42                 a = v;
43         }
44 }
45
46 [StructLayout ( LayoutKind.Explicit )]
47 struct StructWithBigOffsets {
48                 [ FieldOffset(10000) ] public byte b;
49                 [ FieldOffset(11000) ] public short s;
50                 [ FieldOffset(12000) ] public uint i;
51                 [ FieldOffset(13000) ] public long l;
52                 [ FieldOffset(14000) ] public float f;
53                 [ FieldOffset(15000) ] public double d;
54 }
55
56 enum SampleEnum {
57         A,
58         B,
59         C
60 }
61
62 class Tests {
63
64         static int Main () {
65                 return TestDriver.RunTests (typeof (Tests));
66         }
67         
68         static int test_0_return () {
69                 Simple s;
70                 s.a = 1;
71                 s.b = 2;
72                 s.c = (short)(s.a + s.b);
73                 s.d = 4;
74                 return s.a - 1;
75         }
76
77         static int test_0_string_access () {
78                 string s = "Hello";
79                 if (s [1] != 'e')
80                         return 1;
81                 return 0;
82         }
83
84         static int test_0_string_virtual_call () {
85                 string s = "Hello";
86                 string s2 = s.ToString ();
87                 if (s2 [1] != 'e')
88                         return 1;
89                 return 0;
90         }
91
92         static int test_0_iface_call () {
93                 string s = "Hello";
94                 object o = ((ICloneable)s).Clone ();
95                 return 0;
96         }
97
98         static int test_5_newobj () {
99                 Sample s = new Sample (5);
100                 return s.a;
101         }
102
103         static int test_4_box () {
104                 object obj = 4;
105                 return (int)obj;
106         }
107
108         static int test_0_enum_unbox () {
109                 SampleEnum x = SampleEnum.A;
110                 object o = x;
111                 
112                 int res = 1;
113
114                 res = (int)o;
115                 
116                 return res;
117         }
118         
119         static Simple get_simple (int v) {
120                 Simple r = new Simple ();
121                 r.a = v;
122                 r.b = (byte)(v + 1);
123                 r.c = (short)(v + 2);
124                 r.d = v + 3;
125
126                 return r;
127         }
128
129         static int test_3_return_struct () {
130                 Simple v = get_simple (1);
131
132                 if (v.a != 1)
133                         return 0;
134                 if (v.b != 2)
135                         return 0;
136                 if (v.c != 3)
137                         return 0;
138                 if (v.d != 4)
139                         return 0;
140                 return 3;
141         }
142
143         public virtual Simple v_get_simple (int v)
144         {
145                 return get_simple (v);
146         }
147         
148         static int test_2_return_struct_virtual () {
149                 Tests t = new Tests ();
150                 Simple v = t.v_get_simple (2);
151
152                 if (v.a != 2)
153                         return 0;
154                 if (v.b != 3)
155                         return 0;
156                 if (v.c != 4)
157                         return 0;
158                 if (v.d != 5)
159                         return 0;
160                 return 2;
161         }
162
163         static int receive_simple (int a, Simple v, int b) {
164                 if (v.a != 1)
165                         return 1;
166                 if (v.b != 2)
167                         return 2;
168                 if (v.c != 3)
169                         return 3;
170                 if (v.d != 4)
171                         return 4;
172                 if (a != 7)
173                         return 5;
174                 if (b != 9)
175                         return 6;
176                 return 0;
177         }
178         
179         static int test_5_pass_struct () {
180                 Simple v = get_simple (1);
181                 if (receive_simple (7, v, 9) != 0)
182                         return 0;
183                 if (receive_simple (7, get_simple (1), 9) != 0)
184                         return 1;
185                 return 5;
186         }
187
188         // Test alignment of small structs
189
190         static Small get_small (byte v) {
191                 Small r = new Small ();
192         
193                 r.b1 = v;
194                 r.b2 = (byte)(v + 1);
195
196                 return r;
197         }
198
199         static Small return_small (Small s) {
200                 return s;
201         }
202
203         static int receive_small (int a, Small v, int b) {
204                 if (v.b1 != 1)
205                         return 1;
206                 if (v.b2 != 2)
207                         return 2;
208                 return 0;
209         }
210
211         static int test_5_pass_small_struct () {
212                 Small v = get_small (1);
213                 if (receive_small (7, v, 9) != 0)
214                         return 0;
215                 if (receive_small (7, get_small (1), 9) != 0)
216                         return 1;
217                 v = return_small (v);
218                 if (v.b1 != 1)
219                         return 2;
220                 if (v.b2 != 2)
221                         return 3;
222                 return 5;
223         }
224
225         struct AStruct {
226                 public int i;
227
228                 public AStruct (int i) {
229                         this.i = i;
230                 }
231
232                 public override int GetHashCode () {
233                         return i;
234                 }
235         }
236
237         // Test that vtypes are unboxed during a virtual call
238         static int test_44_unbox_trampoline () {
239                 AStruct s = new AStruct (44);
240                 object o = s;
241                 return o.GetHashCode ();
242         }
243
244         // Test fields with big offsets
245         static int test_1_fields_with_big_offsets () {
246                 StructWithBigOffsets s = new StructWithBigOffsets ();
247                 StructWithBigOffsets s2 = new StructWithBigOffsets ();
248
249                 s.b = 0xde;
250                 s.s = 0x12de;
251                 s.i = 0xdeadbeef;
252                 s.l = 0xcafebabe;
253                 s.f = 3.14F;
254                 s.d = 3.14;
255
256                 s2.b = s.b;
257                 s2.s = s.s;
258                 s2.i = s.i;
259                 s2.l = s.l;
260                 s2.f = s.f;
261                 s2.d = s.d;
262
263                 if ((s2.b != 0xde) || (s2.s != 0x12de) || (s2.i != 0xdeadbeef) || (s2.l != 0xcafebabe) || (s2.f != 3.14F) || (s2.d != 3.14))
264                         return 0;
265                 else
266                         return 1;
267         }
268
269         class TestRegA {
270
271                 long buf_start;
272                 int buf_length, buf_offset;
273
274                 public TestRegA () {
275                         buf_start = 0;
276                         buf_length = 0;
277                         buf_offset = 0;
278                 }
279         
280                 public long Seek (long position) {
281                         long pos = position;
282                         /* interaction between the register allocator and
283                          * allocating arguments to registers */
284                         if (pos >= buf_start && pos <= buf_start + buf_length) {
285                                 buf_offset = (int) (pos - buf_start);
286                                 return pos;
287                         }
288                         return buf_start;
289                 }
290
291         }
292
293         static int test_0_seektest () {
294                 TestRegA t = new TestRegA ();
295                 return (int)t.Seek (0);
296         }
297
298         class Super : ICloneable {
299                 public virtual object Clone () {
300                         return null;
301                 }
302         }
303         class Duper: Super {
304         }
305         
306         static int test_0_super_cast () {
307                 Duper d = new Duper ();
308                 Super sup = d;
309                 Object o = d;
310
311                 if (!(o is Super))
312                         return 1;
313                 try {
314                         d = (Duper)sup;
315                 } catch {
316                         return 2;
317                 }
318                 if (!(d is Object))
319                         return 3;
320                 try {
321                         d = (Duper)(object)sup;
322                 } catch {
323                         return 4;
324                 }
325                 return 0;
326         }
327
328         static int test_0_super_cast_array () {
329                 Duper[] d = new Duper [0];
330                 Super[] sup = d;
331                 Object[] o = d;
332
333                 if (!(o is Super[]))
334                         return 1;
335                 try {
336                         d = (Duper[])sup;
337                 } catch {
338                         return 2;
339                 }
340                 if (!(d is Object[]))
341                         return 3;
342                 try {
343                         d = (Duper[])(object[])sup;
344                 } catch {
345                         return 4;
346                 }
347                 return 0;
348         }
349
350         static int test_0_multi_array_cast () {
351                 Duper[,] d = new Duper [1, 1];
352                 object[,] o = d;
353
354                 try {
355                         o [0, 0] = new Super ();
356                         return 1;
357                 }
358                 catch (ArrayTypeMismatchException) {
359                 }
360
361                 return 0;
362         }
363
364         static int test_0_vector_array_cast () {
365                 Array arr1 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {0});
366                 Array arr2 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {10});
367
368                 if (arr1.GetType () != typeof (int[]))
369                         return 1;
370
371                 if (arr2.GetType () == typeof (int[]))
372                         return 2;
373
374                 int[] b;
375
376                 b = (int[])arr1;
377
378                 try {
379                         b = (int[])arr2;
380                         return 3;
381                 }
382                 catch (InvalidCastException) {
383                 }
384
385                 if (arr2 is int[])
386                         return 4;
387
388                 return 0;
389         }
390
391         static int test_0_enum_array_cast () {
392                 TypeCode[] tc = new TypeCode [0];
393                 object[] oa;
394                 ValueType[] vta;
395                 int[] inta;
396                 Array a = tc;
397                 bool ok;
398
399                 if (a is object[])
400                         return 1;
401                 if (a is ValueType[])
402                         return 2;
403                 if (a is Enum[])
404                         return 3;
405                 try {
406                         ok = false;
407                         oa = (object[])a;
408                 } catch {
409                         ok = true;
410                 }
411                 if (!ok)
412                         return 4;
413                 try {
414                         ok = false;
415                         vta = (ValueType[])a;
416                 } catch {
417                         ok = true;
418                 }
419                 if (!ok)
420                         return 5;
421                 try {
422                         ok = true;
423                         inta = (int[])a;
424                 } catch {
425                         ok = false;
426                 }
427                 if (!ok)
428                         return 6;
429                 return 0;
430         }
431
432         static int test_0_more_cast_corner_cases () {
433                 ValueType[] vta = new ValueType [0];
434                 Enum[] ea = new Enum [0];
435                 Array a = vta;
436                 object[] oa;
437                 bool ok;
438
439                 if (!(a is object[]))
440                         return 1;
441                 if (!(a is ValueType[]))
442                         return 2;
443                 if (a is Enum[])
444                         return 3;
445                 a = ea;
446                 if (!(a is object[]))
447                         return 4;
448                 if (!(a is ValueType[]))
449                         return 5;
450                 if (!(a is Enum[]))
451                         return 6;
452
453                 try {
454                         ok = true;
455                         oa = (object[])a;
456                 } catch {
457                         ok = false;
458                 }
459                 if (!ok)
460                         return 7;
461         
462                 try {
463                         ok = true;
464                         oa = (Enum[])a;
465                 } catch {
466                         ok = false;
467                 }
468                 if (!ok)
469                         return 8;
470         
471                 try {
472                         ok = true;
473                         oa = (ValueType[])a;
474                 } catch {
475                         ok = false;
476                 }
477                 if (!ok)
478                         return 9;
479
480                 a = vta;
481                 try {
482                         ok = true;
483                         oa = (object[])a;
484                 } catch {
485                         ok = false;
486                 }
487                 if (!ok)
488                         return 10;
489         
490                 try {
491                         ok = true;
492                         oa = (ValueType[])a;
493                 } catch {
494                         ok = false;
495                 }
496                 if (!ok)
497                         return 11;
498         
499                 try {
500                         ok = false;
501                         vta = (Enum[])a;
502                 } catch {
503                         ok = true;
504                 }
505                 if (!ok)
506                         return 12;
507                 return 0;
508         }
509
510         static int test_0_cast_iface_array () {
511                 object o = new ICloneable [0];
512                 object o2 = new Duper [0];
513                 object t;
514                 bool ok;
515
516                 if (!(o is object[]))
517                         return 1;
518                 if (!(o2 is ICloneable[]))
519                         return 2;
520
521                 try {
522                         ok = true;
523                         t = (object[])o;
524                 } catch {
525                         ok = false;
526                 }
527                 if (!ok)
528                         return 3;
529         
530                 try {
531                         ok = true;
532                         t = (ICloneable[])o2;
533                 } catch {
534                         ok = false;
535                 }
536                 if (!ok)
537                         return 4;
538
539                 try {
540                         ok = true;
541                         t = (ICloneable[])o;
542                 } catch {
543                         ok = false;
544                 }
545                 if (!ok)
546                         return 5;
547
548                 if (!(o is ICloneable[]))
549                         return 6;
550
551                 /* add tests for interfaces that 'inherit' interfaces */
552                 return 0;
553         }
554
555         private static int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
556
557         private static int AbsoluteDays (int year, int month, int day)
558         {
559                 int temp = 0, m = 1;
560                 int[] days = daysmonthleap;
561                 while (m < month)
562                         temp += days[m++];
563                 return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));
564         }
565
566         static int test_719162_complex_div () {
567                 int adays = AbsoluteDays (1970, 1, 1);
568                 return adays;
569         }
570
571         delegate int GetIntDel ();
572
573         static int return4 () {
574                 return 4;
575         }
576
577         int return5 () {
578                 return 5;
579         }
580
581         static int test_2_static_delegate () {
582                 GetIntDel del = new GetIntDel (return4);
583                 int v = del ();
584                 if (v != 4)
585                         return 0;
586                 return 2;
587         }
588
589         static int test_2_instance_delegate () {
590                 Tests t = new Tests ();
591                 GetIntDel del = new GetIntDel (t.return5);
592                 int v = del ();
593                 if (v != 5)
594                         return 0;
595                 return 2;
596         }
597
598         static int test_1_store_decimal () {
599                 decimal[,] a = {{1}};
600
601                 if (a[0,0] != 1m)
602                         return 0;
603                 return 1;
604         }
605
606         static int test_2_intptr_stobj () {
607                 System.IntPtr [] arr = { new System.IntPtr () };
608
609                 if (arr [0] != (System.IntPtr)0)
610                         return 1;
611                 return 2;
612         }
613 }
614