[runtime] Avoid a crash if a generic type definition is passed to RuntimeHelpers...
[mono.git] / mcs / class / corlib / Test / System.Runtime.CompilerServices / RuntimeHelpersTest.cs
1 //
2 // RuntimeHelpersTest.cs - NUnit Test Cases for the System.Runtime.CompilerServices.RuntimeHelpers class
3 //
4 // Zoltan Varga (vargaz@freemail.hu)
5 //
6 // (C) Ximian, Inc.  http://www.ximian.com
7
8 using System;
9 using System.Runtime.CompilerServices;
10
11 using NUnit.Framework;
12
13 namespace MonoTests.System.Runtime.CompilerServices {
14
15         [TestFixture]
16         public class RuntimeHelpersTest {
17             struct FooStruct {
18                         public int i;
19                         public string j;
20
21                         public override int GetHashCode () {
22                                 return 5;
23                         }
24
25                         public override bool Equals (object o) {
26                                 Assert.Fail ();
27                                 return false;
28                         }
29                 }
30
31                 class FooClass {
32                         public static int counter = 0;
33
34                         static FooClass () {
35                                 counter = counter + 1;
36                         }
37
38                         public override int GetHashCode () {
39                                 return 5;
40                         }
41
42                         public override bool Equals (object o) {
43                                 Assert.Fail ();
44                                 return true;
45                         }
46                 }
47
48                 public void TestOffsetToStringData () 
49                 {
50                         Assert.AreEqual (
51                                                   RuntimeHelpers.OffsetToStringData,
52                                                   RuntimeHelpers.OffsetToStringData, "OffsetToStringData is not constant");
53                 }
54
55                 public void TestGetObjectValue ()
56                 {
57                         FooStruct s1;
58                         FooStruct s2;
59
60                         // Test null
61                         Assert.AreEqual (RuntimeHelpers.GetObjectValue (null),
62                                                   null);
63                         
64                         // Test non-valuetype
65                         Assert.AreEqual (RuntimeHelpers.GetObjectValue (this),
66                                                   this);
67
68                         // Test valuetype
69                         s1.i = 42;
70                         s1.j = "FOO";
71                         s2 = (FooStruct)RuntimeHelpers.GetObjectValue(s1);
72                         s1.i = 43;
73                         s1.j = "BAR";
74                         Assert.AreEqual (s2.i, 42);
75                         Assert.AreEqual (s2.j, "FOO");
76                 }
77
78                 public void TestRunClassConstructor ()
79                 {
80                         RuntimeHelpers.RunClassConstructor (typeof(FooClass).TypeHandle);
81                         Assert.AreEqual (FooClass.counter, 1);
82
83                         // Each static constructor should only be run once
84                         RuntimeHelpers.RunClassConstructor (typeof(FooClass).TypeHandle);
85                         Assert.AreEqual (FooClass.counter, 1);
86                 }
87
88                 [Test]
89                 [ExpectedException (typeof (ArgumentException))]
90                 public void RunClassConstructor_Default ()
91                 {
92                         RuntimeTypeHandle rth = new RuntimeTypeHandle ();
93                         Assert.AreEqual (IntPtr.Zero, rth.Value, "Value");
94                         RuntimeHelpers.RunClassConstructor (rth);
95                 }
96
97                 // Expected the handle here is that way, because we are going to test for an ArgumentException being thrown
98 #pragma warning disable 649
99                 static RuntimeTypeHandle handle;
100 #pragma warning restore 649
101                 [Test]
102                 [ExpectedException (typeof (ArgumentException))]
103                 public void RunClassConstructor_Uninitialized ()
104                 {
105                         RuntimeHelpers.RunClassConstructor (handle);
106                 }
107
108                 class Thrower {
109                         static Thrower ()
110                         {
111                                 throw new NotFiniteNumberException ();
112                         }
113                 }
114
115                 [Test]
116                 [ExpectedException (typeof (TypeInitializationException))]
117                 public void RunClassConstructor_Throw ()
118                 {
119                         RuntimeHelpers.RunClassConstructor (typeof (Thrower).TypeHandle);
120                 }
121
122                 class GClass<T> {
123                         protected T Field;
124                 }
125
126                 [Test]
127                 public void RunClassConstructor_Generic ()
128                 {
129                         RuntimeHelpers.RunClassConstructor (typeof (GClass<>).TypeHandle);
130                 }
131
132                 class Fielder {
133                         public byte [] array = new byte [1];
134                 }
135
136                 static RuntimeFieldHandle rfh = typeof (Fielder).GetField ("array").FieldHandle;
137
138                 // Disable expected warning: the point of the test is to validate that an exception is thrown for something with a null (the default value in this case)
139                 #pragma warning disable  649
140                 static RuntimeFieldHandle static_rfh;
141                 #pragma warning restore 649
142
143                 [Test]
144                 [ExpectedException (typeof (ArgumentNullException))]
145                 public void InitializeArray_Null ()
146                 {
147                         RuntimeHelpers.InitializeArray (null, rfh);
148                 }
149
150                 [Test]
151                 [ExpectedException (typeof (ArgumentNullException))]
152                 public void InitializeArray_Default ()
153                 {
154                         RuntimeFieldHandle h = new RuntimeFieldHandle ();
155                         RuntimeHelpers.InitializeArray (new Fielder ().array, h);
156                 }
157
158                 [Test]
159                 [ExpectedException (typeof (ArgumentNullException))]
160                 public void InitializeArray_Uninitialized ()
161                 {
162                         RuntimeHelpers.InitializeArray (new Fielder ().array, static_rfh);
163                 }
164
165                 [Test]
166                 [ExpectedException (typeof (ArgumentException))]
167                 public void InitializeArray ()
168                 {
169                         RuntimeHelpers.InitializeArray (new Fielder ().array, rfh);
170                 }
171
172                 public void TestGetHashCode ()
173                 {
174                         Assert.AreEqual (0, RuntimeHelpers.GetHashCode (null));
175                         object o = new object ();
176                         Assert.AreEqual (o.GetHashCode (), RuntimeHelpers.GetHashCode (o));
177                         Assert.IsTrue (5 != RuntimeHelpers.GetHashCode (new FooClass ()));
178                 }                       
179
180                 public void TestEquals ()
181                 {
182                         Assert.IsTrue (RuntimeHelpers.Equals (null, null));
183                         Assert.IsTrue (!RuntimeHelpers.Equals (new object (), null));
184                         Assert.IsTrue (!RuntimeHelpers.Equals (null, new object ()));
185
186                         FooStruct f1 = new FooStruct ();
187                         f1.i = 5;
188                         FooStruct f2 = new FooStruct ();
189                         f2.i = 5;
190                         object o1 = f1;
191                         object o2 = o1;
192                         object o3 = f2;
193                         object o4 = "AAA";
194                         Assert.IsTrue (RuntimeHelpers.Equals (o1, o2));
195
196                         // This should do a bit-by-bit comparison for valuetypes
197                         Assert.IsTrue (RuntimeHelpers.Equals (o1, o3));
198                         Assert.IsTrue (!RuntimeHelpers.Equals (o1, o4));
199                 }
200         }
201 }