Files
SnapOtter/tests/unit/ai/runtime-resources.test.ts
T

1037 lines
36 KiB
TypeScript
Raw Normal View History

import { describe, expect, it } from "vitest";
import {
assertOcrRuntimeMemory,
getOcrRuntimeEffectiveMemoryBytes,
} from "../../../packages/ai/src/runtime-resources.js";
const GiB = 1024 ** 3;
describe("OCR runtime memory compatibility", () => {
it("uses the smallest configured physical, cgroup v2, or cgroup v1 capacity", () => {
const files = new Map([
["/sys/fs/cgroup/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory/memory.limit_in_bytes", String(5 * GiB)],
["/sys/fs/cgroup/memory.limit_in_bytes", String(7 * GiB)],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "darwin",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
});
it("resolves a private cgroup namespace from the process membership", () => {
const files = new Map([
["/proc/self/cgroup", "0::/\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
["/sys/fs/cgroup/memory.max", String(6 * GiB)],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(6 * GiB);
});
it("resolves the tightest cgroup v2 limit when the hierarchy root has no memory.max", () => {
const files = new Map([
["/proc/self/cgroup", "0::/system.slice/docker:deadbeef.scope\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
["/sys/fs/cgroup/system.slice/docker:deadbeef.scope/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/system.slice/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/cgroup.controllers", "cpu memory\n"],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
});
it("keeps tighter ancestors visible across overlapping cgroup v2 mounts", () => {
const files = new Map([
["/proc/self/cgroup", "0::/outer/parent/child\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:26 /outer/parent /sys/fs/cgroup/delegated rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
].join("\n"),
],
["/sys/fs/cgroup/outer/parent/child/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/outer/parent/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/outer/memory.max", String(2 * GiB)],
["/sys/fs/cgroup/memory.max", "max\n"],
["/sys/fs/cgroup/delegated/child/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/delegated/memory.max", String(6 * GiB)],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(2 * GiB);
});
it("accepts the mount namespace root self-parent sentinel", () => {
const files = new Map([
["/proc/self/cgroup", "0::/job\n"],
[
"/proc/self/mountinfo",
[
"1 1 0:1 / / rw,relatime - overlay overlay rw",
"29 1 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
].join("\n"),
],
["/sys/fs/cgroup/job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/memory.max", "max\n"],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
});
it("resolves mount visibility by path depth independent of mountinfo order", () => {
const files = new Map([
["/proc/self/cgroup", "0::/job\n"],
[
"/proc/self/mountinfo",
[
"29 1 0:26 / /cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"1 1 0:1 / / rw,relatime - overlay overlay rw",
].join("\n"),
],
["/cgroup/job/memory.max", String(5 * GiB)],
["/cgroup/memory.max", "max\n"],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
});
it.each([
["a non-root self-cycle", ["40 40 0:99 / /unrelated rw - tmpfs tmpfs rw"]],
[
"a multi-record parent cycle",
["40 41 0:99 / /cycle-a rw - tmpfs tmpfs rw", "41 40 0:100 / /cycle-b rw - tmpfs tmpfs rw"],
],
])("fails closed when mountinfo contains %s", (_label, malformedMounts) => {
const files = new Map([
["/proc/self/cgroup", "0::/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
...malformedMounts,
].join("\n"),
],
["/sys/fs/cgroup/job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/memory.max", "max\n"],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("fails closed when a same-point cgroup mount covers the matching hierarchy", () => {
const files = new Map([
["/proc/self/cgroup", "0::/real/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:26 /decoy /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
].join("\n"),
],
["/sys/fs/cgroup/real/job/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/real/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory.max", String(6 * GiB)],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("fails closed for a cgroup mount beneath a covered non-cgroup ancestor", () => {
const files = new Map([
["/proc/self/cgroup", "0::/real/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:99 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw",
"31 29 0:26 /real /sys/fs/cgroup/child rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
].join("\n"),
],
["/sys/fs/cgroup/real/job/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/real/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/child/job/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/child/memory.max", String(6 * GiB)],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it.each([
[
"topological record order",
[
"29 23 0:26 /old /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:26 /old/child /sys/fs/cgroup/child rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"31 29 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"32 31 0:26 /child /sys/fs/cgroup/child rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
],
],
[
"adversarial record order",
[
"32 31 0:26 /child /sys/fs/cgroup/child rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:26 /old/child /sys/fs/cgroup/child rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"31 29 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"29 23 0:26 /old /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
],
],
[
"a same-point stack on the replacement child",
[
"33 32 0:26 /child /sys/fs/cgroup/child rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:26 /old/child /sys/fs/cgroup/child rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"29 23 0:26 /old /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"32 31 0:26 /child /sys/fs/cgroup/child rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"31 29 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
],
],
])("ignores a hidden old child when its replacement has the same mountpoint (%s)", (_label, mounts) => {
const files = new Map([
["/proc/self/cgroup", "0::/child/job\n"],
["/proc/self/mountinfo", mounts.join("\n")],
["/sys/fs/cgroup/child/job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/child/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory.max", String(7 * GiB)],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
});
it("fails closed when two reachable mounts claim the same mountpoint", () => {
const files = new Map([
["/proc/self/cgroup", "0::/child/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:26 /child /sys/fs/cgroup/child rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"31 29 0:26 /child /sys/fs/cgroup/child rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
].join("\n"),
],
["/sys/fs/cgroup/child/job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/child/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory.max", String(7 * GiB)],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("fails closed when a nested cgroup mount remaps the process path", () => {
const files = new Map([
["/proc/self/cgroup", "0::/real/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:26 /decoy /sys/fs/cgroup/real rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
].join("\n"),
],
["/sys/fs/cgroup/real/job/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/real/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory.max", "max\n"],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("allows a same-device nested cgroup mount that preserves the logical path", () => {
const files = new Map([
["/proc/self/cgroup", "0::/real/job\n"],
[
"/proc/self/mountinfo",
[
"30 29 0:26 /real /sys/fs/cgroup/real rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
].join("\n"),
],
["/sys/fs/cgroup/real/job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/real/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory.max", String(7 * GiB)],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
});
it("fails closed when a matching nested cgroup root comes from another device", () => {
const files = new Map([
["/proc/self/cgroup", "0::/real/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:27 /real /sys/fs/cgroup/real rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
].join("\n"),
],
["/sys/fs/cgroup/real/job/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/real/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory.max", "max\n"],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("fails closed when a nested non-cgroup mount shadows the process path", () => {
const files = new Map([
["/proc/self/cgroup", "0::/real/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:99 / /sys/fs/cgroup/real rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw",
].join("\n"),
],
["/sys/fs/cgroup/real/job/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/real/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory.max", "max\n"],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("does not confuse a sibling mountpoint with a process-path prefix", () => {
const files = new Map([
["/proc/self/cgroup", "0::/real/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 29 0:99 / /sys/fs/cgroup/real-other rw,nosuid,nodev,noexec,relatime - tmpfs tmpfs rw",
].join("\n"),
],
["/sys/fs/cgroup/real/job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/real/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory.max", String(7 * GiB)],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
});
it.each([
["process directory", "/sys/fs/cgroup/real/job"],
["limit file", "/sys/fs/cgroup/real/job/memory.max"],
])("fails closed when a non-cgroup mount shadows the exact %s", (_label, mountPoint) => {
const files = new Map([
["/proc/self/cgroup", "0::/real/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
`30 29 8:1 /decoy ${mountPoint} rw,relatime - ext4 /dev/root rw`,
].join("\n"),
],
["/sys/fs/cgroup/real/job/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/real/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/memory.max", "max\n"],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("skips an absent non-root cgroup v2 memory controller and keeps walking", () => {
const files = new Map([
["/proc/self/cgroup", "0::/delegated/job\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
["/sys/fs/cgroup/delegated/job/cgroup.controllers", "cpu\n"],
["/sys/fs/cgroup/delegated/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/cgroup.controllers", "cpu memory\n"],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
});
it("uses the binding v1 memory limit on a deeper-root hybrid hierarchy", () => {
const files = new Map([
["/proc/self/cgroup", "0::/delegated/job\n5:memory:/legacy/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 /delegated /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 23 0:27 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory",
].join("\n"),
],
["/sys/fs/cgroup/unified/job/cgroup.controllers", "cpu\n"],
["/sys/fs/cgroup/unified/cgroup.controllers", "cpu\n"],
["/sys/fs/cgroup/memory/legacy/job/memory.limit_in_bytes", String(3 * GiB)],
["/sys/fs/cgroup/memory/legacy/memory.limit_in_bytes", String(4 * GiB)],
["/sys/fs/cgroup/memory/memory.limit_in_bytes", String(16 * GiB)],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(3 * GiB);
});
it("ignores an unresolvable inherited cgroup v2 mount when v1 owns memory", () => {
const files = new Map([
["/proc/self/cgroup", "0::/delegated/job\n5:memory:/legacy/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 /.. /sys/fs/cgroup/unified rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
"30 23 0:27 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory",
].join("\n"),
],
["/sys/fs/cgroup/memory/legacy/job/memory.limit_in_bytes", String(3 * GiB)],
["/sys/fs/cgroup/memory/legacy/memory.limit_in_bytes", String(4 * GiB)],
["/sys/fs/cgroup/memory/memory.limit_in_bytes", String(16 * GiB)],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(3 * GiB);
});
it("ignores a namespace-relative root on an irrelevant v1 controller mount", () => {
const files = new Map([
["/proc/self/cgroup", "2:cpu:/job\n0::/job\n"],
[
"/proc/self/mountinfo",
[
"29 23 0:26 /.. /sys/fs/cgroup/cpu rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,cpu",
"30 23 0:27 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw",
].join("\n"),
],
["/sys/fs/cgroup/job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/cgroup.controllers", "cpu memory\n"],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
});
it.each([
"ENOENT",
"EACCES",
])("fails closed when an absent v2 limit cannot be verified against its cgroup directory (%s)", (coreErrorCode) => {
const files = new Map([
["/proc/self/cgroup", "0::/deleted\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value !== undefined) return value;
const code = path.endsWith("/cgroup.controllers") ? coreErrorCode : "ENOENT";
throw Object.assign(new Error("unavailable"), { code });
},
}),
).toThrow("cgroup memory capacity");
});
it("fails closed when a cgroup v2 ancestor limit is unreadable", () => {
const files = new Map([
["/proc/self/cgroup", "0::/system.slice/docker:deadbeef.scope\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
["/sys/fs/cgroup/system.slice/docker:deadbeef.scope/memory.max", String(6 * GiB)],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("denied"), { code: "EACCES" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("fails closed when a cgroup v2 ancestor limit is malformed", () => {
const files = new Map([
["/proc/self/cgroup", "0::/system.slice/docker:deadbeef.scope\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
["/sys/fs/cgroup/system.slice/docker:deadbeef.scope/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/system.slice/memory.max", "not-a-number\n"],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("fails closed when a cgroup v1 memory limit file is absent", () => {
const files = new Map([
["/proc/self/cgroup", "5:memory:/actions/job\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory\n",
],
["/sys/fs/cgroup/memory/actions/job/memory.limit_in_bytes", String(6 * GiB)],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("treats a numeric zero cgroup limit as binding", () => {
const files = new Map([
["/proc/self/cgroup", "0::/job\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
["/sys/fs/cgroup/job/memory.max", "0\n"],
["/sys/fs/cgroup/cgroup.controllers", "cpu memory\n"],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(0);
});
it("retries resolution when the process cgroup membership changes once", () => {
let membershipReads = 0;
const stableMembership = "0::/new-job\n";
const files = new Map([
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
["/sys/fs/cgroup/old-job/memory.max", String(6 * GiB)],
["/sys/fs/cgroup/new-job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/cgroup.controllers", "cpu memory\n"],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
if (path === "/proc/self/cgroup") {
membershipReads += 1;
return membershipReads === 1 ? "0::/old-job\n" : stableMembership;
}
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
expect(membershipReads).toBe(4);
});
it("retries when the initial cgroup is deleted while the process migrates", () => {
let migrated = false;
const oldMembership = "0::/old-job\n";
const newMembership = "0::/new-job\n";
const files = new Map([
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
["/sys/fs/cgroup/new-job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/cgroup.controllers", "cpu memory\n"],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
if (path === "/proc/self/cgroup") return migrated ? newMembership : oldMembership;
if (path === "/sys/fs/cgroup/old-job/memory.max") {
migrated = true;
throw Object.assign(new Error("deleted"), { code: "ENOENT" });
}
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
expect(migrated).toBe(true);
});
it("fails closed after three unstable cgroup membership snapshots", () => {
let membershipReads = 0;
const files = new Map([
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
["/sys/fs/cgroup/cgroup.controllers", "cpu memory\n"],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
if (path === "/proc/self/cgroup") {
const membership = `0::/job-${membershipReads}\n`;
membershipReads += 1;
return membership;
}
if (/^\/sys\/fs\/cgroup\/job-[0-9]+\/memory\.max$/.test(path)) {
return String(6 * GiB);
}
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
expect(membershipReads).toBe(6);
});
it("rejects parent traversal in the process cgroup membership", () => {
const files = new Map([
["/proc/self/cgroup", "0::/tenant/../job\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
["/sys/fs/cgroup/job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/cgroup.controllers", "cpu memory\n"],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it.each([
["mount root", "/..", "/sys/fs/cgroup"],
["mount point", "/", "/sys/fs/cgroup/\\056\\056/cgroup"],
])("rejects parent traversal in a relevant cgroup %s", (_label, mountRoot, mountPoint) => {
const files = new Map([
["/proc/self/cgroup", "0::/job\n"],
[
"/proc/self/mountinfo",
`29 23 0:26 ${mountRoot} ${mountPoint} rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n`,
],
["/sys/fs/cgroup/job/memory.max", String(5 * GiB)],
["/sys/fs/cgroup/cgroup.controllers", "cpu memory\n"],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it.each([
"x::/job\n",
"1::/job\n",
"0:memory:/job\n",
])("rejects invalid Linux cgroup hierarchy metadata: %s", (membership) => {
const files = new Map([
["/proc/self/cgroup", membership],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory\n",
],
["/sys/fs/cgroup/memory/job/memory.limit_in_bytes", String(5 * GiB)],
["/sys/fs/cgroup/memory/memory.limit_in_bytes", String(8 * GiB)],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("accepts a legitimate v1 named hierarchy without treating it as cgroup v2", () => {
let membershipReads = 0;
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
if (path === "/proc/self/cgroup") {
membershipReads += 1;
return "1:name=systemd:/user.slice\n";
}
throw Object.assign(new Error("missing"), { code: "ENOENT" });
},
}),
).toBe(8 * GiB);
expect(membershipReads).toBe(2);
});
it("selects the tightest limit across a complete cgroup v1 ancestry", () => {
const files = new Map([
["/proc/self/cgroup", "1:name=systemd:/actions/job\n5:memory:/actions/job\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup/memory rw,nosuid,nodev,noexec,relatime - cgroup cgroup rw,memory\n",
],
["/sys/fs/cgroup/memory/actions/job/memory.limit_in_bytes", String(6 * GiB)],
["/sys/fs/cgroup/memory/actions/memory.limit_in_bytes", String(5 * GiB)],
["/sys/fs/cgroup/memory/memory.limit_in_bytes", String(16 * GiB)],
]);
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("missing"), { code: "ENOENT" });
return value;
},
}),
).toBe(5 * GiB);
});
it("fails closed when an identified process memory controller is unreadable", () => {
const files = new Map([
["/proc/self/cgroup", "0::/docker/deadbeef\n"],
[
"/proc/self/mountinfo",
"29 23 0:26 / /sys/fs/cgroup rw,nosuid,nodev,noexec,relatime - cgroup2 cgroup rw\n",
],
]);
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
const value = files.get(path);
if (value === undefined) throw Object.assign(new Error("denied"), { code: "EACCES" });
return value;
},
}),
).toThrow("cgroup memory capacity");
});
it("fails closed when cgroup membership exists but mount metadata is unreadable", () => {
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
if (path === "/proc/self/cgroup") return "0::/docker/deadbeef\n";
throw Object.assign(new Error("denied"), { code: "EACCES" });
},
}),
).toThrow("cgroup memory capacity");
});
it("fails closed on Linux when process cgroup membership is unreadable or malformed", () => {
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: () => {
throw Object.assign(new Error("denied"), { code: "EACCES" });
},
}),
).toThrow("cgroup memory capacity");
expect(() =>
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "linux",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
if (path === "/proc/self/cgroup") return "malformed-membership\n";
throw Object.assign(new Error("missing"), { code: "ENOENT" });
},
}),
).toThrow("cgroup memory capacity");
});
it("treats cgroup v2 max and missing or malformed limits as unbounded", () => {
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "darwin",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
if (path === "/sys/fs/cgroup/memory.max") return "max\n";
if (path.includes("/memory/memory")) return "not-a-number\n";
throw Object.assign(new Error("missing"), { code: "ENOENT" });
},
}),
).toBe(8 * GiB);
});
it("preserves non-Linux fallback handling for a zero limit", () => {
expect(
getOcrRuntimeEffectiveMemoryBytes({
hostPlatform: "darwin",
physicalMemoryBytes: 8 * GiB,
readTextFile: (path) => {
if (path === "/sys/fs/cgroup/memory.max") return "0\n";
throw Object.assign(new Error("missing"), { code: "ENOENT" });
},
}),
).toBe(8 * GiB);
});
it("rejects invalid requirements and reports actionable capacity failures", () => {
expect(() => assertOcrRuntimeMemory(0, { effectiveMemoryBytes: 8 * GiB })).toThrow(
"minimum memory",
);
expect(() => assertOcrRuntimeMemory(4 * GiB, { effectiveMemoryBytes: 3 * GiB })).toThrow(
/4294967296 bytes required, 3221225472 available/,
);
expect(() => assertOcrRuntimeMemory(4 * GiB, { effectiveMemoryBytes: 4 * GiB })).not.toThrow();
});
});