Skip to content

Commit eb57149

Browse files
author
Jos Hickson
committed
Remove time dependencies.
1 parent 99c27e0 commit eb57149

1 file changed

Lines changed: 35 additions & 64 deletions

File tree

Winton.Extensions.Threading.Actor.Tests.Unit/Internal/ActorWorkSchedulerTests.cs

Lines changed: 35 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,13 @@ public void Dispose()
4141
}
4242

4343
[Theory]
44-
[InlineData(WorkType.Async)]
45-
[InlineData(WorkType.Sync)]
46-
public void ShouldBeAbleToScheduleWorkToRepeatAtAFixedInterval(WorkType workType)
44+
[InlineData(WorkType.Async, ActorScheduleOptions.Default)]
45+
[InlineData(WorkType.Async, ActorScheduleOptions.NoInitialDelay)]
46+
[InlineData(WorkType.Sync, ActorScheduleOptions.Default)]
47+
[InlineData(WorkType.Sync, ActorScheduleOptions.NoInitialDelay)]
48+
public void ShouldBeAbleToScheduleWorkToRepeatAtAFixedInterval(WorkType workType, ActorScheduleOptions actorScheduleOptions)
4749
{
50+
var barrier = new TaskCompletionSource<bool>();
4851
var expectedInterval = TimeSpan.FromMilliseconds(100);
4952
var times = new List<DateTime>();
5053
var sampleSize = 5;
@@ -56,23 +59,27 @@ public void ShouldBeAbleToScheduleWorkToRepeatAtAFixedInterval(WorkType workType
5659
{
5760
times.Add(DateTime.UtcNow);
5861
}
62+
63+
if (times.Count == sampleSize)
64+
{
65+
// Block here so that we can assess something that's not moving
66+
barrier.Task.Wait();
67+
}
5968
};
6069

6170
switch (workType)
6271
{
6372
case WorkType.Sync:
64-
{
65-
_scheduler.Schedule(adder, expectedInterval);
66-
}
73+
_scheduler.Schedule(adder, expectedInterval, actorScheduleOptions);
6774
break;
6875
case WorkType.Async:
69-
{
7076
_scheduler.Schedule(async () =>
7177
{
7278
await Task.Yield();
7379
adder();
74-
}, expectedInterval);
75-
}
80+
},
81+
expectedInterval,
82+
actorScheduleOptions);
7683
break;
7784
default:
7885
throw new Exception($"Unhandled test case {workType}.");
@@ -82,47 +89,15 @@ public void ShouldBeAbleToScheduleWorkToRepeatAtAFixedInterval(WorkType workType
8289

8390
var actualIntervals = times.Take(sampleSize - 1).Zip(times.Skip(1), (x, y) => y - x).ToList();
8491

85-
actualIntervals.Should().OnlyContain(x => Math.Abs((expectedInterval - x).TotalMilliseconds) < 30);
86-
}
92+
actualIntervals.Should().OnlyContain(x => x >= expectedInterval);
8793

88-
[Theory]
89-
[InlineData(WorkType.Async)]
90-
[InlineData(WorkType.Sync)]
91-
public void ShouldBeAbleToScheduleWorkToStartImmediatelyBeforeRepeatingAtIntervals(WorkType workType)
92-
{
93-
var expectedInterval = TimeSpan.FromMilliseconds(5000);
94-
var scheduleTime = DateTime.UtcNow;
95-
DateTime? firstWork = null;
96-
97-
switch (workType)
98-
{
99-
case WorkType.Sync:
100-
_scheduler.Schedule(() =>
101-
{
102-
if (!firstWork.HasValue)
103-
{
104-
firstWork = DateTime.UtcNow;
105-
}
106-
}, expectedInterval, ActorScheduleOptions.NoInitialDelay);
107-
break;
108-
case WorkType.Async:
109-
_scheduler.Schedule(async () =>
110-
{
111-
await Task.Yield();
112-
113-
if (!firstWork.HasValue)
114-
{
115-
firstWork = DateTime.UtcNow;
116-
}
117-
}, expectedInterval, ActorScheduleOptions.NoInitialDelay);
118-
break;
119-
default:
120-
throw new Exception($"Unhandled test case {workType}.");
121-
}
94+
var expectedNumberOfDelays = sampleSize - (actorScheduleOptions.HasFlag(ActorScheduleOptions.NoInitialDelay) ? 1 : 0);
12295

123-
Within.FiveSeconds(() => firstWork.HasValue.Should().BeTrue());
96+
Expect.That(() => Mock.Get(_actorTaskFactory)
97+
.Verify(x => x.CreateDelay(expectedInterval, It.IsAny<CancellationToken>()), Times.Exactly(expectedNumberOfDelays)))
98+
.ShouldNotThrow();
12499

125-
(firstWork.Value - scheduleTime).Should().BeLessThan(TimeSpan.FromMilliseconds(1000));
100+
barrier.SetResult(true);
126101
}
127102

128103
[Fact]
@@ -193,19 +168,21 @@ public void ASecondCallToScheduleShouldCancelTheWorkPreviouslyScheduled(WorkType
193168
var output = new List<string>();
194169
var interval = TimeSpan.FromMilliseconds(100);
195170
var task1 = default(Task);
196-
var haveThreeTwos = new TaskCompletionSource<bool>();
171+
var firstTwoAddedPromise = new TaskCompletionSource<bool>();
172+
var gotAOneAfterATwoPromise = new TaskCompletionSource<bool>();
197173

198174
Action<string> adder =
199175
x =>
200176
{
201-
if (!haveThreeTwos.Task.IsCompleted)
202-
{
203-
output.Add(x);
177+
output.Add(x);
204178

205-
if (output.Count(y => y == "two") == 3)
206-
{
207-
haveThreeTwos.SetResult(true);
208-
}
179+
if (x == "two")
180+
{
181+
firstTwoAddedPromise.TrySetResult(true);
182+
}
183+
else if (firstTwoAddedPromise.Task.IsCompleted && x == "one")
184+
{
185+
gotAOneAfterATwoPromise.TrySetResult(true);
209186
}
210187
};
211188

@@ -243,11 +220,9 @@ public void ASecondCallToScheduleShouldCancelTheWorkPreviouslyScheduled(WorkType
243220
throw new Exception($"Unhandled test case {workType2}.");
244221
}
245222

246-
haveThreeTwos.Task.AwaitingShouldCompleteIn(TimeSpan.FromSeconds(5));
247-
248-
var firstTwoIndex = output.IndexOf("two");
223+
firstTwoAddedPromise.Task.AwaitingShouldCompleteIn(TimeSpan.FromSeconds(5));
249224

250-
output.Skip(firstTwoIndex).Should().OnlyContain(x => x == "two");
225+
For.OneSecond(() => gotAOneAfterATwoPromise.Task.IsCompleted.Should().BeFalse("The first bit of work is still being scheduled."));
251226

252227
task1.IsCanceled.Should().BeTrue();
253228
}
@@ -313,7 +288,6 @@ public void WhenAnUnhandledErrorOccursInTheWorkTheScheduleShouldStopAndEmitTheEr
313288
switch (workType)
314289
{
315290
case WorkType.Sync:
316-
{
317291
task = _scheduler.Schedule(() =>
318292
{
319293
times.Add(DateTime.UtcNow);
@@ -323,21 +297,18 @@ public void WhenAnUnhandledErrorOccursInTheWorkTheScheduleShouldStopAndEmitTheEr
323297
throw new Exception("Pah!");
324298
}
325299
}, interval, ActorScheduleOptions.NoInitialDelay);
326-
}
327300
break;
328301
case WorkType.Async:
329-
{
330302
task = _scheduler.Schedule(async () =>
331303
{
332304
times.Add(DateTime.UtcNow);
333305
await Task.Yield();
334-
306+
335307
if (times.Count == 3)
336308
{
337309
throw new Exception("Pah!");
338310
}
339311
}, interval, ActorScheduleOptions.NoInitialDelay);
340-
}
341312
break;
342313
default:
343314
throw new Exception($"Unhandled test case {workType}.");

0 commit comments

Comments
 (0)