import { describe, expect, test } from "bun:test"; import { readFileSync } from "node:fs"; import { join } from "node:path"; /** * doctor обязан диагностировать установку, не изменяя её. * * Регрессия, которую закрепляет этот файл. doctor собирал контекст с * `skipServiceStart` по умолчанию (false) и звал общий smoke, а тот первым же * действием выполняет `systemctl restart hysteria-server hy2xs-admin`. Команда, * которую runbook предлагает запускать при подозрении на проблему, обрывала все * живые VPN-соединения на сервере — в том числе когда с сервисом всё в порядке. * * Проверяется исходник, а не поведение: единственная альтернатива — поднять * настоящие systemd-юниты, чего в этой среде не существует. Утверждение при * этом точное: рестарт в smoke стоит ровно под одним условием, и тест * фиксирует, что doctor это условие закрывает безусловно. */ // Пути считаются от самого файла теста, а не от cwd: `bun test` запускается и // из корня репозитория, и из orchestrator/ — сборка делает первое, разработчик // обычно второе. function source(relativeToSrc: string): string { return readFileSync(join(import.meta.dir, "..", "src", relativeToSrc), "utf8"); } describe("doctor не перезапускает сервисы", () => { test("контекст doctor принудительно выставляет skipServiceStart", () => { const doctorSource = source("commands/doctor.ts"); expect(doctorSource).toContain("skipServiceStart: true"); }); test("skipServiceStart выставляется ПОСЛЕ раскрытия options и не может быть перекрыт", () => { const doctorSource = source("commands/doctor.ts"); const spread = doctorSource.indexOf("...options"); const forced = doctorSource.indexOf("skipServiceStart: true"); expect(spread).toBeGreaterThan(-1); expect(forced).toBeGreaterThan(-1); // Порядок в объектном литерале решает: `{ ...options, skipServiceStart: true }` // игнорирует значение из командной строки, обратный порядок — нет. expect(forced).toBeGreaterThan(spread); }); test("smoke по-прежнему рестартует сервисы только под флагом", () => { const smokeSource = source("steps/smoke.ts"); const restart = "systemctl restart hysteria-server hy2xs-admin"; expect(smokeSource).toContain(restart); // Ровно одно место рестарта, и оно под проверкой флага: иначе выставление // skipServiceStart в doctor ничего бы не гарантировало. expect(smokeSource.split(restart).length - 1).toBe(1); const guard = smokeSource.indexOf("if (!context.options.skipServiceStart)"); const restartAt = smokeSource.indexOf(restart); expect(guard).toBeGreaterThan(-1); expect(guard).toBeLessThan(restartAt); }); test("doctor не глушит остальные проверки smoke", () => { const doctorSource = source("commands/doctor.ts"); // skipSmoke приходит из options и по умолчанию false: doctor сужает только // рестарт, а не диагностику целиком. expect(doctorSource).not.toContain("skipSmoke: true"); expect(doctorSource).toContain("await smoke(context)"); }); });