[runtime] Fix Empty generic enumerator equality
[mono.git] / mcs / class / corlib / Test / System / LazyTest.cs
1 //
2 // LazyTest.cs - NUnit Test Cases for Lazy
3 //
4 // Author:
5 //      Zoltan Varga (vargaz@gmail.com)
6 //
7 // Copyright (C) 2009 Novell, Inc (http://www.novell.com)
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Reflection;
31 using System.Threading;
32 using NUnit.Framework;
33
34 #pragma warning disable 219
35 #pragma warning disable 168
36
37 namespace MonoTests.System
38 {
39         [TestFixture]
40         public class LazyTest
41         {
42                 [Test]
43                 [ExpectedException (typeof (ArgumentNullException))]
44                 public void Ctor_Null_1 () {
45                         new Lazy<int> (null);
46                 }
47
48
49                 [Test]
50                 [ExpectedException (typeof (ArgumentNullException))]
51                 public void Ctor_Null_2 () {
52                         new Lazy<int> (null, false);
53                 }
54
55                 [Test]
56                 public void IsValueCreated () {
57                         var l1 = new Lazy<int> ();
58
59                         Assert.IsFalse (l1.IsValueCreated);
60
61                         int i = l1.Value;
62
63                         Assert.IsTrue (l1.IsValueCreated);
64                 }
65
66                 [Test]
67                 public void DefaultCtor () {
68                         var l1 = new Lazy<DefaultCtorClass> ();
69                         
70                         var o = l1.Value;
71                         Assert.AreEqual (5, o.Prop);
72                 }
73
74                 class DefaultCtorClass {
75                         public DefaultCtorClass () {
76                                 Prop = 5;
77                         }
78
79                         public int Prop {
80                                 get; set;
81                         }
82                 }
83
84                 [Test]
85                 public void NoDefaultCtor () {
86                         var l1 = new Lazy<NoDefaultCtorClass> ();
87                         
88                         try {
89                                 var o = l1.Value;
90                                 Assert.Fail ();
91                         } catch (MissingMemberException) {
92                         }
93                 }
94
95                 class NoDefaultCtorClass {
96                         public NoDefaultCtorClass (int i) {
97                         }
98                 }
99
100                 [Test]
101                 public void NotThreadSafe () {
102                         var l1 = new Lazy<int> ();
103
104                         Assert.AreEqual (0, l1.Value);
105
106                         var l2 = new Lazy<int> (delegate () { return 42; });
107
108                         Assert.AreEqual (42, l2.Value);
109                 }
110
111                 static int counter;
112
113                 [Test]
114                 public void EnsureSingleThreadSafeExecution ()
115                 {
116                         counter = 42;
117                         bool started = false;
118
119                         var l = new Lazy<int> (delegate () { return counter ++; }, true);
120                         bool failed = false;
121                         object monitor = new object ();
122                         var threads = new Thread [4];
123                         for (int i = 0; i < threads.Length; ++i) {
124                                 threads [i] = new Thread (delegate () {
125                                                 lock (monitor) {
126                                                         if (!started) {
127                                                                 if (!Monitor.Wait (monitor, 2000))
128                                                                         failed = true;
129                                                         }
130                                                 }
131                                                 int val = l.Value;
132                                         });
133                         }
134                         for (int i = 0; i < threads.Length; ++i)
135                                 threads [i].Start ();
136                         lock (monitor) {
137                                 started = true;
138                                 Monitor.PulseAll (monitor);
139                         }
140
141                         for (int i = 0; i < threads.Length; ++i)
142                                 threads [i].Join ();
143
144                         Assert.IsFalse (failed);
145                         Assert.AreEqual (42, l.Value);
146                 }
147                 
148                 [Test]
149                 public void InitRecursion ()
150                 {
151                         Lazy<DefaultCtorClass> c = null;
152                         c = new Lazy<DefaultCtorClass> (() => { Console.WriteLine (c.Value); return null; });
153                         
154                         try {
155                                 var r = c.Value;
156                                 Assert.Fail ();
157                         } catch (InvalidOperationException) {
158                         }
159                 }
160
161                 [Test]
162                 public void ModeNone ()
163                 {
164                         int x;
165                         bool fail = true;
166                         Lazy<int> lz = new Lazy<int> (() => { if (fail) throw new Exception (); else return 99; }, LazyThreadSafetyMode.None);
167                         try {
168                                 x = lz.Value;
169                                 Assert.Fail ("#1");
170                                 Console.WriteLine (x);
171                         } catch (Exception ex) { }
172
173                         try {
174                                 x = lz.Value;
175                                 Assert.Fail ("#2");
176                         } catch (Exception ex) { }
177
178                         fail = false;
179                         try {
180                                 x = lz.Value;
181                                 Assert.Fail ("#3");
182                         } catch (Exception ex) { }
183
184                         bool rec = true;
185                         lz = new Lazy<int> (() => rec ? lz.Value : 99, LazyThreadSafetyMode.None);
186
187                         try {
188                                 x = lz.Value;
189                                 Assert.Fail ("#4");
190                         } catch (InvalidOperationException ex) { }
191
192                         rec = false;
193                         try {
194                                 x = lz.Value;
195                                 Assert.Fail ("#5");
196                         } catch (InvalidOperationException ex) { }
197                 }
198
199                 [Test]
200                 public void ModePublicationOnly () {
201                         bool fail = true;
202                         int invoke = 0;
203                         Lazy<int> lz = new Lazy<int> (() => { ++invoke; if (fail) throw new Exception (); else return 99; }, LazyThreadSafetyMode.PublicationOnly);
204
205                         try {
206                                 int x = lz.Value;
207                                 Assert.Fail ("#1");
208                                 Console.WriteLine (x);
209                         } catch (Exception ex) { }
210
211                         try {
212                                 int x = lz.Value;
213                                 Assert.Fail ("#2");
214                         } catch (Exception ex) { }
215
216
217                         Assert.AreEqual (2, invoke, "#3");
218                         fail = false;
219                         Assert.AreEqual (99,  lz.Value, "#4");
220                         Assert.AreEqual (3, invoke, "#5");
221
222                         invoke = 0;
223                         bool rec = true;
224                         lz = new Lazy<int> (() => { ++invoke; bool r = rec; rec = false; return r ? lz.Value : 88; },   LazyThreadSafetyMode.PublicationOnly);
225
226                         Assert.AreEqual (88,  lz.Value, "#6");
227                         Assert.AreEqual (2, invoke, "#7");
228                 }
229
230                 [Test]
231                 public void ModeExecutionAndPublication () {
232                         int invoke = 0;
233                         bool fail = true;
234                         Lazy<int> lz = new Lazy<int> (() => { ++invoke; if (fail) throw new Exception (); else return 99; }, LazyThreadSafetyMode.ExecutionAndPublication);
235
236                         try {
237                                 int x = lz.Value;
238                                 Assert.Fail ("#1");
239                                 Console.WriteLine (x);
240                         } catch (Exception ex) { }
241                         Assert.AreEqual (1, invoke, "#2");
242
243                         try {
244                                 int x = lz.Value;
245                                 Assert.Fail ("#3");
246                         } catch (Exception ex) { }
247                         Assert.AreEqual (1, invoke, "#4");
248
249                         fail = false;
250                         try {
251                                 int x = lz.Value;
252                                 Assert.Fail ("#5");
253                         } catch (Exception ex) { }
254                         Assert.AreEqual (1, invoke, "#6");
255
256                         bool rec = true;
257                         lz = new Lazy<int> (() => rec ? lz.Value : 99, LazyThreadSafetyMode.ExecutionAndPublication);
258
259                         try {
260                                 int x = lz.Value;
261                                 Assert.Fail ("#7");
262                         } catch (InvalidOperationException ex) { }
263
264                         rec = false;
265                         try {
266                                 int x = lz.Value;
267                                 Assert.Fail ("#8");
268                         } catch (InvalidOperationException ex) { }
269                 }
270
271                 static int Return22 () {
272                         return 22;
273                 }
274
275                 [Test]
276                 public void Trivial_Lazy () {
277                         var x = new Lazy<int> (Return22, false);
278                         Assert.AreEqual (22, x.Value, "#1");
279                 }
280
281                 [Test]
282                 public void ConcurrentInitialization ()
283                 {
284                         var init = new AutoResetEvent (false);
285                         var e1_set = new AutoResetEvent (false);
286
287                         var lazy = new Lazy<string> (() => {
288                                 init.Set ();
289                                 Thread.Sleep (10);
290                                 throw new ApplicationException ();
291                         });
292
293                         Exception e1 = null;
294                         var thread = new Thread (() => {
295                                 try {
296                                         string value = lazy.Value;
297                                 } catch (Exception ex) {
298                                         e1 = ex;
299                                         e1_set.Set ();
300                                 }
301                         });
302                         thread.Start ();
303
304                         Assert.IsTrue (init.WaitOne (3000), "#1");
305
306                         Exception e2 = null;
307                         try {
308                                 string value = lazy.Value;
309                         } catch (Exception ex) {
310                                 e2 = ex;
311                         }
312
313                         Exception e3 = null;
314                         try {
315                                 string value = lazy.Value;
316                         } catch (Exception ex) {
317                                 e3 = ex;
318                         }
319
320                         Assert.IsTrue (e1_set.WaitOne (3000), "#2");
321                         Assert.AreSame (e1, e2, "#3");
322                         Assert.AreSame (e1, e3, "#4");
323                 }
324
325         }
326 }