mirror of
https://github.com/aphrody-labs/vu.git
synced 2026-10-14 12:19:18 +00:00
77 lines
3.2 KiB
TypeScript
77 lines
3.2 KiB
TypeScript
// SPDX-License-Identifier: Apache-2.0
|
|
import { expect, test } from "bun:test";
|
|
import { existsSync } from "node:fs";
|
|
import { homedir } from "node:os";
|
|
import { join } from "node:path";
|
|
import { findLibpython } from "./shared-libpython.ts";
|
|
|
|
const artifact =
|
|
process.env["VU_TEST_ARTIFACT"] ??
|
|
join(homedir(), ".vu/runtime/x86_64-unknown-linux-gnu/current");
|
|
const present = existsSync(artifact) && findLibpython(artifact) !== null;
|
|
const site = process.env["VU_TEST_SITE"];
|
|
|
|
test("findLibpython reads the artifact's lib directory", () => {
|
|
expect(findLibpython("/nonexistent")).toBeNull();
|
|
});
|
|
|
|
// Python is initialised and finalised once per process, so each scenario runs in a child Bun.
|
|
async function child(
|
|
code: string,
|
|
withSite: boolean,
|
|
fork?: string,
|
|
): Promise<{ code: number; out: string; err: string }> {
|
|
const script = `import { runInSharedPython } from ${JSON.stringify(join(import.meta.dir, "shared-libpython.ts"))};
|
|
console.log(JSON.stringify(runInSharedPython(${JSON.stringify(artifact)}, ${JSON.stringify(code)}${withSite ? `, ${JSON.stringify(site)}` : ", undefined"}, { promote: ${fork === undefined} })));`;
|
|
const run = Bun.spawn([fork ?? "bun", "-e", script], { stdout: "pipe", stderr: "pipe" });
|
|
const [out, err, exit] = await Promise.all([
|
|
new Response(run.stdout).text(),
|
|
new Response(run.stderr).text(),
|
|
run.exited,
|
|
]);
|
|
return { code: exit, out, err };
|
|
}
|
|
|
|
test.skipIf(!present)("Bun runs the runtime's CPython in-process", async () => {
|
|
const run = await child("open(RESULT_PATH, 'w').write(sys.version.split()[0])", false);
|
|
expect(run.code).toBe(0);
|
|
expect(JSON.parse(run.out).value).toMatch(/^3\.12\./);
|
|
});
|
|
|
|
test.skipIf(!present)("exactly one libpython is mapped in the process", async () => {
|
|
const code = [
|
|
"import re",
|
|
"maps = open('/proc/self/maps').read()",
|
|
"libs = sorted(set(re.findall(r'(\\S*libpython3[^\\s]*)', maps)))",
|
|
"open(RESULT_PATH, 'w').write(str(len(libs)))",
|
|
].join("\n");
|
|
const run = await child(code, false);
|
|
expect(run.code).toBe(0);
|
|
expect(JSON.parse(run.out).value).toBe("1");
|
|
});
|
|
|
|
test.skipIf(!present || site === undefined)(
|
|
"Bun to Python to Rust: a PyO3 extension runs on the same libpython and returns a value to Bun",
|
|
async () => {
|
|
const code =
|
|
"from aphrody import aphrody_rust as r\nopen(RESULT_PATH, 'w').write(repr(r.cosine_similarity([1.0, 2.0], [1.0, 2.0])))";
|
|
const run = await child(code, true);
|
|
expect(run.err).not.toContain("Traceback");
|
|
expect(JSON.parse(run.out).value).toBe("1.0");
|
|
},
|
|
);
|
|
|
|
// The yolo fork opens the library RTLD_GLOBAL itself (`dlopen(..., { global: true })`, plan D18): no promotion from Python.
|
|
// VU_TEST_BUN is the fork's engine link (the `bun` name of the yolo binary, argv0 selects the engine).
|
|
const fork = process.env["VU_TEST_BUN"];
|
|
test.skipIf(!present || site === undefined || fork === undefined)(
|
|
"yolo fork: the same end-to-end path works with no ctypes promotion",
|
|
async () => {
|
|
const code =
|
|
"from aphrody import aphrody_rust as r\nopen(RESULT_PATH, 'w').write(repr(r.cosine_similarity([1.0, 2.0], [1.0, 2.0])))";
|
|
const run = await child(code, true, fork);
|
|
expect(run.err).not.toContain("undefined symbol");
|
|
expect(JSON.parse(run.out).value).toBe("1.0");
|
|
},
|
|
);
|