From cfc2c6f52c6155cefd8e2863f4d3d4ecd8c8d86c Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Tue, 20 Jan 2026 17:00:00 +0400 Subject: [PATCH 01/14] feat: add probe position storage to CoverageManager & send cov per method --- .../drill/agent/test2code/coverage/CoverageManager.kt | 10 +++++++++- .../drill/agent/test2code/coverage/CoverageSender.kt | 8 +++++--- .../drill/agent/test2code/coverage/Instrumentation.kt | 7 ++++++- .../com/epam/drill/agent/test2code/coverage/Models.kt | 1 + .../drill/agent/test2code/coverage/ProbesProvider.kt | 6 +++++- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt index 03e1f321..a20bdb2b 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt @@ -16,6 +16,7 @@ package com.epam.drill.agent.test2code.coverage import com.epam.drill.agent.jacoco.AgentProbes +import java.util.concurrent.ConcurrentHashMap open class CoverageManager( private val threadCoverageRecorder: ICoverageRecorder = ThreadCoverageRecorder(), @@ -23,6 +24,8 @@ open class CoverageManager( ) : IProbesProxy, ICoverageRecorder by threadCoverageRecorder { + private val classProbePositions: ConcurrentHashMap>> = ConcurrentHashMap() + override fun invoke( id: Long, num: Int, @@ -37,12 +40,17 @@ open class CoverageManager( name = name, probes = AgentProbes(probeCount), sessionId = coverage.context.sessionId, - testId = coverage.context.testId + testId = coverage.context.testId, + probePositions = classProbePositions[id]!! // TODO do not throw ) } return execDatum.probes } + override fun addProbePositions(classId: Long, probePositions: Map>) { + classProbePositions[classId] = probePositions + } + override fun pollRecorded(): Sequence { return threadCoverageRecorder.pollRecorded() + globalCoverageRecorder.pollRecorded() } diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt index 1c9e61ae..64c7ed41 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt @@ -20,7 +20,7 @@ import java.util.concurrent.TimeUnit import mu.KotlinLogging import com.epam.drill.agent.common.transport.AgentMessageDestination import com.epam.drill.agent.common.transport.AgentMessageSender -import com.epam.drill.agent.test2code.common.api.ClassCoverage +import com.epam.drill.agent.test2code.common.api.MethodCoverage import com.epam.drill.agent.test2code.common.api.toBitSet import com.epam.drill.agent.test2code.common.transport.CoveragePayload import kotlinx.serialization.KSerializer @@ -73,11 +73,13 @@ class IntervalCoverageSender( */ private fun sendProbes(dataToSend: Sequence) { dataToSend - .map { ClassCoverage( + .flatMap { it.probePositions.map { (signature, positions) -> MethodCoverage( classname = it.name, + signature = signature, testId = it.testId, testSessionId = it.sessionId, - probes = it.probes.values.toBitSet()) } + probes = it.probes.values.copyOfRange(positions.first, positions.first + positions.second).toBitSet() + ) } } .chunked(pageSize) .forEach { sender.send(destination, CoveragePayload(groupId, appId, instanceId, it), CoveragePayload.serializer()) } } diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Instrumentation.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Instrumentation.kt index 2d900557..c9de1260 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Instrumentation.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Instrumentation.kt @@ -21,6 +21,7 @@ import com.epam.drill.agent.jacoco.BooleanArrayProbeInserter.* import com.epam.drill.agent.jacoco.DrillClassProbesAdapter import com.epam.drill.agent.jacoco.DrillDuplicateFrameEliminator import com.epam.drill.agent.jacoco.DrillMethodInstrumenter +import com.epam.drill.agent.test2code.classparsing.ClassProbeCounter import com.epam.drill.agent.test2code.classparsing.ProbeCounter import org.jacoco.core.internal.data.CRC64 import org.jacoco.core.internal.flow.* @@ -42,10 +43,14 @@ class DrillInstrumenter( val classId = CRC64.classId(initialBytes) //count probes before transformation - val counter = ProbeCounter() val reader = InstrSupport.classReaderFor(initialBytes) + val counter = ClassProbeCounter(className) reader.accept(DrillClassProbesAdapter(counter, false), 0) + probesProxy.addProbePositions(classId, counter.methods.associate { m -> + "${m.classname}:${m.name}:${m.params}:${m.returnType}" to Pair(m.probesCount, m.probesStartPos) + }) + val genId = classCounter.incrementAndGet() val probeCount = counter.count val strategy = DrillProbeStrategy( diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt index c64a94c0..a3d9ea91 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt @@ -32,4 +32,5 @@ data class ExecDatum( val probes: AgentProbes, val sessionId: String, val testId: String, + val probePositions: Map> ) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ProbesProvider.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ProbesProvider.kt index 29122602..7d056a94 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ProbesProvider.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/ProbesProvider.kt @@ -21,7 +21,11 @@ import com.epam.drill.agent.jacoco.AgentProbes * Provides boolean array for the probe. * Implementations must be kotlin singleton objects. */ -typealias IProbesProxy = (ClassId, Int, String, Int) -> AgentProbes + +interface IProbesProxy { + fun invoke(id: ClassId, num: Int, name: String, probeCount: Int): AgentProbes + fun addProbePositions(classId: Long, probePositions: Map>) +} const val SESSION_CONTEXT_NONE = "SESSION_CONTEXT_NONE" const val TEST_CONTEXT_NONE = "TEST_CONTEXT_NONE" From ae757a7236edd71730f6cfd4757b390366e50fac Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Tue, 20 Jan 2026 18:07:38 +0400 Subject: [PATCH 02/14] build: set sharedLibsRef to feature/properties-file-parse-multiline-values --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 9be62a1f..8cda8ed2 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,7 @@ apacheHttpClientVersion = 5.2.3 aesyDatasizeVersion = 1.0.0 bytebuddyVersion = 1.14.11 -sharedLibsRef = main +sharedLibsRef = feature/properties-file-parse-multiline-values sharedLibsLocalPath = lib-jvm-shared nativeAgentLibName = drill-agent nativeAgentHookEnabled = false From 78fb6c9aee08c48f00d6c6736c9bdcf39f624c87 Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Tue, 20 Jan 2026 18:15:38 +0400 Subject: [PATCH 03/14] test: fix GlobalCoverageRecorderTest --- .../agent/test2code/coverage/GlobalCoverageRecorderTest.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt b/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt index af3ab796..b4d46025 100644 --- a/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt +++ b/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt @@ -92,7 +92,8 @@ class GlobalCoverageRecorderTest { name = "foo", sessionId = SESSION_CONTEXT_AMBIENT, probes = AgentProbes(initialSize = probes.size, values = booleanArrayOf(*probes)), - testId = TEST_CONTEXT_NONE + testId = TEST_CONTEXT_NONE, + probePositions = emptyMap() ) } From 3013cf0d4937d0e4d7c7b1a1dcb553336d49a7a8 Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Tue, 20 Jan 2026 19:25:15 +0400 Subject: [PATCH 04/14] fix: probesStartPos and probesCount mixed places --- .../com/epam/drill/agent/test2code/coverage/Instrumentation.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Instrumentation.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Instrumentation.kt index c9de1260..ea5c8114 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Instrumentation.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Instrumentation.kt @@ -48,7 +48,7 @@ class DrillInstrumenter( reader.accept(DrillClassProbesAdapter(counter, false), 0) probesProxy.addProbePositions(classId, counter.methods.associate { m -> - "${m.classname}:${m.name}:${m.params}:${m.returnType}" to Pair(m.probesCount, m.probesStartPos) + "${m.classname}:${m.name}:${m.params}:${m.returnType}" to Pair(m.probesStartPos, m.probesCount) }) val genId = classCounter.incrementAndGet() From 3d03a047a04a63534b26ad239f57a39ef73ede06 Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Wed, 21 Jan 2026 16:16:11 +0400 Subject: [PATCH 05/14] feat: filter coverage with empty probes --- .../agent/test2code/coverage/CoverageSender.kt | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt index 64c7ed41..4a8e4912 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt @@ -73,13 +73,17 @@ class IntervalCoverageSender( */ private fun sendProbes(dataToSend: Sequence) { dataToSend - .flatMap { it.probePositions.map { (signature, positions) -> MethodCoverage( - classname = it.name, - signature = signature, - testId = it.testId, - testSessionId = it.sessionId, - probes = it.probes.values.copyOfRange(positions.first, positions.first + positions.second).toBitSet() - ) } } + .flatMap { it.probePositions.mapNotNull { (signature, positions) -> + val methodProbes = it.probes.values.copyOfRange(positions.first, positions.first + positions.second).toBitSet() + if (!methodProbes.isEmpty) null + else MethodCoverage( + classname = it.name, + signature = signature, + testId = it.testId, + testSessionId = it.sessionId, + probes = methodProbes + ) + }} .chunked(pageSize) .forEach { sender.send(destination, CoveragePayload(groupId, appId, instanceId, it), CoveragePayload.serializer()) } } From 1e83e3c2af9f16579535685c40de855c966bd9b1 Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Wed, 21 Jan 2026 16:19:59 +0400 Subject: [PATCH 06/14] refactor: remove redundant classname from ExecDatum --- .../com/epam/drill/agent/test2code/coverage/CoverageManager.kt | 1 - .../com/epam/drill/agent/test2code/coverage/CoverageSender.kt | 1 - .../kotlin/com/epam/drill/agent/test2code/coverage/Models.kt | 1 - .../drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt | 1 - 4 files changed, 4 deletions(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt index a20bdb2b..95c9116b 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt @@ -37,7 +37,6 @@ open class CoverageManager( val execDatum = coverage.execData.getOrPut(id) { ExecDatum( id = id, - name = name, probes = AgentProbes(probeCount), sessionId = coverage.context.sessionId, testId = coverage.context.testId, diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt index 4a8e4912..27004cda 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt @@ -77,7 +77,6 @@ class IntervalCoverageSender( val methodProbes = it.probes.values.copyOfRange(positions.first, positions.first + positions.second).toBitSet() if (!methodProbes.isEmpty) null else MethodCoverage( - classname = it.name, signature = signature, testId = it.testId, testSessionId = it.sessionId, diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt index a3d9ea91..1f2a14ac 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt @@ -28,7 +28,6 @@ typealias ExecData = ConcurrentHashMap */ data class ExecDatum( val id: ClassId, - val name: String, val probes: AgentProbes, val sessionId: String, val testId: String, diff --git a/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt b/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt index b4d46025..b62b526d 100644 --- a/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt +++ b/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt @@ -89,7 +89,6 @@ class GlobalCoverageRecorderTest { private fun ContextCoverage.putProbes(classId: Long, vararg probes: Boolean) { execData[classId] = ExecDatum( id = classId, - name = "foo", sessionId = SESSION_CONTEXT_AMBIENT, probes = AgentProbes(initialSize = probes.size, values = booleanArrayOf(*probes)), testId = TEST_CONTEXT_NONE, From 9af1c44a97dc64c929dd8db3f33a64bc839a822e Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Wed, 21 Jan 2026 16:35:02 +0400 Subject: [PATCH 07/14] build: set sharedLibsRef & remove commented code --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 8cda8ed2..4d0d5639 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,7 @@ apacheHttpClientVersion = 5.2.3 aesyDatasizeVersion = 1.0.0 bytebuddyVersion = 1.14.11 -sharedLibsRef = feature/properties-file-parse-multiline-values +sharedLibsRef = feat/send-coverage-data-per-method sharedLibsLocalPath = lib-jvm-shared nativeAgentLibName = drill-agent nativeAgentHookEnabled = false From f9875902a81d72e3ff55a783a712e6bc5f837d03 Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Thu, 22 Jan 2026 20:34:31 +0400 Subject: [PATCH 08/14] feat: send commitSha & buildVersion with CoveragePayload --- .../com/epam/drill/agent/test2code/Test2Code.kt | 2 ++ .../drill/agent/test2code/coverage/CoverageSender.kt | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt index 43b26b87..f9ebf777 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt @@ -60,6 +60,8 @@ class Test2Code( groupId = configuration.agentMetadata.groupId, appId = configuration.agentMetadata.appId, instanceId = configuration.agentMetadata.instanceId, + commitSha = configuration.agentMetadata.commitSha, + buildVersion = configuration.agentMetadata.buildVersion, intervalMs = configuration.parameters[Test2CodeParameterDefinitions.COVERAGE_SEND_INTERVAL], pageSize = configuration.parameters[Test2CodeParameterDefinitions.COVERAGE_SEND_PAGE_SIZE], sender = sender, diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt index 27004cda..041679e9 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt @@ -33,6 +33,8 @@ interface CoverageSender { class IntervalCoverageSender( private val groupId: String, private val appId: String, + private val commitSha: String?, + private val buildVersion: String?, private val instanceId: String, private val intervalMs: Long, private val pageSize: Int, @@ -84,7 +86,14 @@ class IntervalCoverageSender( ) }} .chunked(pageSize) - .forEach { sender.send(destination, CoveragePayload(groupId, appId, instanceId, it), CoveragePayload.serializer()) } + .forEach { sender.send(destination, CoveragePayload( + groupId = groupId, + appId = appId, + instanceId = instanceId, + commitSha = commitSha, + buildVersion = buildVersion, + coverage = it + ), CoveragePayload.serializer()) } } } From c3f6caaa19133b5fb250cf8c0b96076de548c4ec Mon Sep 17 00:00:00 2001 From: iryabov Date: Mon, 2 Feb 2026 12:39:44 +0100 Subject: [PATCH 09/14] fix: correct methodProbes empty check in CoverageSender --- .../com/epam/drill/agent/test2code/coverage/CoverageSender.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt index 041679e9..a7bac518 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt @@ -77,7 +77,7 @@ class IntervalCoverageSender( dataToSend .flatMap { it.probePositions.mapNotNull { (signature, positions) -> val methodProbes = it.probes.values.copyOfRange(positions.first, positions.first + positions.second).toBitSet() - if (!methodProbes.isEmpty) null + if (methodProbes.isEmpty) null else MethodCoverage( signature = signature, testId = it.testId, From 3cb71735a1473f855ae0b84ce40e559f8c0b57ba Mon Sep 17 00:00:00 2001 From: iryabov Date: Mon, 2 Feb 2026 12:40:35 +0100 Subject: [PATCH 10/14] build: update sharedLibsRef to feature/coverage-with-commit-sha-EPMDJ-11185 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 4d0d5639..acbaeafa 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,7 @@ apacheHttpClientVersion = 5.2.3 aesyDatasizeVersion = 1.0.0 bytebuddyVersion = 1.14.11 -sharedLibsRef = feat/send-coverage-data-per-method +sharedLibsRef = feature/coverage-with-commit-sha-EPMDJ-11185 sharedLibsLocalPath = lib-jvm-shared nativeAgentLibName = drill-agent nativeAgentHookEnabled = false From 9c311608a2ec3a9ffadbb73ee95f477f58f78867 Mon Sep 17 00:00:00 2001 From: iryabov Date: Mon, 2 Feb 2026 12:44:34 +0100 Subject: [PATCH 11/14] fix: handle missing probe positions in CoverageManager --- .../com/epam/drill/agent/test2code/coverage/CoverageManager.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt index 95c9116b..5af8672b 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt @@ -40,7 +40,7 @@ open class CoverageManager( probes = AgentProbes(probeCount), sessionId = coverage.context.sessionId, testId = coverage.context.testId, - probePositions = classProbePositions[id]!! // TODO do not throw + probePositions = classProbePositions[id] ?: emptyMap(), ) } return execDatum.probes From 8575a06e165818a0ceab6d934669739da1ab147d Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Tue, 3 Feb 2026 19:51:15 +0400 Subject: [PATCH 12/14] feat: move classProbePositions from ExecDatum to CoverageSender --- .../epam/drill/agent/test2code/Test2Code.kt | 3 +- .../test2code/coverage/CoverageManager.kt | 3 +- .../test2code/coverage/CoverageSender.kt | 32 ++++++++++++++----- .../drill/agent/test2code/coverage/Models.kt | 1 - 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt index f9ebf777..8adcf4fa 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/Test2Code.kt @@ -66,7 +66,8 @@ class Test2Code( pageSize = configuration.parameters[Test2CodeParameterDefinitions.COVERAGE_SEND_PAGE_SIZE], sender = sender, collectReleasedProbes = { coverageManager.pollRecorded() }, - collectUnreleasedProbes = { coverageManager.getUnreleased() } + collectUnreleasedProbes = { coverageManager.getUnreleased() }, + classProbePositions = coverageManager.classProbePositions ) private val coverageCollectionEnabled = configuration.parameters[COVERAGE_COLLECTION_ENABLED] private val classScanningEnabled = configuration.parameters[Test2CodeParameterDefinitions.CLASS_SCANNING_ENABLED] diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt index 5af8672b..cb3adffa 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt @@ -24,7 +24,7 @@ open class CoverageManager( ) : IProbesProxy, ICoverageRecorder by threadCoverageRecorder { - private val classProbePositions: ConcurrentHashMap>> = ConcurrentHashMap() + val classProbePositions: ConcurrentHashMap>> = ConcurrentHashMap() override fun invoke( id: Long, @@ -40,7 +40,6 @@ open class CoverageManager( probes = AgentProbes(probeCount), sessionId = coverage.context.sessionId, testId = coverage.context.testId, - probePositions = classProbePositions[id] ?: emptyMap(), ) } return execDatum.probes diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt index a7bac518..7c251867 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageSender.kt @@ -24,6 +24,7 @@ import com.epam.drill.agent.test2code.common.api.MethodCoverage import com.epam.drill.agent.test2code.common.api.toBitSet import com.epam.drill.agent.test2code.common.transport.CoveragePayload import kotlinx.serialization.KSerializer +import java.util.concurrent.ConcurrentHashMap interface CoverageSender { fun startSendingCoverage() @@ -40,7 +41,8 @@ class IntervalCoverageSender( private val pageSize: Int, private val sender: AgentMessageSender = StubSender(), private val collectReleasedProbes: () -> Sequence = { emptySequence() }, - private val collectUnreleasedProbes: () -> Sequence = { emptySequence() } + private val collectUnreleasedProbes: () -> Sequence = { emptySequence() }, + private val classProbePositions: ConcurrentHashMap>> ) : CoverageSender { private val scheduledThreadPool = Executors.newSingleThreadScheduledExecutor() private val destination = AgentMessageDestination("POST", "coverage") @@ -75,16 +77,30 @@ class IntervalCoverageSender( */ private fun sendProbes(dataToSend: Sequence) { dataToSend - .flatMap { it.probePositions.mapNotNull { (signature, positions) -> - val methodProbes = it.probes.values.copyOfRange(positions.first, positions.first + positions.second).toBitSet() - if (methodProbes.isEmpty) null - else MethodCoverage( + .mapNotNull { + classProbePositions[it.id]?.let { positionsByMethod -> + it to positionsByMethod + } ?: run { + logger.warn("No probe positions for class id=${it.id}") + null + } + } + .flatMap { (datum, positionsByMethod) -> + positionsByMethod.mapNotNull { (signature, positions) -> + val methodProbes = + datum.probes.values + .copyOfRange(positions.first, positions.first + positions.second) + .toBitSet() + + if (methodProbes.isEmpty) null + else MethodCoverage( signature = signature, - testId = it.testId, - testSessionId = it.sessionId, + testId = datum.testId, + testSessionId = datum.sessionId, probes = methodProbes ) - }} + } + } .chunked(pageSize) .forEach { sender.send(destination, CoveragePayload( groupId = groupId, diff --git a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt index 1f2a14ac..2920b79a 100644 --- a/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt +++ b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/Models.kt @@ -31,5 +31,4 @@ data class ExecDatum( val probes: AgentProbes, val sessionId: String, val testId: String, - val probePositions: Map> ) From dd46c9150cad2d744cd8adb9501a69ec37cd2f30 Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Tue, 3 Feb 2026 20:00:26 +0400 Subject: [PATCH 13/14] tests: remove probePositions from ExecDatum in GlobalCoverageRecorderTest --- .../drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt | 1 - 1 file changed, 1 deletion(-) diff --git a/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt b/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt index b62b526d..c36734e5 100644 --- a/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt +++ b/test2code/src/test/kotlin/com/epam/drill/agent/test2code/coverage/GlobalCoverageRecorderTest.kt @@ -92,7 +92,6 @@ class GlobalCoverageRecorderTest { sessionId = SESSION_CONTEXT_AMBIENT, probes = AgentProbes(initialSize = probes.size, values = booleanArrayOf(*probes)), testId = TEST_CONTEXT_NONE, - probePositions = emptyMap() ) } From 93110d254de2d0d87ad5bf63b64f97731226a093 Mon Sep 17 00:00:00 2001 From: RomanDavlyatshin Date: Fri, 13 Feb 2026 14:16:28 +0400 Subject: [PATCH 14/14] build: set sharedLibsRef = main --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index acbaeafa..9be62a1f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -21,7 +21,7 @@ apacheHttpClientVersion = 5.2.3 aesyDatasizeVersion = 1.0.0 bytebuddyVersion = 1.14.11 -sharedLibsRef = feature/coverage-with-commit-sha-EPMDJ-11185 +sharedLibsRef = main sharedLibsLocalPath = lib-jvm-shared nativeAgentLibName = drill-agent nativeAgentHookEnabled = false