forked from different-ai/openwork
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathshared-world-engine.test.ts
More file actions
177 lines (163 loc) · 7.78 KB
/
Copy pathshared-world-engine.test.ts
File metadata and controls
177 lines (163 loc) · 7.78 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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
import assert from "node:assert/strict";
import { access, mkdir, mkdtemp, readdir, rm, writeFile } from "node:fs/promises";
import { tmpdir } from "node:os";
import { basename, join } from "node:path";
import { fileURLToPath } from "node:url";
import { test } from "@openwork/testkit";
import { discoverWorlds, main } from "@openwork/world";
const REPO_ROOT = fileURLToPath(new URL("../..", import.meta.url));
const WORLDS_DIRECTORY = join(REPO_ROOT, "worlds");
const worldImports: Record<string, () => Promise<unknown>> = {
"acme-demo.ts": () => import("../../worlds/acme-demo.ts"),
"acme-docs.ts": () => import("../../worlds/acme-docs.ts"),
"azure-byok.ts": () => import("../../worlds/azure-byok.ts"),
"cloud-model-infra-worker.ts": () => import("../../worlds/cloud-model-infra-worker.ts"),
"cloud-model-infra.ts": () => import("../../worlds/cloud-model-infra.ts"),
"cross-workspace-split-view.ts": () => import("../../worlds/cross-workspace-split-view.ts"),
"den-split-origin-kind.ts": () => import("../../worlds/den-split-origin-kind.ts"),
"desktop-prod-live.ts": () => import("../../worlds/desktop-prod-live.ts"),
"dev-headless.ts": () => import("../../worlds/dev-headless.ts"),
"headless-prod-live.ts": () => import("../../worlds/headless-prod-live.ts"),
"litellm-per-member.ts": () => import("../../worlds/litellm-per-member.ts"),
"remote-session.ts": () => import("../../worlds/remote-session.ts"),
"solo.ts": () => import("../../worlds/solo.ts"),
};
async function importPromptly(name: string, load: () => Promise<unknown>): Promise<unknown> {
let timer: NodeJS.Timeout | undefined;
try {
return await Promise.race([
load(),
new Promise<never>((_resolve, reject) => {
timer = setTimeout(() => reject(new Error(`Importing ${name} did not finish within 10 seconds.`)), 10_000);
}),
]);
} finally {
if (timer) clearTimeout(timer);
}
}
function ownedResources(): string[] {
return process.getActiveResourcesInfo()
.filter((name) => /process|tcp|udp|server/i.test(name))
.sort();
}
test("world discovery, list, and help label scripts without importing them", async ({ evidence }) => {
const root = await mkdtemp(join(tmpdir(), "openwork-world-discovery-"));
try {
const worldsDirectory = join(root, "worlds");
const receiptsDirectory = join(root, "receipts");
await mkdir(worldsDirectory);
await writeFile(join(worldsDirectory, "unguarded.ts"), 'throw new Error("world module was imported");\n', "utf8");
assert.deepEqual(await discoverWorlds(worldsDirectory), [{
kind: "script",
name: "unguarded",
path: join(worldsDirectory, "unguarded.ts"),
}]);
const previousReceiptsDirectory = process.env.OPENWORK_WORLD_SNAPSHOT_DIR;
process.env.OPENWORK_WORLD_SNAPSHOT_DIR = receiptsDirectory;
try {
for (const command of [["list"], ["help"]]) {
const lines: string[] = [];
assert.equal(await main(command, {
cwd: root,
worldsDirectory,
print: (line) => lines.push(line),
}), 0);
assert.match(lines.join("\n"), /world scripts/i);
assert.match(lines.join("\n"), /unguarded/);
}
} finally {
if (previousReceiptsDirectory === undefined) delete process.env.OPENWORK_WORLD_SNAPSHOT_DIR;
else process.env.OPENWORK_WORLD_SNAPSHOT_DIR = previousReceiptsDirectory;
}
await assert.rejects(access(receiptsDirectory));
evidence.recordAssertionEvidence(
"Discovery and informational commands are import-free",
"A throwing world file was discovered and labeled as a script by list/help, while its module never ran and no receipt directory was created.",
true,
);
} finally {
await rm(root, { recursive: true, force: true });
}
});
test("every root world is an import-safe executable script module", async ({ evidence }) => {
const worldFileNames = (await readdir(WORLDS_DIRECTORY))
.filter((entry) => entry.endsWith(".ts") && !entry.endsWith(".test.ts"))
.sort();
assert.ok(worldFileNames.length > 0, "expected at least one root world file");
assert.deepEqual(Object.keys(worldImports).sort(), worldFileNames);
const discovered = await discoverWorlds(WORLDS_DIRECTORY);
assert.deepEqual(
discovered,
worldFileNames.map((entry) => ({
kind: "script",
name: basename(entry, ".ts"),
path: join(WORLDS_DIRECTORY, entry),
})),
);
const root = await mkdtemp(join(tmpdir(), "openwork-world-imports-"));
const previousReceiptsDirectory = process.env.OPENWORK_WORLD_SNAPSHOT_DIR;
const signalListeners = {
sigint: process.listenerCount("SIGINT"),
sigterm: process.listenerCount("SIGTERM"),
};
const resources = ownedResources();
process.env.OPENWORK_WORLD_SNAPSHOT_DIR = root;
try {
for (const name of worldFileNames) {
const load = worldImports[name];
assert.ok(load, `missing explicit import for ${name}`);
const loaded = await importPromptly(name, load);
assert.equal(typeof loaded, "object", `${name} must import as a module`);
}
assert.deepEqual(await readdir(root), [], "imports must not create lifecycle receipts");
assert.equal(process.listenerCount("SIGINT"), signalListeners.sigint, "imports must not acquire SIGINT listeners");
assert.equal(process.listenerCount("SIGTERM"), signalListeners.sigterm, "imports must not acquire SIGTERM listeners");
assert.deepEqual(ownedResources(), resources, "imports must not acquire child processes or network resources");
evidence.recordAssertionEvidence(
"Every discovered world is an explicit import-safe script module",
`All ${worldFileNames.length} worlds/*.ts files imported within the deadline without receipts, signal listeners, child processes, or network resources.`,
true,
);
} finally {
if (previousReceiptsDirectory === undefined) delete process.env.OPENWORK_WORLD_SNAPSHOT_DIR;
else process.env.OPENWORK_WORLD_SNAPSHOT_DIR = previousReceiptsDirectory;
await rm(root, { recursive: true, force: true });
}
});
test("the retired definition, topology, adapter, and preset APIs are absent", async ({ evidence }) => {
const deletedPaths = [
"packages/world/src/definition.ts",
"packages/world/src/headless-definition.ts",
"packages/world/src/headless-adapter.ts",
"packages/world/src/compat.ts",
"evals/packages/env/src/topology.ts",
"evals/packages/env/src/world.ts",
"evals/packages/env/src/world-adapter.ts",
"evals/packages/env/src/presets.ts",
"packages/world/test/definition.test.ts",
"packages/world/test/headless-adapter.test.ts",
"evals/packages/env/test/topology.test.ts",
"evals/packages/env/test/snapshot.test.ts",
"evals/packages/env/test/cli.test.ts",
];
for (const path of deletedPaths) await assert.rejects(access(join(REPO_ROOT, path)));
const [worldModule, envModule, testkitModule] = await Promise.all([
import("@openwork/world"),
import("../packages/env/src/index.ts"),
import("@openwork/testkit"),
]);
for (const name of ["createWorld" + "Definition", "defineHeadless" + "WebWorld", "createHeadless" + "WebAdapter"]) {
assert.equal(name in worldModule, false, `@openwork/world must not export ${name}`);
}
for (const name of ["define" + "World", "createEval" + "WorldAdapter", "parseUntrusted" + "Snapshot", "resume" + "World"]) {
assert.equal(name in envModule, false, `@openwork/env must not export ${name}`);
}
for (const name of ["start" + "World", "define" + "World"]) {
assert.equal(name in testkitModule, false, `@openwork/testkit must not export ${name}`);
}
evidence.recordAssertionEvidence(
"The old world abstraction has no files or public runtime exports",
`All ${deletedPaths.length} retired files were absent, and representative definition, topology, adapter, resume, and start APIs were absent from package exports.`,
true,
);
});