diff --git a/gradle.properties b/gradle.properties index 9be62a1f..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 = main +sharedLibsRef = feat/send-coverage-data-per-method sharedLibsLocalPath = lib-jvm-shared nativeAgentLibName = drill-agent nativeAgentHookEnabled = false 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/CoverageManager.kt b/test2code/src/main/kotlin/com/epam/drill/agent/test2code/coverage/CoverageManager.kt index 03e1f321..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 @@ -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, @@ -34,15 +37,19 @@ 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 + 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..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 @@ -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 @@ -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, @@ -73,13 +75,25 @@ class IntervalCoverageSender( */ private fun sendProbes(dataToSend: Sequence) { dataToSend - .map { ClassCoverage( - classname = it.name, - testId = it.testId, - testSessionId = it.sessionId, - probes = it.probes.values.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( + signature = signature, + testId = it.testId, + testSessionId = it.sessionId, + probes = methodProbes + ) + }} .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()) } } } 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..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 @@ -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.probesStartPos, m.probesCount) + }) + 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..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,8 +28,8 @@ typealias ExecData = ConcurrentHashMap */ data class ExecDatum( val id: ClassId, - val name: String, 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" 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..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,10 +89,10 @@ 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 + testId = TEST_CONTEXT_NONE, + probePositions = emptyMap() ) }