diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/AbstractGradleMultiplatformWizardTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/AbstractGradleMultiplatformWizardTest.kt new file mode 100644 index 00000000000..754970c1f69 --- /dev/null +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/AbstractGradleMultiplatformWizardTest.kt @@ -0,0 +1,243 @@ +/* + * Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license + * that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle + +import com.intellij.ide.projectWizard.NewProjectWizard +import com.intellij.ide.projectWizard.ProjectTypeStep +import com.intellij.ide.projectWizard.ProjectWizardTestCase +import com.intellij.ide.util.newProjectWizard.AbstractProjectWizard +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.application.Result +import com.intellij.openapi.application.WriteAction +import com.intellij.openapi.components.ServiceManager +import com.intellij.openapi.diagnostic.Logger +import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder +import com.intellij.openapi.externalSystem.model.DataNode +import com.intellij.openapi.externalSystem.model.project.ProjectData +import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode +import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback +import com.intellij.openapi.externalSystem.service.project.ProjectDataManager +import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings +import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil +import com.intellij.openapi.externalSystem.util.ExternalSystemUtil +import com.intellij.openapi.module.ModuleManager +import com.intellij.openapi.project.Project +import com.intellij.openapi.projectRoots.ProjectJdkTable +import com.intellij.openapi.projectRoots.SimpleJavaSdkType +import com.intellij.openapi.roots.ModuleRootManager +import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.roots.ui.configuration.ModulesProvider +import com.intellij.openapi.util.Couple +import com.intellij.openapi.util.Ref +import com.intellij.openapi.util.io.FileUtil +import com.intellij.openapi.util.text.StringUtil +import com.intellij.openapi.vfs.LocalFileSystem +import com.intellij.openapi.vfs.VfsUtilCore +import com.intellij.openapi.vfs.VirtualFile +import com.intellij.testFramework.IdeaTestUtil +import com.intellij.testFramework.UsefulTestCase +import com.intellij.util.containers.ContainerUtil +import com.intellij.util.containers.ContainerUtilRt +import junit.framework.TestCase +import org.jetbrains.kotlin.idea.codeInsight.gradle.GradleImportingTestCase +import org.jetbrains.kotlin.idea.configuration.* +import org.jetbrains.kotlin.utils.PrintingLogger +import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper +import org.jetbrains.plugins.gradle.settings.DistributionType +import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings +import org.jetbrains.plugins.gradle.settings.GradleProjectSettings +import org.jetbrains.plugins.gradle.settings.GradleSettings +import org.jetbrains.plugins.gradle.util.GradleConstants +import org.junit.Test +import java.io.File +import java.io.IOException +import java.util.* + +abstract class AbstractGradleMultiplatformWizardTest : ProjectWizardTestCase() { + + private val pluginVersion = "1.3.0-rc-146" + + override fun createWizard(project: Project?, directory: File): AbstractProjectWizard { + return NewProjectWizard(project, ModulesProvider.EMPTY_MODULES_PROVIDER, directory.path) + } + + private fun Project.reconfigureGradleSettings(f: GradleProjectSettings.() -> Unit) { + val systemSettings = ExternalSystemApiUtil.getSettings( + this, + externalSystemId + ) + val projectSettings = GradleProjectSettings() + projectSettings.f() + val projects = ContainerUtilRt.newHashSet(systemSettings.getLinkedProjectsSettings()) + projects.remove(projectSettings) + projects.add(projectSettings) + systemSettings.setLinkedProjectsSettings(projects) + } + + protected fun testImportFromBuilder( + builder: KotlinGradleAbstractMultiplatformModuleBuilder, + vararg testClassNames: String, + metadataInside: Boolean = false, + performImport: Boolean = true + ) { + // Temporary workaround for duplicated bundled template + class PrintingFactory : Logger.Factory { + override fun getLoggerInstance(category: String): Logger { + return PrintingLogger(System.out) + } + } + Logger.setFactory(PrintingFactory::class.java) + + val project = createProject { step -> + if (step is ProjectTypeStep) { + TestCase.assertTrue(step.setSelectedTemplate("Kotlin", builder.presentableName)) + val steps = myWizard.sequence.selectedSteps + TestCase.assertEquals(4, steps.size) + val projectBuilder = myWizard.projectBuilder + UsefulTestCase.assertInstanceOf(projectBuilder, builder::class.java) + with(projectBuilder as KotlinGradleAbstractMultiplatformModuleBuilder) { + explicitPluginVersion = pluginVersion + } + + myProject.reconfigureGradleSettings { + distributionType = DistributionType.DEFAULT_WRAPPED + } + } + } + + val modules = ModuleManager.getInstance(project).modules + TestCase.assertEquals(1, modules.size) + val module = modules[0] + TestCase.assertTrue(ModuleRootManager.getInstance(module).isSdkInherited) + + val root = ProjectRootManager.getInstance(project).contentRoots[0] + + val settingsScript = VfsUtilCore.findRelativeFile("settings.gradle", root) + TestCase.assertNotNull(settingsScript) + val settingsScriptText = StringUtil.convertLineSeparators(VfsUtilCore.loadText(settingsScript!!)) + TestCase.assertTrue("rootProject.name = " in settingsScriptText) + if (metadataInside) { + TestCase.assertTrue("enableFeaturePreview('GRADLE_METADATA')" in settingsScriptText) + } + + val buildScript = VfsUtilCore.findRelativeFile("build.gradle", root)!! + val buildScriptText = StringUtil.convertLineSeparators(VfsUtilCore.loadText(buildScript)) + println(buildScriptText) + + if (!performImport) return + doImportProject(project) + if (testClassNames.isNotEmpty()) { + doTestProject(project, *testClassNames) + } + } + + @Throws(IOException::class) + private fun Project.createProjectSubFile(relativePath: String): VirtualFile { + val f = File(basePath!!, relativePath) + FileUtil.ensureExists(f.parentFile) + FileUtil.ensureCanCreateFile(f) + val created = f.createNewFile() + if (!created) { + throw AssertionError("Unable to create the project sub file: " + f.absolutePath) + } + return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f)!! + } + + private fun runWrite(f: () -> Unit) { + object : WriteAction() { + override fun run(result: Result) { + f() + } + }.execute() + } + + private fun doImportProject(project: Project) { + ExternalSystemApiUtil.subscribe( + project, + GradleConstants.SYSTEM_ID, + object : ExternalSystemSettingsListenerAdapter() { + override fun onProjectsLinked(settings: Collection) { + val item = ContainerUtil.getFirstItem(settings) + if (item is GradleProjectSettings) { + item.gradleJvm = DEFAULT_SDK + } + } + }) + + GradleSettings.getInstance(project).gradleVmOptions = "-Xmx128m -XX:MaxPermSize=64m" + val wrapperJarFrom = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(GradleImportingTestCase.wrapperJar())!! + val wrapperJarFromTo = project.createProjectSubFile("gradle/wrapper/gradle-wrapper.jar") + runWrite { + wrapperJarFromTo.setBinaryContent(wrapperJarFrom.contentsToByteArray()) + } + + project.reconfigureGradleSettings { + distributionType = DistributionType.DEFAULT_WRAPPED + externalProjectPath = project.basePath!! + gradleJvm = DEFAULT_SDK + } + + val error = Ref.create>() + ExternalSystemUtil.refreshProjects( + ImportSpecBuilder(project, externalSystemId) + .use(ProgressExecutionMode.MODAL_SYNC) + .callback(object : ExternalProjectRefreshCallback { + override fun onSuccess(externalProject: DataNode?) { + if (externalProject == null) { + val errorMessage = "Got null External project after import" + System.err.println(errorMessage) + error.set(Couple.of(errorMessage, null)) + return + } + ServiceManager.getService(ProjectDataManager::class.java).importData(externalProject, project, true) + println("External project was successfully imported") + } + + override fun onFailure(errorMessage: String, errorDetails: String?) { + error.set(Couple.of(errorMessage, errorDetails)) + } + }) + .forceWhenUptodate() + ) + + if (!error.isNull) { + var failureMsg = "Import failed: " + error.get().first + if (StringUtil.isNotEmpty(error.get().second)) { + failureMsg += "\nError details: \n" + error.get().second + } + TestCase.fail(failureMsg) + } + } + + private fun doTestProject(project: Project, vararg testClassNames: String) { + val settings = GradleExecutionSettings(null, null, DistributionType.DEFAULT_WRAPPED, false) + println("Running project tests: ${testClassNames.toList()}") + GradleExecutionHelper().execute(project.basePath!!, settings) { + val testLauncher = it.newTestLauncher() + testLauncher.withJvmTestClasses(*testClassNames).run() + } + println("Waiting for daemon death...") + Thread.sleep(30000L) + println("Trying to clean everything...") + } + + override fun setUp() { + super.setUp() + val javaHome = IdeaTestUtil.requireRealJdkHome() + ApplicationManager.getApplication().runWriteAction { + addSdk(SimpleJavaSdkType().createJdk(DEFAULT_SDK, javaHome)) + addSdk(SimpleJavaSdkType().createJdk("_other", javaHome)) + + println("ProjectWizardTestCase.configureJdk:") + println(Arrays.asList(*ProjectJdkTable.getInstance().allJdks)) + } + } + + companion object { + val externalSystemId = GradleConstants.SYSTEM_ID + } +} \ No newline at end of file diff --git a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/GradleMultiplatformWizardTest.kt b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/GradleMultiplatformWizardTest.kt index c2ce01b6aa1..b9e29883fc0 100644 --- a/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/GradleMultiplatformWizardTest.kt +++ b/idea/idea-gradle/tests/org/jetbrains/kotlin/gradle/GradleMultiplatformWizardTest.kt @@ -5,227 +5,20 @@ package org.jetbrains.kotlin.gradle -import com.intellij.ide.projectWizard.NewProjectWizard -import com.intellij.ide.projectWizard.ProjectTypeStep -import com.intellij.ide.projectWizard.ProjectWizardTestCase -import com.intellij.ide.util.newProjectWizard.AbstractProjectWizard -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.application.Result -import com.intellij.openapi.application.WriteAction -import com.intellij.openapi.components.ServiceManager -import com.intellij.openapi.diagnostic.Logger -import com.intellij.openapi.externalSystem.importing.ImportSpecBuilder -import com.intellij.openapi.externalSystem.model.DataNode -import com.intellij.openapi.externalSystem.model.project.ProjectData -import com.intellij.openapi.externalSystem.service.execution.ProgressExecutionMode -import com.intellij.openapi.externalSystem.service.project.ExternalProjectRefreshCallback -import com.intellij.openapi.externalSystem.service.project.ProjectDataManager -import com.intellij.openapi.externalSystem.settings.ExternalProjectSettings -import com.intellij.openapi.externalSystem.settings.ExternalSystemSettingsListenerAdapter -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil -import com.intellij.openapi.externalSystem.util.ExternalSystemUtil -import com.intellij.openapi.module.ModuleManager -import com.intellij.openapi.project.Project -import com.intellij.openapi.projectRoots.ProjectJdkTable -import com.intellij.openapi.projectRoots.SimpleJavaSdkType -import com.intellij.openapi.roots.ModuleRootManager -import com.intellij.openapi.roots.ProjectRootManager -import com.intellij.openapi.roots.ui.configuration.ModulesProvider -import com.intellij.openapi.util.Couple -import com.intellij.openapi.util.Ref -import com.intellij.openapi.util.io.FileUtil -import com.intellij.openapi.util.text.StringUtil -import com.intellij.openapi.vfs.LocalFileSystem -import com.intellij.openapi.vfs.VfsUtilCore -import com.intellij.openapi.vfs.VirtualFile -import com.intellij.testFramework.IdeaTestUtil -import com.intellij.testFramework.UsefulTestCase -import com.intellij.util.containers.ContainerUtil -import com.intellij.util.containers.ContainerUtilRt -import junit.framework.TestCase import org.jetbrains.kotlin.ide.konan.gradle.KotlinGradleNativeMultiplatformModuleBuilder -import org.jetbrains.kotlin.idea.codeInsight.gradle.GradleImportingTestCase -import org.jetbrains.kotlin.idea.configuration.* -import org.jetbrains.kotlin.utils.PrintingLogger -import org.jetbrains.plugins.gradle.service.execution.GradleExecutionHelper -import org.jetbrains.plugins.gradle.settings.DistributionType -import org.jetbrains.plugins.gradle.settings.GradleExecutionSettings -import org.jetbrains.plugins.gradle.settings.GradleProjectSettings -import org.jetbrains.plugins.gradle.settings.GradleSettings -import org.jetbrains.plugins.gradle.util.GradleConstants +import org.jetbrains.kotlin.idea.configuration.KotlinGradleMobileMultiplatformModuleBuilder +import org.jetbrains.kotlin.idea.configuration.KotlinGradleMobileSharedMultiplatformModuleBuilder +import org.jetbrains.kotlin.idea.configuration.KotlinGradleSharedMultiplatformModuleBuilder +import org.jetbrains.kotlin.idea.configuration.KotlinGradleWebMultiplatformModuleBuilder import org.junit.Test -import java.io.File -import java.io.IOException -import java.util.* -class GradleMultiplatformWizardTest : ProjectWizardTestCase() { - - private val pluginVersion = "1.3.0-rc-146" - - override fun createWizard(project: Project?, directory: File): AbstractProjectWizard { - return NewProjectWizard(project, ModulesProvider.EMPTY_MODULES_PROVIDER, directory.path) +class GradleMultiplatformWizardTest : AbstractGradleMultiplatformWizardTest() { + @Test + fun testMobile() { + // TODO: add import & tests here when we will be able to locate Android SDK automatically (see KT-27635) + testImportFromBuilder(KotlinGradleMobileMultiplatformModuleBuilder(), performImport = false) } - private fun Project.reconfigureGradleSettings(f: GradleProjectSettings.() -> Unit) { - val systemSettings = ExternalSystemApiUtil.getSettings( - this, - externalSystemId - ) - val projectSettings = GradleProjectSettings() - projectSettings.f() - val projects = ContainerUtilRt.newHashSet(systemSettings.getLinkedProjectsSettings()) - projects.remove(projectSettings) - projects.add(projectSettings) - systemSettings.setLinkedProjectsSettings(projects) - } - - private fun testImportFromBuilder( - builder: KotlinGradleAbstractMultiplatformModuleBuilder, - vararg testClassNames: String, - metadataInside: Boolean = false - ) { - // Temporary workaround for duplicated bundled template - class PrintingFactory : Logger.Factory { - override fun getLoggerInstance(category: String): Logger { - return PrintingLogger(System.out) - } - } - Logger.setFactory(PrintingFactory::class.java) - - val project = createProject { step -> - if (step is ProjectTypeStep) { - TestCase.assertTrue(step.setSelectedTemplate("Kotlin", builder.presentableName)) - val steps = myWizard.sequence.selectedSteps - TestCase.assertEquals(4, steps.size) - val projectBuilder = myWizard.projectBuilder - UsefulTestCase.assertInstanceOf(projectBuilder, builder::class.java) - with(projectBuilder as KotlinGradleAbstractMultiplatformModuleBuilder) { - explicitPluginVersion = pluginVersion - } - - myProject.reconfigureGradleSettings { - distributionType = DistributionType.DEFAULT_WRAPPED - } - } - } - - val modules = ModuleManager.getInstance(project).modules - TestCase.assertEquals(1, modules.size) - val module = modules[0] - TestCase.assertTrue(ModuleRootManager.getInstance(module).isSdkInherited) - - val root = ProjectRootManager.getInstance(project).contentRoots[0] - - val settingsScript = VfsUtilCore.findRelativeFile("settings.gradle", root) - TestCase.assertNotNull(settingsScript) - val settingsScriptText = StringUtil.convertLineSeparators(VfsUtilCore.loadText(settingsScript!!)) - TestCase.assertTrue("rootProject.name = " in settingsScriptText) - if (metadataInside) { - TestCase.assertTrue("enableFeaturePreview('GRADLE_METADATA')" in settingsScriptText) - } - - val buildScript = VfsUtilCore.findRelativeFile("build.gradle", root)!! - val buildScriptText = StringUtil.convertLineSeparators(VfsUtilCore.loadText(buildScript)) - println(buildScriptText) - - doImportProject(project) - if (testClassNames.isNotEmpty()) { - doTestProject(project, *testClassNames) - } - } - - @Throws(IOException::class) - private fun Project.createProjectSubFile(relativePath: String): VirtualFile { - val f = File(basePath!!, relativePath) - FileUtil.ensureExists(f.parentFile) - FileUtil.ensureCanCreateFile(f) - val created = f.createNewFile() - if (!created) { - throw AssertionError("Unable to create the project sub file: " + f.absolutePath) - } - return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f)!! - } - - private fun runWrite(f: () -> Unit) { - object : WriteAction() { - override fun run(result: Result) { - f() - } - }.execute() - } - - private fun doImportProject(project: Project) { - ExternalSystemApiUtil.subscribe( - project, - GradleConstants.SYSTEM_ID, - object : ExternalSystemSettingsListenerAdapter() { - override fun onProjectsLinked(settings: Collection) { - val item = ContainerUtil.getFirstItem(settings) - if (item is GradleProjectSettings) { - item.gradleJvm = DEFAULT_SDK - } - } - }) - - GradleSettings.getInstance(project).gradleVmOptions = "-Xmx128m -XX:MaxPermSize=64m" - val wrapperJarFrom = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(GradleImportingTestCase.wrapperJar())!! - val wrapperJarFromTo = project.createProjectSubFile("gradle/wrapper/gradle-wrapper.jar") - runWrite { - wrapperJarFromTo.setBinaryContent(wrapperJarFrom.contentsToByteArray()) - } - - project.reconfigureGradleSettings { - distributionType = DistributionType.DEFAULT_WRAPPED - externalProjectPath = project.basePath!! - gradleJvm = DEFAULT_SDK - } - - val error = Ref.create>() - ExternalSystemUtil.refreshProjects( - ImportSpecBuilder(project, externalSystemId) - .use(ProgressExecutionMode.MODAL_SYNC) - .callback(object : ExternalProjectRefreshCallback { - override fun onSuccess(externalProject: DataNode?) { - if (externalProject == null) { - val errorMessage = "Got null External project after import" - System.err.println(errorMessage) - error.set(Couple.of(errorMessage, null)) - return - } - ServiceManager.getService(ProjectDataManager::class.java).importData(externalProject, project, true) - println("External project was successfully imported") - } - - override fun onFailure(errorMessage: String, errorDetails: String?) { - error.set(Couple.of(errorMessage, errorDetails)) - } - }) - .forceWhenUptodate() - ) - - if (!error.isNull) { - var failureMsg = "Import failed: " + error.get().first - if (StringUtil.isNotEmpty(error.get().second)) { - failureMsg += "\nError details: \n" + error.get().second - } - TestCase.fail(failureMsg) - } - } - - private fun doTestProject(project: Project, vararg testClassNames: String) { - val settings = GradleExecutionSettings(null, null, DistributionType.DEFAULT_WRAPPED, false) - println("Running project tests: ${testClassNames.toList()}") - GradleExecutionHelper().execute(project.basePath!!, settings) { - val testLauncher = it.newTestLauncher() - testLauncher.withJvmTestClasses(*testClassNames).run() - } - println("Waiting for daemon death...") - Thread.sleep(30000L) - println("Trying to clean everything...") - } - - // TODO: add testMobile when we will be able to locate Android SDK automatically - @Test fun testMobileShared() { testImportFromBuilder( @@ -252,20 +45,4 @@ class GradleMultiplatformWizardTest : ProjectWizardTestCase