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