diff --git a/.idea/libraries/jline_terminal_jansi.xml b/.idea/libraries/jline_terminal_jansi.xml new file mode 100644 index 000000000000..5f3969120bd4 --- /dev/null +++ b/.idea/libraries/jline_terminal_jansi.xml @@ -0,0 +1,38 @@ + + + + + + a7b369a2e697215fed314a58b736f10ae8bdedf218096916a6bdb7bc886fe470 + + + 2e5e775a9dc58ffa6bbd6aa6f099d62f8b62dcdeb4c3c3bbbe5cf2301bc2dcc1 + + + 2f461c75091ec3810a42184afc80c96910f54e9dd2110e9ecb9902a5ee6c244b + + + d8bc77bc80edc7d9a02a06a069b2d7085629421db0843aba7c153a869ffe525d + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/jline_terminal_jna.xml b/.idea/libraries/jline_terminal_jna.xml new file mode 100644 index 000000000000..bb7d5482ff67 --- /dev/null +++ b/.idea/libraries/jline_terminal_jna.xml @@ -0,0 +1,38 @@ + + + + + + e7322e6d8dc1bd69f507b91865af741af4a95c649ccab36e79e8be89696bb432 + + + a564158d28ab5127fc6a958028ed54279fe0999662c46425b6a3b09a2a52094d + + + 2f461c75091ec3810a42184afc80c96910f54e9dd2110e9ecb9902a5ee6c244b + + + d8bc77bc80edc7d9a02a06a069b2d7085629421db0843aba7c153a869ffe525d + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml index 865397a0b8c3..7c07a6171aff 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -647,6 +647,7 @@ + diff --git a/platform/build-scripts/src/org/jetbrains/intellij/build/CommunityLibraryLicenses.kt b/platform/build-scripts/src/org/jetbrains/intellij/build/CommunityLibraryLicenses.kt index 59822e421e7e..d5a871873a6a 100644 --- a/platform/build-scripts/src/org/jetbrains/intellij/build/CommunityLibraryLicenses.kt +++ b/platform/build-scripts/src/org/jetbrains/intellij/build/CommunityLibraryLicenses.kt @@ -639,6 +639,19 @@ object CommunityLibraryLicenses { .newBsd("https://opensource.org/license/bsd-3-clause/") .suppliedByOrganizations("Thai Open Source Software Center Ltd"), + LibraryLicense(null, libraryName = "jline.terminal", url = "https://github.com/jline/jline3") + .newBsd("https://github.com/jline/jline3/blob/master/LICENSE.txt") + .suppliedByPersons("Guillaume Nodet"), + + LibraryLicense(null, libraryName = "jline.terminal.jansi", url = "https://github.com/jline/jline3") + .newBsd("https://github.com/jline/jline3/blob/master/LICENSE.txt") + .suppliedByPersons("Guillaume Nodet"), + + LibraryLicense(null, libraryName = "jline.terminal.jna", url = "https://github.com/jline/jline3") + .newBsd("https://github.com/jline/jline3/blob/master/LICENSE.txt") + .suppliedByPersons("Guillaume Nodet"), + + LibraryLicense("JNA", libraryName = "jna", url = "https://github.com/java-native-access/jna") .apache("https://github.com/java-native-access/jna/blob/master/LICENSE"), diff --git a/platform/platform-tests/eel-helper/README.txt b/platform/platform-tests/eel-helper/README.txt new file mode 100644 index 000000000000..aa2c3e4ca057 --- /dev/null +++ b/platform/platform-tests/eel-helper/README.txt @@ -0,0 +1,5 @@ +Helper for EEL local execution test +1. prints hello into stderr +2. prints tty and its size to stdout +3. waits for command exit (exit 0) or sleep (sleep 15_000) +4. installs signal for SIGINT to return 42 \ No newline at end of file diff --git a/platform/platform-tests/eel-helper/api-dump.txt b/platform/platform-tests/eel-helper/api-dump.txt new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/platform/platform-tests/eel-helper/intellij.platform.eelHelper.iml b/platform/platform-tests/eel-helper/intellij.platform.eelHelper.iml new file mode 100644 index 000000000000..58a60ae13a06 --- /dev/null +++ b/platform/platform-tests/eel-helper/intellij.platform.eelHelper.iml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + 2f461c75091ec3810a42184afc80c96910f54e9dd2110e9ecb9902a5ee6c244b + + + d8bc77bc80edc7d9a02a06a069b2d7085629421db0843aba7c153a869ffe525d + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/platform/platform-tests/eel-helper/src/META-INF/MANIFEST.MF b/platform/platform-tests/eel-helper/src/META-INF/MANIFEST.MF new file mode 100644 index 000000000000..75ad3297b4e7 --- /dev/null +++ b/platform/platform-tests/eel-helper/src/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: com.intellij.platform.tests.eelHelper.EelHelper + diff --git a/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/Command.kt b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/Command.kt new file mode 100644 index 000000000000..78477ba01a84 --- /dev/null +++ b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/Command.kt @@ -0,0 +1,20 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.platform.tests.eelHelper + +import org.jetbrains.annotations.TestOnly + +/** + * Commands to be sent from test to this helper + */ +@TestOnly +enum class Command { + /** + * Exit with [GRACEFUL_EXIT_CODE] + */ + EXIT, + + /** + * Sleep for a long time + */ + SLEEP +} \ No newline at end of file diff --git a/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/EelHelper.java b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/EelHelper.java new file mode 100644 index 000000000000..6805ba2ebef0 --- /dev/null +++ b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/EelHelper.java @@ -0,0 +1,20 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.platform.tests.eelHelper; + +import org.jetbrains.annotations.TestOnly; + +import static com.intellij.platform.tests.eelHelper.ImplKt.startHelper; + +/** + * Helper that is run by EEL test: should react on signals and commands + */ +@TestOnly +public final class EelHelper { + private EelHelper() { + } + + @TestOnly + public static void main(String[] args) { + startHelper(); + } +} diff --git a/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/Size.kt b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/Size.kt new file mode 100644 index 000000000000..97d8f07d4dd8 --- /dev/null +++ b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/Size.kt @@ -0,0 +1,4 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.platform.tests.eelHelper + +data class Size(val cols:Int, val rows: Int) \ No newline at end of file diff --git a/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/TTYState.kt b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/TTYState.kt new file mode 100644 index 000000000000..ec4ae27cefb0 --- /dev/null +++ b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/TTYState.kt @@ -0,0 +1,19 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.platform.tests.eelHelper + +import com.fasterxml.jackson.databind.ObjectMapper +import com.fasterxml.jackson.module.kotlin.registerKotlinModule +import org.jetbrains.annotations.TestOnly + +@TestOnly +data class TTYState(val size: Size?) { + companion object { + private val mapper = ObjectMapper().registerKotlinModule() + + @TestOnly + fun deserialize(str: String): TTYState = mapper.readValue(str, TTYState::class.java) + } + + @TestOnly + fun serialize(): String = mapper.writeValueAsString(this) +} \ No newline at end of file diff --git a/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/constants.kt b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/constants.kt new file mode 100644 index 000000000000..9ec7ca704482 --- /dev/null +++ b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/constants.kt @@ -0,0 +1,23 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.platform.tests.eelHelper + +import org.jetbrains.annotations.TestOnly + +/** + * Messages to be printed to stderr by this helper + */ +@TestOnly +const val HELLO: String = "hello" + +/** + * Exit code to be used on `SIGINT` + */ + +@TestOnly +const val INTERRUPT_EXIT_CODE: Int = 42 + +/** + * Exit code for [Command.EXIT] + */ +@TestOnly +const val GRACEFUL_EXIT_CODE: Int = 0 diff --git a/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/impl.kt b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/impl.kt new file mode 100644 index 000000000000..df99ad9a38fb --- /dev/null +++ b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/impl.kt @@ -0,0 +1,57 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.platform.tests.eelHelper + +import org.jetbrains.annotations.TestOnly +import org.jline.terminal.Terminal +import org.jline.terminal.TerminalBuilder +import sun.misc.Signal +import sun.misc.SignalHandler +import kotlin.system.exitProcess + +@TestOnly +private object OnSigint : SignalHandler, Terminal.SignalHandler { + override fun handle(sig: Signal?) { + onSigInt() + } + + override fun handle(signal: Terminal.Signal?) { + onSigInt() + } + + private fun onSigInt() { + exitProcess(INTERRUPT_EXIT_CODE) + } +} + + +@TestOnly +internal fun startHelper() { + + // Exit once SIGINT sent without terminal + Signal.handle(Signal("INT"), OnSigint) + + val terminal = TerminalBuilder.terminal() + val terminalSize = if (terminal.type == Terminal.TYPE_DUMB) null else terminal.size + + // Exit once SIGINT sent with terminal + terminal.handle(Terminal.Signal.INT, OnSigint) + + // First thing to do is to print this to the stderr + System.err.print(HELLO + "\n") + System.err.flush() + + val ttyState = TTYState(terminalSize?.let{ Size(cols = it.columns, rows = it.rows )}) + + // Then, print terminal info to the stdout + println(ttyState.serialize()) + System.out.flush() + + when (Command.valueOf(readln().trim().uppercase())) { + Command.EXIT -> { + exitProcess(GRACEFUL_EXIT_CODE) + } + Command.SLEEP -> { + Thread.sleep(15_000) + } + } +} \ No newline at end of file diff --git a/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/package-info.java b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/package-info.java new file mode 100644 index 000000000000..0b8e36962d58 --- /dev/null +++ b/platform/platform-tests/eel-helper/src/com/intellij/platform/tests/eelHelper/package-info.java @@ -0,0 +1,5 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +@ApiStatus.Internal +package com.intellij.platform.tests.eelHelper; + +import org.jetbrains.annotations.ApiStatus; \ No newline at end of file diff --git a/platform/platform-tests/intellij.platform.tests.iml b/platform/platform-tests/intellij.platform.tests.iml index 8e2365c4dbc1..7b28251551d8 100644 --- a/platform/platform-tests/intellij.platform.tests.iml +++ b/platform/platform-tests/intellij.platform.tests.iml @@ -107,5 +107,6 @@ + \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/execution/eel/EelLocalExecApiTest.kt b/platform/platform-tests/testSrc/com/intellij/execution/eel/EelLocalExecApiTest.kt index 58f4785f12b6..54346de475c1 100644 --- a/platform/platform-tests/testSrc/com/intellij/execution/eel/EelLocalExecApiTest.kt +++ b/platform/platform-tests/testSrc/com/intellij/execution/eel/EelLocalExecApiTest.kt @@ -1,64 +1,46 @@ // Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. package com.intellij.execution.eel -import com.google.gson.Gson import com.intellij.execution.process.UnixSignal import com.intellij.openapi.util.SystemInfoRt -import com.intellij.platform.eel.EelExecApi import com.intellij.platform.eel.EelExecApi.Pty import com.intellij.platform.eel.EelProcess import com.intellij.platform.eel.EelResult import com.intellij.platform.eel.impl.local.EelLocalExecApi -import com.intellij.testFramework.UsefulTestCase.IS_UNDER_TEAMCITY +import com.intellij.platform.tests.eelHelper.* +import com.intellij.platform.tests.eelHelper.Size import com.intellij.testFramework.common.timeoutRunBlocking import com.intellij.testFramework.junit5.TestApplication -import com.intellij.util.io.write +import io.ktor.util.decodeString +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.withContext +import kotlinx.coroutines.withTimeoutOrNull +import org.hamcrest.CoreMatchers import org.hamcrest.CoreMatchers.anyOf import org.hamcrest.CoreMatchers.`is` import org.hamcrest.MatcherAssert.assertThat import org.junit.jupiter.api.Assertions -import org.junit.jupiter.api.Assumptions.assumeFalse import org.junit.jupiter.api.BeforeAll -import org.junit.jupiter.api.BeforeEach -import org.junit.jupiter.api.io.TempDir import org.junitpioneer.jupiter.cartesian.CartesianTest -import java.nio.file.Path -import kotlin.io.path.isExecutable +import java.nio.ByteBuffer import kotlin.test.assertEquals import kotlin.test.assertNotEquals +import kotlin.time.Duration.Companion.minutes +import kotlin.time.Duration.Companion.seconds @TestApplication class EelLocalExecApiTest { companion object { - const val PYTHON_ENV = "PYTHON" private const val PTY_COLS = 42 private const val PTY_ROWS = 24 private val NEW_LINES = Regex("\r?\n") - // TODO: Remove as soon as we migrate to kotlin script from the python + private lateinit var executor: JavaMainClassExecutor + @BeforeAll @JvmStatic - fun skipTestOnTcWindows() { - assumeFalse(SystemInfoRt.isWindows && IS_UNDER_TEAMCITY, "Test is disabled on TC@WIN as there is no python by default there") - } - } - - private data class TtySize(val cols: Int, val rows: Int) - private data class PythonOutput( - val tty: Boolean, - val size: TtySize?, - ) - - private val helperContent = EelLocalExecApiTest::class.java.classLoader.getResource("helper.py")!!.readBytes() - - // TODO: This tests depends on python interpreter. Rewrite to kotlin script - private val python = Path.of(System.getenv(PYTHON_ENV) - ?: if (!SystemInfoRt.isWindows) "/usr/bin/python3" else error("Provide $PYTHON_ENV env var with path to python")) - - @BeforeEach - fun setUp() { - assert(python.isExecutable()) { - "Can't find python or $python isn't executable. Please set $PYTHON_ENV env var to the path to python binary" + fun createExecutor() { + executor = JavaMainClassExecutor(EelHelper::class.java) } } @@ -73,18 +55,15 @@ class EelLocalExecApiTest { /** - * Test runs `helper.py` checking stdin/stdout iteration, exit code, tty and signal/termination handling. + * Test runs [EelHelper] checking stdin/stdout iteration, exit code, tty and signal/termination handling. */ @CartesianTest fun testOutput( @CartesianTest.Enum exitType: ExitType, @CartesianTest.Enum ptyManagement: PTYManagement, - @TempDir tempDir: Path, - ): Unit = timeoutRunBlocking { - val helperScript = tempDir.resolve("helper.py") - helperScript.write(helperContent) + ): Unit = timeoutRunBlocking(1.minutes) { - val builder = EelExecApi.executeProcessBuilder(python.toString()).args(listOf(helperScript.toString())) + val builder = executor.createBuilderToExecuteMain() builder.pty(when (ptyManagement) { PTYManagement.NO_PTY -> null PTYManagement.PTY_SIZE_FROM_START -> Pty(PTY_COLS, PTY_ROWS, true) @@ -111,19 +90,29 @@ class EelLocalExecApiTest { } } - Assertions.assertEquals("hello", process.stderr.receive().decodeToString().trim()) + withContext(Dispatchers.Default) { + val text = ByteBuffer.allocate(1024) + withTimeoutOrNull(10.seconds) { + for (chunk in process.stderr) { + text.put(chunk) + if (HELLO in chunk.decodeToString()) break + } + } + text.limit(text.position()).rewind() + assertThat("No $HELLO reported in stderr", text.decodeString(), CoreMatchers.containsString(HELLO)) + } + // Test tty api // tty might insert "\r\n", we need to remove them. Hence, NEW_LINES. - val pyOutputStr = process.stdout.receive().decodeToString().replace(NEW_LINES, "") - val pyOutputObj = Gson().fromJson(pyOutputStr, PythonOutput::class.java) + val outputStr = process.stdout.receive().decodeToString().replace(NEW_LINES, "") + val pyOutputObj = TTYState.deserialize(outputStr) when (ptyManagement) { PTYManagement.PTY_SIZE_FROM_START, PTYManagement.PTY_RESIZE_LATER -> { - Assertions.assertTrue(pyOutputObj.tty) - Assertions.assertEquals(TtySize(PTY_COLS, PTY_ROWS), pyOutputObj.size, "size must be set for tty") + Assertions.assertNotNull(pyOutputObj.size) + Assertions.assertEquals(Size(PTY_COLS, PTY_ROWS), pyOutputObj.size, "size must be set for tty") } PTYManagement.NO_PTY -> { - Assertions.assertFalse(pyOutputObj.tty) Assertions.assertNull(pyOutputObj.size, "size must not be set if no tty") } } @@ -135,13 +124,12 @@ class EelLocalExecApiTest { ExitType.TERMINATE -> process.terminate() ExitType.INTERRUPT -> { // Terminate sleep with interrupt/CTRL+C signal - process.stdin.send("sleep\n".encodeToByteArray()) - assertEquals("sleeping", process.stdout.receive().decodeToString().trim()) + process.sendCommand(Command.SLEEP) process.interrupt() } ExitType.EXIT_WITH_COMMAND -> { // Just command to ask script return gracefully - process.stdin.send("exit\n".encodeToByteArray()) + process.sendCommand(Command.EXIT) } } val exitCode = process.exitCode.await() @@ -161,13 +149,27 @@ class EelLocalExecApiTest { } } ExitType.INTERRUPT -> { - assertEquals(42, exitCode) // CTRL+C/SIGINT handler returns 42, see script + when (ptyManagement) { + PTYManagement.NO_PTY -> Unit // SIGINT is doubtful without PTY especially without console on Windows + PTYManagement.PTY_SIZE_FROM_START, PTYManagement.PTY_RESIZE_LATER -> { + // CTRL+C/SIGINT handler returns 42, see script + assertEquals(INTERRUPT_EXIT_CODE, exitCode) + } + } } ExitType.EXIT_WITH_COMMAND -> { - assertEquals(0, exitCode) // Graceful exit + assertEquals(GRACEFUL_EXIT_CODE, exitCode) // Graceful exit } } } } } + + /** + * Sends [command] to the helper and flush + */ + private suspend fun EelProcess.sendCommand(command: Command) { + val text = command.name + "\n" + stdin.send(text.encodeToByteArray()) + } } \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/execution/eel/JavaMainClassExecutor.kt b/platform/platform-tests/testSrc/com/intellij/execution/eel/JavaMainClassExecutor.kt new file mode 100644 index 000000000000..3cb299312b84 --- /dev/null +++ b/platform/platform-tests/testSrc/com/intellij/execution/eel/JavaMainClassExecutor.kt @@ -0,0 +1,100 @@ +// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license. +package com.intellij.execution.eel + +import com.intellij.application.options.PathMacrosImpl +import com.intellij.openapi.application.PathManager +import com.intellij.openapi.diagnostic.fileLogger +import com.intellij.openapi.util.SystemInfoRt +import com.intellij.platform.eel.EelExecApi +import com.intellij.util.SystemProperties +import org.jetbrains.jps.model.java.JpsJavaExtensionService +import org.jetbrains.jps.model.library.JpsOrderRootType +import org.jetbrains.jps.model.module.JpsModule +import org.jetbrains.jps.model.serialization.JpsSerializationManager +import java.io.File +import java.nio.file.Path +import kotlin.io.path.Path +import kotlin.io.path.exists +import kotlin.io.path.name +import kotlin.io.path.pathString + + +/** + * Searches for module with [clazz] in [PathManager.ourHomePath] an executes [clazz] `main` with all dependencies + */ +internal class JavaMainClassExecutor(clazz: Class<*>) { + private val exe = Path(ProcessHandle.current().info().command().get()).toString() + private val env = mapOf("CLASSPATH" to getClassPathForClass(clazz)) + private val args = listOf(clazz.canonicalName) + + /** + * Execute `main` method + */ + fun createBuilderToExecuteMain(): EelExecApi.ExecuteProcessBuilder = EelExecApi.executeProcessBuilder(exe).env(env).args(args) + + private companion object { + private fun getClassPathForClass(clazz: Class<*>): String { + val mavenPath = Path(SystemProperties.getUserHome()).resolve(".m2").resolve("repository").toString() + val helperModuleOutputPath = getJpsModuleOutputPathForClass(clazz) + logger.value.info("helper module path: $helperModuleOutputPath") + val helperModuleName = helperModuleOutputPath.name + + val helperModule = module(helperModuleName) + + + var dependencies = JpsJavaExtensionService + .dependencies(helperModule) + .recursively() + + val libraries = dependencies + .libraries + .flatMap { it.getPaths(JpsOrderRootType.COMPILED) } + .map { Path(it.pathString.replace('$' + PathMacrosImpl.MAVEN_REPOSITORY + '$', mavenPath)) } + val modulesOutputPath = helperModuleOutputPath.parent + + val modules = dependencies + .modules + .map { module -> modulesOutputPath.resolve(module.name) } + + return (modules + libraries) + .filter { path -> + path.exists().also { + if (!it) { + logger.value.info("$path doesn't exist") + } + } + } + .joinToString(File.pathSeparator) + } + + private fun module(helperModuleName: String): JpsModule { + for (homePath in arrayOf(PathManager.getHomePath(), PathManager.getCommunityHomePath())) { + val jpsProject = JpsSerializationManager.getInstance().loadProject(homePath, mapOf()) + val helperModule = jpsProject.modules.firstOrNull { module -> module.name == helperModuleName } + if (helperModule != null) return helperModule + logger.value.warn("$helperModuleName not found in $homePath modules. Checked: ${jpsProject.modules}") + } + throw AssertionError("Couldn't find module $helperModuleName") + } + + + private fun getJpsModuleOutputPathForClass(clazz: Class<*>): Path { + val classFile = clazz.name.replace(".", "/") + ".class" + + val absoluteClassPath = clazz.classLoader.getResource(classFile)!!.path.let { path -> + Path(if (SystemInfoRt.isWindows) path.trimStart('/') else path) + } + logger.value.info("Looking for class file $absoluteClassPath") + + val relativeClassPath = Path(classFile) + var pathToModule = absoluteClassPath + while (pathToModule.toList().size > 1) { + if (pathToModule.resolve(relativeClassPath).exists()) break + pathToModule = pathToModule.parent + } + return pathToModule + } + + private val logger = lazy { fileLogger() } + } +} diff --git a/platform/platform-tests/testSrc/helper.py b/platform/platform-tests/testSrc/helper.py deleted file mode 100644 index 7695b7f7679c..000000000000 --- a/platform/platform-tests/testSrc/helper.py +++ /dev/null @@ -1,42 +0,0 @@ -# Script for EEL local execution test -# 1.prints tty and its size -# 2.waits for command exit (exit 0) or sleep (sleep 10_000) -# 3. installs signal for SIGINT to return 42 -import os -import signal -import sys -import json -from time import sleep - - -def exit_42(*_): - exit(42) - -signal.signal(signal.SIGINT, exit_42) - -is_tty = sys.stdin.isatty() -terminal_size = None - -try: - terminal_size = os.get_terminal_size() -except OSError: - pass - - -sys.stderr.write("hello\n") -sys.stderr.flush() - -json.dump({ - "tty": is_tty, - "size": {"cols": terminal_size.columns, "rows":terminal_size.lines} if terminal_size else None -}, sys.stdout) -sys.stdout.flush() - - -command = input().strip() -if command == "exit": - exit(0) -elif command == "sleep": - print("sleeping") - sys.stdout.flush() - sleep(10_000)