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