You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

AsyncAutoResentEventTests.cs 7.6 KiB

5 vuotta sitten
5 vuotta sitten
5 vuotta sitten
6 vuotta sitten
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. using System;
  2. using System.Threading;
  3. using System.Threading.Tasks;
  4. using Microsoft.VisualStudio.TestTools.UnitTesting;
  5. using MQTTnet.Internal;
  6. namespace MQTTnet.Tests
  7. {
  8. [TestClass]
  9. // Inspired from the vs-threading tests (https://github.com/Microsoft/vs-threading/blob/master/src/Microsoft.VisualStudio.Threading.Tests/AsyncAutoResetEventTests.cs)
  10. public class AsyncAutoResetEventTests
  11. {
  12. private readonly AsyncAutoResetEvent _aare;
  13. public AsyncAutoResetEventTests()
  14. {
  15. _aare = new AsyncAutoResetEvent();
  16. }
  17. [TestMethod]
  18. public async Task Cleanup_Waiters()
  19. {
  20. var @lock = new AsyncAutoResetEvent();
  21. var waitOnePassed = false;
  22. Task.Run(async () =>
  23. {
  24. await @lock.WaitOneAsync(TimeSpan.FromSeconds(2));
  25. waitOnePassed = true;
  26. });
  27. await Task.Delay(500);
  28. Assert.AreEqual(1, @lock.WaitersCount);
  29. @lock.Set();
  30. await Task.Delay(1000);
  31. Assert.IsTrue(waitOnePassed);
  32. Assert.AreEqual(0, @lock.WaitersCount);
  33. }
  34. [TestMethod]
  35. public async Task SingleThreadedPulse()
  36. {
  37. for (int i = 0; i < 5; i++)
  38. {
  39. var t = _aare.WaitOneAsync();
  40. Assert.IsFalse(t.IsCompleted);
  41. _aare.Set();
  42. await t;
  43. Assert.IsTrue(t.IsCompleted);
  44. }
  45. }
  46. [TestMethod]
  47. public async Task MultipleSetOnlySignalsOnce()
  48. {
  49. _aare.Set();
  50. _aare.Set();
  51. await _aare.WaitOneAsync();
  52. var t = _aare.WaitOneAsync();
  53. Assert.IsFalse(t.IsCompleted);
  54. await Task.Delay(500);
  55. Assert.IsFalse(t.IsCompleted);
  56. _aare.Set();
  57. await t;
  58. Assert.IsTrue(t.IsCompleted);
  59. }
  60. [TestMethod]
  61. public async Task OrderPreservingQueue()
  62. {
  63. var waiters = new Task[5];
  64. for (int i = 0; i < waiters.Length; i++)
  65. {
  66. waiters[i] = _aare.WaitOneAsync();
  67. }
  68. for (int i = 0; i < waiters.Length; i++)
  69. {
  70. _aare.Set();
  71. await waiters[i].ConfigureAwait(false);
  72. }
  73. }
  74. // This test does not work in appveyor but on local machine it does!?
  75. /////// <summary>
  76. /////// Verifies that inlining continuations do not have to complete execution before Set() returns.
  77. /////// </summary>
  78. ////[TestMethod]
  79. ////public async Task SetReturnsBeforeInlinedContinuations()
  80. ////{
  81. //// var setReturned = new ManualResetEventSlim();
  82. //// var inlinedContinuation = _aare.WaitOneAsync()
  83. //// .ContinueWith(delegate
  84. //// {
  85. //// // Arrange to synchronously block the continuation until Set() has returned,
  86. //// // which would deadlock if Set does not return until inlined continuations complete.
  87. //// Assert.IsTrue(setReturned.Wait(500));
  88. //// });
  89. //// await Task.Delay(100);
  90. //// _aare.Set();
  91. //// setReturned.Set();
  92. //// Assert.IsTrue(inlinedContinuation.Wait(500));
  93. ////}
  94. [TestMethod]
  95. public void WaitAsync_WithCancellationToken()
  96. {
  97. var cts = new CancellationTokenSource();
  98. Task waitTask = _aare.WaitOneAsync(cts.Token);
  99. Assert.IsFalse(waitTask.IsCompleted);
  100. // Cancel the request and ensure that it propagates to the task.
  101. cts.Cancel();
  102. try
  103. {
  104. waitTask.GetAwaiter().GetResult();
  105. Assert.IsTrue(false, "Task was expected to transition to a canceled state.");
  106. }
  107. catch (OperationCanceledException ex)
  108. {
  109. }
  110. // Now set the event and verify that a future waiter gets the signal immediately.
  111. _aare.Set();
  112. waitTask = _aare.WaitOneAsync();
  113. Assert.AreEqual(TaskStatus.WaitingForActivation, waitTask.Status);
  114. }
  115. [TestMethod]
  116. public void WaitAsync_WithCancellationToken_Precanceled()
  117. {
  118. // We construct our own pre-canceled token so that we can do
  119. // a meaningful identity check later.
  120. var tokenSource = new CancellationTokenSource();
  121. tokenSource.Cancel();
  122. var token = tokenSource.Token;
  123. // Verify that a pre-set signal is not reset by a canceled wait request.
  124. _aare.Set();
  125. try
  126. {
  127. _aare.WaitOneAsync(token).GetAwaiter().GetResult();
  128. Assert.IsTrue(false, "Task was expected to transition to a canceled state.");
  129. }
  130. catch (OperationCanceledException ex)
  131. {
  132. Assert.AreEqual(token, ex.CancellationToken);
  133. }
  134. // Verify that the signal was not acquired.
  135. Task waitTask = _aare.WaitOneAsync();
  136. Assert.AreEqual(TaskStatus.RanToCompletion, waitTask.Status);
  137. }
  138. [TestMethod]
  139. public async Task WaitAsync_WithTimeout()
  140. {
  141. Task waitTask = _aare.WaitOneAsync(TimeSpan.FromMilliseconds(500));
  142. Assert.IsFalse(waitTask.IsCompleted);
  143. // Cancel the request and ensure that it propagates to the task.
  144. await Task.Delay(1000).ConfigureAwait(false);
  145. try
  146. {
  147. waitTask.GetAwaiter().GetResult();
  148. Assert.IsTrue(false, "Task was expected to transition to a timeout state.");
  149. }
  150. catch (TimeoutException)
  151. {
  152. Assert.IsTrue(true);
  153. }
  154. // Now set the event and verify that a future waiter gets the signal immediately.
  155. _aare.Set();
  156. waitTask = _aare.WaitOneAsync(TimeSpan.FromMilliseconds(500));
  157. Assert.AreEqual(TaskStatus.RanToCompletion, waitTask.Status);
  158. }
  159. [TestMethod]
  160. public void WaitAsync_Canceled_DoesNotInlineContinuations()
  161. {
  162. var cts = new CancellationTokenSource();
  163. var task = _aare.WaitOneAsync(cts.Token);
  164. var completingActionFinished = new ManualResetEventSlim();
  165. var continuation = task.ContinueWith(
  166. _ => Assert.IsTrue(completingActionFinished.Wait(500)),
  167. CancellationToken.None,
  168. TaskContinuationOptions.None,
  169. TaskScheduler.Default);
  170. cts.Cancel();
  171. completingActionFinished.Set();
  172. // Rethrow the exception if it turned out it deadlocked.
  173. continuation.GetAwaiter().GetResult();
  174. }
  175. [TestMethod]
  176. public async Task AsyncAutoResetEvent()
  177. {
  178. var aare = new AsyncAutoResetEvent();
  179. var globalI = 0;
  180. #pragma warning disable 4014
  181. Task.Run(async () =>
  182. #pragma warning restore 4014
  183. {
  184. await aare.WaitOneAsync(CancellationToken.None);
  185. globalI += 1;
  186. });
  187. #pragma warning disable 4014
  188. Task.Run(async () =>
  189. #pragma warning restore 4014
  190. {
  191. await aare.WaitOneAsync(CancellationToken.None);
  192. globalI += 2;
  193. });
  194. await Task.Delay(500);
  195. aare.Set();
  196. await Task.Delay(500);
  197. aare.Set();
  198. await Task.Delay(100);
  199. Assert.AreEqual(3, globalI);
  200. }
  201. }
  202. }