2 * Copyright 2000-2014 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.openapi.externalSystem.test;
18 import com.intellij.compiler.CompilerTestUtil;
19 import com.intellij.compiler.artifacts.ArtifactsTestUtil;
20 import com.intellij.compiler.impl.ModuleCompileScope;
21 import com.intellij.openapi.application.AccessToken;
22 import com.intellij.openapi.application.ApplicationManager;
23 import com.intellij.openapi.application.Result;
24 import com.intellij.openapi.application.WriteAction;
25 import com.intellij.openapi.command.WriteCommandAction;
26 import com.intellij.openapi.compiler.CompileScope;
27 import com.intellij.openapi.compiler.CompilerMessage;
28 import com.intellij.openapi.module.Module;
29 import com.intellij.openapi.module.ModuleManager;
30 import com.intellij.openapi.module.ModuleType;
31 import com.intellij.openapi.module.StdModuleTypes;
32 import com.intellij.openapi.project.Project;
33 import com.intellij.openapi.projectRoots.Sdk;
34 import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
35 import com.intellij.openapi.roots.ModuleRootModificationUtil;
36 import com.intellij.openapi.util.Pair;
37 import com.intellij.openapi.util.SystemInfo;
38 import com.intellij.openapi.util.io.ByteSequence;
39 import com.intellij.openapi.util.io.FileUtil;
40 import com.intellij.openapi.util.io.FileUtilRt;
41 import com.intellij.openapi.vfs.*;
42 import com.intellij.packaging.artifacts.Artifact;
43 import com.intellij.packaging.impl.compiler.ArtifactCompileScope;
44 import com.intellij.testFramework.*;
45 import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
46 import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
47 import com.intellij.util.io.TestFileSystemItem;
48 import gnu.trove.THashSet;
49 import org.jetbrains.annotations.NonNls;
50 import org.jetbrains.annotations.NotNull;
51 import org.junit.After;
52 import org.junit.Before;
56 import java.io.FileOutputStream;
57 import java.io.IOException;
58 import java.lang.reflect.Field;
59 import java.lang.reflect.Modifier;
61 import java.util.List;
62 import java.util.jar.Attributes;
63 import java.util.jar.JarEntry;
64 import java.util.jar.JarOutputStream;
65 import java.util.jar.Manifest;
68 * @author Vladislav.Soroka
71 public abstract class ExternalSystemTestCase extends UsefulTestCase {
72 private File ourTempDir;
74 protected IdeaProjectTestFixture myTestFixture;
76 protected Project myProject;
78 protected File myTestDir;
79 protected VirtualFile myProjectRoot;
80 protected VirtualFile myProjectConfig;
81 protected List<VirtualFile> myAllConfigs = new ArrayList<VirtualFile>();
84 IdeaTestCase.initPlatformPrefix();
89 public void setUp() throws Exception {
91 ensureTempDirCreated();
93 myTestDir = new File(ourTempDir, getTestName(false));
94 FileUtil.ensureExists(myTestDir);
97 myProject = myTestFixture.getProject();
102 ApplicationManager.getApplication().runWriteAction(new Runnable() {
106 setUpInWriteAction();
108 catch (Throwable e) {
112 catch (Exception e1) {
113 e1.printStackTrace();
115 throw new RuntimeException(e);
123 private void ensureTempDirCreated() throws IOException {
124 if (ourTempDir != null) return;
126 ourTempDir = new File(FileUtil.getTempDirectory(), getTestsTempDir());
127 FileUtil.delete(ourTempDir);
128 FileUtil.ensureExists(ourTempDir);
131 protected abstract String getTestsTempDir();
133 protected void setUpFixtures() throws Exception {
134 myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()).getFixture();
135 myTestFixture.setUp();
138 protected void setUpInWriteAction() throws Exception {
139 File projectDir = new File(myTestDir, "project");
140 FileUtil.ensureExists(projectDir);
141 myProjectRoot = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(projectDir);
146 public void tearDown() throws Exception {
152 CompilerTestUtil.disableExternalCompiler(myProject);
155 catch (Exception e) {
156 throw new RuntimeException(e);
161 if (!FileUtil.delete(myTestDir) && myTestDir.exists()) {
162 System.err.println("Cannot delete " + myTestDir);
163 //printDirectoryContent(myDir);
164 myTestDir.deleteOnExit();
169 resetClassFields(getClass());
173 private static void printDirectoryContent(File dir) {
174 File[] files = dir.listFiles();
175 if (files == null) return;
177 for (File file : files) {
178 System.out.println(file.getAbsolutePath());
180 if (file.isDirectory()) {
181 printDirectoryContent(file);
186 protected void tearDownFixtures() throws Exception {
187 myTestFixture.tearDown();
188 myTestFixture = null;
191 private void resetClassFields(final Class<?> aClass) {
192 if (aClass == null) return;
194 final Field[] fields = aClass.getDeclaredFields();
195 for (Field field : fields) {
196 final int modifiers = field.getModifiers();
197 if ((modifiers & Modifier.FINAL) == 0
198 && (modifiers & Modifier.STATIC) == 0
199 && !field.getType().isPrimitive()) {
200 field.setAccessible(true);
202 field.set(this, null);
204 catch (IllegalAccessException e) {
210 if (aClass == ExternalSystemTestCase.class) return;
211 resetClassFields(aClass.getSuperclass());
215 protected void runTest() throws Throwable {
217 if (runInWriteAction()) {
220 protected void run(@NotNull Result result) throws Throwable {
221 ExternalSystemTestCase.super.runTest();
223 }.executeSilently().throwException();
226 ExternalSystemTestCase.super.runTest();
229 catch (Exception throwable) {
230 Throwable each = throwable;
232 if (each instanceof HeadlessException) {
233 printIgnoredMessage("Doesn't work in Headless environment");
237 while ((each = each.getCause()) != null);
243 protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception {
247 protected boolean runInWriteAction() {
251 protected static String getRoot() {
252 if (SystemInfo.isWindows) return "c:";
256 protected static String getEnvVar() {
257 if (SystemInfo.isWindows) return "TEMP";
258 else if (SystemInfo.isLinux) return "HOME";
262 protected String getProjectPath() {
263 return myProjectRoot.getPath();
266 protected String getParentPath() {
267 return myProjectRoot.getParent().getPath();
270 protected String pathFromBasedir(String relPath) {
271 return pathFromBasedir(myProjectRoot, relPath);
274 protected static String pathFromBasedir(VirtualFile root, String relPath) {
275 return FileUtil.toSystemIndependentName(root.getPath() + "/" + relPath);
278 protected Module createModule(String name) throws IOException {
279 return createModule(name, StdModuleTypes.JAVA);
282 protected Module createModule(final String name, final ModuleType type) throws IOException {
283 return new WriteCommandAction<Module>(myProject) {
285 protected void run(Result<Module> moduleResult) throws Throwable {
286 VirtualFile f = createProjectSubFile(name + "/" + name + ".iml");
287 Module module = ModuleManager.getInstance(myProject).newModule(f.getPath(), type.getId());
288 PsiTestUtil.addContentRoot(module, f.getParent());
289 moduleResult.setResult(module);
291 }.execute().getResultObject();
294 protected VirtualFile createProjectConfig(@NonNls String config) throws IOException {
295 return myProjectConfig = createConfigFile(myProjectRoot, config);
298 protected VirtualFile createConfigFile(final VirtualFile dir, String config) throws IOException {
299 final String configFileName = getExternalSystemConfigFileName();
300 VirtualFile f = dir.findChild(configFileName);
302 f = new WriteAction<VirtualFile>() {
304 protected void run(Result<VirtualFile> result) throws Throwable {
305 VirtualFile res = dir.createChildData(null, configFileName);
306 result.setResult(res);
308 }.execute().getResultObject();
311 setFileContent(f, config, true);
315 protected abstract String getExternalSystemConfigFileName();
317 protected void createStdProjectFolders() throws IOException {
318 createProjectSubDirs("src/main/java",
319 "src/main/resources",
321 "src/test/resources");
324 protected void createProjectSubDirs(String... relativePaths) throws IOException {
325 for (String path : relativePaths) {
326 createProjectSubDir(path);
330 protected VirtualFile createProjectSubDir(String relativePath) throws IOException {
331 File f = new File(getProjectPath(), relativePath);
332 FileUtil.ensureExists(f);
333 return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
336 protected VirtualFile createProjectSubFile(String relativePath) throws IOException {
337 File f = new File(getProjectPath(), relativePath);
338 FileUtil.ensureExists(f.getParentFile());
339 FileUtil.ensureCanCreateFile(f);
340 final boolean created = f.createNewFile();
342 throw new AssertionError("Unable to create the project sub file: " + f.getAbsolutePath());
344 return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
348 protected VirtualFile createProjectJarSubFile(String relativePath, Pair<ByteSequence, String>... contentEntries) throws IOException {
349 assertTrue("Use 'jar' extension for JAR files: '" + relativePath + "'", FileUtilRt.extensionEquals(relativePath, "jar"));
350 File f = new File(getProjectPath(), relativePath);
351 FileUtil.ensureExists(f.getParentFile());
352 FileUtil.ensureCanCreateFile(f);
353 final boolean created = f.createNewFile();
355 throw new AssertionError("Unable to create the project sub file: " + f.getAbsolutePath());
358 Manifest manifest = new Manifest();
359 manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
360 JarOutputStream target = new JarOutputStream(new FileOutputStream(f), manifest);
361 for (Pair<ByteSequence, String> contentEntry : contentEntries) {
362 addJarEntry(contentEntry.first.getBytes(), contentEntry.second, target);
366 final VirtualFile virtualFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
367 assertNotNull(virtualFile);
368 final VirtualFile jarFile = JarFileSystem.getInstance().getJarRootForLocalFile(virtualFile);
369 assertNotNull(jarFile);
373 private static void addJarEntry(byte[] bytes, String path, JarOutputStream target) throws IOException {
374 JarEntry entry = new JarEntry(path.replace("\\", "/"));
375 target.putNextEntry(entry);
380 protected VirtualFile createProjectSubFile(String relativePath, String content) throws IOException {
381 VirtualFile file = createProjectSubFile(relativePath);
382 setFileContent(file, content, false);
387 protected void compileModules(final String... moduleNames) {
388 compile(createModulesCompileScope(moduleNames));
391 protected void buildArtifacts(String... artifactNames) {
392 compile(createArtifactsScope(artifactNames));
395 private void compile(final CompileScope scope) {
397 CompilerTester tester = new CompilerTester(myProject, Arrays.asList(scope.getAffectedModules()));
399 List<CompilerMessage> messages = tester.make(scope);
400 for (CompilerMessage message : messages) {
401 switch (message.getCategory()) {
403 fail("Compilation failed with error: " + message.getMessage());
406 System.out.println("Compilation warning: " + message.getMessage());
419 catch (Exception e) {
420 throw new RuntimeException(e);
425 private CompileScope createModulesCompileScope(final String[] moduleNames) {
426 final List<Module> modules = new ArrayList<Module>();
427 for (String name : moduleNames) {
428 modules.add(getModule(name));
430 return new ModuleCompileScope(myProject, modules.toArray(new Module[modules.size()]), false);
433 private CompileScope createArtifactsScope(String[] artifactNames) {
434 List<Artifact> artifacts = new ArrayList<Artifact>();
435 for (String name : artifactNames) {
436 artifacts.add(ArtifactsTestUtil.findArtifact(myProject, name));
438 return ArtifactCompileScope.createArtifactsScope(myProject, artifacts);
441 protected Sdk setupJdkForModule(final String moduleName) {
442 final Sdk sdk = true ? JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk() : createJdk("Java 1.5");
443 ModuleRootModificationUtil.setModuleSdk(getModule(moduleName), sdk);
447 protected static Sdk createJdk(String versionName) {
448 return IdeaTestUtil.getMockJdk17(versionName);
451 protected Module getModule(final String name) {
452 AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
454 Module m = ModuleManager.getInstance(myProject).findModuleByName(name);
455 assertNotNull("Module " + name + " not found", m);
459 accessToken.finish();
463 protected void assertExplodedLayout(String artifactName, String expected) {
464 assertJarLayout(artifactName + " exploded", expected);
467 protected void assertJarLayout(String artifactName, String expected) {
468 ArtifactsTestUtil.assertLayout(myProject, artifactName, expected);
471 protected void assertArtifactOutputPath(final String artifactName, final String expected) {
472 ArtifactsTestUtil.assertOutputPath(myProject, artifactName, expected);
475 protected void assertArtifactOutputFileName(final String artifactName, final String expected) {
476 ArtifactsTestUtil.assertOutputFileName(myProject, artifactName, expected);
479 protected void assertArtifactOutput(String artifactName, TestFileSystemItem fs) {
480 final Artifact artifact = ArtifactsTestUtil.findArtifact(myProject, artifactName);
481 final VirtualFile outputFile = artifact.getOutputFile();
482 assert outputFile != null;
483 final File file = VfsUtilCore.virtualToIoFile(outputFile);
484 fs.assertFileEqual(file);
487 private static void setFileContent(final VirtualFile file, final String content, final boolean advanceStamps) throws IOException {
488 new WriteAction<VirtualFile>() {
490 protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
492 file.setBinaryContent(content.getBytes(CharsetToolkit.UTF8_CHARSET), -1, file.getTimeStamp() + 4000);
495 file.setBinaryContent(content.getBytes(CharsetToolkit.UTF8_CHARSET), file.getModificationStamp(), file.getTimeStamp());
498 }.execute().getResultObject();
501 protected static <T, U> void assertOrderedElementsAreEqual(Collection<U> actual, Collection<T> expected) {
502 assertOrderedElementsAreEqual(actual, expected.toArray());
505 protected static <T> void assertUnorderedElementsAreEqual(Collection<T> actual, Collection<T> expected) {
506 assertEquals(new HashSet<T>(expected), new HashSet<T>(actual));
508 protected static void assertUnorderedPathsAreEqual(Collection<String> actual, Collection<String> expected) {
509 assertEquals(new SetWithToString<String>(new THashSet<String>(expected, FileUtil.PATH_HASHING_STRATEGY)),
510 new SetWithToString<String>(new THashSet<String>(actual, FileUtil.PATH_HASHING_STRATEGY)));
513 protected static <T> void assertUnorderedElementsAreEqual(T[] actual, T... expected) {
514 assertUnorderedElementsAreEqual(Arrays.asList(actual), expected);
517 protected static <T> void assertUnorderedElementsAreEqual(Collection<T> actual, T... expected) {
518 assertUnorderedElementsAreEqual(actual, Arrays.asList(expected));
521 protected static <T, U> void assertOrderedElementsAreEqual(Collection<U> actual, T... expected) {
522 String s = "\nexpected: " + Arrays.asList(expected) + "\nactual: " + new ArrayList<U>(actual);
523 assertEquals(s, expected.length, actual.size());
525 java.util.List<U> actualList = new ArrayList<U>(actual);
526 for (int i = 0; i < expected.length; i++) {
527 T expectedElement = expected[i];
528 U actualElement = actualList.get(i);
529 assertEquals(s, expectedElement, actualElement);
533 protected static <T> void assertContain(java.util.List<? extends T> actual, T... expected) {
534 java.util.List<T> expectedList = Arrays.asList(expected);
535 assertTrue("expected: " + expectedList + "\n" + "actual: " + actual.toString(), actual.containsAll(expectedList));
538 protected static <T> void assertDoNotContain(java.util.List<T> actual, T... expected) {
539 java.util.List<T> actualCopy = new ArrayList<T>(actual);
540 actualCopy.removeAll(Arrays.asList(expected));
541 assertEquals(actual.toString(), actualCopy.size(), actual.size());
544 protected boolean ignore() {
545 printIgnoredMessage(null);
549 private void printIgnoredMessage(String message) {
550 String toPrint = "Ignored";
551 if (message != null) {
552 toPrint += ", because " + message;
554 toPrint += ": " + getClass().getSimpleName() + "." + getName();
555 System.out.println(toPrint);
558 private static class SetWithToString<T> extends AbstractSet<T> {
560 private final Set<T> myDelegate;
562 public SetWithToString(@NotNull Set<T> delegate) {
563 myDelegate = delegate;
568 return myDelegate.size();
572 public boolean contains(Object o) {
573 return myDelegate.contains(o);
578 public Iterator<T> iterator() {
579 return myDelegate.iterator();
583 public boolean containsAll(Collection<?> c) {
584 return myDelegate.containsAll(c);
588 public boolean equals(Object o) {
589 return myDelegate.equals(o);
593 public int hashCode() {
594 return myDelegate.hashCode();