Files
api/services/nginx/app/tests/Unit/Redis/RedisAtomicReservationTest.php
T
Jeppe B 2a6a86c9c3 Resolve backend Qodana critical and high findings (#314)
Resolve recommended-profile Critical and High findings, retain narrow analyzer exceptions, and update the edge-broker WebSocket dependency to a non-vulnerable release.
2026-07-17 05:44:16 +02:00

102 lines
2.5 KiB
PHP

<?php
app_require('classes/redis.php');
use classes\redis;
use Predis\Client as PredisClient;
class RedisAtomicReservationTestClient extends PredisClient
{
public array $calls = [];
public function __construct(private mixed $returnValue)
{
}
public function mget(array $keyOrKeys): array
{
$this->calls[] = ['mget', $keyOrKeys];
return $this->returnValue;
}
public function set(...$arguments): mixed
{
$this->calls[] = $arguments;
return $this->returnValue;
}
public function disconnect(): void
{
}
}
function redis_test_inject_client(redis $redis, PredisClient $client): void
{
$reflection = new ReflectionClass($redis);
$property = $reflection->getProperty('redis');
$property->setValue($redis, $client);
}
it('claims a slot atomically with nx and expiration', function (): void {
global $REDIS_CONFIG;
$REDIS_CONFIG = [
'host' => 'redis',
'database' => 0,
'password' => '',
];
$client = new RedisAtomicReservationTestClient('OK');
$redis = new redis();
redis_test_inject_client($redis, $client);
expect($redis->set_if_absent_with_expiration('goal_alert_sent:22:2026-03-17', '1', 86400))->toBeTrue();
expect($client->calls)->toBe([
['goal_alert_sent:22:2026-03-17', '1', 'EX', 86400, 'NX'],
]);
});
it('returns false when the slot is already claimed and clamps ttl to one second', function (): void {
global $REDIS_CONFIG;
$REDIS_CONFIG = [
'host' => 'redis',
'database' => 0,
'password' => '',
];
$client = new RedisAtomicReservationTestClient(null);
$redis = new redis();
redis_test_inject_client($redis, $client);
expect($redis->set_if_absent_with_expiration('goal_alert_sent:22:2026-03-17', '1', 0))->toBeFalse();
expect($client->calls)->toBe([
['goal_alert_sent:22:2026-03-17', '1', 'EX', 1, 'NX'],
]);
});
it('does not send empty mget commands to redis', function (): void {
global $REDIS_CONFIG;
$REDIS_CONFIG = [
'host' => 'redis',
'database' => 0,
'password' => '',
];
$client = new RedisAtomicReservationTestClient(['cached-value']);
$redis = new redis();
redis_test_inject_client($redis, $client);
expect($redis->mget([]))->toBe([]);
expect($client->calls)->toBe([]);
expect($redis->mget(['cache-key']))->toBe(['cached-value']);
expect($client->calls)->toBe([
['mget', ['cache-key']],
]);
});