DefaultConcurrencyAbstractionLayerTest.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. #if !NO_REMOTING
  3. using System;
  4. using System.IO;
  5. using System.Reactive.Concurrency;
  6. using System.Reactive.PlatformServices;
  7. using System.Runtime.CompilerServices;
  8. using System.Threading;
  9. using Xunit;
  10. namespace ReactiveTests.Tests
  11. {
  12. [Serializable]
  13. public class DefaultConcurrencyAbstractionLayerTest
  14. {
  15. private AppDomain _domain;
  16. public DefaultConcurrencyAbstractionLayerTest()
  17. {
  18. if (_domain == null)
  19. {
  20. var cur = AppDomain.CurrentDomain.BaseDirectory;
  21. var sub = Path.Combine(cur, "NoCAL");
  22. if (!Directory.Exists(sub))
  23. {
  24. Directory.CreateDirectory(sub);
  25. }
  26. //
  27. // We want to replace the files to make the debugging experience
  28. // better. If the directory already exists, a recompilation does
  29. // not get rid of it. At some point, we should revisit this whole
  30. // directory creation during the test run and try to do away with
  31. // it by making it part of the build process.
  32. //
  33. foreach (var file in Directory.GetFiles(cur))
  34. {
  35. var fn = Path.GetFileName(file);
  36. if (!file.Contains("PlatformServices"))
  37. {
  38. var dest = Path.Combine(sub, fn);
  39. if (File.Exists(dest))
  40. {
  41. try
  42. {
  43. File.Delete(dest);
  44. }
  45. catch (UnauthorizedAccessException)
  46. {
  47. //
  48. // File in use; expected after first pass.
  49. //
  50. }
  51. }
  52. if (!File.Exists(dest))
  53. {
  54. File.Copy(Path.Combine(cur, fn), Path.Combine(sub, fn));
  55. }
  56. }
  57. }
  58. _domain = AppDomain.CreateDomain("Default_CAL", null, new AppDomainSetup { ApplicationBase = sub });
  59. }
  60. }
  61. private void Run(CrossAppDomainDelegate a)
  62. {
  63. _domain.DoCallBack(a);
  64. }
  65. [Fact]
  66. public void Sleep()
  67. {
  68. var ran = new MarshalByRefCell<bool>();
  69. _domain.SetData("state", ran);
  70. Run(() =>
  71. {
  72. Scheduler.Immediate.Schedule(TimeSpan.FromMilliseconds(1), () =>
  73. {
  74. var state = (MarshalByRefCell<bool>)_domain.GetData("state");
  75. state.Value = true;
  76. });
  77. });
  78. Assert.True(ran.Value);
  79. }
  80. [Fact]
  81. public void QueueUserWorkItem()
  82. {
  83. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  84. _domain.SetData("state", e);
  85. Run(() =>
  86. {
  87. Scheduler.Default.Schedule(() =>
  88. {
  89. var state = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("state");
  90. state.Value.Set();
  91. });
  92. });
  93. e.Value.WaitOne();
  94. }
  95. [Fact]
  96. public void StartTimer()
  97. {
  98. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  99. _domain.SetData("state", e);
  100. Run(() =>
  101. {
  102. Scheduler.Default.Schedule(TimeSpan.FromMilliseconds(10), () =>
  103. {
  104. var state = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("state");
  105. state.Value.Set();
  106. });
  107. });
  108. e.Value.WaitOne();
  109. }
  110. [Fact]
  111. public void StartTimer_Cancel()
  112. {
  113. Run(StartTimer_Cancel_Callback);
  114. }
  115. private static void StartTimer_Cancel_Callback()
  116. {
  117. Scheduler.Default.Schedule(TimeSpan.FromSeconds(60), () =>
  118. {
  119. throw new InvalidOperationException("This shouldn't have happened!");
  120. }).Dispose();
  121. }
  122. [Fact]
  123. public void StartPeriodicTimer()
  124. {
  125. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  126. _domain.SetData("state", e);
  127. Run(() =>
  128. {
  129. var n = 0;
  130. Scheduler.Default.SchedulePeriodic(TimeSpan.FromMilliseconds(10), () =>
  131. {
  132. var state = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("state");
  133. if (n++ == 10)
  134. state.Value.Set();
  135. });
  136. });
  137. e.Value.WaitOne();
  138. }
  139. [Fact]
  140. public void StartPeriodicTimer_Cancel()
  141. {
  142. Run(StartPeriodicTimer_Cancel_Callback);
  143. }
  144. private static void StartPeriodicTimer_Cancel_Callback()
  145. {
  146. Scheduler.Default.SchedulePeriodic(TimeSpan.FromSeconds(60), () =>
  147. {
  148. throw new InvalidOperationException("This shouldn't have happened!");
  149. }).Dispose();
  150. }
  151. [Fact]
  152. public void StartPeriodicTimer_Fast()
  153. {
  154. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  155. _domain.SetData("state", e);
  156. Run(() =>
  157. {
  158. var n = 0;
  159. Scheduler.Default.SchedulePeriodic(TimeSpan.Zero, () =>
  160. {
  161. var state = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("state");
  162. if (n++ == 10)
  163. state.Value.Set();
  164. });
  165. });
  166. e.Value.WaitOne();
  167. }
  168. [Fact]
  169. public void StartPeriodicTimer_Fast_Cancel()
  170. {
  171. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  172. _domain.SetData("set_cancel", e);
  173. Run(() =>
  174. {
  175. var n = 0;
  176. var hasAtLeastOneValue = new ManualResetEvent(false);
  177. var schedule = Scheduler.Default.SchedulePeriodic(TimeSpan.Zero, () =>
  178. {
  179. _domain.SetData("value", n++);
  180. hasAtLeastOneValue.Set();
  181. });
  182. _domain.SetData("cancel", new MarshalByRefAction(schedule.Dispose));
  183. hasAtLeastOneValue.WaitOne();
  184. var setCancel = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("set_cancel");
  185. setCancel.Value.Set();
  186. });
  187. e.Value.WaitOne();
  188. var value = (int)_domain.GetData("value");
  189. var cancel = (MarshalByRefAction)_domain.GetData("cancel");
  190. cancel.Invoke();
  191. Thread.Sleep(TimeSpan.FromMilliseconds(50));
  192. var newValue = (int)_domain.GetData("value");
  193. Assert.True(newValue >= value);
  194. Thread.Sleep(TimeSpan.FromMilliseconds(50));
  195. value = (int)_domain.GetData("value");
  196. Assert.Equal(newValue, value);
  197. }
  198. [Fact]
  199. public void CreateThread()
  200. {
  201. var e = new MarshalByRefCell<ManualResetEvent> { Value = new ManualResetEvent(false) };
  202. _domain.SetData("state", e);
  203. var r = new MarshalByRefCell<string> { Value = "" };
  204. _domain.SetData("res", r);
  205. Run(() =>
  206. {
  207. var state = (MarshalByRefCell<ManualResetEvent>)_domain.GetData("state");
  208. var res = (MarshalByRefCell<string>)_domain.GetData("res");
  209. var svc = (IServiceProvider)Scheduler.Default;
  210. var per = (ISchedulerPeriodic)svc.GetService(typeof(ISchedulerPeriodic));
  211. if (per == null)
  212. {
  213. res.Value = "Failed to get ISchedulerPeriodic.";
  214. state.Value.Set();
  215. return;
  216. }
  217. var slr = (ISchedulerLongRunning)svc.GetService(typeof(ISchedulerLongRunning));
  218. if (slr == null)
  219. {
  220. res.Value = "Failed to get ISchedulerLongRunning.";
  221. state.Value.Set();
  222. return;
  223. }
  224. var success = false;
  225. try
  226. {
  227. slr.ScheduleLongRunning(42, null);
  228. }
  229. catch (ArgumentNullException)
  230. {
  231. success = true;
  232. }
  233. if (!success)
  234. {
  235. res.Value = "Failed null check ScheduleLongRunning.";
  236. state.Value.Set();
  237. return;
  238. }
  239. state.Value.Set();
  240. #if !NO_THREAD
  241. var w = new ManualResetEvent(false);
  242. var d = slr.ScheduleLongRunning(cancel =>
  243. {
  244. while (!cancel.IsDisposed)
  245. ;
  246. w.Set();
  247. });
  248. Thread.Sleep(50);
  249. d.Dispose();
  250. w.WaitOne();
  251. #else
  252. state.Value.Set();
  253. #endif
  254. });
  255. e.Value.WaitOne();
  256. Assert.True(string.IsNullOrEmpty(r.Value));
  257. }
  258. #if !NO_TPL
  259. [Fact]
  260. public void Cant_Locate_Scheduler()
  261. {
  262. if (!Utils.IsRunningWithPortableLibraryBinaries())
  263. {
  264. Cant_Locate_Scheduler_NoPlib();
  265. }
  266. }
  267. [MethodImpl(MethodImplOptions.NoInlining)]
  268. private void Cant_Locate_Scheduler_NoPlib()
  269. {
  270. var e = new MarshalByRefCell<Exception>();
  271. _domain.SetData("state", e);
  272. Run(() =>
  273. {
  274. var state = (MarshalByRefCell<Exception>)_domain.GetData("state");
  275. try
  276. {
  277. Scheduler.TaskPool.Schedule(() => { });
  278. }
  279. catch (Exception ex)
  280. {
  281. state.Value = ex;
  282. }
  283. });
  284. Assert.True(e.Value != null && e.Value is NotSupportedException);
  285. }
  286. #endif
  287. #if !NO_PERF && !NO_STOPWATCH
  288. [Fact]
  289. public void Stopwatch()
  290. {
  291. var e = new MarshalByRefCell<bool>();
  292. _domain.SetData("state", e);
  293. Run(() =>
  294. {
  295. var state = (MarshalByRefCell<bool>)_domain.GetData("state");
  296. var sw = Scheduler.Default.StartStopwatch();
  297. var fst = sw.Elapsed;
  298. Thread.Sleep(100);
  299. var snd = sw.Elapsed;
  300. state.Value = snd > fst;
  301. });
  302. Assert.True(e.Value);
  303. }
  304. #endif
  305. [Fact]
  306. public void EnsureLoaded()
  307. {
  308. Assert.True(EnlightenmentProvider.EnsureLoaded());
  309. }
  310. }
  311. public class MarshalByRefCell<T> : MarshalByRefObject
  312. {
  313. public T Value;
  314. }
  315. public class MarshalByRefAction : MarshalByRefObject
  316. {
  317. private readonly Action _action;
  318. public MarshalByRefAction(Action action)
  319. {
  320. _action = action;
  321. }
  322. public void Invoke()
  323. {
  324. _action();
  325. }
  326. }
  327. }
  328. #endif