feat(ads/seo/release): v1.2.0 with live Google Ads, isolated ad profile, ads.txt, and SEO/AEO/GEO optimization
This commit is contained in:
parent
a88aafa1e5
commit
0e568f1f0a
975 changed files with 130593 additions and 16783 deletions
|
|
@ -0,0 +1,70 @@
|
|||
using System;
|
||||
using Paca.Mobile.Core;
|
||||
using Xunit;
|
||||
|
||||
namespace Paca.Tests.Core;
|
||||
|
||||
public class DownloadTokenBucketRateLimiterGateTests
|
||||
{
|
||||
[Fact]
|
||||
public void Gate453_DownloadTokenBucketRateLimiter_AllowsImmediateConsumption_WhenBucketFull()
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var limiter = new DownloadTokenBucketRateLimiter(rateBytesPerSec: 1_000_000, burstCapacityBytes: 2_000_000, initialTime: now);
|
||||
|
||||
var decision = limiter.Request(500_000, now);
|
||||
|
||||
Assert.True(decision.IsAllowedImmediately);
|
||||
Assert.Equal(TimeSpan.Zero, decision.DelayRequired);
|
||||
Assert.Equal(1_500_000, limiter.AvailableTokens, 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate454_DownloadTokenBucketRateLimiter_CalculatesRequiredDelay_WhenTokensExhausted()
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var limiter = new DownloadTokenBucketRateLimiter(rateBytesPerSec: 1_000_000, burstCapacityBytes: 1_000_000, initialTime: now);
|
||||
|
||||
// Exhaust all tokens
|
||||
limiter.Request(1_000_000, now);
|
||||
|
||||
// Request another 500KB immediately (needs 500ms refill)
|
||||
var decision = limiter.Request(500_000, now);
|
||||
|
||||
Assert.False(decision.IsAllowedImmediately);
|
||||
Assert.Equal(TimeSpan.FromMilliseconds(500), decision.DelayRequired);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate455_DownloadTokenBucketRateLimiter_RefillsTokensOverTime_UpToCapacity()
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var limiter = new DownloadTokenBucketRateLimiter(rateBytesPerSec: 1_000_000, burstCapacityBytes: 2_000_000, initialTime: now);
|
||||
|
||||
// Consume everything
|
||||
limiter.Request(2_000_000, now);
|
||||
Assert.Equal(0, limiter.AvailableTokens, 1);
|
||||
|
||||
// Advance time by 3 seconds (3MB generated, capped at 2MB burst)
|
||||
var future = now.AddSeconds(3);
|
||||
var decision = limiter.Request(1, future);
|
||||
|
||||
Assert.True(decision.IsAllowedImmediately);
|
||||
Assert.Equal(2_000_000 - 1, limiter.AvailableTokens, 1);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Gate456_DownloadTokenBucketRateLimiter_DynamicRateAdjustment_PreservesTokens()
|
||||
{
|
||||
var now = DateTime.UtcNow;
|
||||
var limiter = new DownloadTokenBucketRateLimiter(rateBytesPerSec: 1_000_000, burstCapacityBytes: 2_000_000, initialTime: now);
|
||||
|
||||
limiter.Request(1_000_000, now);
|
||||
Assert.Equal(1_000_000, limiter.AvailableTokens, 1);
|
||||
|
||||
// Adjust rate to 5 MB/s
|
||||
limiter.SetRate(5_000_000, now);
|
||||
Assert.Equal(1_000_000, limiter.AvailableTokens, 1);
|
||||
Assert.Equal(5_000_000, limiter.RateBytesPerSec);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue