Fix "Virtual pointer hasn't been disposed" exception in tests. Add sdk to ProjectJdkTable.

This commit is contained in:
Natalia Selezneva
2018-01-30 16:11:31 +03:00
parent f05e926670
commit 74a9881e9d
11 changed files with 74 additions and 36 deletions
@@ -18,6 +18,7 @@ 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.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.PathManagerEx;
import com.intellij.openapi.module.Module;
@@ -56,6 +57,8 @@ public abstract class AndroidTestBase extends UsefulTestCase {
protected JavaCodeInsightTestFixture myFixture;
protected static final String ANDROID_SDK_NAME = "android_test_sdk";
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.
@@ -100,7 +103,7 @@ public abstract class AndroidTestBase extends UsefulTestCase {
String sdkPath = TestUtils.getSdk().toString();
String platformDir = TestUtils.getLatestAndroidPlatform();
Sdk sdk = ProjectJdkTable.getInstance().createSdk("android_test_sdk", AndroidSdkType.getInstance());
Sdk sdk = ProjectJdkTable.getInstance().createSdk(ANDROID_SDK_NAME, AndroidSdkType.getInstance());
SdkModificator sdkModificator = sdk.getSdkModificator();
sdkModificator.setHomePath(sdkPath);
@@ -131,6 +134,9 @@ public abstract class AndroidTestBase extends UsefulTestCase {
sdkModificator.setSdkAdditionalData(data);
ExternalAnnotationsSupport.attachJdkAnnotations(sdkModificator);
sdkModificator.commitChanges();
ApplicationManager.getApplication().runWriteAction(() -> ProjectJdkTable.getInstance().addJdk(sdk));
return sdk;
}
@@ -29,6 +29,8 @@ import com.intellij.facet.ModifiableFacetModel;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.projectRoots.ProjectJdkTable;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.LanguageLevelProjectExtension;
import com.intellij.openapi.roots.ModuleRootModificationUtil;
import com.intellij.openapi.util.Disposer;
@@ -153,6 +155,11 @@ public abstract class AndroidTestCase extends AndroidTestBase {
@Override
protected void tearDown() throws Exception {
try {
Sdk androidSdk = ProjectJdkTable.getInstance().findJdk(ANDROID_SDK_NAME);
if (androidSdk != null) {
ApplicationManager.getApplication().runWriteAction(() -> ProjectJdkTable.getInstance().removeJdk(androidSdk));
}
CodeStyleSettingsManager.getInstance(getProject()).dropTemporarySettings();
myModule = null;
myAdditionalModules = null;
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.test
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.module.Module
import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModifiableRootModel
@@ -34,6 +35,7 @@ import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.utils.PathUtil
import java.io.File
import java.util.*
import kotlin.test.assertNotNull
/**
* Helper for configuring kotlin runtime in tested project.
@@ -88,6 +90,13 @@ object ConfigLibraryUtil {
val rootManager = ModuleRootManager.getInstance(module)
val rootModel = rootManager.modifiableModel
assertNotNull(
ProjectJdkTable.getInstance().findJdk(sdk.name),
"Cannot find sdk in ProjectJdkTable. This may cause sdk leak.\n" +
"You can use ProjectPluginTestBase.addJdk(Disposable ...) to register sdk in ProjectJdkTable.\n" +
"Then sdk will be removed in tearDown"
)
rootModel.sdk = sdk
rootModel.commit()
}
@@ -25,6 +25,7 @@ import com.intellij.openapi.projectRoots.impl.JavaSdkImpl;
import com.intellij.openapi.util.Disposer;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
import kotlin.jvm.functions.Function0;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.kotlin.test.KotlinTestUtils;
@@ -52,6 +53,11 @@ public class PluginTestCaseBase {
@NotNull
private static Sdk getSdk(String sdkHome, String name) {
ProjectJdkTable table = ProjectJdkTable.getInstance();
Sdk existing = table.findJdk(name);
if (existing != null) {
return existing;
}
return JavaSdk.getInstance().createJdk(name, sdkHome, true);
}
@@ -84,6 +90,13 @@ public class PluginTestCaseBase {
return getSdk(javaHome, "Full JDK");
}
@NotNull
public static Sdk addJdk(@NotNull Disposable disposable, @NotNull Function0<Sdk> getJdk) {
Sdk jdk = getJdk.invoke();
ApplicationManager.getApplication().runWriteAction(() -> ProjectJdkTable.getInstance().addJdk(jdk, disposable));
return jdk;
}
@NotNull
public static Sdk jdk(@NotNull TestJdkKind kind) {
switch (kind) {
@@ -18,17 +18,18 @@ package org.jetbrains.kotlin.asJava
import com.intellij.psi.JavaPsiFacade
import com.intellij.psi.impl.ResolveScopeManager
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.asJava.classes.KtLightClassForFacade
import org.jetbrains.kotlin.asJava.classes.KtLightClassForSourceDeclaration
import org.jetbrains.kotlin.idea.caches.resolve.lightClasses.KtLightClassForDecompiledDeclaration
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.SdkAndMockLibraryProjectDescriptor
import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.configureAs
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
import kotlin.test.assertNotNull
class LightClassesClasspathSortingTest : KotlinCodeInsightTestCase() {
class LightClassesClasspathSortingTest : KotlinLightCodeInsightFixtureTestCase() {
fun testExplicitClass() {
doTest("test1.A")
}
@@ -40,13 +41,11 @@ class LightClassesClasspathSortingTest : KotlinCodeInsightTestCase() {
private fun doTest(fqName: String) {
// Same classes are in sources and in compiled Kotlin library. Test that light classes from sources have a priority.
// Configure library first to make classes be indexed before correspondent classes from sources
val dirName = getTestName(true)
module.configureAs(getProjectDescriptor(dirName))
val testDirRoot = File(testDataPath)
val filePaths = File(testDirRoot, dirName).listFiles().map { it.toRelativeString(testDirRoot) }.toTypedArray()
configureByFiles(null, *filePaths)
myFixture.configureByFiles(*filePaths)
checkLightClassBeforeDecompiled(fqName)
}
@@ -60,13 +59,14 @@ class LightClassesClasspathSortingTest : KotlinCodeInsightTestCase() {
assert(psiClass !is KtLightClassForDecompiledDeclaration) { "Should not be decompiled light class: $fqName ${psiClass::class.java}" }
}
private fun getProjectDescriptor(dir: String) =
SdkAndMockLibraryProjectDescriptor(
PluginTestCaseBase.getTestDataPathBase() + "/decompiler/lightClassesOrder/$dir",
override fun getProjectDescriptor(): LightProjectDescriptor {
return SdkAndMockLibraryProjectDescriptor(
"$testDataPath${getTestName(true)}",
true
)
}
override fun getTestDataPath(): String? {
return PluginTestCaseBase.getTestDataPathBase() + "/decompiler/lightClassesOrder/"
override fun getTestDataPath(): String {
return KotlinTestUtils.getHomeDirectory() + "/idea/testData/decompiler/lightClassesOrder/"
}
}
@@ -23,7 +23,7 @@ import org.jetbrains.kotlin.idea.inspections.runInspection
import org.jetbrains.kotlin.idea.jsonUtils.getString
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.KotlinMultiFileTestCase
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.*
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
import java.io.File
@@ -41,13 +41,13 @@ abstract class AbstractMultiFileInspectionTest : KotlinMultiFileTestCase() {
isMultiModule = config["isMultiModule"]?.asBoolean ?: false
doTest({ _, _ ->
val sdk = if (withFullJdk) fullJdk() else mockJdk()
addJdk(testRootDisposable) { sdk }
try {
if (withRuntime) {
project.allModules().forEach { module ->
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(
module,
if (withFullJdk) PluginTestCaseBase.fullJdk() else PluginTestCaseBase.mockJdk()
)
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(module, sdk)
}
}
@@ -57,10 +57,7 @@ abstract class AbstractMultiFileInspectionTest : KotlinMultiFileTestCase() {
finally {
if (withRuntime) {
project.allModules().forEach { module ->
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(
module,
if (withFullJdk) PluginTestCaseBase.fullJdk() else PluginTestCaseBase.mockJdk()
)
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(module, sdk)
}
}
}
@@ -73,6 +70,6 @@ abstract class AbstractMultiFileInspectionTest : KotlinMultiFileTestCase() {
}
override fun getTestDataPath() : String {
return PluginTestCaseBase.getTestDataPathBase()
return getTestDataPathBase()
}
}
@@ -331,6 +331,8 @@ abstract class AbstractExtractionTest : KotlinLightCodeInsightFixtureTestCase()
protected fun doTest(path: String, checkAdditionalAfterdata: Boolean = false, action: (PsiFile) -> Unit) {
val mainFile = File(path)
PluginTestCaseBase.addJdk(myFixture.projectDisposable, PluginTestCaseBase::mockJdk)
fixture.testDataPath = "${KotlinTestUtils.getHomeDirectory()}/${mainFile.parent}"
val mainFileName = mainFile.name
@@ -38,6 +38,8 @@ abstract class AbstractMultiModuleMoveTest : KotlinMultiFileTestCase() {
val modulesWithJvmRuntime: List<Module>
val modulesWithJsRuntime: List<Module>
PluginTestCaseBase.addJdk(testRootDisposable, PluginTestCaseBase::mockJdk)
val withRuntime = config["withRuntime"]?.asBoolean ?: false
if (withRuntime) {
val moduleManager = ModuleManager.getInstance(project)
@@ -38,7 +38,7 @@ import org.jetbrains.kotlin.idea.stubindex.KotlinFullClassNameIndex
import org.jetbrains.kotlin.idea.stubindex.KotlinTopLevelFunctionFqnNameIndex
import org.jetbrains.kotlin.idea.test.ConfigLibraryUtil
import org.jetbrains.kotlin.idea.test.KotlinCodeInsightTestCase
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase.*
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.allChildren
@@ -56,7 +56,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
fun testMainInTest() {
val createResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!)
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createResult.module, PluginTestCaseBase.mockJdk())
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createResult.module, addJdk(testRootDisposable, ::mockJdk))
val runConfiguration = createConfigurationFromMain("some.main")
val javaParameters = getJavaRunParameters(runConfiguration)
@@ -142,7 +142,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
fun testUpdateOnClassRename() {
val createModuleResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!)
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createModuleResult.module, PluginTestCaseBase.mockJdk())
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk))
val runConfiguration = createConfigurationFromObject("renameTest.Foo", save = true)
@@ -155,7 +155,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
fun testUpdateOnPackageRename() {
val createModuleResult = configureModule(moduleDirPath("module"), getTestProject().baseDir!!)
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createModuleResult.module, PluginTestCaseBase.mockJdk())
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk))
val runConfiguration = createConfigurationFromObject("renameTest.Foo", save = true)
@@ -167,15 +167,15 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
}
fun testWithModuleForJdk6() {
checkModuleInfoName(null, PluginTestCaseBase.mockJdk())
checkModuleInfoName(null, addJdk(testRootDisposable, ::mockJdk))
}
fun testWithModuleForJdk9() {
checkModuleInfoName("MAIN", PluginTestCaseBase.mockJdk9())
checkModuleInfoName("MAIN", addJdk(testRootDisposable, ::mockJdk9))
}
fun testWithModuleForJdk9WithoutModuleInfo() {
checkModuleInfoName(null, PluginTestCaseBase.mockJdk9())
checkModuleInfoName(null, addJdk(testRootDisposable, ::mockJdk9))
}
private fun checkModuleInfoName(moduleName: String?, sdk: Sdk) {
@@ -192,7 +192,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
val createModuleResult = configureModule(moduleDirPath("module"), baseDir)
val srcDir = createModuleResult.srcDir
configureRuntime(createModuleResult.module, PluginTestCaseBase.mockJdk())
configureRuntime(createModuleResult.module, addJdk(testRootDisposable, ::mockJdk))
try {
val expectedClasses = ArrayList<String>()
@@ -222,7 +222,7 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
Assert.assertEquals(expectedClasses, actualClasses)
}
finally {
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(createModuleResult.module, PluginTestCaseBase.mockJdk())
ConfigLibraryUtil.unConfigureKotlinRuntimeAndSdk(createModuleResult.module, mockJdk())
}
}
@@ -266,8 +266,8 @@ class RunConfigurationTest: KotlinCodeInsightTestCase() {
private fun moduleDirPath(moduleName: String) = "${testDataPath}${getTestName(false)}/$moduleName"
override fun getTestDataPath() = PluginTestCaseBase.getTestDataPathBase() + "/run/"
override fun getTestProjectJdk() = PluginTestCaseBase.mockJdk()
override fun getTestDataPath() = getTestDataPathBase() + "/run/"
override fun getTestProjectJdk() = mockJdk()
private class CreateModuleResult(
val module: Module,
@@ -51,7 +51,7 @@ abstract class AbstractMultiModuleTest : DaemonAnalyzerTestCase() {
setTestRoot(moduleWithSrcRootSet, name)
}
ConfigLibraryUtil.configureSdk(moduleWithSrcRootSet, PluginTestCaseBase.jdk(jdk))
ConfigLibraryUtil.configureSdk(moduleWithSrcRootSet, PluginTestCaseBase.addJdk(testRootDisposable) { PluginTestCaseBase.jdk(jdk) })
return moduleWithSrcRootSet
}
@@ -55,6 +55,8 @@ abstract class AbstractSpringClassAnnotatorTest : KotlinLightCodeInsightFixtureT
val config = JsonParser().parse(FileUtil.loadFile(configFile, true)) as JsonObject
PluginTestCaseBase.addJdk(myFixture.projectDisposable, PluginTestCaseBase::mockJdk)
val withRuntime = config["withRuntime"]?.asBoolean ?: false
if (withRuntime) {
ConfigLibraryUtil.configureKotlinRuntimeAndSdk(myModule, PluginTestCaseBase.mockJdk())