PageRenderTime 54ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 1ms

/Rx.NET/Source/Tests.System.Reactive/Tests/Concurrency/ThreadPoolSchedulerTest.cs

https://gitlab.com/svsamipillai/Rx.NET
C# | 332 lines | 271 code | 60 blank | 1 comment | 15 complexity | 337ac6ab18c950369b9f69aaf0e0d042 MD5 | raw file
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. #if !NO_THREAD
  3. using System;
  4. using System.Collections.Generic;
  5. using System.Linq;
  6. using System.Reactive.Concurrency;
  7. using System.Reactive.Disposables;
  8. using System.Threading;
  9. using Microsoft.Reactive.Testing;
  10. using Microsoft.VisualStudio.TestTools.UnitTesting;
  11. namespace ReactiveTests.Tests
  12. {
  13. [TestClass]
  14. public class ThreadPoolSchedulerTest
  15. {
  16. [TestMethod]
  17. public void Schedule_ArgumentChecking()
  18. {
  19. ReactiveAssert.Throws<ArgumentNullException>(() => ThreadPoolScheduler.Instance.Schedule<int>(42, default(Func<IScheduler, int, IDisposable>)));
  20. ReactiveAssert.Throws<ArgumentNullException>(() => ThreadPoolScheduler.Instance.Schedule<int>(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
  21. ReactiveAssert.Throws<ArgumentNullException>(() => ThreadPoolScheduler.Instance.Schedule<int>(42, TimeSpan.Zero, default(Func<IScheduler, int, IDisposable>)));
  22. }
  23. [TestMethod]
  24. public void Get_Now()
  25. {
  26. var res = ThreadPoolScheduler.Instance.Now - DateTime.Now;
  27. Assert.IsTrue(res.Seconds < 1);
  28. }
  29. [TestMethod]
  30. public void ScheduleAction()
  31. {
  32. var id = Thread.CurrentThread.ManagedThreadId;
  33. var nt = ThreadPoolScheduler.Instance;
  34. var evt = new ManualResetEvent(false);
  35. nt.Schedule(() => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
  36. evt.WaitOne();
  37. }
  38. #if !NO_CDS
  39. [TestMethod]
  40. public void ProperRooting_NoGC_SingleShot()
  41. {
  42. var cts = new CancellationTokenSource();
  43. new Thread(() =>
  44. {
  45. while (!cts.IsCancellationRequested)
  46. {
  47. Thread.Sleep(50);
  48. GC.Collect();
  49. GC.WaitForPendingFinalizers();
  50. }
  51. }).Start();
  52. var tp = ThreadPoolScheduler.Instance;
  53. var N = 100;
  54. var cd = new CountdownEvent(N);
  55. for (int i = 0; i < N; i++)
  56. {
  57. tp.Schedule(TimeSpan.FromMilliseconds(100 + i), () => { cd.Signal(); });
  58. }
  59. Assert.IsTrue(cd.Wait(TimeSpan.FromMinutes(1)));
  60. cts.Cancel();
  61. }
  62. [TestMethod]
  63. public void ProperRooting_NoGC_Periodic()
  64. {
  65. var cts = new CancellationTokenSource();
  66. new Thread(() =>
  67. {
  68. while (!cts.IsCancellationRequested)
  69. {
  70. Thread.Sleep(50);
  71. GC.Collect();
  72. GC.WaitForPendingFinalizers();
  73. }
  74. }).Start();
  75. var tp = ThreadPoolScheduler.Instance;
  76. var N = 5;
  77. var e = new ManualResetEvent(false);
  78. var n = 0;
  79. var d = tp.SchedulePeriodic(TimeSpan.FromMilliseconds(80), () => { if (Interlocked.Increment(ref n) == N) e.Set(); });
  80. Assert.IsTrue(e.WaitOne(TimeSpan.FromMinutes(1)));
  81. d.Dispose();
  82. cts.Cancel();
  83. }
  84. #endif
  85. #if !SILVERLIGHT
  86. [TestMethod]
  87. public void ScheduleActionDueRelative()
  88. {
  89. var id = Thread.CurrentThread.ManagedThreadId;
  90. var nt = ThreadPoolScheduler.Instance;
  91. var evt = new ManualResetEvent(false);
  92. nt.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
  93. evt.WaitOne();
  94. }
  95. [TestMethod]
  96. public void ScheduleActionDue0()
  97. {
  98. var id = Thread.CurrentThread.ManagedThreadId;
  99. var nt = ThreadPoolScheduler.Instance;
  100. var evt = new ManualResetEvent(false);
  101. nt.Schedule(TimeSpan.FromTicks(0), () => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
  102. evt.WaitOne();
  103. }
  104. [TestMethod]
  105. public void ScheduleActionDueAbsolute()
  106. {
  107. var id = Thread.CurrentThread.ManagedThreadId;
  108. var nt = ThreadPoolScheduler.Instance;
  109. var evt = new ManualResetEvent(false);
  110. nt.Schedule(DateTimeOffset.UtcNow + TimeSpan.FromSeconds(0.2), () => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
  111. evt.WaitOne();
  112. }
  113. #endif
  114. [TestMethod]
  115. public void ScheduleActionCancel()
  116. {
  117. var id = Thread.CurrentThread.ManagedThreadId;
  118. var nt = ThreadPoolScheduler.Instance;
  119. var set = false;
  120. var d = nt.Schedule(TimeSpan.FromSeconds(0.2), () => { Assert.Fail(); set = true; });
  121. d.Dispose();
  122. Thread.Sleep(400);
  123. Assert.IsFalse(set);
  124. }
  125. #if !NO_PERF
  126. [TestMethod]
  127. public void ScheduleLongRunning_ArgumentChecking()
  128. {
  129. ReactiveAssert.Throws<ArgumentNullException>(() => ThreadPoolScheduler.Instance.ScheduleLongRunning<int>(42, default(Action<int, ICancelable>)));
  130. }
  131. [TestMethod]
  132. public void ScheduleLongRunning()
  133. {
  134. var id = Thread.CurrentThread.ManagedThreadId;
  135. var nt = ThreadPoolScheduler.Instance;
  136. var evt = new ManualResetEvent(false);
  137. nt.ScheduleLongRunning(42, (x, cancel) => { Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
  138. evt.WaitOne();
  139. }
  140. [TestMethod]
  141. public void ScheduleLongRunningCancel()
  142. {
  143. var nt = ThreadPoolScheduler.Instance;
  144. var started = new ManualResetEvent(false);
  145. var stopped = new ManualResetEvent(false);
  146. var n = 0;
  147. var d = nt.ScheduleLongRunning(42, (x, cancel) =>
  148. {
  149. for (n = 0; !cancel.IsDisposed; n++)
  150. {
  151. if (n == 10)
  152. started.Set();
  153. }
  154. stopped.Set();
  155. });
  156. started.WaitOne();
  157. d.Dispose();
  158. stopped.WaitOne();
  159. Assert.IsTrue(n >= 10);
  160. }
  161. #if !NO_STOPWATCH
  162. [TestMethod]
  163. public void Stopwatch()
  164. {
  165. var nt = ThreadPoolScheduler.Instance;
  166. var sw = nt.StartStopwatch();
  167. var s0 = sw.Elapsed.Ticks;
  168. Thread.Sleep(10);
  169. var s1 = sw.Elapsed.Ticks;
  170. Assert.IsTrue(s1 > s0);
  171. }
  172. #endif
  173. [TestMethod]
  174. public void Periodic_ArgumentChecking()
  175. {
  176. ReactiveAssert.Throws<ArgumentNullException>(() => ThreadPoolScheduler.Instance.SchedulePeriodic(0, TimeSpan.FromSeconds(1), null));
  177. ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => ThreadPoolScheduler.Instance.SchedulePeriodic(0, TimeSpan.FromSeconds(-1), _ => _));
  178. }
  179. [TestMethod]
  180. public void Periodic_Regular()
  181. {
  182. Periodic_Impl(TimeSpan.FromMilliseconds(25));
  183. }
  184. [TestMethod]
  185. public void Periodic_Zero()
  186. {
  187. Periodic_Impl(TimeSpan.Zero);
  188. }
  189. private void Periodic_Impl(TimeSpan period)
  190. {
  191. var gate = new object();
  192. var n = 0;
  193. var e = new ManualResetEvent(false);
  194. var lst = new List<int>();
  195. var d = ThreadPoolScheduler.Instance.SchedulePeriodic(0, period, x =>
  196. {
  197. lock (gate)
  198. {
  199. if (n++ == 10)
  200. e.Set();
  201. }
  202. lst.Add(x);
  203. return x + 1;
  204. });
  205. e.WaitOne();
  206. d.Dispose();
  207. var m = default(int);
  208. var k = default(int);
  209. var i = 0;
  210. do
  211. {
  212. lock (gate)
  213. m = n;
  214. Thread.Sleep(50);
  215. lock (gate)
  216. k = n;
  217. } while (m != k && i++ < 10); // Wait for Dispose to reach the timer; should be almost instantaneous due to nop'ing out of the action.
  218. Assert.AreNotEqual(10, i);
  219. var res = lst.ToArray();
  220. Assert.IsTrue(res.Length >= 10);
  221. Assert.IsTrue(res.Take(10).SequenceEqual(Enumerable.Range(0, 10)));
  222. }
  223. [TestMethod]
  224. public void Periodic_NonReentrant()
  225. {
  226. var n = 0;
  227. var fail = false;
  228. var d = ThreadPoolScheduler.Instance.SchedulePeriodic(0, TimeSpan.FromMilliseconds(50), x =>
  229. {
  230. try
  231. {
  232. if (Interlocked.Increment(ref n) > 1) // Without an AsyncLock this would fail.
  233. fail = true;
  234. Thread.Sleep(100);
  235. return x + 1;
  236. }
  237. finally
  238. {
  239. Interlocked.Decrement(ref n);
  240. }
  241. });
  242. Thread.Sleep(500);
  243. d.Dispose();
  244. Assert.IsFalse(fail);
  245. }
  246. #endif
  247. #if DESKTOPCLR
  248. [TestMethod]
  249. public void No_ThreadPool_Starvation_Dispose()
  250. {
  251. var bwt = default(int);
  252. var bio = default(int);
  253. ThreadPool.GetAvailableThreads(out bwt, out bio);
  254. var N = Environment.ProcessorCount * 2;
  255. for (int i = 0; i < N; i++)
  256. {
  257. var e = new ManualResetEvent(false);
  258. var f = new ManualResetEvent(false);
  259. var d = ThreadPoolScheduler.Instance.Schedule(TimeSpan.FromMilliseconds(1), () => { e.Set(); f.WaitOne(); });
  260. e.WaitOne();
  261. d.Dispose();
  262. f.Set();
  263. }
  264. var ewt = default(int);
  265. var eio = default(int);
  266. ThreadPool.GetAvailableThreads(out ewt, out eio);
  267. Assert.IsFalse(bwt - ewt >= N);
  268. }
  269. #endif
  270. }
  271. }
  272. #endif