Три вади, знайдені рецензією, яких щасливий шлях показати не міг: * outcome='sent' писався до доставки; помилка читання каналів клала в кеш порожню мапу й з'їдала всі сходинки кабінету за тік — усі зі слідом «надіслано». Канали тепер читаються до просування стану, журнал пишеться після доставки, з правдою. * UPDATE не мав stopped_at IS NULL — підтвердження алерту посеред партії не рятувало людину від дзвінка. * час брався раз на партію. Плюс суміжне: UpdateRule не гасив алертів вимкненого правила, сервер домислював enabled на оновленні, channel_ids сходинок не звірялись із каналами кабінету (зокрема чужого). І scripts/dbtest.sh — тести проти бази перестали мовчки пропускатись. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
92 lines
5.1 KiB
Go
92 lines
5.1 KiB
Go
package store
|
||
|
||
import "testing"
|
||
|
||
// Рішення про прапорець «увімкнено» при правці правила.
|
||
//
|
||
// ЧОГО ЦЕЙ ФАЙЛ БОЇТЬСЯ. Обидві вади, які він закриває, тихі: система
|
||
// після них не падає й нічого не пише в журнал. Видно їх тільки з
|
||
// телефона о третій ночі — або, що гірше, не видно взагалі.
|
||
//
|
||
// 1. Правило вимкнули через PUT (форма надсилає правило цілком) — і
|
||
// його алерти лишились у firing НАЗАВЖДИ: вимкнене правило випадає
|
||
// з ActiveRules, тобто ResolveMissing за ним більше не біжить і
|
||
// погасити їх немає кому. Драбина ескалації при цьому працює далі —
|
||
// з повторами вона будить людей тижнями за проблемою, за якою вже
|
||
// ніхто не стежить.
|
||
// 2. Форма не надсилала `enabled` взагалі, а сервер читав відсутність
|
||
// поля як `true`. Тобто відкрити вимкнене правило, поправити в ньому
|
||
// будь-що й зберегти — означало мовчки його ввімкнути.
|
||
//
|
||
// Перевіряється чистою функцією, а не базою, з тієї ж причини, що й
|
||
// planRestore поруч: на живій базі кожен із чотирьох випадків — це
|
||
// окремий стенд із правилом, алертом і драбиною, а ціна помилки в
|
||
// будь-якому з них платиться не тут і не одразу.
|
||
|
||
func TestPlanRuleEnabledResolvesOnDisable(t *testing.T) {
|
||
// Головний випадок: увімкнене правило вимикають правкою. Алерти
|
||
// треба гасити тут же — іншої нагоди в них не буде.
|
||
off := false
|
||
enabled, resolve := planRuleEnabled(true, &off)
|
||
if enabled {
|
||
t.Fatal("правило мало лишитись вимкненим")
|
||
}
|
||
if !resolve {
|
||
t.Fatal("алерти не гасяться: після вимкнення їх нікому закрити, " +
|
||
"і драбина ескалації будитиме людей за ними далі")
|
||
}
|
||
}
|
||
|
||
func TestPlanRuleEnabledKeepsAlertsWhenStillDisabled(t *testing.T) {
|
||
// Правку вимкненого правила зберігають повторно. Гасити нема чого:
|
||
// його алерти закрив той перехід, який його вимкнув, а зайвий
|
||
// прохід — це ще один запис у event_outbox на кожне збереження.
|
||
off := false
|
||
enabled, resolve := planRuleEnabled(false, &off)
|
||
if enabled {
|
||
t.Fatal("правило мало лишитись вимкненим")
|
||
}
|
||
if resolve {
|
||
t.Fatal("гасити нічого: правило вже було вимкнене до правки")
|
||
}
|
||
}
|
||
|
||
func TestPlanRuleEnabledKeepsAlertsWhenEnabling(t *testing.T) {
|
||
// Увімкнення — не привід чіпати алерти: рішення про них ухвалить
|
||
// найближчий тік движка, і саме він знає, чи проблема ще триває.
|
||
on := true
|
||
enabled, resolve := planRuleEnabled(false, &on)
|
||
if !enabled {
|
||
t.Fatal("правило мало ввімкнутись")
|
||
}
|
||
if resolve {
|
||
t.Fatal("увімкнення гасить алерти — цього не мало статись")
|
||
}
|
||
}
|
||
|
||
func TestPlanRuleEnabledLeavesDisabledRuleAlone(t *testing.T) {
|
||
// ВАДА Б. Поля `enabled` у тілі немає — саме так виглядав кожен
|
||
// PUT із форми правил. Вимкнене правило мусить лишитись вимкненим:
|
||
// «поля не було» означає «не чіпайте», а не «вмикайте».
|
||
enabled, resolve := planRuleEnabled(false, nil)
|
||
if enabled {
|
||
t.Fatal("правка без поля `enabled` увімкнула вимкнене правило — " +
|
||
"людина дізнається про це зі сповіщення, а не з форми")
|
||
}
|
||
if resolve {
|
||
t.Fatal("гасити нічого: стан не змінився")
|
||
}
|
||
}
|
||
|
||
func TestPlanRuleEnabledLeavesEnabledRuleAlone(t *testing.T) {
|
||
// Другий бік тієї ж пари, і без нього перший нічого не доводить:
|
||
// функція, яка завжди повертає false, пройшла б попередній тест.
|
||
enabled, resolve := planRuleEnabled(true, nil)
|
||
if !enabled {
|
||
t.Fatal("правка без поля `enabled` вимкнула увімкнене правило — " +
|
||
"це мовчазна зупинка моніторингу")
|
||
}
|
||
if resolve {
|
||
t.Fatal("гасити нічого: стан не змінився")
|
||
}
|
||
}
|