[sdk] added tests for SdkComboBox.kt and for ES combobox util

GitOrigin-RevId: 7f53b2b1a4ea117dae49853c4d9484f196b6a67a
This commit is contained in:
Sergei Vorobyov
2020-01-16 08:11:51 +00:00
committed by intellij-monorepo-bot
parent 21e2acbaff
commit f9d6ab9cd7
11 changed files with 627 additions and 19 deletions
@@ -22,5 +22,6 @@
<orderEntry type="library" scope="TEST" name="JUnit4" level="project" />
<orderEntry type="library" scope="TEST" name="assertJ" level="project" />
<orderEntry type="library" scope="TEST" name="mockito" level="project" />
<orderEntry type="module" module-name="intellij.platform.lang.tests" scope="TEST" />
</component>
</module>
@@ -7,6 +7,7 @@ import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.*;
import com.intellij.openapi.projectRoots.impl.DependentSdkType;
import com.intellij.openapi.projectRoots.impl.MockSdk;
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.roots.ProjectRootManager;
@@ -5,36 +5,38 @@ package com.intellij.openapi.externalSystem.service.ui
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkException
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil.USE_PROJECT_JDK
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.projectRoots.impl.SdkConfigurationUtil
import com.intellij.openapi.roots.ui.configuration.SdkComboBox
import com.intellij.openapi.roots.ui.configuration.SdkListItem
import org.jetbrains.annotations.TestOnly
fun SdkComboBox.getSelectedJdkReference(): String? {
return when (val it = selectedItem) {
is SdkListItem.ProjectSdkItem -> ExternalSystemJdkUtil.USE_PROJECT_JDK
is SdkListItem.SdkItem -> it.sdk.name
is SdkListItem.InvalidSdkItem -> it.sdkName
fun SdkComboBox.getSelectedJdkReference() = resolveJdkReference(selectedItem)
private fun resolveJdkReference(item: SdkListItem?): String? {
return when (item) {
is SdkListItem.ProjectSdkItem -> USE_PROJECT_JDK
is SdkListItem.SdkItem -> item.sdk.name
is SdkListItem.InvalidSdkItem -> item.sdkName
else -> null
}
}
fun SdkComboBox.setSelectedJdkReference(jdkReference: String?) {
selectedItem = when (jdkReference) {
null -> showNoneSdkItem()
ExternalSystemJdkUtil.USE_PROJECT_JDK -> showProjectSdkItem()
else -> resolveSdkItem(jdkReference)
}
selectedItem = resolveSdkItem(jdkReference)
}
private fun SdkComboBox.resolveSdkItem(selectedJdkReference: String): SdkListItem {
private fun SdkComboBox.resolveSdkItem(jdkReference: String?): SdkListItem {
if (jdkReference == null) return showNoneSdkItem()
if (jdkReference == USE_PROJECT_JDK) return showProjectSdkItem()
try {
val selectedJdk = ExternalSystemJdkUtil.resolveJdkName(null, selectedJdkReference)
if (selectedJdk == null) return showInvalidSdkItem(selectedJdkReference)
val selectedJdk = ExternalSystemJdkUtil.resolveJdkName(null, jdkReference)
if (selectedJdk == null) return showInvalidSdkItem(jdkReference)
return findSdkItem(selectedJdk) ?: addAndGetSdkItem(selectedJdk)
}
catch (ex: ExternalSystemJdkException) {
return showInvalidSdkItem(selectedJdkReference)
return showInvalidSdkItem(jdkReference)
}
}
@@ -47,4 +49,7 @@ private fun SdkComboBox.addAndGetSdkItem(sdk: Sdk): SdkListItem {
private fun SdkComboBox.findSdkItem(sdk: Sdk): SdkListItem? {
return model.listModel.findSdkItem(sdk)
}
}
@TestOnly
fun resolveJdkReferenceInTests(item: SdkListItem?) = resolveJdkReference(item)
@@ -0,0 +1,50 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.externalSystem.service.ui
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil.USE_INTERNAL_JAVA
import com.intellij.openapi.externalSystem.service.execution.ExternalSystemJdkUtil.USE_PROJECT_JDK
import com.intellij.openapi.roots.ui.configuration.SdkListItem.*
class ExternalSystemJdkComboBoxUtilTest : ExternalSystemJdkComboBoxUtilTestCase() {
fun `test reference usage`() {
val sdk1 = createAndRegisterSdk()
val sdk2 = createAndRegisterSdk(isProjectSdk = true)
val sdk3 = createAndRegisterSdk()
val invalidSdk = TestSdkGenerator.createNextSdk()
val internalJdk = getInternalJdk()
val comboBox = createJdkComboBox()
assertComboBoxContent(comboBox)
.reference(USE_PROJECT_JDK)
.reference(sdk1)
.reference(sdk2)
.reference(sdk3)
.nothing()
comboBox.setSelectedJdkReference(USE_PROJECT_JDK)
assertComboBoxSelection<ProjectSdkItem>(comboBox, sdk2, USE_PROJECT_JDK)
comboBox.setSelectedJdkReference(sdk1.name)
assertComboBoxSelection<SdkItem>(comboBox, sdk1, sdk1.name)
comboBox.setSelectedJdkReference(sdk2.name)
assertComboBoxSelection<SdkItem>(comboBox, sdk2, sdk2.name)
comboBox.setSelectedJdkReference(sdk3.name)
assertComboBoxSelection<SdkItem>(comboBox, sdk3, sdk3.name)
comboBox.setSelectedJdkReference(invalidSdk.name)
assertComboBoxSelection<InvalidSdkItem>(comboBox, null, invalidSdk.name)
comboBox.setSelectedJdkReference(USE_INTERNAL_JAVA)
assertComboBoxSelection<SdkItem>(comboBox, internalJdk, internalJdk.name)
comboBox.setSelectedJdkReference(null)
assertComboBoxSelection<NoneSdkItem>(comboBox, null, null)
assertComboBoxContent(comboBox)
.reference(null, isSelected = true)
.reference(USE_PROJECT_JDK)
.reference(invalidSdk.name)
.reference(internalJdk)
.reference(sdk1)
.reference(sdk2)
.reference(sdk3)
.nothing()
}
}
@@ -0,0 +1,40 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.externalSystem.service.ui
import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.projectRoots.JavaSdkType
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl
import com.intellij.openapi.roots.ui.configuration.SdkComboBox
import com.intellij.openapi.roots.ui.configuration.SdkComboBoxTestCase
import com.intellij.openapi.roots.ui.configuration.SdkListItem
abstract class ExternalSystemJdkComboBoxUtilTestCase : SdkComboBoxTestCase() {
override fun tearDown() {
invokeAndWaitIfNeeded {
runWriteAction {
JavaAwareProjectJdkTableImpl.removeInternalJdkInTests()
}
}
super.tearDown()
}
fun createJdkComboBox() = createComboBox { it is JavaSdkType }
fun ComboBoxChecker.reference(sdk: Sdk, isSelected: Boolean = false) =
reference(sdk.name, isSelected)
fun ComboBoxChecker.reference(reference: String?, isSelected: Boolean = false) =
item<SdkListItem>(isSelected) {
assertEquals(reference, resolveJdkReferenceInTests(it))
}
fun getInternalJdk() = JavaAwareProjectJdkTableImpl.getInstanceEx().internalJdk
inline fun <reified I : SdkListItem> assertComboBoxSelection(comboBox: SdkComboBox, expectedSdk: Sdk?, expectedReference: String?) {
assertComboBoxSelection<I>(comboBox, expectedSdk)
assertEquals(expectedReference, comboBox.getSelectedJdkReference())
}
}
@@ -15,12 +15,21 @@ class SdkComboBox(model: SdkComboBoxModel) : SdkComboBoxBase<SdkListItem>(model.
setModel(model.copyAndSetListModel(listModel))
}
override fun getSelectedItem(): SdkListItem? {
return super.getSelectedItem() as SdkListItem?
}
override fun setSelectedItem(anObject: Any?) {
if (anObject is SdkListItem) {
if (myModel.executeAction(this, anObject, ::setSelectedItem)) {
return
}
}
when (anObject) {
is SdkListItem.ProjectSdkItem -> showProjectSdkItem()
is SdkListItem.InvalidSdkItem -> showInvalidSdkItem(anObject.sdkName)
is SdkListItem.NoneSdkItem -> showNoneSdkItem()
}
reloadModel()
super.setSelectedItem(anObject)
}
@@ -37,12 +46,14 @@ class SdkComboBox(model: SdkComboBoxModel) : SdkComboBoxBase<SdkListItem>(model.
fun getSelectedSdk(): Sdk? {
return when (val it = selectedItem) {
is SdkListItem.ProjectSdkItem -> model.sdksModel.projectSdk
is SdkListItem.SdkItem -> it.sdk
is SdkListItem.ProjectSdkItem -> findSdk(model.sdksModel.projectSdk)
is SdkListItem.SdkItem -> findSdk(it.sdk)
else -> null
}
}
private fun findSdk(sdk: Sdk?) = model.sdksModel.findSdk(sdk)
init {
setModel(model)
setRenderer(SdkListPresenter { this@SdkComboBox.model.listModel })
@@ -2,6 +2,7 @@
package com.intellij.openapi.roots.ui.configuration;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ModalityState;
import com.intellij.openapi.diagnostic.Logger;
@@ -58,6 +59,17 @@ public class SdkDetector {
return;
}
/*
TODO[jo] fix: deadlock in combobox tests on {@link SdkDetector#myPublicationLock}
detection must be called from edt {@link SdkDetector#getDetectedSdksWithUpdate}
detection is synchronous for unit tests {@link com.intellij.openapi.progress.impl.CoreProgressManager#run}
*/
Application application = ApplicationManager.getApplication();
if (application.isUnitTestMode() || application.isHeadlessEnvironment()) {
LOG.warn("Sdks detection is skipped, because deadlock is coming for synchronous detection");
return;
}
EdtDetectedSdkListener actualListener = new EdtDetectedSdkListener(callbackModality, listener);
synchronized (myPublicationLock) {
//skip multiple registrations
@@ -121,14 +121,14 @@ public abstract class SdkListItem {
}
}
enum ActionRole {
public enum ActionRole {
DOWNLOAD, ADD
}
public static final class ActionItem extends SdkListItem {
@Nullable final GroupItem myGroup;
@NotNull final ActionRole myRole;
@NotNull final NewSdkAction myAction;
@NotNull final NewSdkAction myAction;
ActionItem(@NotNull ActionRole role, @NotNull NewSdkAction action, @Nullable GroupItem group) {
myRole = role;
@@ -136,6 +136,16 @@ public abstract class SdkListItem {
myGroup = group;
}
@NotNull
public ActionRole getRole() {
return myRole;
}
@NotNull
public NewSdkAction getAction() {
return myAction;
}
@NotNull
ActionItem withGroup(@NotNull GroupItem group) {
return new ActionItem(myRole, myAction, group);
@@ -0,0 +1,116 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.roots.ui.configuration
import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.openapi.projectRoots.Sdk
class SdkComboBoxTest : SdkComboBoxTestCase() {
fun `test simple usage`() {
val sdk1 = createAndRegisterSdk()
val sdk2 = createAndRegisterSdk(isProjectSdk = true)
val sdk3 = createAndRegisterSdk()
val sdk4 = TestSdkGenerator.createNextSdk()
val comboBox = createComboBox()
assertComboBoxContent(comboBox)
.item<SdkListItem.ProjectSdkItem> { assertEquals(sdk2, comboBox.getProjectSdk()) }
.item<SdkListItem.SdkItem> { assertSdkItem(sdk1, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(sdk2, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(sdk3, it) }
.nothing()
assertComboBoxSelection<SdkListItem.NoneSdkItem>(comboBox, null)
comboBox.setSelectedSdk(sdk1)
assertComboBoxSelection<SdkListItem.SdkItem>(comboBox, sdk1)
comboBox.setSelectedSdk(sdk2)
assertComboBoxSelection<SdkListItem.SdkItem>(comboBox, sdk2)
comboBox.setSelectedSdk(sdk3)
assertComboBoxSelection<SdkListItem.SdkItem>(comboBox, sdk3)
comboBox.setSelectedSdk(sdk4)
assertComboBoxSelection<SdkListItem.InvalidSdkItem>(comboBox, null)
comboBox.setSelectedSdk(null)
assertComboBoxSelection<SdkListItem.NoneSdkItem>(comboBox, null)
assertComboBoxContent(comboBox)
.item<SdkListItem.NoneSdkItem>(isSelected = true)
.item<SdkListItem.ProjectSdkItem> { assertEquals(sdk2, comboBox.getProjectSdk()) }
.item<SdkListItem.InvalidSdkItem> { assertEquals(sdk4.name, it.sdkName) }
.item<SdkListItem.SdkItem> { assertSdkItem(sdk1, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(sdk2, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(sdk3, it) }
.nothing()
comboBox.setSelectedItem(SdkListItem.ProjectSdkItem())
assertComboBoxSelection<SdkListItem.ProjectSdkItem>(comboBox, sdk2)
comboBox.setSelectedItem(SdkListItem.NoneSdkItem())
assertComboBoxSelection<SdkListItem.NoneSdkItem>(comboBox, null)
comboBox.setSelectedItem(SdkListItem.InvalidSdkItem("invalid sdk"))
assertComboBoxSelection<SdkListItem.InvalidSdkItem>(comboBox, null)
assertComboBoxContent(comboBox)
.item<SdkListItem.NoneSdkItem>()
.item<SdkListItem.ProjectSdkItem> { assertEquals(sdk2, comboBox.getProjectSdk()) }
.item<SdkListItem.InvalidSdkItem>(isSelected = true) { assertEquals("invalid sdk", it.sdkName) }
.item<SdkListItem.SdkItem> { assertSdkItem(sdk1, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(sdk2, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(sdk3, it) }
.nothing()
}
fun `test combobox actions`() {
val comboBox = createComboBox()
.withOpenDropdownPopup()
assertComboBoxContent(comboBox)
.item<SdkListItem.ActionItem> { assertActionItem(SdkListItem.ActionRole.DOWNLOAD, it) }
.item<SdkListItem.ActionItem> { assertActionItem(SdkListItem.ActionRole.ADD, it) }
.nothing()
val download1 = comboBox.touchDownloadAction()
val download2 = comboBox.touchDownloadAction()
val download3 = comboBox.touchDownloadAction()
val download4 = comboBox.touchDownloadAction()
assertComboBoxContent(comboBox)
.item<SdkListItem.SdkItem> { assertSdkItem(download1, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(download2, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(download3, it) }
.item<SdkListItem.SdkItem>(isSelected = true) { assertSdkItem(download4, it) }
.item<SdkListItem.ActionItem> { assertActionItem(SdkListItem.ActionRole.DOWNLOAD, it) }
.item<SdkListItem.ActionItem> { assertActionItem(SdkListItem.ActionRole.ADD, it) }
.nothing()
val add1 = comboBox.touchAddAction()
val add2 = comboBox.touchAddAction()
val add3 = comboBox.touchAddAction()
val add4 = comboBox.touchAddAction()
assertComboBoxContent(comboBox)
.item<SdkListItem.SdkItem> { assertSdkItem(download1, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(download2, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(download3, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(download4, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(add1, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(add2, it) }
.item<SdkListItem.SdkItem> { assertSdkItem(add3, it) }
.item<SdkListItem.SdkItem>(isSelected = true) { assertSdkItem(add4, it) }
.item<SdkListItem.ActionItem> { assertActionItem(SdkListItem.ActionRole.DOWNLOAD, it) }
.item<SdkListItem.ActionItem> { assertActionItem(SdkListItem.ActionRole.ADD, it) }
.nothing()
assertCollectionContent(comboBox.model.sdksModel.projectSdks.values.sortedBy { it.name })
.element<Sdk> { assertSdk(download1, it) }
.element<Sdk> { assertSdk(download2, it) }
.element<Sdk> { assertSdk(download3, it) }
.element<Sdk> { assertSdk(download4, it) }
.element<Sdk> { assertSdk(add1, it) }
.element<Sdk> { assertSdk(add2, it) }
.element<Sdk> { assertSdk(add3, it) }
.element<Sdk> { assertSdk(add4, it) }
.nothing()
assertCollectionContent(ProjectJdkTable.getInstance().getSdksOfType(TestSdkType))
.nothing()
}
}
@@ -0,0 +1,208 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.roots.ui.configuration
import com.intellij.openapi.Disposable
import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.ProjectJdkTable
import com.intellij.openapi.projectRoots.Sdk
import com.intellij.openapi.projectRoots.SdkType
import com.intellij.openapi.projectRoots.SdkTypeId
import com.intellij.openapi.roots.ui.configuration.SdkComboBoxModel.Companion.createSdkComboBoxModel
import com.intellij.openapi.roots.ui.configuration.projectRoot.ProjectSdksModel
import com.intellij.openapi.util.Disposer
import java.util.function.Predicate
abstract class SdkComboBoxTestCase : SdkTestCase() {
fun createComboBox(filter: (SdkTypeId) -> Boolean = { true }): SdkComboBox {
val sdksModel = TestProjectSdksModel()
sdksModel.reset(project)
Disposer.register(project, sdksModel)
val model = createSdkComboBoxModel(project, sdksModel, Predicate { TestSdkType == it || filter(it) })
return SdkComboBox(model)
}
class ComboBoxChecker(val comboBox: SdkComboBox) :
CollectionChecker<SdkListItem>(comboBox.itemSequence.iterator(), comboBox.dumpToString()) {
inline fun <reified I : SdkListItem> item(
isSelected: Boolean = false,
noinline assertItem: SdkComboBox.(I) -> Unit = {}
): ComboBoxChecker {
element<I> {
assertSelection(comboBox, it, isSelected)
comboBox.assertItem(it)
}
return this
}
fun assertSelection(comboBox: SdkComboBox, elementToCheck: SdkListItem, mustBeSelected: Boolean) {
if (mustBeSelected) {
val message = "'${comboBox.dumpToString(elementToCheck)}' must be selected"
assertTrue(message, comboBox.selectedItem == elementToCheck)
}
else {
val message = "'${comboBox.dumpToString(elementToCheck)}' must not be selected"
assertFalse(message, comboBox.selectedItem == elementToCheck)
}
}
}
open class CollectionChecker<T : Any>(val iterator: Iterator<T?>, val dump: String) {
inline fun <reified I : T> element(noinline assertItem: (I) -> Unit = {}): CollectionChecker<T> {
assertTrue(dump, iterator.hasNext())
val element = iterator.next()
val item = assertIsInstance<I>(dump, element)
withMessageIfException { assertItem(item) }
return this
}
fun nothing() {
assertFalse(dump, iterator.hasNext())
}
fun <R> withMessageIfException(action: () -> R): R {
try {
return action()
}
catch (ex: Throwable) {
System.err.println("${ex::class.java.name}: $dump")
throw ex
}
}
}
/**
* Works in team with:
* [SdkConfigurationUtil.selectSdkHome(SdkType, Component, Consumer<in String>)],
* [SdkComboBoxTestCase.TestProjectSdksModel]
*/
object CanarySdk : TestSdk("canary", "canary-home", "canary-version") {
fun <R> replaceByTestSdk(action: () -> R): R {
return invokeAndWaitIfNeeded {
runWriteAction {
val projectSdkTable = ProjectJdkTable.getInstance()
projectSdkTable.addJdk(CanarySdk)
try {
action()
}
finally {
projectSdkTable.removeJdk(CanarySdk)
}
}
}
}
}
class TestProjectSdksModel : ProjectSdksModel(), Disposable {
override fun addSdk(type: SdkType, home: String, callback: com.intellij.util.Consumer<in Sdk>?) {
if (home == CanarySdk.homePath) {
val sdk = TestSdkGenerator.createNextSdk()
setupSdk(sdk, callback)
}
else {
super.addSdk(type, home, callback)
}
}
private fun setupSdk(newJdk: TestSdk, callback: com.intellij.util.Consumer<in Sdk>?) {
val sdkType = newJdk.sdkType as SdkType
if (!sdkType.setupSdkPaths(newJdk, this)) return
doAdd(newJdk, callback)
}
override fun reset(project: Project?) {
disposeEditableSdks()
super.reset(project)
}
override fun dispose() = disposeEditableSdks()
private fun disposeEditableSdks() {
for (editable in projectSdks.values) {
if (editable is Disposable) {
Disposer.dispose(editable)
}
}
}
}
companion object {
fun assertSdkItem(expected: Sdk, item: SdkListItem.SdkItem) {
assertSdk(expected, item.sdk)
}
fun assertActionItem(role: SdkListItem.ActionRole, item: SdkListItem.ActionItem) {
assertEquals(role, item.role)
assertEquals(TestSdkType, item.action.sdkType)
}
inline fun <reified I : SdkListItem> assertComboBoxSelection(comboBox: SdkComboBox, expectedSdk: Sdk?) {
assertEquals(comboBox.dumpToString(), expectedSdk, comboBox.getSelectedSdk())
assertIsInstance<I>(comboBox.dumpToString(), comboBox.getSelectedItem())
}
fun assertComboBoxContent(comboBox: SdkComboBox) = ComboBoxChecker(comboBox)
fun assertCollectionContent(collection: Collection<*>) = CollectionChecker(collection.iterator(), collection.toString())
inline fun <reified T> assertIsInstance(message: String, o: Any?): T {
requireNotNull(o) { message }
assertTrue("Expected instance of: ${T::class.java.name} actual: ${o::class.java.name}, $message", o is T)
return o as T
}
fun SdkComboBox.getProjectSdk() = model.sdksModel.projectSdk?.let { TestSdkGenerator.findTestSdk(it) }
val SdkComboBox.itemSequence
get() = sequence {
val model = getModel()
for (i in 0 until model.getSize()) {
yield(model.getElementAt(i))
}
}
fun SdkComboBox.touchDownloadAction(): TestSdk {
selectedItem = itemSequence
.filterIsInstance<SdkListItem.ActionItem>()
.first { it.role == SdkListItem.ActionRole.DOWNLOAD }
return TestSdkGenerator.getCurrentSdk()
}
fun SdkComboBox.touchAddAction(): TestSdk {
CanarySdk.replaceByTestSdk {
selectedItem = itemSequence
.filterIsInstance<SdkListItem.ActionItem>()
.first { it.role == SdkListItem.ActionRole.ADD }
}
return TestSdkGenerator.getCurrentSdk()
}
fun SdkComboBox.withOpenDropdownPopup(): SdkComboBox {
firePopupMenuWillBecomeVisible()
return this
}
fun SdkComboBox.dumpToString(): String {
val elements = itemSequence.joinToString { (if (selectedItem == it) "* " else "") + dumpToString(it) }
return "ComboBox { $elements }"
}
fun SdkComboBox.dumpToString(element: SdkListItem?): String {
return when (element) {
is SdkListItem.NoneSdkItem -> "[none]"
is SdkListItem.ProjectSdkItem -> "[project] ${getProjectSdk()?.name}"
is SdkListItem.InvalidSdkItem -> "[invalid] ${element.sdkName}"
is SdkListItem.SdkItem -> "[sdk] ${element.sdk.name}"
is SdkListItem.SuggestedItem -> "[suggested] ${element.homePath}"
is SdkListItem.ActionItem -> "[action] ${element.myRole} ${element.myAction.sdkType.name}"
is SdkListItem.GroupItem -> "[group] {${element.mySubItems.joinToString { dumpToString(it) }}}"
null -> "null"
else -> element::class.java.name
}
}
}
}
@@ -0,0 +1,154 @@
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.openapi.roots.ui.configuration
import com.intellij.openapi.application.invokeAndWaitIfNeeded
import com.intellij.openapi.application.runWriteAction
import com.intellij.openapi.progress.ProgressIndicator
import com.intellij.openapi.projectRoots.*
import com.intellij.openapi.projectRoots.impl.MockSdk
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.roots.ui.configuration.projectRoot.SdkDownload
import com.intellij.openapi.roots.ui.configuration.projectRoot.SdkDownloadTask
import com.intellij.openapi.util.Disposer
import com.intellij.openapi.util.io.FileUtil
import com.intellij.testFramework.LightPlatformTestCase
import com.intellij.util.containers.MultiMap
import org.jdom.Element
import java.io.File
import java.util.*
import java.util.function.Consumer
import javax.swing.JComponent
import kotlin.collections.LinkedHashMap
abstract class SdkTestCase : LightPlatformTestCase() {
override fun setUp() {
super.setUp()
TestSdkGenerator.reset()
SdkType.EP_NAME.getPoint(null)
.registerExtension(TestSdkType, project)
SdkDownload.EP_NAME.getPoint(null)
.registerExtension(TestSdkDownloader, project)
}
override fun tearDown() {
Disposer.disposeChildren(project)
closeAndDeleteProject()
super.tearDown()
}
fun createAndRegisterSdk(isProjectSdk: Boolean = false): Sdk {
val sdk = TestSdkGenerator.createNextSdk()
registerSdk(sdk)
if (isProjectSdk) {
setProjectSdk(sdk)
}
return sdk
}
private fun registerSdk(sdk: Sdk) {
invokeAndWaitIfNeeded {
runWriteAction {
val jdkTable = ProjectJdkTable.getInstance()
jdkTable.addJdk(sdk, project)
}
}
}
private fun setProjectSdk(sdk: Sdk) {
invokeAndWaitIfNeeded {
runWriteAction {
val rootManager = ProjectRootManager.getInstance(project)
rootManager.projectSdk = sdk
}
}
}
object TestSdkType : SdkType("test-type"), JavaSdkType {
override fun getPresentableName(): String = name
override fun isValidSdkHome(path: String?): Boolean = true
override fun suggestSdkName(currentSdkName: String?, sdkHome: String?): String = "sdk-name"
override fun suggestHomePath(): String? = null
override fun createAdditionalDataConfigurable(sdkModel: SdkModel, sdkModificator: SdkModificator): AdditionalDataConfigurable? = null
override fun saveAdditionalData(additionalData: SdkAdditionalData, additional: Element) {}
override fun getBinPath(sdk: Sdk): String = File(sdk.homePath, "bin").path
override fun getToolsPath(sdk: Sdk): String = File(sdk.homePath, "lib/tools.jar").path
override fun getVMExecutablePath(sdk: Sdk): String = File(sdk.homePath, "bin/java").path
}
open class TestSdk(name: String, homePath: String, versionString: String)
: MockSdk(name, homePath, versionString, MultiMap(), TestSdkType) {
override fun getHomePath(): String = super.getHomePath()!!
}
object TestSdkDownloader : SdkDownload {
override fun supportsDownload(sdkTypeId: SdkTypeId) = sdkTypeId == TestSdkType
override fun showDownloadUI(
sdkTypeId: SdkTypeId,
sdkModel: SdkModel,
parentComponent: JComponent,
selectedSdk: Sdk?,
sdkCreatedCallback: Consumer<SdkDownloadTask>
) {
val sdk = TestSdkGenerator.createNextSdk()
sdkCreatedCallback.accept(object : SdkDownloadTask {
override fun doDownload(indicator: ProgressIndicator) {}
override fun getPlannedVersion() = sdk.versionString
override fun getSuggestedSdkName() = sdk.name
override fun getPlannedHomeDir() = sdk.homePath
})
}
}
object TestSdkGenerator {
private var createdSdkCounter = 0
private lateinit var createdSdks: MutableMap<String, TestSdk>
fun findTestSdk(sdk: Sdk): TestSdk? = createdSdks[sdk.name]
fun getCurrentSdk() = createdSdks.values.last()
fun createNextSdk(): TestSdk {
val name = "test-name (${createdSdkCounter++})"
val versionString = "11"
val homePath = FileUtil.getTempDirectory() + "/jdk-$name"
generateJdkStructure(homePath, versionString)
createdSdks[name] = TestSdk(name, homePath, versionString)
return getCurrentSdk()
}
private fun generateJdkStructure(homePath: String, versionString: String) {
createFile("$homePath/release")
createFile("$homePath/jre/lib/rt.jar")
createFile("$homePath/bin/javac")
createFile("$homePath/bin/java")
val properties = Properties()
properties.setProperty("JAVA_FULL_VERSION", versionString)
File("$homePath/release").outputStream().use {
properties.store(it, null)
}
}
private fun createFile(path: String) {
val file = File(path)
file.parentFile.mkdirs()
file.createNewFile()
}
fun reset() {
createdSdkCounter = 0
createdSdks = LinkedHashMap()
}
}
companion object {
fun assertSdk(expected: Sdk, actual: Sdk) {
assertEquals(expected.name, actual.name)
assertEquals(expected.sdkType, actual.sdkType)
assertEquals(expected, TestSdkGenerator.findTestSdk(actual))
}
}
}