mirror of
https://github.com/paperclipai/paperclip.git
synced 2026-10-23 17:33:51 +02:00
test: isolate runtime port claims and canonicalize fixture paths
Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
1 parent
1885918563
commit
1275ef8282
1 file changed
+28
-14
@@ -43,6 +43,7 @@ import {
|
||||
releaseRuntimeServicesForRun,
|
||||
UnresolvedWorkspaceBaseRefError,
|
||||
resetRuntimeServicesForTests,
|
||||
resetRuntimeServicePortReservationsForTests,
|
||||
MANAGED_RUNTIME_PUBLIC_URL_ENV,
|
||||
resolveManagedPaperclipRuntimePublicOrigin,
|
||||
resolveRuntimeProvisionCommand,
|
||||
@@ -454,6 +455,9 @@ afterEach(async () => {
|
||||
delete process.env.PAPERCLIP_WORKTREES_DIR;
|
||||
delete process.env.DATABASE_URL;
|
||||
await resetRuntimeServicesForTests();
|
||||
// Registry reset does not clear the process-local allocation claims. A
|
||||
// failed-start fixture must not reserve another test's ephemeral port.
|
||||
resetRuntimeServicePortReservationsForTests();
|
||||
});
|
||||
|
||||
describe("sanitizeRuntimeServiceBaseEnv", () => {
|
||||
@@ -4099,6 +4103,7 @@ describe("realizeExecutionWorkspace", () => {
|
||||
"utf8",
|
||||
);
|
||||
process.env.PAPERCLIP_WORKTREES_DIR = worktreesDir;
|
||||
const canonicalInstanceRoot = await fs.realpath(instanceRoot);
|
||||
|
||||
await cleanupExecutionWorkspaceArtifacts({
|
||||
workspace: {
|
||||
@@ -4133,7 +4138,7 @@ describe("realizeExecutionWorkspace", () => {
|
||||
expect(operations[0]?.command).toBe("printf 'cleanup ok\\n'");
|
||||
expect(operations[1]?.metadata).toMatchObject({
|
||||
cleanupAction: "remove_worktree_instance",
|
||||
instanceRoot,
|
||||
instanceRoot: canonicalInstanceRoot,
|
||||
});
|
||||
expect(operations[2]?.metadata).toMatchObject({
|
||||
cleanupAction: "worktree_remove",
|
||||
@@ -7643,16 +7648,25 @@ describeEmbeddedPostgres("workspace runtime startup reconciliation", () => {
|
||||
process.env.PAPERCLIP_HOME = paperclipHome;
|
||||
process.env.PAPERCLIP_INSTANCE_ID = `runtime-desired-reconcile-${randomUUID()}`;
|
||||
|
||||
const reservePort = async () => {
|
||||
const probe = net.createServer();
|
||||
await new Promise<void>((resolve) => probe.listen(0, "127.0.0.1", resolve));
|
||||
const address = probe.address();
|
||||
const port = typeof address === "object" && address ? address.port : null;
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
probe.close((error) => error ? reject(error) : resolve());
|
||||
});
|
||||
if (!port) throw new Error("Failed to reserve runtime reconciliation test port");
|
||||
return port;
|
||||
const reservePorts = async () => {
|
||||
const probes = [net.createServer(), net.createServer()];
|
||||
try {
|
||||
// Keep both sockets open until both allocations finish. Closing the
|
||||
// first probe early lets the kernel return that same port again.
|
||||
for (const probe of probes) await new Promise<void>((resolve, reject) => {
|
||||
probe.once("error", reject);
|
||||
probe.listen(0, "127.0.0.1", resolve);
|
||||
});
|
||||
return probes.map(probe => {
|
||||
const address = probe.address();
|
||||
if (!address || typeof address !== "object") throw new Error("Failed to reserve runtime reconciliation test port");
|
||||
return address.port;
|
||||
});
|
||||
} finally {
|
||||
await Promise.all(probes.filter(probe => probe.listening).map(probe => new Promise<void>((resolve, reject) => {
|
||||
probe.close(error => error ? reject(error) : resolve());
|
||||
})));
|
||||
}
|
||||
};
|
||||
const isLoopbackPortFree = async (port: number) => {
|
||||
const probe = net.createServer();
|
||||
@@ -7673,8 +7687,8 @@ describeEmbeddedPostgres("workspace runtime startup reconciliation", () => {
|
||||
}
|
||||
throw new Error(`Port ${port} did not become free in time`);
|
||||
};
|
||||
const stoppedPort = await reservePort();
|
||||
const livePort = await reservePort();
|
||||
const [stoppedPort, livePort] = await reservePorts();
|
||||
expect(stoppedPort).not.toBe(livePort);
|
||||
const companyId = randomUUID();
|
||||
const projectId = randomUUID();
|
||||
const projectWorkspaceId = randomUUID();
|
||||
@@ -9728,7 +9742,7 @@ describe("realizeExecutionWorkspace with an exact existing branch", () => {
|
||||
|
||||
const workspace = await realizeExistingBranch(repoRoot, "feature/legacy-checkout");
|
||||
|
||||
expect(workspace.cwd).toBe(path.resolve(legacyPath));
|
||||
expect(workspace.cwd).toBe(await fs.realpath(legacyPath));
|
||||
expect(workspace.branchName).toBe("feature/legacy-checkout");
|
||||
expect(workspace.created).toBe(false);
|
||||
expect(await readGit(workspace.cwd, ["rev-parse", "HEAD"])).toBe(branchTip);
|
||||
|
||||
Reference in new issue
Block a user