Repository navigation
Expand file tree
/
Copy pathbootstrap.test.ts
More file actions
124 lines (108 loc) · 4.33 KB
/
Copy pathbootstrap.test.ts
File metadata and controls
124 lines (108 loc) · 4.33 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// @effect-diagnostics nodeBuiltinImport:off
import * as NodeFS from "node:fs";
import * as NodeServices from "@effect/platform-node/NodeServices";
import { it } from "@effect/vitest";
import * as FileSystem from "effect/FileSystem";
import * as Schema from "effect/Schema";
import * as Effect from "effect/Effect";
import { vi } from "vite-plus/test";
import * as HostProcess from "@t3tools/shared/HostProcess";
import { readBootstrapEnvelope } from "./bootstrap.ts";
import { assertNone, assertSome } from "@effect/vitest/utils";
const openSyncInterceptor = vi.hoisted(() => ({
failPath: null as string | null,
errorCode: "ENXIO",
}));
const fstatSyncInterceptor = vi.hoisted(() => ({ failFd: null as number | 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(`open failed with ${openSyncInterceptor.errorCode}`);
Object.assign(error, { code: openSyncInterceptor.errorCode });
throw error;
}
return (actual.openSync as (...a: typeof args) => number)(...args);
},
fstatSync: (...args: Parameters<typeof actual.fstatSync>) => {
if (args[0] === fstatSyncInterceptor.failFd) {
const error = new Error("permission denied");
Object.assign(error, { code: "EACCES" });
throw error;
}
return (actual.fstatSync as (...a: typeof args) => NodeFS.Stats)(...args);
},
};
});
const windowsHost = HostProcess.Platform.defaultValue() === "win32";
const nullDevice = windowsHost ? "\\\\.\\NUL" : "/dev/null";
const closeIfOpen = (fd: number) => {
try {
NodeFS.closeSync(fd);
} catch (error) {
if ((error as NodeJS.ErrnoException).code !== "EBADF") throw error;
}
};
// Windows auto-closes the inherited fd; POSIX reopens it, leaving the original for the test to close.
const openBootstrapInputFd = (filePath: string) =>
Effect.acquireRelease(
Effect.sync(() => NodeFS.openSync(filePath, "r")),
(fd) => (windowsHost ? Effect.void : Effect.sync(() => closeIfOpen(fd))),
);
const TestEnvelopeSchema = Schema.Struct({ mode: Schema.String });
const encodeTestEnvelopeSchema = Schema.encodeEffect(Schema.fromJsonString(TestEnvelopeSchema));
it.layer(NodeServices.layer)("readBootstrapEnvelope", (it) => {
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* openBootstrapInputFd(filePath);
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`,
);
// The fallback stream auto-closes asynchronously; a finalizer would race and cause EBADF.
const fd = NodeFS.openSync(filePath, "r");
openSyncInterceptor.failPath = `/proc/self/fd/${fd}`;
try {
const payload = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, {
timeoutMs: 100,
}).pipe(Effect.provideService(HostProcess.Platform, "linux"));
assertSome(payload, {
mode: "desktop",
});
} finally {
openSyncInterceptor.failPath = null;
}
}),
);
it.effect("returns none when the fd is unavailable", () =>
Effect.gen(function* () {
const fd = NodeFS.openSync(nullDevice, "r");
NodeFS.closeSync(fd);
const payload = yield* readBootstrapEnvelope(TestEnvelopeSchema, fd, { timeoutMs: 100 });
assertNone(payload);
}),
);
});