2005-05-22 Zoltan Varga <vargaz@freemail.hu>
[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 struct Large {
40         int one;
41         int two;
42         long three;
43         long four;
44         int five;
45         long six;
46         int seven;
47         long eight;
48         long nine;
49         long ten;
50
51         public void populate ()
52         {
53                 one = 1; two = 2;
54                 three = 3; four = 4;
55                 five = 5; six = 6;
56                 seven = 7; eight = 8;
57                 nine = 9; ten = 10;
58         }
59         public bool check ()
60         {
61                 return one == 1  && two == 2  &&
62                         three == 3  && four == 4  &&
63                         five == 5  && six == 6  &&
64                         seven == 7  && eight == 8  &&
65                         nine == 9  && ten == 10;
66         }
67 }
68
69 class Sample {
70         public int a;
71         public Sample (int v) {
72                 a = v;
73         }
74 }
75
76 [StructLayout ( LayoutKind.Explicit )]
77 struct StructWithBigOffsets {
78                 [ FieldOffset(10000) ] public byte b;
79                 [ FieldOffset(11000) ] public short s;
80                 [ FieldOffset(12000) ] public uint i;
81                 [ FieldOffset(13000) ] public long l;
82                 [ FieldOffset(14000) ] public float f;
83                 [ FieldOffset(15000) ] public double d;
84 }
85
86 enum SampleEnum {
87         A,
88         B,
89         C
90 }
91
92 class Tests {
93
94         static int Main () {
95                 return TestDriver.RunTests (typeof (Tests));
96         }
97         
98         static int test_0_return () {
99                 Simple s;
100                 s.a = 1;
101                 s.b = 2;
102                 s.c = (short)(s.a + s.b);
103                 s.d = 4;
104                 return s.a - 1;
105         }
106
107         static int test_0_string_access () {
108                 string s = "Hello";
109                 if (s [1] != 'e')
110                         return 1;
111                 return 0;
112         }
113
114         static int test_0_string_virtual_call () {
115                 string s = "Hello";
116                 string s2 = s.ToString ();
117                 if (s2 [1] != 'e')
118                         return 1;
119                 return 0;
120         }
121
122         static int test_0_iface_call () {
123                 string s = "Hello";
124                 object o = ((ICloneable)s).Clone ();
125                 return 0;
126         }
127
128         static int test_5_newobj () {
129                 Sample s = new Sample (5);
130                 return s.a;
131         }
132
133         static int test_4_box () {
134                 object obj = 4;
135                 return (int)obj;
136         }
137
138         static int test_0_enum_unbox () {
139                 SampleEnum x = SampleEnum.A;
140                 object o = x;
141                 
142                 int res = 1;
143
144                 res = (int)o;
145                 
146                 return res;
147         }
148         
149         static Simple get_simple (int v) {
150                 Simple r = new Simple ();
151                 r.a = v;
152                 r.b = (byte)(v + 1);
153                 r.c = (short)(v + 2);
154                 r.d = v + 3;
155
156                 return r;
157         }
158
159         static int test_3_return_struct () {
160                 Simple v = get_simple (1);
161
162                 if (v.a != 1)
163                         return 0;
164                 if (v.b != 2)
165                         return 0;
166                 if (v.c != 3)
167                         return 0;
168                 if (v.d != 4)
169                         return 0;
170                 return 3;
171         }
172
173         public virtual Simple v_get_simple (int v)
174         {
175                 return get_simple (v);
176         }
177         
178         static int test_2_return_struct_virtual () {
179                 Tests t = new Tests ();
180                 Simple v = t.v_get_simple (2);
181
182                 if (v.a != 2)
183                         return 0;
184                 if (v.b != 3)
185                         return 0;
186                 if (v.c != 4)
187                         return 0;
188                 if (v.d != 5)
189                         return 0;
190                 return 2;
191         }
192
193         static int receive_simple (int a, Simple v, int b) {
194                 if (v.a != 1)
195                         return 1;
196                 if (v.b != 2)
197                         return 2;
198                 if (v.c != 3)
199                         return 3;
200                 if (v.d != 4)
201                         return 4;
202                 if (a != 7)
203                         return 5;
204                 if (b != 9)
205                         return 6;
206                 return 0;
207         }
208         
209         static int test_5_pass_struct () {
210                 Simple v = get_simple (1);
211                 if (receive_simple (7, v, 9) != 0)
212                         return 0;
213                 if (receive_simple (7, get_simple (1), 9) != 0)
214                         return 1;
215                 return 5;
216         }
217
218         // Test alignment of small structs
219
220         static Small get_small (byte v) {
221                 Small r = new Small ();
222         
223                 r.b1 = v;
224                 r.b2 = (byte)(v + 1);
225
226                 return r;
227         }
228
229         static Small return_small (Small s) {
230                 return s;
231         }
232
233         static int receive_small (int a, Small v, int b) {
234                 if (v.b1 != 1)
235                         return 1;
236                 if (v.b2 != 2)
237                         return 2;
238                 return 0;
239         }
240
241         static int test_5_pass_small_struct () {
242                 Small v = get_small (1);
243                 if (receive_small (7, v, 9) != 0)
244                         return 0;
245                 if (receive_small (7, get_small (1), 9) != 0)
246                         return 1;
247                 v = return_small (v);
248                 if (v.b1 != 1)
249                         return 2;
250                 if (v.b2 != 2)
251                         return 3;
252                 return 5;
253         }
254
255         struct AStruct {
256                 public int i;
257
258                 public AStruct (int i) {
259                         this.i = i;
260                 }
261
262                 public override int GetHashCode () {
263                         return i;
264                 }
265         }
266
267         // Test that vtypes are unboxed during a virtual call
268         static int test_44_unbox_trampoline () {
269                 AStruct s = new AStruct (44);
270                 object o = s;
271                 return o.GetHashCode ();
272         }
273
274         static int test_0_unbox_trampoline2 () {
275                 int i = 12;
276                 object o = i;
277                         
278                 if (i.ToString () != "12")
279                         return 1;
280                 if (((Int32)o).ToString () != "12")
281                         return 2;
282                 if (o.ToString () != "12")
283                         return 3;
284                 return 0;
285         }
286
287         // Test fields with big offsets
288         static int test_0_fields_with_big_offsets () {
289                 StructWithBigOffsets s = new StructWithBigOffsets ();
290                 StructWithBigOffsets s2 = new StructWithBigOffsets ();
291
292                 s.b = 0xde;
293                 s.s = 0x12de;
294                 s.i = 0xdeadbeef;
295                 s.l = 0xcafebabe;
296                 s.f = 3.14F;
297                 s.d = 3.14;
298
299                 s2.b = s.b;
300                 s2.s = s.s;
301                 s2.i = s.i;
302                 s2.l = s.l;
303                 s2.f = s.f;
304                 s2.d = s.d;
305
306                 if (s2.b != 0xde)
307                         return 1;
308                 if (s2.s != 0x12de)
309                         return 2;
310                 if (s2.i != 0xdeadbeef)
311                         return 3;
312                 if (s2.l != 0xcafebabe)
313                         return 4;
314                 if (s2.f != 3.14F)
315                         return 5;
316                 if (s2.d != 3.14)
317                         return 6;
318
319                 return 0;
320         }
321
322         class TestRegA {
323
324                 long buf_start;
325                 int buf_length, buf_offset;
326
327                 public TestRegA () {
328                         buf_start = 0;
329                         buf_length = 0;
330                         buf_offset = 0;
331                 }
332         
333                 public long Seek (long position) {
334                         long pos = position;
335                         /* interaction between the register allocator and
336                          * allocating arguments to registers */
337                         if (pos >= buf_start && pos <= buf_start + buf_length) {
338                                 buf_offset = (int) (pos - buf_start);
339                                 return pos;
340                         }
341                         return buf_start;
342                 }
343
344         }
345
346         static int test_0_seektest () {
347                 TestRegA t = new TestRegA ();
348                 return (int)t.Seek (0);
349         }
350
351         class Super : ICloneable {
352                 public virtual object Clone () {
353                         return null;
354                 }
355         }
356         class Duper: Super {
357         }
358
359         static int test_0_null_cast () {
360                 object o = null;
361
362                 Super s = (Super)o;
363
364                 return 0;
365         }
366         
367         static int test_0_super_cast () {
368                 Duper d = new Duper ();
369                 Super sup = d;
370                 Object o = d;
371
372                 if (!(o is Super))
373                         return 1;
374                 try {
375                         d = (Duper)sup;
376                 } catch {
377                         return 2;
378                 }
379                 if (!(d is Object))
380                         return 3;
381                 try {
382                         d = (Duper)(object)sup;
383                 } catch {
384                         return 4;
385                 }
386                 return 0;
387         }
388
389         static int test_0_super_cast_array () {
390                 Duper[] d = new Duper [0];
391                 Super[] sup = d;
392                 Object[] o = d;
393
394                 if (!(o is Super[]))
395                         return 1;
396                 try {
397                         d = (Duper[])sup;
398                 } catch {
399                         return 2;
400                 }
401                 if (!(d is Object[]))
402                         return 3;
403                 try {
404                         d = (Duper[])(object[])sup;
405                 } catch {
406                         return 4;
407                 }
408                 return 0;
409         }
410
411         static int test_0_multi_array_cast () {
412                 Duper[,] d = new Duper [1, 1];
413                 object[,] o = d;
414
415                 try {
416                         o [0, 0] = new Super ();
417                         return 1;
418                 }
419                 catch (ArrayTypeMismatchException) {
420                 }
421
422                 return 0;
423         }
424
425         static int test_0_vector_array_cast () {
426                 Array arr1 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {0});
427                 Array arr2 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {10});
428
429                 if (arr1.GetType () != typeof (int[]))
430                         return 1;
431
432                 if (arr2.GetType () == typeof (int[]))
433                         return 2;
434
435                 int[] b;
436
437                 b = (int[])arr1;
438
439                 try {
440                         b = (int[])arr2;
441                         return 3;
442                 }
443                 catch (InvalidCastException) {
444                 }
445
446                 if (arr2 is int[])
447                         return 4;
448
449                 return 0;
450         }
451
452         static int test_0_enum_array_cast () {
453                 TypeCode[] tc = new TypeCode [0];
454                 object[] oa;
455                 ValueType[] vta;
456                 int[] inta;
457                 Array a = tc;
458                 bool ok;
459
460                 if (a is object[])
461                         return 1;
462                 if (a is ValueType[])
463                         return 2;
464                 if (a is Enum[])
465                         return 3;
466                 try {
467                         ok = false;
468                         oa = (object[])a;
469                 } catch {
470                         ok = true;
471                 }
472                 if (!ok)
473                         return 4;
474                 try {
475                         ok = false;
476                         vta = (ValueType[])a;
477                 } catch {
478                         ok = true;
479                 }
480                 if (!ok)
481                         return 5;
482                 try {
483                         ok = true;
484                         inta = (int[])a;
485                 } catch {
486                         ok = false;
487                 }
488                 if (!ok)
489                         return 6;
490                 return 0;
491         }
492
493         static int test_0_more_cast_corner_cases () {
494                 ValueType[] vta = new ValueType [0];
495                 Enum[] ea = new Enum [0];
496                 Array a = vta;
497                 object[] oa;
498                 bool ok;
499
500                 if (!(a is object[]))
501                         return 1;
502                 if (!(a is ValueType[]))
503                         return 2;
504                 if (a is Enum[])
505                         return 3;
506                 a = ea;
507                 if (!(a is object[]))
508                         return 4;
509                 if (!(a is ValueType[]))
510                         return 5;
511                 if (!(a is Enum[]))
512                         return 6;
513
514                 try {
515                         ok = true;
516                         oa = (object[])a;
517                 } catch {
518                         ok = false;
519                 }
520                 if (!ok)
521                         return 7;
522         
523                 try {
524                         ok = true;
525                         oa = (Enum[])a;
526                 } catch {
527                         ok = false;
528                 }
529                 if (!ok)
530                         return 8;
531         
532                 try {
533                         ok = true;
534                         oa = (ValueType[])a;
535                 } catch {
536                         ok = false;
537                 }
538                 if (!ok)
539                         return 9;
540
541                 a = vta;
542                 try {
543                         ok = true;
544                         oa = (object[])a;
545                 } catch {
546                         ok = false;
547                 }
548                 if (!ok)
549                         return 10;
550         
551                 try {
552                         ok = true;
553                         oa = (ValueType[])a;
554                 } catch {
555                         ok = false;
556                 }
557                 if (!ok)
558                         return 11;
559         
560                 try {
561                         ok = false;
562                         vta = (Enum[])a;
563                 } catch {
564                         ok = true;
565                 }
566                 if (!ok)
567                         return 12;
568                 return 0;
569         }
570
571         static int test_0_cast_iface_array () {
572                 object o = new ICloneable [0];
573                 object o2 = new Duper [0];
574                 object t;
575                 bool ok;
576
577                 if (!(o is object[]))
578                         return 1;
579                 if (!(o2 is ICloneable[]))
580                         return 2;
581
582                 try {
583                         ok = true;
584                         t = (object[])o;
585                 } catch {
586                         ok = false;
587                 }
588                 if (!ok)
589                         return 3;
590         
591                 try {
592                         ok = true;
593                         t = (ICloneable[])o2;
594                 } catch {
595                         ok = false;
596                 }
597                 if (!ok)
598                         return 4;
599
600                 try {
601                         ok = true;
602                         t = (ICloneable[])o;
603                 } catch {
604                         ok = false;
605                 }
606                 if (!ok)
607                         return 5;
608
609                 if (!(o is ICloneable[]))
610                         return 6;
611
612                 /* add tests for interfaces that 'inherit' interfaces */
613                 return 0;
614         }
615
616         private static int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
617
618         private static int AbsoluteDays (int year, int month, int day)
619         {
620                 int temp = 0, m = 1;
621                 int[] days = daysmonthleap;
622                 while (m < month)
623                         temp += days[m++];
624                 return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));
625         }
626
627         static int test_719162_complex_div () {
628                 int adays = AbsoluteDays (1970, 1, 1);
629                 return adays;
630         }
631
632         delegate int GetIntDel ();
633
634         static int return4 () {
635                 return 4;
636         }
637
638         int return5 () {
639                 return 5;
640         }
641
642         static int test_2_static_delegate () {
643                 GetIntDel del = new GetIntDel (return4);
644                 int v = del ();
645                 if (v != 4)
646                         return 0;
647                 return 2;
648         }
649
650         static int test_2_instance_delegate () {
651                 Tests t = new Tests ();
652                 GetIntDel del = new GetIntDel (t.return5);
653                 int v = del ();
654                 if (v != 5)
655                         return 0;
656                 return 2;
657         }
658
659         static int test_1_store_decimal () {
660                 decimal[,] a = {{1}};
661
662                 if (a[0,0] != 1m)
663                         return 0;
664                 return 1;
665         }
666
667         static int test_2_intptr_stobj () {
668                 System.IntPtr [] arr = { new System.IntPtr () };
669
670                 if (arr [0] != (System.IntPtr)0)
671                         return 1;
672                 return 2;
673         }
674
675         static int llmult (int a, int b, int c, int d) {
676                 return a + b + c + d;
677         }
678
679         /* 
680          * Test that evaluation of complex arguments does not overwrite the
681          * arguments already in outgoing registers.
682          */
683         static int test_155_regalloc () {
684                 int a = 10;
685                 int b = 10;
686
687                 int c = 0;
688                 int d = 0;
689                 int[] arr = new int [5];
690
691                 return llmult (arr [c + d], 150, 5, 0);
692         }
693
694         static bool large_struct_test (Large a, Large b, Large c, Large d)
695         {
696                 if (!a.check ()) return false;
697                 if (!b.check ()) return false;
698                 if (!c.check ()) return false;
699                 if (!d.check ()) return false;
700                 return true;
701         }
702
703         static int test_2_large_struct_pass ()
704         {
705                 Large a, b, c, d;
706                 a = new Large ();
707                 b = new Large ();
708                 c = new Large ();
709                 d = new Large ();
710                 a.populate ();
711                 b.populate ();
712                 c.populate ();
713                 d.populate ();
714                 if (large_struct_test (a, b, c, d))
715                         return 2;
716                 return 0;
717         }
718
719         public static unsafe int test_0_pin_string () {
720                 string x = "xxx";
721                 fixed (char *c = x) {
722                         if (*c != 'x')
723                                 return 1;
724                 }
725                 return 0;
726         }
727 }
728