Skip to content

Commit

Permalink
Adds minJDK and maxJDK to IfMandrelVersion annotation
Browse files Browse the repository at this point in the history
Tested examples:

```java
    @test
    @tag("jdkVersionTest")
    @order(1)
    @IfMandrelVersion(min = "21.3.1")
    public void jdkVersionCheckA(TestInfo testInfo) {
        System.out.println("KARM Running test "+testInfo.getTestMethod());
    }

    @test
    @tag("jdkVersionTest")
    @order(2)
    @IfMandrelVersion(min = "21.3.1", minJDK = "17")
    public void jdkVersionCheckB(TestInfo testInfo) {
        System.out.println("KARM Running test "+testInfo.getTestMethod());
    }

    @test
    @tag("jdkVersionTest")
    @order(3)
    @IfMandrelVersion(min = "22", minJDK = "17")
    public void jdkVersionCheckC(TestInfo testInfo) {
        System.out.println("KARM Running test "+testInfo.getTestMethod());
    }

    @test
    @tag("jdkVersionTest")
    @order(4)
    @IfMandrelVersion(min = "22", minJDK = "17.0.2")
    public void jdkVersionCheckD(TestInfo testInfo) {
        System.out.println("KARM Running test "+testInfo.getTestMethod());
    }

    @test
    @tag("jdkVersionTest")
    @order(5)
    @IfMandrelVersion(min = "22", minJDK = "17", maxJDK = "17.0.2")
    public void jdkVersionCheckE(TestInfo testInfo) {
        System.out.println("KARM Running test "+testInfo.getTestMethod());
    }

    @test
    @tag("jdkVersionTest")
    @order(6)
    @IfMandrelVersion(min = "21", minJDK = "11.0.12", maxJDK = "17.0.1")
    public void jdkVersionCheckF(TestInfo testInfo) {
        System.out.println("KARM Running test "+testInfo.getTestMethod());
    }

    @test
    @tag("jdkVersionTest")
    @order(7)
    @IfMandrelVersion(min = "21", maxJDK = "11")
    public void jdkVersionCheckG(TestInfo testInfo) {
        System.out.println("KARM Running test "+testInfo.getTestMethod());
    }
```

Adds VersionTests
  • Loading branch information
Karm committed Apr 1, 2022
1 parent 8f68c24 commit cf047ae
Show file tree
Hide file tree
Showing 8 changed files with 242 additions and 23 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/local_tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ jobs:
)
pushd ts
copy .github/mvn-settings.xml ~/.m2/settings.xml
mvn clean verify -Ptestsuite -Dquarkus.version=${{ matrix.quarkus-version }}
mvn clean verify -Ptestsuite -DincludeTags=testing-testsuite,runtimes,reproducers -Dquarkus.version=${{ matrix.quarkus-version }}
shell: cmd
- name: Linux test
if: startsWith(matrix.os, 'ubuntu')
Expand All @@ -159,7 +159,7 @@ jobs:
native-image --version
pushd ts
cp .github/mvn-settings.xml ~/.m2/settings.xml
mvn clean verify -Ptestsuite -Dquarkus.version=${{ matrix.quarkus-version }}
mvn clean verify -Ptestsuite -DincludeTags=testing-testsuite,runtimes,reproducers -Dquarkus.version=${{ matrix.quarkus-version }}
shell: bash
- name: Prepare failure archive (if maven failed)
if: failure()
Expand Down
2 changes: 1 addition & 1 deletion testsuite/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@
<dependency>
<groupId>org.graalvm.sdk</groupId>
<artifactId>graal-sdk</artifactId>
<version>21.2.0</version>
<version>21.3.1</version>
</dependency>

<dependency>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,7 @@
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.condition.DisabledOnJre;
import org.junit.jupiter.api.condition.DisabledOnOs;
import org.junit.jupiter.api.condition.JRE;
import org.junit.jupiter.api.condition.OS;

import java.io.File;
Expand Down Expand Up @@ -572,8 +570,7 @@ public void timezonesBakedIn(TestInfo testInfo) throws IOException, InterruptedE
@Test
@Tag("jdk-17")
@Tag("recordannotations")
@DisabledOnJre(JRE.JAVA_11)
@IfMandrelVersion(min = "21.3.1.1")
@IfMandrelVersion(min = "21.3.1.1", minJDK = "17")
public void recordAnnotationsWork(TestInfo testInfo) throws IOException, InterruptedException {
final Apps app = Apps.RECORDANNOTATIONS;
LOGGER.info("Testing app: " + app);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,25 @@
*
* IfMandrelVersion(min = "21.1", inContainer = true)
* i.e. [21.1, +∞)
*
* IfMandrelVersion(min = "21.3.1", minJDK = "17")
* i.e. [21.3.1, +∞) and [17, +∞)
*
* IfMandrelVersion(min = "22", minJDK = "17", maxJDK = "17.0.2")
* i.e. [22, +∞) and [17, 17.0.2]
*
* //@formatter:on
* Note that versions 21.1.0.0-final and 21.1.0.0-snapshot and 21.1.0.0 are all considered equal.
*
* The actual comparator comes from Graal's own org.graalvm.home.Version.
*
* inContainer: Whether the version should be pulled from a builder image container.
*
* JDK versions comparator uses feature.interim.update, the fourth, patch number or
* any other qualifiers following that are not used, i.e.
* 17.0.3-beta+5-202203292328 and 17.0.3-beta+6 are the same and
* 11.0.14.1+1-LTS and 11.0.14 are the same.
*
* @author Michal Karm Babacek <karm@redhat.com>
*/
@Target(ElementType.METHOD)
Expand All @@ -58,5 +70,9 @@

String max() default "";

String minJDK() default "";

String maxJDK() default "";

boolean inContainer() default false;
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,11 @@
import org.junit.jupiter.api.extension.ExtensionContext;

import java.lang.reflect.AnnotatedElement;
import java.util.regex.Pattern;

import static java.lang.String.format;
import static org.graalvm.tests.integration.utils.versions.UsedVersion.compareJDKVersion;
import static org.graalvm.tests.integration.utils.versions.UsedVersion.featureInterimUpdate;
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.disabled;
import static org.junit.jupiter.api.extension.ConditionEvaluationResult.enabled;
import static org.junit.platform.commons.support.AnnotationSupport.findAnnotation;
Expand All @@ -52,15 +55,28 @@ public ConditionEvaluationResult evaluateExecutionCondition(

private ConditionEvaluationResult disableIfVersionMismatch(IfMandrelVersion annotation, AnnotatedElement element) {
final Version usedVersion = UsedVersion.getVersion(annotation.inContainer());
if (annotation.min().isBlank() || usedVersion.compareTo(Version.parse(annotation.min())) >= 0) {
if (annotation.max().isBlank() || usedVersion.compareTo(Version.parse(annotation.max())) <= 0) {
return enabled(format(
"%s is enabled as Mandrel version %s does satisfy constraints: minVersion: %s, maxVersion: %s",
element, usedVersion.toString(), annotation.min(), annotation.max()));
}
boolean jdkConstraintSatisfied = true;
if (!annotation.minJDK().isBlank() || !annotation.maxJDK().isBlank()) {
final int[] jdkVersion = new int[]{
UsedVersion.jdkFeature(annotation.inContainer()),
UsedVersion.jdkInterim(annotation.inContainer()),
UsedVersion.jdkUpdate(annotation.inContainer())
};
final Pattern p = Pattern.compile("(?<jfeature>[0-9]+)(\\.(?<jinterim>[0-9]*)\\.(?<jupdate>[0-9]*))?");
final int[] min = featureInterimUpdate(p, annotation.minJDK(), Integer.MIN_VALUE);
final int[] max = featureInterimUpdate(p, annotation.maxJDK(), Integer.MAX_VALUE);
jdkConstraintSatisfied = compareJDKVersion(jdkVersion, min) >= 0 && compareJDKVersion(jdkVersion, max) <= 0;
}
final boolean mandrelConstraintSatisfied =
(annotation.min().isBlank() || usedVersion.compareTo(Version.parse(annotation.min())) >= 0) &&
(annotation.max().isBlank() || usedVersion.compareTo(Version.parse(annotation.max())) <= 0);
if (mandrelConstraintSatisfied && jdkConstraintSatisfied) {
return enabled(format(
"%s is enabled as Mandrel version %s does satisfy constraints: min: %s, max: %s, minJDK: %s, maxJDK: %s",
element, usedVersion.toString(), annotation.min(), annotation.max(), annotation.minJDK(), annotation.maxJDK()));
}
return disabled(format(
"%s is disabled as Mandrel version %s does not satisfy constraints: minVersion: %s, maxVersion: %s",
element, usedVersion, annotation.min(), annotation.max()));
"%s is disabled as Mandrel version %s does not satisfy constraints: min: %s, max: %s, minJDK: %s, maxJDK: %s",
element, usedVersion, annotation.min(), annotation.max(), annotation.minJDK(), annotation.maxJDK()));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class QuarkusVersion implements Comparable<QuarkusVersion> {
private final int major;
private final int minor;
private final int patch;
private boolean snapshot;
private final boolean snapshot;

public QuarkusVersion(String version) {
this.version = version;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
* @author Michal Karm Babacek <karm@redhat.com>
*/
public class UsedVersion {
private static final int UNDEFINED = -1;

public static Version getVersion(boolean inContainer) {
return inContainer ? InContainer.mVersion.version : Locally.mVersion.version;
Expand All @@ -75,8 +76,8 @@ public static int jdkUpdate(boolean inContainer) {
*/
private static final class MVersion {
private static final Logger LOGGER = Logger.getLogger(MVersion.class.getName());
private static final Pattern VERSION_PATTERN =
Pattern.compile("(?:GraalVM|native-image)(?: Version)? ([^ ]*).*Java Version ([\\d]+)\\.([\\d]+)\\.([\\d]+).*");
private static final Pattern VERSION_PATTERN = Pattern.compile(
"(?:GraalVM|native-image)(?: Version)? (?<version>[^ ]*).*Java Version (?<jfeature>[\\d]+)\\.(?<jinterim>[\\d]+)\\.(?<jupdate>[\\d]+).*");

private final Version version;
private final boolean jdkUsesSysLibs;
Expand All @@ -98,7 +99,8 @@ public MVersion(boolean inContainer) {
final String[] lines = out.split(System.lineSeparator());
lastLine = lines[lines.length - 1].trim();
} else {
final List<String> cmd = getRunCommand("native-image", "--version");
final String TEST_TESTSUITE_ABSOLUTE_PATH = System.getProperty("FAKE_NATIVE_IMAGE_DIR", "");
final List<String> cmd = getRunCommand(TEST_TESTSUITE_ABSOLUTE_PATH + "native-image", "--version");
LOGGER.info("Running command " + cmd + " to determine Mandrel version used.");
try {
lastLine = Commands.runCommand(cmd).trim();
Expand All @@ -124,10 +126,17 @@ public MVersion(boolean inContainer) {
"Output: '" + lastLine + "'");
}
}
version = versionParse(m.group(1));
jdkFeature = Integer.parseInt(m.group(2));
jdkInterim = Integer.parseInt(m.group(3));
jdkUpdate = Integer.parseInt(m.group(4));
version = versionParse(m.group("version"));
final String jFeature = m.group("jfeature");
final String jInterim = m.group("jinterim");
final String jUpdate = m.group("jupdate");
jdkFeature = jFeature == null ? UNDEFINED : Integer.parseInt(jFeature);
jdkInterim = jInterim == null ? UNDEFINED : Integer.parseInt(jInterim);
jdkUpdate = jUpdate == null ? UNDEFINED : Integer.parseInt(jUpdate);
if (jdkFeature == UNDEFINED) {
LOGGER.warn("Failed to correctly parse Java feature (major) version from native-image version command output. " +
"JDK version constraints in tests won't work reliably.");
}
LOGGER.infof("The test suite runs with Mandrel version %s %s, JDK %d.%d.%d.",
version.toString(), inContainer ? "in container" : " installed locally on PATH", jdkFeature, jdkInterim, jdkUpdate);
}
Expand All @@ -149,4 +158,31 @@ private static class Locally {
private static final MVersion mVersion = new MVersion(false);
}

public static int[] featureInterimUpdate(Pattern pattern, String version, int defaultValue) {
final Matcher m = pattern.matcher(version);
if (!m.matches()) {
return new int[]{defaultValue, defaultValue, defaultValue};
}
final String jFeature = m.group("jfeature");
final String jInterim = m.group("jinterim");
final String jUpdate = m.group("jupdate");
return new int[]{
jFeature == null ? defaultValue : Integer.parseInt(jFeature),
jInterim == null ? defaultValue : Integer.parseInt(jInterim),
jUpdate == null ? defaultValue : Integer.parseInt(jUpdate)
};
}

public static int compareJDKVersion(int[] a, int[] b) {
if (a.length != 3 || b.length != 3) {
throw new IllegalArgumentException("3 version elements expected: feature, interim, update");
}
for (int i = 0; i < 3; i++) {
int compare = Integer.compare(a[i], b[i]);
if (compare != 0) {
return compare;
}
}
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package org.graalvm.tests.integration.utils.versions;/*
* Copyright (c) 2022, Red Hat Inc. All rights reserved.
*
* See the NOTICE file(s) distributed with this work for additional
* information regarding copyright ownership.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

import org.graalvm.tests.integration.utils.Logs;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;

import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.PosixFilePermissions;

import static org.graalvm.tests.integration.utils.Commands.IS_THIS_WINDOWS;
import static org.junit.jupiter.api.Assertions.assertEquals;

/**
* Testing test suite...
*
* A fake native-image executable script is created, it contains a single version string.
* Using the property FAKE_NATIVE_IMAGE_DIR, the test suite is tricked into running it
* during native-image version resolution.
* A series of test methods is executed by JUnit, business as usual. Those test methods log
* their executing into a file.
* After all tests are done, the file is examined. If it contains any superfluous entries
* or if it's missing anything, the test lass fails.
*/
@Tag("testing-testsuite")
public class VersionsTest {
static final Path NATIVE_IMAGE = Path.of(System.getProperty("java.io.tmpdir"), IS_THIS_WINDOWS ? "native-image.cmd" : "native-image");
static final String VERSION = "native-image 22.2.0-devdb26f5c4fbe Mandrel Distribution (Java Version 17.0.3-beta+5-202203292328)";
static final Path LOG = Path.of(System.getProperty("java.io.tmpdir"), "versions-log");
static final StandardOpenOption[] LOG_FILE_OPS = new StandardOpenOption[]{StandardOpenOption.CREATE, StandardOpenOption.APPEND, StandardOpenOption.WRITE};

@BeforeAll
public static void setup() throws IOException {
System.setProperty("FAKE_NATIVE_IMAGE_DIR", System.getProperty("java.io.tmpdir") + File.separator);
Files.writeString(NATIVE_IMAGE, IS_THIS_WINDOWS ?
"@echo off" + System.lineSeparator() +
"echo " + VERSION + System.lineSeparator() :
"#!/bin/sh" + System.lineSeparator() +
"echo '" + VERSION + "'" + System.lineSeparator(),
StandardCharsets.UTF_8, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE);
if(!IS_THIS_WINDOWS) {
Files.setPosixFilePermissions(NATIVE_IMAGE, PosixFilePermissions.fromString("rwxr-xr-x"));
}
Files.deleteIfExists(LOG);
}

@AfterAll
public static void teardown() throws IOException {
System.clearProperty("FAKE_NATIVE_IMAGE_DIR");
Files.deleteIfExists(NATIVE_IMAGE);
final String testlog = Files.readString(LOG, StandardCharsets.UTF_8);
try {
assertEquals(
"Running test jdkVersionCheckA\n" +
"Running test jdkVersionCheckB\n" +
"Running test jdkVersionCheckC\n" +
"Running test jdkVersionCheckD\n" +
"Running test jdkVersionCheckI\n", testlog);
} finally {
Logs.archiveLog(VersionsTest.class.getCanonicalName(), "versionTest", LOG.toFile());
Files.deleteIfExists(LOG);
}
}

@Test
@Order(1)
@IfMandrelVersion(min = "21.3.1")
public void jdkVersionCheckA(TestInfo testInfo) throws IOException {
Files.writeString(LOG, "Running test " + testInfo.getTestMethod().get().getName() + "\n", StandardCharsets.UTF_8, LOG_FILE_OPS);
}

@Test
@Order(2)
@IfMandrelVersion(min = "21.3.1", minJDK = "17")
public void jdkVersionCheckB(TestInfo testInfo) throws IOException {
Files.writeString(LOG, "Running test " + testInfo.getTestMethod().get().getName() + "\n", StandardCharsets.UTF_8, LOG_FILE_OPS);
}

@Test
@Order(3)
@IfMandrelVersion(min = "22", minJDK = "17")
public void jdkVersionCheckC(TestInfo testInfo) throws IOException {
Files.writeString(LOG, "Running test " + testInfo.getTestMethod().get().getName() + "\n", StandardCharsets.UTF_8, LOG_FILE_OPS);
}

@Test
@Order(4)
@IfMandrelVersion(min = "22", minJDK = "17.0.2")
public void jdkVersionCheckD(TestInfo testInfo) throws IOException {
Files.writeString(LOG, "Running test " + testInfo.getTestMethod().get().getName() + "\n", StandardCharsets.UTF_8, LOG_FILE_OPS);
}

@Test
@Order(5)
@IfMandrelVersion(min = "22", minJDK = "17", maxJDK = "17.0.2")
public void jdkVersionCheckE(TestInfo testInfo) throws IOException {
Files.writeString(LOG, "Running test " + testInfo.getTestMethod().get().getName() + "\n", StandardCharsets.UTF_8, LOG_FILE_OPS);
}

@Test
@Order(6)
@IfMandrelVersion(min = "21", minJDK = "11.0.12", maxJDK = "17.0.1")
public void jdkVersionCheckF(TestInfo testInfo) throws IOException {
Files.writeString(LOG, "Running test " + testInfo.getTestMethod().get().getName() + "\n", StandardCharsets.UTF_8, LOG_FILE_OPS);
}

@Test
@Order(7)
@IfMandrelVersion(min = "21", maxJDK = "11")
public void jdkVersionCheckG(TestInfo testInfo) throws IOException {
Files.writeString(LOG, "Running test " + testInfo.getTestMethod().get().getName() + "\n", StandardCharsets.UTF_8, LOG_FILE_OPS);
}

@Test
@Order(8)
@IfMandrelVersion(min = "21.2", minJDK = "18.0.0")
public void jdkVersionCheckH(TestInfo testInfo) throws IOException {
Files.writeString(LOG, "Running test " + testInfo.getTestMethod().get().getName() + "\n", StandardCharsets.UTF_8, LOG_FILE_OPS);
}

@Test
@Order(9)
@IfMandrelVersion(min = "22", max = "22.2", minJDK = "17.0.1", maxJDK = "17.0.3")
public void jdkVersionCheckI(TestInfo testInfo) throws IOException {
Files.writeString(LOG, "Running test " + testInfo.getTestMethod().get().getName() + "\n", StandardCharsets.UTF_8, LOG_FILE_OPS);
}

}

0 comments on commit cf047ae

Please sign in to comment.