| /* |
| * Copyright 2000-2009 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 org.jetbrains.android; |
| |
| import com.android.SdkConstants; |
| import com.android.ide.common.rendering.RenderSecurityManager; |
| import com.intellij.analysis.AnalysisScope; |
| import com.intellij.codeInspection.GlobalInspectionTool; |
| import com.intellij.codeInspection.InspectionManager; |
| import com.intellij.codeInspection.ex.GlobalInspectionToolWrapper; |
| import com.intellij.codeInspection.ex.InspectionManagerEx; |
| import com.intellij.facet.FacetManager; |
| import com.intellij.facet.ModifiableFacetModel; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.module.Module; |
| import com.intellij.openapi.roots.LanguageLevelProjectExtension; |
| import com.intellij.openapi.roots.ModuleRootModificationUtil; |
| import com.intellij.openapi.vfs.VirtualFile; |
| import com.intellij.pom.java.LanguageLevel; |
| import com.intellij.testFramework.InspectionTestUtil; |
| import com.intellij.testFramework.builders.JavaModuleFixtureBuilder; |
| import com.intellij.testFramework.fixtures.IdeaProjectTestFixture; |
| import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory; |
| import com.intellij.testFramework.fixtures.JavaTestFixtureFactory; |
| import com.intellij.testFramework.fixtures.TestFixtureBuilder; |
| import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl; |
| import com.intellij.testFramework.fixtures.impl.GlobalInspectionContextForTests; |
| import org.jetbrains.android.facet.AndroidFacet; |
| import org.jetbrains.android.facet.AndroidRootUtil; |
| import org.jetbrains.annotations.NotNull; |
| import org.jetbrains.annotations.Nullable; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| @SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"}) |
| public abstract class AndroidTestCase extends AndroidTestBase { |
| protected Module myModule; |
| protected List<Module> myAdditionalModules; |
| |
| private boolean myCreateManifest; |
| protected AndroidFacet myFacet; |
| |
| public AndroidTestCase(boolean createManifest) { |
| this.myCreateManifest = createManifest; |
| } |
| |
| public AndroidTestCase() { |
| this(true); |
| } |
| |
| @Override |
| public void setUp() throws Exception { |
| super.setUp(); |
| |
| // this will throw an exception if we don't have a full Android SDK, so we need to do this first thing before any other setup |
| String sdkPath = getTestSdkPath(); |
| |
| final TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder = |
| IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()); |
| myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture()); |
| final JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class); |
| final String dirPath = myFixture.getTempDirPath() + getContentRootPath(); |
| final File dir = new File(dirPath); |
| |
| if (!dir.exists()) { |
| assertTrue(dir.mkdirs()); |
| } |
| tuneModule(moduleFixtureBuilder, dirPath); |
| |
| final ArrayList<MyAdditionalModuleData> modules = new ArrayList<MyAdditionalModuleData>(); |
| configureAdditionalModules(projectBuilder, modules); |
| |
| myFixture.setUp(); |
| myFixture.setTestDataPath(getTestDataPath()); |
| myModule = moduleFixtureBuilder.getFixture().getModule(); |
| |
| // Must be done before addAndroidFacet, and must always be done, even if !myCreateManifest. |
| // We will delete it at the end of setUp; this is needed when unit tests want to rewrite |
| // the manifest on their own. |
| createManifest(); |
| |
| myFacet = addAndroidFacet(myModule, sdkPath, getPlatformDir(), isToAddSdk()); |
| |
| LanguageLevel languageLevel = getLanguageLevel(); |
| if (languageLevel != null) { |
| final LanguageLevelProjectExtension extension = LanguageLevelProjectExtension.getInstance(myModule.getProject()); |
| if (extension != null) { |
| extension.setLanguageLevel(languageLevel); |
| } |
| } |
| |
| myFixture.copyDirectoryToProject(getResDir(), "res"); |
| |
| myAdditionalModules = new ArrayList<Module>(); |
| |
| for (MyAdditionalModuleData data : modules) { |
| final Module additionalModule = data.myModuleFixtureBuilder.getFixture().getModule(); |
| myAdditionalModules.add(additionalModule); |
| final AndroidFacet facet = addAndroidFacet(additionalModule, sdkPath, getPlatformDir()); |
| facet.setLibraryProject(data.myLibrary); |
| final String rootPath = getContentRootPath(data.myDirName); |
| myFixture.copyDirectoryToProject("res", rootPath + "/res"); |
| myFixture.copyFileToProject(SdkConstants.FN_ANDROID_MANIFEST_XML, |
| rootPath + '/' + SdkConstants.FN_ANDROID_MANIFEST_XML); |
| if (data.myIsMainModuleDependency) { |
| ModuleRootModificationUtil.addDependency(myModule, additionalModule); |
| } |
| } |
| |
| if (!myCreateManifest) { |
| deleteManifest(); |
| } |
| |
| if (RenderSecurityManager.RESTRICT_READS) { |
| // Unit test class loader includes disk directories which security manager does not allow access to |
| RenderSecurityManager.sEnabled = false; |
| } |
| } |
| |
| protected boolean isToAddSdk() { |
| return true; |
| } |
| |
| protected String getContentRootPath() { |
| return ""; |
| } |
| |
| protected void configureAdditionalModules(@NotNull TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder, |
| @NotNull List<MyAdditionalModuleData> modules) { |
| } |
| |
| protected void addModuleWithAndroidFacet(@NotNull TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder, |
| @NotNull List<MyAdditionalModuleData> modules, |
| @NotNull String dirName, |
| boolean library) { |
| // By default, created module is declared as a main module's dependency |
| addModuleWithAndroidFacet(projectBuilder, modules, dirName, library, true); |
| } |
| |
| protected void addModuleWithAndroidFacet(@NotNull TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder, |
| @NotNull List<MyAdditionalModuleData> modules, |
| @NotNull String dirName, |
| boolean library, |
| boolean isMainModuleDependency) { |
| final JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class); |
| final String moduleDirPath = myFixture.getTempDirPath() + getContentRootPath(dirName); |
| //noinspection ResultOfMethodCallIgnored |
| new File(moduleDirPath).mkdirs(); |
| tuneModule(moduleFixtureBuilder, moduleDirPath); |
| modules.add(new MyAdditionalModuleData(moduleFixtureBuilder, dirName, library, isMainModuleDependency)); |
| } |
| |
| protected static String getContentRootPath(@NotNull String moduleName) { |
| return "/additionalModules/" + moduleName; |
| } |
| |
| protected String getResDir() { |
| return "res"; |
| } |
| |
| public static void tuneModule(JavaModuleFixtureBuilder moduleBuilder, String moduleDirPath) { |
| moduleBuilder.addContentRoot(moduleDirPath); |
| |
| //noinspection ResultOfMethodCallIgnored |
| new File(moduleDirPath + "/src/").mkdir(); |
| moduleBuilder.addSourceRoot("src"); |
| |
| //noinspection ResultOfMethodCallIgnored |
| new File(moduleDirPath + "/gen/").mkdir(); |
| moduleBuilder.addSourceRoot("gen"); |
| } |
| |
| protected void createManifest() throws IOException { |
| myFixture.copyFileToProject(SdkConstants.FN_ANDROID_MANIFEST_XML, SdkConstants.FN_ANDROID_MANIFEST_XML); |
| } |
| |
| protected void createProjectProperties() throws IOException { |
| myFixture.copyFileToProject(SdkConstants.FN_PROJECT_PROPERTIES, SdkConstants.FN_PROJECT_PROPERTIES); |
| } |
| |
| protected void deleteManifest() throws IOException { |
| deleteManifest(myModule); |
| } |
| |
| protected void deleteManifest(final Module module) throws IOException { |
| final AndroidFacet facet = AndroidFacet.getInstance(module); |
| assertNotNull(facet); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| String manifestRelativePath = facet.getProperties().MANIFEST_FILE_RELATIVE_PATH; |
| VirtualFile manifest = AndroidRootUtil.getFileByRelativeModulePath(module, manifestRelativePath, true); |
| if (manifest != null) { |
| try { |
| manifest.delete(this); |
| } |
| catch (IOException e) { |
| fail("Could not delete default manifest"); |
| } |
| } |
| } |
| }); |
| } |
| |
| @Override |
| public void tearDown() throws Exception { |
| myModule = null; |
| myAdditionalModules = null; |
| myFixture.tearDown(); |
| myFixture = null; |
| myFacet = null; |
| if (RenderSecurityManager.RESTRICT_READS) { |
| RenderSecurityManager.sEnabled = true; |
| } |
| super.tearDown(); |
| } |
| |
| public static AndroidFacet addAndroidFacet(Module module, String sdkPath, String platformDir) { |
| return addAndroidFacet(module, sdkPath, platformDir, true); |
| } |
| |
| public static AndroidFacet addAndroidFacet(Module module, String sdkPath, String platformDir, boolean addSdk) { |
| FacetManager facetManager = FacetManager.getInstance(module); |
| AndroidFacet facet = facetManager.createFacet(AndroidFacet.getFacetType(), "Android", null); |
| |
| if (addSdk) { |
| addAndroidSdk(module, sdkPath, platformDir); |
| } |
| final ModifiableFacetModel facetModel = facetManager.createModifiableModel(); |
| facetModel.addFacet(facet); |
| ApplicationManager.getApplication().runWriteAction(new Runnable() { |
| @Override |
| public void run() { |
| facetModel.commit(); |
| } |
| }); |
| return facet; |
| } |
| |
| /** Defines the project level to set for the test project, or null for the default */ |
| @Nullable |
| protected LanguageLevel getLanguageLevel() { |
| return null; |
| } |
| |
| protected void doGlobalInspectionTest(@NotNull GlobalInspectionTool inspection, |
| @NotNull String globalTestDir, |
| @NotNull AnalysisScope scope) { |
| doGlobalInspectionTest(new GlobalInspectionToolWrapper(inspection), globalTestDir, scope); |
| } |
| |
| protected void doGlobalInspectionTest(@NotNull GlobalInspectionToolWrapper wrapper, |
| @NotNull String globalTestDir, |
| @NotNull AnalysisScope scope) { |
| myFixture.enableInspections(wrapper.getTool()); |
| |
| scope.invalidate(); |
| |
| final InspectionManagerEx inspectionManager = (InspectionManagerEx)InspectionManager.getInstance(getProject()); |
| final GlobalInspectionContextForTests globalContext = |
| CodeInsightTestFixtureImpl.createGlobalContextForTool(scope, getProject(), inspectionManager, wrapper); |
| |
| InspectionTestUtil.runTool(wrapper, scope, globalContext); |
| InspectionTestUtil.compareToolResults(globalContext, wrapper, false, getTestDataPath() + globalTestDir); |
| } |
| |
| protected static class MyAdditionalModuleData { |
| final JavaModuleFixtureBuilder myModuleFixtureBuilder; |
| final String myDirName; |
| final boolean myLibrary; |
| final boolean myIsMainModuleDependency; |
| |
| private MyAdditionalModuleData(@NotNull JavaModuleFixtureBuilder moduleFixtureBuilder, |
| @NotNull String dirName, |
| boolean library, |
| boolean isMainModuleDependency) { |
| myModuleFixtureBuilder = moduleFixtureBuilder; |
| myDirName = dirName; |
| myLibrary = library; |
| myIsMainModuleDependency = isMainModuleDependency; |
| } |
| } |
| } |