Changed API for fetching StackFrames in bulk on multiple threads ThreadMirror.FetchFr...
[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 #if NET_4_0
30
31 using System;
32 using System.Reflection;
33 using System.Reflection.Emit;
34 using System.Threading;
35 using NUnit.Framework;
36
37 #pragma warning disable 219
38 #pragma warning disable 168
39
40 namespace MonoTests.System
41 {
42         [TestFixture]
43         public class LazyTest
44         {
45                 [Test]
46                 [ExpectedException (typeof (ArgumentNullException))]
47                 public void Ctor_Null_1 () {
48                         new Lazy<int> (null);
49                 }
50
51
52                 [Test]
53                 [ExpectedException (typeof (ArgumentNullException))]
54                 public void Ctor_Null_2 () {
55                         new Lazy<int> (null, false);
56                 }
57
58                 [Test]
59                 public void IsValueCreated () {
60                         var l1 = new Lazy<int> ();
61
62                         Assert.IsFalse (l1.IsValueCreated);
63
64                         int i = l1.Value;
65
66                         Assert.IsTrue (l1.IsValueCreated);
67                 }
68
69                 [Test]
70                 public void DefaultCtor () {
71                         var l1 = new Lazy<DefaultCtorClass> ();
72                         
73                         var o = l1.Value;
74                         Assert.AreEqual (5, o.Prop);
75                 }
76
77                 class DefaultCtorClass {
78                         public DefaultCtorClass () {
79                                 Prop = 5;
80                         }
81
82                         public int Prop {
83                                 get; set;
84                         }
85                 }
86
87                 [Test]
88                 public void NoDefaultCtor () {
89                         var l1 = new Lazy<NoDefaultCtorClass> ();
90                         
91                         try {
92                                 var o = l1.Value;
93                                 Assert.Fail ();
94                         } catch (MissingMemberException) {
95                         }
96                 }
97
98                 class NoDefaultCtorClass {
99                         public NoDefaultCtorClass (int i) {
100                         }
101                 }
102
103                 [Test]
104                 public void NotThreadSafe () {
105                         var l1 = new Lazy<int> ();
106
107                         Assert.AreEqual (0, l1.Value);
108
109                         var l2 = new Lazy<int> (delegate () { return 42; });
110
111                         Assert.AreEqual (42, l2.Value);
112                 }
113
114                 static int counter;
115
116                 [Test]
117                 public void EnsureSingleThreadSafeExecution () {
118                         counter = 42;
119
120                         var l = new Lazy<int> (delegate () { return counter ++; }, true);
121
122                         object monitor = new object ();
123                         var threads = new Thread [10];
124                         for (int i = 0; i < 10; ++i) {
125                                 threads [i] = new Thread (delegate () {
126                                                 lock (monitor) {
127                                                         Monitor.Wait (monitor);
128                                                 }
129                                                 int val = l.Value;
130                                         });
131                         }
132                         for (int i = 0; i < 10; ++i)
133                                 threads [i].Start ();
134                         lock (monitor)
135                                 Monitor.PulseAll (monitor);
136                         
137                         Assert.AreEqual (42, l.Value);
138                 }
139                 
140                 [Test]
141                 public void InitRecursion ()
142                 {
143                         Lazy<DefaultCtorClass> c = null;
144                         c = new Lazy<DefaultCtorClass> (() => { Console.WriteLine (c.Value); return null; });
145                         
146                         try {
147                                 var r = c.Value;
148                                 Assert.Fail ();
149                         } catch (InvalidOperationException) {
150                         }
151                 }
152
153                 [Test]
154                 public void ModeNone ()
155                 {
156                         int x;
157                         bool fail = true;
158                         Lazy<int> lz = new Lazy<int> (() => { if (fail) throw new Exception (); else return 99; }, LazyThreadSafetyMode.None);
159                         try {
160                                 x = lz.Value;
161                                 Assert.Fail ("#1");
162                                 Console.WriteLine (x);
163                         } catch (Exception ex) { }
164
165                         try {
166                                 x = lz.Value;
167                                 Assert.Fail ("#2");
168                         } catch (Exception ex) { }
169
170                         fail = false;
171                         try {
172                                 x = lz.Value;
173                                 Assert.Fail ("#3");
174                         } catch (Exception ex) { }
175
176                         bool rec = true;
177                         lz = new Lazy<int> (() => rec ? lz.Value : 99, LazyThreadSafetyMode.None);
178
179                         try {
180                                 x = lz.Value;
181                                 Assert.Fail ("#4");
182                         } catch (InvalidOperationException ex) { }
183
184                         rec = false;
185                         try {
186                                 x = lz.Value;
187                                 Assert.Fail ("#5");
188                         } catch (InvalidOperationException ex) { }
189                 }
190
191                 [Test]
192                 public void ModePublicationOnly () {
193                         bool fail = true;
194                         int invoke = 0;
195                         Lazy<int> lz = new Lazy<int> (() => { ++invoke; if (fail) throw new Exception (); else return 99; }, LazyThreadSafetyMode.PublicationOnly);
196
197                         try {
198                                 int x = lz.Value;
199                                 Assert.Fail ("#1");
200                                 Console.WriteLine (x);
201                         } catch (Exception ex) { }
202
203                         try {
204                                 int x = lz.Value;
205                                 Assert.Fail ("#2");
206                         } catch (Exception ex) { }
207
208
209                         Assert.AreEqual (2, invoke, "#3");
210                         fail = false;
211                         Assert.AreEqual (99,  lz.Value, "#4");
212                         Assert.AreEqual (3, invoke, "#5");
213
214                         invoke = 0;
215                         bool rec = true;
216                         lz = new Lazy<int> (() => { ++invoke; bool r = rec; rec = false; return r ? lz.Value : 88; },   LazyThreadSafetyMode.PublicationOnly);
217
218                         Assert.AreEqual (88,  lz.Value, "#6");
219                         Assert.AreEqual (2, invoke, "#7");
220                 }
221
222                 [Test]
223                 public void ModeExecutionAndPublication () {
224                         int invoke = 0;
225                         bool fail = true;
226                         Lazy<int> lz = new Lazy<int> (() => { ++invoke; if (fail) throw new Exception (); else return 99; }, LazyThreadSafetyMode.ExecutionAndPublication);
227
228                         try {
229                                 int x = lz.Value;
230                                 Assert.Fail ("#1");
231                                 Console.WriteLine (x);
232                         } catch (Exception ex) { }
233                         Assert.AreEqual (1, invoke, "#2");
234
235                         try {
236                                 int x = lz.Value;
237                                 Assert.Fail ("#3");
238                         } catch (Exception ex) { }
239                         Assert.AreEqual (1, invoke, "#4");
240
241                         fail = false;
242                         try {
243                                 int x = lz.Value;
244                                 Assert.Fail ("#5");
245                         } catch (Exception ex) { }
246                         Assert.AreEqual (1, invoke, "#6");
247
248                         bool rec = true;
249                         lz = new Lazy<int> (() => rec ? lz.Value : 99, LazyThreadSafetyMode.ExecutionAndPublication);
250
251                         try {
252                                 int x = lz.Value;
253                                 Assert.Fail ("#7");
254                         } catch (InvalidOperationException ex) { }
255
256                         rec = false;
257                         try {
258                                 int x = lz.Value;
259                                 Assert.Fail ("#8");
260                         } catch (InvalidOperationException ex) { }
261                 }
262
263                 static int Return22 () {
264                         return 22;
265                 }
266
267                 [Test]
268                 public void Trivial_Lazy () {
269                         var x = new Lazy<int> (Return22, false);
270                         Assert.AreEqual (22, x.Value, "#1");
271                 }
272
273                 [Test]
274                 public void ConcurrentInitialization ()
275                 {
276                         var init = new AutoResetEvent (false);
277
278                         var lazy = new Lazy<string> (() => {
279                                 init.Set ();
280                                 Thread.Sleep (10);
281                                 throw new ApplicationException ();
282                         });
283
284                         Exception e1 = null;
285                         var thread = new Thread (() => {
286                                 try {
287                                         string value = lazy.Value;
288                                 } catch (Exception ex) {
289                                         e1 = ex;
290                                 }
291                         });
292                         thread.Start ();
293
294                         Assert.IsTrue (init.WaitOne (3000), "#1");
295
296                         Exception e2 = null;
297                         try {
298                                 string value = lazy.Value;
299                         } catch (Exception ex) {
300                                 e2 = ex;
301                         }
302
303                         Exception e3 = null;
304                         try {
305                                 string value = lazy.Value;
306                         } catch (Exception ex) {
307                                 e3 = ex;
308                         }
309
310                         Assert.AreSame (e1, e2, "#2");
311                         Assert.AreSame (e1, e3, "#3");
312                 }
313
314         }
315 }
316
317 #endif