Repository navigation
test(core): run Code Mode's executor on plain workerd, and check what core keeps after many runs #392
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
test(core): run Code Mode's executor on plain workerd, and check what core keeps after many runs #392
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
f065708
test(core): measure what Code Mode runs hold, and run its executor on…
nickruigrok 3149fe7
fix(core): bundle the Code Mode smoke run with Wrangler, and claim on…
nickruigrok 1499b35
test(core): check the Code Mode smoke run streams no more lines than …
nickruigrok 0fc1867
test(core): check the closed-lease cap, and clean up after a failed C…
nickruigrok File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,139 @@ | ||
| import { WorkerEntrypoint, env, exports } from "cloudflare:workers"; | ||
|
|
||
| import { | ||
| codeLimits, | ||
| codeRuntime, | ||
| cutMarker, | ||
| describeRun, | ||
| runCode, | ||
| utf8Bytes, | ||
| } from "../../src/code-mode.ts"; | ||
| import type { CodeRun } from "../../src/code-mode.ts"; | ||
|
|
||
| // Code Mode's executor on plain workerd (scripts/workerd-code-mode.ts): | ||
| // the same `runCode` core runs, with a Worker Loader and a capability of | ||
| // this Worker's own as the code's env, and no Wrangler or Miniflare. Each | ||
| // case runs one module and says how it ended; the script checks them. | ||
|
|
||
| /** Calls the capability took, across every case. */ | ||
| let calls = 0; | ||
|
|
||
| /** A capability the code is given, as core gives its APIs: a loopback stub. */ | ||
| export class Caps extends WorkerEntrypoint { | ||
| // oxlint-disable-next-line class-methods-use-this -- an RPC method, called on the entrypoint | ||
| async double(value: number): Promise<number> { | ||
| calls += 1; | ||
| await scheduler.wait(1); | ||
| return value * 2; | ||
| } | ||
| } | ||
|
|
||
| interface Case { | ||
| code: string; | ||
| timeoutMs?: number; | ||
| /** Cancels the run this long after it starts. */ | ||
| cancelAfterMs?: number; | ||
| } | ||
|
|
||
| const cases: Record<string, Case> = { | ||
| complete: { | ||
| code: "const twice = (env, n) => env.caps.double(n); export default async (self, env, ctx) => ({ self, ctx: Object.keys(ctx), sum: (await Promise.all([twice(env, 1), twice(env, 2)])).reduce((a, b) => a + b, 0) });", | ||
| }, | ||
| network: { | ||
| code: "export default async () => (await fetch('https://example.com')).status;", | ||
| }, | ||
| syntax: { code: "export default async () => {" }, | ||
| notAFunction: { code: "export default 42;" }, | ||
| throwsAsItLoads: { | ||
| code: "console.log('loading'); throw new Error('broken module'); export default async () => 1;", | ||
| }, | ||
| throws: { code: "export default async () => { throw new Error('nope'); };" }, | ||
| oversized: { | ||
| code: `export default async () => 1; // ${"x".repeat(codeLimits.sourceChars)}`, | ||
| }, | ||
| neverSettles: { | ||
| code: "export default async () => { await new Promise(() => {}); };", | ||
| }, | ||
| waitsPastItsTime: { | ||
| code: "export default async () => { await scheduler.wait(60_000); };", | ||
| timeoutMs: 1000, | ||
| }, | ||
| cancelled: { | ||
| code: "export default async () => { await scheduler.wait(60_000); };", | ||
| cancelAfterMs: 300, | ||
| }, | ||
| manyLines: { | ||
| code: "export default async () => { for (let i = 0; i < 5000; i++) console.log(i); return 'done'; };", | ||
| }, | ||
| flood: { | ||
| code: "export default async () => { for (let i = 0; i < 5000; i++) console.log('é'.repeat(200)); throw new Error('the end'); };", | ||
| }, | ||
| }; | ||
|
|
||
| /** Whether `value` is a stub a loaded Worker can be given in its env. */ | ||
| const isFetcher = (value: unknown): value is Fetcher => | ||
| (typeof value === "object" || typeof value === "function") && | ||
| value !== null && | ||
| "fetch" in value; | ||
|
|
||
| /** A loopback stub of {@link Caps}, as core makes its APIs' stubs. */ | ||
| const capability = (): Fetcher => { | ||
| const make: unknown = Reflect.get(exports, "Caps"); | ||
| if (typeof make !== "function") { | ||
| throw new TypeError("This Worker exports no Caps"); | ||
| } | ||
| const stub: unknown = Reflect.apply(make, exports, [{}]); | ||
| if (!isFetcher(stub)) { | ||
| throw new TypeError("Caps gave no stub"); | ||
| } | ||
| return stub; | ||
| }; | ||
|
|
||
| /** One case: how it ended, what the model would read, what streamed. */ | ||
| const runCase = async ({ code, timeoutMs, cancelAfterMs }: Case) => { | ||
| const cancel = new AbortController(); | ||
| if (cancelAfterMs !== undefined) { | ||
| setTimeout(() => { | ||
| cancel.abort(); | ||
| }, cancelAfterMs); | ||
| } | ||
| const streamed: string[] = []; | ||
| const started = Date.now(); | ||
| const run: CodeRun = await runCode( | ||
| env.LOADER, | ||
| code, | ||
| { caps: capability() }, | ||
| { | ||
| signal: cancel.signal, | ||
| ...(timeoutMs === undefined ? {} : { timeoutMs }), | ||
| onOutput: (line) => { | ||
| streamed.push(line); | ||
| }, | ||
| } | ||
| ); | ||
| const text = describeRun(run); | ||
| return { | ||
| status: run.status, | ||
| text: text.slice(0, 400), | ||
| ending: text.slice(-200), | ||
| ms: Date.now() - started, | ||
| bytes: utf8Bytes(text), | ||
| cut: text.includes(cutMarker), | ||
| streamed: streamed.length, | ||
| }; | ||
| }; | ||
|
|
||
| export default { | ||
| async fetch(): Promise<Response> { | ||
| const results: Record<string, unknown> = {}; | ||
| for (const [name, each] of Object.entries(cases)) { | ||
| // oxlint-disable-next-line no-await-in-loop -- one run at a time, as a chat runs them | ||
| results[name] = await runCase(each); | ||
| } | ||
| return Response.json({ | ||
| runtime: codeRuntime({ RUNTIME_PROFILE: "workerd" }), | ||
| calls, | ||
| results, | ||
| }); | ||
| }, | ||
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.