ControlSchedulerTest.cs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. #if HAS_WINFORMS
  3. using System;
  4. using System.Reactive.Concurrency;
  5. using System.Reactive.Disposables;
  6. using System.Diagnostics;
  7. using System.Threading;
  8. using System.Windows.Forms;
  9. using Microsoft.VisualStudio.TestTools.UnitTesting;
  10. using Microsoft.Reactive.Testing;
  11. namespace ReactiveTests.Tests
  12. {
  13. [TestClass]
  14. public class ControlSchedulerTest
  15. {
  16. [TestMethod]
  17. public void Ctor_ArgumentChecking()
  18. {
  19. ReactiveAssert.Throws<ArgumentNullException>(() => new ControlScheduler(null));
  20. }
  21. [TestMethod]
  22. public void Control()
  23. {
  24. var lbl = new Label();
  25. Assert.AreSame(lbl, new ControlScheduler(lbl).Control);
  26. }
  27. [TestMethod]
  28. public void Now()
  29. {
  30. var res = new ControlScheduler(new Label()).Now - DateTime.Now;
  31. Assert.IsTrue(res.Seconds < 1);
  32. }
  33. [TestMethod]
  34. public void Schedule_ArgumentChecking()
  35. {
  36. var s = new ControlScheduler(new Label());
  37. ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, default(Func<IScheduler, int, IDisposable>)));
  38. ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, TimeSpan.FromSeconds(1), default(Func<IScheduler, int, IDisposable>)));
  39. ReactiveAssert.Throws<ArgumentNullException>(() => s.Schedule(42, DateTimeOffset.Now, default(Func<IScheduler, int, IDisposable>)));
  40. }
  41. [TestMethod]
  42. public void Schedule()
  43. {
  44. var evt = new ManualResetEvent(false);
  45. var id = Thread.CurrentThread.ManagedThreadId;
  46. var lbl = CreateLabel();
  47. var sch = new ControlScheduler(lbl);
  48. sch.Schedule(() => { lbl.Text = "Okay"; Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); });
  49. sch.Schedule(() => { Assert.AreEqual("Okay", lbl.Text); Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId); evt.Set(); });
  50. evt.WaitOne();
  51. Application.Exit();
  52. }
  53. [TestMethod]
  54. public void ScheduleError()
  55. {
  56. var evt = new ManualResetEvent(false);
  57. var ex = new Exception();
  58. var lbl = CreateLabelWithHandler(e => {
  59. Assert.AreSame(ex, e);
  60. evt.Set();
  61. });
  62. var sch = new ControlScheduler(lbl);
  63. sch.Schedule(() => { throw ex; });
  64. evt.WaitOne();
  65. Application.Exit();
  66. }
  67. [TestMethod]
  68. public void ScheduleRelative()
  69. {
  70. ScheduleRelative_(TimeSpan.FromSeconds(0.1));
  71. }
  72. [TestMethod]
  73. public void ScheduleRelative_Zero()
  74. {
  75. ScheduleRelative_(TimeSpan.Zero);
  76. }
  77. private void ScheduleRelative_(TimeSpan delay)
  78. {
  79. var evt = new ManualResetEvent(false);
  80. var id = Thread.CurrentThread.ManagedThreadId;
  81. var lbl = CreateLabel();
  82. var sch = new ControlScheduler(lbl);
  83. sch.Schedule(delay, () =>
  84. {
  85. lbl.Text = "Okay";
  86. Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
  87. sch.Schedule(() =>
  88. {
  89. Assert.AreEqual("Okay", lbl.Text);
  90. Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
  91. evt.Set();
  92. });
  93. });
  94. evt.WaitOne();
  95. Application.Exit();
  96. }
  97. [TestMethod]
  98. public void ScheduleRelative_Nested()
  99. {
  100. var evt = new ManualResetEvent(false);
  101. var id = Thread.CurrentThread.ManagedThreadId;
  102. var lbl = CreateLabel();
  103. var sch = new ControlScheduler(lbl);
  104. sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
  105. {
  106. sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
  107. {
  108. lbl.Text = "Okay";
  109. Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
  110. sch.Schedule(() =>
  111. {
  112. Assert.AreEqual("Okay", lbl.Text);
  113. Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
  114. evt.Set();
  115. });
  116. });
  117. });
  118. evt.WaitOne();
  119. Application.Exit();
  120. }
  121. [TestMethod]
  122. public void ScheduleRelative_Cancel()
  123. {
  124. var evt = new ManualResetEvent(false);
  125. var id = Thread.CurrentThread.ManagedThreadId;
  126. var lbl = CreateLabel();
  127. var sch = new ControlScheduler(lbl);
  128. sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
  129. {
  130. lbl.Text = "Okay";
  131. Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
  132. var d = sch.Schedule(TimeSpan.FromSeconds(0.1), () =>
  133. {
  134. lbl.Text = "Oops!";
  135. });
  136. sch.Schedule(() =>
  137. {
  138. d.Dispose();
  139. });
  140. sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
  141. {
  142. Assert.AreEqual("Okay", lbl.Text);
  143. Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
  144. evt.Set();
  145. });
  146. });
  147. evt.WaitOne();
  148. Application.Exit();
  149. }
  150. [TestMethod]
  151. public void SchedulePeriodic_ArgumentChecking()
  152. {
  153. var s = new ControlScheduler(new Label());
  154. ReactiveAssert.Throws<ArgumentNullException>(() => s.SchedulePeriodic(42, TimeSpan.FromSeconds(1), default(Func<int, int>)));
  155. ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.Zero, x => x));
  156. ReactiveAssert.Throws<ArgumentOutOfRangeException>(() => s.SchedulePeriodic(42, TimeSpan.FromMilliseconds(1).Subtract(TimeSpan.FromTicks(1)), x => x));
  157. }
  158. [TestMethod]
  159. public void SchedulePeriodic()
  160. {
  161. var evt = new ManualResetEvent(false);
  162. var id = Thread.CurrentThread.ManagedThreadId;
  163. var lbl = CreateLabel();
  164. var sch = new ControlScheduler(lbl);
  165. var d = new SingleAssignmentDisposable();
  166. d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n =>
  167. {
  168. lbl.Text = "Okay " + n;
  169. Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
  170. if (n == 3)
  171. {
  172. d.Dispose();
  173. sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
  174. {
  175. Assert.AreEqual("Okay 3", lbl.Text);
  176. Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
  177. evt.Set();
  178. });
  179. }
  180. if (n > 3)
  181. {
  182. Assert.Fail();
  183. }
  184. return n + 1;
  185. });
  186. evt.WaitOne();
  187. Application.Exit();
  188. }
  189. [TestMethod]
  190. public void SchedulePeriodic_Nested()
  191. {
  192. var evt = new ManualResetEvent(false);
  193. var id = Thread.CurrentThread.ManagedThreadId;
  194. var lbl = CreateLabel();
  195. var sch = new ControlScheduler(lbl);
  196. sch.Schedule(() =>
  197. {
  198. lbl.Text = "Okay";
  199. var d = new SingleAssignmentDisposable();
  200. d.Disposable = sch.SchedulePeriodic(1, TimeSpan.FromSeconds(0.1), n =>
  201. {
  202. lbl.Text = "Okay " + n;
  203. Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
  204. if (n == 3)
  205. {
  206. d.Dispose();
  207. sch.Schedule(TimeSpan.FromSeconds(0.2), () =>
  208. {
  209. Assert.AreEqual("Okay 3", lbl.Text);
  210. Assert.AreNotEqual(id, Thread.CurrentThread.ManagedThreadId);
  211. evt.Set();
  212. });
  213. }
  214. return n + 1;
  215. });
  216. });
  217. evt.WaitOne();
  218. Application.Exit();
  219. }
  220. private Label CreateLabel()
  221. {
  222. var loaded = new ManualResetEvent(false);
  223. var lbl = default(Label);
  224. var t = new Thread(() =>
  225. {
  226. lbl = new Label();
  227. var frm = new Form { Controls = { lbl }, Width = 0, Height = 0, FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false };
  228. frm.Load += (_, __) =>
  229. {
  230. loaded.Set();
  231. };
  232. Application.Run(frm);
  233. });
  234. t.SetApartmentState(ApartmentState.STA);
  235. t.Start();
  236. loaded.WaitOne();
  237. return lbl;
  238. }
  239. private Label CreateLabelWithHandler(Action<Exception> handler)
  240. {
  241. var loaded = new ManualResetEvent(false);
  242. var lbl = default(Label);
  243. var t = new Thread(() =>
  244. {
  245. lbl = new Label();
  246. var frm = new Form { Controls = { lbl }, Width = 0, Height = 0, FormBorderStyle = FormBorderStyle.None, ShowInTaskbar = false };
  247. frm.Load += (_, __) =>
  248. {
  249. loaded.Set();
  250. };
  251. Application.ThreadException += (o, e) =>
  252. {
  253. handler(e.Exception);
  254. };
  255. Application.Run(frm);
  256. });
  257. t.SetApartmentState(ApartmentState.STA);
  258. t.Start();
  259. loaded.WaitOne();
  260. return lbl;
  261. }
  262. }
  263. }
  264. #endif