Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 1
<?php
2
// This file is part of Moodle - http://moodle.org/
3
//
4
// Moodle is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8
//
9
// Moodle is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13
//
14
// You should have received a copy of the GNU General Public License
15
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16
 
17
namespace core_ai;
18
 
19
defined('MOODLE_INTERNAL') || die();
20
 
21
global $CFG;
22
require_once($CFG->libdir . '/testing/classes/incrementing_clock.php');
23
 
24
/**
25
 * Test ai subsystem rate limiter methods.
26
 *
27
 * @package    core_ai
28
 * @copyright  2024 Matt Porritt
29
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
30
 * @covers     \core_ai\rate_limiter
31
 */
32
final class rate_limiter_test extends \advanced_testcase {
33
    /**
34
     * Set up before tests.
35
     */
36
    protected function setUp(): void {
37
        parent::setUp();
38
        $this->resetAfterTest(true);
39
    }
40
 
41
    /**
42
     * Test global rate limit is enforced correctly.
43
     */
44
    public function test_global_rate_limit(): void {
45
        $ratelimiter = \core\di::get(rate_limiter::class);
46
        $component = 'testcomponent';
47
        $ratelimit = 5;
48
 
49
        // Make 5 requests, all should be allowed.
50
        for ($i = 0; $i < 5; $i++) {
51
            $this->assertTrue($ratelimiter->check_global_rate_limit($component, $ratelimit));
52
        }
53
 
54
        // The 6th request should be denied.
55
        $this->assertFalse($ratelimiter->check_global_rate_limit($component, $ratelimit));
56
    }
57
 
58
    /**
59
     * Test user rate limit is enforced correctly.
60
     */
61
    public function test_user_rate_limit(): void {
62
        $ratelimiter = \core\di::get(rate_limiter::class);
63
        $component = 'testcomponent';
64
        $ratelimit = 3;
65
        $userid = 12345;
66
 
67
        // Make 3 requests for the user, all should be allowed.
68
        for ($i = 0; $i < 3; $i++) {
69
            $this->assertTrue($ratelimiter->check_user_rate_limit($component, $ratelimit, $userid));
70
        }
71
 
72
        // The 4th request should be denied.
73
        $this->assertFalse($ratelimiter->check_user_rate_limit($component, $ratelimit, $userid));
74
    }
75
 
76
    /**
77
     * Test global rate limit resets after time window.
78
     */
79
    public function test_global_rate_limit_reset(): void {
80
        $clock = $this->mock_clock_with_incrementing(0);
81
        $ratelimiter = \core\di::get(rate_limiter::class);
82
        $component = 'testcomponent';
83
        $ratelimit = 3;
84
 
85
        // Make 3 requests, all should be allowed.
86
        for ($i = 0; $i < 3; $i++) {
87
            $this->assertTrue($ratelimiter->check_global_rate_limit($component, $ratelimit));
88
        }
89
 
90
        // Simulate moving time forward by TIME_WINDOW to reset the rate limit.
91
        $clock->set_to(rate_limiter::TIME_WINDOW + 1);
92
 
93
        // The next request should be allowed again.
94
        $this->assertTrue($ratelimiter->check_global_rate_limit($component, $ratelimit));
95
    }
96
 
97
    /**
98
     * Test user rate limit resets after time window.
99
     */
100
    public function test_user_rate_limit_reset(): void {
101
        $clock = $this->mock_clock_with_incrementing(0);
102
        $ratelimiter = \core\di::get(rate_limiter::class);
103
        $component = 'testcomponent';
104
        $ratelimit = 3;
105
        $userid = 12345;
106
 
107
        // Make 3 requests for the user, all should be allowed.
108
        for ($i = 0; $i < 3; $i++) {
109
            $this->assertTrue($ratelimiter->check_user_rate_limit($component, $ratelimit, $userid));
110
        }
111
 
112
        // Simulate moving time forward by TIME_WINDOW to reset the rate limit.
113
        $clock->set_to(rate_limiter::TIME_WINDOW + 1);
114
 
115
        // The next user request should be allowed again.
116
        $this->assertTrue($ratelimiter->check_user_rate_limit($component, $ratelimit, $userid));
117
    }
118
}