New tests.
[mono.git] / mcs / class / corlib / Test / System.Threading / SpinLockTests.cs
1 #if NET_4_0
2 //
3 // SpinLockTests.cs
4 //
5 // Author:
6 //       Jérémie "Garuma" Laval <jeremie.laval@gmail.com>
7 //
8 // Copyright (c) 2010 Jérémie "Garuma" Laval
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining a copy
11 // of this software and associated documentation files (the "Software"), to deal
12 // in the Software without restriction, including without limitation the rights
13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
14 // copies of the Software, and to permit persons to whom the Software is
15 // furnished to do so, subject to the following conditions:
16 //
17 // The above copyright notice and this permission notice shall be included in
18 // all copies or substantial portions of the Software.
19 //
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
26 // THE SOFTWARE.
27
28 using System;
29 using System.Threading;
30
31 using NUnit.Framework;
32
33 using MonoTests.System.Threading.Tasks;
34
35 namespace MonoTests.System.Threading
36 {
37         [TestFixture]
38         public class SpinLockTests
39         {
40                 SpinLock sl;
41
42                 [SetUp]
43                 public void Setup ()
44                 {
45                         sl = new SpinLock (true);
46                 }
47
48                 [Test, ExpectedException (typeof (LockRecursionException))]
49                 public void RecursionExceptionTest ()
50                 {
51                         sl = new SpinLock (true);
52                         bool taken = false, taken2 = false;
53
54                         sl.Enter (ref taken);
55                         Assert.IsTrue (taken, "#1");
56                         sl.Enter (ref taken2);
57                 }
58
59                 [Test]
60                 public void SimpleEnterExitSchemeTest ()
61                 {
62                         bool taken = false;
63
64                         for (int i = 0; i < 50000; i++) {
65                                 sl.Enter (ref taken);
66                                 Assert.IsTrue (taken, "#" + i.ToString ());
67                                 sl.Exit ();
68                                 taken = false;
69                         }
70                 }
71
72                 [Test]
73                 public void SemanticCorrectnessTest ()
74                 {
75                         sl = new SpinLock (false);
76
77                         bool taken = false;
78                         bool taken2 = false;
79
80                         sl.Enter (ref taken);
81                         Assert.IsTrue (taken, "#1");
82                         sl.TryEnter (ref taken2);
83                         Assert.IsFalse (taken2, "#2");
84                         sl.Exit ();
85
86                         sl.TryEnter (ref taken2);
87                         Assert.IsTrue (taken2, "#3");
88                 }
89
90                 [Test, ExpectedException (typeof (ArgumentException))]
91                 public void FirstTakenParameterTest ()
92                 {
93                         bool taken = true;
94
95                         sl.Enter (ref taken);
96                 }
97
98                 [Test, ExpectedException (typeof (ArgumentException))]
99                 public void SecondTakenParameterTest ()
100                 {
101                         bool taken = true;
102
103                         sl.TryEnter (ref taken);
104                 }
105
106                 internal class SpinLockWrapper
107                 {
108                         public SpinLock Lock = new SpinLock (false);
109                 }
110
111                 [Test]
112                 public void LockUnicityTest ()
113                 {
114                         ParallelTestHelper.Repeat (delegate {
115                                 int currentCount = 0;
116                                 bool fail = false;
117                                 SpinLockWrapper wrapper = new SpinLockWrapper ();
118
119                                 ParallelTestHelper.ParallelStressTest (wrapper, delegate {
120                                         bool taken = false;
121                                         wrapper.Lock.Enter (ref taken);
122                                         int current = currentCount++;
123                                         if (current != 0)
124                                                 fail = true;
125
126                                         SpinWait sw = new SpinWait ();
127                                         for (int i = 0; i < 200; i++)
128                                                 sw.SpinOnce ();
129                                         currentCount -= 1;
130
131                                         wrapper.Lock.Exit ();
132                                 }, 4);
133
134                                 Assert.IsFalse (fail);
135                         }, 200);
136                 }
137
138                 [Test]
139                 public void IsHeldByCurrentThreadTest ()
140                 {
141                         bool lockTaken = false;
142
143                         sl.Enter (ref lockTaken);
144                         Assert.IsTrue (lockTaken, "#1");
145                         Assert.IsTrue (sl.IsHeldByCurrentThread, "#2");
146
147                         lockTaken = false;
148                         sl = new SpinLock (true);
149
150                         sl.Enter (ref lockTaken);
151                         Assert.IsTrue (lockTaken, "#3");
152                         Assert.IsTrue (sl.IsHeldByCurrentThread, "#4");
153                 }
154         }
155 }
156 #endif