PageRenderTime 85ms CodeModel.GetById 29ms app.highlight 47ms RepoModel.GetById 1ms app.codeStats 2ms

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