blob: 449de84f46279dc68974cd36c9c6a1a7b8f3ff20 [file] [log] [blame]
/*
* Copyright 2000-2014 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.openapi.externalSystem.test;
import com.intellij.compiler.CompilerTestUtil;
import com.intellij.compiler.CompilerWorkspaceConfiguration;
import com.intellij.compiler.artifacts.ArtifactsTestUtil;
import com.intellij.compiler.impl.ModuleCompileScope;
import com.intellij.openapi.application.AccessToken;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.compiler.CompileContext;
import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.CompileStatusNotification;
import com.intellij.openapi.compiler.CompilerManager;
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.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.packaging.artifacts.Artifact;
import com.intellij.packaging.impl.compiler.ArtifactCompileScope;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.IdeaTestUtil;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.util.concurrency.Semaphore;
import com.intellij.util.io.TestFileSystemItem;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.junit.After;
import org.junit.Before;
import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.List;
/**
* @author Vladislav.Soroka
* @since 6/30/2014
*/
public abstract class ExternalSystemTestCase extends UsefulTestCase {
private static File ourTempDir;
protected IdeaProjectTestFixture myTestFixture;
protected Project myProject;
protected File myTestDir;
protected VirtualFile myProjectRoot;
protected VirtualFile myProjectConfig;
protected List<VirtualFile> myAllConfigs = new ArrayList<VirtualFile>();
static {
IdeaTestCase.initPlatformPrefix();
}
@Before
@Override
public void setUp() throws Exception {
super.setUp();
ensureTempDirCreated();
myTestDir = new File(ourTempDir, getTestName(false));
FileUtil.ensureExists(myTestDir);
setUpFixtures();
myProject = myTestFixture.getProject();
edt(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);
}
}
});
}
});
}
private void ensureTempDirCreated() throws IOException {
if (ourTempDir != null) return;
ourTempDir = new File(FileUtil.getTempDirectory(), getTestsTempDir());
FileUtil.delete(ourTempDir);
FileUtil.ensureExists(ourTempDir);
}
protected abstract String getTestsTempDir();
protected void setUpFixtures() throws Exception {
myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()).getFixture();
myTestFixture.setUp();
}
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 {
edt(new Runnable() {
@Override
public void run() {
try {
CompilerTestUtil.disableExternalCompiler(myProject);
tearDownFixtures();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
myProject = null;
if (!FileUtil.delete(myTestDir) && myTestDir.exists()) {
System.err.println("Cannot delete " + myTestDir);
//printDirectoryContent(myDir);
myTestDir.deleteOnExit();
}
}
finally {
super.tearDown();
resetClassFields(getClass());
}
}
private static void printDirectoryContent(File dir) {
File[] files = dir.listFiles();
if (files == null) return;
for (File file : files) {
System.out.println(file.getAbsolutePath());
if (file.isDirectory()) {
printDirectoryContent(file);
}
}
}
protected void tearDownFixtures() throws Exception {
myTestFixture.tearDown();
myTestFixture = null;
}
private void resetClassFields(final Class<?> aClass) {
if (aClass == null) return;
final Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
final int modifiers = field.getModifiers();
if ((modifiers & Modifier.FINAL) == 0
&& (modifiers & Modifier.STATIC) == 0
&& !field.getType().isPrimitive()) {
field.setAccessible(true);
try {
field.set(this, null);
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
if (aClass == ExternalSystemTestCase.class) return;
resetClassFields(aClass.getSuperclass());
}
@Override
protected void runTest() throws Throwable {
try {
if (runInWriteAction()) {
new WriteAction() {
@Override
protected void run(@NotNull Result result) throws Throwable {
ExternalSystemTestCase.super.runTest();
}
}.executeSilently().throwException();
}
else {
ExternalSystemTestCase.super.runTest();
}
}
catch (Exception throwable) {
Throwable each = throwable;
do {
if (each instanceof HeadlessException) {
printIgnoredMessage("Doesn't work in Headless environment");
return;
}
}
while ((each = each.getCause()) != null);
throw throwable;
}
}
@Override
protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception {
runnable.run();
}
protected boolean runInWriteAction() {
return false;
}
protected static String getRoot() {
if (SystemInfo.isWindows) return "c:";
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 String getParentPath() {
return myProjectRoot.getParent().getPath();
}
protected String pathFromBasedir(String relPath) {
return pathFromBasedir(myProjectRoot, relPath);
}
protected static String pathFromBasedir(VirtualFile root, String relPath) {
return FileUtil.toSystemIndependentName(root.getPath() + "/" + relPath);
}
protected Module createModule(String name) throws IOException {
return createModule(name, StdModuleTypes.JAVA);
}
protected Module createModule(final String name, final ModuleType type) throws IOException {
return new WriteCommandAction<Module>(myProject) {
@Override
protected void run(Result<Module> moduleResult) throws Throwable {
VirtualFile f = createProjectSubFile(name + "/" + name + ".iml");
Module module = ModuleManager.getInstance(myProject).newModule(f.getPath(), type.getId());
PsiTestUtil.addContentRoot(module, f.getParent());
moduleResult.setResult(module);
}
}.execute().getResultObject();
}
protected VirtualFile createProjectConfig(@NonNls String config) throws IOException {
return myProjectConfig = createConfigFile(myProjectRoot, config);
}
protected 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(Result<VirtualFile> result) throws Throwable {
VirtualFile res = dir.createChildData(null, configFileName);
result.setResult(res);
}
}.execute().getResultObject();
myAllConfigs.add(f);
}
setFileContent(f, config, true);
return f;
}
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);
final boolean created = f.createNewFile();
if(!created) {
throw new AssertionError("Unable to create the project sub file: " + f.getAbsolutePath());
}
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
}
protected VirtualFile createProjectSubFile(String relativePath, String content) throws IOException {
VirtualFile file = createProjectSubFile(relativePath);
setFileContent(file, content, false);
return file;
}
protected void compileModules(final String... moduleNames) {
compile(createModulesCompileScope(moduleNames));
}
protected void buildArtifacts(String... artifactNames) {
compile(createArtifactsScope(artifactNames));
}
private void compile(final CompileScope scope) {
edt(new Runnable() {
@Override
public void run() {
for (Module module : scope.getAffectedModules()) {
setupJdkForModule(module.getName());
}
}
});
CompilerWorkspaceConfiguration.getInstance(myProject).CLEAR_OUTPUT_DIRECTORY = true;
final Semaphore semaphore = new Semaphore();
semaphore.down();
edt(new Runnable() {
@Override
public void run() {
CompilerTestUtil.enableExternalCompiler();
CompilerManager.getInstance(myProject).make(scope, new CompileStatusNotification() {
@Override
public void finished(boolean aborted, int errors, int warnings, CompileContext compileContext) {
//assertFalse(aborted);
//assertEquals(collectMessages(compileContext, CompilerMessageCategory.ERROR), 0, errors);
//assertEquals(collectMessages(compileContext, CompilerMessageCategory.WARNING), 0, warnings);
semaphore.up();
}
});
}
});
while (!semaphore.waitFor(100)) {
if (SwingUtilities.isEventDispatchThread()) {
UIUtil.dispatchAllInvocationEvents();
}
}
if (SwingUtilities.isEventDispatchThread()) {
UIUtil.dispatchAllInvocationEvents();
}
}
private CompileScope createModulesCompileScope(final String[] moduleNames) {
final List<Module> modules = new ArrayList<Module>();
for (String name : moduleNames) {
modules.add(getModule(name));
}
return new ModuleCompileScope(myProject, modules.toArray(new Module[modules.size()]), false);
}
private CompileScope createArtifactsScope(String[] artifactNames) {
List<Artifact> artifacts = new ArrayList<Artifact>();
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("Java 1.5");
ModuleRootModificationUtil.setModuleSdk(getModule(moduleName), sdk);
return sdk;
}
protected static Sdk createJdk(String versionName) {
return IdeaTestUtil.getMockJdk17(versionName);
}
protected Module getModule(final String name) {
AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
try {
Module m = ModuleManager.getInstance(myProject).findModuleByName(name);
assertNotNull("Module " + name + " not found", m);
return m;
}
finally {
accessToken.finish();
}
}
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 VirtualFile outputFile = artifact.getOutputFile();
assert outputFile != null;
final File file = VfsUtilCore.virtualToIoFile(outputFile);
fs.assertFileEqual(file);
}
private 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("UTF-8"), -1, file.getTimeStamp() + 4000);
}
else {
file.setBinaryContent(content.getBytes("UTF-8"), file.getModificationStamp(), file.getTimeStamp());
}
}
}.execute().getResultObject();
}
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<T>(expected), new HashSet<T>(actual));
}
protected static void assertUnorderedPathsAreEqual(Collection<String> actual, Collection<String> expected) {
assertEquals(new SetWithToString<String>(new THashSet<String>(expected, FileUtil.PATH_HASHING_STRATEGY)),
new SetWithToString<String>(new THashSet<String>(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) {
String s = "\nexpected: " + Arrays.asList(expected) + "\nactual: " + new ArrayList<U>(actual);
assertEquals(s, expected.length, actual.size());
java.util.List<U> actualList = new ArrayList<U>(actual);
for (int i = 0; i < expected.length; i++) {
T expectedElement = expected[i];
U actualElement = actualList.get(i);
assertEquals(s, expectedElement, actualElement);
}
}
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<T>(actual);
actualCopy.removeAll(Arrays.asList(expected));
assertEquals(actual.toString(), actualCopy.size(), actual.size());
}
protected boolean ignore() {
printIgnoredMessage(null);
return true;
}
private void printIgnoredMessage(String message) {
String toPrint = "Ignored";
if (message != null) {
toPrint += ", because " + message;
}
toPrint += ": " + getClass().getSimpleName() + "." + getName();
System.out.println(toPrint);
}
private static class SetWithToString<T> extends AbstractSet<T> {
private final Set<T> myDelegate;
public 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();
}
}
}