Newer
Older
smart-home-server / server / tests / RateLimiterTest.php
<?php

use PHPUnit\Framework\TestCase;
use SHServ\Tools\RateLimiter;

class RateLimiterTest extends TestCase {
	private ?RateLimiter $limiter = null;

	protected function tearDown(): void {
		if ($this -> limiter !== null) {
			$this -> limiter -> clear();
		}
	}

	public function test_allows_requests_within_limit(): void {
		$this -> limiter = new RateLimiter(5, 60);
		for ($i = 0; $i < 5; $i++) {
			$this -> assertTrue($this -> limiter -> check('ip1'));
		}
	}

	public function test_blocks_excess_requests(): void {
		$this -> limiter = new RateLimiter(3, 60);
		for ($i = 0; $i < 3; $i++) {
			$this -> limiter -> check('ip2');
		}
		$this -> assertFalse($this -> limiter -> check('ip2'));
	}

	public function test_resets_after_window(): void {
		$this -> limiter = new RateLimiter(2, 1);
		$this -> assertTrue($this -> limiter -> check('ip3'));
		$this -> assertTrue($this -> limiter -> check('ip3'));
		$this -> assertFalse($this -> limiter -> check('ip3'));

		sleep(2);
		$this -> assertTrue($this -> limiter -> check('ip3'));
	}

	public function test_different_keys_are_independent(): void {
		$this -> limiter = new RateLimiter(1, 60);
		$this -> assertTrue($this -> limiter -> check('ip_a'));
		$this -> assertTrue($this -> limiter -> check('ip_b'));
	}

	public function test_file_storage_shared_across_instances(): void {
		$tmpFile = sys_get_temp_dir() . '/rl-test-' . uniqid() . '.json';
		$limiterA = new RateLimiter(2, 60, $tmpFile);
		$limiterB = new RateLimiter(2, 60, $tmpFile);

		$this -> assertTrue($limiterA -> check('shared'));
		$this -> assertTrue($limiterB -> check('shared'));
		$this -> assertFalse($limiterA -> check('shared'));

		unlink($tmpFile);
	}
}