Update AndroidTestCase to AS 2.3 + Android tests refactoring

This commit is contained in:
Vyacheslav Gerasimov
2017-04-24 21:52:30 +03:00
parent e2c62cbded
commit 386ec53dd5
25 changed files with 808 additions and 549 deletions
@@ -0,0 +1,62 @@
/*
* Copyright 2010-2017 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.kotlin.android;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkAdditionalData;
import org.jetbrains.android.sdk.AndroidSdkAdditionalData;
import org.jetbrains.android.sdk.AndroidSdkData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* Stub for com.android.tools.idea.sdk.AndroidSdks
* stabbed to minimize changes in AndroidTestBase
*/
public class AndroidSdks {
private static AndroidSdks INSTANCE;
private AndroidSdkData mySdkData;
private AndroidSdks() {
}
public static AndroidSdks getInstance() {
if (INSTANCE == null) {
INSTANCE = new AndroidSdks();
}
return INSTANCE;
}
public AndroidSdkData tryToChooseAndroidSdk() {
return mySdkData;
}
public void setSdkData(AndroidSdkData data) {
mySdkData = data;
}
@Nullable
public AndroidSdkAdditionalData getAndroidSdkAdditionalData(@NotNull Sdk sdk) {
SdkAdditionalData data = sdk.getSdkAdditionalData();
return data instanceof AndroidSdkAdditionalData ? (AndroidSdkAdditionalData)data : null;
}
}
@@ -0,0 +1,257 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.kotlin.android;
import com.android.sdklib.IAndroidTarget;
import com.android.tools.idea.res.ResourceHelper;
import com.android.tools.idea.startup.ExternalAnnotationsSupport;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.roots.JavadocOrderRootType;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.util.Segment;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.io.FileUtil;
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.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.xml.XmlAttributeValue;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.fixtures.JavaCodeInsightTestFixture;
import org.jetbrains.android.dom.wrappers.LazyValueResourceElementWrapper;
import org.jetbrains.android.sdk.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.nio.file.Paths;
/**
* Copied from AS 2.3 sources
*/
@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"})
public abstract class AndroidTestBase extends UsefulTestCase {
protected JavaCodeInsightTestFixture myFixture;
protected AndroidTestBase() {
// IDEA14 seems to be stricter regarding validating accesses against known roots. By default, it contains the entire idea folder,
// but it doesn't seem to include our custom structure tools/idea/../adt/idea where the android plugin is placed.
// The following line explicitly adds that folder as an allowed root.
VfsRootAccess.allowRootAccess(FileUtil.toCanonicalPath(getAndroidPluginHome()));
}
public String getAbsoluteTestDataPath() {
// The following code doesn't work right now that the Android
// plugin lives in a separate place:
//String androidHomePath = System.getProperty("android.home.path");
//if (androidHomePath == null) {
// androidHomePath = new File(PathManager.getHomePath(), "android/android").getPath();
//}
//return PathUtil.getCanonicalPath(androidHomePath + "/testData");
String path = Paths.get(getTestDataPath()).toAbsolutePath().toString();
assertTrue(new File(path).isAbsolute());
return path;
}
public String getTestDataPath() {
return getAndroidPluginHome() + "/testData";
}
public static String getAndroidPluginHome() {
// Now that the Android plugin is kept in a separate place, we need to look in
// a relative position instead
String adtPath = PathManager.getHomePath() + "/../adt/idea/android";
if (new File(adtPath).exists()) {
return adtPath;
}
return PathManagerEx.findFileUnderCommunityHome("plugins/android").getPath();
}
protected static void addLatestAndroidSdk(Module module) {
Sdk androidSdk = createLatestAndroidSdk();
ModuleRootModificationUtil.setModuleSdk(module, androidSdk);
}
public static Sdk createLatestAndroidSdk() {
String sdkPath = TestUtils.getSdk().toString();
String platformDir = TestUtils.getLatestAndroidPlatform();
Sdk sdk = ProjectJdkTable.getInstance().createSdk("android_test_sdk", AndroidSdkType.getInstance());
SdkModificator sdkModificator = sdk.getSdkModificator();
sdkModificator.setHomePath(sdkPath);
VirtualFile androidJar = JarFileSystem.getInstance().findFileByPath(sdkPath + "/platforms/" + platformDir + "/android.jar!/");
sdkModificator.addRoot(androidJar, OrderRootType.CLASSES);
VirtualFile resFolder = LocalFileSystem.getInstance().findFileByPath(sdkPath + "/platforms/" + platformDir + "/data/res");
sdkModificator.addRoot(resFolder, OrderRootType.CLASSES);
VirtualFile docsFolder = LocalFileSystem.getInstance().findFileByPath(sdkPath + "/docs/reference");
if (docsFolder != null) {
sdkModificator.addRoot(docsFolder, JavadocOrderRootType.getInstance());
}
AndroidSdkAdditionalData data = new AndroidSdkAdditionalData(sdk);
AndroidSdkData sdkData = AndroidSdkData.getSdkData(sdkPath);
assertNotNull(sdkData);
IAndroidTarget target = null;
IAndroidTarget[] targets = sdkData.getTargets();
for (IAndroidTarget t : targets) {
if (t.getLocation().contains(platformDir)) {
target = t;
break;
}
}
assertNotNull(target);
data.setBuildTarget(target);
sdkModificator.setSdkAdditionalData(data);
ExternalAnnotationsSupport.attachJdkAnnotations(sdkModificator);
sdkModificator.commitChanges();
return sdk;
}
protected Project getProject() {
return myFixture.getProject();
}
protected void ensureSdkManagerAvailable() {
AndroidSdks androidSdks = AndroidSdks.getInstance();
AndroidSdkData sdkData = androidSdks.tryToChooseAndroidSdk();
if (sdkData == null) {
sdkData = createTestSdkManager();
if (sdkData != null) {
androidSdks.setSdkData(sdkData);
}
}
assertNotNull(sdkData);
}
@Nullable
protected AndroidSdkData createTestSdkManager() {
Sdk androidSdk = createLatestAndroidSdk();
AndroidSdkAdditionalData data = AndroidSdks.getInstance().getAndroidSdkAdditionalData(androidSdk);
if (data != null) {
AndroidPlatform androidPlatform = data.getAndroidPlatform();
if (androidPlatform != null) {
// Put default platforms in the list before non-default ones so they'll be looked at first.
return androidPlatform.getSdkData();
} else {
fail("No getAndroidPlatform() associated with the AndroidSdkAdditionalData: " + data);
}
} else {
fail("Could not find data associated with the SDK: " + androidSdk.getName());
}
return null;
}
/** Returns a description of the given elements, suitable as unit test golden file output */
public static String describeElements(@Nullable PsiElement[] elements) {
if (elements == null) {
return "Empty";
}
StringBuilder sb = new StringBuilder();
for (PsiElement target : elements) {
appendElementDescription(sb, target);
}
return sb.toString();
}
/** Appends a description of the given element, suitable as unit test golden file output */
public static void appendElementDescription(@NotNull StringBuilder sb, @NotNull PsiElement element) {
if (element instanceof LazyValueResourceElementWrapper) {
LazyValueResourceElementWrapper wrapper = (LazyValueResourceElementWrapper)element;
XmlAttributeValue value = wrapper.computeElement();
if (value != null) {
element = value;
}
}
PsiFile file = element.getContainingFile();
int offset = element.getTextOffset();
TextRange segment = element.getTextRange();
appendSourceDescription(sb, file, offset, segment);
}
/** Appends a description of the given elements, suitable as unit test golden file output */
public static void appendSourceDescription(@NotNull StringBuilder sb, @Nullable PsiFile file, int offset, @Nullable Segment segment) {
if (file != null && segment != null) {
if (ResourceHelper.getFolderType(file) != null) {
assertNotNull(file.getParent());
sb.append(file.getParent().getName());
sb.append("/");
}
sb.append(file.getName());
sb.append(':');
String text = file.getText();
int lineNumber = 1;
for (int i = 0; i < offset; i++) {
if (text.charAt(i) == '\n') {
lineNumber++;
}
}
sb.append(lineNumber);
sb.append(":");
sb.append('\n');
int startOffset = segment.getStartOffset();
int endOffset = segment.getEndOffset();
assertTrue(offset == -1 || offset >= startOffset);
assertTrue(offset == -1 || offset <= endOffset);
int lineStart = startOffset;
while (lineStart > 0 && text.charAt(lineStart - 1) != '\n') {
lineStart--;
}
// Skip over leading whitespace
while (lineStart < startOffset && Character.isWhitespace(text.charAt(lineStart))) {
lineStart++;
}
int lineEnd = startOffset;
while (lineEnd < text.length() && text.charAt(lineEnd) != '\n') {
lineEnd++;
}
String indent = " ";
sb.append(indent);
sb.append(text.substring(lineStart, lineEnd));
sb.append('\n');
sb.append(indent);
for (int i = lineStart; i < lineEnd; i++) {
if (i == offset) {
sb.append('|');
} else if (i >= startOffset && i <= endOffset) {
sb.append('~');
} else {
sb.append(' ');
}
}
} else {
sb.append(offset);
sb.append(":?");
}
sb.append('\n');
}
}
@@ -0,0 +1,378 @@
/*
* 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.kotlin.android;
import com.android.SdkConstants;
import com.android.tools.idea.rendering.RenderSecurityManager;
import com.android.tools.idea.startup.AndroidCodeStyleSettingsModifier;
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.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.components.impl.ComponentManagerImpl;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.codeStyle.CodeStyleSchemes;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.testFramework.InspectionTestUtil;
import com.intellij.testFramework.ThreadTracker;
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 com.intellij.util.ArrayUtil;
import org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.android.formatter.AndroidXmlCodeStyleSettings;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.picocontainer.MutablePicoContainer;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Copied from AS 2.3 sources
*/
@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"})
public abstract class AndroidTestCase extends AndroidTestBase {
protected Module myModule;
protected List<Module> myAdditionalModules;
protected AndroidFacet myFacet;
protected CodeStyleSettings mySettings;
private List<String> myAllowedRoots = new ArrayList<>();
private boolean myUseCustomSettings;
@Override
protected void setUp() throws Exception {
super.setUp();
TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName());
myFixture = JavaTestFixtureFactory.getFixtureFactory().createCodeInsightFixture(projectBuilder.getFixture());
JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class);
File moduleRoot = new File(myFixture.getTempDirPath());
if (!moduleRoot.exists()) {
assertTrue(moduleRoot.mkdirs());
}
initializeModuleFixtureBuilderWithSrcAndGen(moduleFixtureBuilder, moduleRoot.toString());
ArrayList<MyAdditionalModuleData> modules = new ArrayList<>();
configureAdditionalModules(projectBuilder, modules);
myFixture.setUp();
myFixture.setTestDataPath(getTestDataPath());
myModule = moduleFixtureBuilder.getFixture().getModule();
// Must be done before addAndroidFacet, and must always be done, even if a test provides
// its own custom manifest file. However, in that case, we will delete it shortly below.
createManifest();
myFacet = addAndroidFacet(myModule);
LanguageLevel languageLevel = getLanguageLevel();
if (languageLevel != null) {
LanguageLevelProjectExtension extension = LanguageLevelProjectExtension.getInstance(myModule.getProject());
if (extension != null) {
extension.setLanguageLevel(languageLevel);
}
}
// TODO: myFixture.copyDirectoryToProject(getResDir(), "res");
myAdditionalModules = new ArrayList<>();
for (MyAdditionalModuleData data : modules) {
Module additionalModule = data.myModuleFixtureBuilder.getFixture().getModule();
myAdditionalModules.add(additionalModule);
AndroidFacet facet = addAndroidFacet(additionalModule);
facet.setLibraryProject(data.myProjectType == 1);
String rootPath = getAdditionalModulePath(data.myDirName);
myFixture.copyDirectoryToProject(getResDir(), rootPath + "/res");
myFixture.copyFileToProject(SdkConstants.FN_ANDROID_MANIFEST_XML, rootPath + '/' + SdkConstants.FN_ANDROID_MANIFEST_XML);
if (data.myIsMainModuleDependency) {
ModuleRootModificationUtil.addDependency(myModule, additionalModule);
}
}
if (providesCustomManifest()) {
deleteManifest();
}
if (RenderSecurityManager.RESTRICT_READS) {
// Unit test class loader includes disk directories which security manager does not allow access to
RenderSecurityManager.sEnabled = false;
}
ArrayList<String> allowedRoots = new ArrayList<>();
collectAllowedRoots(allowedRoots);
// TODO: registerAllowedRoots(allowedRoots, myTestRootDisposable);
mySettings = CodeStyleSettingsManager.getSettings(getProject()).clone();
AndroidCodeStyleSettingsModifier.modify(mySettings);
CodeStyleSettingsManager.getInstance(getProject()).setTemporarySettings(mySettings);
myUseCustomSettings = getAndroidCodeStyleSettings().USE_CUSTOM_SETTINGS;
getAndroidCodeStyleSettings().USE_CUSTOM_SETTINGS = true;
// Layoutlib rendering thread will be shutdown when the app is closed so do not report it as a leak
ThreadTracker.longRunningThreadCreated(ApplicationManager.getApplication(), "Layoutlib");
}
@Override
protected void tearDown() throws Exception {
try {
CodeStyleSettingsManager.getInstance(getProject()).dropTemporarySettings();
myModule = null;
myAdditionalModules = null;
myFixture.tearDown();
myFixture = null;
myFacet = null;
getAndroidCodeStyleSettings().USE_CUSTOM_SETTINGS = myUseCustomSettings;
if (RenderSecurityManager.RESTRICT_READS) {
RenderSecurityManager.sEnabled = true;
}
}
finally {
super.tearDown();
}
}
private static void initializeModuleFixtureBuilderWithSrcAndGen(JavaModuleFixtureBuilder moduleFixtureBuilder, String moduleRoot) {
moduleFixtureBuilder.addContentRoot(moduleRoot);
//noinspection ResultOfMethodCallIgnored
new File(moduleRoot + "/src/").mkdir();
moduleFixtureBuilder.addSourceRoot("src");
//noinspection ResultOfMethodCallIgnored
new File(moduleRoot + "/gen/").mkdir();
moduleFixtureBuilder.addSourceRoot("gen");
}
/**
* Returns the path that any additional modules registered by
* {@link #configureAdditionalModules(TestFixtureBuilder, List)} or
* {@link #addModuleWithAndroidFacet(TestFixtureBuilder, List, String, int, boolean)} are
* installed into.
*/
protected static String getAdditionalModulePath(@NotNull String moduleName) {
return "/additionalModules/" + moduleName;
}
/**
* Indicates whether this class provides its own {@code AndroidManifest.xml} for its tests. If
* {@code true}, then {@link #setUp()} calls {@link #deleteManifest()} before finishing.
*/
protected boolean providesCustomManifest() {
return false;
}
/**
* Get the "res" directory for this SDK. Children classes can override this if they need to
* provide a custom "res" location for tests.
*/
protected String getResDir() {
return "res";
}
/**
* Defines the project level to set for the test project, or null to get the default language
* level associated with the test project.
*/
@Nullable
protected LanguageLevel getLanguageLevel() {
return null;
}
protected static AndroidXmlCodeStyleSettings getAndroidCodeStyleSettings() {
return AndroidXmlCodeStyleSettings.getInstance(CodeStyleSchemes.getInstance().getDefaultScheme().getCodeStyleSettings());
}
/**
* Hook point for child test classes to register directories that can be safely accessed by all
* of its tests.
*
* @see {@link VfsRootAccess}
*/
protected void collectAllowedRoots(List<String> roots) throws IOException {
}
private void registerAllowedRoots(List<String> roots, @NotNull Disposable disposable) {
List<String> newRoots = new ArrayList<>(roots);
newRoots.removeAll(myAllowedRoots);
String[] newRootsArray = ArrayUtil.toStringArray(newRoots);
VfsRootAccess.allowRootAccess(newRootsArray);
myAllowedRoots.addAll(newRoots);
Disposer.register(disposable, () -> {
VfsRootAccess.disallowRootAccess(newRootsArray);
myAllowedRoots.removeAll(newRoots);
});
}
public static AndroidFacet addAndroidFacet(Module module) {
return addAndroidFacet(module, true);
}
private static AndroidFacet addAndroidFacet(Module module, boolean attachSdk) {
FacetManager facetManager = FacetManager.getInstance(module);
AndroidFacet facet = facetManager.createFacet(AndroidFacet.getFacetType(), "Android", null);
if (attachSdk) {
addLatestAndroidSdk(module);
}
ModifiableFacetModel facetModel = facetManager.createModifiableModel();
facetModel.addFacet(facet);
ApplicationManager.getApplication().runWriteAction(facetModel::commit);
return facet;
}
protected void configureAdditionalModules(
@NotNull TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder, @NotNull List<MyAdditionalModuleData> modules) {
}
protected final void addModuleWithAndroidFacet(
@NotNull TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder,
@NotNull List<MyAdditionalModuleData> modules,
@NotNull String dirName,
int projectType) {
// By default, created module is declared as a main module's dependency
addModuleWithAndroidFacet(projectBuilder, modules, dirName, projectType, true);
}
protected final void addModuleWithAndroidFacet(
@NotNull TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder,
@NotNull List<MyAdditionalModuleData> modules,
@NotNull String dirName,
int projectType,
boolean isMainModuleDependency) {
JavaModuleFixtureBuilder moduleFixtureBuilder = projectBuilder.addModule(JavaModuleFixtureBuilder.class);
String moduleDirPath = myFixture.getTempDirPath() + getAdditionalModulePath(dirName);
//noinspection ResultOfMethodCallIgnored
new File(moduleDirPath).mkdirs();
initializeModuleFixtureBuilderWithSrcAndGen(moduleFixtureBuilder, moduleDirPath);
modules.add(new MyAdditionalModuleData(moduleFixtureBuilder, dirName, projectType, isMainModuleDependency));
}
protected void createManifest() throws IOException {
myFixture.copyFileToProject(SdkConstants.FN_ANDROID_MANIFEST_XML, SdkConstants.FN_ANDROID_MANIFEST_XML);
}
protected final void createProjectProperties() throws IOException {
myFixture.copyFileToProject(SdkConstants.FN_PROJECT_PROPERTIES, SdkConstants.FN_PROJECT_PROPERTIES);
}
protected final void deleteManifest() throws IOException {
deleteManifest(myModule);
}
protected final void deleteManifest(final Module module) throws IOException {
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");
}
}
}
});
}
protected final void doGlobalInspectionTest(
@NotNull GlobalInspectionTool inspection, @NotNull String globalTestDir, @NotNull AnalysisScope scope) {
doGlobalInspectionTest(new GlobalInspectionToolWrapper(inspection), globalTestDir, scope);
}
/**
* Given an inspection and a path to a directory that contains an "expected.xml" file, run the
* inspection on the current test project and verify that its output matches that of the
* expected file.
*/
protected final void doGlobalInspectionTest(
@NotNull GlobalInspectionToolWrapper wrapper, @NotNull String globalTestDir, @NotNull AnalysisScope scope) {
myFixture.enableInspections(wrapper.getTool());
scope.invalidate();
InspectionManagerEx inspectionManager = (InspectionManagerEx)InspectionManager.getInstance(getProject());
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 int myProjectType;
final boolean myIsMainModuleDependency;
private MyAdditionalModuleData(
@NotNull JavaModuleFixtureBuilder moduleFixtureBuilder, @NotNull String dirName, int projectType, boolean isMainModuleDependency) {
myModuleFixtureBuilder = moduleFixtureBuilder;
myDirName = dirName;
myProjectType = projectType;
myIsMainModuleDependency = isMainModuleDependency;
}
}
@NotNull
protected <T> T registerApplicationComponent(@NotNull Class<T> key, @NotNull T instance) throws Exception {
MutablePicoContainer picoContainer = (MutablePicoContainer)ApplicationManager.getApplication().getPicoContainer();
@SuppressWarnings("unchecked")
T old = (T)picoContainer.getComponentInstance(key.getName());
picoContainer.unregisterComponent(key.getName());
picoContainer.registerComponentInstance(key.getName(), instance);
return old;
}
@NotNull
protected <T> T registerProjectComponent(@NotNull Class<T> key, @NotNull T instance) {
MutablePicoContainer picoContainer = (MutablePicoContainer)getProject().getPicoContainer();
@SuppressWarnings("unchecked")
T old = (T)picoContainer.getComponentInstance(key.getName());
picoContainer.unregisterComponent(key.getName());
picoContainer.registerComponentInstance(key.getName(), instance);
return old;
}
}
@@ -1,271 +0,0 @@
/*
* Copyright 2010-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 org.jetbrains.kotlin.android;
import com.android.SdkConstants;
import com.android.tools.idea.rendering.RenderSecurityManager;
import com.android.tools.idea.res.PsiProjectListener;
import com.intellij.facet.FacetManager;
import com.intellij.facet.ModifiableFacetModel;
import com.intellij.ide.startup.impl.StartupManagerImpl;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.startup.StartupManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
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 org.jetbrains.android.facet.AndroidFacet;
import org.jetbrains.android.facet.AndroidRootUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"})
public abstract class KotlinAndroidTestCase extends KotlinAndroidTestCaseBase {
protected Module myModule;
protected List<Module> myAdditionalModules;
private final boolean myCreateManifest;
protected AndroidFacet myFacet;
private boolean kotlinInternalModeOriginalValue;
public KotlinAndroidTestCase(boolean createManifest) {
this.myCreateManifest = createManifest;
}
public KotlinAndroidTestCase() {
this(true);
}
protected File[] getResourceDirs(String path) {
return new File(path).listFiles(new FileFilter() {
@Override
public boolean accept(@NotNull File file) {
return file.getName().startsWith("res") && file.isDirectory();
}
});
}
@Override
protected void setUp() throws Exception {
// sdk path workaround, set real android sdk path and platform for android plugin to work
System.setProperty(KotlinAndroidTestCaseBase.SDK_PATH_PROPERTY, PathManager.getHomePath() + "/../dependencies/androidSDK");
System.setProperty(KotlinAndroidTestCaseBase.PLATFORM_DIR_PROPERTY, "android-23");
VfsRootAccess.allowRootAccess(KotlinTestUtils.getHomeDirectory());
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 List<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();
androidSdk = createAndroidSdk(getTestSdkPath(), getPlatformDir());
myFacet = addAndroidFacet(myModule, sdkPath, getPlatformDir(), isToAddSdk());
for (File resDir : getResourceDirs(dirPath)) {
if (resDir.exists()) {
myFixture.copyDirectoryToProject(resDir.getName(), resDir.getName());
} else {
Logger.getInstance(this.getClass()).info("No res directory found in test");
}
}
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);
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;
}
((StartupManagerImpl) StartupManager.getInstance(getProject())).runPostStartupActivities();
kotlinInternalModeOriginalValue = KotlinInternalMode.Instance.getEnabled();
KotlinInternalMode.Instance.setEnabled(true);
}
protected boolean isToAddSdk() {
return true;
}
protected String getContentRootPath() {
return "";
}
protected void configureAdditionalModules(@NotNull TestFixtureBuilder<IdeaProjectTestFixture> projectBuilder,
@NotNull List<MyAdditionalModuleData> modules) {
}
protected static String getContentRootPath(@NotNull String moduleName) {
return "/additionalModules/" + moduleName;
}
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("plugins/android-extensions/android-extensions-idea/testData/android/AndroidManifest.xml",
SdkConstants.FN_ANDROID_MANIFEST_XML);
}
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 {
KotlinInternalMode.Instance.setEnabled(kotlinInternalModeOriginalValue);
Field listenersField = PsiProjectListener.class.getDeclaredField("myListeners");
listenersField.setAccessible(true);
Map listeners = (Map)listenersField.get(PsiProjectListener.getInstance(getProject()));
listeners.clear();
VfsRootAccess.disallowRootAccess(KotlinTestUtils.getHomeDirectory());
super.tearDown();
myModule = null;
myAdditionalModules = null;
myFixture.tearDown();
myFixture = null;
myFacet = null;
if (RenderSecurityManager.RESTRICT_READS) {
RenderSecurityManager.sEnabled = true;
}
}
public AndroidFacet addAndroidFacet(Module module, String sdkPath, String platformDir) {
return addAndroidFacet(module, sdkPath, platformDir, true);
}
public 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;
}
protected static class MyAdditionalModuleData {
final JavaModuleFixtureBuilder myModuleFixtureBuilder;
final String myDirName;
final boolean myLibrary;
private MyAdditionalModuleData(@NotNull JavaModuleFixtureBuilder moduleFixtureBuilder,
@NotNull String dirName,
boolean library) {
myModuleFixtureBuilder = moduleFixtureBuilder;
myDirName = dirName;
myLibrary = library;
}
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2017 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.kotlin.android
import com.android.SdkConstants
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
abstract class KotlinAndroidTestCase : AndroidTestCase() {
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory()
override fun createManifest() {
myFixture.copyFileToProject("idea/testData/android/AndroidManifest.xml", SdkConstants.FN_ANDROID_MANIFEST_XML)
}
fun copyResourceDirectoryForTest(path: String) {
val testFile = File(path)
if (testFile.isFile) {
myFixture.copyDirectoryToProject(testFile.parent + "/res", "res")
} else if (testFile.isDirectory) {
myFixture.copyDirectoryToProject(testFile.path + "/res", "res")
}
}
}
@@ -1,185 +0,0 @@
/*
* Copyright (C) 2013 The Android Open Source Project
*
* 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.kotlin.android;
import com.android.sdklib.IAndroidTarget;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkModificator;
import com.intellij.openapi.roots.JavadocOrderRootType;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.testFramework.IdeaTestCase;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.fixtures.CodeInsightTestFixture;
import org.jetbrains.android.sdk.AndroidSdkAdditionalData;
import org.jetbrains.android.sdk.AndroidSdkData;
import org.jetbrains.android.sdk.AndroidSdkType;
import org.jetbrains.kotlin.idea.test.RunnableWithException;
import org.jetbrains.kotlin.idea.test.TestUtilsKt;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import java.io.File;
@SuppressWarnings({"JUnitTestCaseWithNonTrivialConstructors"})
public abstract class KotlinAndroidTestCaseBase extends UsefulTestCase {
/** Environment variable or system property containing the full path to an SDK install */
public static final String SDK_PATH_PROPERTY = "ADT_TEST_SDK_PATH";
/** Environment variable or system property pointing to the directory name of the platform inside $sdk/platforms, e.g. "android-17" */
public static final String PLATFORM_DIR_PROPERTY = "ADT_TEST_PLATFORM";
protected CodeInsightTestFixture myFixture;
protected Sdk androidSdk;
protected VirtualFile androidJar;
private static final String TEST_DATA_PROJECT_RELATIVE = "/plugins/android-extensions/android-extensions-idea/testData/android";
protected KotlinAndroidTestCaseBase() {
IdeaTestCase.initPlatformPrefix();
}
public static String getPluginTestDataPathBase() {
return KotlinTestUtils.getHomeDirectory() + TEST_DATA_PROJECT_RELATIVE;
}
public String getTestDataPath() {
return getPluginTestDataPathBase();
}
public String getDefaultTestSdkPath() {
return getTestDataPath() + "/sdk1.5";
}
@Override
protected void tearDown() throws Exception {
TestUtilsKt.doKotlinTearDown(getProject(), new RunnableWithException() {
@Override
public void run() throws Exception {
KotlinAndroidTestCaseBase.super.tearDown();
androidJar = null;
androidSdk = null;
}
});
}
public String getDefaultPlatformDir() {
return "android-1.5";
}
protected String getTestSdkPath() {
if (requireRecentSdk()) {
String override = System.getProperty(SDK_PATH_PROPERTY);
if (override != null) {
assertTrue("Must also define " + PLATFORM_DIR_PROPERTY, System.getProperty(PLATFORM_DIR_PROPERTY) != null);
assertTrue(override, new File(override).exists());
return override;
}
override = System.getenv(SDK_PATH_PROPERTY);
if (override != null) {
assertTrue("Must also define " + PLATFORM_DIR_PROPERTY, System.getenv(PLATFORM_DIR_PROPERTY) != null);
return override;
}
fail("This unit test requires " + SDK_PATH_PROPERTY + " and " + PLATFORM_DIR_PROPERTY + " to be defined.");
}
return getDefaultTestSdkPath();
}
protected String getPlatformDir() {
if (requireRecentSdk()) {
String override = System.getProperty(PLATFORM_DIR_PROPERTY);
if (override != null) {
return override;
}
override = System.getenv(PLATFORM_DIR_PROPERTY);
if (override != null) {
return override;
}
fail("This unit test requires " + SDK_PATH_PROPERTY + " and " + PLATFORM_DIR_PROPERTY + " to be defined.");
}
return getDefaultPlatformDir();
}
/** Is the bundled (incomplete) SDK install adequate or do we need to find a valid install? */
protected boolean requireRecentSdk() {
return true;
}
protected void addAndroidSdk(Module module, String sdkPath, String platformDir) {
assert androidSdk != null : "android sdk must be initialized";
ModuleRootModificationUtil.setModuleSdk(module, androidSdk);
}
public Sdk createAndroidSdk(String sdkPath, String platformDir) {
Sdk sdk = ProjectJdkTable.getInstance().createSdk("android_test_sdk", AndroidSdkType.getInstance());
SdkModificator sdkModificator = sdk.getSdkModificator();
sdkModificator.setHomePath(sdkPath);
if (platformDir.equals(getDefaultPlatformDir())) {
// Compatibility: the unit tests were using android.jar outside the sdk1.5 install;
// we need to use that one, rather than the real one in sdk1.5, in order for the
// tests to pass. Longer term, we should switch the unit tests over to all using
// a valid SDK.
String androidJarPath = sdkPath + "/../android.jar!/";
androidJar = VirtualFileManager.getInstance().findFileByUrl("jar://" + androidJarPath);
} else {
androidJar = VirtualFileManager.getInstance().findFileByUrl("jar://" + sdkPath + "/platforms/" + platformDir + "/android.jar!/");
}
sdkModificator.addRoot(androidJar, OrderRootType.CLASSES);
VirtualFile resFolder = LocalFileSystem.getInstance().findFileByPath(sdkPath + "/platforms/" + platformDir + "/data/res");
sdkModificator.addRoot(resFolder, OrderRootType.CLASSES);
VirtualFile docsFolder = LocalFileSystem.getInstance().findFileByPath(sdkPath + "/docs/reference");
if (docsFolder != null) {
sdkModificator.addRoot(docsFolder, JavadocOrderRootType.getInstance());
}
AndroidSdkAdditionalData data = new AndroidSdkAdditionalData(sdk);
AndroidSdkData sdkData = AndroidSdkData.getSdkData(sdkPath);
assertNotNull(sdkData);
IAndroidTarget target = sdkData.findTargetByName("Android 5.0"); // TODO: Get rid of this hardcoded version number
if (target == null) {
IAndroidTarget[] targets = sdkData.getTargets();
for (IAndroidTarget t : targets) {
if (t.getLocation().contains(platformDir)) {
target = t;
break;
}
}
if (target == null && targets.length > 0) {
target = targets[targets.length - 1];
}
}
assertNotNull(target);
data.setBuildTarget(target);
sdkModificator.setSdkAdditionalData(data);
sdkModificator.commitChanges();
return sdk;
}
protected Project getProject() {
return myFixture.getProject();
}
}
@@ -0,0 +1,39 @@
/*
* Copyright 2010-2017 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.kotlin.android;
import com.android.annotations.NonNull;
import com.intellij.openapi.application.PathManager;
import java.io.File;
/**
* Stub for com.android.testutils.TestUtils
* stabbed to minimize changes in AndroidTestBase
*/
public class TestUtils {
@NonNull
public static File getSdk() {
return new File(PathManager.getHomePath() + "/../dependencies/androidSDK");
}
@NonNull
public static String getLatestAndroidPlatform() {
return "android-23";
}
}
@@ -17,7 +17,6 @@
package org.jetbrains.kotlin.android.configure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.configuration.AbstractConfigureProjectByChangingFileTest;
import org.jetbrains.kotlin.idea.configuration.AbstractGradleConfigureProjectByChangingFileTest;
public abstract class AbstractConfigureProjectTest extends AbstractGradleConfigureProjectByChangingFileTest {
@@ -16,21 +16,16 @@
package org.jetbrains.kotlin.android.folding
import com.android.SdkConstants
import org.jetbrains.kotlin.android.KotlinAndroidTestCase
import java.io.File
abstract class AbstractAndroidResourceFoldingTest : KotlinAndroidTestCase() {
fun doTest(path: String) {
myFixture.copyFileToProject("values.xml", "res/values/values.xml")
myFixture.copyFileToProject("R.java", "gen/com/myapp/R.java")
val testFile = File(path)
myFixture.copyFileToProject("${testFile.parent}/values.xml", "res/values/values.xml")
myFixture.copyFileToProject("${testFile.parent}/R.java", "gen/com/myapp/R.java")
myFixture.testFoldingWithCollapseStatus(path, "${myFixture.tempDirPath}/src/main.kt")
}
override fun createManifest() {
myFixture.copyFileToProject("idea/testData/android/AndroidManifest.xml", SdkConstants.FN_ANDROID_MANIFEST_XML)
}
override fun getTestDataPath() = "idea/testData/android/folding"
}
@@ -22,9 +22,7 @@ import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.PathUtil
import org.jetbrains.kotlin.android.KotlinAndroidTestCase
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
@@ -81,10 +79,4 @@ abstract class AbstractAndroidIntentionTest : KotlinAndroidTestCase() {
}
}
}
override fun createManifest() {
myFixture.copyFileToProject("idea/testData/android/AndroidManifest.xml", SdkConstants.FN_ANDROID_MANIFEST_XML)
}
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory()
}
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.android.intention
import com.android.SdkConstants
import com.google.gson.JsonObject
import com.google.gson.JsonParser
import com.intellij.codeInsight.intention.IntentionAction
@@ -116,8 +115,4 @@ abstract class AbstractAndroidResourceIntentionTest : KotlinAndroidTestCase() {
fun getResourceDirectory() = LocalFileSystem.getInstance().findFileByPath(myFixture.tempDirPath + "/res")
fun getTargetElement() = myFixture.file.findElementAt(myFixture.caretOffset)?.parent
override fun createManifest() {
myFixture.copyFileToProject("idea/testData/android/AndroidManifest.xml", SdkConstants.FN_ANDROID_MANIFEST_XML)
}
}
@@ -20,7 +20,6 @@ import org.jetbrains.android.inspections.klint.AndroidLintInspectionBase
import org.jetbrains.kotlin.android.KotlinAndroidTestCase
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.test.InTextDirectivesUtils.findStringWithPrefixes
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
abstract class AbstractKotlinLintTest : KotlinAndroidTestCase() {
@@ -70,6 +69,4 @@ abstract class AbstractKotlinLintTest : KotlinAndroidTestCase() {
myFixture.checkHighlighting(true, false, false)
}
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory() + "/idea/testData/android/lint/"
}
@@ -16,14 +16,12 @@
package org.jetbrains.kotlin.android.quickfix
import com.android.SdkConstants
import com.intellij.codeInspection.InspectionProfileEntry
import com.intellij.openapi.util.io.FileUtil
import com.intellij.util.PathUtil
import org.jetbrains.android.inspections.klint.AndroidLintInspectionBase
import org.jetbrains.kotlin.android.KotlinAndroidTestCase
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
@@ -61,10 +59,4 @@ abstract class AbstractAndroidLintQuickfixTest : KotlinAndroidTestCase() {
assertNull("Intention should not be available", myFixture.availableIntentions.find { it.text == intentionText })
}
}
override fun createManifest() {
myFixture.copyFileToProject("idea/testData/android/AndroidManifest.xml", SdkConstants.FN_ANDROID_MANIFEST_XML)
}
override fun getTestDataPath() = KotlinTestUtils.getHomeDirectory()
}
@@ -5,6 +5,6 @@
<application>
<activity android:name=".Test$MyActivity"/>
<activity android:name=".Test$MyActivity" />
</application>
</manifest>
@@ -5,6 +5,6 @@
<application>
<activity android:name=".MyActivity"/>
<activity android:name=".MyActivity" />
</application>
</manifest>
@@ -5,6 +5,6 @@
<application>
<receiver android:name=".Test$MyReceiver"/>
<receiver android:name=".Test$MyReceiver" />
</application>
</manifest>
@@ -5,6 +5,6 @@
<application>
<receiver android:name=".MyReceiver"/>
<receiver android:name=".MyReceiver" />
</application>
</manifest>
@@ -5,6 +5,6 @@
<application>
<service android:name=".Test$MyService"/>
<service android:name=".Test$MyService" />
</application>
</manifest>
@@ -5,6 +5,6 @@
<application>
<service android:name=".MyService"/>
<service android:name=".MyService" />
</application>
</manifest>
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:orientation="vertical" android:layout_width="match_parent"
android:layout_height="match_parent">
</LinearLayout>
@@ -43,19 +43,14 @@ abstract class AbstractAndroidCompletionTest : KotlinAndroidTestCase() {
private fun completionType() = CompletionType.BASIC
fun doTest(path: String?) {
getResourceDirs(path).forEach { myFixture.copyDirectoryToProject(it.name, it.name) }
fun doTest(path: String) {
copyResourceDirectoryForTest(path)
val virtualFile = myFixture.copyFileToProject(path + getTestName(true) + ".kt", "src/" + getTestName(true) + ".kt")
myFixture.configureFromExistingVirtualFile(virtualFile)
val fileText = FileUtil.loadFile(File(path + getTestName(true) + ".kt"), true)
testCompletion(fileText, JvmPlatform, { completionType, count -> myFixture.complete(completionType, count) })
}
override fun getTestDataPath(): String {
return KotlinAndroidTestCaseBase.getPluginTestDataPathBase() + "/completion/" + getTestName(true) + "/"
}
override fun tearDown() {
val settings = CodeInsightSettings.getInstance()
settings.AUTOCOMPLETE_ON_CODE_COMPLETION = codeCompletionOldValue
@@ -16,26 +16,17 @@
package org.jetbrains.kotlin.android
import com.intellij.codeInsight.TargetElementUtil
abstract class AbstractAndroidFindUsagesTest : KotlinAndroidTestCase() {
override fun getTestDataPath() = KotlinAndroidTestCaseBase.getPluginTestDataPathBase() + "/findUsages/" + getTestName(true) + "/"
fun doTest(path: String) {
if (true) return // Muted (actually works in IDEA)
val f = myFixture!!
getResourceDirs(path).forEach { myFixture.copyDirectoryToProject(it.name, it.name) }
val virtualFile = f.copyFileToProject(path + getTestName(true) + ".kt", "src/" + getTestName(true) + ".kt")
f.configureFromExistingVirtualFile(virtualFile)
val targetElement = TargetElementUtil.findTargetElement(
f.editor, TargetElementUtil.ELEMENT_NAME_ACCEPTED or TargetElementUtil.REFERENCED_ELEMENT_ACCEPTED)
assertNotNull(targetElement)
val propUsages = f.findUsages(targetElement!!)
return // TODO: investigate and fix this test
copyResourceDirectoryForTest(path)
val testFileName = getTestName(true) + ".kt"
val virtualFile = myFixture.copyFileToProject(path + testFileName, "src/" + getTestName(true) + ".kt")
myFixture.configureFromExistingVirtualFile(virtualFile)
val propUsages = myFixture.findUsages(myFixture.elementAtCaret)
assertTrue(propUsages.isNotEmpty())
}
}
@@ -31,22 +31,17 @@ import org.jetbrains.kotlin.test.KotlinTestUtils
abstract class AbstractAndroidGotoTest : KotlinAndroidTestCase() {
override fun getTestDataPath(): String {
return KotlinAndroidTestCaseBase.getPluginTestDataPathBase() + "/goto/" + getTestName(true) + "/"
}
fun doTest(path: String) {
val f = myFixture!!
getResourceDirs(path).forEach { myFixture.copyDirectoryToProject(it.name, it.name) }
val virtualFile = f.copyFileToProject(path + getTestName(true) + ".kt", "src/" + getTestName(true) + ".kt")
f.configureFromExistingVirtualFile(virtualFile)
copyResourceDirectoryForTest(path)
val virtualFile = myFixture.copyFileToProject(path + getTestName(true) + ".kt", "src/" + getTestName(true) + ".kt")
myFixture.configureFromExistingVirtualFile(virtualFile)
val expression = TargetElementUtil.findReference(f.editor, f.caretOffset)!!.element as KtElement
val expression = TargetElementUtil.findReference(myFixture.editor, myFixture.caretOffset)!!.element as KtElement
val bindingContext = expression.analyzeFully()
val resolvedCall = bindingContext[BindingContext.RESOLVED_CALL, bindingContext[BindingContext.CALL, expression]]!!
val property = resolvedCall.resultingDescriptor as? PropertyDescriptor ?: throw AssertionError("PropertyDescriptor expected")
val targetElement = GotoDeclarationAction.findTargetElement(f.project, f.editor, f.caretOffset)!!
val targetElement = GotoDeclarationAction.findTargetElement(myFixture.project, myFixture.editor, myFixture.caretOffset)!!
assert(targetElement is XmlAttributeValue) { "XmlAttributeValue expected, got ${targetElement::class.java}" }
assertEquals("@+id/${property.name}", (targetElement as XmlAttributeValue).value)
@@ -29,12 +29,11 @@ abstract class AbstractAndroidLayoutRenameTest : KotlinAndroidTestCase() {
private val NEW_NAME_XML = "$NEW_NAME.xml"
fun doTest(path: String) {
val f = myFixture!!
getResourceDirs(path).forEach { myFixture.copyDirectoryToProject(it.name, it.name) }
val virtualFile = f.copyFileToProject(path + getTestName(true) + ".kt", "src/" + getTestName(true) + ".kt")
f.configureFromExistingVirtualFile(virtualFile)
copyResourceDirectoryForTest(path)
val virtualFile = myFixture.copyFileToProject(path + getTestName(true) + ".kt", "src/" + getTestName(true) + ".kt")
myFixture.configureFromExistingVirtualFile(virtualFile)
val completionEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(f.editor, f.file)
val completionEditor = InjectedLanguageUtil.getEditorForInjectedLanguageNoCommit(myFixture.editor, myFixture.file)
val element = TargetElementUtil.findTargetElement(
completionEditor,
@@ -42,10 +41,8 @@ abstract class AbstractAndroidLayoutRenameTest : KotlinAndroidTestCase() {
val file = element.containingFile as XmlFile
RenameProcessor(f.project, file, NEW_NAME_XML, false, true).run()
RenameProcessor(myFixture.project, file, NEW_NAME_XML, false, true).run()
(f.file as KtFile).importDirectives.any { it.importedFqName!!.asString() == AndroidConst.SYNTHETIC_PACKAGE + ".main." + NEW_NAME }
(myFixture.file as KtFile).importDirectives.any { it.importedFqName!!.asString() == AndroidConst.SYNTHETIC_PACKAGE + ".main." + NEW_NAME }
}
override fun getTestDataPath() = KotlinAndroidTestCaseBase.getPluginTestDataPathBase() + "/rename/" + getTestName(true) + "/"
}
@@ -16,24 +16,19 @@
package org.jetbrains.kotlin.android
import com.intellij.codeInsight.TargetElementUtil
import com.intellij.openapi.vfs.LocalFileSystem
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil
import com.intellij.refactoring.rename.RenameProcessor
import com.intellij.psi.impl.source.xml.XmlAttributeValueImpl
import com.intellij.testFramework.PlatformTestUtil
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
abstract class AbstractAndroidRenameTest : KotlinAndroidTestCase() {
private val NEW_NAME = "NEWNAME"
private val NEW_ID_NAME = "@+id/$NEW_NAME"
fun doTest(path: String) {
getResourceDirs(path).forEach { myFixture.copyDirectoryToProject(it.name, it.name) }
copyResourceDirectoryForTest(path)
val virtualFile = myFixture.copyFileToProject("$path${getTestName(true)}.kt", "src/${getTestName(true)}.kt")
myFixture.configureFromExistingVirtualFile(virtualFile)
myFixture.renameElement(myFixture.elementAtCaret, NEW_ID_NAME)
myFixture.checkResultByFile("expected/${getTestName(true)}.kt")
myFixture.checkResultByFile("$path/expected/${getTestName(true)}.kt")
assertResourcesEqual("$path/expected/res")
}
@@ -42,6 +37,4 @@ abstract class AbstractAndroidRenameTest : KotlinAndroidTestCase() {
}
fun getResourceDirectory() = LocalFileSystem.getInstance().findFileByPath(myFixture.tempDirPath + "/res")
override fun getTestDataPath() = KotlinAndroidTestCaseBase.getPluginTestDataPathBase() + "/rename/" + getTestName(true) + "/"
}