MPP wizard tests: extract test functions into separate class

This commit is contained in:
Mikhail Glukhikh
2018-10-17 10:54:03 +03:00
parent 35d4b7dfd9
commit 853d90d906
6 changed files with 305 additions and 232 deletions
@@ -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<AbstractProjectWizard>() {
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<Any>(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<Any>() {
override fun run(result: Result<Any>) {
f()
}
}.execute()
}
private fun doImportProject(project: Project) {
ExternalSystemApiUtil.subscribe(
project,
GradleConstants.SYSTEM_ID,
object : ExternalSystemSettingsListenerAdapter<ExternalProjectSettings>() {
override fun onProjectsLinked(settings: Collection<ExternalProjectSettings>) {
val item = ContainerUtil.getFirstItem<Any>(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<Couple<String>>()
ExternalSystemUtil.refreshProjects(
ImportSpecBuilder(project, externalSystemId)
.use(ProgressExecutionMode.MODAL_SYNC)
.callback(object : ExternalProjectRefreshCallback {
override fun onSuccess(externalProject: DataNode<ProjectData>?) {
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
}
}
@@ -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<AbstractProjectWizard>() {
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<Any>(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<Any>() {
override fun run(result: Result<Any>) {
f()
}
}.execute()
}
private fun doImportProject(project: Project) {
ExternalSystemApiUtil.subscribe(
project,
GradleConstants.SYSTEM_ID,
object : ExternalSystemSettingsListenerAdapter<ExternalProjectSettings>() {
override fun onProjectsLinked(settings: Collection<ExternalProjectSettings>) {
val item = ContainerUtil.getFirstItem<Any>(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<Couple<String>>()
ExternalSystemUtil.refreshProjects(
ImportSpecBuilder(project, externalSystemId)
.use(ProgressExecutionMode.MODAL_SYNC)
.callback(object : ExternalProjectRefreshCallback {
override fun onSuccess(externalProject: DataNode<ProjectData>?) {
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<AbstractProjectWizar
fun testWeb() {
testImportFromBuilder(KotlinGradleWebMultiplatformModuleBuilder(), "SampleTests", "SampleTestsJVM")
}
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
}
}
@@ -0,0 +1,9 @@
/*
* 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
class GradleMultiplatformWizardTest : AbstractGradleMultiplatformWizardTest() {
}
@@ -0,0 +1,26 @@
/*
* 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 org.jetbrains.kotlin.idea.configuration.KotlinGradleSharedMultiplatformModuleBuilder
import org.jetbrains.kotlin.idea.configuration.KotlinGradleWebMultiplatformModuleBuilder
import org.junit.Test
class GradleMultiplatformWizardTest : AbstractGradleMultiplatformWizardTest() {
@Test
fun testShared() {
// NB: I'm not quite sure this thing really works in 181 (Native is inside)
testImportFromBuilder(
KotlinGradleSharedMultiplatformModuleBuilder(),
"SampleTests", "SampleTestsJVM", "SampleTestsNative", metadataInside = true
)
}
@Test
fun testWeb() {
testImportFromBuilder(KotlinGradleWebMultiplatformModuleBuilder(), "SampleTests", "SampleTestsJVM")
}
}
@@ -0,0 +1,9 @@
/*
* 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
class GradleMultiplatformWizardTest : AbstractGradleMultiplatformWizardTest() {
}
@@ -0,0 +1,9 @@
/*
* 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
class GradleMultiplatformWizardTest : AbstractGradleMultiplatformWizardTest() {
}