Skip to content

Commit 1ae527e

Browse files
committed
vitestで全テスト動くようになった
1 parent db4d038 commit 1ae527e

File tree

6 files changed

+188
-78
lines changed

6 files changed

+188
-78
lines changed

packages/runtime/src/tests.ts

Lines changed: 74 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,44 @@
11
import { expect } from "chai";
22
import { RefObject } from "react";
33
import { RuntimeLang } from "./languages";
4-
import { emptyMutex, ReplOutput, RuntimeContext, UpdatedFile } from "./interface";
4+
import { ReplOutput, RuntimeContext, UpdatedFile } from "./interface";
55

66
export function defineTests(
77
lang: RuntimeLang,
88
runtimeRef: RefObject<Record<RuntimeLang, RuntimeContext>>
99
) {
1010
describe(`${lang} Runtime`, function () {
11-
this.timeout(
12-
(
13-
{
14-
python: 2000,
15-
ruby: 5000,
16-
cpp: 10000,
17-
javascript: 2000,
18-
} as Record<RuntimeLang, number>
19-
)[lang]
20-
);
11+
const timeout = (
12+
{
13+
python: 2000,
14+
ruby: 5000,
15+
javascript: 2000,
16+
typescript: 2000,
17+
cpp: 10000,
18+
rust: 10000,
19+
} as Record<RuntimeLang, number>
20+
)[lang];
21+
22+
if (typeof this !== "undefined" && "timeout" in this) {
23+
(this as any).timeout(timeout);
24+
}
2125

2226
beforeEach(async function () {
23-
this.timeout(60000);
24-
while (!runtimeRef.current[lang].ready) {
27+
if (typeof this !== "undefined" && "timeout" in this) {
28+
(this as any).timeout(60000);
29+
}
30+
31+
while (true) {
32+
const runtime = runtimeRef.current[lang];
33+
if (runtime?.ready) {
34+
const isLocked = runtime.mutex?.isLocked();
35+
if (!isLocked) {
36+
break;
37+
}
38+
}
2539
await new Promise((resolve) => setTimeout(resolve, 100));
2640
}
41+
await new Promise((resolve) => setTimeout(resolve, 50));
2742
});
2843

2944
describe("REPL", function () {
@@ -40,7 +55,10 @@ export function defineTests(
4055
} satisfies Record<RuntimeLang, string | null>
4156
)[lang];
4257
if (!printCode) {
43-
this.skip();
58+
if (typeof this !== "undefined" && "skip" in this) {
59+
return (this as any).skip();
60+
}
61+
return;
4462
}
4563
const outputs: ReplOutput[] = [];
4664
await (runtimeRef.current[lang].mutex || emptyMutex).runExclusive(() =>
@@ -69,7 +87,10 @@ export function defineTests(
6987
} satisfies Record<RuntimeLang, string[] | null[]>
7088
)[lang];
7189
if (!setIntVarCode || !printIntVarCode) {
72-
this.skip();
90+
if (typeof this !== "undefined" && "skip" in this) {
91+
return (this as any).skip();
92+
}
93+
return;
7394
}
7495
const outputs: ReplOutput[] = [];
7596
await (runtimeRef.current[lang].mutex || emptyMutex).runExclusive(
@@ -103,7 +124,10 @@ export function defineTests(
103124
} satisfies Record<RuntimeLang, string | null>
104125
)[lang];
105126
if (!errorCode) {
106-
this.skip();
127+
if (typeof this !== "undefined" && "skip" in this) {
128+
return (this as any).skip();
129+
}
130+
return;
107131
}
108132
const outputs: ReplOutput[] = [];
109133
await (runtimeRef.current[lang].mutex || emptyMutex).runExclusive(() =>
@@ -133,7 +157,10 @@ export function defineTests(
133157
} satisfies Record<RuntimeLang, (string | null)[]>
134158
)[lang];
135159
if (!setIntVarCode || !infLoopCode || !printIntVarCode) {
136-
this.skip();
160+
if (typeof this !== "undefined" && "skip" in this) {
161+
return (this as any).skip();
162+
}
163+
return;
137164
}
138165
const runPromise = (
139166
runtimeRef.current[lang].mutex || emptyMutex
@@ -146,9 +173,18 @@ export function defineTests(
146173
runtimeRef.current[lang].interrupt!();
147174
await new Promise((resolve) => setTimeout(resolve, 100));
148175
await runPromise;
149-
while (!runtimeRef.current[lang].ready) {
176+
177+
// Wait for it to become ready again
178+
const start = Date.now();
179+
while (true) {
180+
const runtime = runtimeRef.current[lang];
181+
if (runtime?.ready && !runtime.mutex?.isLocked()) {
182+
break;
183+
}
184+
if (Date.now() - start > 30000) break;
150185
await new Promise((resolve) => setTimeout(resolve, 100));
151186
}
187+
152188
const outputs: ReplOutput[] = [];
153189
await (runtimeRef.current[lang].mutex || emptyMutex).runExclusive(() =>
154190
runtimeRef.current[lang].runCommand!(printIntVarCode, (output) => {
@@ -173,7 +209,10 @@ export function defineTests(
173209
} satisfies Record<RuntimeLang, string | null>
174210
)[lang];
175211
if (!writeCode) {
176-
this.skip();
212+
if (typeof this !== "undefined" && "skip" in this) {
213+
return (this as any).skip();
214+
}
215+
return;
177216
}
178217
const updatedFiles: UpdatedFile[] = [];
179218
await (runtimeRef.current[lang].mutex || emptyMutex).runExclusive(() =>
@@ -206,7 +245,10 @@ export function defineTests(
206245
} satisfies Record<RuntimeLang, [string, string] | [null, null]>
207246
)[lang];
208247
if (!filename || !code) {
209-
this.skip();
248+
if (typeof this !== "undefined" && "skip" in this) {
249+
return (this as any).skip();
250+
}
251+
return;
210252
}
211253
const outputs: ReplOutput[] = [];
212254
await runtimeRef.current[lang].runFiles(
@@ -242,7 +284,10 @@ export function defineTests(
242284
} satisfies Record<RuntimeLang, [string, string] | [null, null]>
243285
)[lang];
244286
if (!filename || !code) {
245-
this.skip();
287+
if (typeof this !== "undefined" && "skip" in this) {
288+
return (this as any).skip();
289+
}
290+
return;
246291
}
247292
const outputs: ReplOutput[] = [];
248293
await runtimeRef.current[lang].runFiles(
@@ -305,7 +350,10 @@ export function defineTests(
305350
>
306351
)[lang];
307352
if (!codes || !execFiles) {
308-
this.skip();
353+
if (typeof this !== "undefined" && "skip" in this) {
354+
return (this as any).skip();
355+
}
356+
return;
309357
}
310358
const outputs: ReplOutput[] = [];
311359
await runtimeRef.current[lang].runFiles(execFiles, codes, (output) => {
@@ -335,7 +383,10 @@ export function defineTests(
335383
} satisfies Record<RuntimeLang, [string, string] | [null, null]>
336384
)[lang];
337385
if (!filename || !code) {
338-
this.skip();
386+
if (typeof this !== "undefined" && "skip" in this) {
387+
return (this as any).skip();
388+
}
389+
return;
339390
}
340391
const updatedFiles: UpdatedFile[] = [];
341392
await runtimeRef.current[lang].runFiles(

packages/runtime/src/typescript/runtime.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
import { ReplOutput, RuntimeContext, RuntimeInfo, UpdatedFile } from "../interface";
1515

1616
export const compilerOptions: CompilerOptions = {
17-
lib: ["ESNext", "WebWorker"],
17+
lib: ["ESNext", "WebWorker", "DOM"],
1818
target: 10 satisfies ScriptTarget.ES2023,
1919
strict: true,
2020
};
@@ -165,10 +165,11 @@ export function useTypeScript(jsEval: RuntimeContext): RuntimeContext {
165165
);
166166
return {
167167
init,
168-
ready: tsEnv !== null,
168+
ready: tsEnv !== null && jsEval.ready,
169169
runFiles,
170170
getCommandlineStr,
171171
runtimeInfo,
172+
mutex: jsEval.mutex,
172173
};
173174
}
174175

packages/runtime/src/worker/pyodide.worker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import check_syntax_py from "./pyodide/check_syntax.py?raw";
1515
const HOME = `/home/pyodide/`;
1616

1717
let pyodide: PyodideInterface;
18-
let currentOutputCallback: ((output: ReplOutput) => void) | null = null;
18+
let currentOutputCallback: ((output: ReplOutput | UpdatedFile) => void) | null = null;
1919

2020
// Helper function to read all files from the Pyodide file system
2121
function readAllFiles(): Record<string, string> {

packages/runtime/src/worker/ruby.worker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import type { ReplOutput, ReplOutputType, UpdatedFile } from "../interface";
1010
import init_rb from "./ruby/init.rb?raw";
1111

1212
let rubyVM: RubyVM | null = null;
13-
let currentOutputCallback: ((output: ReplOutput) => void) | null = null;
13+
let currentOutputCallback: ((output: ReplOutput | UpdatedFile) => void) | null = null;
1414
let stdoutBuffer = "";
1515
let stderrBuffer = "";
1616

packages/runtime/src/worker/runtime.tsx

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,12 @@ import {
1212
import { wrap, Remote, proxy } from "comlink";
1313
import { RuntimeLang } from "../languages";
1414
import { Mutex, MutexInterface } from "async-mutex";
15-
import { ReplOutput, RuntimeContext, SyntaxStatus, UpdatedFile } from "../interface";
15+
import {
16+
ReplOutput,
17+
RuntimeContext,
18+
SyntaxStatus,
19+
UpdatedFile,
20+
} from "../interface";
1621

1722
type WorkerLang = "python" | "ruby" | "javascript";
1823
export type WorkerCapabilities = {
@@ -71,13 +76,19 @@ export function WorkerProvider({
7176
lang satisfies RuntimeLang;
7277
switch (lang) {
7378
case "python":
74-
worker = new Worker(new URL("./pyodide.worker.ts", import.meta.url), { type: 'module' });
79+
worker = new Worker(new URL("./pyodide.worker.ts", import.meta.url), {
80+
type: "module",
81+
});
7582
break;
7683
case "ruby":
77-
worker = new Worker(new URL("./ruby.worker.ts", import.meta.url), { type: 'module' });
84+
worker = new Worker(new URL("./ruby.worker.ts", import.meta.url), {
85+
type: "module",
86+
});
7887
break;
7988
case "javascript":
80-
worker = new Worker(new URL("./jsEval.worker.ts", import.meta.url), { type: 'module' });
89+
worker = new Worker(new URL("./jsEval.worker.ts", import.meta.url), {
90+
type: "module",
91+
});
8192
break;
8293
default:
8394
lang satisfies never;
@@ -119,6 +130,11 @@ export function WorkerProvider({
119130
});
120131
return () => {
121132
void mutex.runExclusive(async () => {
133+
// Reject all pending promises
134+
const error = new Error("Worker terminated");
135+
pendingPromises.current.forEach((reject) => reject(error));
136+
pendingPromises.current.clear();
137+
122138
workerRef.current?.terminate();
123139
workerRef.current = null;
124140
setReady(false);
@@ -167,7 +183,10 @@ export function WorkerProvider({
167183
}, [initializeWorker, mutex]);
168184

169185
const runCommand = useCallback(
170-
async (code: string, onOutput: (output: ReplOutput | UpdatedFile) => void): Promise<void> => {
186+
async (
187+
code: string,
188+
onOutput: (output: ReplOutput | UpdatedFile) => void
189+
): Promise<void> => {
171190
if (!mutex.isLocked()) {
172191
throw new Error(`mutex of context must be locked for runCommand`);
173192
}

0 commit comments

Comments
 (0)