public void QuickPulseQuotaTrackerQuotaGetsRefilled() { // ARRANGE var mockTimeProvider = new ClockMock(); QuickPulseQuotaTracker quotaTracker = new QuickPulseQuotaTracker(mockTimeProvider, 30, 0); bool counted; // ACT & ASSERT Assert.AreEqual(0, quotaTracker.CurrentQuota); Assert.IsTrue(quotaTracker.QuotaExhausted); counted = quotaTracker.ApplyQuota(); Assert.IsFalse(counted); // No quota yet Assert.AreEqual(0, quotaTracker.CurrentQuota); Assert.IsTrue(quotaTracker.QuotaExhausted); mockTimeProvider.FastForward(TimeSpan.FromSeconds(1)); // 0.5 quota accumulated counted = quotaTracker.ApplyQuota(); Assert.IsFalse(counted); // No quota yet Assert.AreEqual(0.5f, quotaTracker.CurrentQuota); Assert.IsTrue(quotaTracker.QuotaExhausted); mockTimeProvider.FastForward(TimeSpan.FromSeconds(1)); // 1 quota accumulated counted = quotaTracker.ApplyQuota(); Assert.IsTrue(counted); Assert.AreEqual(0, quotaTracker.CurrentQuota); Assert.IsTrue(quotaTracker.QuotaExhausted); counted = quotaTracker.ApplyQuota(); Assert.IsFalse(counted); // Quota was already exhausted. Assert.AreEqual(0, quotaTracker.CurrentQuota); Assert.IsTrue(quotaTracker.QuotaExhausted); }
public void QuickPulseQuotaTrackerShouldNotGetBursts() { // ARRANGE int maxQuota = 30; var mockTimeProvider = new ClockMock(); QuickPulseQuotaTracker quotaTracker = new QuickPulseQuotaTracker(mockTimeProvider, maxQuota, 0); mockTimeProvider.FastForward(TimeSpan.FromSeconds(1)); // ACT & ASSERT // Emulate that every second we try to track 100 of documents. We should expect // only one document every 2nd second (quota = 30 documents per min). for (int i = 0; i < 1000; i++) { int count = 0; for (int j = 0; j < 100; j++) { bool counted = quotaTracker.ApplyQuota(); if (counted) { ++count; } } Assert.AreEqual((i % 2) == 0 ? 0 : 1, count); mockTimeProvider.FastForward(TimeSpan.FromSeconds(1)); } }
/// <summary> /// Initializes a new instance of the <see cref="QuickPulseTelemetryProcessor"/> class. Internal constructor for unit tests only. /// </summary> /// <param name="next">The next TelemetryProcessor in the chain.</param> /// <param name="timeProvider">Time provider.</param> /// <param name="maxTelemetryQuota">Max telemetry quota.</param> /// <param name="initialTelemetryQuota">Initial telemetry quota.</param> /// <exception cref="ArgumentNullException">Thrown if next is null.</exception> internal QuickPulseTelemetryProcessor( ITelemetryProcessor next, Clock timeProvider, int?maxTelemetryQuota = null, int?initialTelemetryQuota = null) { if (next == null) { throw new ArgumentNullException(nameof(next)); } this.Register(); this.Next = next; this.requestQuotaTracker = new QuickPulseQuotaTracker( timeProvider, maxTelemetryQuota ?? MaxTelemetryQuota, initialTelemetryQuota ?? InitialTelemetryQuota); this.dependencyQuotaTracker = new QuickPulseQuotaTracker( timeProvider, maxTelemetryQuota ?? MaxTelemetryQuota, initialTelemetryQuota ?? InitialTelemetryQuota); this.exceptionQuotaTracker = new QuickPulseQuotaTracker( timeProvider, maxTelemetryQuota ?? MaxTelemetryQuota, initialTelemetryQuota ?? InitialTelemetryQuota); }
/// <summary> /// Initializes a new instance of the <see cref="QuickPulseTelemetryProcessor"/> class. Internal constructor for unit tests only. /// </summary> /// <param name="next">The next TelemetryProcessor in the chain.</param> /// <param name="timeProvider">Time provider.</param> /// <param name="maxGlobalTelemetryQuota">Max overall telemetry quota.</param> /// <param name="initialGlobalTelemetryQuota">Initial overall telemetry quota.</param> /// <exception cref="ArgumentNullException">Thrown if next is null.</exception> internal QuickPulseTelemetryProcessor( ITelemetryProcessor next, Clock timeProvider, float?maxGlobalTelemetryQuota = null, float?initialGlobalTelemetryQuota = null) { this.Next = next ?? throw new ArgumentNullException(nameof(next)); this.RegisterSelfWithQuickPulseTelemetryModule(); this.globalQuotaTracker = new QuickPulseQuotaTracker( timeProvider, maxGlobalTelemetryQuota ?? MaxGlobalTelemetryQuota, initialGlobalTelemetryQuota ?? InitialGlobalTelemetryQuota); }
public void QuickPulseQuotaTrackerQuotaNotEmptyAtStart() { // ARRANGE int startQuota = 10; bool counted; var mockTimeProvider = new ClockMock(); QuickPulseQuotaTracker quotaTracker = new QuickPulseQuotaTracker(mockTimeProvider, 30, startQuota); // ACT & ASSERT while (startQuota > 0) { counted = quotaTracker.ApplyQuota(); Assert.IsTrue(counted); --startQuota; } // Quota should be exhausted. counted = quotaTracker.ApplyQuota(); Assert.IsFalse(counted); }
public void QuickPulseQuotaTrackerQuotaDoesNotExceedMax() { // ARRANGE int startQuota = 10; int maxQuota = 30; var mockTimeProvider = new ClockMock(); QuickPulseQuotaTracker quotaTracker = new QuickPulseQuotaTracker(mockTimeProvider, maxQuota, startQuota); bool counted; mockTimeProvider.FastForward(TimeSpan.FromDays(1)); // ACT & ASSERT while (maxQuota > 0) { counted = quotaTracker.ApplyQuota(); Assert.IsTrue(counted); --maxQuota; } counted = quotaTracker.ApplyQuota(); Assert.IsFalse(counted); // We should exhaust quota by this time }
public void QuickPulseQuotaTrackerIsThreadSafe() { // ARRANGE int maxQuota = 100 * 60; int experimentLengthInSeconds = 1000; int concurrency = 1000; var mockTimeProvider = new ClockMock(); var quotaTracker = new QuickPulseQuotaTracker(mockTimeProvider, maxQuota, 0); var quotaApplicationResults = new ConcurrentQueue <bool>(); // ACT for (int i = 0; i < experimentLengthInSeconds; i++) { mockTimeProvider.FastForward(TimeSpan.FromSeconds(1)); var tasks = new List <Action>(); for (int j = 0; j < concurrency; j++) { tasks.Add(() => quotaApplicationResults.Enqueue(quotaTracker.ApplyQuota())); } Parallel.Invoke(new ParallelOptions() { MaxDegreeOfParallelism = concurrency }, tasks.ToArray()); } // ASSERT var passedQuotaCount = quotaApplicationResults.Count(result => result); var correctResult = maxQuota / 60 * experimentLengthInSeconds; Assert.AreEqual(correctResult, passedQuotaCount); Assert.IsFalse(quotaTracker.ApplyQuota()); }