Skip to content
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,16 @@
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(),
private val globalCoverageRecorder: GlobalCoverageRecorder = GlobalCoverageRecorder(),
) : IProbesProxy,
ICoverageRecorder by threadCoverageRecorder {

private val classProbePositions: ConcurrentHashMap<Long, Map<String, Pair<Int, Int>>> = ConcurrentHashMap()

override fun invoke(
id: Long,
num: Int,
Expand All @@ -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<String, Pair<Int, Int>>) {
classProbePositions[classId] = probePositions
}

override fun pollRecorded(): Sequence<ExecDatum> {
return threadCoverageRecorder.pollRecorded() + globalCoverageRecorder.pollRecorded()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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,
Expand Down Expand Up @@ -73,13 +75,25 @@ class IntervalCoverageSender(
*/
private fun sendProbes(dataToSend: Sequence<ExecDatum>) {
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()) }
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.*
Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ typealias ExecData = ConcurrentHashMap<ClassId, ExecDatum>
*/
data class ExecDatum(
val id: ClassId,
val name: String,
val probes: AgentProbes,
val sessionId: String,
val testId: String,
val probePositions: Map<String, Pair<Int, Int>>
)
Original file line number Diff line number Diff line change
Expand Up @@ -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<String, Pair<Int,Int>>)
}

const val SESSION_CONTEXT_NONE = "SESSION_CONTEXT_NONE"
const val TEST_CONTEXT_NONE = "TEST_CONTEXT_NONE"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
)
}

Expand Down
Loading