Repository navigation
Expand file tree
/
Copy pathNet.test.ts
More file actions
100 lines (83 loc) · 2.91 KB
/
Copy pathNet.test.ts
File metadata and controls
100 lines (83 loc) · 2.91 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
import * as NodeNet from "node:net";
import { assert, describe, it } from "@effect/vitest";
import * as Effect from "effect/Effect";
import * as NetService from "./Net.ts";
const closeServer = (server: NodeNet.Server) =>
Effect.sync(() => {
try {
server.close();
} catch {
// Ignore cleanup failures in tests.
}
});
const getPort = (server: NodeNet.Server): number => {
const address = server.address();
return typeof address === "object" && address !== null ? address.port : 0;
};
const openServer = (host?: string): Effect.Effect<NodeNet.Server, NetService.NetError> =>
Effect.callback<NodeNet.Server, NetService.NetError>((resume) => {
const server = NodeNet.createServer();
let settled = false;
const settle = (effect: Effect.Effect<NodeNet.Server, NetService.NetError>) => {
if (settled) return;
settled = true;
resume(effect);
};
server.once("error", (cause) => {
settle(
Effect.fail(new NetService.NetError({ message: "Failed to open test server", cause })),
);
});
if (host) {
server.listen(0, host, () => settle(Effect.succeed(server)));
} else {
server.listen(0, () => settle(Effect.succeed(server)));
}
return closeServer(server);
});
it.layer(NetService.layer)("NetService", (it) => {
describe("Net helpers", () => {
it.effect("reserveLoopbackPort returns a positive loopback port", () =>
Effect.gen(function* () {
const net = yield* NetService.NetService;
const port = yield* net.reserveLoopbackPort();
assert.ok(port > 0);
}),
);
it.effect("isPortAvailableOnLoopback reports false for an occupied port", () =>
Effect.acquireUseRelease(
openServer("127.0.0.1"),
(server) =>
Effect.gen(function* () {
const net = yield* NetService.NetService;
const port = getPort(server);
const available = yield* net.isPortAvailableOnLoopback(port);
assert.equal(available, false);
}),
closeServer,
),
);
it.effect("findAvailablePort returns preferred when it is free", () =>
Effect.gen(function* () {
const net = yield* NetService.NetService;
const preferred = yield* net.reserveLoopbackPort();
const resolved = yield* net.findAvailablePort(preferred);
assert.equal(resolved, preferred);
}),
);
it.effect("findAvailablePort falls back when a wildcard listener occupies IPv4", () =>
Effect.acquireUseRelease(
openServer("0.0.0.0"),
(server) =>
Effect.gen(function* () {
const net = yield* NetService.NetService;
const preferred = getPort(server);
const resolved = yield* net.findAvailablePort(preferred);
assert.ok(resolved > 0);
assert.notEqual(resolved, preferred);
}),
closeServer,
),
);
});
});