Minor correction.
[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         static int test_0_unbox_trampoline2 () {
245                 int i = 12;
246                 object o = i;
247                         
248                 if (i.ToString () != "12")
249                         return 1;
250                 if (((Int32)o).ToString () != "12")
251                         return 2;
252                 if (o.ToString () != "12")
253                         return 3;
254                 return 0;
255         }
256
257         // Test fields with big offsets
258         static int test_0_fields_with_big_offsets () {
259                 StructWithBigOffsets s = new StructWithBigOffsets ();
260                 StructWithBigOffsets s2 = new StructWithBigOffsets ();
261
262                 s.b = 0xde;
263                 s.s = 0x12de;
264                 s.i = 0xdeadbeef;
265                 s.l = 0xcafebabe;
266                 s.f = 3.14F;
267                 s.d = 3.14;
268
269                 s2.b = s.b;
270                 s2.s = s.s;
271                 s2.i = s.i;
272                 s2.l = s.l;
273                 s2.f = s.f;
274                 s2.d = s.d;
275
276                 if (s2.b != 0xde)
277                         return 1;
278                 if (s2.s != 0x12de)
279                         return 2;
280                 if (s2.i != 0xdeadbeef)
281                         return 3;
282                 if (s2.l != 0xcafebabe)
283                         return 4;
284                 if (s2.f != 3.14F)
285                         return 5;
286                 if (s2.d != 3.14)
287                         return 6;
288
289                 return 0;
290         }
291
292         class TestRegA {
293
294                 long buf_start;
295                 int buf_length, buf_offset;
296
297                 public TestRegA () {
298                         buf_start = 0;
299                         buf_length = 0;
300                         buf_offset = 0;
301                 }
302         
303                 public long Seek (long position) {
304                         long pos = position;
305                         /* interaction between the register allocator and
306                          * allocating arguments to registers */
307                         if (pos >= buf_start && pos <= buf_start + buf_length) {
308                                 buf_offset = (int) (pos - buf_start);
309                                 return pos;
310                         }
311                         return buf_start;
312                 }
313
314         }
315
316         static int test_0_seektest () {
317                 TestRegA t = new TestRegA ();
318                 return (int)t.Seek (0);
319         }
320
321         class Super : ICloneable {
322                 public virtual object Clone () {
323                         return null;
324                 }
325         }
326         class Duper: Super {
327         }
328         
329         static int test_0_super_cast () {
330                 Duper d = new Duper ();
331                 Super sup = d;
332                 Object o = d;
333
334                 if (!(o is Super))
335                         return 1;
336                 try {
337                         d = (Duper)sup;
338                 } catch {
339                         return 2;
340                 }
341                 if (!(d is Object))
342                         return 3;
343                 try {
344                         d = (Duper)(object)sup;
345                 } catch {
346                         return 4;
347                 }
348                 return 0;
349         }
350
351         static int test_0_super_cast_array () {
352                 Duper[] d = new Duper [0];
353                 Super[] sup = d;
354                 Object[] o = d;
355
356                 if (!(o is Super[]))
357                         return 1;
358                 try {
359                         d = (Duper[])sup;
360                 } catch {
361                         return 2;
362                 }
363                 if (!(d is Object[]))
364                         return 3;
365                 try {
366                         d = (Duper[])(object[])sup;
367                 } catch {
368                         return 4;
369                 }
370                 return 0;
371         }
372
373         static int test_0_multi_array_cast () {
374                 Duper[,] d = new Duper [1, 1];
375                 object[,] o = d;
376
377                 try {
378                         o [0, 0] = new Super ();
379                         return 1;
380                 }
381                 catch (ArrayTypeMismatchException) {
382                 }
383
384                 return 0;
385         }
386
387         static int test_0_vector_array_cast () {
388                 Array arr1 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {0});
389                 Array arr2 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {10});
390
391                 if (arr1.GetType () != typeof (int[]))
392                         return 1;
393
394                 if (arr2.GetType () == typeof (int[]))
395                         return 2;
396
397                 int[] b;
398
399                 b = (int[])arr1;
400
401                 try {
402                         b = (int[])arr2;
403                         return 3;
404                 }
405                 catch (InvalidCastException) {
406                 }
407
408                 if (arr2 is int[])
409                         return 4;
410
411                 return 0;
412         }
413
414         static int test_0_enum_array_cast () {
415                 TypeCode[] tc = new TypeCode [0];
416                 object[] oa;
417                 ValueType[] vta;
418                 int[] inta;
419                 Array a = tc;
420                 bool ok;
421
422                 if (a is object[])
423                         return 1;
424                 if (a is ValueType[])
425                         return 2;
426                 if (a is Enum[])
427                         return 3;
428                 try {
429                         ok = false;
430                         oa = (object[])a;
431                 } catch {
432                         ok = true;
433                 }
434                 if (!ok)
435                         return 4;
436                 try {
437                         ok = false;
438                         vta = (ValueType[])a;
439                 } catch {
440                         ok = true;
441                 }
442                 if (!ok)
443                         return 5;
444                 try {
445                         ok = true;
446                         inta = (int[])a;
447                 } catch {
448                         ok = false;
449                 }
450                 if (!ok)
451                         return 6;
452                 return 0;
453         }
454
455         static int test_0_more_cast_corner_cases () {
456                 ValueType[] vta = new ValueType [0];
457                 Enum[] ea = new Enum [0];
458                 Array a = vta;
459                 object[] oa;
460                 bool ok;
461
462                 if (!(a is object[]))
463                         return 1;
464                 if (!(a is ValueType[]))
465                         return 2;
466                 if (a is Enum[])
467                         return 3;
468                 a = ea;
469                 if (!(a is object[]))
470                         return 4;
471                 if (!(a is ValueType[]))
472                         return 5;
473                 if (!(a is Enum[]))
474                         return 6;
475
476                 try {
477                         ok = true;
478                         oa = (object[])a;
479                 } catch {
480                         ok = false;
481                 }
482                 if (!ok)
483                         return 7;
484         
485                 try {
486                         ok = true;
487                         oa = (Enum[])a;
488                 } catch {
489                         ok = false;
490                 }
491                 if (!ok)
492                         return 8;
493         
494                 try {
495                         ok = true;
496                         oa = (ValueType[])a;
497                 } catch {
498                         ok = false;
499                 }
500                 if (!ok)
501                         return 9;
502
503                 a = vta;
504                 try {
505                         ok = true;
506                         oa = (object[])a;
507                 } catch {
508                         ok = false;
509                 }
510                 if (!ok)
511                         return 10;
512         
513                 try {
514                         ok = true;
515                         oa = (ValueType[])a;
516                 } catch {
517                         ok = false;
518                 }
519                 if (!ok)
520                         return 11;
521         
522                 try {
523                         ok = false;
524                         vta = (Enum[])a;
525                 } catch {
526                         ok = true;
527                 }
528                 if (!ok)
529                         return 12;
530                 return 0;
531         }
532
533         static int test_0_cast_iface_array () {
534                 object o = new ICloneable [0];
535                 object o2 = new Duper [0];
536                 object t;
537                 bool ok;
538
539                 if (!(o is object[]))
540                         return 1;
541                 if (!(o2 is ICloneable[]))
542                         return 2;
543
544                 try {
545                         ok = true;
546                         t = (object[])o;
547                 } catch {
548                         ok = false;
549                 }
550                 if (!ok)
551                         return 3;
552         
553                 try {
554                         ok = true;
555                         t = (ICloneable[])o2;
556                 } catch {
557                         ok = false;
558                 }
559                 if (!ok)
560                         return 4;
561
562                 try {
563                         ok = true;
564                         t = (ICloneable[])o;
565                 } catch {
566                         ok = false;
567                 }
568                 if (!ok)
569                         return 5;
570
571                 if (!(o is ICloneable[]))
572                         return 6;
573
574                 /* add tests for interfaces that 'inherit' interfaces */
575                 return 0;
576         }
577
578         private static int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
579
580         private static int AbsoluteDays (int year, int month, int day)
581         {
582                 int temp = 0, m = 1;
583                 int[] days = daysmonthleap;
584                 while (m < month)
585                         temp += days[m++];
586                 return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));
587         }
588
589         static int test_719162_complex_div () {
590                 int adays = AbsoluteDays (1970, 1, 1);
591                 return adays;
592         }
593
594         delegate int GetIntDel ();
595
596         static int return4 () {
597                 return 4;
598         }
599
600         int return5 () {
601                 return 5;
602         }
603
604         static int test_2_static_delegate () {
605                 GetIntDel del = new GetIntDel (return4);
606                 int v = del ();
607                 if (v != 4)
608                         return 0;
609                 return 2;
610         }
611
612         static int test_2_instance_delegate () {
613                 Tests t = new Tests ();
614                 GetIntDel del = new GetIntDel (t.return5);
615                 int v = del ();
616                 if (v != 5)
617                         return 0;
618                 return 2;
619         }
620
621         static int test_1_store_decimal () {
622                 decimal[,] a = {{1}};
623
624                 if (a[0,0] != 1m)
625                         return 0;
626                 return 1;
627         }
628
629         static int test_2_intptr_stobj () {
630                 System.IntPtr [] arr = { new System.IntPtr () };
631
632                 if (arr [0] != (System.IntPtr)0)
633                         return 1;
634                 return 2;
635         }
636
637         static int llmult (int a, int b, int c, int d) {
638                 return a + b + c + d;
639         }
640
641         /* 
642          * Test that evaluation of complex arguments does not overwrite the
643          * arguments already in outgoing registers.
644          */
645         static int test_155_regalloc () {
646                 int a = 10;
647                 int b = 10;
648
649                 int c = 0;
650                 int d = 0;
651                 int[] arr = new int [5];
652
653                 return llmult (arr [c + d], 150, 5, 0);
654         }
655
656 }
657