HEX
Server: LiteSpeed
System: Linux s1049.use1.mysecurecloudhost.com 4.18.0-477.27.2.lve.el8.x86_64 #1 SMP Wed Oct 11 12:32:56 UTC 2023 x86_64
User: xedaptot (3356)
PHP: 8.3.31
Disabled: NONE
Upload Files
File: /home/xedaptot/ai.naniguide.com/tests/Unit/RateTrackerTest.php
<?php

use App\Library\RateTracker;
use App\Library\RateLimit;
use Carbon\Carbon;

test('Rollback just works', function () {
    $file = '/tmp/test-rate-'.uniqid();
    $tracker = new RateTracker($file);

    $now = Carbon::now();
    $oneMinuteAgo = $now->clone()->add('1 minute ago');

    // 4 times
    $tracker->count($oneMinuteAgo);
    $tracker->count($oneMinuteAgo);
    $tracker->count($now);
    $tracker->count($now);

    /*
     * After 4 counts, the lock file should look like this
     *
     * 202307300013:2
     * 202307300014:2
     *
     */

    $used = $tracker->getCreditsUsed($oneMinuteAgo, $now);
    $linesCount = sizeof(file($tracker->getLockFilePath()));
    expect($used)->toBe(4);
    expect($linesCount)->toBe(2);

    // Rollback 1
    $tracker->rollback();

    /*
     * After rollback 1, the lock file should look like this
     *
     * 202307300013:2
     * 202307300014:1
     *
     */

    $used = $tracker->getCreditsUsed($oneMinuteAgo, $now);
    $linesCount = sizeof(file($tracker->getLockFilePath()));
    expect($used)->toBe(3);
    expect($linesCount)->toBe(2);

    // Rollback 2
    $tracker->rollback();

    /*
     * After rollback 2, the lock file should look like this
     *
     * 202307300013:2
     *
     */

    $used = $tracker->getCreditsUsed($oneMinuteAgo, $now);
    $linesCount = sizeof(file($tracker->getLockFilePath()));
    expect($used)->toBe(2);
    expect($linesCount)->toBe(1);
});

test('Clean up tracker', function () {

    $file = '/tmp/test-rate';
    $tracker = new RateTracker($file);

    $tracker->cleanup();

    $this->assertEquals($tracker->getCreditsUsed(), 0);

    $now = now();
    $twoMinuteAgo = $now->copy()->add('2 minute ago');
    $oneMinuteAgo = $now->copy()->add('1 minute ago');

    // 2 time
    $tracker->count($twoMinuteAgo);
    $tracker->count($twoMinuteAgo);

    // 3 times
    $tracker->count($oneMinuteAgo);
    $tracker->count($oneMinuteAgo);
    $tracker->count($oneMinuteAgo);

    // two: 2
    // one: 3
    $this->assertEquals($tracker->getCreditsUsed(), 5);

    // 1 time
    $tracker->count($now);

    // two: 2
    // one: 3
    // now: 1
    $this->assertEquals($tracker->getCreditsUsed(), 6);

    // Clean up
    $tracker->cleanup('2 minute'); // keep records during the last 2 minute, including 'two', 'one' and 'now'
    $this->assertEquals($tracker->getCreditsUsed(), 6);

    $tracker->cleanup('1 minute'); // keep records during the last 1 minute, including 'one' and 'now'
    $this->assertEquals($tracker->getCreditsUsed(), 4);
});

test('Rollback truncates a shorter rewritten record from 10 to 9', function () {
    $file = '/tmp/test-rate-'.uniqid();
    $tracker = new RateTracker($file);
    $now = Carbon::create(2026, 4, 21, 12, 30, 0);

    for ($i = 0; $i < 10; $i++) {
        $tracker->count($now);
    }

    $tracker->rollback();

    expect(trim(file_get_contents($tracker->getLockFilePath())))->toBe('202604211230:9');
    expect($tracker->getCreditsUsed($now->copy()->subMinute(), $now))->toBe(9);
});

test('Rollback truncates a shorter rewritten record from 100 to 99', function () {
    $file = '/tmp/test-rate-'.uniqid();
    $tracker = new RateTracker($file);
    $now = Carbon::create(2026, 4, 21, 12, 30, 0);

    for ($i = 0; $i < 100; $i++) {
        $tracker->count($now);
    }

    $tracker->rollback();

    expect(trim(file_get_contents($tracker->getLockFilePath())))->toBe('202604211230:99');
    expect($tracker->getCreditsUsed($now->copy()->subMinute(), $now))->toBe(99);
});

test('Test checks limits without mutating the tracker file', function () {
    $file = '/tmp/test-rate-'.uniqid();
    $now = Carbon::create(2026, 4, 21, 12, 30, 0);
    $tracker = new RateTracker($file, [
        new RateLimit(5, 1, 'minute', '5 per minute'),
    ]);

    for ($i = 0; $i < 3; $i++) {
        $tracker->count($now);
    }

    $before = file_get_contents($tracker->getLockFilePath());

    $tracker->test($now);

    expect(file_get_contents($tracker->getLockFilePath()))->toBe($before);
    expect(trim($before))->toBe('202604211230:3');
});