From a600410ef56dbca8885cd4bcf2db804578987888 Mon Sep 17 00:00:00 2001 From: "James R. Perkins" Date: Mon, 14 Oct 2024 14:57:36 -0700 Subject: [PATCH 1/3] Refactored the ReleaseTest to be more dynamic and allow testing all available Java release versions based on the runtimes release version. Signed-off-by: James R. Perkins --- tools/sigtest/pom.xml | 26 ++- .../signaturetest/classpath/ReleaseTest.java | 190 +++++++++++------- 2 files changed, 135 insertions(+), 81 deletions(-) diff --git a/tools/sigtest/pom.xml b/tools/sigtest/pom.xml index 3ce03e4a2..da7b487b9 100644 --- a/tools/sigtest/pom.xml +++ b/tools/sigtest/pom.xml @@ -247,6 +247,17 @@ + + + + org.junit + junit-bom + 5.11.2 + pom + import + + + org.apache.maven @@ -298,16 +309,19 @@ - - org.junit.jupiter - junit-jupiter-engine - 5.10.2 - test + + org.junit.jupiter + junit-jupiter-engine + test org.junit.vintage junit-vintage-engine - 5.10.2 + test + + + org.junit.jupiter + junit-jupiter-params test diff --git a/tools/sigtest/src/test/java/com/sun/tdk/signaturetest/classpath/ReleaseTest.java b/tools/sigtest/src/test/java/com/sun/tdk/signaturetest/classpath/ReleaseTest.java index ec08d501a..b402ec762 100644 --- a/tools/sigtest/src/test/java/com/sun/tdk/signaturetest/classpath/ReleaseTest.java +++ b/tools/sigtest/src/test/java/com/sun/tdk/signaturetest/classpath/ReleaseTest.java @@ -24,98 +24,138 @@ */ package com.sun.tdk.signaturetest.classpath; -import com.sun.tdk.signaturetest.loaders.BinaryClassDescrLoader; -import com.sun.tdk.signaturetest.model.ClassDescription; -import com.sun.tdk.signaturetest.model.MethodDescr; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; import java.util.Arrays; +import java.util.HashMap; import java.util.HashSet; +import java.util.List; +import java.util.Map; import java.util.Set; -import org.junit.Test; -import static org.junit.Assert.*; +import java.util.stream.Stream; -public class ReleaseTest { - - public ReleaseTest() { - } +import com.sun.tdk.signaturetest.loaders.BinaryClassDescrLoader; +import com.sun.tdk.signaturetest.model.ClassDescription; +import com.sun.tdk.signaturetest.model.MethodDescr; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; - @Test - public void testFindJDK8() throws ClassNotFoundException { - Release jdk8 = Release.find(8); - assertNotNull(jdk8.findClass("java.lang.Object")); - assertNull(jdk8.findClass("java.lang.Module")); +public class ReleaseTest { - BinaryClassDescrLoader loader = new BinaryClassDescrLoader(new ClasspathImpl(jdk8, null), 4096); - ClassDescription deprecatedClass = loader.load("java.lang.Deprecated"); - assertMethods(deprecatedClass); + @ParameterizedTest + @MethodSource("jdkParameters") + public void verifyJdk(final int version, final List expectedTypes, final List unexpectedTypes, final Map> methodChecks) throws Exception { + final Release release = Release.find(version); + Assertions.assertNotNull(release, () -> "Failed to find release version " + version); + for (String expectedType : expectedTypes) { + assertNotNull(release.findClass(expectedType), () -> String.format("Failed to find class %s in Java %d", expectedType, version)); + } + for (String unexpectedType : unexpectedTypes) { + assertNull(release.findClass(unexpectedType), () -> String.format("Did not expect to find type %s in Java %d", unexpectedType, version)); + } + if (!methodChecks.isEmpty()) { + final BinaryClassDescrLoader loader = new BinaryClassDescrLoader(new ClasspathImpl(release, null), 4096); + for (var entry : methodChecks.entrySet()) { + final ClassDescription classDescription = loader.load(entry.getKey()); + Assertions.assertNotNull(classDescription, () -> String.format("Failed to find class %s in Java %d", entry.getKey(), version)); + assertMethods(classDescription, entry.getValue()); + } + } } - @Test - public void testFindJDK9() throws ClassNotFoundException { - Release jdk9 = Release.find(9); - assertNotNull(jdk9.findClass("java.lang.Object")); - assertNotNull(jdk9.findClass("java.lang.Module")); - assertNull(jdk9.findClass("java.lang.Record")); - - BinaryClassDescrLoader loader = new BinaryClassDescrLoader(new ClasspathImpl(jdk9, null), 4096); - ClassDescription deprecatedClass = loader.load("java.lang.Deprecated"); - assertMethods(deprecatedClass, "forRemoval", "since"); + private static Stream jdkParameters() { + final List jdkParameters = new ArrayList<>(); + final int currentVersion = Runtime.version().feature(); + final int minVersion = discoverMinimumVersion(); + for (int i = currentVersion; i >= minVersion; i--) { + final List expectedTypes = new ArrayList<>(); + final List unexpectedTypes = new ArrayList<>(); + final Map> methodChecks = new HashMap<>(); + expectedTypes.add("java.lang.Object"); + if (i == 8) { + unexpectedTypes.add("java.lang.Module"); + methodChecks.put("java.lang.Deprecated", List.of()); + } else { + expectedTypes.add("java.lang.Module"); + methodChecks.put("java.lang.Deprecated", List.of("forRemoval", "since")); + } + if (i > 13) { + expectedTypes.add("java.lang.Record"); + } else { + unexpectedTypes.add("java.lang.Record"); + } + + if (i > 16) { + expectedTypes.add("java.util.random.RandomGeneratorFactory"); + } else { + unexpectedTypes.add("java.util.random.RandomGeneratorFactory"); + } + + if (i > 20) { + expectedTypes.add("java.util.SequencedCollection"); + } else { + unexpectedTypes.add("java.util.SequencedCollection"); + } + + + jdkParameters.add(Arguments.of(i, List.copyOf(expectedTypes), List.copyOf(unexpectedTypes), Map.copyOf(methodChecks))); + } + return jdkParameters.stream(); } - @Test - public void testFindJDK13() throws ClassNotFoundException { - Release jdk13 = Release.find(13); - assertNotNull(jdk13.findClass("java.lang.Object")); - assertNotNull(jdk13.findClass("java.lang.Module")); - assertNull(jdk13.findClass("java.lang.Record")); - - BinaryClassDescrLoader loader = new BinaryClassDescrLoader(new ClasspathImpl(jdk13, null), 4096); - ClassDescription deprecatedClass = loader.load("java.lang.Deprecated"); - assertMethods(deprecatedClass, "forRemoval", "since"); - } + private void assertMethods(final ClassDescription deprecatedClass, final List names) { + MethodDescr[] arr = deprecatedClass.getDeclaredMethods(); + assertEquals(names.size(), arr.length, () -> "Same number of methods: " + Arrays.toString(arr)); - @Test - public void testFindJDK14() { - Release jdk14 = Release.find(14); - assertNotNull(jdk14.findClass("java.lang.Object")); - assertNotNull(jdk14.findClass("java.lang.Module")); - assertNotNull(jdk14.findClass("java.lang.Record")); - } + Set all = new HashSet<>(names); + for (MethodDescr m : arr) { + all.remove(m.getName()); + } - @Test - public void testFindJDK15() throws ClassNotFoundException { - Release jdk15 = Release.find(15); - assertNotNull(jdk15.findClass("java.lang.Object")); - assertNotNull(jdk15.findClass("java.lang.Module")); - assertNotNull(jdk15.findClass("java.lang.Record")); - BinaryClassDescrLoader loader = new BinaryClassDescrLoader(new ClasspathImpl(jdk15, null), 4096); - ClassDescription deprecatedClass = loader.load("java.lang.Deprecated"); - assertMethods(deprecatedClass, "forRemoval", "since"); + assertEquals(0, all.size(), () -> "Not found methods " + all); } - @Test - public void testFindJDK17() throws ClassNotFoundException { - Release jdk17 = Release.find(17); - assertNotNull(jdk17.findClass("java.lang.Object")); - assertNotNull(jdk17.findClass("java.lang.Module")); - assertNotNull(jdk17.findClass("java.lang.Record")); - assertNotNull(jdk17.findClass("java.util.random.RandomGeneratorFactory")); - BinaryClassDescrLoader loader = new BinaryClassDescrLoader(new ClasspathImpl(jdk17, null), 4096); - ClassDescription deprecatedClass = loader.load("java.lang.Deprecated"); - assertMethods(deprecatedClass, "forRemoval", "since"); + private static int discoverMinimumVersion() { + for (int version = 8; version <= Runtime.version().feature(); version++) { + if (isAvailableRelease(version)) { + return version; + } + } + return Runtime.version().feature(); } - private void assertMethods(ClassDescription deprecatedClass, String... names) { - MethodDescr[] arr = deprecatedClass.getDeclaredMethods(); - assertEquals("Same number of methods: " + Arrays.toString(arr), names.length, arr.length); - - Set all = new HashSet<>(Arrays.asList(names)); - for (int i = 0; i < arr.length; i++) { - MethodDescr m = arr[i]; - all.remove(m.getName()); + private static boolean isAvailableRelease(final int version) { + // Use the process builder to invoke javac to ensure the --release version is available + final ProcessBuilder pb = new ProcessBuilder("javac", "--release", Integer.toString(version), "--version") + .redirectErrorStream(true); + Process process; + try { + process = pb.start(); + final InputStream in = pb.start().getInputStream(); + final ByteArrayOutputStream baos = new ByteArrayOutputStream(); + final Thread consumer = new Thread(() -> { + try { + final byte[] buffer = new byte[1024]; + int len; + while ((len = in.read(buffer)) != -1) { + baos.write(buffer, 0, len); + } + } catch (IOException ignore) {} + }); + consumer.setDaemon(true); + consumer.start(); + return process.waitFor() == 0; + } catch (IOException | InterruptedException ignored) { + return false; } - - assertEquals("Not found methods " + all, 0, all.size()); } - } From 610389d6e3b5dfcea042036a607afd031079f309 Mon Sep 17 00:00:00 2001 From: "James R. Perkins" Date: Mon, 14 Oct 2024 14:58:51 -0700 Subject: [PATCH 2/3] [35] Do not fail if a version of a Release is greater than 21. Signed-off-by: James R. Perkins --- .../main/java/com/sun/tdk/signaturetest/classpath/Release.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/sigtest/src/main/java/com/sun/tdk/signaturetest/classpath/Release.java b/tools/sigtest/src/main/java/com/sun/tdk/signaturetest/classpath/Release.java index e6fd39651..e6937dde9 100644 --- a/tools/sigtest/src/main/java/com/sun/tdk/signaturetest/classpath/Release.java +++ b/tools/sigtest/src/main/java/com/sun/tdk/signaturetest/classpath/Release.java @@ -40,9 +40,6 @@ private Release(char version, FileSystem zipFs, String... prefixes) { * @return found version or null */ public static Release find(int version) { - if (version > 21) { - return null; - } char ch = (char) (version < 10 ? '0' + version : 'A' + (version - 10)); return RELEASES.get(ch); } From 416bc1b1b843344bf530e47ce499bc0735cc5844 Mon Sep 17 00:00:00 2001 From: "James R. Perkins" Date: Mon, 14 Oct 2024 15:04:15 -0700 Subject: [PATCH 3/3] Add a workflow for sigtest CI testing. Signed-off-by: James R. Perkins --- .github/workflows/sigtest-ci.yml | 52 ++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) create mode 100644 .github/workflows/sigtest-ci.yml diff --git a/.github/workflows/sigtest-ci.yml b/.github/workflows/sigtest-ci.yml new file mode 100644 index 000000000..e8bf3fc6f --- /dev/null +++ b/.github/workflows/sigtest-ci.yml @@ -0,0 +1,52 @@ +# This workflow will build a Java project with Maven +# For more information see: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions + +name: Build and Test TCK sigtest Tooling + +on: + pull_request: + branches: + - '**' + paths: + - '.github/workflows/sigtest-ci.yml' + - 'tools/sigtest/**' + push: + branches: + - '**' + paths: + - '.github/workflows/sigtest-ci.yml' + - 'tools/sigtest/**' + +# Only run the latest job +concurrency: + group: '${{ github.workflow }} @ ${{ github.event.pull_request.head.label || github.head_ref || github.ref }}' + cancel-in-progress: true + +jobs: + build-sigtest-tools: + + runs-on: ubuntu-latest + timeout-minutes: 120 + strategy: + fail-fast: false + matrix: + java: ['17', '21', '23'] + + steps: + - uses: actions/checkout@v4 + - name: Set up JDK ${{ matrix.java }} + uses: actions/setup-java@v4 + with: + java-version: ${{ matrix.java }} + distribution: 'temurin' + cache: 'maven' + + - name: sigtest-jdk-${{ matrix.java }} + run: | + cd tools/sigtest + mvn clean install -U -B -fae + - uses: actions/upload-artifact@v4 + if: failure() + with: + name: surefire-reports-jdk-${{ matrix.java }} + path: '**/surefire-reports/'