Files
portal/app/tests/Unit/External/SelfRenderLivenessProbeTest.php
T

91 lines
5.1 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use App\Services\External\SelfRenderLivenessProbe;
use Illuminate\Support\Facades\Http;
use Tests\TestCase;
/**
* Сторож живости своей рендер-виртуалки.
*
* 🔴 03.08.2026 виртуалка стала ЕДИНСТВЕННОЙ точкой отказа «Поиска клиентов»:
* чужой xf4.ru умер и снят. А сторож у неё был болен ровно тем же, чем сторож
* xf4: считал сервис живым по «ответ меньше 500». Поле `ok`, которое виртуалка
* честно отдаёт в `/health`, не читалось вовсе — значит зелёный не мог означать
* ничего, а прежний тест «зелёный при 404» этот изъян ещё и ОХРАНЯЛ.
*
* Новое правило: зелёный только когда виртуалка сама сказала `ok: true`.
* Молчание про `ok` — это красный, а не зелёный: раз ручка перестала отвечать
* так, как договаривались, мы про неё больше ничего не знаем.
*
* 🪤 Чего этот сторож НЕ доказывает: что виртуалка отрисует страницу. `ok` — её
* рассказ о себе. Настоящая проверка рендера стоит живой отрисовки на каждый
* показ плитки, и такого решения владелец не принимал.
*/
uses(TestCase::class);
/** Ответ health-ручки виртуалки — тот же вид, что она отдаёт на бою. */
function vmHealth(array $body, int $status = 200): void
{
config()->set('services.self_render.health_url', 'https://vm.local/health');
Http::fake(['vm.local/health' => Http::response($body, $status)]);
}
it('серый, когда адрес проверки не задан', function () {
config()->set('services.self_render.endpoint', 'https://vm.local/render');
config()->set('services.self_render.health_url', '');
// 🪤 Раньше при пустом адресе проверки сторож пинговал саму ручку рендера.
// Она принимает только POST и на GET отдаёт 404/405 — то есть сторож был
// ЗЕЛЁНЫМ навсегда. Честный ответ здесь — «проверить нечем».
expect((new SelfRenderLivenessProbe)->check()->light)->toBe('grey');
});
it('зелёный, когда виртуалка сказала ok', function () {
vmHealth(['ok' => true, 'active' => 0, 'max' => 8, 'proxies' => 1]);
$r = (new SelfRenderLivenessProbe)->check();
expect($r->light)->toBe('green')
// Числа показываем человеку: занятость и наличие прокси видно сразу,
// без похода на виртуалку руками.
->and($r->detail)->toContain('0 из 8')
->and($r->detail)->toContain('прокси 1');
});
it('КРАСНЫЙ, когда виртуалка сказала ok: false', function () {
// Ради этого прогона всё и затевалось: раньше такой ответ был бы зелёным,
// потому что 200 меньше 500.
vmHealth(['ok' => false, 'active' => 8, 'max' => 8, 'proxies' => 0]);
expect((new SelfRenderLivenessProbe)->check()->light)->toBe('red');
});
it('КРАСНЫЙ, когда про ok в ответе не сказано ничего', function () {
// Ручка ответила 200, но не тем, о чём договаривались, — значит мы про
// виртуалку ничего не знаем. Молчание засчитывать за «жива» нельзя.
config()->set('services.self_render.health_url', 'https://vm.local/health');
Http::fake(['vm.local/health' => Http::response('ok', 200)]);
expect((new SelfRenderLivenessProbe)->check()->light)->toBe('red');
});
it('КРАСНЫЙ на 404 и 405 — это GET к ручке, которая их не принимает', function () {
// Прежний тест требовал здесь ЗЕЛЁНЫЙ. Именно это правило сделало сторожа
// xf4 слепым навсегда, и его нельзя повторять.
vmHealth(['ok' => true], 404);
expect((new SelfRenderLivenessProbe)->check()->light)->toBe('red');
vmHealth(['ok' => true], 405);
expect((new SelfRenderLivenessProbe)->check()->light)->toBe('red');
});
it('красный при 500 и при сетевой ошибке', function () {
vmHealth(['ok' => false], 500);
expect((new SelfRenderLivenessProbe)->check()->light)->toBe('red');
config()->set('services.self_render.health_url', 'https://vm.local/health');
Http::fake(fn () => throw new RuntimeException('down'));
expect((new SelfRenderLivenessProbe)->check()->light)->toBe('red');
});