From 2b6586a841a770f822543ea3431467430c34340e Mon Sep 17 00:00:00 2001 From: igor Date: Thu, 31 Aug 2023 16:28:54 +0200 Subject: [PATCH] Add configuration cache compatibility and config cache test --- .../gradle/BuildLogicFunctionalTest.java | 102 ++++++------------ .../gradle/GradlePluginClasspathProvider.java | 70 ++++++++++++ 2 files changed, 103 insertions(+), 69 deletions(-) create mode 100644 typescript-generator-gradle-plugin/src/test/java/cz/habarta/typescript/generator/gradle/GradlePluginClasspathProvider.java diff --git a/typescript-generator-gradle-plugin/src/test/java/cz/habarta/typescript/generator/gradle/BuildLogicFunctionalTest.java b/typescript-generator-gradle-plugin/src/test/java/cz/habarta/typescript/generator/gradle/BuildLogicFunctionalTest.java index 70c731450..bed99d0fd 100644 --- a/typescript-generator-gradle-plugin/src/test/java/cz/habarta/typescript/generator/gradle/BuildLogicFunctionalTest.java +++ b/typescript-generator-gradle-plugin/src/test/java/cz/habarta/typescript/generator/gradle/BuildLogicFunctionalTest.java @@ -4,30 +4,28 @@ import org.gradle.testkit.runner.BuildResult; import org.gradle.testkit.runner.GradleRunner; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import sun.misc.Unsafe; import java.io.BufferedWriter; import java.io.File; import java.io.FileWriter; import java.io.IOException; -import java.lang.reflect.Field; import java.net.URL; -import java.net.URLClassLoader; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; +import java.nio.charset.StandardCharsets; +import static cz.habarta.typescript.generator.gradle.GradlePluginClasspathProvider.getClasspath; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.CoreMatchers.containsString; public class BuildLogicFunctionalTest { - - String sampleGradle = "/Users/igor/typescript-generator/sample-gradle"; + String sampleGradle = "../../typescript-generator/sample-gradle"; File sourceDir = new File(sampleGradle + "/src"); @TempDir File testProjectDir; @@ -35,22 +33,31 @@ public class BuildLogicFunctionalTest { private File classpathFile; @BeforeEach - public void setup() throws IOException { - // settingsFile = new File(testProjectDir, "settings.gradle"); - + public void setup() { buildFile = new File(testProjectDir, "build.gradle"); - classpathFile = new File(new File(BuildLogicFunctionalTest.class.getResource("/build.gradle.template").getPath()).getParent(), "plugin-under-test-metadata.properties"); + classpathFile = new File(buildGradleTemplate().getParent(), "plugin-under-test-metadata.properties"); } - @Test - public void testConfigurationCache() throws IOException { - writeFile(classpathFile, "implementation-classpath=" + getClasspath(testProjectDir).stream().collect(Collectors.joining(File.pathSeparator))); - FileUtils.copyToFile(getClass().getResourceAsStream("/build.gradle.template"), buildFile); + public void shouldWorkWithConfigurationCache() throws IOException, NoSuchFieldException, IllegalAccessException { + String classpath = "implementation-classpath=" + String.join(File.pathSeparator, getClasspath(testProjectDir)); + System.out.println("Classpath: " + classpath); + writeFile(classpathFile, classpath); + FileUtils.copyToFile(buildGradleTemplateUrl().openStream(), buildFile); FileUtils.copyDirectory(sourceDir, new File(testProjectDir, "src")); + assertTrue(runGradle("assemble").getOutput().contains("BUILD SUCCESSFUL")); BuildResult generateTypeScript = runGradle("generateTypeScript"); assertTrue(generateTypeScript.getOutput().contains("BUILD SUCCESSFUL")); + + String testFileName = testProjectDir.getName() + ".d.ts"; + String testFilePath = testProjectDir.toString() + "/build/typescript-generator/" + testFileName; + String schema = FileUtils.readFileToString(new File(testFilePath) , StandardCharsets.UTF_8); + assertThat(schema, containsString("export interface Person {\n")); + assertThat(schema, containsString("export interface PersonGroovy {\n")); + assertThat(schema, containsString("export interface PersonKt {\n")); + assertThat(schema, containsString("export interface PersonScala {\n")); + } private BuildResult runGradle(String task) { @@ -59,71 +66,28 @@ private BuildResult runGradle(String task) { .withGradleVersion("8.2.1") .withPluginClasspath() .withArguments( - "--stacktrace", - "--info", + "--stacktrace", + "--info", "--configuration-cache", task ) .build(); } - private static List getClasspath(File projectDir) { - List list = new ArrayList<>(Arrays.asList(getUrls(ClassLoader.getSystemClassLoader())).stream().map(URL::getFile).collect(Collectors.toList())); - list.addAll(buildDirs(projectDir.toString())); - return list; + @NotNull + private static File buildGradleTemplate() { + return new File(buildGradleTemplateUrl().getPath()); } - @NotNull - private static List buildDirs(String sampleGradle) { - List projectBuildDirs = new ArrayList<>(); - projectBuildDirs.add(sampleGradle + "/build/classes/java/main/"); - projectBuildDirs.add(sampleGradle + "/build/classes/groovy/main/"); - projectBuildDirs.add(sampleGradle + "/build/classes/scala/main/"); - projectBuildDirs.add(sampleGradle + "/build/classes/kotlin/main/"); - return projectBuildDirs; + @Nullable + private static URL buildGradleTemplateUrl() { + return BuildLogicFunctionalTest.class.getResource("/build.gradle.template"); } private void writeFile(File destination, String content) throws IOException { - BufferedWriter output = null; - try { - output = new BufferedWriter(new FileWriter(destination)); + try (BufferedWriter output = new BufferedWriter(new FileWriter(destination))) { output.write(content); - } finally { - if (output != null) { - output.close(); - } - } - } - - public static URL[] getUrls(ClassLoader classLoader) { - if (classLoader instanceof URLClassLoader) { - return ((URLClassLoader) classLoader).getURLs(); - } - - // jdk9 - if (classLoader.getClass().getName().startsWith("jdk.internal.loader.ClassLoaders$")) { - try { - Field field = Unsafe.class.getDeclaredField("theUnsafe"); - field.setAccessible(true); - Unsafe unsafe = (Unsafe) field.get(null); - - // jdk.internal.loader.ClassLoaders.AppClassLoader.ucp - Field ucpField = classLoader.getClass().getSuperclass().getDeclaredField("ucp"); - long ucpFieldOffset = unsafe.objectFieldOffset(ucpField); - Object ucpObject = unsafe.getObject(classLoader, ucpFieldOffset); - - // jdk.internal.loader.URLClassPath.path - Field pathField = ucpField.getType().getDeclaredField("path"); - long pathFieldOffset = unsafe.objectFieldOffset(pathField); - ArrayList path = (ArrayList) unsafe.getObject(ucpObject, pathFieldOffset); - - return path.toArray(new URL[path.size()]); - } catch (Exception e) { - e.printStackTrace(); - return null; - } } - return null; } } diff --git a/typescript-generator-gradle-plugin/src/test/java/cz/habarta/typescript/generator/gradle/GradlePluginClasspathProvider.java b/typescript-generator-gradle-plugin/src/test/java/cz/habarta/typescript/generator/gradle/GradlePluginClasspathProvider.java new file mode 100644 index 000000000..d6787f5e0 --- /dev/null +++ b/typescript-generator-gradle-plugin/src/test/java/cz/habarta/typescript/generator/gradle/GradlePluginClasspathProvider.java @@ -0,0 +1,70 @@ +package cz.habarta.typescript.generator.gradle; + +import org.jetbrains.annotations.NotNull; +import sun.misc.Unsafe; + +import java.io.File; +import java.lang.reflect.Field; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.*; +import java.util.stream.Collectors; + +public class GradlePluginClasspathProvider { + public static List getClasspath(File projectDir) throws NoSuchFieldException, IllegalAccessException { + List list = new ArrayList<>(Arrays.asList(GradlePluginClasspathProvider.getUrls(ClassLoader.getSystemClassLoader())).stream().map(URL::getFile).collect(Collectors.toList())); + list.addAll(buildDirs(projectDir.toString())); + return list; + } + + public static URL[] getUrls(ClassLoader classLoader) throws NoSuchFieldException, IllegalAccessException { + System.out.println(classLoader.getClass().getName()); + if (classLoader instanceof URLClassLoader) { + return ((URLClassLoader) classLoader).getURLs(); + } + + // jdk9 + if (classLoader.getClass().getName().startsWith("jdk.internal.loader.ClassLoaders$")) { + Field field = Unsafe.class.getDeclaredField("theUnsafe"); + field.setAccessible(true); + Unsafe unsafe = (Unsafe) field.get(null); + + // jdk.internal.loader.ClassLoaders.AppClassLoader.ucp + Field ucpField = classLoader.getClass().getSuperclass().getDeclaredField("ucp"); + long ucpFieldOffset = unsafe.objectFieldOffset(ucpField); + Object ucpObject = unsafe.getObject(classLoader, ucpFieldOffset); + + // jdk.internal.loader.URLClassPath.path + Field pathField = ucpField.getType().getDeclaredField("path"); + long pathFieldOffset = unsafe.objectFieldOffset(pathField); + ArrayList path = (ArrayList) unsafe.getObject(ucpObject, pathFieldOffset); + + Field mapField = ucpField.getType().getDeclaredField("lmap"); + long mapFieldOffset = unsafe.objectFieldOffset(mapField); + Map map = (Map) unsafe.getObject(ucpObject, mapFieldOffset); + List all = new ArrayList<>(); + all.addAll(path); + all.addAll(map.keySet().stream().map(url -> { + try { + return new URL(url); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + }).collect(Collectors.toSet())); + return all.toArray(new URL[0]); + } + return null; + } + + @NotNull + private static List buildDirs(String sampleGradleDir) { + List buildDirs = new ArrayList<>(); + buildDirs.add(sampleGradleDir + "/build/classes/java/main/"); + buildDirs.add(sampleGradleDir + "/build/classes/groovy/main/"); + buildDirs.add(sampleGradleDir + "/build/classes/scala/main/"); + buildDirs.add(sampleGradleDir + "/build/classes/kotlin/main/"); + return buildDirs; + } + +}