public void CalculatesTheDelayUntilTheNextFreeSlot() { TimeService.CurrentDateTime.Returns( baseTime, baseTime + TimeSpan.FromSeconds(6), baseTime + TimeSpan.FromSeconds(8)); var bucket = new LeakyBucket(TimeService, AnalyticsService, slotsPerWindow: 2, movingWindowSize: TimeSpan.FromSeconds(10)); bucket.TryClaimFreeSlot(out _); bucket.TryClaimFreeSlot(out _); var claimed = bucket.TryClaimFreeSlot(out var timeToFreeSlot); claimed.Should().BeFalse(); timeToFreeSlot.Should().Be(TimeSpan.FromSeconds(2)); }
public void TracksBucketOverflow() { TimeService.CurrentDateTime.Returns(baseTime); var bucket = new LeakyBucket(TimeService, AnalyticsService, 1); bucket.TryClaimFreeSlot(out _); bucket.TryClaimFreeSlots(1, out _); AnalyticsService.Received().LeakyBucketOverflow.Track(); }
public void ReturnsNonZeroTimeToNextSlotWhenTooManySlotsAreUsedInAShortPeriodOfTime(int slotsPerWindowLimit) { TimeService.CurrentDateTime.Returns(baseTime); var bucket = new LeakyBucket(TimeService, AnalyticsService, slotsPerWindowLimit); bucket.TryClaimFreeSlot(out _); var claimed = bucket.TryClaimFreeSlots(slotsPerWindowLimit, out var time); claimed.Should().BeFalse(); time.Should().BeGreaterThan(TimeSpan.Zero); }
public async Task ReturnsDelayTransitionWhenTheLeakyBucketDoesNotHaveFreeSlots() { var delay = TimeSpan.FromSeconds(123.45); LeakyBucket.TryClaimFreeSlot(out _).Returns(x => { x[0] = delay; return(false); }); var state = CreateState(); var entity = Substitute.For <IThreadSafeTestModel>(); var transition = await state.Start(entity); transition.Result.Should().Be(state.PreventOverloadingServer); ((Transition <TimeSpan>)transition).Parameter.Should().Be(delay); }
protected BasePushEntityStateTests() { RateLimiter.WaitForFreeSlot().Returns(Observable.Return(Unit.Default)); LeakyBucket.TryClaimFreeSlot(out _).Returns(true); }