mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
Cleanup usages of Gradle version comparators in GradleImportingTestCase. The minimum supported Gradle version is 4.5. GitOrigin-RevId: b1522b9f782ade08f5125e039940fce51883bfc7
415 lines
14 KiB
Java
415 lines
14 KiB
Java
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
|
package org.jetbrains.plugins.gradle.compiler;
|
|
|
|
import com.intellij.openapi.util.io.FileUtil;
|
|
import com.intellij.openapi.util.registry.Registry;
|
|
import com.intellij.openapi.vfs.VirtualFile;
|
|
import com.intellij.task.ProjectTaskContext;
|
|
import com.intellij.task.ProjectTaskListener;
|
|
import com.intellij.task.ProjectTaskManager;
|
|
import com.intellij.util.PathUtil;
|
|
import com.intellij.util.messages.MessageBusConnection;
|
|
import org.intellij.lang.annotations.Language;
|
|
import org.jetbrains.annotations.NotNull;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.jetbrains.plugins.gradle.importing.TestGradleBuildScriptBuilder;
|
|
import org.junit.Test;
|
|
|
|
import java.io.IOException;
|
|
import java.util.*;
|
|
import java.util.stream.Collectors;
|
|
|
|
import static java.util.Arrays.asList;
|
|
import static org.assertj.core.api.Assertions.assertThat;
|
|
|
|
public class GradleImprovedHotswapDetectionTest extends GradleDelegatedBuildTestCase {
|
|
@Language("Java")
|
|
private static final String APP_JAVA =
|
|
"""
|
|
package my.pack;
|
|
public class App {
|
|
public int method() { return 42; }
|
|
}""";
|
|
|
|
// App.java with a new method added
|
|
@Language("Java")
|
|
private static final String APP_JAVA_WITH_NEW_METHOD =
|
|
"""
|
|
package my.pack;
|
|
public class App extends Impl {
|
|
public int method() { return 42; }
|
|
public int methodX() { return 100_000; }
|
|
}""";
|
|
|
|
// App.java with new added NewInnerClass inner class
|
|
@Language("Java")
|
|
private static final String APP_JAVA_WITH_INNER_CLASS =
|
|
"""
|
|
package my.pack;
|
|
public class App extends Impl {
|
|
public int method() { return 42; }
|
|
public static class NewInnerClass {
|
|
public void doNothing() {} }}""";
|
|
|
|
// the NewInnerClass method changed from 'doNothing' to 'doSomething'
|
|
@Language("Java")
|
|
private static final String APP_JAVA_WITH_MODIFIED_INNER_CLASS =
|
|
"""
|
|
package my.pack;
|
|
public class App extends Impl {
|
|
public int method() { return 42; }
|
|
public static class NewInnerClass {
|
|
public boolean doSomething() { return true; }
|
|
}
|
|
}""";
|
|
|
|
@Language("Java")
|
|
private static final String IMPL_JAVA =
|
|
"""
|
|
package my.pack;
|
|
import my.pack.Api;
|
|
public class Impl extends Api {}""";
|
|
|
|
@Language("Java")
|
|
private static final String IMPL_JAVA_WITH_NEW_METHOD =
|
|
"""
|
|
package my.pack;
|
|
import my.pack.Api;
|
|
public class Impl extends Api {
|
|
public void newImplMethod() {}
|
|
}""";
|
|
|
|
private String mainRoot;
|
|
private String testRoot;
|
|
private String apiMainRoot;
|
|
private String apiTestRoot;
|
|
private String implMainRoot;
|
|
private String implTestRoot;
|
|
private String apiJar;
|
|
|
|
private VirtualFile appFile;
|
|
private VirtualFile implFile;
|
|
private final List<String> dirtyOutputRoots = new ArrayList<>();
|
|
private final Map<String, Collection<String>> generatedFiles = new HashMap<>();
|
|
|
|
@Override
|
|
public void setUp() throws Exception {
|
|
super.setUp();
|
|
|
|
mainRoot = "build/classes/java/main";
|
|
testRoot = "build/classes/java/test";
|
|
apiMainRoot = "api/build/classes/java/main";
|
|
apiTestRoot = "api/build/classes/java/test";
|
|
implMainRoot = "impl/build/classes/java/main";
|
|
implTestRoot = "impl/build/classes/java/test";
|
|
apiJar = "api/build/libs/api.jar";
|
|
|
|
clearOutputs();
|
|
Registry.get("gradle.improved.hotswap.detection").setValue(true, getTestRootDisposable());
|
|
createProject();
|
|
subscribeToProject();
|
|
}
|
|
|
|
@Test
|
|
public void testBuildMainProject() {
|
|
compileModules("project.main");
|
|
|
|
List<String> expected = new ArrayList<>(asList(apiJar));
|
|
|
|
if (isGradleAtLeast("7.1")) {
|
|
expected.addAll(asList("build/tmp/compileJava/previous-compilation-data.bin",
|
|
"api/build/tmp/compileJava/previous-compilation-data.bin",
|
|
"impl/build/tmp/compileJava/previous-compilation-data.bin"));
|
|
}
|
|
|
|
assertThat(dirtyOutputRoots).containsExactlyInAnyOrderElementsOf(expected);
|
|
|
|
assertThat(generatedFiles).containsOnly(
|
|
Map.entry(mainRoot, Set.of("my/pack/App.class", "my/pack/Other.class")),
|
|
Map.entry(apiMainRoot, Set.of("my/pack/Api.class")),
|
|
Map.entry(implMainRoot, Set.of("my/pack/Impl.class"))
|
|
);
|
|
|
|
assertCopied(mainRoot + "/my/pack/App.class");
|
|
assertNotCopied(testRoot + "/my/pack/AppTest.class");
|
|
|
|
assertCopied(apiMainRoot + "/my/pack/Api.class");
|
|
assertNotCopied(apiTestRoot + "my/pack/ApiTest.class");
|
|
|
|
assertCopied(implMainRoot + "/my/pack/Impl.class");
|
|
assertNotCopied(implTestRoot + "/my/pack/ImplTest.class");
|
|
}
|
|
|
|
|
|
@Test
|
|
public void testBuildTestProject() {
|
|
compileModules("project.test");
|
|
|
|
List<String> expected = new ArrayList<>(asList(apiJar));
|
|
|
|
if (isGradleAtLeast("7.1")) {
|
|
expected.addAll(asList("build/tmp/compileJava/previous-compilation-data.bin",
|
|
"build/tmp/compileTestJava/previous-compilation-data.bin",
|
|
"api/build/tmp/compileJava/previous-compilation-data.bin",
|
|
"impl/build/tmp/compileJava/previous-compilation-data.bin"));
|
|
}
|
|
|
|
assertThat(dirtyOutputRoots).containsExactlyInAnyOrderElementsOf(expected);
|
|
|
|
assertThat(generatedFiles)
|
|
.containsOnly(
|
|
Map.entry(mainRoot, Set.of("my/pack/App.class", "my/pack/Other.class")),
|
|
Map.entry(testRoot, Set.of("my/pack/AppTest.class")),
|
|
Map.entry(apiMainRoot, Set.of("my/pack/Api.class")),
|
|
Map.entry(implMainRoot, Set.of("my/pack/Impl.class"))
|
|
);
|
|
|
|
assertCopied(mainRoot + "/my/pack/App.class");
|
|
assertCopied(testRoot + "/my/pack/AppTest.class");
|
|
|
|
assertCopied(apiMainRoot + "/my/pack/Api.class");
|
|
assertNotCopied(apiTestRoot + "my/pack/ApiTest.class");
|
|
|
|
assertCopied(implMainRoot + "/my/pack/Impl.class");
|
|
assertNotCopied(implTestRoot + "/my/pack/ImplTest.class");
|
|
}
|
|
|
|
@Test
|
|
public void testIncrementalBuildMainProjectUpdatedClass() {
|
|
compileModules("project.main");
|
|
|
|
setFileContent(appFile, APP_JAVA_WITH_NEW_METHOD, false);
|
|
|
|
clearOutputs();
|
|
compileModules("project.main");
|
|
|
|
if (isGradleAtLeast("7.1")) {
|
|
assertThat(dirtyOutputRoots).as("Dirty output roots").containsExactlyInAnyOrder("build/tmp/compileJava/previous-compilation-data.bin");
|
|
} else {
|
|
assertThat(dirtyOutputRoots).as("Dirty output roots").isEmpty();
|
|
}
|
|
|
|
assertThat(generatedFiles)
|
|
.containsOnly(Map.entry(mainRoot, Set.of("my/pack/App.class")));
|
|
}
|
|
|
|
/**
|
|
* Test that adding a new inner class correctly marks
|
|
* the inner class *.class file as generated
|
|
*/
|
|
@Test
|
|
public void testIncrementalBuildMainProjectNewInnerClass() {
|
|
compileModules("project.main");
|
|
|
|
setFileContent(appFile, APP_JAVA_WITH_INNER_CLASS, false);
|
|
|
|
clearOutputs();
|
|
compileModules("project.main");
|
|
|
|
assertThat(generatedFiles).as("Generated files").containsOnly(
|
|
Map.entry(mainRoot, Set.of("my/pack/App.class", "my/pack/App$NewInnerClass.class"))
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Test that modifying inner class correctly marks
|
|
* only the inner class *.class file as generated
|
|
*/
|
|
@Test
|
|
public void testIncrementalBuildMainProjectUpdateInnerClass() {
|
|
setFileContent(appFile, APP_JAVA_WITH_INNER_CLASS, false);
|
|
compileModules("project.main");
|
|
|
|
|
|
setFileContent(appFile, APP_JAVA_WITH_MODIFIED_INNER_CLASS, false);
|
|
|
|
|
|
clearOutputs();
|
|
compileModules("project.main");
|
|
|
|
assertThat(generatedFiles).as("Generated files").containsOnly(
|
|
Map.entry(mainRoot, Set.of("my/pack/App$NewInnerClass.class"))
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testRebuildMainProjectAfterChangingImpl() {
|
|
compileModules("project.main");
|
|
|
|
setFileContent(implFile, IMPL_JAVA_WITH_NEW_METHOD, false);
|
|
|
|
clearOutputs();
|
|
compileModules("project.main");
|
|
|
|
List<String> expected = new ArrayList<>();
|
|
|
|
if (isGradleAtLeast("7.1")) {
|
|
expected.add("impl/build/tmp/compileJava/previous-compilation-data.bin");
|
|
}
|
|
|
|
assertThat(dirtyOutputRoots).as("Dirty output roots").containsExactlyInAnyOrderElementsOf(expected);
|
|
|
|
// note that the "implJar" is not marked as a generated file
|
|
// this is jar itself is marked as dirty root
|
|
assertThat(generatedFiles).as("Generated files").containsOnly(
|
|
Map.entry(implMainRoot, Set.of("my/pack/Impl.class"))
|
|
);
|
|
}
|
|
|
|
@Test
|
|
public void testBuildTestProjectAfterMain() {
|
|
compileModules("project.main");
|
|
|
|
clearOutputs();
|
|
compileModules("project.test");
|
|
|
|
if (isGradleAtLeast("7.1")) {
|
|
assertThat(dirtyOutputRoots).as("Dirty output roots").containsExactlyInAnyOrder("build/tmp/compileTestJava/previous-compilation-data.bin");
|
|
} else {
|
|
assertThat(dirtyOutputRoots).as("Dirty output roots").isEmpty();
|
|
}
|
|
assertThat(generatedFiles).as("Generated files").containsOnly(
|
|
Map.entry(testRoot, Set.of("my/pack/AppTest.class"))
|
|
);
|
|
|
|
assertCopied(testRoot + "/my/pack/AppTest.class");
|
|
assertNotCopied(apiTestRoot + "/my/pack/ApiTest.class");
|
|
assertNotCopied(implTestRoot + "/my/pack/ImplTest.class");
|
|
}
|
|
|
|
@Test
|
|
public void testRebuildMainProjectAfterUndoingChange() {
|
|
compileModules("project.main");
|
|
|
|
setFileContent(appFile, """
|
|
package my.pack;
|
|
public class App {
|
|
public int method() { return 42; }
|
|
public int methodX() { return 42; }
|
|
}""", false);
|
|
|
|
clearOutputs();
|
|
compileModules("project.main");
|
|
|
|
// revert file to previous value
|
|
setFileContent(appFile, APP_JAVA, false);
|
|
|
|
clearOutputs();
|
|
compileModules("project.main");
|
|
|
|
if (isGradleAtLeast("7.1")) {
|
|
assertThat(dirtyOutputRoots).as("Dirty output roots").containsExactlyInAnyOrder("build/tmp/compileJava/previous-compilation-data.bin");
|
|
} else {
|
|
assertThat(dirtyOutputRoots).as("Dirty output roots").isEmpty();
|
|
}
|
|
assertThat(generatedFiles).containsOnly(Map.entry(mainRoot, Set.of("my/pack/App.class")));
|
|
}
|
|
|
|
@Test
|
|
public void testBuildProjectWithResources() throws IOException {
|
|
compileModules("project.main");
|
|
createProjectSubFile("src/main/resources/runtime.properties",
|
|
"resourceString=foobar");
|
|
|
|
clearOutputs();
|
|
compileModules("project.main");
|
|
|
|
assertThat(dirtyOutputRoots).as("Dirty output roots").isEmpty();
|
|
assertThat(generatedFiles).containsOnly(Map.entry("build/resources/main", Set.of("runtime.properties")));
|
|
}
|
|
|
|
private void subscribeToProject() {
|
|
MessageBusConnection connection = myProject.getMessageBus().connect(getTestRootDisposable());
|
|
connection.subscribe(ProjectTaskListener.TOPIC, new ProjectTaskListener() {
|
|
@Override
|
|
public void started(@NotNull ProjectTaskContext context) {
|
|
context.enableCollectionOfGeneratedFiles();
|
|
}
|
|
|
|
@Override
|
|
public void finished(@NotNull ProjectTaskManager.Result result) {
|
|
result.getContext().getDirtyOutputPaths()
|
|
.ifPresent(paths -> paths
|
|
.map(path -> relativePath(path))
|
|
.forEach(dirtyOutputRoots::add));
|
|
|
|
result.getContext().getGeneratedFilesRoots()
|
|
.forEach(generatedRoot -> {
|
|
Set<String> generatedFilesRelativePaths = result.getContext().getGeneratedFilesRelativePaths(generatedRoot)
|
|
.stream()
|
|
.map(path -> PathUtil.toSystemIndependentName(path))
|
|
.collect(Collectors.toSet());
|
|
generatedFiles.put(relativePath(generatedRoot), generatedFilesRelativePaths);
|
|
});
|
|
}
|
|
});
|
|
}
|
|
|
|
private void createProject() throws IOException {
|
|
createSettingsFile("include 'api', 'impl' ");
|
|
createProjectSubFile("gradle.properties",
|
|
"org.gradle.caching=true");
|
|
|
|
appFile = createProjectSubFile("src/main/java/my/pack/App.java", APP_JAVA);
|
|
|
|
createProjectSubFile("src/main/java/my/pack/Other.java",
|
|
"""
|
|
package my.pack;
|
|
public class Other {
|
|
public String method() { return "foo"; }
|
|
}""");
|
|
|
|
createProjectSubFile("src/test/java/my/pack/AppTest.java",
|
|
"""
|
|
package my.pack;
|
|
public class AppTest {
|
|
public void test() { new App().method(); }
|
|
}""");
|
|
|
|
createProjectSubFile("api/src/main/java/my/pack/Api.java",
|
|
"""
|
|
package my.pack;
|
|
public class Api {
|
|
public int method() { return 42; }
|
|
}""");
|
|
|
|
createProjectSubFile("api/src/test/java/my/pack/ApiTest.java",
|
|
"package my.pack;\n" +
|
|
"public class ApiTest {}");
|
|
|
|
implFile = createProjectSubFile("impl/src/main/java/my/pack/Impl.java", IMPL_JAVA);
|
|
|
|
createProjectSubFile("impl/src/test/java/my/pack/ImplTest.java",
|
|
"""
|
|
package my.pack;
|
|
import my.pack.ApiTest;
|
|
public class ImplTest extends ApiTest {}""");
|
|
|
|
importProject(script(it -> {
|
|
it.allprojects(TestGradleBuildScriptBuilder::withJavaPlugin)
|
|
.addImplementationDependency(it.project(":impl"))
|
|
.project(":impl", p -> {
|
|
p
|
|
.withJavaLibraryPlugin()
|
|
.addApiDependency(p.project(":api"));
|
|
});
|
|
}));
|
|
|
|
assertModules("project", "project.main", "project.test",
|
|
"project.api", "project.api.main", "project.api.test",
|
|
"project.impl", "project.impl.main", "project.impl.test");
|
|
}
|
|
|
|
private void clearOutputs() {
|
|
dirtyOutputRoots.clear();
|
|
generatedFiles.clear();
|
|
}
|
|
|
|
@Nullable
|
|
private String relativePath(@NotNull String path) {
|
|
String basePath = PathUtil.toSystemIndependentName(getProjectPath());
|
|
String filePath = PathUtil.toSystemIndependentName(path);
|
|
return FileUtil.getRelativePath(basePath, filePath, '/');
|
|
}
|
|
}
|