Thu Sep 8 11:28:45 BST 2005 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 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(10001) ] public sbyte sb;
80                 [ FieldOffset(11000) ] public short s;
81                 [ FieldOffset(11002) ] public ushort us;
82                 [ FieldOffset(12000) ] public uint i;
83                 [ FieldOffset(12004) ] public int si;
84                 [ FieldOffset(13000) ] public long l;
85                 [ FieldOffset(14000) ] public float f;
86                 [ FieldOffset(15000) ] public double d;
87 }
88
89 enum SampleEnum {
90         A,
91         B,
92         C
93 }
94
95 class Tests {
96
97         static int Main () {
98                 return TestDriver.RunTests (typeof (Tests));
99         }
100         
101         static int test_0_return () {
102                 Simple s;
103                 s.a = 1;
104                 s.b = 2;
105                 s.c = (short)(s.a + s.b);
106                 s.d = 4;
107                 return s.a - 1;
108         }
109
110         static int test_0_string_access () {
111                 string s = "Hello";
112                 if (s [1] != 'e')
113                         return 1;
114                 return 0;
115         }
116
117         static int test_0_string_virtual_call () {
118                 string s = "Hello";
119                 string s2 = s.ToString ();
120                 if (s2 [1] != 'e')
121                         return 1;
122                 return 0;
123         }
124
125         static int test_0_iface_call () {
126                 string s = "Hello";
127                 object o = ((ICloneable)s).Clone ();
128                 return 0;
129         }
130
131         static int test_5_newobj () {
132                 Sample s = new Sample (5);
133                 return s.a;
134         }
135
136         static int test_4_box () {
137                 object obj = 4;
138                 return (int)obj;
139         }
140
141         static int test_0_enum_unbox () {
142                 SampleEnum x = SampleEnum.A;
143                 object o = x;
144                 
145                 int res = 1;
146
147                 res = (int)o;
148                 
149                 return res;
150         }
151         
152         static Simple get_simple (int v) {
153                 Simple r = new Simple ();
154                 r.a = v;
155                 r.b = (byte)(v + 1);
156                 r.c = (short)(v + 2);
157                 r.d = v + 3;
158
159                 return r;
160         }
161
162         static int test_3_return_struct () {
163                 Simple v = get_simple (1);
164
165                 if (v.a != 1)
166                         return 0;
167                 if (v.b != 2)
168                         return 0;
169                 if (v.c != 3)
170                         return 0;
171                 if (v.d != 4)
172                         return 0;
173                 return 3;
174         }
175
176         public virtual Simple v_get_simple (int v)
177         {
178                 return get_simple (v);
179         }
180         
181         static int test_2_return_struct_virtual () {
182                 Tests t = new Tests ();
183                 Simple v = t.v_get_simple (2);
184
185                 if (v.a != 2)
186                         return 0;
187                 if (v.b != 3)
188                         return 0;
189                 if (v.c != 4)
190                         return 0;
191                 if (v.d != 5)
192                         return 0;
193                 return 2;
194         }
195
196         static int receive_simple (int a, Simple v, int b) {
197                 if (v.a != 1)
198                         return 1;
199                 if (v.b != 2)
200                         return 2;
201                 if (v.c != 3)
202                         return 3;
203                 if (v.d != 4)
204                         return 4;
205                 if (a != 7)
206                         return 5;
207                 if (b != 9)
208                         return 6;
209                 return 0;
210         }
211         
212         static int test_5_pass_struct () {
213                 Simple v = get_simple (1);
214                 if (receive_simple (7, v, 9) != 0)
215                         return 0;
216                 if (receive_simple (7, get_simple (1), 9) != 0)
217                         return 1;
218                 return 5;
219         }
220
221         // Test alignment of small structs
222
223         static Small get_small (byte v) {
224                 Small r = new Small ();
225         
226                 r.b1 = v;
227                 r.b2 = (byte)(v + 1);
228
229                 return r;
230         }
231
232         static Small return_small (Small s) {
233                 return s;
234         }
235
236         static int receive_small (int a, Small v, int b) {
237                 if (v.b1 != 1)
238                         return 1;
239                 if (v.b2 != 2)
240                         return 2;
241                 return 0;
242         }
243
244         static int test_5_pass_small_struct () {
245                 Small v = get_small (1);
246                 if (receive_small (7, v, 9) != 0)
247                         return 0;
248                 if (receive_small (7, get_small (1), 9) != 0)
249                         return 1;
250                 v = return_small (v);
251                 if (v.b1 != 1)
252                         return 2;
253                 if (v.b2 != 2)
254                         return 3;
255                 return 5;
256         }
257
258         struct AStruct {
259                 public int i;
260
261                 public AStruct (int i) {
262                         this.i = i;
263                 }
264
265                 public override int GetHashCode () {
266                         return i;
267                 }
268         }
269
270         // Test that vtypes are unboxed during a virtual call
271         static int test_44_unbox_trampoline () {
272                 AStruct s = new AStruct (44);
273                 object o = s;
274                 return o.GetHashCode ();
275         }
276
277         static int test_0_unbox_trampoline2 () {
278                 int i = 12;
279                 object o = i;
280                         
281                 if (i.ToString () != "12")
282                         return 1;
283                 if (((Int32)o).ToString () != "12")
284                         return 2;
285                 if (o.ToString () != "12")
286                         return 3;
287                 return 0;
288         }
289
290         // Test fields with big offsets
291         static int test_0_fields_with_big_offsets () {
292                 StructWithBigOffsets s = new StructWithBigOffsets ();
293                 StructWithBigOffsets s2 = new StructWithBigOffsets ();
294
295                 s.b = 0xde;
296                 s.sb = 0xe;
297                 s.s = 0x12de;
298                 s.us = 0x12da;
299                 s.i = 0xdeadbeef;
300                 s.si = 0xcafe;
301                 s.l = 0xcafebabe;
302                 s.f = 3.14F;
303                 s.d = 3.14;
304
305                 s2.b = s.b;
306                 s2.sb = s.sb;
307                 s2.s = s.s;
308                 s2.us = s.us;
309                 s2.i = s.i;
310                 s2.si = s.si;
311                 s2.l = s.l;
312                 s2.f = s.f;
313                 s2.d = s.d;
314
315                 if (s2.b != 0xde)
316                         return 1;
317                 if (s2.s != 0x12de)
318                         return 2;
319                 if (s2.i != 0xdeadbeef)
320                         return 3;
321                 if (s2.l != 0xcafebabe)
322                         return 4;
323                 if (s2.f != 3.14F)
324                         return 5;
325                 if (s2.d != 3.14)
326                         return 6;
327                 if (s2.sb != 0xe)
328                         return 7;
329                 if (s2.us != 0x12da)
330                         return 9;
331                 if (s2.si != 0xdeadcafe)
332                         return 10;
333
334                 return 0;
335         }
336
337         class TestRegA {
338
339                 long buf_start;
340                 int buf_length, buf_offset;
341
342                 public TestRegA () {
343                         buf_start = 0;
344                         buf_length = 0;
345                         buf_offset = 0;
346                 }
347         
348                 public long Seek (long position) {
349                         long pos = position;
350                         /* interaction between the register allocator and
351                          * allocating arguments to registers */
352                         if (pos >= buf_start && pos <= buf_start + buf_length) {
353                                 buf_offset = (int) (pos - buf_start);
354                                 return pos;
355                         }
356                         return buf_start;
357                 }
358
359         }
360
361         static int test_0_seektest () {
362                 TestRegA t = new TestRegA ();
363                 return (int)t.Seek (0);
364         }
365
366         class Super : ICloneable {
367                 public virtual object Clone () {
368                         return null;
369                 }
370         }
371         class Duper: Super {
372         }
373
374         static int test_0_null_cast () {
375                 object o = null;
376
377                 Super s = (Super)o;
378
379                 return 0;
380         }
381         
382         static int test_0_super_cast () {
383                 Duper d = new Duper ();
384                 Super sup = d;
385                 Object o = d;
386
387                 if (!(o is Super))
388                         return 1;
389                 try {
390                         d = (Duper)sup;
391                 } catch {
392                         return 2;
393                 }
394                 if (!(d is Object))
395                         return 3;
396                 try {
397                         d = (Duper)(object)sup;
398                 } catch {
399                         return 4;
400                 }
401                 return 0;
402         }
403
404         static int test_0_super_cast_array () {
405                 Duper[] d = new Duper [0];
406                 Super[] sup = d;
407                 Object[] o = d;
408
409                 if (!(o is Super[]))
410                         return 1;
411                 try {
412                         d = (Duper[])sup;
413                 } catch {
414                         return 2;
415                 }
416                 if (!(d is Object[]))
417                         return 3;
418                 try {
419                         d = (Duper[])(object[])sup;
420                 } catch {
421                         return 4;
422                 }
423                 return 0;
424         }
425
426         static int test_0_multi_array_cast () {
427                 Duper[,] d = new Duper [1, 1];
428                 object[,] o = d;
429
430                 try {
431                         o [0, 0] = new Super ();
432                         return 1;
433                 }
434                 catch (ArrayTypeMismatchException) {
435                 }
436
437                 return 0;
438         }
439
440         static int test_0_vector_array_cast () {
441                 Array arr1 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {0});
442                 Array arr2 = Array.CreateInstance (typeof (int), new int[] {1}, new int[] {10});
443
444                 if (arr1.GetType () != typeof (int[]))
445                         return 1;
446
447                 if (arr2.GetType () == typeof (int[]))
448                         return 2;
449
450                 int[] b;
451
452                 b = (int[])arr1;
453
454                 try {
455                         b = (int[])arr2;
456                         return 3;
457                 }
458                 catch (InvalidCastException) {
459                 }
460
461                 if (arr2 is int[])
462                         return 4;
463
464                 return 0;
465         }
466
467         static int test_0_enum_array_cast () {
468                 TypeCode[] tc = new TypeCode [0];
469                 object[] oa;
470                 ValueType[] vta;
471                 int[] inta;
472                 Array a = tc;
473                 bool ok;
474
475                 if (a is object[])
476                         return 1;
477                 if (a is ValueType[])
478                         return 2;
479                 if (a is Enum[])
480                         return 3;
481                 try {
482                         ok = false;
483                         oa = (object[])a;
484                 } catch {
485                         ok = true;
486                 }
487                 if (!ok)
488                         return 4;
489                 try {
490                         ok = false;
491                         vta = (ValueType[])a;
492                 } catch {
493                         ok = true;
494                 }
495                 if (!ok)
496                         return 5;
497                 try {
498                         ok = true;
499                         inta = (int[])a;
500                 } catch {
501                         ok = false;
502                 }
503                 if (!ok)
504                         return 6;
505                 return 0;
506         }
507
508         static int test_0_more_cast_corner_cases () {
509                 ValueType[] vta = new ValueType [0];
510                 Enum[] ea = new Enum [0];
511                 Array a = vta;
512                 object[] oa;
513                 bool ok;
514
515                 if (!(a is object[]))
516                         return 1;
517                 if (!(a is ValueType[]))
518                         return 2;
519                 if (a is Enum[])
520                         return 3;
521                 a = ea;
522                 if (!(a is object[]))
523                         return 4;
524                 if (!(a is ValueType[]))
525                         return 5;
526                 if (!(a is Enum[]))
527                         return 6;
528
529                 try {
530                         ok = true;
531                         oa = (object[])a;
532                 } catch {
533                         ok = false;
534                 }
535                 if (!ok)
536                         return 7;
537         
538                 try {
539                         ok = true;
540                         oa = (Enum[])a;
541                 } catch {
542                         ok = false;
543                 }
544                 if (!ok)
545                         return 8;
546         
547                 try {
548                         ok = true;
549                         oa = (ValueType[])a;
550                 } catch {
551                         ok = false;
552                 }
553                 if (!ok)
554                         return 9;
555
556                 a = vta;
557                 try {
558                         ok = true;
559                         oa = (object[])a;
560                 } catch {
561                         ok = false;
562                 }
563                 if (!ok)
564                         return 10;
565         
566                 try {
567                         ok = true;
568                         oa = (ValueType[])a;
569                 } catch {
570                         ok = false;
571                 }
572                 if (!ok)
573                         return 11;
574         
575                 try {
576                         ok = false;
577                         vta = (Enum[])a;
578                 } catch {
579                         ok = true;
580                 }
581                 if (!ok)
582                         return 12;
583                 return 0;
584         }
585
586         static int test_0_cast_iface_array () {
587                 object o = new ICloneable [0];
588                 object o2 = new Duper [0];
589                 object t;
590                 bool ok;
591
592                 if (!(o is object[]))
593                         return 1;
594                 if (!(o2 is ICloneable[]))
595                         return 2;
596
597                 try {
598                         ok = true;
599                         t = (object[])o;
600                 } catch {
601                         ok = false;
602                 }
603                 if (!ok)
604                         return 3;
605         
606                 try {
607                         ok = true;
608                         t = (ICloneable[])o2;
609                 } catch {
610                         ok = false;
611                 }
612                 if (!ok)
613                         return 4;
614
615                 try {
616                         ok = true;
617                         t = (ICloneable[])o;
618                 } catch {
619                         ok = false;
620                 }
621                 if (!ok)
622                         return 5;
623
624                 if (!(o is ICloneable[]))
625                         return 6;
626
627                 /* add tests for interfaces that 'inherit' interfaces */
628                 return 0;
629         }
630
631         private static int[] daysmonthleap = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
632
633         private static int AbsoluteDays (int year, int month, int day)
634         {
635                 int temp = 0, m = 1;
636                 int[] days = daysmonthleap;
637                 while (m < month)
638                         temp += days[m++];
639                 return ((day-1) + temp + (365* (year-1)) + ((year-1)/4) - ((year-1)/100) + ((year-1)/400));
640         }
641
642         static int test_719162_complex_div () {
643                 int adays = AbsoluteDays (1970, 1, 1);
644                 return adays;
645         }
646
647         delegate int GetIntDel ();
648
649         static int return4 () {
650                 return 4;
651         }
652
653         int return5 () {
654                 return 5;
655         }
656
657         static int test_2_static_delegate () {
658                 GetIntDel del = new GetIntDel (return4);
659                 int v = del ();
660                 if (v != 4)
661                         return 0;
662                 return 2;
663         }
664
665         static int test_2_instance_delegate () {
666                 Tests t = new Tests ();
667                 GetIntDel del = new GetIntDel (t.return5);
668                 int v = del ();
669                 if (v != 5)
670                         return 0;
671                 return 2;
672         }
673
674         static int test_1_store_decimal () {
675                 decimal[,] a = {{1}};
676
677                 if (a[0,0] != 1m)
678                         return 0;
679                 return 1;
680         }
681
682         static int test_2_intptr_stobj () {
683                 System.IntPtr [] arr = { new System.IntPtr () };
684
685                 if (arr [0] != (System.IntPtr)0)
686                         return 1;
687                 return 2;
688         }
689
690         static int llmult (int a, int b, int c, int d) {
691                 return a + b + c + d;
692         }
693
694         /* 
695          * Test that evaluation of complex arguments does not overwrite the
696          * arguments already in outgoing registers.
697          */
698         static int test_155_regalloc () {
699                 int a = 10;
700                 int b = 10;
701
702                 int c = 0;
703                 int d = 0;
704                 int[] arr = new int [5];
705
706                 return llmult (arr [c + d], 150, 5, 0);
707         }
708
709         static bool large_struct_test (Large a, Large b, Large c, Large d)
710         {
711                 if (!a.check ()) return false;
712                 if (!b.check ()) return false;
713                 if (!c.check ()) return false;
714                 if (!d.check ()) return false;
715                 return true;
716         }
717
718         static int test_2_large_struct_pass ()
719         {
720                 Large a, b, c, d;
721                 a = new Large ();
722                 b = new Large ();
723                 c = new Large ();
724                 d = new Large ();
725                 a.populate ();
726                 b.populate ();
727                 c.populate ();
728                 d.populate ();
729                 if (large_struct_test (a, b, c, d))
730                         return 2;
731                 return 0;
732         }
733
734         public static unsafe int test_0_pin_string () {
735                 string x = "xxx";
736                 fixed (char *c = x) {
737                         if (*c != 'x')
738                                 return 1;
739                 }
740                 return 0;
741         }
742         
743         public static int my_flags;
744         public static int test_0_and_cmp_static ()
745         {
746                 
747                 /* various forms of test [mem], imm */
748                 
749                 my_flags = 0x01020304;
750                 
751                 if ((my_flags & 0x01020304) == 0)
752                         return 1;
753                 
754                 if ((my_flags & 0x00000304) == 0)
755                         return 2;
756                 
757                 if ((my_flags & 0x00000004) == 0)
758                         return 3;
759                 
760                 if ((my_flags & 0x00000300) == 0)
761                         return 4;
762                 
763                 if ((my_flags & 0x00020000) == 0)
764                         return 5;
765                 
766                 if ((my_flags & 0x01000000) == 0)
767                         return 6;
768                 
769                 return 0;
770         }
771         
772         static byte b;
773         public static int test_0_byte_compares ()
774         {
775                 b = 0xff;
776                 if (b == -1)
777                         return 1;
778                 b = 0;
779                 if (!(b < System.Byte.MaxValue))
780                         return 2;
781                 
782                 if (!(b <= System.Byte.MaxValue))
783                         return 3;
784                 
785                 return 0;
786         }
787
788         public static int test_71_long_shift_right () {
789                 ulong value = 38654838087;
790                 int x = 0;
791                 byte [] buffer = new byte [1];
792                 buffer [x] = ((byte)(value >> x));
793                 return buffer [x];
794         }
795         
796         static long x;
797         public static int test_0_addsub_mem ()
798         {
799                 x = 0;
800                 x += 5;
801                 
802                 if (x != 5)
803                         return 1;
804                 
805                 x -= 10;
806                 
807                 if (x != -5)
808                         return 2;
809                 
810                 return 0;
811         }
812         
813         static ulong y;
814         public static int test_0_sh32_mem ()
815         {
816                 y = 0x0102130405060708;
817                 y >>= 32;
818                 
819                 if (y != 0x01021304)
820                         return 1;
821                 
822                 y = 0x0102130405060708;
823                 y <<= 32;
824                 
825                 if (y != 0x0506070800000000)
826                         return 2;
827                 
828                 x = 0x0102130405060708;
829                 x <<= 32;
830                 
831                 if (x != 0x0506070800000000)
832                         return 2;
833                 
834                 return 0;
835         }
836
837
838         static uint dum_de_dum = 1;
839         static int test_0_long_arg_opt ()
840         {
841                 return Foo (0x1234567887654321, dum_de_dum);
842         }
843         
844         static int Foo (ulong x, ulong y)
845         {
846                 if (x != 0x1234567887654321)
847                         return 1;
848                 
849                 if (y != 1)
850                         return 2;
851                 
852                 return 0;
853         }
854         
855         static int test_0_long_ret_opt ()
856         {
857                 ulong x = X ();
858                 if (x != 0x1234567887654321)
859                         return 1;
860                 ulong y = Y ();
861                 if (y != 1)
862                         return 2;
863                 
864                 return 0;
865         }
866         
867         static ulong X ()
868         {
869                 return 0x1234567887654321;
870         }
871         
872         static ulong Y ()
873         {
874                 return dum_de_dum;
875         }
876
877         /* from bug# 71515 */
878         static int counter = 0;
879         static bool WriteStuff () {
880                 counter = 10;
881                 return true;
882         }
883         static int test_0_cond_branch_side_effects () {
884                 counter = 5;
885                 if (WriteStuff());
886                 if (counter == 10)
887                         return 0;
888                 return 1;
889         }
890
891         // bug #74992
892         public static int arg_only_written (string file_name, int[]
893 ncells ) {
894                 if (file_name == null)
895                         return 1;
896
897                 ncells = foo ();
898                 bar (ncells [0]);
899
900                 return 0;
901         }
902
903         public static int[] foo () {
904                 return new int [3];
905         }
906
907         public static void bar (int i) {
908         }
909         
910
911         public static int test_0_arg_only_written ()
912         {
913                 return arg_only_written ("md.in", null);
914         }               
915 }
916