2008-03-14 Mark Probst <mark.probst@gmail.com>
[mono.git] / mono / tests / generics-sharing.2.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Reflection;
4
5 namespace GenericSharingTest {
6
7 public delegate int IntVoidDelegate ();
8
9 public class ClassA {}
10 public class ClassB {}
11 public class ClassC {}
12
13 public class GenExc<T> : Exception {}
14
15 public class NonGen {
16         public static int field = 123;
17
18         public static void doThrow () {
19                 throw new GenExc<ClassA> ();
20         }
21 }
22
23 public class GenBi<S,T> {
24         public static int field = 123;
25         public static float floatField = 1.0f;
26
27         public static int staticMethod (int x) {
28                 return x + field;
29         }
30
31         public static void staticVoidMethod (int x) {
32                 field = x;
33         }
34
35         public static float staticFloatMethod () {
36                 return floatField;
37         }
38
39         public static long staticLongMethod (long x) {
40                 return x + field;
41         }
42
43         public static GenStruct<T> staticValueMethod (int x) {
44                 return new GenStruct<T> (x);
45         }
46 }
47
48 public struct GenStruct<T> {
49         public int field;
50         public int dummy1;
51         public int dummy2;
52         public int dummy3;
53
54         public GenStruct (int f) {
55                 field = f;
56                 dummy1 = dummy2 = dummy3 = 0;
57         }
58
59         public int method (int x) {
60                 return x + field;
61         }
62 }
63
64 public class GenA<T> {
65         public static T[] arr;
66
67         public static GenA () {
68                 arr = new T [3];
69         }
70
71         public GenA () {}
72
73         public GenA<T> newGen () {
74                 return new GenA<T> ();
75         }
76
77         public GenA<int> newGenInt () {
78                 return new GenA<int> ();
79         }
80
81         public int getGenField () {
82                 return GenB<ClassA>.field;
83         }
84
85         public int getNonGenField () {
86                 return NonGen.field;
87         }
88
89         public T[] getArr () {
90                 return arr;
91         }
92
93         public T[] newArr () {
94                 return new T [3];
95         }
96
97         public GenA<T>[] newSelfArr () {
98                 return new GenA<T> [3];
99         }
100
101         public GenB<GenB<T>>[] newArrNested () {
102                 /*
103                 GenB<GenB<T>>[] arr = null;
104                 for (int i = 0; i < 10000000; ++i)
105                         arr = new GenB<GenB<T>> [3];
106                 */
107                 return new GenB<GenB<T>> [3];
108         }
109
110         public int hash (T obj) {
111                 return obj.GetHashCode ();
112         }
113
114         public T ident (T obj) {
115                 return obj;
116         }
117
118         public T cast (Object obj) {
119                 return (T)obj;
120         }
121
122         public void except () {
123                 try {
124                         NonGen.doThrow ();
125                 }
126                 catch (GenExc<T>) {
127                         //Console.WriteLine("exception thrown");
128                 }
129         }
130
131         public static void staticExcept () {
132                 try {
133                         NonGen.doThrow ();
134                 }
135                 catch (GenExc<T>) {
136                         Console.WriteLine("exception thrown and caught");
137                 }
138         }
139
140         public static int staticField = 54321;
141
142         public static int staticMethod () {
143                 return staticField;
144         }
145
146         public static int staticMethodCaller () {
147                 return staticMethod ();
148         }
149
150         public static float staticFloatField = 1.0f;
151
152         public static float staticFloatMethod () {
153                 return staticFloatField;
154         }
155
156         public static int staticBiCaller (int x) {
157                 return GenBi<int,T>.staticMethod (x);
158         }
159
160         public static void staticBiVoidCaller (int x) {
161                 GenBi<int,T>.staticVoidMethod (x);
162         }
163
164         public static float staticBiFloatCaller () {
165                 return GenBi<int,T>.staticFloatMethod ();
166         }
167
168         public static GenStruct<T> staticBiValueCaller (int x) {
169                 return GenBi<int,T>.staticValueMethod (x);
170         }
171
172         public static int staticSharedBiCaller (int x) {
173                 return GenBi<T,T>.staticMethod (x);
174         }
175
176         public static void staticSharedBiVoidCaller (int x) {
177                 GenBi<T,T>.staticVoidMethod (x);
178         }
179
180         public static float staticSharedBiFloatCaller () {
181                 return GenBi<T,T>.staticFloatMethod ();
182         }
183
184         public static GenStruct<T> staticSharedBiValueCaller (int x) {
185                 return GenBi<T,T>.staticValueMethod (x);
186         }
187
188         public static long staticBiLongCaller (long x) {
189                 return GenBi<int, T>.staticLongMethod (x);
190         }
191 }
192
193 public class GenB<T> {
194         public static int field = 123;
195 }
196
197 public class GenC<T> {
198         public static int field ;
199
200         public static GenC () {
201                 field = 1234;
202         }
203 }
204
205 public class StaticTest<T> {
206         static int stat;
207
208         public StaticTest (int x) {
209                 stat = x;
210         }
211
212         public int getStat () {
213                 return stat;
214         }
215
216         public int getOtherStat () {
217                 return StaticTest<Object>.stat;
218         }
219
220         public int getGenCStat () {
221                 return GenC<T>.field;
222         }
223 }
224
225 public class GenADeriv<T> : GenA<T> {
226         public static int otherField = 123;
227 }
228
229 public class GenABDeriv<T> : GenA<GenB<T>> {
230         public T[] newDerivArr () {
231                 return new T [3];
232         }
233 }
234
235 public class NonGenUser<T> where T : NonGen {
236         public int getNonGenField () {
237                 return T.field;
238         }
239 }
240
241 public class AccessTest<T> {
242         private static int field = 123;
243
244         public int getOtherField () {
245                 return AccessTest<int>.field;
246         }
247 }
248
249 public class VirtualTest<T> {
250         public virtual T[] newArr () {
251                 return new T [3];
252         }
253 }
254
255 public class VirtualTestDeriv<T> : VirtualTest<T> {
256         public override T[] newArr () {
257                 return new T [4];
258         }
259 }
260
261 public class VirtualTestCaller<T> {
262         public T[] doCall (VirtualTest<T> vt) {
263                 return vt.newArr ();
264         }
265 }
266
267 public class MyCons<T> {
268         public T car;
269         public MyCons<T> cdr;
270
271         public static void printCar (T _car) {
272                 Console.WriteLine ("car " + _car.ToString () /* + " cdr " + _cdr.ToString () */);
273         }
274
275         public MyCons (T _car, MyCons<T> _cdr) {
276                 //printCar (_car);
277                 car = _car; cdr = _cdr;
278         }
279
280         public static MyCons<T> returnList (MyCons<T> l) { return l; }
281
282         public static MyCons<T> returnCdr (MyCons<T> cons) { return returnList(cons.cdr); }
283 }
284
285 public class MyPair<N,M> {
286         public N n;
287         public M m;
288
289         public MyPair (N _n, M _m) { n = _n; m = _m; }
290 }
291
292 public class MyDict<N,M> {
293         public MyPair<N,M> p;
294
295         public MyDict (N n, M m) { p = new MyPair<N,M> (n, m); }
296 }
297
298 public class RGCTXTest<T> {
299         public GenA<T>[] newAArr () {
300                 return new GenA<T> [3];
301         }
302 }
303
304 public class RGCTXTestSubA<T> : RGCTXTest<T> {
305         public GenB<T>[] newBArr () {
306                 return new GenB<T> [3];
307         }
308 }
309
310 public class RGCTXTestSubB<T> : RGCTXTest<T> {
311         public GenC<T>[] newCArr () {
312                 return new GenC<T> [3];
313         }
314 }
315
316 public class RGCTXTestSubASub : RGCTXTestSubA<ClassA> {
317 }
318
319 public class RGCTXTestSubASubSub<T> : RGCTXTestSubASub {
320         public GenC<T>[] newCArr () {
321                 return new GenC<T> [3];
322         }
323 }
324
325 public class main {
326         static bool haveError = false;
327
328         public static void error (string message) {
329                 haveError = true;
330                 Console.WriteLine (message);
331         }
332
333         public static void typeCheck (String method, Object obj, Type t) {
334                 if (obj.GetType () != t)
335                         error ("object from " + method + " should have type " + t.ToString () + " but has type " + obj.GetType ().ToString ());
336         }
337
338         public static int callStaticMethod<T> () {
339                 return GenA<T>.staticMethod ();
340         }
341
342         public static void work<T> (T obj, bool mustCatch) {
343                 EqualityComparer<T> comp = EqualityComparer<T>.Default;
344
345                 GenA<T> ga = new GenA<T> ();
346
347                 typeCheck ("newGen", ga.newGen (), typeof (GenA<T>));
348                 typeCheck ("newGenInt", ga.newGenInt (), typeof (GenA<int>));
349                 typeCheck ("getArr", ga.getArr (), typeof (T[]));
350                 typeCheck ("newArr", ga.newArr (), typeof (T[]));
351                 typeCheck ("newSelfArr", ga.newSelfArr (), typeof (GenA<T>[]));
352                 //ga.newArrNested ();
353                 typeCheck ("newArrNested", ga.newArrNested (), typeof (GenB<GenB<T>>[]));
354
355                 if (ga.getGenField () != 123)
356                         error ("getGenField");
357
358                 if (ga.getNonGenField () != 123)
359                         error ("getNonGenField");
360
361                 ga.hash (obj);
362
363                 if (!comp.Equals (ga.ident (obj), obj))
364                         error ("ident");
365
366                 if (!comp.Equals (ga.cast (obj), obj))
367                         error ("cast");
368
369                 if (callStaticMethod<T> () != 54321)
370                         error ("staticMethod");
371
372                 GenBi<int,T>.field = 123;
373                 if (GenA<T>.staticBiCaller (123) != 246)
374                         error ("staticBiCaller");
375                 GenA<T>.staticBiVoidCaller (1234);
376                 if (GenBi<int,T>.field != 1234)
377                         error ("staticBiVoidCaller");
378                 if (GenA<T>.staticBiFloatCaller () != 1.0f)
379                         error ("staticBiFloatCaller");
380                 if (GenA<T>.staticBiLongCaller (123) != 123 + 1234)
381                         error ("staticBiLongCaller");
382                 GenStruct<T> gs = GenA<T>.staticBiValueCaller (987);
383                 if (gs.field != 987)
384                         error ("staticBiValueCaller");
385
386                 GenBi<T,T>.field = 123;
387                 if (GenA<T>.staticSharedBiCaller (123) != 246)
388                         error ("staticSharedBiCaller");
389                 GenA<T>.staticSharedBiVoidCaller (1234);
390                 if (GenBi<T,T>.field != 1234)
391                         error ("staticSharedBiVoidCaller");
392                 if (GenA<T>.staticSharedBiFloatCaller () != 1.0f)
393                         error ("staticSharedBiFloatCaller");
394                 GenStruct<T> gss = GenA<T>.staticSharedBiValueCaller (987);
395                 if (gss.field != 987)
396                         error ("staticSharedBiValueCaller");
397
398                 IntVoidDelegate ivdel = new IntVoidDelegate (GenA<T>.staticMethod);
399                 if (ivdel () != 54321)
400                         error ("staticMethod delegate");
401
402                 Type gatype = typeof (GenA<T>);
403                 MethodInfo staticMethodInfo = gatype.GetMethod ("staticMethod");
404                 if ((Convert.ToInt32 (staticMethodInfo.Invoke (null, null))) != 54321)
405                         error ("staticMethod reflection");
406
407                 if (GenA<T>.staticMethodCaller () != 54321)
408                         error ("staticMethodCaller");
409
410                 if (GenA<T>.staticFloatMethod () != 1.0)
411                         error ("staticFloatMethod");
412
413                 new GenADeriv<T> ();
414
415                 if (mustCatch) {
416                         bool didCatch = false;
417
418                         try {
419                                 ga.except ();
420                         } catch (GenExc<ClassA>) {
421                                 didCatch = true;
422                         }
423                         if (!didCatch)
424                                 error ("except");
425
426                         didCatch = false;
427
428                         try {
429                                 GenA<T>.staticExcept ();
430                         } catch (GenExc<ClassA>) {
431                                 didCatch = true;
432                         }
433                         if (!didCatch)
434                                 error ("staticExcept");
435                 } else {
436                         ga.except ();
437                         GenA<T>.staticExcept ();
438                 }
439
440                 MyDict<T, ClassB> dtb = new MyDict<T, ClassB> (obj, new ClassB ());
441
442                 typeCheck ("MyPair", dtb.p, typeof (MyPair<T, ClassB>));
443
444                 GenABDeriv<T> gabd = new GenABDeriv<T> ();
445
446                 typeCheck ("GenABDeriv.newArr", gabd.newArr (), typeof (GenB<T>[]));
447                 typeCheck ("GenABDeriv.newDerivArr", gabd.newDerivArr (), typeof (T[]));
448
449                 RGCTXTest<T> rt = new RGCTXTest<T> ();
450                 RGCTXTestSubA<T> rtsa = new RGCTXTestSubA<T> ();
451                 RGCTXTestSubB<T> rtsb = new RGCTXTestSubB<T> ();
452                 RGCTXTestSubASub rtsas = new RGCTXTestSubASub ();
453                 RGCTXTestSubASubSub<T> rtsass = new RGCTXTestSubASubSub<T> ();
454
455                 typeCheck ("rtsass.newCArr", rtsass.newCArr (), typeof (GenC<T>[]));
456                 typeCheck ("rgsa.newBArr", rtsa.newBArr (), typeof (GenB<T>[]));
457                 typeCheck ("rg.newAArr", rt.newAArr (), typeof (GenA<T>[]));
458                 typeCheck ("rgsb.newCArr", rtsb.newCArr (), typeof (GenC<T>[]));
459
460                 /* repeat all for each class */
461                 typeCheck ("rtsass.newCArr", rtsass.newCArr (), typeof (GenC<T>[]));
462                 typeCheck ("rtsass.newBArr", rtsass.newBArr (), typeof (GenB<ClassA>[]));
463                 typeCheck ("rtsass.newAArr", rtsass.newAArr (), typeof (GenA<ClassA>[]));
464
465                 typeCheck ("rtsas.newBArr", rtsas.newBArr (), typeof (GenB<ClassA>[]));
466                 typeCheck ("rtsas.newAArr", rtsas.newAArr (), typeof (GenA<ClassA>[]));
467
468                 typeCheck ("rtsa.newBArr", rtsa.newBArr (), typeof (GenB<T>[]));
469                 typeCheck ("rtsa.newAArr", rtsa.newAArr (), typeof (GenA<T>[]));
470
471                 typeCheck ("rtsb.newCArr", rtsb.newCArr (), typeof (GenC<T>[]));
472                 typeCheck ("rtsb.newAArr", rtsb.newAArr (), typeof (GenA<T>[]));
473
474                 typeCheck ("rt.newAArr", rt.newAArr (), typeof (GenA<T>[]));
475         }
476
477         public static void virtualTest<T> (VirtualTest<T> vt, int len) {
478                 VirtualTestCaller<T> vtc = new VirtualTestCaller<T> ();
479                 T[] arr = vtc.doCall (vt);
480
481                 typeCheck ("virtualTest", arr, typeof (T[]));
482
483                 if (arr.Length != len)
484                         error ("virtualTest length");
485         }
486
487         public static void listTest () {
488                 MyCons<string> ls = new MyCons<string> ("abc", null);
489                 MyCons<string> cdr = MyCons<string>.returnCdr (ls);
490
491                 if (cdr != null)
492                         error ("cdr is not null");
493         }
494
495         public static int Main ()
496         {
497                 work<ClassA> (new ClassA (), false);
498                 work<ClassB> (new ClassB (), true);
499                 work<ClassC> (new ClassC (), true);
500                 work<GenA<ClassA>> (new GenA<ClassA> (), true);
501                 work<int[]> (new int[3], true);
502                 work<int> (123, true);
503
504                 StaticTest<ClassA> sa = new StaticTest<ClassA> (1234);
505                 StaticTest<ClassB> sb = new StaticTest<ClassB> (2345);
506
507                 if (sa.getStat () != 1234)
508                         error ("getStat");
509                 if (sb.getStat () != 2345)
510                         error ("getStat");
511                 if (sa.getOtherStat () != 0)
512                         error ("getOtherStat");
513                 if (sa.getGenCStat () != 1234)
514                         error ("getGenCStat A");
515                 if (sb.getGenCStat () != 1234)
516                         error ("getGenCStat B");
517
518                 NonGenUser<NonGen> ngu = new NonGenUser<NonGen> ();
519
520                 if (ngu.getNonGenField () != 123)
521                         error ("getNonGenField");
522
523                 AccessTest<ClassA> ata = new AccessTest<ClassA> ();
524
525                 if (ata.getOtherField () != 123)
526                         error ("getOtherField");
527
528                 VirtualTest<ClassA> vta = new VirtualTest<ClassA> ();
529                 VirtualTest<ClassB> vtb = new VirtualTestDeriv<ClassB> ();
530
531                 virtualTest<ClassA> (vta, 3);
532                 virtualTest<ClassB> (vtb, 4);
533
534                 listTest ();
535
536                 if (haveError)
537                         return 1;
538                 return 0;
539         }
540 }
541
542 }