177 lines
5.5 KiB
PHP
177 lines
5.5 KiB
PHP
<?php
|
|
/**
|
|
* Tests for MLF_Rate_Limiter class.
|
|
*
|
|
* @package Maple_Local_Fonts
|
|
*/
|
|
|
|
/**
|
|
* Class Test_MLF_Rate_Limiter
|
|
*
|
|
* @covers MLF_Rate_Limiter
|
|
*/
|
|
class Test_MLF_Rate_Limiter extends WP_UnitTestCase {
|
|
|
|
/**
|
|
* Rate limiter instance.
|
|
*
|
|
* @var MLF_Rate_Limiter
|
|
*/
|
|
private $rate_limiter;
|
|
|
|
/**
|
|
* Set up test fixtures.
|
|
*/
|
|
public function set_up() {
|
|
parent::set_up();
|
|
$this->rate_limiter = new MLF_Rate_Limiter(3, 60); // 3 requests per 60 seconds
|
|
}
|
|
|
|
/**
|
|
* Clean up after tests.
|
|
*/
|
|
public function tear_down() {
|
|
// Clear any transients
|
|
$this->rate_limiter->clear('test_action');
|
|
parent::tear_down();
|
|
}
|
|
|
|
/**
|
|
* Test that first request is not limited.
|
|
*/
|
|
public function test_first_request_not_limited() {
|
|
$this->assertFalse($this->rate_limiter->is_limited('test_action'));
|
|
}
|
|
|
|
/**
|
|
* Test that remaining count starts at limit.
|
|
*/
|
|
public function test_remaining_starts_at_limit() {
|
|
$this->assertEquals(3, $this->rate_limiter->get_remaining('test_action'));
|
|
}
|
|
|
|
/**
|
|
* Test that check_and_record allows requests within limit.
|
|
*/
|
|
public function test_check_and_record_allows_within_limit() {
|
|
$this->assertTrue($this->rate_limiter->check_and_record('test_action'));
|
|
$this->assertTrue($this->rate_limiter->check_and_record('test_action'));
|
|
$this->assertTrue($this->rate_limiter->check_and_record('test_action'));
|
|
}
|
|
|
|
/**
|
|
* Test that check_and_record blocks after limit exceeded.
|
|
*/
|
|
public function test_check_and_record_blocks_after_limit() {
|
|
// Use up all allowed requests
|
|
$this->rate_limiter->check_and_record('test_action');
|
|
$this->rate_limiter->check_and_record('test_action');
|
|
$this->rate_limiter->check_and_record('test_action');
|
|
|
|
// Next request should be blocked
|
|
$this->assertFalse($this->rate_limiter->check_and_record('test_action'));
|
|
}
|
|
|
|
/**
|
|
* Test that remaining count decreases correctly.
|
|
*/
|
|
public function test_remaining_decreases() {
|
|
$this->rate_limiter->record_request('test_action');
|
|
$this->assertEquals(2, $this->rate_limiter->get_remaining('test_action'));
|
|
|
|
$this->rate_limiter->record_request('test_action');
|
|
$this->assertEquals(1, $this->rate_limiter->get_remaining('test_action'));
|
|
|
|
$this->rate_limiter->record_request('test_action');
|
|
$this->assertEquals(0, $this->rate_limiter->get_remaining('test_action'));
|
|
}
|
|
|
|
/**
|
|
* Test that is_limited returns true after limit exceeded.
|
|
*/
|
|
public function test_is_limited_after_exceeding() {
|
|
$this->rate_limiter->record_request('test_action');
|
|
$this->rate_limiter->record_request('test_action');
|
|
$this->rate_limiter->record_request('test_action');
|
|
|
|
$this->assertTrue($this->rate_limiter->is_limited('test_action'));
|
|
}
|
|
|
|
/**
|
|
* Test that clear resets the rate limit.
|
|
*/
|
|
public function test_clear_resets_limit() {
|
|
// Use up all requests
|
|
$this->rate_limiter->record_request('test_action');
|
|
$this->rate_limiter->record_request('test_action');
|
|
$this->rate_limiter->record_request('test_action');
|
|
|
|
$this->assertTrue($this->rate_limiter->is_limited('test_action'));
|
|
|
|
// Clear and verify reset
|
|
$this->rate_limiter->clear('test_action');
|
|
$this->assertFalse($this->rate_limiter->is_limited('test_action'));
|
|
$this->assertEquals(3, $this->rate_limiter->get_remaining('test_action'));
|
|
}
|
|
|
|
/**
|
|
* Test that different actions are tracked separately.
|
|
*/
|
|
public function test_different_actions_tracked_separately() {
|
|
// Use up all requests for action1
|
|
$this->rate_limiter->record_request('action1');
|
|
$this->rate_limiter->record_request('action1');
|
|
$this->rate_limiter->record_request('action1');
|
|
|
|
// action1 should be limited
|
|
$this->assertTrue($this->rate_limiter->is_limited('action1'));
|
|
|
|
// action2 should not be limited
|
|
$this->assertFalse($this->rate_limiter->is_limited('action2'));
|
|
$this->assertEquals(3, $this->rate_limiter->get_remaining('action2'));
|
|
|
|
// Clean up
|
|
$this->rate_limiter->clear('action1');
|
|
$this->rate_limiter->clear('action2');
|
|
}
|
|
|
|
/**
|
|
* Test that logged in user uses user ID for tracking.
|
|
*/
|
|
public function test_logged_in_user_tracking() {
|
|
// Create and log in a user
|
|
$user_id = $this->factory->user->create(['role' => 'administrator']);
|
|
wp_set_current_user($user_id);
|
|
|
|
// Use up requests
|
|
$this->rate_limiter->record_request('test_action');
|
|
$this->rate_limiter->record_request('test_action');
|
|
$this->rate_limiter->record_request('test_action');
|
|
|
|
$this->assertTrue($this->rate_limiter->is_limited('test_action'));
|
|
|
|
// Clean up
|
|
wp_set_current_user(0);
|
|
$this->rate_limiter->clear('test_action');
|
|
}
|
|
|
|
/**
|
|
* Test constructor with custom limits.
|
|
*/
|
|
public function test_custom_limits() {
|
|
$custom_limiter = new MLF_Rate_Limiter(5, 120);
|
|
|
|
$this->assertEquals(5, $custom_limiter->get_remaining('custom_action'));
|
|
|
|
// Use 5 requests
|
|
for ($i = 0; $i < 5; $i++) {
|
|
$this->assertTrue($custom_limiter->check_and_record('custom_action'));
|
|
}
|
|
|
|
// 6th should be blocked
|
|
$this->assertFalse($custom_limiter->check_and_record('custom_action'));
|
|
|
|
// Clean up
|
|
$custom_limiter->clear('custom_action');
|
|
}
|
|
}
|