1import * as NodeServices from "@effect/platform-node/NodeServices";
2import * as HostProcess from "@t3tools/shared/HostProcess";
3import { afterEach, assert, describe, expect, it, vi } from "@effect/vitest";
4import * as Effect from "effect/Effect";
5import * as FileSystem from "effect/FileSystem";
6
7import * as ServerConfig from "../config.ts";
8import * as ResourceMonitorBinary from "./ResourceMonitorBinary.ts";
9
10// The override checks POSIX exec bits on a real file under a linux platform
11// mock; NTFS never reports those bits, so the check cannot be satisfied there.
12const windowsHost = HostProcess.Platform.defaultValue() === "win32";
13
14describe("ResourceMonitorBinary", () => {
15 afterEach(() => {
16 vi.restoreAllMocks();
17 });
18
19 it.effect("skips Linux libc detection on Windows", () =>
20 Effect.gen(function* () {
21 const getReport = vi.spyOn(process.report, "getReport").mockImplementation(() => {
22 throw new Error("Linux libc detection must not run on Windows");
23 });
24 const fileSystem = yield* FileSystem.FileSystem;
25 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
26 prefix: "t3-resource-monitor-binary-",
27 });
28 const binaryPath = `${baseDir}/t3-resource-monitor.exe`;
29 yield* fileSystem.writeFileString(binaryPath, "binary");
30
31 const service = yield* ResourceMonitorBinary.make().pipe(
32 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
33 Effect.provideService(HostProcess.Platform, "win32"),
34 Effect.provideService(HostProcess.Architecture, "arm64"),
35 Effect.provideService(HostProcess.Environment, {
36 T3CODE_RESOURCE_MONITOR_PATH: binaryPath,
37 }),
38 );
39
40 assert.equal(yield* service.resolve, binaryPath);
41 expect(getReport).not.toHaveBeenCalled();
42 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
43 );
44
45 it.effect.skipIf(windowsHost)("resolves an executable override", () =>
46 Effect.gen(function* () {
47 const fileSystem = yield* FileSystem.FileSystem;
48 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
49 prefix: "t3-resource-monitor-binary-",
50 });
51 const binaryPath = `${baseDir}/t3-resource-monitor`;
52 yield* fileSystem.writeFileString(binaryPath, "binary");
53 yield* fileSystem.chmod(binaryPath, 0o755);
54
55 const service = yield* ResourceMonitorBinary.make().pipe(
56 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
57 Effect.provideService(HostProcess.Platform, "linux"),
58 Effect.provideService(HostProcess.Architecture, "x64"),
59 Effect.provideService(ResourceMonitorBinary.ResourceMonitorHostLinuxLibc, "musl"),
60 Effect.provideService(HostProcess.Environment, {
61 T3CODE_RESOURCE_MONITOR_PATH: binaryPath,
62 }),
63 );
64
65 assert.equal(yield* service.resolve, binaryPath);
66 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
67 );
68
69 it.effect.skipIf(windowsHost)("resolves an executable override on an unsupported platform", () =>
70 Effect.gen(function* () {
71 const fileSystem = yield* FileSystem.FileSystem;
72 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
73 prefix: "t3-resource-monitor-binary-",
74 });
75 const binaryPath = `${baseDir}/custom-resource-monitor`;
76 yield* fileSystem.writeFileString(binaryPath, "binary");
77 yield* fileSystem.chmod(binaryPath, 0o755);
78
79 const service = yield* ResourceMonitorBinary.make().pipe(
80 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
81 Effect.provideService(HostProcess.Platform, "freebsd"),
82 Effect.provideService(HostProcess.Architecture, "ia32"),
83 Effect.provideService(HostProcess.Environment, {
84 T3CODE_RESOURCE_MONITOR_PATH: binaryPath,
85 }),
86 );
87
88 assert.equal(yield* service.resolve, binaryPath);
89 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
90 );
91
92 it.effect("rejects a non-executable POSIX override", () =>
93 Effect.gen(function* () {
94 const fileSystem = yield* FileSystem.FileSystem;
95 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
96 prefix: "t3-resource-monitor-binary-",
97 });
98 const binaryPath = `${baseDir}/t3-resource-monitor`;
99 yield* fileSystem.writeFileString(binaryPath, "binary");
100 yield* fileSystem.chmod(binaryPath, 0o644);
101
102 const service = yield* ResourceMonitorBinary.make().pipe(
103 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
104 Effect.provideService(HostProcess.Platform, "linux"),
105 Effect.provideService(HostProcess.Architecture, "x64"),
106 Effect.provideService(ResourceMonitorBinary.ResourceMonitorHostLinuxLibc, "gnu"),
107 Effect.provideService(HostProcess.Environment, {
108 T3CODE_RESOURCE_MONITOR_PATH: binaryPath,
109 }),
110 );
111 const error = yield* Effect.flip(service.resolve);
112
113 assert.instanceOf(error, ResourceMonitorBinary.ResourceMonitorBinaryNotExecutable);
114 assert.equal(error.path, binaryPath);
115 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
116 );
117
118 it.effect("rejects a directory override", () =>
119 Effect.gen(function* () {
120 const fileSystem = yield* FileSystem.FileSystem;
121 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
122 prefix: "t3-resource-monitor-binary-",
123 });
124
125 const service = yield* ResourceMonitorBinary.make().pipe(
126 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
127 Effect.provideService(HostProcess.Platform, "win32"),
128 Effect.provideService(HostProcess.Architecture, "arm64"),
129 Effect.provideService(HostProcess.Environment, {
130 T3CODE_RESOURCE_MONITOR_PATH: baseDir,
131 }),
132 );
133 const error = yield* Effect.flip(service.resolve);
134
135 assert.instanceOf(error, ResourceMonitorBinary.ResourceMonitorBinaryNotExecutable);
136 assert.equal(error.path, baseDir);
137 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
138 );
139
140 it.effect("rejects unsupported platform and architecture pairs", () =>
141 Effect.gen(function* () {
142 const fileSystem = yield* FileSystem.FileSystem;
143 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
144 prefix: "t3-resource-monitor-binary-",
145 });
146 const service = yield* ResourceMonitorBinary.make().pipe(
147 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
148 Effect.provideService(HostProcess.Platform, "freebsd"),
149 Effect.provideService(HostProcess.Architecture, "ia32"),
150 Effect.provideService(HostProcess.Environment, {}),
151 );
152 const error = yield* Effect.flip(service.resolve);
153
154 assert.instanceOf(error, ResourceMonitorBinary.ResourceMonitorBinaryUnsupported);
155 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
156 );
157
158 it.effect("rejects bundled glibc binaries on musl Linux hosts", () =>
159 Effect.gen(function* () {
160 const fileSystem = yield* FileSystem.FileSystem;
161 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
162 prefix: "t3-resource-monitor-binary-",
163 });
164 const service = yield* ResourceMonitorBinary.make().pipe(
165 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
166 Effect.provideService(HostProcess.Platform, "linux"),
167 Effect.provideService(HostProcess.Architecture, "x64"),
168 Effect.provideService(ResourceMonitorBinary.ResourceMonitorHostLinuxLibc, "musl"),
169 Effect.provideService(HostProcess.Environment, {}),
170 );
171 const error = yield* Effect.flip(service.resolve);
172
173 assert.instanceOf(error, ResourceMonitorBinary.ResourceMonitorBinaryUnsupported);
174 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
175 );
176});