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.
 
 
 
 

210 rivejä
6.9 KiB

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