Merge changes in ExternalSystemTestCase into KotlinGradleTests

This commit is contained in:
Andrey Uskov
2020-04-14 23:54:26 +03:00
parent 45481b214a
commit d2a10cbb2d
5 changed files with 1306 additions and 228 deletions
@@ -0,0 +1,126 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.codeInsight.gradle;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.artifacts.ArtifactManager;
import com.intellij.packaging.artifacts.ArtifactType;
import com.intellij.packaging.artifacts.ModifiableArtifactModel;
import com.intellij.packaging.elements.CompositePackagingElement;
import com.intellij.packaging.elements.PackagingElement;
import com.intellij.packaging.elements.PackagingElementFactory;
import com.intellij.packaging.elements.PackagingElementResolvingContext;
import com.intellij.packaging.impl.elements.ArchivePackagingElement;
import com.intellij.packaging.impl.elements.DirectoryPackagingElement;
import com.intellij.packaging.impl.elements.ManifestFileUtil;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import static org.assertj.core.api.Assertions.*;
public class ArtifactsTestUtil {
public static String printToString(PackagingElement element, int level) {
StringBuilder builder = new StringBuilder(StringUtil.repeatSymbol(' ', level));
if (element instanceof ArchivePackagingElement) {
builder.append(((ArchivePackagingElement)element).getArchiveFileName());
}
else if (element instanceof DirectoryPackagingElement) {
builder.append(((DirectoryPackagingElement)element).getDirectoryName()).append("/");
}
else {
builder.append(element.toString());
}
builder.append("\n");
if (element instanceof CompositePackagingElement) {
for (PackagingElement<?> child : ((CompositePackagingElement<?>)element).getChildren()) {
builder.append(printToString(child, level + 1));
}
}
return builder.toString();
}
public static void assertLayout(PackagingElement element, String expected) {
assertThat(printToString(element, 0)).isEqualTo(adjustMultiLine(expected));
}
private static String adjustMultiLine(String expected) {
final List<String> strings = StringUtil.split(StringUtil.trimStart(expected, "\n"), "\n");
int min = Integer.MAX_VALUE;
for (String s : strings) {
int k = 0;
while (k < s.length() && s.charAt(k) == ' ') {
k++;
}
min = Math.min(min, k);
}
List<String> lines = new ArrayList<>();
for (String s : strings) {
lines.add(s.substring(min));
}
return StringUtil.join(lines, "\n") + "\n";
}
public static void assertLayout(Project project, String artifactName, String expected) {
assertLayout(findArtifact(project, artifactName).getRootElement(), expected);
}
public static void assertOutputPath(Project project, String artifactName, String expected) {
assertThat(findArtifact(project, artifactName).getOutputPath()).isEqualTo(expected);
}
public static void assertOutputFileName(Project project, String artifactName, String expected) {
assertThat(findArtifact(project, artifactName).getRootElement().getName()).isEqualTo(expected);
}
public static void setOutput(final Project project, final String artifactName, final String outputPath) {
WriteAction.runAndWait(() -> {
final ModifiableArtifactModel model = ArtifactManager.getInstance(project).createModifiableModel();
model.getOrCreateModifiableArtifact(findArtifact(project, artifactName)).setOutputPath(outputPath);
model.commit();
});
}
public static void addArtifactToLayout(final Project project, final Artifact parent, final Artifact toAdd) {
WriteAction.runAndWait(() -> {
final ModifiableArtifactModel model = ArtifactManager.getInstance(project).createModifiableModel();
final PackagingElement<?> artifactElement = PackagingElementFactory.getInstance().createArtifactElement(toAdd, project);
model.getOrCreateModifiableArtifact(parent).getRootElement().addOrFindChild(artifactElement);
model.commit();
});
}
public static Artifact findArtifact(Project project, String artifactName) {
final ArtifactManager manager = ArtifactManager.getInstance(project);
final Artifact artifact = manager.findArtifact(artifactName);
assertThat(artifact).describedAs("'" + artifactName + "' artifact not found").isNotNull();
return artifact;
}
public static void assertManifest(Artifact artifact, PackagingElementResolvingContext context, @Nullable String mainClass, @Nullable String classpath) {
final CompositePackagingElement<?> rootElement = artifact.getRootElement();
final ArtifactType type = artifact.getArtifactType();
assertManifest(rootElement, context, type, mainClass, classpath);
}
public static void assertManifest(CompositePackagingElement<?> rootElement,
PackagingElementResolvingContext context,
ArtifactType type,
@Nullable String mainClass, @Nullable String classpath) {
final VirtualFile file = ManifestFileUtil.findManifestFile(rootElement, context, type);
assertThat(file).isNotNull();
final Manifest manifest = ManifestFileUtil.readManifest(file);
assertThat(manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS)).isEqualTo(mainClass);
assertThat(manifest.getMainAttributes().getValue(Attributes.Name.CLASS_PATH)).isEqualTo(classpath);
}
}
@@ -15,27 +15,61 @@
*/
package org.jetbrains.kotlin.idea.codeInsight.gradle;
import com.intellij.find.FindManager;
import com.intellij.find.findUsages.FindUsagesHandler;
import com.intellij.find.findUsages.FindUsagesManager;
import com.intellij.find.findUsages.FindUsagesOptions;
import com.intellij.find.impl.FindManagerImpl;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.compiler.CompilerPaths;
import com.intellij.openapi.components.ServiceManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.externalSystem.importing.ImportSpec;
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder;
import com.intellij.openapi.externalSystem.model.DataNode;
import com.intellij.openapi.externalSystem.model.ExternalProjectInfo;
import com.intellij.openapi.externalSystem.model.ProjectSystemId;
import com.intellij.openapi.externalSystem.model.project.ProjectData;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskId;
import com.intellij.openapi.externalSystem.model.task.ExternalSystemTaskNotificationListenerAdapter;
import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode;
import com.intellij.openapi.externalSystem.service.notification.ExternalSystemProgressNotificationManager;
import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback;
import com.intellij.openapi.externalSystem.service.project.ProjectDataManager;
import com.intellij.openapi.externalSystem.service.project.manage.ProjectDataManagerImpl;
import com.intellij.openapi.externalSystem.settings.AbstractExternalSystemSettings;
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings;
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil;
import com.intellij.openapi.externalSystem.util.ExternalSystemUtil;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TestDialog;
import com.intellij.openapi.util.Couple;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.artifacts.ArtifactManager;
import com.intellij.psi.PsiElement;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.usageView.UsageInfo;
import com.intellij.util.BooleanFunction;
import com.intellij.util.CommonProcessors;
import com.intellij.util.Function;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ConcurrentWeakKeySoftValueHashMap;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.ContainerUtilRt;
@@ -48,7 +82,17 @@ import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Proxy;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiPredicate;
import java.util.function.Predicate;
import org.apache.log4j.Level;
import org.jetbrains.jps.model.java.JavaResourceRootType;
import org.jetbrains.jps.model.java.JavaSourceRootProperties;
import org.jetbrains.jps.model.java.JavaSourceRootType;
import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
import static com.intellij.testFramework.EdtTestUtil.runInEdtAndGet;
// part of com.intellij.openapi.externalSystem.test.ExternalSystemImportingTestCase
public abstract class ExternalSystemImportingTestCase extends ExternalSystemTestCase {
@@ -58,17 +102,354 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest
private Logger logger;
@Override
protected Module getModule(String name) {
AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
try {
Module m = ModuleManager.getInstance(myProject).findModuleByName(name);
assertNotNull("Module " + name + " not found", m);
return m;
protected abstract ExternalProjectSettings getCurrentExternalProjectSettings();
protected abstract ProjectSystemId getExternalSystemId();
// assertion methods
protected void assertModulesContains(@NotNull Project project, String... expectedNames) {
Module[] actual = ModuleManager.getInstance(project).getModules();
List<String> actualNames = new ArrayList<>();
for (Module m : actual) {
actualNames.add(m.getName());
}
finally {
accessToken.finish();
assertContain(actualNames, expectedNames);
}
protected void assertModulesContains(String... expectedNames) {
assertModulesContains(myProject, expectedNames);
}
protected void assertModules(@NotNull Project project, String... expectedNames) {
Module[] actual = ModuleManager.getInstance(project).getModules();
List<String> actualNames = new ArrayList<>();
for (Module m : actual) {
actualNames.add(m.getName());
}
assertUnorderedElementsAreEqual(actualNames, expectedNames);
}
protected void assertModules(String... expectedNames) {
assertModules(myProject, expectedNames);
}
protected void assertContentRoots(String moduleName, String... expectedRoots) {
List<String> actual = new ArrayList<>();
for (ContentEntry e : getContentRoots(moduleName)) {
actual.add(e.getUrl());
}
for (int i = 0; i < expectedRoots.length; i++) {
expectedRoots[i] = VfsUtilCore.pathToUrl(expectedRoots[i]);
}
assertUnorderedPathsAreEqual(actual, Arrays.asList(expectedRoots));
}
protected void assertSources(String moduleName, String... expectedSources) {
doAssertContentFolders(moduleName, JavaSourceRootType.SOURCE, expectedSources);
}
protected void assertGeneratedSources(String moduleName, String... expectedSources) {
assertGeneratedSources(moduleName, JavaSourceRootType.SOURCE, expectedSources);
}
protected void assertGeneratedTestSources(String moduleName, String... expectedSources) {
assertGeneratedSources(moduleName, JavaSourceRootType.TEST_SOURCE, expectedSources);
}
private void assertGeneratedSources(String moduleName, JavaSourceRootType type, String... expectedSources) {
final ContentEntry[] contentRoots = getContentRoots(moduleName);
String rootUrl = contentRoots.length > 1 ? ExternalSystemApiUtil.getExternalProjectPath(getModule(moduleName)) : null;
List<String> actual = new ArrayList<>();
for (ContentEntry contentRoot : contentRoots) {
rootUrl = VirtualFileManager.extractPath(rootUrl == null ? contentRoot.getUrl() : rootUrl);
for (SourceFolder f : contentRoot.getSourceFolders(type)) {
String folderUrl = VirtualFileManager.extractPath(f.getUrl());
if (folderUrl.startsWith(rootUrl)) {
int length = rootUrl.length() + 1;
folderUrl = folderUrl.substring(Math.min(length, folderUrl.length()));
}
JavaSourceRootProperties properties = f.getJpsElement().getProperties(type);
if (properties != null && properties.isForGeneratedSources()) {
actual.add(folderUrl);
}
}
}
assertOrderedElementsAreEqual(actual, Arrays.asList(expectedSources));
}
protected void assertResources(String moduleName, String... expectedSources) {
doAssertContentFolders(moduleName, JavaResourceRootType.RESOURCE, expectedSources);
}
protected void assertTestSources(String moduleName, String... expectedSources) {
doAssertContentFolders(moduleName, JavaSourceRootType.TEST_SOURCE, expectedSources);
}
protected void assertTestResources(String moduleName, String... expectedSources) {
doAssertContentFolders(moduleName, JavaResourceRootType.TEST_RESOURCE, expectedSources);
}
protected void assertExcludes(String moduleName, String... expectedExcludes) {
ContentEntry contentRoot = getContentRoot(moduleName);
doAssertContentFolders(contentRoot, Arrays.asList(contentRoot.getExcludeFolders()), expectedExcludes);
}
protected void assertContentRootExcludes(String moduleName, String contentRoot, String... expectedExcudes) {
ContentEntry root = getContentRoot(moduleName, contentRoot);
doAssertContentFolders(root, Arrays.asList(root.getExcludeFolders()), expectedExcudes);
}
private void doAssertContentFolders(String moduleName, @NotNull JpsModuleSourceRootType<?> rootType, String... expected) {
final ContentEntry[] contentRoots = getContentRoots(moduleName);
final String rootUrl = contentRoots.length > 1 ? ExternalSystemApiUtil.getExternalProjectPath(getModule(moduleName)) : null;
doAssertContentFolders(rootUrl, contentRoots, rootType, expected);
}
protected static List<SourceFolder> doAssertContentFolders(@Nullable String rootUrl,
ContentEntry[] contentRoots,
@NotNull JpsModuleSourceRootType<?> rootType,
String... expected) {
List<SourceFolder> result = new ArrayList<>();
List<String> actual = new ArrayList<>();
for (ContentEntry contentRoot : contentRoots) {
for (SourceFolder f : contentRoot.getSourceFolders(rootType)) {
rootUrl = VirtualFileManager.extractPath(rootUrl == null ? contentRoot.getUrl() : rootUrl);
String folderUrl = VirtualFileManager.extractPath(f.getUrl());
if (folderUrl.startsWith(rootUrl)) {
int length = rootUrl.length() + 1;
folderUrl = folderUrl.substring(Math.min(length, folderUrl.length()));
}
actual.add(folderUrl);
result.add(f);
}
}
assertOrderedElementsAreEqual(actual, Arrays.asList(expected));
return result;
}
private static void doAssertContentFolders(ContentEntry e, final List<? extends ContentFolder> folders, String... expected) {
List<String> actual = new ArrayList<>();
for (ContentFolder f : folders) {
String rootUrl = e.getUrl();
String folderUrl = f.getUrl();
if (folderUrl.startsWith(rootUrl)) {
int length = rootUrl.length() + 1;
folderUrl = folderUrl.substring(Math.min(length, folderUrl.length()));
}
actual.add(folderUrl);
}
assertOrderedElementsAreEqual(actual, Arrays.asList(expected));
}
protected void assertModuleOutputs(String moduleName, String... outputs) {
String[] outputPaths = ContainerUtil.map2Array(CompilerPaths.getOutputPaths(new Module[]{getModule(moduleName)}), String.class,
s -> getAbsolutePath(s));
assertUnorderedElementsAreEqual(outputPaths, outputs);
}
protected void assertModuleOutput(String moduleName, String output, String testOutput) {
CompilerModuleExtension e = getCompilerExtension(moduleName);
assertFalse(e.isCompilerOutputPathInherited());
assertEquals(output, getAbsolutePath(e.getCompilerOutputUrl()));
assertEquals(testOutput, getAbsolutePath(e.getCompilerOutputUrlForTests()));
}
protected void assertModuleInheritedOutput(String moduleName) {
CompilerModuleExtension e = getCompilerExtension(moduleName);
assertTrue(e.isCompilerOutputPathInherited());
}
protected static String getAbsolutePath(String path) {
path = VfsUtilCore.urlToPath(path);
path = PathUtil.getCanonicalPath(path);
return FileUtil.toSystemIndependentName(path);
}
protected void assertProjectOutput(String module) {
assertTrue(getCompilerExtension(module).isCompilerOutputPathInherited());
}
protected CompilerModuleExtension getCompilerExtension(String module) {
return CompilerModuleExtension.getInstance(getModule(module));
}
protected void assertModuleLibDep(String moduleName, String depName) {
assertModuleLibDep(moduleName, depName, null);
}
protected void assertModuleLibDep(String moduleName, String depName, String classesPath) {
assertModuleLibDep(moduleName, depName, classesPath, null, null);
}
protected void assertModuleLibDep(String moduleName, String depName, String classesPath, String sourcePath, String javadocPath) {
LibraryOrderEntry lib = ContainerUtil.getFirstItem(getModuleLibDeps(moduleName, depName));
final String errorMessage = "Failed to find dependency with name [" + depName + "] in module [" + moduleName + "]\n" +
"Available dependencies: " + collectModuleDepsNames(moduleName, LibraryOrderEntry.class);
assertNotNull(errorMessage, lib);
assertModuleLibDepPath(lib, OrderRootType.CLASSES, classesPath == null ? null : Collections.singletonList(classesPath));
assertModuleLibDepPath(lib, OrderRootType.SOURCES, sourcePath == null ? null : Collections.singletonList(sourcePath));
assertModuleLibDepPath(lib, JavadocOrderRootType.getInstance(), javadocPath == null ? null : Collections.singletonList(javadocPath));
}
protected void assertModuleLibDep(String moduleName,
String depName,
List<String> classesPaths,
List<String> sourcePaths,
List<String> javadocPaths) {
LibraryOrderEntry lib = ContainerUtil.getFirstItem(getModuleLibDeps(moduleName, depName));
assertModuleLibDepPath(lib, OrderRootType.CLASSES, classesPaths);
assertModuleLibDepPath(lib, OrderRootType.SOURCES, sourcePaths);
assertModuleLibDepPath(lib, JavadocOrderRootType.getInstance(), javadocPaths);
}
private static void assertModuleLibDepPath(LibraryOrderEntry lib, OrderRootType type, List<String> paths) {
assertNotNull(lib);
if (paths == null) return;
assertUnorderedPathsAreEqual(Arrays.asList(lib.getRootUrls(type)), paths);
// also check the library because it may contain slight different set of urls (e.g. with duplicates)
final Library library = lib.getLibrary();
assertNotNull(library);
assertUnorderedPathsAreEqual(Arrays.asList(library.getUrls(type)), paths);
}
protected void assertModuleLibDepScope(String moduleName, String depName, DependencyScope... scopes) {
List<LibraryOrderEntry> deps = getModuleLibDeps(moduleName, depName);
assertUnorderedElementsAreEqual(ContainerUtil.map2Array(deps, entry -> entry.getScope()), scopes);
}
protected List<LibraryOrderEntry> getModuleLibDeps(String moduleName, String depName) {
return getModuleDep(moduleName, depName, LibraryOrderEntry.class);
}
protected void assertModuleLibDeps(String moduleName, String... expectedDeps) {
assertModuleDeps(moduleName, LibraryOrderEntry.class, expectedDeps);
}
protected void assertModuleLibDeps(BiPredicate<String, String> predicate, String moduleName, String... expectedDeps) {
assertModuleDeps(predicate, moduleName, LibraryOrderEntry.class, expectedDeps);
}
protected void assertExportedDeps(String moduleName, String... expectedDeps) {
final List<String> actual = new ArrayList<>();
getRootManager(moduleName).orderEntries().withoutSdk().withoutModuleSourceEntries().exportedOnly().process(new RootPolicy<Object>() {
@Override
public Object visitModuleOrderEntry(@NotNull ModuleOrderEntry e, Object value) {
actual.add(e.getModuleName());
return null;
}
@Override
public Object visitLibraryOrderEntry(@NotNull LibraryOrderEntry e, Object value) {
actual.add(e.getLibraryName());
return null;
}
}, null);
assertOrderedElementsAreEqual(actual, expectedDeps);
}
protected void assertModuleModuleDeps(String moduleName, String... expectedDeps) {
assertModuleDeps(moduleName, ModuleOrderEntry.class, expectedDeps);
}
private void assertModuleDeps(String moduleName, Class clazz, String... expectedDeps) {
assertModuleDeps(equalsPredicate(), moduleName, clazz, expectedDeps);
}
private void assertModuleDeps(BiPredicate<String, String> predicate, String moduleName, Class clazz, String... expectedDeps) {
assertOrderedElementsAreEqual(predicate, collectModuleDepsNames(moduleName, clazz), expectedDeps);
}
protected void assertProductionOnTestDependencies(String moduleName, String... expectedDeps) {
assertOrderedElementsAreEqual(collectModuleDepsNames(
moduleName, entry -> entry instanceof ModuleOrderEntry && ((ModuleOrderEntry)entry).isProductionOnTestDependency()
), expectedDeps);
}
protected void assertModuleModuleDepScope(String moduleName, String depName, DependencyScope... scopes) {
List<ModuleOrderEntry> deps = getModuleModuleDeps(moduleName, depName);
assertUnorderedElementsAreEqual(ContainerUtil.map2Array(deps, entry -> entry.getScope()), scopes);
}
protected void assertNoModuleDepForModule(String moduleName, String depName) {
assertEmpty("No dependency '" + depName + "' was expected", collectModuleDeps(moduleName, depName, ModuleOrderEntry.class));
}
protected void assertNoLibraryDepForModule(String moduleName, String depName) {
assertEmpty("No dependency '" + depName + "' was expected", collectModuleDeps(moduleName, depName, LibraryOrderEntry.class));
}
public void assertProjectLibraries(String... expectedNames) {
List<String> actualNames = new ArrayList<>();
for (Library each : LibraryTablesRegistrar.getInstance().getLibraryTable(myProject).getLibraries()) {
String name = each.getName();
actualNames.add(name == null ? "<unnamed>" : name);
}
assertUnorderedElementsAreEqual(actualNames, expectedNames);
}
protected void assertModuleGroupPath(String moduleName, String... expected) {
String[] path = ModuleManager.getInstance(myProject).getModuleGroupPath(getModule(moduleName));
if (expected.length == 0) {
assertNull(path);
}
else {
assertNotNull(path);
assertOrderedElementsAreEqual(Arrays.asList(path), expected);
}
}
protected void assertArtifacts(String... expectedNames) {
final List<String> actualNames = ContainerUtil.map(
ArtifactManager.getInstance(myProject).getAllArtifactsIncludingInvalid(),
(Function<Artifact, String>)artifact -> artifact.getName());
assertUnorderedElementsAreEqual(actualNames, expectedNames);
}
//end of assertions
private ContentEntry getContentRoot(String moduleName) {
ContentEntry[] ee = getContentRoots(moduleName);
List<String> roots = new ArrayList<>();
for (ContentEntry e : ee) {
roots.add(e.getUrl());
}
String message = "Several content roots found: [" + StringUtil.join(roots, ", ") + "]";
assertEquals(message, 1, ee.length);
return ee[0];
}
private ContentEntry getContentRoot(String moduleName, String path) {
for (ContentEntry e : getContentRoots(moduleName)) {
if (e.getUrl().equals(VfsUtilCore.pathToUrl(path))) return e;
}
throw new AssertionError("content root not found");
}
public ContentEntry[] getContentRoots(String moduleName) {
return getRootManager(moduleName).getContentEntries();
}
protected void importProject(@NonNls String config) throws IOException {
@@ -198,71 +579,161 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest
private void doImportProject() {
AbstractExternalSystemSettings systemSettings = ExternalSystemApiUtil.getSettings(myProject, getExternalSystemId());
ExternalProjectSettings projectSettings = getCurrentExternalProjectSettings();
final ExternalProjectSettings projectSettings = getCurrentExternalProjectSettings();
projectSettings.setExternalProjectPath(getProjectPath());
@SuppressWarnings("unchecked") Set<ExternalProjectSettings> projects =
ContainerUtilRt.newHashSet(systemSettings.getLinkedProjectsSettings());
//noinspection unchecked
Set<ExternalProjectSettings> projects = new HashSet<>(systemSettings.getLinkedProjectsSettings());
projects.remove(projectSettings);
projects.add(projectSettings);
//noinspection unchecked
systemSettings.setLinkedProjectsSettings(projects);
final Ref<Couple<String>> error = Ref.create();
ExternalSystemUtil.refreshProjects(
new TestImportSpecBuilder(myProject, getExternalSystemId())
.setCreateEmptyContentRoots(projectSettings.isCreateEmptyContentRootDirectories())
.use(ProgressExecutionMode.MODAL_SYNC)
.callback(new ExternalProjectRefreshCallback() {
@Override
public void onSuccess(@Nullable DataNode<ProjectData> externalProject) {
if (externalProject == null) {
System.err.println("Got null External project after import");
return;
}
inspectForGradleMemoryLeaks(externalProject);
ServiceManager.getService(ProjectDataManager.class).importData(externalProject, myProject, true);
System.out.println("External project was successfully imported");
}
ImportSpec importSpec = createImportSpec();
ExternalProjectRefreshCallback callback = importSpec.getCallback();
if (callback == null || callback instanceof ImportSpecBuilder.DefaultProjectRefreshCallback) {
importSpec = new TestImportSpecBuilder(importSpec)
.setCreateEmptyContentRoots(projectSettings.isCreateEmptyContentRootDirectories())
.callback(new ExternalProjectRefreshCallback() {
@Override
public void onSuccess(@Nullable final DataNode<ProjectData> externalProject) {
if (externalProject == null) {
System.err.println("Got null External project after import");
return;
}
ServiceManager.getService(ProjectDataManager.class).importData(externalProject, myProject, true);
System.out.println("External project was successfully imported");
@Override
public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
error.set(Couple.of(errorMessage, errorDetails));
}
})
.forceWhenUptodate()
);
inspectForGradleMemoryLeaks(externalProject);
}
@Override
public void onFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
error.set(Couple.of(errorMessage, errorDetails));
}
}).build();
}
ExternalSystemProgressNotificationManager notificationManager =
ServiceManager.getService(ExternalSystemProgressNotificationManager.class);
ExternalSystemTaskNotificationListenerAdapter listener = new ExternalSystemTaskNotificationListenerAdapter() {
@Override
public void onTaskOutput(@NotNull ExternalSystemTaskId id, @NotNull String text, boolean stdOut) {
if (StringUtil.isEmptyOrSpaces(text)) return;
(stdOut ? System.out : System.err).print(text);
}
};
notificationManager.addNotificationListener(listener);
try {
ExternalSystemUtil.refreshProjects(importSpec);
}
finally {
notificationManager.removeNotificationListener(listener);
}
if (!error.isNull()) {
String failureMsg = "Import failed: " + error.get().first;
if (StringUtil.isNotEmpty(error.get().second)) {
failureMsg += "\nError details: \n" + error.get().second;
handleImportFailure(error.get().first, error.get().second);
}
}
protected void handleImportFailure(@NotNull String errorMessage, @Nullable String errorDetails) {
String failureMsg = "Import failed: " + errorMessage;
if (StringUtil.isNotEmpty(errorDetails)) {
failureMsg += "\nError details: \n" + errorDetails;
}
fail(failureMsg);
}
protected ImportSpec createImportSpec() {
ImportSpecBuilder importSpecBuilder = new ImportSpecBuilder(myProject, getExternalSystemId())
.use(ProgressExecutionMode.MODAL_SYNC)
.forceWhenUptodate();
return importSpecBuilder.build();
}
protected void setupJdkForModules(String... moduleNames) {
for (String each : moduleNames) {
setupJdkForModule(each);
}
}
@Override
protected Sdk setupJdkForModule(final String moduleName) {
final Sdk sdk = true ? JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk() : createJdk("Java 1.5");
ModuleRootModificationUtil.setModuleSdk(getModule(moduleName), sdk);
return sdk;
}
protected static Sdk createJdk(String versionName) {
return IdeaTestUtil.getMockJdk17(versionName);
}
protected static AtomicInteger configConfirmationForYesAnswer() {
final AtomicInteger counter = new AtomicInteger();
Messages.setTestDialog(new TestDialog() {
@Override
public int show(@NotNull String message) {
counter.set(counter.get() + 1);
return 0;
}
});
return counter;
}
protected static AtomicInteger configConfirmationForNoAnswer() {
final AtomicInteger counter = new AtomicInteger();
Messages.setTestDialog(new TestDialog() {
@Override
public int show(@NotNull String message) {
counter.set(counter.get() + 1);
return 1;
}
});
return counter;
}
protected static Collection<UsageInfo> findUsages(@NotNull PsiElement element) throws Exception {
return ProgressManager.getInstance().run(new Task.WithResult<Collection<UsageInfo>, Exception>(null, "", false) {
@Override
protected Collection<UsageInfo> compute(@NotNull ProgressIndicator indicator) {
return runInEdtAndGet(() -> {
FindUsagesManager findUsagesManager = ((FindManagerImpl) FindManager.getInstance(element.getProject())).getFindUsagesManager();
FindUsagesHandler handler = findUsagesManager.getFindUsagesHandler(element, false);
assertNotNull(handler);
final FindUsagesOptions options = handler.getFindUsagesOptions();
final CommonProcessors.CollectProcessor<UsageInfo> processor = new CommonProcessors.CollectProcessor<>();
for (PsiElement element : handler.getPrimaryElements()) {
handler.processElementUsages(element, processor, options);
}
for (PsiElement element : handler.getSecondaryElements()) {
handler.processElementUsages(element, processor, options);
}
return processor.getResults();
});
}
});
}
@Nullable
protected SourceFolder findSource(@NotNull String moduleName, @NotNull String sourcePath) {
return findSource(getRootManager(moduleName), sourcePath);
}
@Nullable
protected SourceFolder findSource(@NotNull ModuleRootModel moduleRootManager, @NotNull String sourcePath) {
ContentEntry[] contentRoots = moduleRootManager.getContentEntries();
Module module = moduleRootManager.getModule();
String rootUrl = getAbsolutePath(ExternalSystemApiUtil.getExternalProjectPath(module));
for (ContentEntry contentRoot : contentRoots) {
for (SourceFolder f : contentRoot.getSourceFolders()) {
String folderPath = getAbsolutePath(f.getUrl());
String rootPath = getAbsolutePath(rootUrl + "/" + sourcePath);
if (folderPath.equals(rootPath)) return f;
}
fail(failureMsg);
}
return null;
}
protected abstract ExternalProjectSettings getCurrentExternalProjectSettings();
protected abstract ProjectSystemId getExternalSystemId();
protected void assertModuleModuleDepScope(String moduleName, String depName, DependencyScope... scopes) {
List<ModuleOrderEntry> deps = getModuleModuleDeps(moduleName, depName);
Set<DependencyScope> actualScopes = new HashSet<DependencyScope>();
for (ModuleOrderEntry dep : deps) {
actualScopes.add(dep.getScope());
}
HashSet<DependencyScope> expectedScopes = new HashSet<DependencyScope>(Arrays.asList(scopes));
assertEquals("Dependency '" + depName + "' for module '" + moduleName + "' has unexpected scope",
expectedScopes, actualScopes);
}
protected void assertNoModuleDepForModule(String moduleName, String depName) {
assertEmpty("No dependency '" + depName + "' was expected", collectModuleDeps(moduleName, depName, ModuleOrderEntry.class));
}
protected void assertNoLibraryDepForModule(String moduleName, String depName) {
assertEmpty("No dependency '" + depName + "' was expected", collectModuleDeps(moduleName, depName, LibraryOrderEntry.class));
}
@NotNull
private List<ModuleOrderEntry> getModuleModuleDeps(@NotNull String moduleName, @NotNull String depName) {
@@ -273,16 +744,31 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest
return ModuleRootManager.getInstance(getModule(module));
}
protected void ignoreData(BooleanFunction<DataNode<?>> booleanFunction, final boolean ignored) {
final ExternalProjectInfo externalProjectInfo = ProjectDataManagerImpl.getInstance().getExternalProjectData(
myProject, getExternalSystemId(), getCurrentExternalProjectSettings().getExternalProjectPath());
assertNotNull(externalProjectInfo);
final DataNode<ProjectData> projectDataNode = externalProjectInfo.getExternalProjectStructure();
assertNotNull(projectDataNode);
final Collection<DataNode<?>> nodes = ExternalSystemApiUtil.findAllRecursively(projectDataNode, booleanFunction);
for (DataNode<?> node : nodes) {
node.visit(dataNode -> dataNode.setIgnored(ignored));
}
ServiceManager.getService(ProjectDataManager.class).importData(projectDataNode, myProject, true);
}
@NotNull
private <T> List<T> getModuleDep(@NotNull String moduleName, @NotNull String depName, @NotNull Class<T> clazz) {
List<T> deps = collectModuleDeps(moduleName, depName, clazz);
assertTrue("Dependency '" +
depName +
"' for module '" +
moduleName +
"' not found among: " +
collectModuleDepsNames(moduleName, clazz),
!deps.isEmpty());
List<T> deps = new ArrayList<>();
for (OrderEntry e : getRootManager(moduleName).getOrderEntries()) {
if (clazz.isInstance(e) && e.getPresentableName().equals(depName)) {
deps.add((T)e);
}
}
assertNotNull("Dependency for module \"" + moduleName + "\" not found: " + depName + "\namong: " + collectModuleDepsNames(moduleName, clazz), deps);
return deps;
}
@@ -299,14 +785,19 @@ public abstract class ExternalSystemImportingTestCase extends ExternalSystemTest
return deps;
}
private List<String> collectModuleDepsNames(String moduleName, Class clazz) {
List<String> actual = new ArrayList<String>();
private List<String> collectModuleDepsNames(String moduleName, Predicate<OrderEntry> predicate) {
List<String> actual = new ArrayList<>();
for (OrderEntry e : getRootManager(moduleName).getOrderEntries()) {
if (clazz.isInstance(e)) {
if (predicate.test(e)) {
actual.add(e.getPresentableName());
}
}
return actual;
}
private List<String> collectModuleDepsNames(String moduleName, Class clazz) {
return collectModuleDepsNames(moduleName, entry -> clazz.isInstance(entry));
}
}
@@ -15,156 +15,199 @@
*/
package org.jetbrains.kotlin.idea.codeInsight.gradle;
import com.intellij.compiler.CompilerTestUtil;
import com.intellij.openapi.application.AccessToken;
import com.intellij.compiler.impl.ModuleCompileScope;
import com.intellij.compiler.server.BuildManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompilerMessage;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.util.Pair;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.ByteArraySequence;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.vfs.JarFileSystem;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
import com.intellij.testFramework.EdtTestUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.impl.compiler.ArtifactCompileScope;
import com.intellij.task.ProjectTaskManager;
import com.intellij.testFramework.*;
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Processor;
import com.intellij.util.ThrowableRunnable;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ArrayUtilRt;
import com.intellij.util.ExceptionUtil;
import com.intellij.util.PathUtil;
import com.intellij.util.SmartList;
import com.intellij.util.io.PathKt;
import com.intellij.util.io.TestFileSystemItem;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.SystemIndependent;
import org.jetbrains.concurrency.Promise;
import org.junit.After;
import org.junit.Before;
import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.List;
import java.util.*;
import java.util.function.BiPredicate;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import static com.intellij.testFramework.EdtTestUtilKt.runInEdtAndWait;
// part of com.intellij.openapi.externalSystem.test.ExternalSystemTestCase
/**
* @author Vladislav.Soroka
*/
public abstract class ExternalSystemTestCase extends UsefulTestCase {
private static final BiPredicate<Object, Object> EQUALS_PREDICATE = (t, u) -> Objects.equals(t, u);
private File ourTempDir;
protected IdeaProjectTestFixture myTestFixture;
protected Project myProject;
private VirtualFile myProjectRoot;
private final List<VirtualFile> myAllConfigs = new ArrayList<VirtualFile>();
protected File myTestDir;
protected VirtualFile myProjectRoot;
protected VirtualFile myProjectConfig;
protected List<VirtualFile> myAllConfigs = new ArrayList<>();
protected boolean useProjectTaskManager;
@Before
@Override
public void setUp() throws Exception {
super.setUp();
ensureTempDirCreated();
myTestDir = ourTempDir;//TODO was new File(ourTempDir, getTestName(false)); but paths appear to be too long
FileUtil.ensureExists(myTestDir);
setUpFixtures();
myProject = myTestFixture.getProject();
invokeTestRunnable(new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
try {
setUpInWriteAction();
}
catch (Throwable e) {
try {
tearDown();
}
catch (Exception e1) {
e1.printStackTrace();
}
throw new RuntimeException(e);
}
}
});
EdtTestUtil.runInEdtAndWait(() -> ApplicationManager.getApplication().runWriteAction(() -> {
try {
setUpInWriteAction();
}
});
catch (Throwable e) {
try {
tearDown();
}
catch (Exception e1) {
e1.printStackTrace();
}
throw new RuntimeException(e);
}
}));
List<String> allowedRoots = new ArrayList<String>();
List<String> allowedRoots = new ArrayList<>();
collectAllowedRoots(allowedRoots);
if (!allowedRoots.isEmpty()) {
VfsRootAccess.allowRootAccess(getTestRootDisposable(), ArrayUtil.toStringArray(allowedRoots));
VfsRootAccess.allowRootAccess(myTestFixture.getTestRootDisposable(), ArrayUtilRt.toStringArray(allowedRoots));
}
CompilerTestUtil.enableExternalCompiler();
}
protected void collectAllowedRoots(List<String> roots) throws IOException {
protected void collectAllowedRoots(List<String> roots) {
}
public static Collection<String> collectRootsInside(String root) {
final List<String> roots = ContainerUtil.newSmartList();
final List<String> roots = new SmartList<>();
roots.add(root);
FileUtil.processFilesRecursively(new File(root), new Processor<File>() {
@Override
public boolean process(File file) {
try {
String path = file.getCanonicalPath();
if (!FileUtil.isAncestor(path, path, false)) {
roots.add(path);
}
FileUtil.processFilesRecursively(new File(root), file -> {
try {
String path = file.getCanonicalPath();
if (!FileUtil.isAncestor(path, path, false)) {
roots.add(path);
}
catch (IOException ignore) {
}
return true;
}
catch (IOException ignore) {
}
return true;
});
return roots;
}
private void ensureTempDirCreated() throws IOException {
if (ourTempDir != null) return;
ourTempDir = new File(FileUtil.getTempDirectory(), getTestsTempDir());
FileUtil.delete(ourTempDir);
FileUtil.ensureExists(ourTempDir);
}
protected final String getTestsTempDir() {
return "";
}
protected void setUpFixtures() throws Exception {
myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()).getFixture();
myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName(), useDirectoryBasedStorageFormat()).getFixture();
myTestFixture.setUp();
}
private void setUpInWriteAction() throws Exception {
File projectDir = FileUtil.createTempDirectory("project", "", false);
protected boolean useDirectoryBasedStorageFormat() {
return false;
}
protected void setUpInWriteAction() throws Exception {
File projectDir = new File(myTestDir, "project");
FileUtil.ensureExists(projectDir);
myProjectRoot = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(projectDir);
}
@After
@Override
public void tearDown() throws Exception {
try {
EdtTestUtil.runInEdtAndWait(new ThrowableRunnable<Throwable>() {
@Override
public void run() throws Throwable {
CompilerTestUtil.disableExternalCompiler(myProject);
tearDownFixtures();
}
});
myProject = null;
}
finally {
super.tearDown();
resetClassFields(getClass());
}
new RunAll(
() -> {
if (myProject != null && !myProject.isDisposed()) {
PathKt.delete(ProjectUtil.getExternalConfigurationDir(myProject));
}
},
() -> EdtTestUtil.runInEdtAndWait(() -> tearDownFixtures()),
() -> myProject = null,
() -> PathKt.delete(myTestDir.toPath()),
() -> super.tearDown(),
() -> resetClassFields(getClass())
).run();
}
protected void tearDownFixtures() throws Exception {
myTestFixture.tearDown();
protected void tearDownFixtures() {
if (myTestFixture != null) {
try {
myTestFixture.tearDown();
}
catch (Exception ignored) {
}
}
myTestFixture = null;
}
private void resetClassFields(Class<?> aClass) {
private void resetClassFields(final Class<?> aClass) {
if (aClass == null) return;
Field[] fields = aClass.getDeclaredFields();
final Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
final int modifiers = field.getModifiers();
if ((modifiers & Modifier.FINAL) == 0
@@ -187,7 +230,17 @@ public abstract class ExternalSystemTestCase extends UsefulTestCase {
@Override
protected void runTest() throws Throwable {
try {
super.runTest();
if (runInWriteAction()) {
try {
WriteAction.runAndWait(() -> super.runTest());
}
catch (Throwable throwable) {
ExceptionUtil.rethrowAllAsUnchecked(throwable);
}
}
else {
super.runTest();
}
}
catch (Exception throwable) {
Throwable each = throwable;
@@ -203,11 +256,12 @@ public abstract class ExternalSystemTestCase extends UsefulTestCase {
}
@Override
protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception {
runInEdtAndWait(() -> {
runnable.run();
return null;
});
protected void invokeTestRunnable(@NotNull Runnable runnable) {
runnable.run();
}
protected boolean runInWriteAction() {
return false;
}
protected static String getRoot() {
@@ -215,74 +269,356 @@ public abstract class ExternalSystemTestCase extends UsefulTestCase {
return "";
}
protected static String getEnvVar() {
if (SystemInfo.isWindows) return "TEMP";
else if (SystemInfo.isLinux) return "HOME";
return "TMPDIR";
}
protected String getProjectPath() {
return myProjectRoot.getPath();
}
protected VirtualFile createProjectConfig(@NonNls String config) throws IOException {
return createConfigFile(myProjectRoot, config);
protected String getParentPath() {
return myProjectRoot.getParent().getPath();
}
private VirtualFile createConfigFile(final VirtualFile dir, String config) throws IOException {
final String configFileName = getExternalSystemConfigFileName();
VirtualFile f = dir.findChild(configFileName);
if (f == null) {
f = new WriteAction<VirtualFile>() {
@Override
protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
VirtualFile res = dir.createChildData(null, configFileName);
result.setResult(res);
}
}.execute().getResultObject();
myAllConfigs.add(f);
@SystemIndependent
protected String path(@NotNull String relativePath) {
return PathUtil.toSystemIndependentName(file(relativePath).getPath());
}
protected File file(@NotNull String relativePath) {
return new File(getProjectPath(), relativePath);
}
protected Module createModule(String name) {
return createModule(name, StdModuleTypes.JAVA);
}
protected Module createModule(final String name, final ModuleType type) {
try {
return WriteCommandAction.writeCommandAction(myProject).compute(() -> {
VirtualFile f = createProjectSubFile(name + "/" + name + ".iml");
Module module = ModuleManager.getInstance(myProject).newModule(f.getPath(), type.getId());
PsiTestUtil.addContentRoot(module, f.getParent());
return module;
});
}
setFileContent(f, config, true);
return f;
catch (IOException e) {
throw new RuntimeException(e);
}
}
protected VirtualFile createProjectConfig(@NonNls String config) {
return myProjectConfig = createConfigFile(myProjectRoot, config);
}
protected VirtualFile createConfigFile(final VirtualFile dir, String config) {
final String configFileName = getExternalSystemConfigFileName();
VirtualFile configFile;
try {
configFile = WriteAction.computeAndWait(() -> {
VirtualFile file = dir.findChild(configFileName);
return file == null ? dir.createChildData(null, configFileName) : file;
});
myAllConfigs.add(configFile);
}
catch (IOException e) {
throw new RuntimeException(e);
}
setFileContent(configFile, config, true);
return configFile;
}
protected abstract String getExternalSystemConfigFileName();
protected void createStdProjectFolders() throws IOException {
createProjectSubDirs("src/main/java",
"src/main/resources",
"src/test/java",
"src/test/resources");
}
protected void createProjectSubDirs(String... relativePaths) throws IOException {
for (String path : relativePaths) {
createProjectSubDir(path);
}
}
protected VirtualFile createProjectSubDir(String relativePath) throws IOException {
File f = new File(getProjectPath(), relativePath);
FileUtil.ensureExists(f);
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
}
protected VirtualFile createProjectSubFile(String relativePath) throws IOException {
File f = new File(getProjectPath(), relativePath);
FileUtil.ensureExists(f.getParentFile());
FileUtil.ensureCanCreateFile(f);
boolean created = f.createNewFile();
if (!created) {
final boolean created = f.createNewFile();
if (!created && !f.exists()) {
throw new AssertionError("Unable to create the project sub file: " + f.getAbsolutePath());
}
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
}
@NotNull
protected VirtualFile createProjectJarSubFile(String relativePath, Pair<ByteArraySequence, String>... contentEntries) throws IOException {
assertTrue("Use 'jar' extension for JAR files: '" + relativePath + "'", FileUtilRt.extensionEquals(relativePath, "jar"));
File f = new File(getProjectPath(), relativePath);
FileUtil.ensureExists(f.getParentFile());
FileUtil.ensureCanCreateFile(f);
final boolean created = f.createNewFile();
if (!created) {
throw new AssertionError("Unable to create the project sub file: " + f.getAbsolutePath());
}
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
JarOutputStream target = new JarOutputStream(new FileOutputStream(f), manifest);
for (Pair<ByteArraySequence, String> contentEntry : contentEntries) {
addJarEntry(contentEntry.first.getBytes(), contentEntry.second, target);
}
target.close();
final VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
assertNotNull(virtualFile);
final VirtualFile jarFile = JarFileSystem.getInstance().getJarRootForLocalFile(virtualFile);
assertNotNull(jarFile);
return jarFile;
}
private static void addJarEntry(byte[] bytes, String path, JarOutputStream target) throws IOException {
JarEntry entry = new JarEntry(path.replace("\\", "/"));
target.putNextEntry(entry);
target.write(bytes);
target.close();
}
protected VirtualFile createProjectSubFile(String relativePath, String content) throws IOException {
VirtualFile file = createProjectSubFile(relativePath);
setFileContent(file, content, false);
return file;
}
protected Module getModule(String name) {
AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
try {
Module m = ModuleManager.getInstance(myProject).findModuleByName(name);
assertNotNull("Module " + name + " not found", m);
return m;
protected void compileModules(final String... moduleNames) {
if (useProjectTaskManager) {
Module[] modules = Arrays.stream(moduleNames).map(moduleName -> getModule(moduleName)).toArray(Module[]::new);
build(modules);
}
finally {
accessToken.finish();
else {
compile(createModulesCompileScope(moduleNames));
}
}
protected static void setFileContent(final VirtualFile file, final String content, final boolean advanceStamps) throws IOException {
new WriteAction<VirtualFile>() {
@Override
protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
if (advanceStamps) {
file.setBinaryContent(content.getBytes(CharsetToolkit.UTF8_CHARSET), -1, file.getTimeStamp() + 4000);
}
else {
file.setBinaryContent(content.getBytes(CharsetToolkit.UTF8_CHARSET), file.getModificationStamp(), file.getTimeStamp());
protected void buildArtifacts(String... artifactNames) {
if (useProjectTaskManager) {
Artifact[] artifacts = Arrays.stream(artifactNames)
.map(artifactName -> ArtifactsTestUtil.findArtifact(myProject, artifactName)).toArray(Artifact[]::new);
build(artifacts);
}
else {
compile(createArtifactsScope(artifactNames));
}
}
private void build(Object[] buildableElements) {
Promise<ProjectTaskManager.Result> promise;
if (buildableElements instanceof Module[]) {
promise = ProjectTaskManager.getInstance(myProject).build((Module[])buildableElements);
}
else if (buildableElements instanceof Artifact[]) {
promise = ProjectTaskManager.getInstance(myProject).build((Artifact[])buildableElements);
}
else {
throw new AssertionError("Unsupported buildableElements: " + Arrays.toString(buildableElements));
}
edt(() -> PlatformTestUtil.waitForPromise(promise));
}
private void compile(@NotNull CompileScope scope) {
try {
CompilerTester tester = new CompilerTester(myProject, Arrays.asList(scope.getAffectedModules()), null);
try {
List<CompilerMessage> messages = tester.make(scope);
for (CompilerMessage message : messages) {
switch (message.getCategory()) {
case ERROR:
fail("Compilation failed with error: " + message.getMessage());
break;
case WARNING:
System.out.println("Compilation warning: " + message.getMessage());
break;
case INFORMATION:
break;
case STATISTICS:
break;
}
}
}
}.execute().getResultObject();
finally {
tester.tearDown();
}
}
catch (Exception e) {
ExceptionUtil.rethrow(e);
}
}
private CompileScope createModulesCompileScope(final String[] moduleNames) {
final List<Module> modules = new ArrayList<>();
for (String name : moduleNames) {
modules.add(getModule(name));
}
return new ModuleCompileScope(myProject, modules.toArray(Module.EMPTY_ARRAY), false);
}
private CompileScope createArtifactsScope(String[] artifactNames) {
List<Artifact> artifacts = new ArrayList<>();
for (String name : artifactNames) {
artifacts.add(ArtifactsTestUtil.findArtifact(myProject, name));
}
return ArtifactCompileScope.createArtifactsScope(myProject, artifacts);
}
protected Sdk setupJdkForModule(final String moduleName) {
final Sdk sdk = true ? JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk() : createJdk();
ModuleRootModificationUtil.setModuleSdk(getModule(moduleName), sdk);
return sdk;
}
protected static Sdk createJdk() {
return IdeaTestUtil.getMockJdk17();
}
protected Module getModule(final String name) {
return getModule(myProject, name);
}
protected Module getModule(Project project, String name) {
Module m = ReadAction.compute(() -> ModuleManager.getInstance(project).findModuleByName(name));
assertNotNull("Module " + name + " not found", m);
return m;
}
protected void assertExplodedLayout(String artifactName, String expected) {
assertJarLayout(artifactName + " exploded", expected);
}
protected void assertJarLayout(String artifactName, String expected) {
ArtifactsTestUtil.assertLayout(myProject, artifactName, expected);
}
protected void assertArtifactOutputPath(final String artifactName, final String expected) {
ArtifactsTestUtil.assertOutputPath(myProject, artifactName, expected);
}
protected void assertArtifactOutputFileName(final String artifactName, final String expected) {
ArtifactsTestUtil.assertOutputFileName(myProject, artifactName, expected);
}
protected void assertArtifactOutput(String artifactName, TestFileSystemItem fs) {
final Artifact artifact = ArtifactsTestUtil.findArtifact(myProject, artifactName);
final String outputFile = artifact.getOutputFilePath();
assert outputFile != null;
final File file = new File(outputFile);
assert file.exists();
fs.assertFileEqual(file);
}
protected static void setFileContent(final VirtualFile file, final String content, final boolean advanceStamps) {
try {
WriteAction.runAndWait(() -> {
if (advanceStamps) {
file.setBinaryContent(content.getBytes(StandardCharsets.UTF_8), -1, file.getTimeStamp() + 4000);
}
else {
file.setBinaryContent(content.getBytes(StandardCharsets.UTF_8), file.getModificationStamp(), file.getTimeStamp());
}
});
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
protected static <T, U> void assertOrderedElementsAreEqual(Collection<U> actual, Collection<T> expected) {
assertOrderedElementsAreEqual(actual, expected.toArray());
}
protected static <T> void assertUnorderedElementsAreEqual(Collection<T> actual, Collection<T> expected) {
assertEquals(new HashSet<>(expected), new HashSet<>(actual));
}
protected static void assertUnorderedPathsAreEqual(Collection<String> actual, Collection<String> expected) {
assertEquals(new SetWithToString<>(new THashSet<>(expected, FileUtil.PATH_HASHING_STRATEGY)),
new SetWithToString<>(new THashSet<>(actual, FileUtil.PATH_HASHING_STRATEGY)));
}
protected static <T> void assertUnorderedElementsAreEqual(T[] actual, T... expected) {
assertUnorderedElementsAreEqual(Arrays.asList(actual), expected);
}
protected static <T> void assertUnorderedElementsAreEqual(Collection<T> actual, T... expected) {
assertUnorderedElementsAreEqual(actual, Arrays.asList(expected));
}
protected static <T, U> void assertOrderedElementsAreEqual(Collection<U> actual, T... expected) {
assertOrderedElementsAreEqual(equalsPredicate(), actual, expected);
}
protected static <T, U> void assertOrderedElementsAreEqual(BiPredicate<U, T> predicate, Collection<U> actual, T... expected) {
String s = "\nexpected: " + Arrays.asList(expected) + "\nactual: " + new ArrayList<>(actual);
assertEquals(s, expected.length, actual.size());
java.util.List<U> actualList = new ArrayList<>(actual);
for (int i = 0; i < expected.length; i++) {
T expectedElement = expected[i];
U actualElement = actualList.get(i);
assertTrue(s, predicate.test(actualElement, expectedElement));
}
}
protected static <T> void assertContain(java.util.List<? extends T> actual, T... expected) {
java.util.List<T> expectedList = Arrays.asList(expected);
assertTrue("expected: " + expectedList + "\n" + "actual: " + actual.toString(), actual.containsAll(expectedList));
}
protected static <T> void assertDoNotContain(java.util.List<T> actual, T... expected) {
java.util.List<T> actualCopy = new ArrayList<>(actual);
actualCopy.removeAll(Arrays.asList(expected));
assertEquals(actual.toString(), actualCopy.size(), actual.size());
}
protected boolean ignore() {
printIgnoredMessage(null);
return true;
}
protected static <T, U> BiPredicate<T, U> equalsPredicate() {
//noinspection unchecked
return (BiPredicate<T, U>)EQUALS_PREDICATE;
}
public static void deleteBuildSystemDirectory() {
BuildManager buildManager = BuildManager.getInstance();
if (buildManager == null) return;
Path buildSystemDirectory = buildManager.getBuildSystemDirectory();
try {
PathKt.delete(buildSystemDirectory);
return;
}
catch (Exception ignore) {
}
try {
FileUtil.delete(buildSystemDirectory.toFile());
}
catch (Exception e) {
LOG.warn("Unable to remove build system directory.", e);
}
}
private void printIgnoredMessage(String message) {
@@ -293,4 +629,44 @@ public abstract class ExternalSystemTestCase extends UsefulTestCase {
toPrint += ": " + getClass().getSimpleName() + "." + getName();
System.out.println(toPrint);
}
private static class SetWithToString<T> extends AbstractSet<T> {
private final Set<T> myDelegate;
SetWithToString(@NotNull Set<T> delegate) {
myDelegate = delegate;
}
@Override
public int size() {
return myDelegate.size();
}
@Override
public boolean contains(Object o) {
return myDelegate.contains(o);
}
@NotNull
@Override
public Iterator<T> iterator() {
return myDelegate.iterator();
}
@Override
public boolean containsAll(Collection<?> c) {
return myDelegate.containsAll(c);
}
@Override
public boolean equals(Object o) {
return myDelegate.equals(o);
}
@Override
public int hashCode() {
return myDelegate.hashCode();
}
}
}
@@ -15,10 +15,11 @@
*/
package org.jetbrains.kotlin.idea.codeInsight.gradle
import com.intellij.compiler.server.BuildManager
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.application.Result
import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.externalSystem.importing.ImportSpec
import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder
import com.intellij.openapi.externalSystem.model.ProjectSystemId
import com.intellij.openapi.externalSystem.model.settings.ExternalSystemExecutionSettings
import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings
@@ -28,19 +29,28 @@ import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.fileEditor.impl.LoadTextUtil
import com.intellij.openapi.fileTypes.FileTypeManager
import com.intellij.openapi.projectRoots.JavaSdk
import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil
import com.intellij.openapi.ui.Messages
import com.intellij.openapi.ui.TestDialog
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess
import com.intellij.testFramework.IdeaTestUtil
import com.intellij.testFramework.RunAll
import com.intellij.testFramework.VfsTestUtil
import com.intellij.util.ArrayUtilRt
import com.intellij.util.PathUtil
import com.intellij.util.SmartList
import com.intellij.util.ThrowableRunnable
import com.intellij.util.containers.ContainerUtil
import junit.framework.TestCase
import org.gradle.StartParameter
import org.gradle.util.GradleVersion
import org.gradle.wrapper.GradleWrapperMain
import org.gradle.wrapper.PathAssembler
import org.intellij.lang.annotations.Language
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.idea.test.KotlinSdkCreationChecker
@@ -52,7 +62,9 @@ import org.jetbrains.kotlin.test.RunnerFactoryWithMuteInDatabase
import org.jetbrains.plugins.gradle.settings.DistributionType
import org.jetbrains.plugins.gradle.settings.GradleProjectSettings
import org.jetbrains.plugins.gradle.settings.GradleSettings
import org.jetbrains.plugins.gradle.settings.GradleSystemSettings
import org.jetbrains.plugins.gradle.util.GradleConstants
import org.jetbrains.plugins.gradle.util.GradleUtil
import org.jetbrains.plugins.groovy.GroovyFileType
import org.junit.AfterClass
import org.junit.Assume.assumeThat
@@ -67,6 +79,8 @@ import java.io.IOException
import java.io.StringWriter
import java.net.URISyntaxException
import java.util.*
import java.util.zip.ZipException
import java.util.zip.ZipFile
// part of org.jetbrains.plugins.gradle.importing.GradleImportingTestCase
@RunWith(value = JUnitParameterizedWithIdeaConfigurationRunner::class)
@@ -75,6 +89,8 @@ abstract class GradleImportingTestCase : ExternalSystemImportingTestCase() {
protected var sdkCreationChecker : KotlinSdkCreationChecker? = null
private val removedSdks: MutableList<Sdk> = SmartList()
@JvmField
@Rule
var name = TestName()
@@ -112,6 +128,7 @@ abstract class GradleImportingTestCase : ExternalSystemImportingTestCase() {
super.setUp()
assumeTrue(isApplicableTest())
assumeThat(gradleVersion, versionMatcherRule.matcher)
removedSdks.clear()
runWrite {
val jdkTable = getProjectJdkTableSafe()
jdkTable.findJdk(GRADLE_JDK_NAME)?.let {
@@ -127,47 +144,77 @@ abstract class GradleImportingTestCase : ExternalSystemImportingTestCase() {
myProjectSettings = GradleProjectSettings().apply {
this.isUseQualifiedModuleNames = false
}
System.setProperty(ExternalSystemExecutionSettings.REMOTE_PROCESS_IDLE_TTL_IN_MS_KEY, GRADLE_DAEMON_TTL_MS.toString())
val distribution = WriteAction.computeAndWait<PathAssembler.LocalDistribution, Throwable> { configureWrapper() }
val allowedRoots = ArrayList<String>()
collectAllowedRoots(allowedRoots, distribution)
if (!allowedRoots.isEmpty()) {
VfsRootAccess.allowRootAccess(myTestFixture.testRootDisposable, *ArrayUtilRt.toStringArray(allowedRoots))
}
GradleSettings.getInstance(myProject).gradleVmOptions =
"${jvmHeapArgsByGradleVersion(gradleVersion)} -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=${System.getProperty("user.dir")}"
System.setProperty(ExternalSystemExecutionSettings.REMOTE_PROCESS_IDLE_TTL_IN_MS_KEY, GRADLE_DAEMON_TTL_MS.toString())
configureWrapper()
sdkCreationChecker = KotlinSdkCreationChecker()
}
override fun tearDown() {
try {
runWrite {
val old = getProjectJdkTableSafe().findJdk(GRADLE_JDK_NAME)
if (old != null) {
SdkConfigurationUtil.removeSdk(old)
}
}
Messages.setTestDialog(TestDialog.DEFAULT)
FileUtil.delete(BuildManager.getInstance().buildSystemDirectory.toFile())
sdkCreationChecker?.removeNewKotlinSdk()
} finally {
super.tearDown()
if (myJdkHome == null) {
//super.setUp() wasn't called
return
}
RunAll(
ThrowableRunnable {
runWrite {
Arrays.stream(ProjectJdkTable.getInstance().allJdks).forEach { jdk: Sdk ->
ProjectJdkTable.getInstance().removeJdk(jdk)
}
for (sdk in removedSdks) {
SdkConfigurationUtil.addSdk(sdk)
}
removedSdks.clear()
}
},
ThrowableRunnable {
Messages.setTestDialog(TestDialog.DEFAULT)
deleteBuildSystemDirectory()
// was FileUtil.delete(BuildManager.getInstance().buildSystemDirectory.toFile())
sdkCreationChecker?.removeNewKotlinSdk()
},
ThrowableRunnable {
super.tearDown()
}
).run()
}
override fun collectAllowedRoots(roots: MutableList<String>) {
super.collectAllowedRoots(roots)
roots.add(myJdkHome)
roots.addAll(ExternalSystemTestCase.collectRootsInside(myJdkHome))
roots.add(PathManager.getConfigPath())
}
protected open fun collectAllowedRoots(
roots: MutableList<String>,
distribution: PathAssembler.LocalDistribution?
) {
//Note: could be required to use:
//Environment.getEnvVariable("JAVA_HOME")
roots.add(myJdkHome)
}
override fun getName(): String {
return if (name.methodName == null) super.getName() else FileUtil.sanitizeFileName(name.methodName)
}
override fun getExternalSystemConfigFileName(): String = "build.gradle"
protected fun importProjectUsingSingeModulePerGradleProject() {
myProjectSettings.isResolveModulePerSourceSet = false
importProject()
@Throws(IOException::class)
protected open fun importProjectUsingSingeModulePerGradleProject(config: String? = null) {
currentExternalProjectSettings.isResolveModulePerSourceSet = false
importProject(config)
}
override fun importProject() {
@@ -185,28 +232,43 @@ abstract class GradleImportingTestCase : ExternalSystemImportingTestCase() {
super.importProject()
}
override fun importProject(@NonNls @Language("Groovy") config: String) {
super.importProject(
"""
allprojects {
repositories {
maven {
url 'https://maven.labs.intellij.net/repo1'
}
}
}
@Throws(IOException::class)
override fun importProject(@NonNls @Language("Groovy") config: String?) {
var config = config
config = injectRepo(config)
super.importProject(config)
}
$config
""".trimIndent()
)
protected open fun injectRepo(@NonNls @Language("Groovy") config: String?): String {
var config = config ?: ""
config = """allprojects {
repositories {
maven {
url 'https://repo.labs.intellij.net/repo1'
}
}}
$config"""
return config
}
override fun createImportSpec(): ImportSpec? {
val importSpecBuilder = ImportSpecBuilder(super.createImportSpec())
importSpecBuilder.withArguments("--stacktrace")
return importSpecBuilder.build()
}
override fun getCurrentExternalProjectSettings(): GradleProjectSettings = myProjectSettings
override fun getExternalSystemId(): ProjectSystemId = GradleConstants.SYSTEM_ID
@Throws(IOException::class)
protected open fun createSettingsFile(@NonNls @Language("Groovy") content: String?): VirtualFile? {
return createProjectSubFile("settings.gradle", content)
}
@Throws(IOException::class, URISyntaxException::class)
private fun configureWrapper() {
private fun configureWrapper(): PathAssembler.LocalDistribution {
val distributionUri = AbstractModelBuilderTest.DistributionLocator().getDistributionFor(GradleVersion.version(gradleVersion))
myProjectSettings.distributionType = DistributionType.DEFAULT_WRAPPED
@@ -228,6 +290,27 @@ abstract class GradleImportingTestCase : ExternalSystemImportingTestCase() {
properties.store(writer, null)
createProjectSubFile("gradle/wrapper/gradle-wrapper.properties", writer.toString())
val wrapperConfiguration =
GradleUtil.getWrapperConfiguration(projectPath)
val localDistribution = PathAssembler(
StartParameter.DEFAULT_GRADLE_USER_HOME
).getDistribution(wrapperConfiguration)
val zip = localDistribution.zipFile
try {
if (zip.exists()) {
val zipFile = ZipFile(zip)
zipFile.close()
}
} catch (e: ZipException) {
e.printStackTrace()
println("Corrupted file will be removed: " + zip.path)
FileUtil.delete(zip)
} catch (e: IOException) {
e.printStackTrace()
}
return localDistribution
}
protected open fun testDataDirName(): String = ""
@@ -290,7 +373,6 @@ abstract class GradleImportingTestCase : ExternalSystemImportingTestCase() {
}
}
private fun runWrite(f: () -> Unit) {
object : WriteAction<Any>() {
override fun run(result: Result<Any>) {
@@ -299,6 +381,10 @@ abstract class GradleImportingTestCase : ExternalSystemImportingTestCase() {
}.execute()
}
protected open fun enableGradleDebugWithSuspend() {
GradleSystemSettings.getInstance().gradleVmOptions = "-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=5005"
}
companion object {
const val GRADLE_JDK_NAME = "Gradle JDK"
private const val GRADLE_DAEMON_TTL_MS = 10000
@@ -13,10 +13,9 @@ import org.jetbrains.annotations.NotNull;
public class TestImportSpecBuilder extends ImportSpecBuilder {
public TestImportSpecBuilder(
@NotNull Project project,
@NotNull ProjectSystemId id
@NotNull ImportSpec importSpec
) {
super(project, id);
super(importSpec);
}
public ImportSpecBuilder setCreateEmptyContentRoots(boolean value) {