diff --git a/idea/idea-android/tests/org/jetbrains/kotlin/android/AndroidTestBase.java b/idea/idea-android/tests/org/jetbrains/kotlin/android/AndroidTestBase.java index e47883cf602..4b9a895ea7c 100644 --- a/idea/idea-android/tests/org/jetbrains/kotlin/android/AndroidTestBase.java +++ b/idea/idea-android/tests/org/jetbrains/kotlin/android/AndroidTestBase.java @@ -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; } diff --git a/idea/idea-android/tests/org/jetbrains/kotlin/android/AndroidTestCase.java b/idea/idea-android/tests/org/jetbrains/kotlin/android/AndroidTestCase.java index dcf6b52b039..ba5b74fa1d3 100644 --- a/idea/idea-android/tests/org/jetbrains/kotlin/android/AndroidTestCase.java +++ b/idea/idea-android/tests/org/jetbrains/kotlin/android/AndroidTestCase.java @@ -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; diff --git a/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt b/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt index e83772df1fe..5e5027e9f3f 100644 --- a/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt +++ b/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/ConfigLibraryUtil.kt @@ -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() } diff --git a/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/PluginTestCaseBase.java b/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/PluginTestCaseBase.java index ee7c1587811..64aa79ba08e 100644 --- a/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/PluginTestCaseBase.java +++ b/idea/idea-test-framework/src/org/jetbrains/kotlin/idea/test/PluginTestCaseBase.java @@ -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 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) { diff --git a/idea/tests/org/jetbrains/kotlin/asJava/LightClassesClasspathSortingTest.kt b/idea/tests/org/jetbrains/kotlin/asJava/LightClassesClasspathSortingTest.kt index 7a27beee7db..22902012b58 100644 --- a/idea/tests/org/jetbrains/kotlin/asJava/LightClassesClasspathSortingTest.kt +++ b/idea/tests/org/jetbrains/kotlin/asJava/LightClassesClasspathSortingTest.kt @@ -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/" } } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractMultiFileInspectionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractMultiFileInspectionTest.kt index e5fa6723700..951d2a832a4 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractMultiFileInspectionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeInsight/AbstractMultiFileInspectionTest.kt @@ -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() } } diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt index 3c031bf76a3..21ddddc499a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/introduce/AbstractExtractionTest.kt @@ -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 diff --git a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/AbstractMultiModuleMoveTest.kt b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/AbstractMultiModuleMoveTest.kt index 2a4f1574366..f58e7a2283e 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/AbstractMultiModuleMoveTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/refactoring/move/AbstractMultiModuleMoveTest.kt @@ -38,6 +38,8 @@ abstract class AbstractMultiModuleMoveTest : KotlinMultiFileTestCase() { val modulesWithJvmRuntime: List val modulesWithJsRuntime: List + PluginTestCaseBase.addJdk(testRootDisposable, PluginTestCaseBase::mockJdk) + val withRuntime = config["withRuntime"]?.asBoolean ?: false if (withRuntime) { val moduleManager = ModuleManager.getInstance(project) diff --git a/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt b/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt index b7bec3ab30d..5a5b6908e16 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/run/RunConfigurationTest.kt @@ -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() @@ -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, diff --git a/idea/tests/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt b/idea/tests/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt index 4981b6d91bb..409bac99168 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/stubs/AbstractMultiModuleTest.kt @@ -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 } diff --git a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/AbstractSpringClassAnnotatorTest.kt b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/AbstractSpringClassAnnotatorTest.kt index ecf7938044d..19079df2504 100644 --- a/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/AbstractSpringClassAnnotatorTest.kt +++ b/ultimate/tests/org/jetbrains/kotlin/idea/spring/tests/gutter/AbstractSpringClassAnnotatorTest.kt @@ -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())