Files
portal/tools/night/disk.test.mjs
T
Дмитрий 6d095d582c fix: шесть дыр из ворот К2 в правилах ночи — замок, сравнение путей, потерянные пороги, единый час, враньё про полночь, день обновления
1. Битая карточка прогона больше не считается отсутствующей: readRuns различает файл-нет и файл-есть-но-не-читается через readJsonOrBroken, и на нечитаемой карточке замок ЗАКРЫТ. Раньше порванный run.json молча выпадал из списка — замок открывался ровно в ту ночь, когда кончилось место.

2. samePath у замка сведён к поведению samePlanPath у печати через resolve: полный путь владельца и путь от корня хранилища от сторожа теперь один файл. Замерено: lefthook 2.1.8 подставляет staged_files путём ОТ КОРНЯ хранилища.

3. Потерянная настройка больше не читается как можно: нет disk_free_min_gb — отказ; нет hours_limit — hoursLimitHit падает громко, а checkSelfLimits гасит работника с названной причиной.

4. Дорога к московскому часу правда одна: limits берёт час у budget.moskovskoeVremya, своего Intl там больше нет.

5. Запись про полночь-как-24 переписана по замеру: этот Node отдаёт 00. Подчистку сторожит прямая проверка normalizeMskHour, а не случайная зелень.

6. Отказ по запасу без дня обновления и с бессмысленной датой от невиданного прибора теперь виден как сбой, а не как нормальный ответ: renewalDay плюс поле renews_on_problem.

Каждая починка накрыта проверкой, краснеющей при её вырезании. Проверок в четырёх файлах 155, было 108. Полный набор tools: 619 зелёных в 31 файле.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-02 02:29:40 +03:00

84 lines
4.1 KiB
JavaScript

import { describe, it, expect } from 'vitest';
import { freeGb, diskState } from './disk.mjs';
describe('freeGb — замер живьём', () => {
it('на живой машине отдаёт положительное число', async () => {
const gb = await freeGb(process.cwd());
expect(typeof gb).toBe('number');
expect(gb).toBeGreaterThan(0);
});
it('каталога нет вовсе — не выдумываем число, отдаём null', async () => {
// 🪤 Ноль почти всегда сбой, а не правда о мире. Ноль здесь означал бы «места нет»,
// а правда другая: мы не смогли посмотреть.
expect(await freeGb('Z:\\такого-каталога-нет-никогда')).toBeNull();
});
});
describe('diskState — можно ли работать', () => {
it('места больше порога — работать можно', () => {
expect(diskState(50, 5)).toEqual({ ok: true, free_gb: 50, min_gb: 5, reason: null });
});
it('места ровно порог — уже нельзя: порог это черта, а не «можно до неё»', () => {
const s = diskState(5, 5);
expect(s.ok).toBe(false);
expect(s.reason).toMatch(/место/i);
});
it('места меньше порога — нельзя, и причина названа человеку понятно', () => {
const s = diskState(1.5, 5);
expect(s.ok).toBe(false);
expect(s.reason).toContain('1.5');
expect(s.reason).toContain('5');
});
it('замерить не удалось — считаем, что нельзя, а не «наверное хватит»', () => {
const s = diskState(null, 5);
expect(s.ok).toBe(false);
expect(s.free_gb).toBeNull();
expect(s.reason).toMatch(/замерить не удалось/i);
});
});
describe('diskState — ПОРОГА НЕ ДАЛИ (дыра 3)', () => {
// 🔴 Раньше правило читало «настройку потеряли» как «можно»: `50 <= undefined` — ложь,
// и место пропускало что угодно. Ни одна проверка этого не ловила: `diskState` во всех
// проверках звался с порогом-числом, случая «порога нет» не было ни одного.
// Вырежи ветку про порог в disk.mjs — покраснеет весь этот раздел.
it('порога нет вовсе — НЕЛЬЗЯ, а не «места полно»', () => {
const s = diskState(50, undefined);
expect(s.ok).toBe(false);
expect(s.min_gb).toBeNull();
expect(s.reason).toMatch(/порог/i);
});
it('порог пустой (null) — тоже нельзя', () => {
expect(diskState(50, null).ok).toBe(false);
});
it('порог не число (NaN, строка) — тоже нельзя', () => {
expect(diskState(50, NaN).ok).toBe(false);
expect(diskState(50, '5').ok).toBe(false);
expect(diskState(50, Infinity).ok).toBe(false);
});
it('в отказе названа сама потерянная настройка — владельцу есть куда смотреть', () => {
expect(diskState(50, undefined).reason).toContain('disk_free_min_gb');
});
it('и замерить не удалось, и порога нет — отказ, и число не выдумано', () => {
const s = diskState(null, undefined);
expect(s.ok).toBe(false);
expect(s.free_gb).toBeNull();
expect(s.min_gb).toBeNull();
});
it('порог ноль — это настоящий порог, а не «не задан»', () => {
// 🪤 Ноль легко спутать с «не дали». Здесь он законен: владелец вправе поставить 0,
// и тогда работает правило «ровно порог — уже нельзя».
expect(diskState(0, 0).ok).toBe(false);
expect(diskState(1, 0)).toEqual({ ok: true, free_gb: 1, min_gb: 0, reason: null });
});
});