[eel] PY-85575, IJPL-172898: add EelTargetEnvironmentTest

GitOrigin-RevId: adbfbfc527baa9ada97d8acf11c01be43df44db9
This commit is contained in:
Andrii Zinchenko
2025-11-13 17:00:42 +00:00
committed by intellij-monorepo-bot
parent e021713fef
commit 00785c162c
8 changed files with 67 additions and 24 deletions
@@ -3,6 +3,7 @@ package com.intellij.execution.target
import com.intellij.execution.ExecutionException
import com.intellij.execution.Platform
import com.intellij.openapi.components.BaseState
import com.intellij.openapi.components.PersistentStateComponent
import com.intellij.openapi.components.Service
import com.intellij.openapi.components.service
@@ -20,6 +21,8 @@ import com.intellij.platform.eel.fs.getPath
import com.intellij.platform.eel.path.EelPath
import com.intellij.platform.eel.provider.asEelPath
import com.intellij.platform.eel.provider.asNioPath
import com.intellij.platform.eel.provider.getEelDescriptor
import com.intellij.platform.eel.provider.toEelApiBlocking
import com.intellij.platform.eel.provider.utils.*
import com.intellij.platform.util.coroutines.childScope
import com.intellij.ui.icons.EMPTY_ICON
@@ -36,11 +39,12 @@ import java.nio.file.Path
import java.util.*
import java.util.concurrent.ConcurrentHashMap
import javax.swing.Icon
import kotlin.io.path.Path
import kotlin.io.path.isSameFileAs
private fun EelPlatform.toTargetPlatform(): TargetPlatform = when (this) {
is EelPlatform.Posix -> TargetPlatform(Platform.UNIX)
is EelPlatform.Windows -> TargetPlatform(Platform.WINDOWS)
private fun EelOsFamily.toTargetPlatform(): TargetPlatform = when (this) {
EelOsFamily.Posix -> TargetPlatform(Platform.UNIX)
EelOsFamily.Windows -> TargetPlatform(Platform.WINDOWS)
}
private fun LocalHostPort(port: Int) = HostPort("localhost", port)
@@ -75,30 +79,68 @@ class EelTargetType : TargetEnvironmentType<EelTargetEnvironmentRequest.Configur
}
override fun createSerializer(config: EelTargetEnvironmentRequest.Configuration): PersistentStateComponent<*> {
throw UnsupportedOperationException()
return config
}
override fun createDefaultConfig(): EelTargetEnvironmentRequest.Configuration {
throw UnsupportedOperationException()
return EelTargetEnvironmentRequest.Configuration()
}
override fun duplicateConfig(config: EelTargetEnvironmentRequest.Configuration): EelTargetEnvironmentRequest.Configuration {
return EelTargetEnvironmentRequest.Configuration(config.eel)
return EelTargetEnvironmentRequest.Configuration.create(config.descriptor).also {
it.projectRootOnTarget = config.projectRootOnTarget
}
}
}
@ApiStatus.Internal
class EelTargetEnvironmentRequest(override val configuration: Configuration) : BaseTargetEnvironmentRequest(), VolumeCopyingRequest {
class Configuration(val eel: EelApi) : TargetEnvironmentConfiguration(TARGET_TYPE_NAME), TargetConfigurationWithLocalFsAccess {
class EelTargetEnvironmentRequest(
override val configuration: Configuration,
) : BaseTargetEnvironmentRequest(), VolumeCopyingRequest {
class Configuration private constructor(
eelDescriptor: EelDescriptor?,
) : TargetEnvironmentConfiguration(TARGET_TYPE_NAME), TargetConfigurationWithLocalFsAccess, PersistentStateComponent<Configuration.PersistentState> {
internal constructor() : this(null)
constructor(eelApi: EelApi) : this(eelApi.descriptor)
private var myDescriptor = eelDescriptor
val descriptor: EelDescriptor get() = myDescriptor ?: error("EEL descriptor is not set")
companion object {
@JvmStatic
fun create(eelDescriptor: EelDescriptor): Configuration = Configuration(
eelDescriptor = eelDescriptor
)
}
override var projectRootOnTarget: String = ""
override val asTargetConfig: TargetEnvironmentConfiguration = this
override fun getTargetPathIfLocalPathIsOnTarget(probablyPathOnTarget: Path): FullPathOnTarget? {
return probablyPathOnTarget.asEelPath().takeIf { it.descriptor == eel.descriptor }?.toString()
return probablyPathOnTarget.asEelPath().takeIf { it.descriptor == descriptor }?.toString()
}
override fun getState(): PersistentState {
return PersistentState().also {
it.projectRootOnTarget = projectRootOnTarget
it.eelRootPath = (descriptor as? EelPathBoundDescriptor)?.rootPath.toString()
}
}
override fun loadState(state: PersistentState) {
projectRootOnTarget = state.projectRootOnTarget ?: ""
myDescriptor = state.eelRootPath?.let(::Path)?.getEelDescriptor() ?: descriptor
}
class PersistentState : BaseState() {
var projectRootOnTarget: String? by string()
var eelRootPath: String? by string()
}
}
override val targetPlatform: TargetPlatform = configuration.eel.platform.toTargetPlatform()
override val targetPlatform: TargetPlatform = configuration.descriptor.osFamily.toTargetPlatform()
override fun prepareEnvironment(progressIndicator: TargetProgressIndicator): TargetEnvironment {
val env = EelTargetEnvironment(this)
@@ -116,9 +158,9 @@ class EelTargetEnvironment(override val request: EelTargetEnvironmentRequest) :
private val myTargetPortBindings: MutableMap<TargetPortBinding, ResolvedPortBinding> = HashMap()
private val myLocalPortBindings: MutableMap<LocalPortBinding, ResolvedPortBinding> = ConcurrentHashMap()
private val eel = request.configuration.eel
private val eel = request.configuration.descriptor.toEelApiBlocking()
private val forwardingScope by lazy { service<EelTargetScope>().scope.childScope("Eel target forwarding scope: ${request.configuration.eel}") }
private val forwardingScope by lazy { service<EelTargetScope>().scope.childScope("Eel target forwarding scope: ${request.configuration.descriptor}") }
override val uploadVolumes: Map<UploadRoot, UploadableVolume>
get() = Collections.unmodifiableMap(myUploadVolumes)
@@ -29,6 +29,7 @@ jvm_library(
"//platform/util",
"//platform/util/coroutines",
"//platform/util-ex",
"//platform/projectModel-api:projectModel",
]
)
@@ -60,6 +61,7 @@ jvm_library(
"//platform/util/coroutines",
"//platform/util-ex",
"//platform/execution",
"//platform/projectModel-api:projectModel",
]
)
### auto-generated section `build intellij.platform.testFramework.junit5.eel` end
@@ -28,5 +28,6 @@
<orderEntry type="module" module-name="intellij.platform.util.coroutines" />
<orderEntry type="module" module-name="intellij.platform.util.ex" />
<orderEntry type="module" module-name="intellij.platform.execution" scope="TEST" />
<orderEntry type="module" module-name="intellij.platform.projectModel" />
</component>
</module>
@@ -19,4 +19,4 @@ const val DEFAULT_EEL_TEST_DOCKER_IMAGE: String = "debian"
@Target(AnnotationTarget.CLASS, AnnotationTarget.FUNCTION)
@TestApplicationWithEel
@Repeatable
annotation class DockerTest(val image: String = DEFAULT_EEL_TEST_DOCKER_IMAGE, val mandatory: Boolean = true)
annotation class DockerTest(val image: String = DEFAULT_EEL_TEST_DOCKER_IMAGE, val mandatory: Boolean = true, val setupCommands: Array<String> = [])
@@ -1,11 +1,12 @@
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.platform.testFramework.junit5.eel.params.api
import com.intellij.execution.target.EelTargetEnvironmentRequest
import com.intellij.execution.target.TargetEnvironmentConfiguration
import com.intellij.platform.eel.EelApi
import com.intellij.platform.eel.LocalEelApi
import org.jetbrains.annotations.ApiStatus
import org.jetbrains.annotations.TestOnly
import org.opentest4j.TestAbortedException
/**
* Accept as an argument of your test, be sure to use [EelSource]
@@ -35,7 +36,4 @@ sealed interface EelHolder {
* Consider using [EelHolder.eel] in a new code.
*/
val EelHolder.target: TargetEnvironmentConfiguration?
get() = when (val t = type) {
is Docker, is Wsl -> t.target
Local -> null
}
get() = if (eel is LocalEelApi) null else EelTargetEnvironmentRequest.Configuration(eel)
@@ -6,11 +6,9 @@ import org.jetbrains.annotations.ApiStatus
@ApiStatus.Internal
sealed interface EelType
sealed interface RemoteEelType {
val target: TargetEnvironmentConfiguration
}
sealed interface RemoteEelType
class Wsl(override val target: TargetEnvironmentConfiguration) : EelType, RemoteEelType
class Docker(override val target: TargetEnvironmentConfiguration) : EelType, RemoteEelType
class Wsl : EelType, RemoteEelType
class Docker : EelType, RemoteEelType
data object Local : EelType
@@ -28,7 +28,6 @@ class EelParametrizedClassShowCaseTest(val eelProvider: EelHolder) {
when (val type = eelProvider.type) {
is Docker -> {
println("I am on docker")
type.target
}
Local -> Unit //no target for local
is Wsl -> Unit
@@ -60,6 +60,9 @@ internal suspend fun createProcessLauncherOnTarget(binOnTarget: BinOnTarget, lau
fileLogger().warn("Failed to start $target", e) // TODO: i18n
return@withContext Result.failure(ExecuteGetProcessError.EnvironmentError(MessageError("Failed to start environment due to ${e.localizedMessage}")))
}
targetEnv.uploadVolumes.forEach { _, volume ->
volume.upload(".", TargetProgressIndicator.EMPTY)
}
val args = launchRequest.args.getArgs { localFile ->
targetEnv.getTargetPaths(localFile.pathString).first()
}