From d4d2392bbcf6581f38f23dc4bd0a801347f77ee5 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Fri, 22 Sep 2023 20:48:49 +0300 Subject: [PATCH 1/3] Check for code usage fluctuations in native images This aims to aid in detecting code usage fluctuations as early as possible. I set the threshold to 3% which might be a bit tight. Ideally most (if not all) ITs being tested in native mode should include such checks. This way when a dependency gets updated and brings in more bloat, or a GraalVM change results in more code becoming reachable we will be able to notice. If significant fluctuations between GraalVM/Mandrel versions are detected the annotations `@DisableIfBuiltWithGraalVMOlderThan` and `@DisableIfBuiltWithGraalVMNewerThan` may be used to run tests with different properties files. The properties files can be generated by running the following script, passing the build output json file as the first parameter and the path to the target properties file as the second parameter (it will be overwritten), after a failed run. This way enabling the check for a new integration test is a matter of: 1. copying `ImageMetricsITCase.java` in the corresponding folder 2. running the test once 3. running the following script passing the build output json file as the first parameter. ```bash KEYS=( \ image_details.total_bytes \ analysis_results.types.reachable \ analysis_results.methods.reachable \ analysis_results.fields.reachable \ analysis_results.types.reflection \ analysis_results.methods.reflection \ analysis_results.fields.reflection \ analysis_results.types.jni \ analysis_results.methods.jni \ analysis_results.fields.jni \ ) echo "# Properties file used by ImageMetricsITCase" > $2 for i in $KEYS do echo "$i=$(jq .$i $1) >> $2 echo "$i.tolerance=3 >> $2 done ``` --- .../it/jpa/postgresql/ImageMetricsITCase.java | 15 +++ .../resources/image-metrics-test.properties | 20 ++++ .../it/jpa/postgresql/ImageMetricsITCase.java | 15 +++ .../resources/image-metrics-test.properties | 20 ++++ .../quarkus/it/main/ImageMetricsITCase.java | 15 +++ .../resources/image-metrics-test.properties | 23 ++++ .../test/junit/nativeimage/BuildOutput.java | 106 ++++++++++++++++++ 7 files changed, 214 insertions(+) create mode 100644 integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java create mode 100644 integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics-test.properties create mode 100644 integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java create mode 100644 integration-tests/jpa-postgresql/src/test/resources/image-metrics-test.properties create mode 100644 integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java create mode 100644 integration-tests/main/src/test/resources/image-metrics-test.properties create mode 100644 test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutput.java diff --git a/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java b/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java new file mode 100644 index 0000000000000..5d87c443803d7 --- /dev/null +++ b/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java @@ -0,0 +1,15 @@ +package io.quarkus.it.jpa.postgresql; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.quarkus.test.junit.nativeimage.BuildOutput; + +@QuarkusIntegrationTest +public class ImageMetricsITCase { + @Test + public void verifyImageMetrics() { + BuildOutput buildOutput = new BuildOutput(); + buildOutput.verifyImageMetrics(); + } +} diff --git a/integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics-test.properties b/integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics-test.properties new file mode 100644 index 0000000000000..a0bf29ad7a012 --- /dev/null +++ b/integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics-test.properties @@ -0,0 +1,20 @@ +image_details.total_bytes=81172328 +image_details.total_bytes.tolerance=3 +analysis_results.types.reachable=18854 +analysis_results.types.reachable.tolerance=3 +analysis_results.methods.reachable=93385 +analysis_results.methods.reachable.tolerance=3 +analysis_results.fields.reachable=28156 +analysis_results.fields.reachable.tolerance=3 +analysis_results.types.reflection=5978 +analysis_results.types.reflection.tolerance=3 +analysis_results.methods.reflection=4107 +analysis_results.methods.reflection.tolerance=3 +analysis_results.fields.reflection=127 +analysis_results.fields.reflection.tolerance=3 +analysis_results.types.jni=63 +analysis_results.types.jni.tolerance=1 +analysis_results.methods.jni=55 +analysis_results.methods.jni.tolerance=1 +analysis_results.fields.jni=68 +analysis_results.fields.jni.tolerance=1 diff --git a/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java b/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java new file mode 100644 index 0000000000000..5d87c443803d7 --- /dev/null +++ b/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java @@ -0,0 +1,15 @@ +package io.quarkus.it.jpa.postgresql; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.quarkus.test.junit.nativeimage.BuildOutput; + +@QuarkusIntegrationTest +public class ImageMetricsITCase { + @Test + public void verifyImageMetrics() { + BuildOutput buildOutput = new BuildOutput(); + buildOutput.verifyImageMetrics(); + } +} diff --git a/integration-tests/jpa-postgresql/src/test/resources/image-metrics-test.properties b/integration-tests/jpa-postgresql/src/test/resources/image-metrics-test.properties new file mode 100644 index 0000000000000..4876a11f791e2 --- /dev/null +++ b/integration-tests/jpa-postgresql/src/test/resources/image-metrics-test.properties @@ -0,0 +1,20 @@ +image_details.total_bytes=72185704 +image_details.total_bytes.tolerance=3 +analysis_results.types.reachable=17905 +analysis_results.types.reachable.tolerance=3 +analysis_results.methods.reachable=87856 +analysis_results.methods.reachable.tolerance=3 +analysis_results.fields.reachable=25370 +analysis_results.fields.reachable.tolerance=3 +analysis_results.types.reflection=5659 +analysis_results.types.reflection.tolerance=3 +analysis_results.methods.reflection=4200 +analysis_results.methods.reflection.tolerance=3 +analysis_results.fields.reflection=154 +analysis_results.fields.reflection.tolerance=3 +analysis_results.types.jni=63 +analysis_results.types.jni.tolerance=1 +analysis_results.methods.jni=55 +analysis_results.methods.jni.tolerance=1 +analysis_results.fields.jni=68 +analysis_results.fields.jni.tolerance=1 diff --git a/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java b/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java new file mode 100644 index 0000000000000..f904c97fe3823 --- /dev/null +++ b/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java @@ -0,0 +1,15 @@ +package io.quarkus.it.main; + +import org.junit.jupiter.api.Test; + +import io.quarkus.test.junit.QuarkusIntegrationTest; +import io.quarkus.test.junit.nativeimage.BuildOutput; + +@QuarkusIntegrationTest +public class ImageMetricsITCase { + @Test + public void verifyImageMetrics() { + BuildOutput buildOutput = new BuildOutput(); + buildOutput.verifyImageMetrics(); + } +} diff --git a/integration-tests/main/src/test/resources/image-metrics-test.properties b/integration-tests/main/src/test/resources/image-metrics-test.properties new file mode 100644 index 0000000000000..667e9b4cb408d --- /dev/null +++ b/integration-tests/main/src/test/resources/image-metrics-test.properties @@ -0,0 +1,23 @@ +image_details.total_bytes=138778008 +image_details.total_bytes.tolerance=3 +# TODO: Switch to using analysis_results.types.reachable key once we drop support for GraalVM 22.3.0 +analysis_results.classes.reachable=30005 +analysis_results.classes.reachable.tolerance=3 +analysis_results.methods.reachable=149440 +analysis_results.methods.reachable.tolerance=3 +analysis_results.fields.reachable=44161 +analysis_results.fields.reachable.tolerance=3 +# TODO: Switch to using analysis_results.types.reflection key once we drop support for GraalVM 22.3.0 +analysis_results.classes.reflection=8966 +analysis_results.classes.reflection.tolerance=3 +analysis_results.methods.reflection=7346 +analysis_results.methods.reflection.tolerance=3 +analysis_results.fields.reflection=438 +analysis_results.fields.reflection.tolerance=3 +# TODO: Switch to using analysis_results.types.jni key once we drop support for GraalVM 22.3.0 +analysis_results.classes.jni=64 +analysis_results.classes.jni.tolerance=1 +analysis_results.methods.jni=55 +analysis_results.methods.jni.tolerance=1 +analysis_results.fields.jni=70 +analysis_results.fields.jni.tolerance=1 diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutput.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutput.java new file mode 100644 index 0000000000000..e1091aba18d91 --- /dev/null +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutput.java @@ -0,0 +1,106 @@ +package io.quarkus.test.junit.nativeimage; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Locale; +import java.util.Properties; + +import jakarta.json.Json; +import jakarta.json.JsonObject; + +import org.junit.jupiter.api.Assertions; + +/** + * This is a general utility to assert via + * unit testing how many classes, methods, objects etc. have been included in a native-image. + *

+ * For detailed information and explanations on the build output, visit + * the upstream GraalVM + * documentation. + */ +public class BuildOutput { + + private static final String IMAGE_METRICS_TEST_PROPERTIES = "image-metrics-test.properties"; + private final JsonObject buildOutput; + + public BuildOutput() { + this.buildOutput = getBuildOutput(); + } + + public void verifyImageMetrics() { + verifyImageMetrics(IMAGE_METRICS_TEST_PROPERTIES); + } + + public void verifyImageMetrics(String propertiesFileName) { + Properties properties = getProperties(propertiesFileName); + + properties.forEach((key, value) -> { + if (((String) key).endsWith(".tolerance")) { + return; + } + String[] keyParts = ((String) key).split("\\."); + String tolerance = properties.getProperty(key + ".tolerance"); + assert tolerance != null : "tolerance not defined for " + key; + assertValueWithinRange(Integer.parseInt((String) value), Integer.parseInt(tolerance), keyParts); + }); + } + + private Properties getProperties(String propertiesFileName) { + Properties properties = new Properties(); + try { + properties.load(getClass().getClassLoader().getResourceAsStream(propertiesFileName)); + } catch (IOException e) { + Assertions.fail("Could not load properties from " + propertiesFileName, e); + } + return properties; + } + + private void assertValueWithinRange(int expectedValue, int tolerancePercentage, String... key) { + JsonObject currentObject = buildOutput; + for (int i = 0; i < key.length - 1; i++) { + currentObject = currentObject.getJsonObject(key[i]); + } + String lastKey = key[key.length - 1]; + int actualValue = currentObject.getInt(lastKey); + Assertions.assertTrue(isNumberWithinRange(expectedValue, actualValue, tolerancePercentage), + "Expected " + String.join(".", key) + " to be within range [" + expectedValue + " +- " + tolerancePercentage + + "%] but was " + actualValue); + } + + private boolean isNumberWithinRange(int expectedNumberOfClasses, int actualNumberOfClasses, int tolerancePercentage) { + final int lowerBound = expectedNumberOfClasses - (expectedNumberOfClasses * tolerancePercentage / 100); + final int upperBound = expectedNumberOfClasses + (expectedNumberOfClasses * tolerancePercentage / 100); + return actualNumberOfClasses >= lowerBound && actualNumberOfClasses <= upperBound; + } + + private static JsonObject getBuildOutput() { + final Path buildOutputPath = getBuildOutputPath(); + try (InputStream inputStream = Files.newInputStream(buildOutputPath)) { + return Json.createReader(inputStream).readObject(); + } catch (Exception e) { + throw new RuntimeException("Could not load build output", e); + } + } + + private static Path getBuildOutputPath() { + final Path buildDirectory = locateNativeImageBuildDirectory(); + final File[] buildOutput = buildDirectory.toFile().listFiles((dir, name) -> name.toLowerCase(Locale.ROOT) + .endsWith("-build-output-stats.json")); + Assertions.assertNotNull(buildOutput, "Could not identify the native image build output"); + Assertions.assertEquals(1, buildOutput.length, "Could not identify the native image build output"); + return buildOutput[0].toPath(); + } + + private static Path locateNativeImageBuildDirectory() { + Path buildPath = Paths.get("target"); + final File[] files = buildPath.toFile().listFiles((dir, name) -> name.toLowerCase(Locale.ROOT) + .endsWith("-native-image-source-jar")); + Assertions.assertNotNull(files, "Could not identify the native image build directory"); + Assertions.assertEquals(1, files.length, "Could not identify the native image build directory"); + return files[0].toPath(); + } +} From 612d8169ebfeb1e082b499c910474934554e9a60 Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Tue, 28 Nov 2023 21:27:08 +0200 Subject: [PATCH 2/3] Add support for different thresholds per GraalVM version `ImageMetricsITCase` tests are skipped for versions with undefined thresholds --- .../quarkus/deployment/pkg/steps/GraalVM.java | 7 ++++ .../it/jpa/postgresql/ImageMetricsITCase.java | 6 ++- .../23.0/image-metrics.properties} | 15 +++---- .../23.1/image-metrics.properties | 21 ++++++++++ .../it/jpa/postgresql/ImageMetricsITCase.java | 7 +++- .../23.0/image-metrics.properties} | 15 +++---- .../23.1/image-metrics.properties | 21 ++++++++++ .../quarkus/it/main/ImageMetricsITCase.java | 6 ++- .../23.0/image-metrics.properties | 21 ++++++++++ .../23.1/image-metrics.properties} | 19 +++++---- .../test/junit/IntegrationTestUtil.java | 2 +- ...dOutput.java => BuildOutputExtension.java} | 42 ++++++++++++++++--- 12 files changed, 147 insertions(+), 35 deletions(-) rename integration-tests/jpa-postgresql-withxml/src/test/resources/{image-metrics-test.properties => image-metrics/23.0/image-metrics.properties} (62%) create mode 100644 integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics/23.1/image-metrics.properties rename integration-tests/jpa-postgresql/src/test/resources/{image-metrics-test.properties => image-metrics/23.0/image-metrics.properties} (62%) create mode 100644 integration-tests/jpa-postgresql/src/test/resources/image-metrics/23.1/image-metrics.properties create mode 100644 integration-tests/main/src/test/resources/image-metrics/23.0/image-metrics.properties rename integration-tests/main/src/test/resources/{image-metrics-test.properties => image-metrics/23.1/image-metrics.properties} (66%) rename test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/{BuildOutput.java => BuildOutputExtension.java} (69%) diff --git a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/GraalVM.java b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/GraalVM.java index 6b9be123db6b3..1b212a0369006 100644 --- a/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/GraalVM.java +++ b/core/deployment/src/main/java/io/quarkus/deployment/pkg/steps/GraalVM.java @@ -297,6 +297,13 @@ public String getVersionAsString() { return version; } + public String getMajorMinorAsString() { + if (versions.length >= 2) { + return versions[0] + "." + versions[1]; + } + return versions[0] + ".0"; + } + @Override public String toString() { return "Version{" + diff --git a/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java b/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java index 5d87c443803d7..52edc45b5ae5b 100644 --- a/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java +++ b/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java @@ -1,15 +1,17 @@ package io.quarkus.it.jpa.postgresql; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import io.quarkus.test.junit.QuarkusIntegrationTest; -import io.quarkus.test.junit.nativeimage.BuildOutput; +import io.quarkus.test.junit.nativeimage.BuildOutputExtension; +@ExtendWith(BuildOutputExtension.class) @QuarkusIntegrationTest public class ImageMetricsITCase { @Test public void verifyImageMetrics() { - BuildOutput buildOutput = new BuildOutput(); + BuildOutputExtension buildOutput = new BuildOutputExtension(); buildOutput.verifyImageMetrics(); } } diff --git a/integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics-test.properties b/integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics/23.0/image-metrics.properties similarity index 62% rename from integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics-test.properties rename to integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics/23.0/image-metrics.properties index a0bf29ad7a012..8795ff6bf212a 100644 --- a/integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics-test.properties +++ b/integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics/23.0/image-metrics.properties @@ -1,16 +1,17 @@ -image_details.total_bytes=81172328 +# Properties file used by ImageMetricsITCase +image_details.total_bytes=86417288 image_details.total_bytes.tolerance=3 -analysis_results.types.reachable=18854 +analysis_results.types.reachable=20067 analysis_results.types.reachable.tolerance=3 -analysis_results.methods.reachable=93385 +analysis_results.methods.reachable=99493 analysis_results.methods.reachable.tolerance=3 -analysis_results.fields.reachable=28156 +analysis_results.fields.reachable=29845 analysis_results.fields.reachable.tolerance=3 -analysis_results.types.reflection=5978 +analysis_results.types.reflection=6394 analysis_results.types.reflection.tolerance=3 -analysis_results.methods.reflection=4107 +analysis_results.methods.reflection=4580 analysis_results.methods.reflection.tolerance=3 -analysis_results.fields.reflection=127 +analysis_results.fields.reflection=143 analysis_results.fields.reflection.tolerance=3 analysis_results.types.jni=63 analysis_results.types.jni.tolerance=1 diff --git a/integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics/23.1/image-metrics.properties b/integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics/23.1/image-metrics.properties new file mode 100644 index 0000000000000..a40ab0e9d5ca8 --- /dev/null +++ b/integration-tests/jpa-postgresql-withxml/src/test/resources/image-metrics/23.1/image-metrics.properties @@ -0,0 +1,21 @@ +# Properties file used by ImageMetricsITCase +image_details.total_bytes=91650760 +image_details.total_bytes.tolerance=3 +analysis_results.types.reachable=20387 +analysis_results.types.reachable.tolerance=3 +analysis_results.methods.reachable=100956 +analysis_results.methods.reachable.tolerance=3 +analysis_results.fields.reachable=29789 +analysis_results.fields.reachable.tolerance=3 +analysis_results.types.reflection=6522 +analysis_results.types.reflection.tolerance=3 +analysis_results.methods.reflection=4682 +analysis_results.methods.reflection.tolerance=3 +analysis_results.fields.reflection=163 +analysis_results.fields.reflection.tolerance=3 +analysis_results.types.jni=61 +analysis_results.types.jni.tolerance=1 +analysis_results.methods.jni=55 +analysis_results.methods.jni.tolerance=1 +analysis_results.fields.jni=59 +analysis_results.fields.jni.tolerance=1 diff --git a/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java b/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java index 5d87c443803d7..a3bd0121316c3 100644 --- a/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java +++ b/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java @@ -1,15 +1,18 @@ package io.quarkus.it.jpa.postgresql; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import io.quarkus.test.junit.QuarkusIntegrationTest; -import io.quarkus.test.junit.nativeimage.BuildOutput; +import io.quarkus.test.junit.nativeimage.BuildOutputExtension; +@ExtendWith(BuildOutputExtension.class) @QuarkusIntegrationTest public class ImageMetricsITCase { + @Test public void verifyImageMetrics() { - BuildOutput buildOutput = new BuildOutput(); + BuildOutputExtension buildOutput = new BuildOutputExtension(); buildOutput.verifyImageMetrics(); } } diff --git a/integration-tests/jpa-postgresql/src/test/resources/image-metrics-test.properties b/integration-tests/jpa-postgresql/src/test/resources/image-metrics/23.0/image-metrics.properties similarity index 62% rename from integration-tests/jpa-postgresql/src/test/resources/image-metrics-test.properties rename to integration-tests/jpa-postgresql/src/test/resources/image-metrics/23.0/image-metrics.properties index 4876a11f791e2..8dd4994f234b8 100644 --- a/integration-tests/jpa-postgresql/src/test/resources/image-metrics-test.properties +++ b/integration-tests/jpa-postgresql/src/test/resources/image-metrics/23.0/image-metrics.properties @@ -1,16 +1,17 @@ -image_details.total_bytes=72185704 +# Properties file used by ImageMetricsITCase +image_details.total_bytes=78626464 image_details.total_bytes.tolerance=3 -analysis_results.types.reachable=17905 +analysis_results.types.reachable=19172 analysis_results.types.reachable.tolerance=3 -analysis_results.methods.reachable=87856 +analysis_results.methods.reachable=95204 analysis_results.methods.reachable.tolerance=3 -analysis_results.fields.reachable=25370 +analysis_results.fields.reachable=27139 analysis_results.fields.reachable.tolerance=3 -analysis_results.types.reflection=5659 +analysis_results.types.reflection=5939 analysis_results.types.reflection.tolerance=3 -analysis_results.methods.reflection=4200 +analysis_results.methods.reflection=4401 analysis_results.methods.reflection.tolerance=3 -analysis_results.fields.reflection=154 +analysis_results.fields.reflection=170 analysis_results.fields.reflection.tolerance=3 analysis_results.types.jni=63 analysis_results.types.jni.tolerance=1 diff --git a/integration-tests/jpa-postgresql/src/test/resources/image-metrics/23.1/image-metrics.properties b/integration-tests/jpa-postgresql/src/test/resources/image-metrics/23.1/image-metrics.properties new file mode 100644 index 0000000000000..4025eb7e8d23b --- /dev/null +++ b/integration-tests/jpa-postgresql/src/test/resources/image-metrics/23.1/image-metrics.properties @@ -0,0 +1,21 @@ +# Properties file used by ImageMetricsITCase +image_details.total_bytes=83036632 +image_details.total_bytes.tolerance=3 +analysis_results.types.reachable=19394 +analysis_results.types.reachable.tolerance=3 +analysis_results.methods.reachable=96465 +analysis_results.methods.reachable.tolerance=3 +analysis_results.fields.reachable=27025 +analysis_results.fields.reachable.tolerance=3 +analysis_results.types.reflection=6048 +analysis_results.types.reflection.tolerance=3 +analysis_results.methods.reflection=4495 +analysis_results.methods.reflection.tolerance=3 +analysis_results.fields.reflection=192 +analysis_results.fields.reflection.tolerance=3 +analysis_results.types.jni=61 +analysis_results.types.jni.tolerance=1 +analysis_results.methods.jni=55 +analysis_results.methods.jni.tolerance=1 +analysis_results.fields.jni=59 +analysis_results.fields.jni.tolerance=1 diff --git a/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java b/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java index f904c97fe3823..bd0beb4d698d0 100644 --- a/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java +++ b/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java @@ -1,15 +1,17 @@ package io.quarkus.it.main; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import io.quarkus.test.junit.QuarkusIntegrationTest; -import io.quarkus.test.junit.nativeimage.BuildOutput; +import io.quarkus.test.junit.nativeimage.BuildOutputExtension; +@ExtendWith(BuildOutputExtension.class) @QuarkusIntegrationTest public class ImageMetricsITCase { @Test public void verifyImageMetrics() { - BuildOutput buildOutput = new BuildOutput(); + BuildOutputExtension buildOutput = new BuildOutputExtension(); buildOutput.verifyImageMetrics(); } } diff --git a/integration-tests/main/src/test/resources/image-metrics/23.0/image-metrics.properties b/integration-tests/main/src/test/resources/image-metrics/23.0/image-metrics.properties new file mode 100644 index 0000000000000..dc00bbc1f4eed --- /dev/null +++ b/integration-tests/main/src/test/resources/image-metrics/23.0/image-metrics.properties @@ -0,0 +1,21 @@ +# Properties file used by ImageMetricsITCase +image_details.total_bytes=139447360 +image_details.total_bytes.tolerance=3 +analysis_results.types.reachable=30117 +analysis_results.types.reachable.tolerance=3 +analysis_results.methods.reachable=150060 +analysis_results.methods.reachable.tolerance=3 +analysis_results.fields.reachable=44502 +analysis_results.fields.reachable.tolerance=3 +analysis_results.types.reflection=8989 +analysis_results.types.reflection.tolerance=3 +analysis_results.methods.reflection=7393 +analysis_results.methods.reflection.tolerance=3 +analysis_results.fields.reflection=438 +analysis_results.fields.reflection.tolerance=3 +analysis_results.types.jni=64 +analysis_results.types.jni.tolerance=1 +analysis_results.methods.jni=55 +analysis_results.methods.jni.tolerance=1 +analysis_results.fields.jni=70 +analysis_results.fields.jni.tolerance=1 diff --git a/integration-tests/main/src/test/resources/image-metrics-test.properties b/integration-tests/main/src/test/resources/image-metrics/23.1/image-metrics.properties similarity index 66% rename from integration-tests/main/src/test/resources/image-metrics-test.properties rename to integration-tests/main/src/test/resources/image-metrics/23.1/image-metrics.properties index 667e9b4cb408d..3e643eb8117a5 100644 --- a/integration-tests/main/src/test/resources/image-metrics-test.properties +++ b/integration-tests/main/src/test/resources/image-metrics/23.1/image-metrics.properties @@ -1,23 +1,24 @@ -image_details.total_bytes=138778008 +# Properties file used by ImageMetricsITCase +image_details.total_bytes=147268552 image_details.total_bytes.tolerance=3 # TODO: Switch to using analysis_results.types.reachable key once we drop support for GraalVM 22.3.0 -analysis_results.classes.reachable=30005 +analysis_results.classes.reachable=30415 analysis_results.classes.reachable.tolerance=3 -analysis_results.methods.reachable=149440 +analysis_results.methods.reachable=151296 analysis_results.methods.reachable.tolerance=3 -analysis_results.fields.reachable=44161 +analysis_results.fields.reachable=44325 analysis_results.fields.reachable.tolerance=3 # TODO: Switch to using analysis_results.types.reflection key once we drop support for GraalVM 22.3.0 -analysis_results.classes.reflection=8966 +analysis_results.classes.reflection=9118 analysis_results.classes.reflection.tolerance=3 -analysis_results.methods.reflection=7346 +analysis_results.methods.reflection=7741 analysis_results.methods.reflection.tolerance=3 -analysis_results.fields.reflection=438 +analysis_results.fields.reflection=480 analysis_results.fields.reflection.tolerance=3 # TODO: Switch to using analysis_results.types.jni key once we drop support for GraalVM 22.3.0 -analysis_results.classes.jni=64 +analysis_results.classes.jni=62 analysis_results.classes.jni.tolerance=1 analysis_results.methods.jni=55 analysis_results.methods.jni.tolerance=1 -analysis_results.fields.jni=70 +analysis_results.fields.jni=61 analysis_results.fields.jni.tolerance=1 diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java index d0642fbf170ec..81d0fd3b41bf1 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/IntegrationTestUtil.java @@ -422,7 +422,7 @@ public void close() { } } - static Properties readQuarkusArtifactProperties(ExtensionContext context) { + public static Properties readQuarkusArtifactProperties(ExtensionContext context) { Path buildOutputDirectory = determineBuildOutputDirectory(context); Path artifactProperties = buildOutputDirectory.resolve("quarkus-artifact.properties"); if (!Files.exists(artifactProperties)) { diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutput.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutputExtension.java similarity index 69% rename from test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutput.java rename to test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutputExtension.java index e1091aba18d91..5be4f78893184 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutput.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutputExtension.java @@ -1,5 +1,7 @@ package io.quarkus.test.junit.nativeimage; +import static io.quarkus.test.junit.IntegrationTestUtil.readQuarkusArtifactProperties; + import java.io.File; import java.io.IOException; import java.io.InputStream; @@ -13,6 +15,11 @@ import jakarta.json.JsonObject; import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.extension.BeforeAllCallback; +import org.junit.jupiter.api.extension.ExtensionContext; + +import io.quarkus.deployment.pkg.steps.GraalVM; /** * This is a general utility to assert via @@ -22,17 +29,21 @@ * the upstream GraalVM * documentation. */ -public class BuildOutput { +public class BuildOutputExtension implements BeforeAllCallback { - private static final String IMAGE_METRICS_TEST_PROPERTIES = "image-metrics-test.properties"; + private static final String IMAGE_METRICS_TEST_PROPERTIES = "image-metrics.properties"; + private static final String IMAGE_METRICS_DIR = "image-metrics"; private final JsonObject buildOutput; + private static GraalVM.Version mandrelVersion; - public BuildOutput() { + public BuildOutputExtension() { this.buildOutput = getBuildOutput(); } public void verifyImageMetrics() { - verifyImageMetrics(IMAGE_METRICS_TEST_PROPERTIES); + String version = mandrelVersion.getMajorMinorAsString(); + String propertiesFileName = IMAGE_METRICS_DIR + "/" + version + "/" + IMAGE_METRICS_TEST_PROPERTIES; + verifyImageMetrics(propertiesFileName); } public void verifyImageMetrics(String propertiesFileName) { @@ -52,7 +63,10 @@ public void verifyImageMetrics(String propertiesFileName) { private Properties getProperties(String propertiesFileName) { Properties properties = new Properties(); try { - properties.load(getClass().getClassLoader().getResourceAsStream(propertiesFileName)); + InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream(propertiesFileName); + Assumptions.assumeTrue(resourceAsStream != null, + "Could not find properties file matching the Mandrel version being used: " + propertiesFileName); + properties.load(resourceAsStream); } catch (IOException e) { Assertions.fail("Could not load properties from " + propertiesFileName, e); } @@ -103,4 +117,22 @@ private static Path locateNativeImageBuildDirectory() { Assertions.assertEquals(1, files.length, "Could not identify the native image build directory"); return files[0].toPath(); } + + @Override + public void beforeAll(ExtensionContext extensionContext) throws Exception { + mandrelVersion = getMandrelVersion(extensionContext); + } + + private GraalVM.Version getMandrelVersion(ExtensionContext context) { + Properties quarkusArtifactProperties = readQuarkusArtifactProperties(context); + String fullVersion = quarkusArtifactProperties.getProperty("metadata.graalvm.version.full"); + try { + return GraalVM.Version.of(fullVersion.lines()); + } catch (NumberFormatException e) { + System.out.println( + "WARNING: Unable to determine the GraalVM version with which the native binary was built. metadata.graalvm.version.full = " + + fullVersion); + return GraalVM.Version.CURRENT; + } + } } From 2e44e78723f90ae41f4209823eb907f9c47a2f1a Mon Sep 17 00:00:00 2001 From: Foivos Zakkak Date: Mon, 11 Dec 2023 18:25:54 +0200 Subject: [PATCH 3/3] Rename `BuildOutputExtension` to `NativeBuildOutputExtension` --- .../io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java | 6 +++--- .../io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java | 6 +++--- .../test/java/io/quarkus/it/main/ImageMetricsITCase.java | 6 +++--- ...OutputExtension.java => NativeBuildOutputExtension.java} | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) rename test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/{BuildOutputExtension.java => NativeBuildOutputExtension.java} (98%) diff --git a/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java b/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java index 52edc45b5ae5b..7928216825aaf 100644 --- a/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java +++ b/integration-tests/jpa-postgresql-withxml/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java @@ -4,14 +4,14 @@ import org.junit.jupiter.api.extension.ExtendWith; import io.quarkus.test.junit.QuarkusIntegrationTest; -import io.quarkus.test.junit.nativeimage.BuildOutputExtension; +import io.quarkus.test.junit.nativeimage.NativeBuildOutputExtension; -@ExtendWith(BuildOutputExtension.class) +@ExtendWith(NativeBuildOutputExtension.class) @QuarkusIntegrationTest public class ImageMetricsITCase { @Test public void verifyImageMetrics() { - BuildOutputExtension buildOutput = new BuildOutputExtension(); + NativeBuildOutputExtension buildOutput = new NativeBuildOutputExtension(); buildOutput.verifyImageMetrics(); } } diff --git a/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java b/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java index a3bd0121316c3..7598509c8bb62 100644 --- a/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java +++ b/integration-tests/jpa-postgresql/src/test/java/io/quarkus/it/jpa/postgresql/ImageMetricsITCase.java @@ -4,15 +4,15 @@ import org.junit.jupiter.api.extension.ExtendWith; import io.quarkus.test.junit.QuarkusIntegrationTest; -import io.quarkus.test.junit.nativeimage.BuildOutputExtension; +import io.quarkus.test.junit.nativeimage.NativeBuildOutputExtension; -@ExtendWith(BuildOutputExtension.class) +@ExtendWith(NativeBuildOutputExtension.class) @QuarkusIntegrationTest public class ImageMetricsITCase { @Test public void verifyImageMetrics() { - BuildOutputExtension buildOutput = new BuildOutputExtension(); + NativeBuildOutputExtension buildOutput = new NativeBuildOutputExtension(); buildOutput.verifyImageMetrics(); } } diff --git a/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java b/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java index bd0beb4d698d0..527b3d840c87d 100644 --- a/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java +++ b/integration-tests/main/src/test/java/io/quarkus/it/main/ImageMetricsITCase.java @@ -4,14 +4,14 @@ import org.junit.jupiter.api.extension.ExtendWith; import io.quarkus.test.junit.QuarkusIntegrationTest; -import io.quarkus.test.junit.nativeimage.BuildOutputExtension; +import io.quarkus.test.junit.nativeimage.NativeBuildOutputExtension; -@ExtendWith(BuildOutputExtension.class) +@ExtendWith(NativeBuildOutputExtension.class) @QuarkusIntegrationTest public class ImageMetricsITCase { @Test public void verifyImageMetrics() { - BuildOutputExtension buildOutput = new BuildOutputExtension(); + NativeBuildOutputExtension buildOutput = new NativeBuildOutputExtension(); buildOutput.verifyImageMetrics(); } } diff --git a/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutputExtension.java b/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/NativeBuildOutputExtension.java similarity index 98% rename from test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutputExtension.java rename to test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/NativeBuildOutputExtension.java index 5be4f78893184..821e4cb8ce66e 100644 --- a/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/BuildOutputExtension.java +++ b/test-framework/junit5/src/main/java/io/quarkus/test/junit/nativeimage/NativeBuildOutputExtension.java @@ -29,14 +29,14 @@ * the upstream GraalVM * documentation. */ -public class BuildOutputExtension implements BeforeAllCallback { +public class NativeBuildOutputExtension implements BeforeAllCallback { private static final String IMAGE_METRICS_TEST_PROPERTIES = "image-metrics.properties"; private static final String IMAGE_METRICS_DIR = "image-metrics"; private final JsonObject buildOutput; private static GraalVM.Version mandrelVersion; - public BuildOutputExtension() { + public NativeBuildOutputExtension() { this.buildOutput = getBuildOutput(); }