DefaultConcurrencyAbstractionLayerTest.cs 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. // Licensed to the .NET Foundation under one or more agreements.
  2. // The .NET Foundation licenses this file to you under the Apache 2.0 License.
  3. // See the LICENSE file in the project root for more information.
  4. #if !NO_REMOTING
  5. using System;
  6. using System.Reactive.Concurrency;
  7. using System.Reactive.PlatformServices;
  8. using System.Runtime.CompilerServices;
  9. using System.Threading;
  10. using Xunit;
  11. namespace ReactiveTests.Tests
  12. {
  13. [Serializable]
  14. public class DefaultConcurrencyAbstractionLayerTest
  15. {
  16. private AppDomain _domain;
  17. public DefaultConcurrencyAbstractionLayerTest()
  18. {
  19. if (_domain == null)
  20. {
  21. _domain = AppDomain.CreateDomain("Default_CAL", null, new AppDomainSetup { ApplicationBase = AppDomain.CurrentDomain.BaseDirectory });
  22. }
  23. }
  24. private void Run(CrossAppDomainDelegate a)
  25. {
  26. _domain.DoCallBack(a);
  27. }
  28. [Fact]
  29. public void Sleep()
  30. {
  31. var ran = new MarshalByRefCell<bool>();
  32. _domain.SetData("state", ran);
  33. Run(() =>
  34. {
  35. Scheduler.Immediate.Schedule(TimeSpan.FromMilliseconds(1), () =>
  36. {
  37. var state = (MarshalByRefCell<bool>)_domain.GetData("state");
  38. state.Value = true;
  39. });
  40. });
  41. Assert.True(ran.Value);
  42. }
  43. [Fact]
  44. public void QueueUserWorkItem()
  45. {
  46. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  47. _domain.SetData("state", e);
  48. Run(() =>
  49. {
  50. Scheduler.Default.Schedule(() =>
  51. {
  52. var state = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("state");
  53. state.Value.Set();
  54. });
  55. });
  56. e.Value.WaitOne();
  57. }
  58. [Fact]
  59. public void StartTimer()
  60. {
  61. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  62. _domain.SetData("state", e);
  63. Run(() =>
  64. {
  65. Scheduler.Default.Schedule(TimeSpan.FromMilliseconds(10), () =>
  66. {
  67. var state = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("state");
  68. state.Value.Set();
  69. });
  70. });
  71. e.Value.WaitOne();
  72. }
  73. [Fact]
  74. public void StartTimer_Cancel()
  75. {
  76. Run(StartTimer_Cancel_Callback);
  77. }
  78. private static void StartTimer_Cancel_Callback()
  79. {
  80. Scheduler.Default.Schedule(TimeSpan.FromSeconds(60), () =>
  81. {
  82. throw new InvalidOperationException("This shouldn't have happened!");
  83. }).Dispose();
  84. }
  85. [Fact]
  86. public void StartPeriodicTimer()
  87. {
  88. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  89. _domain.SetData("state", e);
  90. Run(() =>
  91. {
  92. var n = 0;
  93. Scheduler.Default.SchedulePeriodic(TimeSpan.FromMilliseconds(10), () =>
  94. {
  95. var state = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("state");
  96. if (n++ == 10)
  97. {
  98. state.Value.Set();
  99. }
  100. });
  101. });
  102. e.Value.WaitOne();
  103. }
  104. [Fact]
  105. public void StartPeriodicTimer_Cancel()
  106. {
  107. Run(StartPeriodicTimer_Cancel_Callback);
  108. }
  109. private static void StartPeriodicTimer_Cancel_Callback()
  110. {
  111. Scheduler.Default.SchedulePeriodic(TimeSpan.FromSeconds(60), () =>
  112. {
  113. throw new InvalidOperationException("This shouldn't have happened!");
  114. }).Dispose();
  115. }
  116. [Fact]
  117. public void StartPeriodicTimer_Fast()
  118. {
  119. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  120. _domain.SetData("state", e);
  121. Run(() =>
  122. {
  123. var n = 0;
  124. Scheduler.Default.SchedulePeriodic(TimeSpan.Zero, () =>
  125. {
  126. var state = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("state");
  127. if (n++ == 10)
  128. {
  129. state.Value.Set();
  130. }
  131. });
  132. });
  133. e.Value.WaitOne();
  134. }
  135. [Fact]
  136. public void StartPeriodicTimer_Fast_Cancel()
  137. {
  138. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  139. _domain.SetData("set_cancel", e);
  140. Run(() =>
  141. {
  142. var n = 0;
  143. var hasAtLeastOneValue = new ManualResetEvent(false);
  144. var schedule = Scheduler.Default.SchedulePeriodic(TimeSpan.Zero, () =>
  145. {
  146. _domain.SetData("value", n++);
  147. hasAtLeastOneValue.Set();
  148. });
  149. _domain.SetData("cancel", new MarshalByRefAction(schedule.Dispose));
  150. hasAtLeastOneValue.WaitOne();
  151. var setCancel = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("set_cancel");
  152. setCancel.Value.Set();
  153. });
  154. e.Value.WaitOne();
  155. var value = (int)_domain.GetData("value");
  156. var cancel = (MarshalByRefAction)_domain.GetData("cancel");
  157. cancel.Invoke();
  158. Thread.Sleep(TimeSpan.FromMilliseconds(50));
  159. var newValue = (int)_domain.GetData("value");
  160. Assert.True(newValue >= value);
  161. Thread.Sleep(TimeSpan.FromMilliseconds(50));
  162. value = (int)_domain.GetData("value");
  163. Assert.Equal(newValue, value);
  164. }
  165. [Fact]
  166. public void CreateThread()
  167. {
  168. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  169. _domain.SetData("state", e);
  170. var r = new MarshalByRefCell<string> { Value = "" };
  171. _domain.SetData("res", r);
  172. Run(() =>
  173. {
  174. var state = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("state");
  175. var res = (MarshalByRefCell<string>)_domain.GetData("res");
  176. var svc = (IServiceProvider)Scheduler.Default;
  177. var per = (ISchedulerPeriodic)svc.GetService(typeof(ISchedulerPeriodic));
  178. if (per == null)
  179. {
  180. res.Value = "Failed to get ISchedulerPeriodic.";
  181. state.Value.Set();
  182. return;
  183. }
  184. var slr = (ISchedulerLongRunning)svc.GetService(typeof(ISchedulerLongRunning));
  185. if (slr == null)
  186. {
  187. res.Value = "Failed to get ISchedulerLongRunning.";
  188. state.Value.Set();
  189. return;
  190. }
  191. var success = false;
  192. try
  193. {
  194. slr.ScheduleLongRunning(42, null);
  195. }
  196. catch (ArgumentNullException)
  197. {
  198. success = true;
  199. }
  200. if (!success)
  201. {
  202. res.Value = "Failed null check ScheduleLongRunning.";
  203. state.Value.Set();
  204. return;
  205. }
  206. state.Value.Set();
  207. #if !NO_THREAD
  208. var w = new ManualResetEvent(false);
  209. var d = slr.ScheduleLongRunning(cancel =>
  210. {
  211. while (!cancel.IsDisposed)
  212. {
  213. ;
  214. }
  215. w.Set();
  216. });
  217. Thread.Sleep(50);
  218. d.Dispose();
  219. w.WaitOne();
  220. #else
  221. state.Value.Set();
  222. #endif
  223. });
  224. e.Value.WaitOne();
  225. Assert.True(string.IsNullOrEmpty(r.Value));
  226. }
  227. [Fact]
  228. public void Cant_Locate_Scheduler()
  229. {
  230. Cant_Locate_Scheduler_NoPlib();
  231. }
  232. [MethodImpl(MethodImplOptions.NoInlining)]
  233. private void Cant_Locate_Scheduler_NoPlib()
  234. {
  235. var e = new MarshalByRefCell<bool>();
  236. _domain.SetData("state", e);
  237. Run(() =>
  238. {
  239. var state = (MarshalByRefCell<bool>)_domain.GetData("state");
  240. try
  241. {
  242. state.Value = Scheduler.TaskPool != null;
  243. }
  244. catch (Exception)
  245. {
  246. state.Value = false;
  247. }
  248. });
  249. Assert.True(e.Value);
  250. }
  251. #if !NO_PERF
  252. [Fact]
  253. public void Stopwatch()
  254. {
  255. var e = new MarshalByRefCell<bool>();
  256. _domain.SetData("state", e);
  257. Run(() =>
  258. {
  259. var state = (MarshalByRefCell<bool>)_domain.GetData("state");
  260. var sw = Scheduler.Default.StartStopwatch();
  261. var fst = sw.Elapsed;
  262. Thread.Sleep(100);
  263. var snd = sw.Elapsed;
  264. state.Value = snd > fst;
  265. });
  266. Assert.True(e.Value);
  267. }
  268. #endif
  269. [Fact]
  270. public void EnsureLoaded()
  271. {
  272. Assert.True(EnlightenmentProvider.EnsureLoaded());
  273. }
  274. }
  275. public class MarshalByRefCell<T> : MarshalByRefObject
  276. {
  277. public T Value;
  278. public override object InitializeLifetimeService()
  279. {
  280. return null;
  281. }
  282. }
  283. public class MarshalByRefAction : MarshalByRefObject
  284. {
  285. private readonly Action _action;
  286. public MarshalByRefAction(Action action)
  287. {
  288. _action = action;
  289. }
  290. public void Invoke()
  291. {
  292. _action();
  293. }
  294. public override object InitializeLifetimeService()
  295. {
  296. return null;
  297. }
  298. }
  299. }
  300. #endif