Skip to content

Commit fe665eb

Browse files
committed
Add missing tasks
1 parent 337a9e7 commit fe665eb

File tree

4 files changed

+296
-0
lines changed

4 files changed

+296
-0
lines changed
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
/*
2+
* Copyright and related rights waived via CC0
3+
*
4+
* You should have received a copy of the CC0 legalcode along with this
5+
* work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
6+
*/
7+
package org.graalvm.internal.tck.harness.tasks
8+
9+
import org.gradle.api.GradleException
10+
import org.gradle.api.tasks.TaskAction
11+
import org.gradle.process.ExecOperations
12+
import org.gradle.process.ExecSpec
13+
import org.graalvm.internal.tck.harness.TckExtension
14+
15+
import javax.inject.Inject
16+
import java.nio.charset.StandardCharsets
17+
import java.nio.file.Path
18+
19+
import static org.graalvm.internal.tck.Utils.coordinatesMatch
20+
import static org.graalvm.internal.tck.Utils.readIndexFile
21+
import static org.graalvm.internal.tck.Utils.splitCoordinates
22+
23+
/**
24+
* Base task that resolves coordinates (via CoordinatesAwareTask) and executes a command for each coordinate.
25+
* Subclasses implement commandFor(String coordinates) and may override hooks for logging.
26+
*/
27+
abstract class AllCoordinatesExecTask extends CoordinatesAwareTask {
28+
29+
@Inject
30+
abstract ExecOperations getExecOperations()
31+
32+
33+
/**
34+
* Subclasses must return the command line to run for the given coordinates.
35+
*/
36+
abstract List<String> commandFor(String coordinates)
37+
38+
/**
39+
* Customize error message.
40+
*/
41+
protected String errorMessageFor(String coordinates, int exitCode) {
42+
return "Execution failed for ${coordinates} with exit code ${exitCode}"
43+
}
44+
45+
/**
46+
* Hook invoked before executing each coordinate.
47+
*/
48+
protected void beforeEach(String coordinates, List<String> command) {
49+
// no-op
50+
}
51+
52+
/**
53+
* Hook invoked after executing each coordinate on success.
54+
*/
55+
protected void afterEach(String coordinates) {
56+
// no-op
57+
}
58+
59+
@TaskAction
60+
final void runAll() {
61+
List<String> coords = resolveCoordinates()
62+
if (coords.isEmpty()) {
63+
getLogger().lifecycle("No matching coordinates found. Nothing to do.")
64+
return
65+
}
66+
for (String c : coords) {
67+
runSingle(c)
68+
}
69+
}
70+
71+
private void runSingle(String coordinates) {
72+
List<String> command = commandFor(coordinates)
73+
beforeEach(coordinates, command)
74+
75+
def out = new ByteArrayOutputStream()
76+
def err = new ByteArrayOutputStream()
77+
78+
def execResult = getExecOperations().exec { ExecSpec spec ->
79+
this.configureSpec(spec, coordinates, command)
80+
spec.standardOutput = new TeeOutputStream(out, System.out)
81+
spec.errorOutput = new TeeOutputStream(err, System.err)
82+
}
83+
84+
// write output file like AbstractSubprojectTask
85+
String hash = command.join(",").md5()
86+
File outputFile = project.layout.buildDirectory.file("tests/${coordinates}/${hash}.out").get().asFile
87+
outputFile.parentFile.mkdirs()
88+
outputFile.text = """Standard out
89+
-----
90+
${out.toString(StandardCharsets.UTF_8)}
91+
-----
92+
Standard err
93+
----
94+
${err.toString(StandardCharsets.UTF_8)}
95+
----
96+
"""
97+
98+
int exitCode = execResult.exitValue
99+
if (exitCode != 0) {
100+
throw new GradleException(errorMessageFor(coordinates, exitCode))
101+
}
102+
afterEach(coordinates)
103+
}
104+
105+
protected void configureSpec(ExecSpec spec, String coordinates, List<String> command) {
106+
def (String groupId, String artifactId, String version) = splitCoordinates(coordinates)
107+
Path metadataDir = tckExtension.getMetadataDir(coordinates)
108+
boolean override = false
109+
110+
def metadataIndex = readIndexFile(metadataDir.parent)
111+
for (def entry in metadataIndex) {
112+
if (coordinatesMatch((String) entry["module"], groupId, artifactId) && ((List<String>) entry["tested-versions"]).contains(version)) {
113+
if (entry.containsKey("override")) {
114+
override |= entry["override"] as boolean
115+
}
116+
break
117+
}
118+
}
119+
120+
Path testDir = tckExtension.getTestDir(coordinates)
121+
122+
Map<String, String> env = new HashMap<>(System.getenv())
123+
env.put("GVM_TCK_LC", coordinates)
124+
env.put("GVM_TCK_EXCLUDE", override.toString())
125+
if (System.getenv("GVM_TCK_LV") == null) {
126+
env.put("GVM_TCK_LV", version)
127+
}
128+
env.put("GVM_TCK_MD", metadataDir.toAbsolutePath().toString())
129+
env.put("GVM_TCK_TCKDIR", tckExtension.getTckRoot().get().getAsFile().toPath().toAbsolutePath().toString())
130+
131+
spec.environment(env)
132+
spec.commandLine(command)
133+
spec.workingDir(testDir.toAbsolutePath().toFile())
134+
spec.setIgnoreExitValue(true)
135+
spec.standardOutput = System.out
136+
spec.errorOutput = System.err
137+
}
138+
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Copyright and related rights waived via CC0
3+
*
4+
* You should have received a copy of the CC0 legalcode along with this
5+
* work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
6+
*/
7+
package org.graalvm.internal.tck.harness.tasks
8+
9+
import org.gradle.api.GradleException
10+
import org.gradle.api.tasks.TaskAction
11+
import org.graalvm.internal.tck.MetadataFilesCheckerTask
12+
13+
/**
14+
* Executes MetadataFilesCheckerTask for all matching coordinates resolved via -Pcoordinates.
15+
* This unifies handling so the task itself performs coordinate resolution and iteration.
16+
*/
17+
@SuppressWarnings('unused')
18+
abstract class CheckMetadataFilesAllTask extends CoordinatesAwareTask {
19+
20+
@TaskAction
21+
void runAll() {
22+
List<String> coords = resolveCoordinates()
23+
if (coords.isEmpty()) {
24+
getLogger().lifecycle("No matching coordinates found for metadata checks. Nothing to do.")
25+
return
26+
}
27+
28+
List<String> failures = []
29+
coords.each { c ->
30+
if (c.startsWith("samples:") || c.startsWith("org.example:")) {
31+
return // skip samples/infrastructure
32+
}
33+
String tmpName = ("checkMetadataFiles_" + c.replace(":", "_") + "_" + System.nanoTime())
34+
def t = project.tasks.create(tmpName, MetadataFilesCheckerTask.class)
35+
t.setCoordinates(c)
36+
try {
37+
t.run()
38+
getLogger().lifecycle("Metadata files check passed for {}", c)
39+
} catch (Throwable ex) {
40+
failures.add("${c}: ${ex.message}")
41+
getLogger().error("Metadata files check failed for {}: {}", c, ex.message)
42+
} finally {
43+
// Best effort cleanup to avoid cluttering the task graph
44+
project.tasks.remove(t)
45+
}
46+
}
47+
48+
if (!failures.isEmpty()) {
49+
String msg = "Metadata files check failed for the following coordinates:\n - " + failures.join("\n - ")
50+
throw new GradleException(msg)
51+
}
52+
}
53+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* Copyright and related rights waived via CC0
3+
*
4+
* You should have received a copy of the CC0 legalcode along with this
5+
* work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
6+
*/
7+
package org.graalvm.internal.tck.harness.tasks
8+
9+
import org.gradle.api.DefaultTask
10+
import org.gradle.api.provider.ListProperty
11+
import org.gradle.api.tasks.Input
12+
import org.gradle.api.tasks.Optional
13+
import org.graalvm.internal.tck.harness.TckExtension
14+
import org.graalvm.internal.tck.utils.CoordinateUtils
15+
16+
import javax.inject.Inject
17+
18+
/**
19+
* Base task providing unified coordinate resolution from -Pcoordinates and optional overrides.
20+
* Supports:
21+
* - single coordinate: group:artifact:version
22+
* - filter by group/artifact
23+
* - "all"
24+
* - fractional batches "k/n"
25+
* Always filters out "samples:".
26+
*/
27+
abstract class CoordinatesAwareTask extends DefaultTask {
28+
29+
protected final TckExtension tckExtension
30+
31+
@Inject
32+
CoordinatesAwareTask() {
33+
this.tckExtension = project.extensions.findByType(TckExtension)
34+
// Default to no override
35+
getCoordinatesOverride().convention(Collections.<String>emptyList())
36+
}
37+
38+
/**
39+
* Allows tasks (e.g., diff) to override the set of coordinates to run on.
40+
*/
41+
@Input
42+
@Optional
43+
final ListProperty<String> coordinatesOverride = project.objects.listProperty(String)
44+
45+
ListProperty<String> getCoordinatesOverride() {
46+
return coordinatesOverride
47+
}
48+
49+
void setCoordinatesOverride(List<String> coords) {
50+
getCoordinatesOverride().set(coords)
51+
}
52+
53+
protected List<String> resolveCoordinates() {
54+
List<String> override = getCoordinatesOverride().orNull
55+
List<String> coords
56+
if (override != null && !override.isEmpty()) {
57+
coords = override
58+
} else {
59+
String coordinateFilter = Objects.requireNonNullElse(project.findProperty("coordinates"), "") as String
60+
coords = computeMatchingCoordinates(coordinateFilter)
61+
}
62+
return coords.findAll { !it.startsWith("samples:") }
63+
}
64+
65+
protected List<String> computeMatchingCoordinates(String filter) {
66+
if (CoordinateUtils.isFractionalBatch(filter)) {
67+
int[] frac = CoordinateUtils.parseFraction(filter)
68+
List<String> all = tckExtension.getMatchingCoordinates("all")
69+
return CoordinateUtils.computeBatchedCoordinates(all, frac[0], frac[1])
70+
} else {
71+
return tckExtension.getMatchingCoordinates(filter)
72+
}
73+
}
74+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright and related rights waived via CC0
3+
*
4+
* You should have received a copy of the CC0 legalcode along with this
5+
* work. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>.
6+
*/
7+
package org.graalvm.internal.tck.harness.tasks
8+
9+
import org.gradle.api.GradleException
10+
11+
/**
12+
* Base task for actions that must operate on exactly one coordinate.
13+
* Reuses the same unified resolution as CoordinatesAwareTask and enforces a single result.
14+
*/
15+
abstract class SingleCoordinateTask extends CoordinatesAwareTask {
16+
17+
/**
18+
* Resolves to exactly one coordinate or fails with a helpful error.
19+
*/
20+
protected String resolveSingleCoordinate() {
21+
List<String> coords = resolveCoordinates()
22+
if (coords.isEmpty()) {
23+
throw new GradleException("No matching coordinates found. Provide a concrete coordinate via -Pcoordinates=group:artifact:version")
24+
}
25+
if (coords.size() > 1) {
26+
throw new GradleException("Multiple coordinates matched: ${coords}. This task requires a single concrete coordinate. " +
27+
"Please specify an exact 'group:artifact:version' using -Pcoordinates.")
28+
}
29+
return coords.get(0)
30+
}
31+
}

0 commit comments

Comments
 (0)