From 2442eccd9c899a81dfd4f8eb8c83db9c54167579 Mon Sep 17 00:00:00 2001 From: iryabov Date: Thu, 18 Jun 2026 06:44:31 +0200 Subject: [PATCH 1/3] refactor: replace `/recommended-tests` to `/impacted-tests` endpoint --- .../configuration/ParameterDefinitions.kt | 1 + .../RecommendedTestsReceiver.kt | 39 +++++++++++-------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt index 894669d68..00353e1ac 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt @@ -66,6 +66,7 @@ object ParameterDefinitions: AgentParameterDefinitionCollection() { val RECOMMENDED_TESTS_TARGET_BUILD_VERSION = AgentParameterDefinition.forString(name = "recommendedTestsTargetBuildVersion", defaultValue = "").register() val RECOMMENDED_TESTS_BASELINE_COMMIT_SHA = AgentParameterDefinition.forString(name = "recommendedTestsBaselineCommitSha", defaultValue = "").register() val RECOMMENDED_TESTS_BASELINE_BUILD_VERSION = AgentParameterDefinition.forString(name = "recommendedTestsBaselineBuildVersion", defaultValue = "").register() + val RECOMMENDED_TESTS_LIMIT = AgentParameterDefinition.forInt(name = "recommendedTestsLimit", defaultValue = 1000).register() val TEST_TRACING_PER_SESSION_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingPerTestSessionEnabled", defaultValue = true).register() val TEST_TRACING_PER_TEST_LAUNCH_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingPerTestLaunchEnabled", defaultValue = true).register() diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt index 0f85ed708..8fe1764e2 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt @@ -42,7 +42,6 @@ class RecommendedTestsReceiverImpl( if (!Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED]) return emptyList() val groupId = Configuration.parameters[DefaultParameterDefinitions.GROUP_ID] - val testTaskId = Configuration.parameters[ParameterDefinitions.TEST_TASK_ID] val targetAppId = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_TARGET_APP_ID] val targetBuildVersion = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_TARGET_BUILD_VERSION] .takeIf { it.isNotEmpty() } @@ -53,26 +52,30 @@ class RecommendedTestsReceiverImpl( val baselineBuildVersion = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_BASELINE_BUILD_VERSION] .takeIf { it.isNotEmpty() } - + val limit = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_LIMIT] val parameters: String = buildString { append("?groupId=$groupId") append("&appId=$targetAppId") - append("&testTaskId=$testTaskId") - append("&testsToSkip=true") - targetBuildVersion?.let { append("&targetBuildVersion=$it") } - targetCommitSha?.let { append("&targetCommitSha=$it") } + targetBuildVersion?.let { append("&buildVersion=$it") } + targetCommitSha?.let { append("&commitSha=$it") } baselineCommitSha?.let { append("&baselineCommitSha=$it") } baselineBuildVersion?.let { append("&baselineBuildVersion=$it") } + append("&impactStatuses=NOT_IMPACTED") + append("&pageSize=$limit") } - logger.debug { "Retrieving information about recommended tests, testTaskId: $testTaskId" } + logger.debug { "Retrieving information about recommended tests..." } return runCatching { - agentMessageReceiver.receive( + val response = agentMessageReceiver.receive( AgentMessageDestination( "GET", - "/recommended-tests$parameters", + "/impacted-tests$parameters", ), RecommendedTestsApiResponse::class - ).data.recommendedTests.map { it.toTestMethodInfo() } + ) + if (response.paging.pageSize >= limit) { + logger.warn { "The number of recommended tests is more or equal than $limit. Consider increasing the limit." } + } + response.data.map { it.toTestMethodInfo() } }.onFailure { logger.warn { "Unable to retrieve information about recommended tests. Error message: $it" } }.getOrElse { @@ -87,12 +90,8 @@ class RecommendedTestsReceiverImpl( @Serializable class RecommendedTestsApiResponse( - val data: RecommendedTestsResponse -) - -@Serializable -class RecommendedTestsResponse( - val recommendedTests: List + val data: List, + val paging: Paging ) @Serializable @@ -103,6 +102,14 @@ class TestDefinitionResponse( val testName: String, val tags: List, val metadata: Map, + val impactStatus: String, +) + +@Serializable +data class Paging( + val page: Int, + val pageSize: Int, + val total: Long? ) private fun TestDefinitionResponse.toTestMethodInfo() = TestMethodInfo( From 31411f4e33bb0dbaa03d73358f40e195a402616d Mon Sep 17 00:00:00 2001 From: iryabov Date: Thu, 18 Jun 2026 14:57:50 +0200 Subject: [PATCH 2/3] fix: add compatibility for JUnit Platform 1.11+ with getOutputDirectoryProvider() delegation --- .../JUnitPlatformPrioritizingTransformer.kt | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt index 14bf57179..d617d83f0 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/instrument/junit/JUnitPlatformPrioritizingTransformer.kt @@ -176,6 +176,28 @@ actual object JUnitPlatformPrioritizingTransformer : Transformer, AbstractJUnitT cc ) ) + // JUnit Platform 1.11+ added getOutputDirectoryProvider() to LauncherDiscoveryRequest. + // This ensures compatibility with both JUnit Platform < 1.11 and >= 1.11. + val runtimeClassLoader = classLoader ?: ClassLoader.getSystemClassLoader() + runCatching { + runtimeClassLoader.loadClass(LauncherDiscoveryRequest) + .getMethod("getOutputDirectoryProvider") + }.onSuccess { method -> + val returnType = method.returnType.name + cc.addMethod( + CtMethod.make( + """ + public $returnType getOutputDirectoryProvider() { + return delegate.getOutputDirectoryProvider(); + } + """.trimIndent(), + cc + ) + ) + logger.debug { "JUnit Platform >= 1.11 detected: added getOutputDirectoryProvider() delegation (returnType=$returnType) to LauncherDiscoveryRequestAdapter" } + }.onFailure { + logger.debug { "JUnit Platform < 1.11 detected: skipping getOutputDirectoryProvider() delegation" } + } cc.toClass(classLoader, protectionDomain) return cc } From 846332341e6215d153688f3df83349abed00a12d Mon Sep 17 00:00:00 2001 From: iryabov Date: Tue, 30 Jun 2026 09:44:25 +0200 Subject: [PATCH 3/3] feat: add support for loading tests to skip from a JSON file --- gradle.properties | 2 +- .../configuration/ParameterDefinitions.kt | 4 ++++ .../RecommendedTestsReceiver.kt | 24 +++++++++++++++++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9810ef177..aee31396c 100644 --- a/gradle.properties +++ b/gradle.properties @@ -28,7 +28,7 @@ nativeAgentLibName = drill-agent nativeAgentHookEnabled = false macosLd64 = false -org.gradle.jvmargs = -Xmx4096m -XX:MaxPermSize=1024m +org.gradle.jvmargs = -Xmx4096m org.gradle.daemon = false org.gradle.parallel = true org.gradle.workers.max = 4 diff --git a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt index 00353e1ac..f6c134f7d 100644 --- a/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt +++ b/java-agent/src/commonMain/kotlin/com/epam/drill/agent/configuration/ParameterDefinitions.kt @@ -67,6 +67,10 @@ object ParameterDefinitions: AgentParameterDefinitionCollection() { val RECOMMENDED_TESTS_BASELINE_COMMIT_SHA = AgentParameterDefinition.forString(name = "recommendedTestsBaselineCommitSha", defaultValue = "").register() val RECOMMENDED_TESTS_BASELINE_BUILD_VERSION = AgentParameterDefinition.forString(name = "recommendedTestsBaselineBuildVersion", defaultValue = "").register() val RECOMMENDED_TESTS_LIMIT = AgentParameterDefinition.forInt(name = "recommendedTestsLimit", defaultValue = 1000).register() + val RECOMMENDED_TESTS_FILE = NullableAgentParameterDefinition.forString( + name = "recommendedTestsFile", + description = "Path to a JSON file containing a list of tests to skip." + ).register() val TEST_TRACING_PER_SESSION_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingPerTestSessionEnabled", defaultValue = true).register() val TEST_TRACING_PER_TEST_LAUNCH_ENABLED = AgentParameterDefinition.forBoolean(name = "testTracingPerTestLaunchEnabled", defaultValue = true).register() diff --git a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt index 8fe1764e2..3aaa84f0a 100644 --- a/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt +++ b/java-agent/src/jvmMain/kotlin/com/epam/drill/agent/test/prioritization/RecommendedTestsReceiver.kt @@ -25,7 +25,10 @@ import com.epam.drill.agent.test.execution.TestExecutionRecorder import com.epam.drill.agent.test.execution.TestMethodInfo import com.epam.drill.agent.transport.MetricsMessageReceiver import kotlinx.serialization.Serializable +import kotlinx.serialization.builtins.ListSerializer +import kotlinx.serialization.json.Json import mu.KotlinLogging +import java.io.File interface RecommendedTestsReceiver { fun getTestsToSkip(): List @@ -39,6 +42,10 @@ class RecommendedTestsReceiverImpl( private val logger = KotlinLogging.logger {} override fun getTestsToSkip(): List { + val testsToSkipFilePath = Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_FILE] + if (testsToSkipFilePath != null) { + return loadTestsToSkipFromFile(testsToSkipFilePath) + } if (!Configuration.parameters[ParameterDefinitions.RECOMMENDED_TESTS_ENABLED]) return emptyList() val groupId = Configuration.parameters[DefaultParameterDefinitions.GROUP_ID] @@ -86,8 +93,25 @@ class RecommendedTestsReceiverImpl( override fun sendSkippedTest(test: TestMethodInfo) { testExecutionRecorder.recordTestIgnoring(test, isSmartSkip = true) } + + private fun loadTestsToSkipFromFile(filePath: String): List { + logger.debug { "Loading tests to skip from file: $filePath" } + return runCatching { + val content = File(filePath).readText() + val entries = fileJson.decodeFromString(ListSerializer(TestDefinitionResponse.serializer()), content) + entries.map { it.toTestMethodInfo() }.also { + logger.info { "Loaded ${it.size} tests to skip from file: $filePath" } + } + }.onFailure { + logger.warn { "Unable to load tests to skip from file '$filePath'. Error message: $it" } + }.getOrElse { + emptyList() + } + } } +private val fileJson = Json { ignoreUnknownKeys = true } + @Serializable class RecommendedTestsApiResponse( val data: List,