JobQueueTest.cs 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. using System;
  2. using System.Threading;
  3. using System.Threading.Tasks;
  4. using Robust.Shared.CPUJob.JobQueues;
  5. using Robust.Shared.CPUJob.JobQueues.Queues;
  6. using NUnit.Framework;
  7. using Robust.Shared.Timing;
  8. using Robust.UnitTesting;
  9. namespace Content.Tests.Server.Jobs
  10. {
  11. [TestFixture]
  12. [TestOf(typeof(Job<>))]
  13. [TestOf(typeof(JobQueue))]
  14. public sealed class JobQueueTest : RobustUnitTest
  15. {
  16. /// <summary>
  17. /// Test a job that immediately exits with a value.
  18. /// </summary>
  19. [Test]
  20. public void TestImmediateJob()
  21. {
  22. // Pass debug stopwatch so time doesn't advance.
  23. var sw = new DebugStopwatch();
  24. var queue = new JobQueue(sw);
  25. var job = new ImmediateJob();
  26. queue.EnqueueJob(job);
  27. queue.Process();
  28. Assert.That(job.Status, Is.EqualTo(JobStatus.Finished));
  29. Assert.That(job.Result, Is.EqualTo("honk!"));
  30. }
  31. [Test]
  32. public void TestLongJob()
  33. {
  34. var swA = new DebugStopwatch();
  35. var swB = new DebugStopwatch();
  36. var queue = new LongJobQueue(swB);
  37. var job = new LongJob(swA, swB);
  38. queue.EnqueueJob(job);
  39. queue.Process();
  40. Assert.That(job.Status, Is.EqualTo(JobStatus.Paused));
  41. Assert.That((float)job.DebugTime, new ApproxEqualityConstraint(1f));
  42. queue.Process();
  43. Assert.That(job.Status, Is.EqualTo(JobStatus.Paused));
  44. Assert.That((float)job.DebugTime, new ApproxEqualityConstraint(2f));
  45. queue.Process();
  46. Assert.That(job.Status, Is.EqualTo(JobStatus.Finished));
  47. Assert.That(job.Result, Is.EqualTo("foo!"));
  48. Assert.That((float)job.DebugTime, new ApproxEqualityConstraint(2.4f));
  49. }
  50. [Test]
  51. public void TestLongJobCancel()
  52. {
  53. var swA = new DebugStopwatch();
  54. var swB = new DebugStopwatch();
  55. var queue = new LongJobQueue(swB);
  56. var cts = new CancellationTokenSource();
  57. var job = new LongJob(swA, swB, cts.Token);
  58. queue.EnqueueJob(job);
  59. queue.Process();
  60. Assert.That(job.Status, Is.EqualTo(JobStatus.Paused));
  61. queue.Process();
  62. Assert.That(job.Status, Is.EqualTo(JobStatus.Paused));
  63. cts.Cancel();
  64. queue.Process();
  65. Assert.That(job.Status, Is.EqualTo(JobStatus.Finished));
  66. Assert.That((float)job.DebugTime, new ApproxEqualityConstraint(2.0f));
  67. Assert.That(job.Result, Is.Null);
  68. }
  69. [Test]
  70. public void TestWaitingJob()
  71. {
  72. var sw = new DebugStopwatch();
  73. var queue = new LongJobQueue(sw);
  74. var tcs = new TaskCompletionSource<object>();
  75. var job = new WaitingJob(tcs.Task);
  76. queue.EnqueueJob(job);
  77. queue.Process();
  78. Assert.That(job.Status, Is.EqualTo(JobStatus.Waiting));
  79. queue.Process();
  80. Assert.That(job.Status, Is.EqualTo(JobStatus.Waiting));
  81. tcs.SetResult(1);
  82. queue.Process();
  83. Assert.That(job.Status, Is.EqualTo(JobStatus.Finished));
  84. Assert.That(job.Result, Is.EqualTo("oof!"));
  85. }
  86. [Test]
  87. public void TestWaitingJobCancel()
  88. {
  89. var sw = new DebugStopwatch();
  90. var queue = new LongJobQueue(sw);
  91. var tcs = new TaskCompletionSource<object>();
  92. var job = new WaitingJob(tcs.Task);
  93. queue.EnqueueJob(job);
  94. queue.Process();
  95. Assert.That(job.Status, Is.EqualTo(JobStatus.Waiting));
  96. queue.Process();
  97. Assert.That(job.Status, Is.EqualTo(JobStatus.Waiting));
  98. tcs.SetCanceled();
  99. queue.Process();
  100. Assert.That(job.Status, Is.EqualTo(JobStatus.Finished));
  101. Assert.That(job.Result, Is.Null);
  102. }
  103. private sealed class DebugStopwatch : IStopwatch
  104. {
  105. public TimeSpan Elapsed { get; set; }
  106. public void Restart()
  107. {
  108. Elapsed = TimeSpan.Zero;
  109. }
  110. public void Start()
  111. {
  112. Elapsed = TimeSpan.Zero;
  113. }
  114. }
  115. private sealed class ImmediateJob : Job<string>
  116. {
  117. public ImmediateJob() : base(0)
  118. {
  119. }
  120. protected override Task<string> Process()
  121. {
  122. return Task.FromResult("honk!");
  123. }
  124. }
  125. private sealed class LongJob : Job<string>
  126. {
  127. private readonly DebugStopwatch _stopwatch;
  128. private readonly DebugStopwatch _stopwatchB;
  129. public LongJob(DebugStopwatch stopwatchA, DebugStopwatch stopwatchB, CancellationToken cancel = default) :
  130. base(0.95, stopwatchA, cancel)
  131. {
  132. _stopwatch = stopwatchA;
  133. _stopwatchB = stopwatchB;
  134. }
  135. protected override async Task<string> Process()
  136. {
  137. for (var i = 0; i < 12; i++)
  138. {
  139. // Increment time by 0.2 seconds.
  140. IncrementTime();
  141. await SuspendIfOutOfTime();
  142. }
  143. return "foo!";
  144. }
  145. private void IncrementTime()
  146. {
  147. var diff = TimeSpan.FromSeconds(0.2);
  148. _stopwatch.Elapsed += diff;
  149. _stopwatchB.Elapsed += diff;
  150. }
  151. }
  152. private sealed class LongJobQueue : JobQueue
  153. {
  154. public LongJobQueue(IStopwatch swB) : base(swB)
  155. {
  156. }
  157. public override double MaxTime => 0.9;
  158. }
  159. private sealed class WaitingJob : Job<string>
  160. {
  161. private readonly Task _t;
  162. public WaitingJob(Task t) : base(0)
  163. {
  164. _t = t;
  165. }
  166. protected override async Task<string> Process()
  167. {
  168. await WaitAsyncTask(_t);
  169. return "oof!";
  170. }
  171. }
  172. }
  173. }