TaskTest.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349
  1. //
  2. // TaskTest.cs
  3. //
  4. // Copyright (c) 2008 Jérémie "Garuma" Laval
  5. //
  6. // Permission is hereby granted, free of charge, to any person obtaining a copy
  7. // of this software and associated documentation files (the "Software"), to deal
  8. // in the Software without restriction, including without limitation the rights
  9. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10. // copies of the Software, and to permit persons to whom the Software is
  11. // furnished to do so, subject to the following conditions:
  12. //
  13. // The above copyright notice and this permission notice shall be included in
  14. // all copies or substantial portions of the Software.
  15. //
  16. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  19. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22. // THE SOFTWARE.
  23. //
  24. //
  25. #if NET_4_0
  26. using System;
  27. using System.Threading;
  28. using System.Threading.Tasks;
  29. using NUnit.Framework;
  30. namespace MonoTests.System.Threading.Tasks
  31. {
  32. [TestFixture]
  33. public class TaskTests
  34. {
  35. Task[] tasks;
  36. static readonly int max = 3 * Environment.ProcessorCount;
  37. [SetUp]
  38. public void Setup()
  39. {
  40. tasks = new Task[max];
  41. }
  42. void InitWithDelegate(Action action)
  43. {
  44. for (int i = 0; i < max; i++) {
  45. tasks[i] = Task.Factory.StartNew(action);
  46. }
  47. }
  48. [TestAttribute]
  49. public void WaitAnyTest()
  50. {
  51. ParallelTestHelper.Repeat (delegate {
  52. int flag = 0;
  53. int finished = 0;
  54. InitWithDelegate(delegate {
  55. int times = Interlocked.Exchange (ref flag, 1);
  56. if (times == 1) {
  57. SpinWait sw = new SpinWait ();
  58. while (finished == 0) sw.SpinOnce ();
  59. } else {
  60. Interlocked.Increment (ref finished);
  61. }
  62. });
  63. int index = Task.WaitAny(tasks);
  64. Assert.AreNotEqual (-1, index, "#3");
  65. Assert.AreEqual (1, flag, "#1");
  66. Assert.AreEqual (1, finished, "#2");
  67. Task.WaitAll (tasks);
  68. });
  69. }
  70. [TestAttribute]
  71. public void WaitAllTest()
  72. {
  73. ParallelTestHelper.Repeat (delegate {
  74. int achieved = 0;
  75. InitWithDelegate(delegate { Interlocked.Increment(ref achieved); });
  76. Task.WaitAll(tasks);
  77. Assert.AreEqual(max, achieved, "#1");
  78. });
  79. }
  80. [Test]
  81. public void CancelTestCase()
  82. {
  83. bool result = false;
  84. CancellationTokenSource src = new CancellationTokenSource ();
  85. Task t = new Task (delegate {
  86. result = true;
  87. }, src.Token);
  88. src.Cancel ();
  89. t.Start ();
  90. Exception ex = null;
  91. try {
  92. t.Wait ();
  93. } catch (Exception e) {
  94. ex = e;
  95. }
  96. Assert.IsNotNull (ex, "#1");
  97. Assert.IsInstanceOfType (typeof(AggregateException), ex, "#2");
  98. Assert.IsNull (t.Exception, "#3");
  99. AggregateException aggr = (AggregateException)ex;
  100. Assert.AreEqual (1, aggr.InnerExceptions.Count, "#4");
  101. Assert.IsInstanceOfType (typeof (OperationCanceledException), aggr.InnerExceptions[0], "#5");
  102. }
  103. [Test, ExpectedException (typeof (InvalidOperationException))]
  104. public void CreationWhileInitiallyCanceled ()
  105. {
  106. var token = new CancellationToken (true);
  107. var task = new Task (() => { }, token);
  108. Assert.AreEqual (TaskStatus.Canceled, task.Status);
  109. task.Start ();
  110. }
  111. [Test]
  112. public void ContinueWithOnAnyTestCase()
  113. {
  114. ParallelTestHelper.Repeat (delegate {
  115. bool result = false;
  116. Task t = Task.Factory.StartNew(delegate { });
  117. Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.None);
  118. Assert.IsTrue (t.Wait (2000), "First wait, (status, {0})", t.Status);
  119. Assert.IsTrue (cont.Wait(2000), "Cont wait, (result, {0}) (parent status, {2}) (status, {1})", result, cont.Status, t.Status);
  120. Assert.IsNull(cont.Exception, "#1");
  121. Assert.IsNotNull(cont, "#2");
  122. Assert.IsTrue(result, "#3");
  123. });
  124. }
  125. [Test]
  126. public void ContinueWithOnCompletedSuccessfullyTestCase()
  127. {
  128. ParallelTestHelper.Repeat (delegate {
  129. bool result = false;
  130. Task t = Task.Factory.StartNew(delegate { });
  131. Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnRanToCompletion);
  132. t.Wait();
  133. cont.Wait();
  134. Assert.IsNull(cont.Exception, "#1");
  135. Assert.IsNotNull(cont, "#2");
  136. Assert.IsTrue(result, "#3");
  137. });
  138. }
  139. [Test]
  140. public void ContinueWithOnAbortedTestCase()
  141. {
  142. ParallelTestHelper.Repeat (delegate {
  143. bool result = false;
  144. bool taskResult = false;
  145. CancellationTokenSource src = new CancellationTokenSource ();
  146. Task t = new Task(delegate { taskResult = true; }, src.Token);
  147. src.Cancel ();
  148. Task cont = t.ContinueWith (delegate { result = true; },
  149. TaskContinuationOptions.OnlyOnCanceled | TaskContinuationOptions.ExecuteSynchronously);
  150. t.Start();
  151. cont.Wait();
  152. Assert.IsFalse (taskResult, "#-1");
  153. Assert.AreEqual (TaskStatus.Canceled, t.Status, "#0");
  154. Assert.IsTrue (t.IsCanceled, "#0bis");
  155. Assert.IsNull(cont.Exception, "#1");
  156. Assert.IsNotNull(cont, "#2");
  157. Assert.IsTrue(result, "#3");
  158. });
  159. }
  160. [Test]
  161. public void ContinueWithOnFailedTestCase()
  162. {
  163. ParallelTestHelper.Repeat (delegate {
  164. bool result = false;
  165. Task t = Task.Factory.StartNew(delegate { throw new Exception("foo"); });
  166. Task cont = t.ContinueWith(delegate { result = true; }, TaskContinuationOptions.OnlyOnFaulted);
  167. cont.Wait();
  168. Assert.IsNotNull (t.Exception, "#1");
  169. Assert.IsNotNull (cont, "#2");
  170. Assert.IsTrue (result, "#3");
  171. });
  172. }
  173. [Test]
  174. public void ContinueWithChildren ()
  175. {
  176. ParallelTestHelper.Repeat (delegate {
  177. bool result = false;
  178. var t = Task.Factory.StartNew (() => Task.Factory.StartNew (() => Thread.Sleep (100), TaskCreationOptions.AttachedToParent));
  179. t.ContinueWith (_ => result = true);
  180. while (!t.IsCompleted)
  181. Thread.Sleep (200);
  182. Assert.IsTrue (result);
  183. }, 2);
  184. }
  185. [TestAttribute]
  186. public void MultipleTaskTestCase()
  187. {
  188. ParallelTestHelper.Repeat (delegate {
  189. bool r1 = false, r2 = false, r3 = false;
  190. Task t1 = Task.Factory.StartNew(delegate {
  191. r1 = true;
  192. });
  193. Task t2 = Task.Factory.StartNew(delegate {
  194. r2 = true;
  195. });
  196. Task t3 = Task.Factory.StartNew(delegate {
  197. r3 = true;
  198. });
  199. t1.Wait();
  200. t2.Wait();
  201. t3.Wait();
  202. Assert.IsTrue(r1, "#1");
  203. Assert.IsTrue(r2, "#2");
  204. Assert.IsTrue(r3, "#3");
  205. });
  206. }
  207. [Test]
  208. public void WaitChildTestCase()
  209. {
  210. ParallelTestHelper.Repeat (delegate {
  211. bool r1 = false, r2 = false, r3 = false;
  212. Task t = Task.Factory.StartNew(delegate {
  213. Task.Factory.StartNew(delegate {
  214. Thread.Sleep(50);
  215. r1 = true;
  216. }, TaskCreationOptions.AttachedToParent);
  217. Task.Factory.StartNew(delegate {
  218. Thread.Sleep(300);
  219. r2 = true;
  220. }, TaskCreationOptions.AttachedToParent);
  221. Task.Factory.StartNew(delegate {
  222. Thread.Sleep(150);
  223. r3 = true;
  224. }, TaskCreationOptions.AttachedToParent);
  225. });
  226. t.Wait();
  227. Assert.IsTrue(r2, "#1");
  228. Assert.IsTrue(r3, "#2");
  229. Assert.IsTrue(r1, "#3");
  230. Assert.AreEqual (TaskStatus.RanToCompletion, t.Status, "#4");
  231. }, 10);
  232. }
  233. [Test]
  234. public void ExecuteSynchronouslyTest ()
  235. {
  236. var val = 0;
  237. Task t = new Task (() => { Thread.Sleep (100); val = 1; });
  238. t.RunSynchronously ();
  239. Assert.AreEqual (1, val);
  240. }
  241. [Test]
  242. public void RunSynchronouslyArgumentChecks ()
  243. {
  244. Task t = new Task (() => { });
  245. try {
  246. t.RunSynchronously (null);
  247. Assert.Fail ("#1");
  248. } catch (ArgumentNullException) {
  249. }
  250. }
  251. [Test]
  252. public void UnobservedExceptionOnFinalizerThreadTest ()
  253. {
  254. bool wasCalled = false;
  255. TaskScheduler.UnobservedTaskException += (o, args) => {
  256. wasCalled = true;
  257. args.SetObserved ();
  258. };
  259. var inner = new ApplicationException ();
  260. Task.Factory.StartNew (() => { throw inner; });
  261. Thread.Sleep (1000);
  262. GC.Collect ();
  263. Thread.Sleep (1000);
  264. GC.WaitForPendingFinalizers ();
  265. Assert.IsTrue (wasCalled);
  266. }
  267. [Test, ExpectedException (typeof (InvalidOperationException))]
  268. public void StartFinishedTaskTest ()
  269. {
  270. var t = Task.Factory.StartNew (delegate () { });
  271. t.Wait ();
  272. t.Start ();
  273. }
  274. [Test, ExpectedException (typeof (InvalidOperationException))]
  275. public void DisposeUnstartedTest ()
  276. {
  277. var t = new Task (() => { });
  278. t.Dispose ();
  279. }
  280. [Test]
  281. public void ThrowingUnrelatedCanceledExceptionTest ()
  282. {
  283. Task t = new Task (() => {
  284. throw new TaskCanceledException ();
  285. });
  286. t.RunSynchronously ();
  287. Assert.IsTrue (t.IsFaulted);
  288. Assert.IsFalse (t.IsCanceled);
  289. }
  290. }
  291. }
  292. #endif