148 lines · 5.1 KB · TypeScript
RawDownload
// @effect-diagnostics nodeBuiltinImport:offimport * as NFS from "node:fs";import * as path from "node:path";import { execFileSync, spawn } from "node:child_process";import * as NodeServices from "@effect/platform-node/NodeServices";import { assert, it } from "@effect/vitest";import * as FileSystem from "effect/FileSystem";import * as Schema from "effect/Schema";import * as Duration from "effect/Duration";import * as Effect from "effect/Effect";import * as Fiber from "effect/Fiber";import * as TestClock from "effect/testing/TestClock";import { vi } from "vite-plus/test"; import { readBootstrapEnvelope, resolveFdPath } from "./bootstrap.ts";import { assertNone, assertSome } from "@effect/vitest/utils"; const openSyncInterceptor = vi.hoisted(() => ({ failPath: null as string | null })); vi.mock("node:fs", async (importOriginal) => {  const actual = await importOriginal<typeof import("node:fs")>();  return {    ...actual,    openSync: (...args: Parameters<typeof actual.openSync>) => {      const [filePath, flags] = args;      if (        typeof filePath === "string" &&        filePath === openSyncInterceptor.failPath &&        flags === "r"      ) {        const error = new Error("no such device or address");        Object.assign(error, { code: "ENXIO" });        throw error;      }      return (actual.openSync as (...a: typeof args) => number)(...args);    },  };}); const TestEnvelopeSchema = Schema.Struct({ mode: Schema.String });const encodeTestEnvelopeSchema = Schema.encodeEffect(Schema.fromJsonString(TestEnvelopeSchema)); it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => {  it.effect("uses platform-specific fd paths", () =>    Effect.sync(() => {      assert.equal(resolveFdPath(3, "linux"), "/proc/self/fd/3");      assert.equal(resolveFdPath(3, "darwin"), "/dev/fd/3");      assert.equal(resolveFdPath(3, "win32"), undefined);    }),  );   it.effect("reads a bootstrap envelope from a provided fd", () =>    Effect.gen(function* () {      const fs = yield* FileSystem.FileSystem;      const filePath = yield* fs.makeTempFileScoped({ prefix: "t3-bootstrap-", suffix: ".ndjson" });       yield* fs.writeFileString(        filePath,        `${yield* encodeTestEnvelopeSchema({ mode: "desktop" })}\n`,      );       const fd = yield* Effect.acquireRelease(        Effect.sync(() => NFS.openSync(filePath, "r")),        (fd) => Effect.sync(() => NFS.closeSync(fd)),      );       const payload = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, { timeoutMs: 100 });      assertSome(payload, {        mode: "desktop",      });    }),  );   it.effect("falls back to reading the inherited fd when path duplication fails", () =>    Effect.gen(function* () {      const fs = yield* FileSystem.FileSystem;      const filePath = yield* fs.makeTempFileScoped({ prefix: "t3-bootstrap-", suffix: ".ndjson" });       yield* fs.writeFileString(        filePath,        `${yield* encodeTestEnvelopeSchema({ mode: "desktop" })}\n`,      );       // Open without acquireRelease: the direct-stream fallback uses autoClose: true,      // so the stream owns the fd lifecycle and closes it asynchronously on end.      // Attempting to also close it synchronously in a finalizer races with the      // stream's async close and produces an uncaught EBADF.      const fd = NFS.openSync(filePath, "r");       openSyncInterceptor.failPath = `/proc/self/fd/${fd}`;      try {        const payload = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, { timeoutMs: 100 });        assertSome(payload, {          mode: "desktop",        });      } finally {        openSyncInterceptor.failPath = null;      }    }),  );   it.effect("returns none when the fd is unavailable", () =>    Effect.gen(function* () {      const fd = NFS.openSync("/dev/null", "r");      NFS.closeSync(fd);       const payload = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, { timeoutMs: 100 });      assertNone(payload);    }),  );   it.effect("returns none when the bootstrap read times out before any value arrives", () =>    Effect.gen(function* () {      const fs = yield* FileSystem.FileSystem;      const tempDir = yield* fs.makeTempDirectoryScoped({ prefix: "t3-bootstrap-" });      const fifoPath = path.join(tempDir, "bootstrap.pipe");       yield* Effect.sync(() => execFileSync("mkfifo", [fifoPath]));       const _writer = yield* Effect.acquireRelease(        Effect.sync(() =>          spawn("sh", ["-c", 'exec 3>"$1"; sleep 60', "sh", fifoPath], {            stdio: ["ignore", "ignore", "ignore"],          }),        ),        (writer) =>          Effect.sync(() => {            writer.kill("SIGKILL");          }),      );       const fd = yield* Effect.acquireRelease(        Effect.sync(() => NFS.openSync(fifoPath, "r")),        (fd) => Effect.sync(() => NFS.closeSync(fd)),      );       const fiber = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, {        timeoutMs: 100,      }).pipe(Effect.forkScoped);       yield* Effect.yieldNow;      yield* TestClock.adjust(Duration.millis(100));       const payload = yield* Fiber.join(fiber);      assertNone(payload);    }).pipe(Effect.provide(TestClock.layer())),  );});