2024-07-24 20:26:54 -04:00
|
|
|
#!/usr/bin/env -S deno run --allow-write --allow-read --allow-run --allow-net --config=tests/config/deno.json
|
2024-01-01 14:58:21 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2024-08-20 15:14:37 -04:00
|
|
|
|
|
|
|
// deno-lint-ignore-file no-console
|
|
|
|
|
2023-08-19 00:26:12 -04:00
|
|
|
import { buildMode, getPrebuilt, getSources, join, ROOT_PATH } from "./util.js";
|
2023-01-13 13:42:15 -05:00
|
|
|
import { checkCopyright } from "./copyright_checker.js";
|
2024-03-01 11:11:32 -05:00
|
|
|
import * as ciFile from "../.github/workflows/ci.generate.ts";
|
2023-01-13 13:42:15 -05:00
|
|
|
|
2023-09-26 00:41:07 -04:00
|
|
|
const promises = [];
|
2023-01-13 13:42:15 -05:00
|
|
|
|
2023-09-26 00:41:07 -04:00
|
|
|
let js = Deno.args.includes("--js");
|
|
|
|
let rs = Deno.args.includes("--rs");
|
|
|
|
if (!js && !rs) {
|
|
|
|
js = true;
|
|
|
|
rs = true;
|
2023-01-13 13:42:15 -05:00
|
|
|
}
|
|
|
|
|
2023-09-26 00:41:07 -04:00
|
|
|
if (rs) {
|
|
|
|
promises.push(clippy());
|
|
|
|
}
|
|
|
|
|
2024-03-01 11:11:32 -05:00
|
|
|
if (js) {
|
|
|
|
promises.push(dlint());
|
|
|
|
promises.push(dlintPreferPrimordials());
|
|
|
|
promises.push(ensureCiYmlUpToDate());
|
2024-04-20 17:58:14 -04:00
|
|
|
promises.push(ensureNoNewITests());
|
2024-03-01 11:11:32 -05:00
|
|
|
|
|
|
|
if (rs) {
|
|
|
|
promises.push(checkCopyright());
|
|
|
|
}
|
2023-09-26 00:41:07 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
const results = await Promise.allSettled(promises);
|
|
|
|
for (const result of results) {
|
|
|
|
if (result.status === "rejected") {
|
|
|
|
console.error(result.reason);
|
|
|
|
Deno.exit(1);
|
|
|
|
}
|
2023-01-13 13:42:15 -05:00
|
|
|
}
|
2020-11-05 09:53:21 -05:00
|
|
|
|
|
|
|
async function dlint() {
|
2021-01-16 18:32:59 -05:00
|
|
|
const configFile = join(ROOT_PATH, ".dlint.json");
|
2023-08-19 00:26:12 -04:00
|
|
|
const execPath = await getPrebuilt("dlint");
|
2020-11-05 09:53:21 -05:00
|
|
|
|
|
|
|
const sourceFiles = await getSources(ROOT_PATH, [
|
|
|
|
"*.js",
|
|
|
|
"*.ts",
|
2021-04-10 02:46:27 -04:00
|
|
|
":!:.github/mtime_cache/action.js",
|
2022-08-19 06:24:54 -04:00
|
|
|
":!:cli/bench/testdata/npm/*",
|
2022-01-18 06:58:50 -05:00
|
|
|
":!:cli/bench/testdata/express-router.js",
|
2022-08-18 08:05:02 -04:00
|
|
|
":!:cli/bench/testdata/react-dom.js",
|
2020-11-05 09:53:21 -05:00
|
|
|
":!:cli/compilers/wasm_wrap.js",
|
2022-11-25 18:29:48 -05:00
|
|
|
":!:cli/tsc/dts/**",
|
2024-08-20 15:14:37 -04:00
|
|
|
":!:cli/tsc/*typescript.js",
|
|
|
|
":!:cli/tsc/compiler.d.ts",
|
|
|
|
":!:runtime/examples/",
|
2024-05-03 16:44:41 -04:00
|
|
|
":!:target/",
|
2024-05-06 21:06:01 -04:00
|
|
|
":!:tests/registry/**",
|
2024-03-13 22:37:56 -04:00
|
|
|
":!:tests/specs/**",
|
2024-08-20 15:14:37 -04:00
|
|
|
":!:tests/testdata/**",
|
|
|
|
":!:tests/unit_node/testdata/**",
|
2024-02-15 22:32:28 -05:00
|
|
|
":!:tests/wpt/suite/**",
|
2024-06-04 19:09:29 -04:00
|
|
|
":!:tests/wpt/runner/**",
|
2020-11-05 09:53:21 -05:00
|
|
|
]);
|
|
|
|
|
|
|
|
if (!sourceFiles.length) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2021-08-19 19:14:20 -04:00
|
|
|
const chunks = splitToChunks(sourceFiles, `${execPath} run`.length);
|
2023-03-15 22:39:40 -04:00
|
|
|
const pending = [];
|
2020-11-05 09:53:21 -05:00
|
|
|
for (const chunk of chunks) {
|
2022-12-01 10:51:47 -05:00
|
|
|
const cmd = new Deno.Command(execPath, {
|
2023-01-13 13:42:15 -05:00
|
|
|
cwd: ROOT_PATH,
|
2022-05-18 16:00:11 -04:00
|
|
|
args: ["run", "--config=" + configFile, ...chunk],
|
2023-03-15 22:39:40 -04:00
|
|
|
// capture to not conflict with clippy output
|
|
|
|
stderr: "piped",
|
2020-11-05 09:53:21 -05:00
|
|
|
});
|
2023-03-15 22:39:40 -04:00
|
|
|
pending.push(
|
|
|
|
cmd.output().then(({ stderr, code }) => {
|
|
|
|
if (code > 0) {
|
|
|
|
const decoder = new TextDecoder();
|
|
|
|
console.log("\n------ dlint ------");
|
|
|
|
console.log(decoder.decode(stderr));
|
|
|
|
throw new Error("dlint failed");
|
|
|
|
}
|
|
|
|
}),
|
|
|
|
);
|
2020-11-05 09:53:21 -05:00
|
|
|
}
|
2024-08-30 17:18:47 -04:00
|
|
|
const results = await Promise.allSettled(pending);
|
|
|
|
for (const result of results) {
|
|
|
|
if (result.status === "rejected") {
|
|
|
|
throw new Error(result.reason);
|
|
|
|
}
|
|
|
|
}
|
2020-11-05 09:53:21 -05:00
|
|
|
}
|
|
|
|
|
2021-08-19 19:14:20 -04:00
|
|
|
// `prefer-primordials` has to apply only to files related to bootstrapping,
|
|
|
|
// which is different from other lint rules. This is why this dedicated function
|
|
|
|
// is needed.
|
|
|
|
async function dlintPreferPrimordials() {
|
2023-08-19 00:26:12 -04:00
|
|
|
const execPath = await getPrebuilt("dlint");
|
2021-08-19 19:14:20 -04:00
|
|
|
const sourceFiles = await getSources(ROOT_PATH, [
|
|
|
|
"runtime/**/*.js",
|
2024-01-07 17:20:02 -05:00
|
|
|
"runtime/**/*.ts",
|
2021-08-19 19:14:20 -04:00
|
|
|
"ext/**/*.js",
|
2024-01-07 17:20:02 -05:00
|
|
|
"ext/**/*.ts",
|
|
|
|
":!:ext/**/*.d.ts",
|
2023-06-27 02:18:22 -04:00
|
|
|
"ext/node/polyfills/*.mjs",
|
2021-08-19 19:14:20 -04:00
|
|
|
]);
|
|
|
|
|
|
|
|
if (!sourceFiles.length) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
const chunks = splitToChunks(sourceFiles, `${execPath} run`.length);
|
|
|
|
for (const chunk of chunks) {
|
2022-12-01 10:51:47 -05:00
|
|
|
const cmd = new Deno.Command(execPath, {
|
2023-01-13 13:42:15 -05:00
|
|
|
cwd: ROOT_PATH,
|
2022-05-18 16:00:11 -04:00
|
|
|
args: ["run", "--rule", "prefer-primordials", ...chunk],
|
|
|
|
stdout: "inherit",
|
|
|
|
stderr: "inherit",
|
2021-08-19 19:14:20 -04:00
|
|
|
});
|
2022-12-01 10:51:47 -05:00
|
|
|
const { code } = await cmd.output();
|
|
|
|
|
|
|
|
if (code > 0) {
|
2021-08-19 19:14:20 -04:00
|
|
|
throw new Error("prefer-primordials failed");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function splitToChunks(paths, initCmdLen) {
|
|
|
|
let cmdLen = initCmdLen;
|
|
|
|
const MAX_COMMAND_LEN = 30000;
|
|
|
|
const chunks = [[]];
|
|
|
|
for (const p of paths) {
|
|
|
|
if (cmdLen + p.length > MAX_COMMAND_LEN) {
|
|
|
|
chunks.push([p]);
|
|
|
|
cmdLen = initCmdLen;
|
|
|
|
} else {
|
|
|
|
chunks[chunks.length - 1].push(p);
|
|
|
|
cmdLen += p.length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return chunks;
|
|
|
|
}
|
|
|
|
|
2020-11-05 09:53:21 -05:00
|
|
|
async function clippy() {
|
|
|
|
const currentBuildMode = buildMode();
|
2023-03-10 07:07:28 -05:00
|
|
|
const cmd = ["clippy", "--all-targets", "--all-features", "--locked"];
|
2020-11-05 09:53:21 -05:00
|
|
|
|
|
|
|
if (currentBuildMode != "debug") {
|
|
|
|
cmd.push("--release");
|
|
|
|
}
|
|
|
|
|
2022-12-01 10:51:47 -05:00
|
|
|
const cargoCmd = new Deno.Command("cargo", {
|
2023-01-13 13:42:15 -05:00
|
|
|
cwd: ROOT_PATH,
|
2022-11-10 06:53:31 -05:00
|
|
|
args: [
|
|
|
|
...cmd,
|
|
|
|
"--",
|
|
|
|
"-D",
|
|
|
|
"warnings",
|
2024-03-11 23:48:00 -04:00
|
|
|
"--deny",
|
|
|
|
"clippy::unused_async",
|
2024-05-08 22:45:06 -04:00
|
|
|
// generally prefer the `log` crate, but ignore
|
|
|
|
// these print_* rules if necessary
|
|
|
|
"--deny",
|
|
|
|
"clippy::print_stderr",
|
|
|
|
"--deny",
|
|
|
|
"clippy::print_stdout",
|
2022-11-10 06:53:31 -05:00
|
|
|
],
|
2022-05-18 16:00:11 -04:00
|
|
|
stdout: "inherit",
|
|
|
|
stderr: "inherit",
|
2020-11-05 09:53:21 -05:00
|
|
|
});
|
2022-12-01 10:51:47 -05:00
|
|
|
const { code } = await cargoCmd.output();
|
|
|
|
|
|
|
|
if (code > 0) {
|
2020-11-05 09:53:21 -05:00
|
|
|
throw new Error("clippy failed");
|
|
|
|
}
|
|
|
|
}
|
2024-03-01 11:11:32 -05:00
|
|
|
|
|
|
|
async function ensureCiYmlUpToDate() {
|
|
|
|
const expectedCiFileText = ciFile.generate();
|
|
|
|
const actualCiFileText = await Deno.readTextFile(ciFile.CI_YML_URL);
|
|
|
|
if (expectedCiFileText !== actualCiFileText) {
|
|
|
|
throw new Error(
|
|
|
|
"./.github/workflows/ci.yml is out of date. Run: ./.github/workflows/ci.generate.ts",
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
2024-04-20 17:58:14 -04:00
|
|
|
|
|
|
|
async function ensureNoNewITests() {
|
|
|
|
// Note: Only decrease these numbers. Never increase them!!
|
|
|
|
// This is to help ensure we slowly deprecate these tests and
|
|
|
|
// replace them with spec tests.
|
|
|
|
const iTestCounts = {
|
2024-04-29 10:08:27 -04:00
|
|
|
"bench_tests.rs": 0,
|
2024-05-28 14:58:43 -04:00
|
|
|
"bundle_tests.rs": 11,
|
2024-04-29 10:08:27 -04:00
|
|
|
"cache_tests.rs": 0,
|
2024-05-02 20:43:12 -04:00
|
|
|
"cert_tests.rs": 0,
|
2024-04-29 10:08:27 -04:00
|
|
|
"check_tests.rs": 23,
|
2024-04-20 17:58:14 -04:00
|
|
|
"compile_tests.rs": 0,
|
|
|
|
"coverage_tests.rs": 0,
|
2024-04-29 10:08:27 -04:00
|
|
|
"doc_tests.rs": 15,
|
2024-04-20 17:58:14 -04:00
|
|
|
"eval_tests.rs": 9,
|
|
|
|
"flags_tests.rs": 0,
|
|
|
|
"fmt_tests.rs": 17,
|
2024-04-29 10:08:27 -04:00
|
|
|
"info_tests.rs": 18,
|
2024-04-20 17:58:14 -04:00
|
|
|
"init_tests.rs": 0,
|
|
|
|
"inspector_tests.rs": 0,
|
|
|
|
"install_tests.rs": 0,
|
|
|
|
"jsr_tests.rs": 0,
|
|
|
|
"js_unit_tests.rs": 0,
|
|
|
|
"jupyter_tests.rs": 0,
|
2024-04-29 10:08:27 -04:00
|
|
|
"lint_tests.rs": 18,
|
|
|
|
// Read the comment above. Please don't increase these numbers!
|
2024-04-20 17:58:14 -04:00
|
|
|
"lsp_tests.rs": 0,
|
|
|
|
"node_compat_tests.rs": 4,
|
2024-05-14 19:51:51 -04:00
|
|
|
"node_unit_tests.rs": 2,
|
2024-08-28 14:17:47 -04:00
|
|
|
"npm_tests.rs": 92,
|
2024-04-20 17:58:14 -04:00
|
|
|
"pm_tests.rs": 0,
|
2024-04-29 10:08:27 -04:00
|
|
|
"publish_tests.rs": 0,
|
2024-04-20 17:58:14 -04:00
|
|
|
"repl_tests.rs": 0,
|
2024-05-28 14:58:43 -04:00
|
|
|
"run_tests.rs": 360,
|
2024-04-20 17:58:14 -04:00
|
|
|
"shared_library_tests.rs": 0,
|
|
|
|
"task_tests.rs": 30,
|
2024-04-29 10:08:27 -04:00
|
|
|
"test_tests.rs": 77,
|
2024-04-20 17:58:14 -04:00
|
|
|
"upgrade_tests.rs": 0,
|
|
|
|
"vendor_tests.rs": 1,
|
|
|
|
"watcher_tests.rs": 0,
|
2024-05-03 01:52:47 -04:00
|
|
|
"worker_tests.rs": 18,
|
2024-04-20 17:58:14 -04:00
|
|
|
};
|
|
|
|
const integrationDir = join(ROOT_PATH, "tests", "integration");
|
|
|
|
for await (const entry of Deno.readDir(integrationDir)) {
|
|
|
|
if (!entry.name.endsWith("_tests.rs")) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
const fileText = await Deno.readTextFile(join(integrationDir, entry.name));
|
|
|
|
const actualCount = fileText.match(/itest\!/g)?.length ?? 0;
|
|
|
|
const expectedCount = iTestCounts[entry.name] ?? 0;
|
|
|
|
// console.log(`"${entry.name}": ${actualCount},`);
|
|
|
|
if (actualCount > expectedCount) {
|
|
|
|
throw new Error(
|
2024-04-29 10:08:27 -04:00
|
|
|
`New itest added to ${entry.name}! The itest macro is deprecated. Please move your new test to ~/tests/specs.`,
|
2024-04-20 17:58:14 -04:00
|
|
|
);
|
|
|
|
} else if (actualCount < expectedCount) {
|
|
|
|
throw new Error(
|
|
|
|
`Thanks for removing an itest in ${entry.name}. ` +
|
|
|
|
`Please update the count in tools/lint.js for this file to ${actualCount}.`,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|