Test Framework refactored to allow fully customized project setup

This commit is contained in:
Anton Makeev
2015-07-16 13:31:29 +02:00
parent 889c7e23b4
commit 6ad1dcbfef
5 changed files with 139 additions and 153 deletions
@@ -30,7 +30,7 @@ import org.jetbrains.annotations.NotNull;
/**
* @author peter
*/
public class DefaultLightProjectDescriptor implements LightProjectDescriptor {
public class DefaultLightProjectDescriptor extends LightProjectDescriptor {
@NotNull
@Override
public ModuleType getModuleType() {
@@ -53,7 +53,6 @@ import com.intellij.openapi.fileTypes.FileTypeManager;
import com.intellij.openapi.fileTypes.impl.FileTypeManagerImpl;
import com.intellij.openapi.module.EmptyModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.ModuleAdapter;
import com.intellij.openapi.project.Project;
@@ -61,18 +60,19 @@ import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ex.ProjectManagerEx;
import com.intellij.openapi.project.impl.ProjectManagerImpl;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.ShutDownTracker;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.encoding.EncodingManager;
import com.intellij.openapi.vfs.encoding.EncodingManagerImpl;
import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
import com.intellij.openapi.vfs.impl.VirtualFilePointerManagerImpl;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFS;
import com.intellij.openapi.vfs.newvfs.persistent.PersistentFSImpl;
@@ -92,19 +92,17 @@ import com.intellij.psi.impl.PsiManagerImpl;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageManagerImpl;
import com.intellij.psi.templateLanguages.TemplateDataLanguageMappings;
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl;
import com.intellij.util.Consumer;
import com.intellij.util.GCUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.LocalTimeCounter;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.indexing.IndexableFileSet;
import com.intellij.util.messages.MessageBusConnection;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashMap;
import junit.framework.TestCase;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import javax.swing.*;
@@ -119,8 +117,6 @@ import java.util.Collections;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
import static com.intellij.openapi.roots.ModuleRootModificationUtil.updateModel;
/**
* @author yole
*/
@@ -228,11 +224,6 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
((PersistentFSImpl)PersistentFS.getInstance()).cleanPersistedContents();
}
public static boolean isLight(@NotNull Project project) {
String creationPlace = project.getUserData(CREATION_PLACE);
return creationPlace != null && StringUtil.startsWith(creationPlace, LIGHT_PROJECT_MARK);
}
private static void initProject(@NotNull final LightProjectDescriptor descriptor) throws Exception {
ourProjectDescriptor = descriptor;
@@ -261,78 +252,10 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
registerShutdownHook();
}
ourPsiManager = null;
ourModule = createMainModule(descriptor.getModuleType());
if (descriptor instanceof LightProjectDescriptorEx) {
((LightProjectDescriptorEx)descriptor).setupModule(ourModule);
if(!((LightProjectDescriptorEx)descriptor).shouldConfigureModule()) return;
}
VirtualFile dummyRoot = VirtualFileManager.getInstance().findFileByUrl("temp:///");
assert dummyRoot != null;
dummyRoot.refresh(false, false);
try {
ourSourceRoot = dummyRoot.createChildDirectory(this, "src");
cleanSourceRoot();
}
catch (IOException e) {
throw new RuntimeException(e);
}
final IndexableFileSet indexableFileSet = new IndexableFileSet() {
@Override
public boolean isInSet(@NotNull final VirtualFile file) {
return ourSourceRoot != null &&
file.getFileSystem() == ourSourceRoot.getFileSystem() &&
ourProject != null &&
ourProject.isOpen();
}
@Override
public void iterateIndexableFilesIn(@NotNull final VirtualFile file, @NotNull final ContentIterator iterator) {
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
@Override
public boolean visitFile(@NotNull VirtualFile file) {
iterator.processFile(file);
return true;
}
});
}
};
FileBasedIndex.getInstance().registerIndexableSet(indexableFileSet, null);
Disposer.register(ourProject, new Disposable() {
@Override
public void dispose() {
FileBasedIndex.getInstance().removeIndexableSet(indexableFileSet);
}
});
updateModel(ourModule, new Consumer<ModifiableRootModel>() {
@Override
public void consume(ModifiableRootModel model) {
final Sdk sdk = descriptor.getSdk();
if (sdk != null) {
model.setSdk(sdk);
}
ContentEntry contentEntry = model.addContentEntry(ourSourceRoot);
contentEntry.addSourceFolder(ourSourceRoot, false);
descriptor.configureModule(ourModule, model, contentEntry);
}
});
}
private void cleanSourceRoot() throws IOException {
TempFileSystem tempFs = (TempFileSystem)ourSourceRoot.getFileSystem();
for (VirtualFile child : ourSourceRoot.getChildren()) {
if (!tempFs.exists(child)) {
tempFs.createChildFile(this, ourSourceRoot, child.getName());
}
child.delete(this);
}
LightProjectDescriptor.ProjectInfo projectInfo = ourProjectDescriptor.setUpProject(ourProject);
ourModule = projectInfo.module;
ourSourceRoot = projectInfo.moduleSourcesRoot;
}
}.execute().throwException();
@@ -340,15 +263,6 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
((VirtualFilePointerManagerImpl)VirtualFilePointerManager.getInstance()).storePointers();
}
@NotNull
protected static Module createMainModule(@NotNull final ModuleType moduleType) {
return ApplicationManager.getApplication().runWriteAction(new Computable<Module>() {
@Override
public Module compute() {
return ModuleManager.getInstance(ourProject).newModule("light_idea_test_case.iml", moduleType.getId());
}
});
}
/**
* @return The only source root
@@ -838,11 +752,11 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
});
}
private static class SimpleLightProjectDescriptor implements LightProjectDescriptor {
private static class SimpleLightProjectDescriptor extends LightProjectDescriptor {
@NotNull private final ModuleType myModuleType;
private final Sdk mySdk;
@Nullable private final Sdk mySdk;
SimpleLightProjectDescriptor(@NotNull ModuleType moduleType, Sdk sdk) {
SimpleLightProjectDescriptor(@NotNull ModuleType moduleType, @Nullable Sdk sdk) {
myModuleType = moduleType;
mySdk = sdk;
}
@@ -853,15 +767,12 @@ public abstract class LightPlatformTestCase extends UsefulTestCase implements Da
return myModuleType;
}
@Nullable
@Override
public Sdk getSdk() {
return mySdk;
}
@Override
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
@@ -15,39 +15,144 @@
*/
package com.intellij.testFramework;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.EmptyModuleType;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ContentIterator;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.openapi.vfs.VirtualFileVisitor;
import com.intellij.openapi.vfs.ex.temp.TempFileSystem;
import com.intellij.util.Consumer;
import com.intellij.util.indexing.FileBasedIndex;
import com.intellij.util.indexing.IndexableFileSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.IOException;
import static com.intellij.openapi.roots.ModuleRootModificationUtil.updateModel;
public class LightProjectDescriptor {
public static final LightProjectDescriptor EMPTY_PROJECT_DESCRIPTOR = new LightProjectDescriptor();
/**
* @author yole
*/
public interface LightProjectDescriptor {
@NotNull
ModuleType getModuleType();
Sdk getSdk();
void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry);
public ProjectInfo setUpProject(@NotNull Project project) throws Exception {
Module module = createMainModule(project);
VirtualFile contentRoot = createSourcesRoot(module);
return new ProjectInfo(module, contentRoot);
}
class Empty implements LightProjectDescriptor {
@NotNull
@Override
public ModuleType getModuleType() {
return EmptyModuleType.getInstance();
@NotNull
public Module createMainModule(@NotNull final Project project) {
return ApplicationManager.getApplication().runWriteAction(new Computable<Module>() {
@Override
public Module compute() {
return ModuleManager.getInstance(project).newModule("light_idea_test_case.iml", getModuleType().getId());
}
});
}
@NotNull
public ModuleType getModuleType() {
return EmptyModuleType.getInstance();
}
@Nullable
public VirtualFile createSourcesRoot(@NotNull final Module module) {
VirtualFile dummyRoot = VirtualFileManager.getInstance().findFileByUrl("temp:///");
assert dummyRoot != null;
dummyRoot.refresh(false, false);
final VirtualFile srcRoot;
try {
srcRoot = dummyRoot.createChildDirectory(this, "src");
cleanSourceRoot(srcRoot);
}
catch (IOException e) {
throw new RuntimeException(e);
}
@Override
public Sdk getSdk() {
return null;
}
final IndexableFileSet indexableFileSet = new IndexableFileSet() {
@Override
public boolean isInSet(@NotNull final VirtualFile file) {
return file.getFileSystem() == srcRoot.getFileSystem() &&
module.getProject().isOpen();
}
@Override
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
@Override
public void iterateIndexableFilesIn(@NotNull final VirtualFile file, @NotNull final ContentIterator iterator) {
VfsUtilCore.visitChildrenRecursively(file, new VirtualFileVisitor() {
@Override
public boolean visitFile(@NotNull VirtualFile file) {
iterator.processFile(file);
return true;
}
});
}
};
FileBasedIndex.getInstance().registerIndexableSet(indexableFileSet, null);
Disposer.register(module.getProject(), new Disposable() {
@Override
public void dispose() {
FileBasedIndex.getInstance().removeIndexableSet(indexableFileSet);
}
});
updateModel(module, new Consumer<ModifiableRootModel>() {
@Override
public void consume(ModifiableRootModel model) {
Sdk sdk = getSdk();
if (sdk != null) {
model.setSdk(sdk);
}
ContentEntry contentEntry = model.addContentEntry(srcRoot);
contentEntry.addSourceFolder(srcRoot, false);
configureModule(module, model, contentEntry);
}
});
return srcRoot;
}
@Nullable
public Sdk getSdk() {
return null;
}
private void cleanSourceRoot(@NotNull VirtualFile contentRoot) throws IOException {
TempFileSystem tempFs = (TempFileSystem)contentRoot.getFileSystem();
for (VirtualFile child : contentRoot.getChildren()) {
if (!tempFs.exists(child)) {
tempFs.createChildFile(this, contentRoot, child.getName());
}
child.delete(this);
}
}
LightProjectDescriptor EMPTY_PROJECT_DESCRIPTOR = new Empty();
protected void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
}
public static class ProjectInfo {
@NotNull public final Module module;
@Nullable public final VirtualFile moduleSourcesRoot;
public ProjectInfo(@NotNull Module module, @Nullable VirtualFile moduleSourcesRoot) {
this.module = module;
this.moduleSourcesRoot = moduleSourcesRoot;
}
}
}
@@ -1,24 +0,0 @@
/*
* Copyright 2000-2015 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.testFramework;
import com.intellij.openapi.module.Module;
public interface LightProjectDescriptorEx extends LightProjectDescriptor {
boolean shouldConfigureModule();
void setupModule(Module module);
}
@@ -16,10 +16,8 @@
package com.jetbrains.python.fixtures;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.ContentEntry;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.roots.libraries.Library;
@@ -34,7 +32,7 @@ import org.jetbrains.annotations.NotNull;
* Project descriptor (extracted from {@link com.jetbrains.python.fixtures.PyTestCase}) and should be used with it.
* @author Ilya.Kazakevich
*/
public class PyLightProjectDescriptor implements LightProjectDescriptor {
public class PyLightProjectDescriptor extends LightProjectDescriptor {
private final String myPythonVersion;
public PyLightProjectDescriptor(String pythonVersion) {
@@ -52,10 +50,6 @@ public class PyLightProjectDescriptor implements LightProjectDescriptor {
return PythonMockSdk.findOrCreate(myPythonVersion);
}
@Override
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, @NotNull ContentEntry contentEntry) {
}
protected void createLibrary(ModifiableRootModel model, final String name, final String path) {
final Library.ModifiableModel modifiableModel = model.getModuleLibraryTable().createLibrary(name).getModifiableModel();
final VirtualFile home =