nhance/tests/unit/RateLimiterServiceSmokeTest.php
2026-05-18 12:28:19 +05:30

105 lines
3.6 KiB
PHP

<?php
use App\Libraries\RateLimiterService;
use CodeIgniter\Test\CIUnitTestCase;
/**
* @internal
*/
final class RateLimiterServiceSmokeTest extends CIUnitTestCase
{
private RateLimiterService $service;
protected function setUp(): void
{
parent::setUp();
helper('utility');
$this->service = new RateLimiterService();
}
public function testIpBlockEscalationAndUnblockFlow(): void
{
$cfg = config('RateLimiter');
$fingerprint = 'smoke-ip-' . uniqid('', true);
// Initially no IP block.
$this->assertNull($this->service->getIpBlock($fingerprint));
// Record enough failures to trigger soft block.
$result = null;
for ($i = 0; $i < $cfg->ipBlock['violation_soft']; $i++) {
$result = $this->service->recordIpFailure($fingerprint);
}
$this->assertIsArray($result);
$this->assertSame('soft', $result['level']);
// Hitting again while blocked should eventually escalate to hard.
$this->service->checkIp($fingerprint, 'jwtApi'); // return soft, escalate to medium
$this->service->checkIp($fingerprint, 'jwtApi'); // return medium, escalate to hard
$blocked = $this->service->checkIp($fingerprint, 'jwtApi'); // return hard
$this->assertIsArray($blocked);
$this->assertSame('hard', $blocked['level']);
$this->service->unblockIp($fingerprint);
$this->assertNull($this->service->getIpBlock($fingerprint));
}
public function testUserFailureFlowAndManualUnblock(): void
{
$cfg = config('RateLimiter');
$identity = 'smoke-user-' . uniqid('', true) . '@example.com';
$this->assertNull($this->service->getUserBlock($identity));
$result = null;
for ($i = 0; $i < $cfg->authApi['violation_soft']; $i++) {
$result = $this->service->recordUserFailure($identity, 'authApi');
}
$this->assertIsArray($result);
$this->assertSame('soft', $result['level']);
// Re-hits while blocked escalate from soft -> medium -> hard.
$this->service->checkUser($identity); // return soft, escalate to medium
$this->service->checkUser($identity); // return medium, escalate to hard
$blocked = $this->service->checkUser($identity); // return hard
$this->assertIsArray($blocked);
$this->assertSame('hard', $blocked['level']);
$this->service->unblockUser($identity);
$this->assertNull($this->service->getUserBlock($identity));
}
public function testJwtUserThrottleToSoftBlock(): void
{
$cfg = config('RateLimiter');
$identity = 'smoke-throttle-' . uniqid('', true) . '@example.com';
// First "limit" requests should pass.
for ($i = 0; $i < $cfg->jwtApi['limit']; $i++) {
$this->assertNull($this->service->checkUserThrottle($identity, 'jwtApi'));
}
// Over-limit attempts should return throttle first, then soft block after enough violations.
$throttle = $this->service->checkUserThrottle($identity, 'jwtApi');
$this->assertIsArray($throttle);
$this->assertSame('throttle', $throttle['level']);
$blocked = null;
for ($i = 0; $i < $cfg->jwtApi['violation_soft']; $i++) {
$blocked = $this->service->checkUserThrottle($identity, 'jwtApi');
}
$this->assertIsArray($blocked);
$this->assertContains($blocked['level'], ['soft', 'medium', 'hard']);
$this->service->unblockUser($identity);
$this->assertNull($this->service->getUserBlock($identity));
}
}