Skip to content

Commit

Permalink
Introduce the ability to skip native tests if GraalVM version is too old
Browse files Browse the repository at this point in the history
Essentially the test is skipped if the GraalVM version used to build the
native binary was older than the version specified in the new
@DisableIfBuiltWithGraalVMOlderThan annotation
  • Loading branch information
geoand committed Apr 5, 2021
1 parent c7b5494 commit 9dcfb36
Show file tree
Hide file tree
Showing 9 changed files with 355 additions and 204 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,48 @@
public final class NativeImageBuildItem extends SimpleBuildItem {

private final Path path;
private final GraalVMVersion graalVMVersion;

public NativeImageBuildItem(Path path) {
public NativeImageBuildItem(Path path, GraalVMVersion graalVMVersion) {
this.path = path;
this.graalVMVersion = graalVMVersion;
}

public Path getPath() {
return path;
}

public GraalVMVersion getGraalVMInfo() {
return graalVMVersion;
}

public static class GraalVMVersion {
private final String fullVersion;
private final int major;
private final int minor;
private final String distribution;

public GraalVMVersion(String fullVersion, int major, int minor, String distribution) {
this.fullVersion = fullVersion;
this.major = major;
this.minor = minor;
this.distribution = distribution;
}

public String getFullVersion() {
return fullVersion;
}

public int getMajor() {
return major;
}

public int getMinor() {
return minor;
}

public String getDistribution() {
return distribution;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package io.quarkus.deployment.pkg.steps;

import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

final class GraalVM {
static final class Version implements Comparable<Version> {
private static final Pattern PATTERN = Pattern.compile(
"GraalVM Version (([1-9][0-9]*)\\.([0-9]+)\\.[0-9]+|\\p{XDigit}*)[^(\n$]*(\\(Mandrel Distribution\\))?\\s*");

static final Version UNVERSIONED = new Version("Undefined", -1, -1, Distribution.ORACLE);
static final Version SNAPSHOT_ORACLE = new Version("Snapshot", Integer.MAX_VALUE, Integer.MAX_VALUE,
Distribution.ORACLE);
static final Version SNAPSHOT_MANDREL = new Version("Snapshot", Integer.MAX_VALUE, Integer.MAX_VALUE,
Distribution.MANDREL);

static final Version VERSION_20_3 = new Version("GraalVM 20.3", 20, 3, Distribution.ORACLE);
static final Version VERSION_21_0 = new Version("GraalVM 21.0", 21, 0, Distribution.ORACLE);

static final Version MINIMUM = VERSION_20_3;
static final Version CURRENT = VERSION_21_0;

final String fullVersion;
final int major;
final int minor;
final Distribution distribution;

Version(String fullVersion, int major, int minor, Distribution distro) {
this.fullVersion = fullVersion;
this.major = major;
this.minor = minor;
this.distribution = distro;
}

String getFullVersion() {
return fullVersion;
}

boolean isDetected() {
return this != UNVERSIONED;
}

boolean isObsolete() {
return this.compareTo(MINIMUM) < 0;
}

boolean isMandrel() {
return distribution == Distribution.MANDREL;
}

boolean isSnapshot() {
return this == SNAPSHOT_ORACLE || this == SNAPSHOT_MANDREL;
}

boolean isNewerThan(Version version) {
return this.compareTo(version) > 0;
}

@Override
public int compareTo(Version o) {
if (major > o.major) {
return 1;
}

if (major == o.major) {
if (minor > o.minor) {
return 1;
} else if (minor == o.minor) {
return 0;
}
}

return -1;
}

static Version of(Stream<String> lines) {
final Iterator<String> it = lines.iterator();
while (it.hasNext()) {
final String line = it.next();
final Matcher matcher = PATTERN.matcher(line);
if (matcher.find() && matcher.groupCount() >= 3) {
final String distro = matcher.group(4);
if (isSnapshot(matcher.group(2))) {
return isMandrel(distro) ? SNAPSHOT_MANDREL : SNAPSHOT_ORACLE;
} else {
return new Version(
line,
Integer.parseInt(matcher.group(2)), Integer.parseInt(matcher.group(3)),
isMandrel(distro) ? Distribution.MANDREL : Distribution.ORACLE);
}
}
}

return UNVERSIONED;
}

private static boolean isSnapshot(String s) {
return s == null;
}

private static boolean isMandrel(String s) {
return "(Mandrel Distribution)".equals(s);
}

@Override
public String toString() {
return "Version{" +
"major=" + major +
", minor=" + minor +
", distribution=" + distribution +
'}';
}
}

enum Distribution {
ORACLE,
MANDREL;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@

import org.jboss.logging.Logger;

import io.quarkus.deployment.pkg.steps.NativeImageBuildStep.GraalVM;
import io.quarkus.deployment.util.ProcessUtil;

public abstract class NativeImageBuildRunner {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import org.apache.commons.lang3.SystemUtils;
Expand Down Expand Up @@ -67,7 +66,12 @@ public class NativeImageBuildStep {

@BuildStep(onlyIf = NativeBuild.class)
ArtifactResultBuildItem result(NativeImageBuildItem image) {
return new ArtifactResultBuildItem(image.getPath(), PackageConfig.NATIVE, Collections.emptyMap());
NativeImageBuildItem.GraalVMVersion graalVMVersion = image.getGraalVMInfo();
Map<String, Object> graalVMInfoProps = new HashMap<>();
graalVMInfoProps.put("graalvm.version.full", graalVMVersion.getFullVersion());
graalVMInfoProps.put("graalvm.version.major", "" + graalVMVersion.getMajor());
graalVMInfoProps.put("graalvm.version.minor", "" + graalVMVersion.getMinor());
return new ArtifactResultBuildItem(image.getPath(), PackageConfig.NATIVE, graalVMInfoProps);
}

@BuildStep(onlyIf = NativeSourcesBuild.class)
Expand Down Expand Up @@ -208,7 +212,10 @@ public NativeImageBuildItem build(NativeConfig nativeConfig, NativeImageSourceJa
log.warn("That will result in a larger native image with debug symbols embedded in it.");
}

return new NativeImageBuildItem(finalExecutablePath);
return new NativeImageBuildItem(finalExecutablePath,
new NativeImageBuildItem.GraalVMVersion(graalVMVersion.fullVersion, graalVMVersion.major,
graalVMVersion.minor,
graalVMVersion.distribution.name()));
} catch (Exception e) {
throw new RuntimeException("Failed to build native image", e);
} finally {
Expand Down Expand Up @@ -484,121 +491,6 @@ private static void objcopy(String... args) {
}
}

protected static final class GraalVM {
static final class Version implements Comparable<Version> {
private static final Pattern PATTERN = Pattern.compile(
"GraalVM Version (([1-9][0-9]*)\\.([0-9]+)\\.[0-9]+|\\p{XDigit}*)[^(\n$]*(\\(Mandrel Distribution\\))?\\s*");

static final Version UNVERSIONED = new Version("Undefined", -1, -1, Distribution.ORACLE);
static final Version SNAPSHOT_ORACLE = new Version("Snapshot", Integer.MAX_VALUE, Integer.MAX_VALUE,
Distribution.ORACLE);
static final Version SNAPSHOT_MANDREL = new Version("Snapshot", Integer.MAX_VALUE, Integer.MAX_VALUE,
Distribution.MANDREL);

static final Version VERSION_20_3 = new Version("GraalVM 20.3", 20, 3, Distribution.ORACLE);
static final Version VERSION_21_0 = new Version("GraalVM 21.0", 21, 0, Distribution.ORACLE);

static final Version MINIMUM = VERSION_20_3;
static final Version CURRENT = VERSION_21_0;

final String fullVersion;
final int major;
final int minor;
final Distribution distribution;

Version(String fullVersion, int major, int minor, Distribution distro) {
this.fullVersion = fullVersion;
this.major = major;
this.minor = minor;
this.distribution = distro;
}

String getFullVersion() {
return fullVersion;
}

boolean isDetected() {
return this != UNVERSIONED;
}

boolean isObsolete() {
return this.compareTo(MINIMUM) < 0;
}

boolean isMandrel() {
return distribution == Distribution.MANDREL;
}

boolean isSnapshot() {
return this == SNAPSHOT_ORACLE || this == SNAPSHOT_MANDREL;
}

boolean isNewerThan(Version version) {
return this.compareTo(version) > 0;
}

@Override
public int compareTo(Version o) {
if (major > o.major) {
return 1;
}

if (major == o.major) {
if (minor > o.minor) {
return 1;
} else if (minor == o.minor) {
return 0;
}
}

return -1;
}

static Version of(Stream<String> lines) {
final Iterator<String> it = lines.iterator();
while (it.hasNext()) {
final String line = it.next();
final Matcher matcher = PATTERN.matcher(line);
if (matcher.find() && matcher.groupCount() >= 3) {
final String distro = matcher.group(4);
if (isSnapshot(matcher.group(2))) {
return isMandrel(distro) ? SNAPSHOT_MANDREL : SNAPSHOT_ORACLE;
} else {
return new Version(
line,
Integer.parseInt(matcher.group(2)), Integer.parseInt(matcher.group(3)),
isMandrel(distro) ? Distribution.MANDREL : Distribution.ORACLE);
}
}
}

return UNVERSIONED;
}

private static boolean isSnapshot(String s) {
return s == null;
}

private static boolean isMandrel(String s) {
return "(Mandrel Distribution)".equals(s);
}

@Override
public String toString() {
return "Version{" +
"major=" + major +
", minor=" + minor +
", distribution=" + distribution +
'}';
}
}

enum Distribution {
ORACLE,
MANDREL;
}
}

private static class NativeImageInvokerInfo {
private final List<String> args;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
package io.quarkus.deployment.pkg.steps;

import static io.quarkus.deployment.pkg.steps.NativeImageBuildStep.GraalVM.Distribution.MANDREL;
import static io.quarkus.deployment.pkg.steps.NativeImageBuildStep.GraalVM.Distribution.ORACLE;
import static io.quarkus.deployment.pkg.steps.GraalVM.Distribution.MANDREL;
import static io.quarkus.deployment.pkg.steps.GraalVM.Distribution.ORACLE;
import static org.assertj.core.api.Assertions.assertThat;

import java.util.stream.Stream;

import org.junit.jupiter.api.Test;

import io.quarkus.deployment.pkg.steps.NativeImageBuildStep.GraalVM.Distribution;
import io.quarkus.deployment.pkg.steps.NativeImageBuildStep.GraalVM.Version;
import io.quarkus.deployment.pkg.steps.GraalVM.Distribution;
import io.quarkus.deployment.pkg.steps.GraalVM.Version;

public class NativeImageBuildStepTest {

Expand Down
Loading

0 comments on commit 9dcfb36

Please sign in to comment.