Skip to content

Commit 497f99c

Browse files
authored
test: isolate offline BYOK children from ambient proxies (#172)
1 parent 4c0d829 commit 497f99c

4 files changed

Lines changed: 60 additions & 24 deletions

File tree

‎release/public-source.json‎

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎test/byok.test.mjs‎

Lines changed: 42 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import path from "node:path";
1515
import { fileURLToPath } from "node:url";
1616
import Database from "better-sqlite3";
1717
import { parse as parseYaml } from "yaml";
18+
import { withoutProxyEnvironment } from "./offline-environment.mjs";
1819

1920
const cli = fileURLToPath(new URL("../dist/cli.js", import.meta.url));
2021
// This fixture validates BYOK transport and real Runtime persistence, not model quality.
@@ -152,7 +153,6 @@ test(
152153
});
153154
const baseUrl = `http://127.0.0.1:${server.address().port}/v1`;
154155
const env = {
155-
...process.env,
156156
MINIMAX_DATA_DIR: dataDir,
157157
MAVIS_DATA_DIR: dataDir,
158158
MCODE_PROVIDER_API_KEY: "fixture-only-key",
@@ -161,12 +161,9 @@ test(
161161
MCODE_TEST_MANAGED_OFFLINE: "1",
162162
MCODE_TEST_PROCESS_PROBE: "1",
163163
NODE_OPTIONS: `--import=${new URL("./network-deny.mjs", import.meta.url).href}`,
164-
HTTP_PROXY: "",
165-
HTTPS_PROXY: "",
166-
ALL_PROXY: "",
167164
};
168165
let commandSequence = 0;
169-
async function run(args) {
166+
async function run(args, environment = process.env) {
170167
const startedAt = Date.now();
171168
const label = args.slice(0, 2).join(" ");
172169
const requestCountAtStart = requests.length;
@@ -177,7 +174,7 @@ test(
177174
return new Promise((resolve, reject) => {
178175
const child = spawn(process.execPath, [cli, ...commandArgs], {
179176
cwd: dataDir,
180-
env,
177+
env: { ...withoutProxyEnvironment(environment), ...env },
181178
stdio: ["ignore", "pipe", "pipe"],
182179
});
183180
let stdout = "",
@@ -247,13 +244,45 @@ test(
247244
(p) => p.kind === "custom" && p.name === "Fixture",
248245
);
249246
assert.ok(selected?.hasApiKey);
250-
await run([
251-
"provider",
252-
"test",
253-
selected.providerId,
254-
"--model",
255-
"fixture-model",
256-
]);
247+
const proxyNames = [
248+
"HTTP_PROXY", "HTTPS_PROXY", "ALL_PROXY", "NO_PROXY",
249+
"http_proxy", "https_proxy", "all_proxy", "no_proxy",
250+
];
251+
const cleanEnvironment = Object.fromEntries(
252+
Object.entries(process.env).filter(([name]) => !proxyNames.includes(name)),
253+
);
254+
const proxyValue = (name) => name.toLowerCase() === "no_proxy"
255+
? "*"
256+
: "http://127.0.0.1:9";
257+
for (const [label, proxies] of [
258+
["no proxy", {}],
259+
...proxyNames.map((name) => [name, { [name]: proxyValue(name) }]),
260+
["uppercase and lowercase together", Object.fromEntries(
261+
proxyNames.map((name) => [name, proxyValue(name)]),
262+
)],
263+
]) {
264+
await t.test(`offline BYOK ignores ambient proxies: ${label}`, async () => {
265+
const environment = Object.freeze({ ...cleanEnvironment, ...proxies });
266+
// NO_PROXY alone does not enable proxy mode, so check its isolation explicitly.
267+
const isolated = withoutProxyEnvironment(environment);
268+
for (const name of proxyNames) assert.equal(isolated[name], "");
269+
assert.equal(isolated.PATH, environment.PATH);
270+
const beforeRequests = requests.length;
271+
const managedAudit = `${networkAudit}.managed`;
272+
const beforeManaged = readFileSync(managedAudit, "utf8").length;
273+
await run([
274+
"provider", "test", selected.providerId, "--model", "fixture-model",
275+
], environment);
276+
assert.ok(requests.length > beforeRequests, "The local provider must receive the request");
277+
assert.equal(requests[beforeRequests].body.model, "fixture-model");
278+
assert.match(
279+
readFileSync(managedAudit, "utf8").slice(beforeManaged),
280+
/https:\/\/models\.dev\/api\.json|\/mavis\/api\/v1\/models-dev\/catalog/,
281+
);
282+
assert.equal(existsSync(networkAudit), false, "No outbound network attempt is allowed");
283+
for (const [name, value] of Object.entries(proxies)) assert.equal(environment[name], value);
284+
});
285+
}
257286
const configPath = path.join(dataDir, "config.yaml");
258287
const savedConfig = () => parseYaml(readFileSync(configPath, "utf8"));
259288
assert.equal(savedConfig().defaultModel, "minimax/MiniMax-M3");

‎test/offline-environment.mjs‎

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Proxy setup installs undici.fetch over the preloaded offline mock.
2+
// Keep host proxy settings out of isolated CLI children without changing the parent.
3+
export function withoutProxyEnvironment(environment = process.env) {
4+
return {
5+
...environment,
6+
HTTP_PROXY: "",
7+
HTTPS_PROXY: "",
8+
ALL_PROXY: "",
9+
NO_PROXY: "",
10+
http_proxy: "",
11+
https_proxy: "",
12+
all_proxy: "",
13+
no_proxy: "",
14+
};
15+
}

‎test/smoke.test.mjs‎

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { tmpdir } from "node:os";
66
import path from "node:path";
77
import { fileURLToPath } from "node:url";
88
import Database from "better-sqlite3";
9+
import { withoutProxyEnvironment } from "./offline-environment.mjs";
910

1011
const root = fileURLToPath(new URL("../", import.meta.url));
1112
const cli = path.join(root, "dist/cli.js");
@@ -39,17 +40,7 @@ function fixture(t, environment = process.env) {
3940
return {
4041
cwd: dataDir,
4142
env: {
42-
...environment,
43-
// Proxy setup installs undici.fetch over the preloaded offline mock.
44-
// Keep host proxy settings out of these isolated test children.
45-
HTTP_PROXY: "",
46-
HTTPS_PROXY: "",
47-
ALL_PROXY: "",
48-
NO_PROXY: "",
49-
http_proxy: "",
50-
https_proxy: "",
51-
all_proxy: "",
52-
no_proxy: "",
43+
...withoutProxyEnvironment(environment),
5344
MINIMAX_DATA_DIR: dataDir,
5445
MAVIS_DATA_DIR: dataDir,
5546
MCODE_TEST_NETWORK_AUDIT: audit,

0 commit comments

Comments
 (0)