Open History to see the last commit
1import * as NodeServices from "@effect/platform-node/NodeServices";
2import * as HostProcess from "@t3tools/shared/HostProcess";
3import { afterEach, assert, describe, it, vi } from "@effect/vitest";
4import * as Effect from "effect/Effect";
5import * as FileSystem from "effect/FileSystem";
6import * as Path from "effect/Path";
7
8import * as ServerConfig from "../config.ts";
9import * as ResourceMonitorBinary from "./ResourceMonitorBinary.ts";
10
11// NTFS lacks POSIX exec bits required by this Linux-mocked override check.
12const windowsHost = HostProcess.Platform.defaultValue() === "win32";
13
14describe("ResourceMonitorBinary", () => {
15 afterEach(() => {
16 vi.restoreAllMocks();
17 });
18
19 it.effect.skipIf(windowsHost)("resolves an executable override on an unsupported platform", () =>
20 Effect.gen(function* () {
21 const fileSystem = yield* FileSystem.FileSystem;
22 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
23 prefix: "t3-resource-monitor-binary-",
24 });
25 const binaryPath = `${baseDir}/custom-resource-monitor`;
26 yield* fileSystem.writeFileString(binaryPath, "binary");
27 yield* fileSystem.chmod(binaryPath, 0o755);
28
29 const service = yield* ResourceMonitorBinary.make().pipe(
30 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
31 Effect.provideService(HostProcess.Platform, "freebsd"),
32 Effect.provideService(HostProcess.Architecture, "ia32"),
33 Effect.provideService(HostProcess.Environment, {
34 T3CODE_RESOURCE_MONITOR_PATH: binaryPath,
35 }),
36 );
37
38 assert.equal(yield* service.resolve, binaryPath);
39 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
40 );
41
42 it.effect("rejects a non-executable POSIX override", () =>
43 Effect.gen(function* () {
44 const fileSystem = yield* FileSystem.FileSystem;
45 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
46 prefix: "t3-resource-monitor-binary-",
47 });
48 const binaryPath = `${baseDir}/t3-resource-monitor`;
49 yield* fileSystem.writeFileString(binaryPath, "binary");
50 yield* fileSystem.chmod(binaryPath, 0o644);
51
52 const service = yield* ResourceMonitorBinary.make().pipe(
53 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
54 Effect.provideService(HostProcess.Platform, "linux"),
55 Effect.provideService(HostProcess.Architecture, "x64"),
56 Effect.provideService(HostProcess.LinuxLibc, "gnu"),
57 Effect.provideService(HostProcess.Environment, {
58 T3CODE_RESOURCE_MONITOR_PATH: binaryPath,
59 }),
60 );
61 const error = yield* Effect.flip(service.resolve);
62
63 assert.instanceOf(error, ResourceMonitorBinary.ResourceMonitorBinaryNotExecutable);
64 assert.equal(error.path, binaryPath);
65 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
66 );
67
68 // regression: #16838 a directory resolved as the resource monitor binary
69 it.effect("rejects a directory override", () =>
70 Effect.gen(function* () {
71 const fileSystem = yield* FileSystem.FileSystem;
72 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
73 prefix: "t3-resource-monitor-binary-",
74 });
75
76 const service = yield* ResourceMonitorBinary.make().pipe(
77 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
78 Effect.provideService(HostProcess.Platform, "win32"),
79 Effect.provideService(HostProcess.Architecture, "arm64"),
80 Effect.provideService(HostProcess.Environment, {
81 T3CODE_RESOURCE_MONITOR_PATH: baseDir,
82 }),
83 );
84 const error = yield* Effect.flip(service.resolve);
85
86 assert.instanceOf(error, ResourceMonitorBinary.ResourceMonitorBinaryNotExecutable);
87 assert.equal(error.path, baseDir);
88 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
89 );
90
91 it.effect.each(["release", "debug"])(
92 "resolves a cargo %s binary from the built server layout",
93 (profile) =>
94 Effect.gen(function* () {
95 const fileSystem = yield* FileSystem.FileSystem;
96 const path = yield* Path.Path;
97 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
98 prefix: "t3-resource-monitor-binary-",
99 });
100 const projectDirectory = path.join(baseDir, "repo");
101 const distDirectory = path.join(projectDirectory, "apps", "server", "dist");
102 const binaryDirectory = path.join(
103 projectDirectory,
104 "native",
105 "resource-monitor",
106 "target",
107 profile,
108 );
109 const binaryPath = path.join(binaryDirectory, "t3-resource-monitor.exe");
110 yield* fileSystem.makeDirectory(distDirectory, { recursive: true });
111 yield* fileSystem.makeDirectory(binaryDirectory, { recursive: true });
112 yield* fileSystem.writeFileString(binaryPath, "binary");
113 yield* fileSystem.chmod(binaryPath, 0o755);
114
115 const service = yield* ResourceMonitorBinary.make().pipe(
116 // The bundled module lives in dist rather than src/resourceTelemetry.
117 Effect.provideService(Path.Path, {
118 ...path,
119 resolve: (...segments) =>
120 path.resolve(
121 ...segments.map((segment) =>
122 segment === import.meta.dirname ? distDirectory : segment,
123 ),
124 ),
125 }),
126 Effect.provide(ServerConfig.layerTest(projectDirectory, baseDir)),
127 Effect.provideService(HostProcess.Platform, "win32"),
128 Effect.provideService(HostProcess.Architecture, "arm64"),
129 Effect.provideService(HostProcess.Environment, {}),
130 );
131
132 assert.equal(yield* service.resolve, binaryPath);
133 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
134 );
135
136 it.effect("rejects bundled glibc binaries on musl Linux hosts", () =>
137 Effect.gen(function* () {
138 const fileSystem = yield* FileSystem.FileSystem;
139 const baseDir = yield* fileSystem.makeTempDirectoryScoped({
140 prefix: "t3-resource-monitor-binary-",
141 });
142 const service = yield* ResourceMonitorBinary.make().pipe(
143 Effect.provide(ServerConfig.layerTest(process.cwd(), baseDir)),
144 Effect.provideService(HostProcess.Platform, "linux"),
145 Effect.provideService(HostProcess.Architecture, "x64"),
146 Effect.provideService(HostProcess.LinuxLibc, "musl"),
147 Effect.provideService(HostProcess.Environment, {}),
148 );
149 const error = yield* Effect.flip(service.resolve);
150
151 assert.instanceOf(error, ResourceMonitorBinary.ResourceMonitorBinaryUnsupported);
152 }).pipe(Effect.scoped, Effect.provide(NodeServices.layer)),
153 );
154});