Non puoi selezionare più di 25 argomenti Gli argomenti devono iniziare con una lettera o un numero, possono includere trattini ('-') e possono essere lunghi fino a 35 caratteri.
 
 
 
 

211 righe
7.0 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. // This test does not work in appveyor but on local machine it does!?
  58. /////// <summary>
  59. /////// Verifies that inlining continuations do not have to complete execution before Set() returns.
  60. /////// </summary>
  61. ////[TestMethod]
  62. ////public async Task SetReturnsBeforeInlinedContinuations()
  63. ////{
  64. //// var setReturned = new ManualResetEventSlim();
  65. //// var inlinedContinuation = _aare.WaitOneAsync()
  66. //// .ContinueWith(delegate
  67. //// {
  68. //// // Arrange to synchronously block the continuation until Set() has returned,
  69. //// // which would deadlock if Set does not return until inlined continuations complete.
  70. //// Assert.IsTrue(setReturned.Wait(500));
  71. //// });
  72. //// await Task.Delay(100);
  73. //// _aare.Set();
  74. //// setReturned.Set();
  75. //// Assert.IsTrue(inlinedContinuation.Wait(500));
  76. ////}
  77. [TestMethod]
  78. public void WaitAsync_WithCancellationToken()
  79. {
  80. var cts = new CancellationTokenSource();
  81. Task waitTask = _aare.WaitOneAsync(cts.Token);
  82. Assert.IsFalse(waitTask.IsCompleted);
  83. // Cancel the request and ensure that it propagates to the task.
  84. cts.Cancel();
  85. try
  86. {
  87. waitTask.GetAwaiter().GetResult();
  88. Assert.IsTrue(false, "Task was expected to transition to a canceled state.");
  89. }
  90. catch (OperationCanceledException ex)
  91. {
  92. Assert.AreEqual(cts.Token, ex.CancellationToken);
  93. }
  94. // Now set the event and verify that a future waiter gets the signal immediately.
  95. _aare.Set();
  96. waitTask = _aare.WaitOneAsync();
  97. Assert.AreEqual(TaskStatus.RanToCompletion, waitTask.Status);
  98. }
  99. [TestMethod]
  100. public void WaitAsync_WithCancellationToken_Precanceled()
  101. {
  102. // We construct our own pre-canceled token so that we can do
  103. // a meaningful identity check later.
  104. var tokenSource = new CancellationTokenSource();
  105. tokenSource.Cancel();
  106. var token = tokenSource.Token;
  107. // Verify that a pre-set signal is not reset by a canceled wait request.
  108. _aare.Set();
  109. try
  110. {
  111. _aare.WaitOneAsync(token).GetAwaiter().GetResult();
  112. Assert.IsTrue(false, "Task was expected to transition to a canceled state.");
  113. }
  114. catch (OperationCanceledException ex)
  115. {
  116. Assert.AreEqual(token, ex.CancellationToken);
  117. }
  118. // Verify that the signal was not acquired.
  119. Task waitTask = _aare.WaitOneAsync();
  120. Assert.AreEqual(TaskStatus.RanToCompletion, waitTask.Status);
  121. }
  122. [TestMethod]
  123. public async Task WaitAsync_WithTimeout()
  124. {
  125. Task waitTask = _aare.WaitOneAsync(TimeSpan.FromMilliseconds(500));
  126. Assert.IsFalse(waitTask.IsCompleted);
  127. // Cancel the request and ensure that it propagates to the task.
  128. await Task.Delay(1000).ConfigureAwait(false);
  129. try
  130. {
  131. waitTask.GetAwaiter().GetResult();
  132. Assert.IsTrue(false, "Task was expected to transition to a timeout state.");
  133. }
  134. catch (TimeoutException)
  135. {
  136. Assert.IsTrue(true);
  137. }
  138. // Now set the event and verify that a future waiter gets the signal immediately.
  139. _aare.Set();
  140. waitTask = _aare.WaitOneAsync(TimeSpan.FromMilliseconds(500));
  141. Assert.AreEqual(TaskStatus.RanToCompletion, waitTask.Status);
  142. }
  143. [TestMethod]
  144. public void WaitAsync_Canceled_DoesNotInlineContinuations()
  145. {
  146. var cts = new CancellationTokenSource();
  147. var task = _aare.WaitOneAsync(cts.Token);
  148. var completingActionFinished = new ManualResetEventSlim();
  149. var continuation = task.ContinueWith(
  150. _ => Assert.IsTrue(completingActionFinished.Wait(500)),
  151. CancellationToken.None,
  152. TaskContinuationOptions.None,
  153. TaskScheduler.Default);
  154. cts.Cancel();
  155. completingActionFinished.Set();
  156. // Rethrow the exception if it turned out it deadlocked.
  157. continuation.GetAwaiter().GetResult();
  158. }
  159. [TestMethod]
  160. public async Task AsyncAutoResetEvent()
  161. {
  162. var aare = new AsyncAutoResetEvent();
  163. var globalI = 0;
  164. #pragma warning disable 4014
  165. Task.Run(async () =>
  166. #pragma warning restore 4014
  167. {
  168. await aare.WaitOneAsync(CancellationToken.None);
  169. globalI += 1;
  170. });
  171. #pragma warning disable 4014
  172. Task.Run(async () =>
  173. #pragma warning restore 4014
  174. {
  175. await aare.WaitOneAsync(CancellationToken.None);
  176. globalI += 2;
  177. });
  178. await Task.Delay(500);
  179. aare.Set();
  180. await Task.Delay(500);
  181. aare.Set();
  182. await Task.Delay(100);
  183. Assert.AreEqual(3, globalI);
  184. }
  185. }
  186. }