Ctrl K
ComunidadGuías…

electron/cua-restart.test.mjs

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
import { afterEach, describe, expect, it, vi } from "vitest";
import { createHelperRestarts, followLinuxConnection, HELPER_KEEPS_CRASHING, HELPER_RESTARTING, RESTART_WAITS_MS } from "./cua-restart.mjs";

afterEach(() => vi.useRealTimers());

function restarts({ back = () => true } = {}) {
  vi.useFakeTimers();
  const reports = [];
  const calls = [];
  const keeper = createHelperRestarts({
    restart: async () => { calls.push(Date.now()); return back(calls.length); },
    report: (reason) => reports.push(reason),
  });
  return { keeper, reports, calls };
}

describe("restarting a helper that dies", () => {
  it("says it is restarting at once and restarts after the first wait", async () => {
    const { keeper, reports, calls } = restarts();
    keeper.started();
    keeper.exited("code 1");
    expect(reports).toEqual([HELPER_RESTARTING]);
    expect(calls).toHaveLength(0);
    await vi.advanceTimersByTimeAsync(RESTART_WAITS_MS[0] - 1);
    expect(calls).toHaveLength(0);
    await vi.advanceTimersByTimeAsync(1);
    expect(calls).toHaveLength(1);
  });

  it("waits longer each time, then stops and says so when it keeps dying", async () => {
    const { keeper, reports, calls } = restarts();
    keeper.started();
    for (const wait of RESTART_WAITS_MS) {
      keeper.exited("crash");
      await vi.advanceTimersByTimeAsync(wait);
    }
    expect(calls).toHaveLength(RESTART_WAITS_MS.length);
    keeper.exited("crash");
    await vi.advanceTimersByTimeAsync(600_000);
    expect(calls).toHaveLength(RESTART_WAITS_MS.length);
    expect(reports.at(-1)).toBe(HELPER_KEEPS_CRASHING);
  });

  it("keeps trying while a restart fails, within the same bound", async () => {
    const { keeper, reports, calls } = restarts({ back: () => false });
    keeper.exited("crash");
    await vi.advanceTimersByTimeAsync(600_000);
    expect(calls).toHaveLength(RESTART_WAITS_MS.length);
    expect(reports.at(-1)).toBe(HELPER_KEEPS_CRASHING);
  });

  it("starts a new count after the helper has run for a while", async () => {
    const { keeper, reports, calls } = restarts();
    keeper.started();
    keeper.exited("crash");
    await vi.advanceTimersByTimeAsync(RESTART_WAITS_MS[0]);
    keeper.exited("crash");
    await vi.advanceTimersByTimeAsync(RESTART_WAITS_MS[1]);
    await vi.advanceTimersByTimeAsync(120_000);
    keeper.exited("crash");
    await vi.advanceTimersByTimeAsync(RESTART_WAITS_MS[0]);
    expect(calls).toHaveLength(3);
    expect(reports.every((reason) => reason === HELPER_RESTARTING)).toBe(true);
  });

  it("stops and leaves the published reason when only the person can fix it", async () => {
    const { keeper, reports, calls } = restarts({ back: () => "needs-person" });
    keeper.exited("crash");
    await vi.advanceTimersByTimeAsync(600_000);
    expect(calls).toHaveLength(1);
    expect(reports).toEqual([HELPER_RESTARTING]);
  });

  it("a person's restart cancels the waiting restart and forgets the count", async () => {
    const { keeper, calls } = restarts();
    keeper.exited("crash");
    keeper.reset();
    await vi.advanceTimersByTimeAsync(600_000);
    expect(calls).toHaveLength(0);
  });
});

describe("following the Linux runtime", () => {
  const spies = () => ({ started: vi.fn(), exited: vi.fn() });

  it("counts a died daemon as an exit and a ready one as started", () => {
    const restarts = spies();
    followLinuxConnection(restarts, { status: "error", reasonCode: "daemon-exited", exitCode: 139 });
    expect(restarts.exited).toHaveBeenCalledWith("exit 139");
    followLinuxConnection(restarts, { status: "ready" });
    expect(restarts.started).toHaveBeenCalledOnce();
  });

  it("ignores every other change, such as the person turning it off", () => {
    const restarts = spies();
    followLinuxConnection(restarts, { status: "disabled", reasonCode: "opt-in-required" });
    followLinuxConnection(restarts, { status: "error", reasonCode: "wayland-health-lost" });
    followLinuxConnection(restarts, null);
    expect(restarts.started).not.toHaveBeenCalled();
    expect(restarts.exited).not.toHaveBeenCalled();
  });
});