@descryy/runtime-test-runner 0.4.11 → 0.4.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bounded-file.d.ts +18 -0
- package/dist/bounded-file.d.ts.map +1 -0
- package/dist/bounded-file.js +77 -0
- package/dist/bounded-file.js.map +1 -0
- package/dist/child-environment.d.ts +12 -0
- package/dist/child-environment.d.ts.map +1 -0
- package/dist/child-environment.js +124 -0
- package/dist/child-environment.js.map +1 -0
- package/dist/coverage-capture.d.ts +23 -0
- package/dist/coverage-capture.d.ts.map +1 -0
- package/dist/coverage-capture.js +165 -0
- package/dist/coverage-capture.js.map +1 -0
- package/dist/executed-coverage.d.ts +45 -0
- package/dist/executed-coverage.d.ts.map +1 -0
- package/dist/executed-coverage.js +143 -0
- package/dist/executed-coverage.js.map +1 -0
- package/dist/go-cover-profile.d.ts +29 -0
- package/dist/go-cover-profile.d.ts.map +1 -0
- package/dist/go-cover-profile.js +162 -0
- package/dist/go-cover-profile.js.map +1 -0
- package/dist/go-test.d.ts +29 -2
- package/dist/go-test.d.ts.map +1 -1
- package/dist/go-test.js +149 -30
- package/dist/go-test.js.map +1 -1
- package/dist/graph-mapping.d.ts +1 -0
- package/dist/graph-mapping.d.ts.map +1 -1
- package/dist/graph-mapping.js +78 -1
- package/dist/graph-mapping.js.map +1 -1
- package/dist/index.d.ts +21 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/lexers/c-family.d.ts +4 -0
- package/dist/lexers/c-family.d.ts.map +1 -0
- package/dist/lexers/c-family.js +221 -0
- package/dist/lexers/c-family.js.map +1 -0
- package/dist/lexers/chars.d.ts +7 -0
- package/dist/lexers/chars.d.ts.map +1 -0
- package/dist/lexers/chars.js +49 -0
- package/dist/lexers/chars.js.map +1 -0
- package/dist/lexers/index.d.ts +7 -0
- package/dist/lexers/index.d.ts.map +1 -0
- package/dist/lexers/index.js +5 -0
- package/dist/lexers/index.js.map +1 -0
- package/dist/lexers/python.d.ts +3 -0
- package/dist/lexers/python.d.ts.map +1 -0
- package/dist/lexers/python.js +101 -0
- package/dist/lexers/python.js.map +1 -0
- package/dist/quality/annotations.d.ts +14 -0
- package/dist/quality/annotations.d.ts.map +1 -0
- package/dist/quality/annotations.js +147 -0
- package/dist/quality/annotations.js.map +1 -0
- package/dist/quality/assertion-kinds.d.ts +18 -0
- package/dist/quality/assertion-kinds.d.ts.map +1 -0
- package/dist/quality/assertion-kinds.js +25 -0
- package/dist/quality/assertion-kinds.js.map +1 -0
- package/dist/quality/chains.d.ts +25 -0
- package/dist/quality/chains.d.ts.map +1 -0
- package/dist/quality/chains.js +129 -0
- package/dist/quality/chains.js.map +1 -0
- package/dist/quality/common.d.ts +31 -0
- package/dist/quality/common.d.ts.map +1 -0
- package/dist/quality/common.js +211 -0
- package/dist/quality/common.js.map +1 -0
- package/dist/quality/csharp-family.d.ts +9 -0
- package/dist/quality/csharp-family.d.ts.map +1 -0
- package/dist/quality/csharp-family.js +560 -0
- package/dist/quality/csharp-family.js.map +1 -0
- package/dist/quality/detect.d.ts +3 -0
- package/dist/quality/detect.d.ts.map +1 -0
- package/dist/quality/detect.js +348 -0
- package/dist/quality/detect.js.map +1 -0
- package/dist/quality/durations.d.ts +4 -0
- package/dist/quality/durations.d.ts.map +1 -0
- package/dist/quality/durations.js +177 -0
- package/dist/quality/durations.js.map +1 -0
- package/dist/quality/expressions.d.ts +7 -0
- package/dist/quality/expressions.d.ts.map +1 -0
- package/dist/quality/expressions.js +123 -0
- package/dist/quality/expressions.js.map +1 -0
- package/dist/quality/facts.d.ts +5 -0
- package/dist/quality/facts.d.ts.map +1 -0
- package/dist/quality/facts.js +183 -0
- package/dist/quality/facts.js.map +1 -0
- package/dist/quality/failure-of.d.ts +4 -0
- package/dist/quality/failure-of.d.ts.map +1 -0
- package/dist/quality/failure-of.js +233 -0
- package/dist/quality/failure-of.js.map +1 -0
- package/dist/quality/frameworks.d.ts +5 -0
- package/dist/quality/frameworks.d.ts.map +1 -0
- package/dist/quality/frameworks.js +20 -0
- package/dist/quality/frameworks.js.map +1 -0
- package/dist/quality/go-family.d.ts +6 -0
- package/dist/quality/go-family.d.ts.map +1 -0
- package/dist/quality/go-family.js +393 -0
- package/dist/quality/go-family.js.map +1 -0
- package/dist/quality/index.d.ts +10 -0
- package/dist/quality/index.d.ts.map +1 -0
- package/dist/quality/index.js +19 -0
- package/dist/quality/index.js.map +1 -0
- package/dist/quality/java-family.d.ts +12 -0
- package/dist/quality/java-family.d.ts.map +1 -0
- package/dist/quality/java-family.js +529 -0
- package/dist/quality/java-family.js.map +1 -0
- package/dist/quality/js-assertions.d.ts +11 -0
- package/dist/quality/js-assertions.d.ts.map +1 -0
- package/dist/quality/js-assertions.js +297 -0
- package/dist/quality/js-assertions.js.map +1 -0
- package/dist/quality/js-family.d.ts +3 -0
- package/dist/quality/js-family.d.ts.map +1 -0
- package/dist/quality/js-family.js +470 -0
- package/dist/quality/js-family.js.map +1 -0
- package/dist/quality/python-family.d.ts +6 -0
- package/dist/quality/python-family.d.ts.map +1 -0
- package/dist/quality/python-family.js +786 -0
- package/dist/quality/python-family.js.map +1 -0
- package/dist/quality/scope.d.ts +26 -0
- package/dist/quality/scope.d.ts.map +1 -0
- package/dist/quality/scope.js +33 -0
- package/dist/quality/scope.js.map +1 -0
- package/dist/quality/selectors.d.ts +14 -0
- package/dist/quality/selectors.d.ts.map +1 -0
- package/dist/quality/selectors.js +137 -0
- package/dist/quality/selectors.js.map +1 -0
- package/dist/quality/statuses.d.ts +7 -0
- package/dist/quality/statuses.d.ts.map +1 -0
- package/dist/quality/statuses.js +143 -0
- package/dist/quality/statuses.js.map +1 -0
- package/dist/quality/stream.d.ts +23 -0
- package/dist/quality/stream.d.ts.map +1 -0
- package/dist/quality/stream.js +194 -0
- package/dist/quality/stream.js.map +1 -0
- package/dist/quality/types.d.ts +88 -0
- package/dist/quality/types.d.ts.map +1 -0
- package/dist/quality/types.js +2 -0
- package/dist/quality/types.js.map +1 -0
- package/dist/run-timeout.d.ts +25 -0
- package/dist/run-timeout.d.ts.map +1 -0
- package/dist/run-timeout.js +52 -0
- package/dist/run-timeout.js.map +1 -0
- package/dist/runner-wrappers.d.ts +74 -0
- package/dist/runner-wrappers.d.ts.map +1 -0
- package/dist/runner-wrappers.js +604 -0
- package/dist/runner-wrappers.js.map +1 -0
- package/dist/swift-xctest.d.ts +15 -2
- package/dist/swift-xctest.d.ts.map +1 -1
- package/dist/swift-xctest.js +143 -20
- package/dist/swift-xctest.js.map +1 -1
- package/dist/test-runner-collector.d.ts +56 -6
- package/dist/test-runner-collector.d.ts.map +1 -1
- package/dist/test-runner-collector.js +265 -113
- package/dist/test-runner-collector.js.map +1 -1
- package/dist/testgen/csharp-facts.d.ts +3 -0
- package/dist/testgen/csharp-facts.d.ts.map +1 -0
- package/dist/testgen/csharp-facts.js +306 -0
- package/dist/testgen/csharp-facts.js.map +1 -0
- package/dist/testgen/csharp-profile.d.ts +14 -0
- package/dist/testgen/csharp-profile.d.ts.map +1 -0
- package/dist/testgen/csharp-profile.js +233 -0
- package/dist/testgen/csharp-profile.js.map +1 -0
- package/dist/testgen/declarations.d.ts +10 -0
- package/dist/testgen/declarations.d.ts.map +1 -0
- package/dist/testgen/declarations.js +110 -0
- package/dist/testgen/declarations.js.map +1 -0
- package/dist/testgen/facts-common.d.ts +33 -0
- package/dist/testgen/facts-common.d.ts.map +1 -0
- package/dist/testgen/facts-common.js +76 -0
- package/dist/testgen/facts-common.js.map +1 -0
- package/dist/testgen/failure.d.ts +4 -0
- package/dist/testgen/failure.d.ts.map +1 -0
- package/dist/testgen/failure.js +106 -0
- package/dist/testgen/failure.js.map +1 -0
- package/dist/testgen/frameworks.d.ts +6 -0
- package/dist/testgen/frameworks.d.ts.map +1 -0
- package/dist/testgen/frameworks.js +516 -0
- package/dist/testgen/frameworks.js.map +1 -0
- package/dist/testgen/go-facts.d.ts +11 -0
- package/dist/testgen/go-facts.d.ts.map +1 -0
- package/dist/testgen/go-facts.js +237 -0
- package/dist/testgen/go-facts.js.map +1 -0
- package/dist/testgen/go-profile.d.ts +6 -0
- package/dist/testgen/go-profile.d.ts.map +1 -0
- package/dist/testgen/go-profile.js +155 -0
- package/dist/testgen/go-profile.js.map +1 -0
- package/dist/testgen/index.d.ts +28 -0
- package/dist/testgen/index.d.ts.map +1 -0
- package/dist/testgen/index.js +21 -0
- package/dist/testgen/index.js.map +1 -0
- package/dist/testgen/java-build.d.ts +13 -0
- package/dist/testgen/java-build.d.ts.map +1 -0
- package/dist/testgen/java-build.js +250 -0
- package/dist/testgen/java-build.js.map +1 -0
- package/dist/testgen/java-facts.d.ts +3 -0
- package/dist/testgen/java-facts.d.ts.map +1 -0
- package/dist/testgen/java-facts.js +349 -0
- package/dist/testgen/java-facts.js.map +1 -0
- package/dist/testgen/java-profile.d.ts +13 -0
- package/dist/testgen/java-profile.d.ts.map +1 -0
- package/dist/testgen/java-profile.js +194 -0
- package/dist/testgen/java-profile.js.map +1 -0
- package/dist/testgen/languages.d.ts +11 -0
- package/dist/testgen/languages.d.ts.map +1 -0
- package/dist/testgen/languages.js +63 -0
- package/dist/testgen/languages.js.map +1 -0
- package/dist/testgen/lexer.d.ts +19 -0
- package/dist/testgen/lexer.d.ts.map +1 -0
- package/dist/testgen/lexer.js +257 -0
- package/dist/testgen/lexer.js.map +1 -0
- package/dist/testgen/mutant-core.d.ts +19 -0
- package/dist/testgen/mutant-core.d.ts.map +1 -0
- package/dist/testgen/mutant-core.js +39 -0
- package/dist/testgen/mutant-core.js.map +1 -0
- package/dist/testgen/mutants-lang.d.ts +6 -0
- package/dist/testgen/mutants-lang.d.ts.map +1 -0
- package/dist/testgen/mutants-lang.js +291 -0
- package/dist/testgen/mutants-lang.js.map +1 -0
- package/dist/testgen/mutants.d.ts +9 -0
- package/dist/testgen/mutants.d.ts.map +1 -0
- package/dist/testgen/mutants.js +148 -0
- package/dist/testgen/mutants.js.map +1 -0
- package/dist/testgen/paths.d.ts +32 -0
- package/dist/testgen/paths.d.ts.map +1 -0
- package/dist/testgen/paths.js +211 -0
- package/dist/testgen/paths.js.map +1 -0
- package/dist/testgen/process.d.ts +19 -0
- package/dist/testgen/process.d.ts.map +1 -0
- package/dist/testgen/process.js +89 -0
- package/dist/testgen/process.js.map +1 -0
- package/dist/testgen/profile-failure.d.ts +7 -0
- package/dist/testgen/profile-failure.d.ts.map +1 -0
- package/dist/testgen/profile-failure.js +29 -0
- package/dist/testgen/profile-failure.js.map +1 -0
- package/dist/testgen/python-facts.d.ts +11 -0
- package/dist/testgen/python-facts.d.ts.map +1 -0
- package/dist/testgen/python-facts.js +380 -0
- package/dist/testgen/python-facts.js.map +1 -0
- package/dist/testgen/python-profile.d.ts +4 -0
- package/dist/testgen/python-profile.d.ts.map +1 -0
- package/dist/testgen/python-profile.js +344 -0
- package/dist/testgen/python-profile.js.map +1 -0
- package/dist/testgen/source-facts.d.ts +30 -0
- package/dist/testgen/source-facts.d.ts.map +1 -0
- package/dist/testgen/source-facts.js +497 -0
- package/dist/testgen/source-facts.js.map +1 -0
- package/dist/testgen/stubs.d.ts +4 -0
- package/dist/testgen/stubs.d.ts.map +1 -0
- package/dist/testgen/stubs.js +66 -0
- package/dist/testgen/stubs.js.map +1 -0
- package/dist/testgen/toolchain.d.ts +23 -0
- package/dist/testgen/toolchain.d.ts.map +1 -0
- package/dist/testgen/toolchain.js +201 -0
- package/dist/testgen/toolchain.js.map +1 -0
- package/dist/testgen/types.d.ts +67 -0
- package/dist/testgen/types.d.ts.map +1 -0
- package/dist/testgen/types.js +2 -0
- package/dist/testgen/types.js.map +1 -0
- package/dist/v8-coverage.d.ts +21 -0
- package/dist/v8-coverage.d.ts.map +1 -0
- package/dist/v8-coverage.js +217 -0
- package/dist/v8-coverage.js.map +1 -0
- package/dist/vitest-reporter.d.ts +46 -13
- package/dist/vitest-reporter.d.ts.map +1 -1
- package/dist/vitest-reporter.js +119 -26
- package/dist/vitest-reporter.js.map +1 -1
- package/dist/vitest-version.d.ts +21 -0
- package/dist/vitest-version.d.ts.map +1 -0
- package/dist/vitest-version.js +98 -0
- package/dist/vitest-version.js.map +1 -0
- package/package.json +14 -8
- package/reporters/junit/classes/DescryJUnitListener.class +0 -0
- package/reporters/junit/classes/META-INF/services/org.junit.platform.launcher.TestExecutionListener +1 -0
- package/reporters/minitest/descry_minitest_reporter.rb +150 -0
- package/reporters/phpunit/DescryPhpUnitExtension.php +209 -0
- package/reporters/pytest/descry_pytest_plugin.py +397 -0
- package/reporters/rspec/descry_rspec_formatter.rb +175 -0
- package/reporters/xunit/bin/Release/netstandard2.0/Descry.TestLogger.deps.json +203 -0
- package/reporters/xunit/bin/Release/netstandard2.0/Descry.TestLogger.dll +0 -0
- package/reporters/xunit/bin/Release/netstandard2.0/Descry.TestLogger.pdb +0 -0
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { spawnSync } from "node:child_process";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { existsSync, mkdirSync, readFileSync, rmSync } from "node:fs";
|
|
4
|
+
import { mkdir, readdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
5
|
+
import { delimiter, join } from "node:path";
|
|
6
|
+
import { tokenizeCFamily } from "../lexers/c-family.js";
|
|
7
|
+
import { withoutComments } from "./facts-common.js";
|
|
8
|
+
import { entriesOf, isInside, mapToWork, quote } from "./paths.js";
|
|
9
|
+
import { runBounded, timeoutFrom } from "./process.js";
|
|
10
|
+
export const MAIN_SOURCE_ROOT = "src/main/java/";
|
|
11
|
+
const DEFAULT_COMPILE_TIMEOUT_MS = 120_000;
|
|
12
|
+
const DIAGNOSTIC_LIMIT = 2048;
|
|
13
|
+
const SOURCE_LIMIT = 20_000;
|
|
14
|
+
const BUILD_DIRECTORY = ".descry-testgen";
|
|
15
|
+
const MARKER_NAME = "java-prepared.json";
|
|
16
|
+
export function packageOf(source) {
|
|
17
|
+
const tokens = withoutComments(tokenizeCFamily(source, "java"));
|
|
18
|
+
const index = tokens.findIndex((token) => token.kind === "identifier" && token.text === "package");
|
|
19
|
+
if (index === -1)
|
|
20
|
+
return "";
|
|
21
|
+
const parts = [];
|
|
22
|
+
for (let cursor = index + 1; cursor < tokens.length && tokens[cursor].text !== ";"; cursor += 1) {
|
|
23
|
+
if (tokens[cursor].kind === "identifier")
|
|
24
|
+
parts.push(tokens[cursor].text);
|
|
25
|
+
}
|
|
26
|
+
return parts.join(".");
|
|
27
|
+
}
|
|
28
|
+
function topLevelTypeOf(source) {
|
|
29
|
+
const tokens = withoutComments(tokenizeCFamily(source, "java"));
|
|
30
|
+
let depth = 0;
|
|
31
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
32
|
+
const token = tokens[i];
|
|
33
|
+
if (token.text === "{")
|
|
34
|
+
depth += 1;
|
|
35
|
+
else if (token.text === "}")
|
|
36
|
+
depth -= 1;
|
|
37
|
+
else if (depth === 0 && token.kind === "identifier" && (token.text === "class" || token.text === "record" || token.text === "enum") && tokens[i + 1]?.kind === "identifier" && tokens[i - 1]?.text !== ".") {
|
|
38
|
+
return tokens[i + 1].text;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
function listJavaSources(directory, found = []) {
|
|
44
|
+
for (const name of entriesOf(directory)) {
|
|
45
|
+
if (found.length >= SOURCE_LIMIT)
|
|
46
|
+
break;
|
|
47
|
+
const path = join(directory, name);
|
|
48
|
+
if (name.endsWith(".java"))
|
|
49
|
+
found.push(path);
|
|
50
|
+
else if (!name.includes("."))
|
|
51
|
+
listJavaSources(path, found);
|
|
52
|
+
}
|
|
53
|
+
return found;
|
|
54
|
+
}
|
|
55
|
+
async function listJavaSourcesAsync(directory, signal, found = []) {
|
|
56
|
+
let names;
|
|
57
|
+
try {
|
|
58
|
+
names = await readdir(directory);
|
|
59
|
+
}
|
|
60
|
+
catch {
|
|
61
|
+
return found;
|
|
62
|
+
}
|
|
63
|
+
for (const name of names) {
|
|
64
|
+
if (found.length >= SOURCE_LIMIT || signal.aborted)
|
|
65
|
+
break;
|
|
66
|
+
const path = join(directory, name);
|
|
67
|
+
if (name.endsWith(".java"))
|
|
68
|
+
found.push(path);
|
|
69
|
+
else if (!name.includes("."))
|
|
70
|
+
await listJavaSourcesAsync(path, signal, found);
|
|
71
|
+
}
|
|
72
|
+
return found;
|
|
73
|
+
}
|
|
74
|
+
export function jarsIn(directory) {
|
|
75
|
+
return entriesOf(directory)
|
|
76
|
+
.filter((name) => name.endsWith(".jar"))
|
|
77
|
+
.sort()
|
|
78
|
+
.map((name) => join(directory, name));
|
|
79
|
+
}
|
|
80
|
+
function inWork(path, request) {
|
|
81
|
+
const mapped = mapToWork(path, request.repoRoot, request.workRoot);
|
|
82
|
+
return existsSync(mapped) ? mapped : path;
|
|
83
|
+
}
|
|
84
|
+
function planOf(request, context) {
|
|
85
|
+
const java = context.toolchain.locate("java");
|
|
86
|
+
const javac = context.toolchain.locate("javac");
|
|
87
|
+
const launcher = context.toolchain.junitLauncher();
|
|
88
|
+
if (java === null || javac === null)
|
|
89
|
+
return { ok: false, reason: "java and javac were not found, and the test has to be compiled before it runs." };
|
|
90
|
+
if (launcher === null)
|
|
91
|
+
return { ok: false, reason: "No JUnit Platform Console Launcher jar was found." };
|
|
92
|
+
if (!isInside(context.moduleRoot, request.testFile))
|
|
93
|
+
return { ok: false, reason: `${request.testFile} is outside ${context.moduleRoot}, the module the tests run in.` };
|
|
94
|
+
const type = topLevelTypeOf(request.testSource);
|
|
95
|
+
if (type === null)
|
|
96
|
+
return { ok: false, reason: "The test source declares no class, so there is nothing for the launcher to select." };
|
|
97
|
+
const pkg = packageOf(request.testSource);
|
|
98
|
+
if (isInside(request.repoRoot, request.workRoot)) {
|
|
99
|
+
return { ok: false, reason: `The work root ${request.workRoot} is inside the repository ${request.repoRoot}, and compiled classes are never written into the repository.` };
|
|
100
|
+
}
|
|
101
|
+
const buildDirectory = join(request.workRoot, BUILD_DIRECTORY);
|
|
102
|
+
const compiledTests = inWork(join(context.moduleRoot, "target", "test-classes"), request);
|
|
103
|
+
return {
|
|
104
|
+
ok: true,
|
|
105
|
+
plan: {
|
|
106
|
+
java,
|
|
107
|
+
javac,
|
|
108
|
+
launcher,
|
|
109
|
+
qualified: pkg === "" ? type : `${pkg}.${type}`,
|
|
110
|
+
workModule: mapToWork(context.moduleRoot, request.repoRoot, request.workRoot),
|
|
111
|
+
workTestSource: mapToWork(request.testFile, request.repoRoot, request.workRoot),
|
|
112
|
+
classes: join(buildDirectory, "java-classes"),
|
|
113
|
+
markerPath: join(buildDirectory, MARKER_NAME),
|
|
114
|
+
digest: createHash("sha256").update(request.testSource).digest("hex"),
|
|
115
|
+
jars: context.dependencyJars().map((jar) => inWork(jar, request)),
|
|
116
|
+
compiledTests: existsSync(compiledTests) ? compiledTests : null,
|
|
117
|
+
},
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
function javacArguments(plan, mainSources, request) {
|
|
121
|
+
const compilePath = [plan.launcher, ...plan.jars, ...(plan.compiledTests === null ? [] : [plan.compiledTests])].join(delimiter);
|
|
122
|
+
const workMain = mainSources.map((path) => mapToWork(path, request.repoRoot, request.workRoot)).sort();
|
|
123
|
+
return ["-proc:none", "-nowarn", "-encoding", "UTF-8", "-d", plan.classes, "-cp", compilePath, ...workMain, plan.workTestSource];
|
|
124
|
+
}
|
|
125
|
+
function diagnosticsOf(output) {
|
|
126
|
+
const lines = output
|
|
127
|
+
.split("\n")
|
|
128
|
+
.filter((line) => line.trim() !== "")
|
|
129
|
+
.join("\n");
|
|
130
|
+
return lines.length > DIAGNOSTIC_LIMIT ? `${lines.slice(0, DIAGNOSTIC_LIMIT)}\n[javac output trimmed]` : lines;
|
|
131
|
+
}
|
|
132
|
+
function launchCommand(plan, request, context, notes) {
|
|
133
|
+
const resources = [join(context.moduleRoot, "src", "main", "resources"), join(context.moduleRoot, "src", "test", "resources")]
|
|
134
|
+
.map((path) => mapToWork(path, request.repoRoot, request.workRoot))
|
|
135
|
+
.filter((path) => existsSync(path));
|
|
136
|
+
const runPath = [plan.classes, ...resources, ...plan.jars, ...(plan.compiledTests === null ? [] : [plan.compiledTests])].join(delimiter);
|
|
137
|
+
const args = [plan.java, "-jar", plan.launcher, "execute", "--class-path", runPath, "--select-class", plan.qualified, "--details=none", "--disable-banner"];
|
|
138
|
+
return { ok: true, cwd: plan.workModule, notes, command: args.map(quote).join(" ") };
|
|
139
|
+
}
|
|
140
|
+
function markerFor(request, plan) {
|
|
141
|
+
return JSON.stringify({ testFile: request.testFile, digest: plan.digest });
|
|
142
|
+
}
|
|
143
|
+
function isPrepared(request, plan) {
|
|
144
|
+
try {
|
|
145
|
+
return readFileSync(plan.markerPath, "utf8") === markerFor(request, plan) && existsSync(plan.classes);
|
|
146
|
+
}
|
|
147
|
+
catch {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
function sourcesDiffer(sources, request) {
|
|
152
|
+
for (const original of sources) {
|
|
153
|
+
const copy = mapToWork(original, request.repoRoot, request.workRoot);
|
|
154
|
+
try {
|
|
155
|
+
if (readFileSync(copy, "utf8") !== readFileSync(original, "utf8"))
|
|
156
|
+
return true;
|
|
157
|
+
}
|
|
158
|
+
catch {
|
|
159
|
+
return true;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
async function sourcesDifferAsync(sources, request, signal) {
|
|
165
|
+
for (const original of sources) {
|
|
166
|
+
if (signal.aborted)
|
|
167
|
+
return false;
|
|
168
|
+
const copy = mapToWork(original, request.repoRoot, request.workRoot);
|
|
169
|
+
try {
|
|
170
|
+
if ((await readFile(copy, "utf8")) !== (await readFile(original, "utf8")))
|
|
171
|
+
return true;
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
function stoppedReason(run, timeoutMs) {
|
|
180
|
+
if (run.outcome === "cancelled")
|
|
181
|
+
return "cancelled";
|
|
182
|
+
if (run.outcome === "timed-out")
|
|
183
|
+
return `javac did not finish within ${timeoutMs} ms and was stopped.`;
|
|
184
|
+
if (run.outcome === "failed-to-start")
|
|
185
|
+
return `javac could not be started: ${run.message ?? "no reason was given"}.`;
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
export async function prepareJava(request, signal, context) {
|
|
189
|
+
if (signal.aborted)
|
|
190
|
+
return { ok: false, reason: "cancelled" };
|
|
191
|
+
const planned = planOf(request, context);
|
|
192
|
+
if (!planned.ok)
|
|
193
|
+
return planned;
|
|
194
|
+
const { plan } = planned;
|
|
195
|
+
const timeoutMs = timeoutFrom(request.timeoutMs, DEFAULT_COMPILE_TIMEOUT_MS);
|
|
196
|
+
try {
|
|
197
|
+
await rm(plan.markerPath, { force: true });
|
|
198
|
+
await rm(plan.classes, { recursive: true, force: true });
|
|
199
|
+
await mkdir(plan.classes, { recursive: true });
|
|
200
|
+
const mainSources = await listJavaSourcesAsync(join(context.moduleRoot, MAIN_SOURCE_ROOT), signal);
|
|
201
|
+
if (signal.aborted)
|
|
202
|
+
return { ok: false, reason: "cancelled" };
|
|
203
|
+
const run = await runBounded(plan.javac, javacArguments(plan, mainSources, request), { cwd: plan.workModule, timeoutMs, signal });
|
|
204
|
+
const stopped = stoppedReason(run, timeoutMs);
|
|
205
|
+
if (stopped !== null)
|
|
206
|
+
return { ok: false, reason: stopped };
|
|
207
|
+
if (run.status !== 0) {
|
|
208
|
+
const diagnostics = diagnosticsOf(run.output);
|
|
209
|
+
if (signal.aborted)
|
|
210
|
+
return { ok: false, reason: "cancelled" };
|
|
211
|
+
if (await sourcesDifferAsync(mainSources, request, signal))
|
|
212
|
+
return { ok: false, reason: `mutant did not build: ${diagnostics}` };
|
|
213
|
+
return { ok: false, reason: `javac could not compile the module with this test (exit ${String(run.status)}):\n${diagnostics}` };
|
|
214
|
+
}
|
|
215
|
+
if (signal.aborted)
|
|
216
|
+
return { ok: false, reason: "cancelled" };
|
|
217
|
+
await writeFile(plan.markerPath, markerFor(request, plan));
|
|
218
|
+
return { ok: true };
|
|
219
|
+
}
|
|
220
|
+
catch (error) {
|
|
221
|
+
return { ok: false, reason: `Preparing the Java build failed: ${error.message}` };
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
export function javaCommand(request, context) {
|
|
225
|
+
const planned = planOf(request, context);
|
|
226
|
+
if (!planned.ok)
|
|
227
|
+
return planned;
|
|
228
|
+
const { plan } = planned;
|
|
229
|
+
if (isPrepared(request, plan))
|
|
230
|
+
return launchCommand(plan, request, context, []);
|
|
231
|
+
const mainSources = listJavaSources(join(context.moduleRoot, MAIN_SOURCE_ROOT));
|
|
232
|
+
rmSync(plan.markerPath, { force: true });
|
|
233
|
+
rmSync(plan.classes, { recursive: true, force: true });
|
|
234
|
+
mkdirSync(plan.classes, { recursive: true });
|
|
235
|
+
const compiled = spawnSync(plan.javac, javacArguments(plan, mainSources, request), {
|
|
236
|
+
cwd: plan.workModule,
|
|
237
|
+
encoding: "utf8",
|
|
238
|
+
timeout: DEFAULT_COMPILE_TIMEOUT_MS,
|
|
239
|
+
maxBuffer: 8 * 1024 * 1024,
|
|
240
|
+
});
|
|
241
|
+
const notes = ["prepare was not called for this request, so the module was compiled synchronously inside command(), which blocks the event loop until javac finishes."];
|
|
242
|
+
if (compiled.status !== 0) {
|
|
243
|
+
const diagnostics = diagnosticsOf(`${compiled.stdout ?? ""}${compiled.stderr ?? ""}`);
|
|
244
|
+
if (!sourcesDiffer(mainSources, request))
|
|
245
|
+
return { ok: false, reason: `javac could not compile the module with this test (${compiled.error?.message ?? `exit ${String(compiled.status)}`}):\n${diagnostics}` };
|
|
246
|
+
notes.push("A change to the code under test did not compile, so no test ran for it.");
|
|
247
|
+
}
|
|
248
|
+
return launchCommand(plan, request, context, notes);
|
|
249
|
+
}
|
|
250
|
+
//# sourceMappingURL=java-build.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"java-build.js","sourceRoot":"","sources":["../../src/testgen/java-build.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"java-facts.d.ts","sourceRoot":"","sources":["../../src/testgen/java-facts.ts"],"names":[],"mappings":"AAEA,OAAO,EAA6E,KAAK,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAyVlI,eAAO,MAAM,UAAU,EAAE,aAexB,CAAC"}
|
|
@@ -0,0 +1,349 @@
|
|
|
1
|
+
import { tokenizeCFamily } from "../lexers/c-family.js";
|
|
2
|
+
import { isDeclaredPublic } from "./declarations.js";
|
|
3
|
+
import { chainAt, HazardSet, inRange, simpleName, startsStatement, withoutComments } from "./facts-common.js";
|
|
4
|
+
const JAVA_LANG = ["java.lang"];
|
|
5
|
+
const JAVA_TIME = ["java.time"];
|
|
6
|
+
function statics(type, members, kind, required, packages, args = "any") {
|
|
7
|
+
return { type, members, kind, required, packages, arguments: args };
|
|
8
|
+
}
|
|
9
|
+
const STATIC_ENTRIES = [
|
|
10
|
+
statics("System", ["currentTimeMillis", "nanoTime"], "time", true, JAVA_LANG),
|
|
11
|
+
statics("System", ["getenv"], "environment", false, JAVA_LANG),
|
|
12
|
+
statics("System", ["exit"], "process", false, JAVA_LANG),
|
|
13
|
+
statics("Math", ["random"], "randomness", true, JAVA_LANG),
|
|
14
|
+
statics("Thread", ["sleep"], "time", true, JAVA_LANG),
|
|
15
|
+
statics("Runtime", ["getRuntime"], "process", false, JAVA_LANG),
|
|
16
|
+
...["Instant", "LocalDateTime", "LocalDate", "LocalTime", "ZonedDateTime", "OffsetDateTime", "OffsetTime", "Year", "YearMonth", "MonthDay"].map((type) => statics(type, ["now"], "time", true, JAVA_TIME, "empty")),
|
|
17
|
+
statics("Clock", ["systemUTC", "systemDefaultZone"], "time", true, JAVA_TIME),
|
|
18
|
+
statics("Calendar", ["getInstance"], "time", true, ["java.util"]),
|
|
19
|
+
statics("UUID", ["randomUUID"], "randomness", true, ["java.util"]),
|
|
20
|
+
statics("ThreadLocalRandom", ["current"], "randomness", true, ["java.util.concurrent"]),
|
|
21
|
+
statics("SecureRandom", ["getInstance", "getInstanceStrong"], "randomness", true, ["java.security"]),
|
|
22
|
+
statics("HttpClient", ["newHttpClient", "newBuilder"], "network", true, ["java.net.http"]),
|
|
23
|
+
statics("HttpClients", ["createDefault", "custom", "createSystem"], "network", true, ["org.apache.http.impl.client", "org.apache.hc.client5.http.impl.classic"]),
|
|
24
|
+
statics("WebClient", ["create", "builder"], "network", true, ["org.springframework.web.reactive.function.client"]),
|
|
25
|
+
statics("RestClient", ["create", "builder"], "network", true, ["org.springframework.web.client"]),
|
|
26
|
+
statics("DriverManager", ["getConnection"], "database", true, ["java.sql"]),
|
|
27
|
+
statics("Persistence", ["createEntityManagerFactory"], "database", true, ["jakarta.persistence", "javax.persistence"]),
|
|
28
|
+
statics("MongoClients", ["create"], "database", true, ["com.mongodb.client", "com.mongodb.reactivestreams.client"]),
|
|
29
|
+
statics("Files", "*", "filesystem", false, ["java.nio.file"]),
|
|
30
|
+
statics("File", ["createTempFile"], "filesystem", false, ["java.io"]),
|
|
31
|
+
];
|
|
32
|
+
function ctor(type, kind, required, packages, args = "any") {
|
|
33
|
+
return { type, kind, required, packages, arguments: args };
|
|
34
|
+
}
|
|
35
|
+
const CONSTRUCTOR_ENTRIES = [
|
|
36
|
+
ctor("Date", "time", true, ["java.util"], "empty"),
|
|
37
|
+
ctor("Random", "randomness", true, ["java.util"], "empty"),
|
|
38
|
+
ctor("SecureRandom", "randomness", true, ["java.security"]),
|
|
39
|
+
ctor("Timer", "time", true, ["java.util"]),
|
|
40
|
+
ctor("RestTemplate", "network", true, ["org.springframework.web.client"]),
|
|
41
|
+
ctor("OkHttpClient", "network", true, ["okhttp3"]),
|
|
42
|
+
...["Socket", "ServerSocket", "DatagramSocket"].map((type) => ctor(type, "network", true, ["java.net"])),
|
|
43
|
+
...["File", "FileInputStream", "FileOutputStream", "FileReader", "FileWriter", "RandomAccessFile"].map((type) => ctor(type, "filesystem", false, ["java.io"])),
|
|
44
|
+
ctor("ProcessBuilder", "process", false, JAVA_LANG),
|
|
45
|
+
ctor("JdbcTemplate", "database", true, ["org.springframework.jdbc.core"]),
|
|
46
|
+
ctor("HikariDataSource", "database", true, ["com.zaxxer.hikari"]),
|
|
47
|
+
...["Jedis", "JedisPool"].map((type) => ctor(type, "database", true, ["redis.clients.jedis"])),
|
|
48
|
+
ctor("MongoClient", "database", true, ["com.mongodb", "com.mongodb.client"]),
|
|
49
|
+
];
|
|
50
|
+
const VARIABLE_ENTRIES = [
|
|
51
|
+
ctor("HttpClient", "network", true, ["java.net.http"]),
|
|
52
|
+
ctor("RestTemplate", "network", true, ["org.springframework.web.client"]),
|
|
53
|
+
ctor("RestClient", "network", true, ["org.springframework.web.client"]),
|
|
54
|
+
ctor("WebClient", "network", true, ["org.springframework.web.reactive.function.client"]),
|
|
55
|
+
ctor("OkHttpClient", "network", true, ["okhttp3"]),
|
|
56
|
+
ctor("CloseableHttpClient", "network", true, ["org.apache.http.impl.client", "org.apache.hc.client5.http.impl.classic"]),
|
|
57
|
+
ctor("HttpURLConnection", "network", true, ["java.net"]),
|
|
58
|
+
...["EntityManager", "EntityManagerFactory"].map((type) => ctor(type, "database", true, ["jakarta.persistence", "javax.persistence"])),
|
|
59
|
+
...["JdbcTemplate"].map((type) => ctor(type, "database", true, ["org.springframework.jdbc.core"])),
|
|
60
|
+
ctor("NamedParameterJdbcTemplate", "database", true, ["org.springframework.jdbc.core.namedparam"]),
|
|
61
|
+
ctor("DataSource", "database", true, ["javax.sql"]),
|
|
62
|
+
...["Connection", "Statement", "PreparedStatement"].map((type) => ctor(type, "database", true, ["java.sql"])),
|
|
63
|
+
...["SessionFactory", "Session"].map((type) => ctor(type, "database", true, ["org.hibernate"])),
|
|
64
|
+
...["MongoClient", "MongoDatabase", "MongoCollection"].map((type) => ctor(type, "database", true, ["com.mongodb", "com.mongodb.client"])),
|
|
65
|
+
ctor("MongoTemplate", "database", true, ["org.springframework.data.mongodb.core"]),
|
|
66
|
+
ctor("RedisTemplate", "database", true, ["org.springframework.data.redis.core"]),
|
|
67
|
+
ctor("Jedis", "database", true, ["redis.clients.jedis"]),
|
|
68
|
+
ctor("ProcessBuilder", "process", false, JAVA_LANG),
|
|
69
|
+
];
|
|
70
|
+
const SPEC = {
|
|
71
|
+
annotationStyle: "java",
|
|
72
|
+
modifiers: new Set(["public", "private", "protected", "static", "final", "abstract", "synchronized", "native", "default", "sealed", "strictfp", "transient", "volatile"]),
|
|
73
|
+
typeKeywords: new Set(["class", "interface", "enum", "record"]),
|
|
74
|
+
interfaceKeyword: "interface",
|
|
75
|
+
implicitlyPublicInInterface: true,
|
|
76
|
+
};
|
|
77
|
+
const MOCK_FACTORIES = new Set(["mock", "spy", "mockStatic", "mockConstruction"]);
|
|
78
|
+
const MOCK_ANNOTATIONS = new Set(["Mock", "MockBean", "MockitoBean", "SpyBean", "MockitoSpyBean", "Spy"]);
|
|
79
|
+
function code(source) {
|
|
80
|
+
return withoutComments(tokenizeCFamily(source, "java"));
|
|
81
|
+
}
|
|
82
|
+
function importsOf(tokens) {
|
|
83
|
+
const byName = new Map();
|
|
84
|
+
const wildcards = [];
|
|
85
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
86
|
+
const token = tokens[i];
|
|
87
|
+
if (token.kind !== "identifier" || token.text !== "import" || !startsStatement(tokens, i))
|
|
88
|
+
continue;
|
|
89
|
+
let cursor = i + 1;
|
|
90
|
+
const isStatic = tokens[cursor]?.text === "static";
|
|
91
|
+
if (isStatic)
|
|
92
|
+
cursor += 1;
|
|
93
|
+
const parts = [];
|
|
94
|
+
let wildcard = false;
|
|
95
|
+
while (cursor < tokens.length && tokens[cursor].text !== ";") {
|
|
96
|
+
const part = tokens[cursor];
|
|
97
|
+
if (part.kind === "identifier")
|
|
98
|
+
parts.push(part.text);
|
|
99
|
+
else if (part.text === "*")
|
|
100
|
+
wildcard = true;
|
|
101
|
+
else if (part.text !== ".")
|
|
102
|
+
break;
|
|
103
|
+
cursor += 1;
|
|
104
|
+
}
|
|
105
|
+
if (parts.length === 0 || isStatic)
|
|
106
|
+
continue;
|
|
107
|
+
if (wildcard)
|
|
108
|
+
wildcards.push(parts.join("."));
|
|
109
|
+
else
|
|
110
|
+
byName.set(parts[parts.length - 1], parts.join("."));
|
|
111
|
+
}
|
|
112
|
+
return { byName, wildcards };
|
|
113
|
+
}
|
|
114
|
+
function acceptedType(simple, packages, imports) {
|
|
115
|
+
const explicit = imports.byName.get(simple);
|
|
116
|
+
if (explicit !== undefined) {
|
|
117
|
+
const owner = explicit.slice(0, explicit.length - simple.length - 1);
|
|
118
|
+
return packages.includes(owner) ? explicit : null;
|
|
119
|
+
}
|
|
120
|
+
const wildcard = imports.wildcards.find((entry) => packages.includes(entry));
|
|
121
|
+
if (wildcard !== undefined)
|
|
122
|
+
return `${wildcard}.${simple}`;
|
|
123
|
+
if (packages.includes("java.lang"))
|
|
124
|
+
return `java.lang.${simple}`;
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
function typeEntry(entries, simple, imports) {
|
|
128
|
+
for (const entry of entries) {
|
|
129
|
+
if (entry.type !== simple)
|
|
130
|
+
continue;
|
|
131
|
+
const fqn = acceptedType(simple, entry.packages, imports);
|
|
132
|
+
if (fqn !== null)
|
|
133
|
+
return { entry, fqn };
|
|
134
|
+
}
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
function skipGenerics(tokens, from) {
|
|
138
|
+
if (tokens[from]?.text !== "<")
|
|
139
|
+
return from;
|
|
140
|
+
let depth = 0;
|
|
141
|
+
for (let cursor = from; cursor < tokens.length; cursor += 1) {
|
|
142
|
+
const text = tokens[cursor].text;
|
|
143
|
+
if (text === "<")
|
|
144
|
+
depth += 1;
|
|
145
|
+
else if (text === ">") {
|
|
146
|
+
depth -= 1;
|
|
147
|
+
if (depth === 0)
|
|
148
|
+
return cursor + 1;
|
|
149
|
+
}
|
|
150
|
+
else if (text === ";" || text === "{" || text === "(")
|
|
151
|
+
return from;
|
|
152
|
+
}
|
|
153
|
+
return from;
|
|
154
|
+
}
|
|
155
|
+
function declaredVariables(tokens, imports) {
|
|
156
|
+
const variables = new Map();
|
|
157
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
158
|
+
const token = tokens[i];
|
|
159
|
+
if (token.kind !== "identifier" || tokens[i - 1]?.text === "." || tokens[i - 1]?.text === "new")
|
|
160
|
+
continue;
|
|
161
|
+
const resolved = typeEntry(VARIABLE_ENTRIES, token.text, imports);
|
|
162
|
+
if (resolved === null)
|
|
163
|
+
continue;
|
|
164
|
+
const after = skipGenerics(tokens, i + 1);
|
|
165
|
+
const name = tokens[after];
|
|
166
|
+
const terminator = tokens[after + 1]?.text;
|
|
167
|
+
if (name?.kind === "identifier" && (terminator === ";" || terminator === "=" || terminator === "," || terminator === ")" || terminator === ":"))
|
|
168
|
+
variables.set(name.text, resolved);
|
|
169
|
+
}
|
|
170
|
+
return variables;
|
|
171
|
+
}
|
|
172
|
+
function hazardsIn(source, range) {
|
|
173
|
+
const tokens = code(source);
|
|
174
|
+
const imports = importsOf(tokens);
|
|
175
|
+
const variables = declaredVariables(tokens, imports);
|
|
176
|
+
const set = new HazardSet();
|
|
177
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
178
|
+
const token = tokens[i];
|
|
179
|
+
if (!inRange(token, range))
|
|
180
|
+
continue;
|
|
181
|
+
if (token.kind === "identifier" && token.text === "new" && tokens[i - 1]?.text !== ".") {
|
|
182
|
+
const chain = chainAt(tokens, i + 1);
|
|
183
|
+
if (chain !== null && chain.called) {
|
|
184
|
+
const simple = chain.segments[chain.segments.length - 1];
|
|
185
|
+
const resolved = typeEntry(CONSTRUCTOR_ENTRIES, simple, imports);
|
|
186
|
+
const qualified = chain.segments.length === 1 || resolved?.entry.packages.includes(chain.segments.slice(0, -1).join(".")) === true;
|
|
187
|
+
if (resolved !== null && qualified && (resolved.entry.arguments === "any" || chain.emptyCall)) {
|
|
188
|
+
set.add({ kind: resolved.entry.kind, line: token.line, text: `new ${simple}`, module: resolved.fqn, required: resolved.entry.required });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
const chain = chainAt(tokens, i);
|
|
194
|
+
if (chain === null)
|
|
195
|
+
continue;
|
|
196
|
+
const segments = chain.segments[0] === "this" ? chain.segments.slice(1) : chain.segments;
|
|
197
|
+
if (segments.length < 2)
|
|
198
|
+
continue;
|
|
199
|
+
const head = segments[0];
|
|
200
|
+
const variable = variables.get(head);
|
|
201
|
+
if (variable !== undefined && chain.called) {
|
|
202
|
+
set.add({ kind: variable.entry.kind, line: token.line, text: segments.join("."), module: variable.fqn, required: variable.entry.required });
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
const timeUnit = acceptedType(head, ["java.util.concurrent"], imports);
|
|
206
|
+
if (head === "TimeUnit" && timeUnit !== null && segments[segments.length - 1] === "sleep" && chain.called) {
|
|
207
|
+
set.add({ kind: "time", line: token.line, text: segments.join("."), module: timeUnit, required: true });
|
|
208
|
+
continue;
|
|
209
|
+
}
|
|
210
|
+
const member = segments[1];
|
|
211
|
+
for (const entry of STATIC_ENTRIES) {
|
|
212
|
+
if (entry.type !== head || !chain.called)
|
|
213
|
+
continue;
|
|
214
|
+
if (entry.members !== "*" && !entry.members.includes(member))
|
|
215
|
+
continue;
|
|
216
|
+
if (segments.length !== 2)
|
|
217
|
+
continue;
|
|
218
|
+
if (entry.arguments === "empty" && !(chain.emptyCall && chain.segments.length === segments.length))
|
|
219
|
+
continue;
|
|
220
|
+
const fqn = acceptedType(head, entry.packages, imports);
|
|
221
|
+
if (fqn === null)
|
|
222
|
+
continue;
|
|
223
|
+
set.add({ kind: entry.kind, line: token.line, text: `${head}.${member}`, module: fqn, required: entry.required });
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return set.sorted();
|
|
228
|
+
}
|
|
229
|
+
function resolveType(chainSegments, imports) {
|
|
230
|
+
const head = chainSegments[0];
|
|
231
|
+
const imported = imports.byName.get(head);
|
|
232
|
+
return imported === undefined ? chainSegments.join(".") : [imported, ...chainSegments.slice(1)].join(".");
|
|
233
|
+
}
|
|
234
|
+
function moduleReferences(source) {
|
|
235
|
+
const tokens = code(source);
|
|
236
|
+
const imports = importsOf(tokens);
|
|
237
|
+
const references = [];
|
|
238
|
+
for (let i = 0; i < tokens.length; i += 1) {
|
|
239
|
+
const token = tokens[i];
|
|
240
|
+
if (token.kind === "identifier" && token.text === "import" && startsStatement(tokens, i)) {
|
|
241
|
+
let cursor = i + 1;
|
|
242
|
+
const parts = [];
|
|
243
|
+
let wildcard = false;
|
|
244
|
+
if (tokens[cursor]?.text === "static")
|
|
245
|
+
cursor += 1;
|
|
246
|
+
while (cursor < tokens.length && tokens[cursor].text !== ";") {
|
|
247
|
+
const part = tokens[cursor];
|
|
248
|
+
if (part.kind === "identifier")
|
|
249
|
+
parts.push(part.text);
|
|
250
|
+
else if (part.text === "*")
|
|
251
|
+
wildcard = true;
|
|
252
|
+
else if (part.text !== ".")
|
|
253
|
+
break;
|
|
254
|
+
cursor += 1;
|
|
255
|
+
}
|
|
256
|
+
if (parts.length > 0)
|
|
257
|
+
references.push({ specifier: wildcard ? `${parts.join(".")}.*` : parts.join("."), line: token.line, form: "import" });
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if (token.text === "@" && tokens[i + 1]?.kind === "identifier" && MOCK_ANNOTATIONS.has(tokens[i + 1].text)) {
|
|
261
|
+
const type = annotatedType(tokens, i + 2);
|
|
262
|
+
if (type !== null)
|
|
263
|
+
references.push({ specifier: resolveType(type, imports), line: token.line, form: "mock" });
|
|
264
|
+
continue;
|
|
265
|
+
}
|
|
266
|
+
const chain = chainAt(tokens, i);
|
|
267
|
+
if (chain === null || !chain.called || !MOCK_FACTORIES.has(chain.segments[chain.segments.length - 1]))
|
|
268
|
+
continue;
|
|
269
|
+
const argument = chainAt(tokens, chain.last + 2);
|
|
270
|
+
if (argument === null || argument.segments[argument.segments.length - 1] !== "class")
|
|
271
|
+
continue;
|
|
272
|
+
references.push({ specifier: resolveType(argument.segments.slice(0, -1), imports), line: token.line, form: "mock" });
|
|
273
|
+
}
|
|
274
|
+
return references;
|
|
275
|
+
}
|
|
276
|
+
function annotatedType(tokens, from) {
|
|
277
|
+
let cursor = from;
|
|
278
|
+
if (tokens[cursor]?.text === "(") {
|
|
279
|
+
let depth = 0;
|
|
280
|
+
for (; cursor < tokens.length; cursor += 1) {
|
|
281
|
+
if (tokens[cursor].text === "(")
|
|
282
|
+
depth += 1;
|
|
283
|
+
else if (tokens[cursor].text === ")") {
|
|
284
|
+
depth -= 1;
|
|
285
|
+
if (depth === 0) {
|
|
286
|
+
cursor += 1;
|
|
287
|
+
break;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
for (let guard = 0; guard < 20 && cursor < tokens.length; guard += 1) {
|
|
293
|
+
const token = tokens[cursor];
|
|
294
|
+
if (token.text === "@") {
|
|
295
|
+
cursor += 2;
|
|
296
|
+
if (tokens[cursor]?.text === "(") {
|
|
297
|
+
let depth = 0;
|
|
298
|
+
for (; cursor < tokens.length; cursor += 1) {
|
|
299
|
+
if (tokens[cursor].text === "(")
|
|
300
|
+
depth += 1;
|
|
301
|
+
else if (tokens[cursor].text === ")") {
|
|
302
|
+
depth -= 1;
|
|
303
|
+
if (depth === 0) {
|
|
304
|
+
cursor += 1;
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
continue;
|
|
311
|
+
}
|
|
312
|
+
if (token.kind === "identifier" && SPEC.modifiers.has(token.text)) {
|
|
313
|
+
cursor += 1;
|
|
314
|
+
continue;
|
|
315
|
+
}
|
|
316
|
+
break;
|
|
317
|
+
}
|
|
318
|
+
const chain = chainAt(tokens, cursor);
|
|
319
|
+
return chain === null ? null : [...chain.segments];
|
|
320
|
+
}
|
|
321
|
+
function isExported(source, name, startLine) {
|
|
322
|
+
return isDeclaredPublic(code(source), name, startLine, SPEC);
|
|
323
|
+
}
|
|
324
|
+
function bareModuleName(specifier) {
|
|
325
|
+
return specifier.replace(/\.\*$/, "");
|
|
326
|
+
}
|
|
327
|
+
function stubbedByMock(hazard, mocked) {
|
|
328
|
+
if (hazard.module === null)
|
|
329
|
+
return false;
|
|
330
|
+
const wanted = simpleName(hazard.module);
|
|
331
|
+
return mocked.some((specifier) => simpleName(specifier) === wanted);
|
|
332
|
+
}
|
|
333
|
+
export const JAVA_FACTS = {
|
|
334
|
+
hazardsIn,
|
|
335
|
+
moduleReferences,
|
|
336
|
+
isExported,
|
|
337
|
+
bareModuleName,
|
|
338
|
+
stubbedByMock,
|
|
339
|
+
stubPatterns: {
|
|
340
|
+
time: [/\bClock\s*\.\s*(?:fixed|offset|tick)\b/, /\bmockStatic\s*\(\s*(?:Instant|LocalDate|LocalDateTime|LocalTime|ZonedDateTime|OffsetDateTime|System|Date|Calendar|Clock)\b/, /\b(?:setClock|withClock|FixedClock|MutableClock)\b/],
|
|
341
|
+
randomness: [/\bnew\s+Random\s*\(\s*[^)\s]/, /\bmockStatic\s*\(\s*(?:UUID|Math|ThreadLocalRandom|SecureRandom)\b/, /\bsetSeed\s*\(/],
|
|
342
|
+
network: [/\b(?:WireMock\w*|MockWebServer|MockRestServiceServer|MockServerClient|Hoverfly)\b/, /@RestClientTest\b/],
|
|
343
|
+
database: [/\b(?:EmbeddedDatabase|EmbeddedDatabaseBuilder)\b/, /@(?:DataJpaTest|JdbcTest)\b/, /jdbc:h2:/],
|
|
344
|
+
environment: [/\b(?:EnvironmentVariables|SystemStubs)\b/, /@SetEnvironmentVariable\b/],
|
|
345
|
+
filesystem: [/@TempDir\b/, /\bTemporaryFolder\b/, /\bFiles\s*\.\s*createTemp(?:File|Directory)\b/],
|
|
346
|
+
process: [],
|
|
347
|
+
},
|
|
348
|
+
};
|
|
349
|
+
//# sourceMappingURL=java-facts.js.map
|