All basic tests passing or skipped

This commit is contained in:
Radon Rosborough 2020-07-30 17:32:11 -06:00
parent d14df69cf6
commit 30ec0e2ee0
5 changed files with 89 additions and 29 deletions

1
.gitignore vendored
View File

@ -4,3 +4,4 @@
node_modules node_modules
out out
tests tests
tests-*

View File

@ -262,6 +262,7 @@ export class Session {
break; break;
} }
await this.ensure(this.config.ensure); await this.ensure(this.config.ensure);
break;
default: default:
this.logBadMessage(msg); this.logBadMessage(msg);
break; break;

View File

@ -48,6 +48,8 @@ export interface LangConfig {
item?: string; // FIXME item?: string; // FIXME
}; };
template: string; template: string;
timeout?: number;
skip?: string[];
} }
export const langs: { [key: string]: LangConfig } = { export const langs: { [key: string]: LangConfig } = {
@ -349,6 +351,7 @@ int main() {
print("Hello, world!"); print("Hello, world!");
} }
`, `,
timeout: 15,
}, },
chef: { chef: {
name: "Chef", name: "Chef",
@ -424,11 +427,13 @@ Refrigerate for 1 hour.
run: `wine cmd /k main.bat`, run: `wine cmd /k main.bat`,
template: `echo "Hello, world!" template: `echo "Hello, world!"
`, `,
timeout: 15,
}, },
commonlisp: { commonlisp: {
aliases: ["lisp", "sbcl"], aliases: ["lisp", "sbcl"],
name: "Common Lisp", name: "Common Lisp",
repl: "rlwrap sbcl", repl: "rlwrap sbcl",
input: "(* 123 234)",
main: "main.lisp", main: "main.lisp",
run: "rlwrap sbcl --userinit main.lisp", run: "rlwrap sbcl --userinit main.lisp",
template: `(format t "Hello, world!") template: `(format t "Hello, world!")
@ -489,6 +494,7 @@ int main() {
run: "crystal main.cr", run: "crystal main.cr",
template: `puts "Hello, world!" template: `puts "Hello, world!"
`, `,
timeout: 15,
}, },
csharp: { csharp: {
aliases: ["cs", "mcs"], aliases: ["cs", "mcs"],
@ -617,6 +623,7 @@ void main()
lsp: { start: "/opt/elixir-ls/language_server.sh" }, lsp: { start: "/opt/elixir-ls/language_server.sh" },
template: `IO.puts("Hello, world!") template: `IO.puts("Hello, world!")
`, `,
skip: ["repl", "runrepl"],
}, },
elm: { elm: {
name: "Elm", name: "Elm",
@ -733,7 +740,7 @@ main() ->
aliases: ["fs", "gforth"], aliases: ["fs", "gforth"],
name: "Forth", name: "Forth",
repl: "gforth", repl: "gforth",
input: ". 123 234 *", input: "123 234 * .",
main: "main.fs", main: "main.fs",
run: "gforth main.fs", run: "gforth main.fs",
template: `." Hello, world!" CR template: `." Hello, world!" CR
@ -769,6 +776,7 @@ main() ->
run: "fsharpi --use:main.fsx", run: "fsharpi --use:main.fsx",
template: `printfn "Hello, world!" template: `printfn "Hello, world!"
`, `,
timeout: 15,
}, },
go: { go: {
aliases: ["golang"], aliases: ["golang"],
@ -803,6 +811,7 @@ func main() {
run: `JAVA_OPTS="-Djava.util.prefs.systemRoot=$PWD/.java -Djava.util.prefs.userRoot=$PWD/.java/.userPrefs" groovysh main.groovy`, run: `JAVA_OPTS="-Djava.util.prefs.systemRoot=$PWD/.java -Djava.util.prefs.userRoot=$PWD/.java/.userPrefs" groovysh main.groovy`,
template: `print "Hello, world!"; template: `print "Hello, world!";
`, `,
timeout: 15,
}, },
hack: { hack: {
name: "Hack", name: "Hack",
@ -923,11 +932,12 @@ PLEASE GIVE UP
ioke: { ioke: {
aliases: ["ik"], aliases: ["ik"],
name: "Ioke", name: "Ioke",
repl: "ioke", repl: `JAVA_OPTS="-Duser.home=$PWD" ioke`,
main: "main.ik", main: "main.ik",
run: "ioke main.ik; ioke", run: `JAVA_OPTS="-Duser.home=$PWD" ioke main.ik; JAVA_OPTS="-Duser.home=$PWD" ioke`,
template: `"Hello, world!" println template: `"Hello, world!" println
`, `,
timeout: 15,
}, },
java: { java: {
aliases: ["javac"], aliases: ["javac"],
@ -979,6 +989,7 @@ PLEASE GIVE UP
run: "kitten main.ktn; kitten", run: "kitten main.ktn; kitten",
template: `"Hello, world!" say template: `"Hello, world!" say
`, `,
timeout: 15,
}, },
kotlin: { kotlin: {
aliases: ["kts", "kotlinc"], aliases: ["kts", "kotlinc"],
@ -989,6 +1000,7 @@ PLEASE GIVE UP
run: `JAVA_OPTS="-Duser.home=$PWD" kotlinc -script main.kts; kotlinc`, run: `JAVA_OPTS="-Duser.home=$PWD" kotlinc -script main.kts; kotlinc`,
template: `println("Hello, world!") template: `println("Hello, world!")
`, `,
timeout: 30,
}, },
ksh: { ksh: {
aliases: ["kshell"], aliases: ["kshell"],
@ -1019,9 +1031,10 @@ PLEASE GIVE UP
name: "LiveScript", name: "LiveScript",
repl: "lsc", repl: "lsc",
main: "main.ls", main: "main.ls",
run: "lsc -r ./main.ls; lsc", run: "lsc -r ./main.ls",
template: `console.log "Hello, world!" template: `console.log "Hello, world!"
`, `,
skip: ["repl", "runrepl"],
}, },
llvm: { llvm: {
name: "LLVM", name: "LLVM",
@ -1161,6 +1174,7 @@ message:
run: `rm -rf data && mysqld -h "$PWD/data" --initialize-insecure && (mysqld -h "$PWD/data" --socket="$PWD/socket" --pid-file="$PWD/pid-file" --mysqlx=OFF --skip-networking &) && until [[ -e socket ]]; do sleep 0.01; done && (mysql --socket="$PWD/socket" -u root < main.sql; mysql --socket="$PWD/socket" -u root)`, run: `rm -rf data && mysqld -h "$PWD/data" --initialize-insecure && (mysqld -h "$PWD/data" --socket="$PWD/socket" --pid-file="$PWD/pid-file" --mysqlx=OFF --skip-networking &) && until [[ -e socket ]]; do sleep 0.01; done && (mysql --socket="$PWD/socket" -u root < main.sql; mysql --socket="$PWD/socket" -u root)`,
template: `SELECT 'Hello, world!'; template: `SELECT 'Hello, world!';
`, `,
timeout: 15,
}, },
nim: { nim: {
name: "Nim", name: "Nim",
@ -1348,6 +1362,7 @@ pipi pikachu
run: `rm -rf data && /usr/lib/postgresql/*/bin/initdb -D data && (echo "listen_addresses = ''" && echo "unix_socket_directories = '.'") >> data/postgresql.conf && /usr/lib/postgresql/*/bin/pg_ctl -D data -w start && (psql -h "$PWD/data" postgres -f main.sql; psql -h "$PWD/data" postgres)`, run: `rm -rf data && /usr/lib/postgresql/*/bin/initdb -D data && (echo "listen_addresses = ''" && echo "unix_socket_directories = '.'") >> data/postgresql.conf && /usr/lib/postgresql/*/bin/pg_ctl -D data -w start && (psql -h "$PWD/data" postgres -f main.sql; psql -h "$PWD/data" postgres)`,
template: `SELECT 'Hello, world!'; template: `SELECT 'Hello, world!';
`, `,
timeout: 15,
}, },
powershell: { powershell: {
aliases: ["pwsh", "ps1"], aliases: ["pwsh", "ps1"],
@ -1362,6 +1377,7 @@ pipi pikachu
}, },
template: `Write-Host "Hello, world!" template: `Write-Host "Hello, world!"
`, `,
skip: ["repl", "runrepl"],
}, },
prolog: { prolog: {
name: "Prolog", name: "Prolog",
@ -1404,6 +1420,7 @@ main :: Effect Unit
main = do main = do
log "Hello, world!" log "Hello, world!"
`, `,
timeout: 45,
}, },
python: { python: {
aliases: ["python3", "python2", "py"], aliases: ["python3", "python2", "py"],
@ -1502,6 +1519,7 @@ main = do
"rm -f socket; (redis-server --port 0 --unixsocket socket &); until [[ -e socket ]]; do sleep 0.01; done; redis-cli -s socket < main.redis; redis-cli -s socket", "rm -f socket; (redis-server --port 0 --unixsocket socket &); until [[ -e socket ]]; do sleep 0.01; done; redis-cli -s socket < main.redis; redis-cli -s socket",
template: `ECHO "Hello, world!" template: `ECHO "Hello, world!"
`, `,
skip: ["repl", "runrepl"],
}, },
restructuredtext: { restructuredtext: {
aliases: ["rst"], aliases: ["rst"],
@ -1584,6 +1602,7 @@ binding_irb.run(IRB.conf)
lsp: { start: "solargraph stdio" }, lsp: { start: "solargraph stdio" },
template: `puts "Hello, world!" template: `puts "Hello, world!"
`, `,
skip: ["repl", "runrepl"],
}, },
rust: { rust: {
aliases: ["rs", "rustc"], aliases: ["rs", "rustc"],
@ -1613,6 +1632,7 @@ binding_irb.run(IRB.conf)
run: "scala -i main.scala", run: "scala -i main.scala",
template: `println("Hello, world!") template: `println("Hello, world!")
`, `,
timeout: 30,
}, },
scheme: { scheme: {
aliases: ["scm", "mitscheme"], aliases: ["scm", "mitscheme"],
@ -1769,6 +1789,7 @@ Ophelia:
[Exeunt] [Exeunt]
`, `,
timeout: 15,
}, },
smalltalk: { smalltalk: {
aliases: ["gst", "st"], aliases: ["gst", "st"],
@ -1914,6 +1935,7 @@ a
format: { run: "prettier --no-config main.ts" }, format: { run: "prettier --no-config main.ts" },
template: `console.log("Hello, world!"); template: `console.log("Hello, world!");
`, `,
timeout: 15,
}, },
unlambda: { unlambda: {
aliases: ["unl"], aliases: ["unl"],
@ -1956,6 +1978,7 @@ a
End Sub End Sub
End Module End Module
`, `,
timeout: 15,
}, },
whitespace: { whitespace: {
aliases: ["ws"], aliases: ["ws"],
@ -1981,6 +2004,7 @@ End Module
run: "mathics --persist main.wls", run: "mathics --persist main.wls",
template: `Print["Hello, world!"] template: `Print["Hello, world!"]
`, `,
timeout: 15,
}, },
x86: { x86: {
aliases: ["s", "asm", "assembly", "x86-64"], aliases: ["s", "asm", "assembly", "x86-64"],
@ -2043,6 +2067,7 @@ message:
010011000110110010011101111011011101110000001000011010011110 010011000110110010011101111011011101110000001000011010011110
11000110110001101101010011000010010 11000110110001101101010011000010010
`, `,
timeout: 30,
}, },
zsh: { zsh: {
aliases: ["zshell", "zshrc"], aliases: ["zshell", "zshrc"],

View File

@ -10,8 +10,8 @@ import { v4 as getUUID } from "uuid";
import * as api from "./api"; import * as api from "./api";
import { LangConfig, langs } from "./langs"; import { LangConfig, langs } from "./langs";
const TIMEOUT_MS = 16000; const TIMEOUT_SECS = 5;
const CONCURRENCY = 24; const CONCURRENCY = 16;
function findPosition(str: string, idx: number) { function findPosition(str: string, idx: number) {
const lines = str.substring(0, idx).split("\n"); const lines = str.substring(0, idx).split("\n");
@ -57,6 +57,9 @@ class Test {
}; };
run = async () => { run = async () => {
if ((this.config.skip || []).includes(this.type)) {
return "skipped";
}
let session = null; let session = null;
let timeout = null; let timeout = null;
try { try {
@ -95,7 +98,7 @@ class Test {
timeout = setTimeout(() => { timeout = setTimeout(() => {
this.timedOut = true; this.timedOut = true;
this.handleUpdate(); this.handleUpdate();
}, TIMEOUT_MS); }, (this.config.timeout || TIMEOUT_SECS) * 1000);
await session.setup(); await session.setup();
switch (this.type) { switch (this.type) {
case "ensure": case "ensure":
@ -142,7 +145,7 @@ class Test {
while (this.handledMessages < this.messages.length) { while (this.handledMessages < this.messages.length) {
const msg = this.messages[this.handledMessages]; const msg = this.messages[this.handledMessages];
const result = handler(msg); const result = handler(msg);
if (result) { if (![undefined, null, false].includes(result as any)) {
resolve(result); resolve(result);
} }
this.handledMessages += 1; this.handledMessages += 1;
@ -539,12 +542,12 @@ function lint(lang: string) {
} }
// These can be removed when the types are adjusted to make these // These can be removed when the types are adjusted to make these
// situations impossible. // situations impossible.
if (config.format && !config.format.input) { // if (config.format && !config.format.input) {
throw new Error("formatter is missing test"); // throw new Error("formatter is missing test");
} // }
if (config.lsp && !(config.lsp.code && config.lsp.item)) { // if (config.lsp && !(config.lsp.code && config.lsp.item)) {
throw new Error("LSP is missing test"); // throw new Error("LSP is missing test");
} // }
} }
const testTypes: { const testTypes: {
@ -565,10 +568,10 @@ const testTypes: {
scope: { scope: {
pred: ({ scope }) => (scope ? true : false), pred: ({ scope }) => (scope ? true : false),
}, },
format: { // format: {
pred: ({ format }) => (format ? true : false), // pred: ({ format }) => (format ? true : false),
}, // },
lsp: { pred: ({ lsp }) => (lsp ? true : false) }, // lsp: { pred: ({ lsp }) => (lsp ? true : false) },
}; };
function getTestList() { function getTestList() {
@ -583,9 +586,25 @@ function getTestList() {
return tests; return tests;
} }
async function writeLog(lang: string, type: string, log: string) { async function writeLog(
lang: string,
type: string,
result: string,
log: string
) {
log = `${result.toUpperCase()}: ${lang}/${type}\n` + log;
await promisify(fs.mkdir)(`tests/${lang}`, { recursive: true }); await promisify(fs.mkdir)(`tests/${lang}`, { recursive: true });
await promisify(fs.writeFile)(`tests/${lang}/${type}.log`, log); await promisify(fs.writeFile)(`tests/${lang}/${type}.log`, log);
await promisify(fs.mkdir)(`tests-run/${lang}`, { recursive: true });
await promisify(fs.symlink)(
`../../tests/${lang}/${type}.log`,
`tests-run/${lang}/${type}.log`
);
await promisify(fs.mkdir)(`tests-${result}/${lang}`, { recursive: true });
await promisify(fs.symlink)(
`../../tests/${lang}/${type}.log`,
`tests-${result}/${lang}/${type}.log`
);
} }
async function main() { async function main() {
@ -630,26 +649,35 @@ async function main() {
); );
process.exit(1); process.exit(1);
} }
await promisify(rimraf)("tests"); await promisify(rimraf)("tests-run");
await promisify(rimraf)("tests-passed");
await promisify(rimraf)("tests-skipped");
await promisify(rimraf)("tests-failed");
const queue = new PQueue({ concurrency: CONCURRENCY }); const queue = new PQueue({ concurrency: CONCURRENCY });
let passed = new Set(); let passed = new Set();
let skipped = new Set();
let failed = new Map(); let failed = new Map();
for (const { lang, type } of tests) { for (const { lang, type } of tests) {
queue.add(async () => { queue.add(async () => {
const test = new Test(lang, type); const test = new Test(lang, type);
let err = null; let err;
try { try {
await test.run(); err = await test.run();
} catch (error) { } catch (error) {
err = error; err = error;
} }
if (!err) { if (err === "skipped") {
skipped.add({ lang, type });
console.error(`SKIPPED: ${lang}/${type}`);
await writeLog(lang, type, "skipped", "");
} else if (!err) {
passed.add({ lang, type }); passed.add({ lang, type });
console.error(`PASSED: ${lang}/${type}`); console.error(`PASSED: ${lang}/${type}`);
await writeLog( await writeLog(
lang, lang,
type, type,
`PASSED: ${lang}/${type}\n` + test.getLog({ pretty: true }) + "\n" "passed",
test.getLog({ pretty: true }) + "\n"
); );
} else { } else {
failed.set({ lang, type }, err); failed.set({ lang, type }, err);
@ -659,8 +687,8 @@ async function main() {
await writeLog( await writeLog(
lang, lang,
type, type,
`FAILED: ${lang}/${type}\n` + "failed",
test.getLog({ pretty: true }) + test.getLog({ pretty: true }) +
"\n" + "\n" +
(err.stack ? err.stack + "\n" : err ? `${err}` : "") (err.stack ? err.stack + "\n" : err ? `${err}` : "")
); );
@ -676,6 +704,11 @@ async function main() {
if (passed.size > 0) { if (passed.size > 0) {
console.error(`${passed.size} test${passed.size !== 1 ? "s" : ""} PASSED`); console.error(`${passed.size} test${passed.size !== 1 ? "s" : ""} PASSED`);
} }
if (skipped.size > 0) {
console.error(
`${skipped.size} test${skipped.size !== 1 ? "s" : ""} SKIPPED`
);
}
if (failed.size > 0) { if (failed.size > 0) {
console.error(`${failed.size} test${failed.size !== 1 ? "s" : ""} FAILED`); console.error(`${failed.size} test${failed.size !== 1 ? "s" : ""} FAILED`);
_.sortBy(Array.from(failed), [ _.sortBy(Array.from(failed), [

View File

@ -78,9 +78,9 @@ export async function run(
proc.stderr!.on("data", (data: Buffer) => { proc.stderr!.on("data", (data: Buffer) => {
output += `${data}`; output += `${data}`;
}); });
await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
proc.on("error", reject); proc.on("error", reject);
proc.on("close", (code: number) => { proc.on("close", (code: number, signal: string) => {
output = output.trim(); output = output.trim();
if (output) { if (output) {
log(`Output from ${args[0]}:\n` + output); log(`Output from ${args[0]}:\n` + output);
@ -88,7 +88,7 @@ export async function run(
if (code === 0 || !check) { if (code === 0 || !check) {
resolve(code); resolve(code);
} else { } else {
reject(`command ${args[0]} failed with error code ${code}`); reject(`command ${args[0]} failed with error code ${signal || code}`);
} }
}); });
}); });