Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,11 +60,14 @@ 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,
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]
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 {

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

override fun invoke(
id: Long,
num: Int,
Expand All @@ -34,15 +37,18 @@ 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,
)
}
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,10 +20,11 @@ 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
import java.util.concurrent.ConcurrentHashMap

interface CoverageSender {
fun startSendingCoverage()
Expand All @@ -33,12 +34,15 @@ 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,
private val sender: AgentMessageSender = StubSender(),
private val collectReleasedProbes: () -> Sequence<ExecDatum> = { emptySequence() },
private val collectUnreleasedProbes: () -> Sequence<ExecDatum> = { emptySequence() }
private val collectUnreleasedProbes: () -> Sequence<ExecDatum> = { emptySequence() },
private val classProbePositions: ConcurrentHashMap<Long, Map<String, Pair<Int, Int>>>
) : CoverageSender {
private val scheduledThreadPool = Executors.newSingleThreadScheduledExecutor()
private val destination = AgentMessageDestination("POST", "coverage")
Expand Down Expand Up @@ -73,13 +77,39 @@ 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()) }
.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 = datum.testId,
testSessionId = datum.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,7 +28,6 @@ typealias ExecData = ConcurrentHashMap<ClassId, ExecDatum>
*/
data class ExecDatum(
val id: ClassId,
val name: String,
val probes: AgentProbes,
val sessionId: String,
val testId: String,
Expand Down
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,9 @@ 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,
)
}

Expand Down
Loading