ControlSchedulerTest.cs 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the MIT License.
  3. // See the LICENSE file in the project root for more information.
  4. #if HAS_WINFORMS
  5. #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested.
  6. using System;
  7. using System.Reactive.Concurrency;
  8. using System.Reactive.Disposables;
  9. using System.Diagnostics;
  10. using System.Threading;
  11. using System.Windows.Forms;
  12. using Microsoft.VisualStudio.TestTools.UnitTesting;
  13. using Microsoft.Reactive.Testing;
  14. using Assert = Xunit.Assert;
  15. namespace ReactiveTests.Tests
  16. {
  17. [TestClass]
  18. public class ControlSchedulerTest
  19. {
  20. [TestMethod]
  21. public void Ctor_ArgumentChecking()
  22. {
  23. #pragma warning disable CA1806 // (Unused new instance.) We expect the constructor to throw.
  24. ReactiveAssert.Throws<ArgumentNullException>(() => new ControlScheduler(null));
  25. #pragma warning restore CA1806
  26. }
  27. [TestMethod]
  28. public void Control()
  29. {
  30. var lbl = new Label();
  31. Assert.Same(lbl, new ControlScheduler(lbl).Control);
  32. }
  33. [TestMethod]
  34. public void Now()
  35. {
  36. var res = new ControlScheduler(new Label()).Now - DateTime.Now;
  37. Assert.True(res.Seconds < 1);
  38. }
  39. [TestMethod]
  40. public void Schedule_ArgumentChecking()
  41. {
  42. var s = new ControlScheduler(new Label());
  43. ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, default(Func<IScheduler, int, IDisposable>)));
  44. ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, TimeSpan.FromSeconds(1), default(Func<IScheduler, int, IDisposable>)));
  45. ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
  46. }
  47. [TestMethod]
  48. public void Schedule()
  49. {
  50. using (WinFormsTestUtils.RunTest(out var lbl))
  51. {
  52. var evt = new ManualResetEvent(false);
  53. var id = Environment.CurrentManagedThreadId;
  54. var sch = new ControlScheduler(lbl);
  55. sch.Schedule(() => { lbl.Text = "Okay"; Assert.NotEqual(id, Environment.CurrentManagedThreadId); });
  56. sch.Schedule(() => { Assert.Equal("Okay", lbl.Text); Assert.NotEqual(id, Environment.CurrentManagedThreadId); evt.Set(); });
  57. evt.WaitOne();
  58. }
  59. }
  60. [TestMethod]
  61. public void ScheduleError()
  62. {
  63. using (WinFormsTestUtils.RunTest(out var lbl))
  64. {
  65. var evt = new ManualResetEvent(false);
  66. var ex = new Exception();
  67. lbl.Invoke(new Action(() =>
  68. {
  69. Application.ThreadException += (o, e) =>
  70. {
  71. Assert.Same(ex, e.Exception);
  72. evt.Set();
  73. };
  74. }));
  75. var sch = new ControlScheduler(lbl);
  76. sch.Schedule(() => { throw ex; });
  77. evt.WaitOne();
  78. }
  79. }
  80. [TestMethod]
  81. public void ScheduleRelative()
  82. {
  83. ScheduleRelative_(TimeSpan.FromSeconds(0.1));
  84. }
  85. [TestMethod]
  86. public void ScheduleRelative_Zero()
  87. {
  88. ScheduleRelative_(TimeSpan.Zero);
  89. }
  90. private void ScheduleRelative_(TimeSpan delay)
  91. {
  92. using (WinFormsTestUtils.RunTest(out var lbl))
  93. {
  94. var evt = new ManualResetEvent(false);
  95. var id = Environment.CurrentManagedThreadId;
  96. var sch = new ControlScheduler(lbl);
  97. sch.Schedule(delay, () =>
  98. {
  99. lbl.Text = "Okay";
  100. Assert.NotEqual(id, Environment.CurrentManagedThreadId);
  101. sch.Schedule(() =>
  102. {
  103. Assert.Equal("Okay", lbl.Text);
  104. Assert.NotEqual(id, Environment.CurrentManagedThreadId);
  105. evt.Set();
  106. });
  107. });
  108. evt.WaitOne();
  109. }
  110. }
  111. [TestMethod]
  112. public void ScheduleRelative_Nested()
  113. {
  114. using (WinFormsTestUtils.RunTest(out var lbl))
  115. {
  116. var evt = new ManualResetEvent(false);
  117. var id = Environment.CurrentManagedThreadId;
  118. var sch = new ControlScheduler(lbl);
  119. sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
  120. {
  121. sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
  122. {
  123. lbl.Text = "Okay";
  124. Assert.NotEqual(id, Environment.CurrentManagedThreadId);
  125. sch.Schedule(() =>
  126. {
  127. Assert.Equal("Okay", lbl.Text);
  128. Assert.NotEqual(id, Environment.CurrentManagedThreadId);
  129. evt.Set();
  130. });
  131. });
  132. });
  133. evt.WaitOne();
  134. }
  135. }
  136. [TestMethod]
  137. public void ScheduleRelative_Cancel()
  138. {
  139. using (WinFormsTestUtils.RunTest(out var lbl))
  140. {
  141. var evt = new ManualResetEvent(false);
  142. var id = Environment.CurrentManagedThreadId;
  143. var sch = new ControlScheduler(lbl);
  144. sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
  145. {
  146. lbl.Text = "Okay";
  147. Assert.NotEqual(id, Environment.CurrentManagedThreadId);
  148. var d = sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
  149. {
  150. lbl.Text = "Oops!";
  151. });
  152. sch.Schedule(() =>
  153. {
  154. d.Dispose();
  155. });
  156. sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
  157. {
  158. Assert.Equal("Okay", lbl.Text);
  159. Assert.NotEqual(id, Environment.CurrentManagedThreadId);
  160. evt.Set();
  161. });
  162. });
  163. evt.WaitOne();
  164. }
  165. }
  166. [TestMethod]
  167. public void SchedulePeriodic_ArgumentChecking()
  168. {
  169. var s = new ControlScheduler(new Label());
  170. #pragma warning disable IDE0034 // (Simplify 'default'.) Want to be explicit about overload being tested.
  171. ReactiveAssert.Throws<ArgumentNullException>(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
  172. #pragma warning restore IDE0034
  173. ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.Zero, x => x));
  174. ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.FromMilliseconds(1).Subtract(TimeSpan.FromTicks(1)), x => x));
  175. }
  176. [TestMethod]
  177. public void SchedulePeriodic()
  178. {
  179. using (WinFormsTestUtils.RunTest(out var lbl))
  180. {
  181. var evt = new ManualResetEvent(false);
  182. var id = Environment.CurrentManagedThreadId;
  183. var sch = new ControlScheduler(lbl);
  184. var d = new SingleAssignmentDisposable();
  185. d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n =>
  186. {
  187. lbl.Text = "Okay " + n;
  188. Assert.NotEqual(id, Environment.CurrentManagedThreadId);
  189. if (n == 3)
  190. {
  191. d.Dispose();
  192. sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
  193. {
  194. Assert.Equal("Okay 3", lbl.Text);
  195. Assert.NotEqual(id, Environment.CurrentManagedThreadId);
  196. evt.Set();
  197. });
  198. }
  199. if (n > 3)
  200. {
  201. Assert.True(false);
  202. }
  203. return n + 1;
  204. });
  205. evt.WaitOne();
  206. }
  207. }
  208. [TestMethod]
  209. public void SchedulePeriodic_Nested()
  210. {
  211. using (WinFormsTestUtils.RunTest(out var lbl))
  212. {
  213. var evt = new ManualResetEvent(false);
  214. var id = Environment.CurrentManagedThreadId;
  215. var sch = new ControlScheduler(lbl);
  216. sch.Schedule(() =>
  217. {
  218. lbl.Text = "Okay";
  219. var d = new SingleAssignmentDisposable();
  220. d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n =>
  221. {
  222. lbl.Text = "Okay " + n;
  223. Assert.NotEqual(id, Environment.CurrentManagedThreadId);
  224. if (n == 3)
  225. {
  226. d.Dispose();
  227. sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
  228. {
  229. Assert.Equal("Okay 3", lbl.Text);
  230. Assert.NotEqual(id, Environment.CurrentManagedThreadId);
  231. evt.Set();
  232. });
  233. }
  234. return n + 1;
  235. });
  236. });
  237. evt.WaitOne();
  238. }
  239. }
  240. }
  241. }
  242. #endif