Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix part of #5343: Enable Code Coverage Analysis for many to one test target files #5459

Merged
merged 132 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
132 commits
Select commit Hold shift + click to select a range
d1c07cd
Code Coverage M1 edge case, added arg names to specifically pick the …
Rd4dev Jun 28, 2024
b26ac35
Modified script example doc and updated the exception string to be mo…
Rd4dev Jun 28, 2024
b89d9a8
Added tests for edge case checks
Rd4dev Jun 28, 2024
23cba86
Increasing the processTimeout to 10 minutes as coverage analysis take…
Rd4dev Jun 28, 2024
e24578e
Setting processTimeout in the run coverage script to see if this affe…
Rd4dev Jun 28, 2024
96c2b74
Set processTimeout for added test cases
Rd4dev Jun 28, 2024
349be2e
Triggering Build to check TIMEOUT
Rd4dev Jun 29, 2024
300fb90
Reverting the changes just to check if these changes have any effect …
Rd4dev Jun 29, 2024
181e8b2
Reverting the changes just to check if these changes have any effect …
Rd4dev Jun 29, 2024
87926ad
Re-introducing the changes while removing the ignore case check as we…
Rd4dev Jun 29, 2024
718b065
Re-introducing the test changes with the passed ci check with ignore …
Rd4dev Jun 29, 2024
c15d6e7
Trying out other unit of processTimeout value
Rd4dev Jun 29, 2024
f417bda
Do not merge - Updated WAIT_PROCESS_TIMEOUT_MS to x4
Rd4dev Jun 29, 2024
70378d6
Using a smaller / simpler source and test file to check if this still…
Rd4dev Jun 29, 2024
9dbd7be
Commenting out 1 of 2 newly added tests
Rd4dev Jun 29, 2024
f59c768
Using a simpler test and source file for sampleTestsDefaultFormat to …
Rd4dev Jun 29, 2024
f5663d7
Using a simpler test and source file for scriptTestsMarkdownFormat to…
Rd4dev Jun 29, 2024
bab336e
Checking if remvoing the 2nd test case solves the timeout to confirm
Rd4dev Jun 29, 2024
2ee1bba
Reverting back to original changes
Rd4dev Jun 29, 2024
23b15b7
Trying to see if moving the declration to setup could reduce load
Rd4dev Jun 29, 2024
6f30dac
Moving scripts source and test files to setup
Rd4dev Jun 29, 2024
b391b1c
Removed any duplicate coverage file creations as they were already in…
Rd4dev Jun 29, 2024
f684951
Almost making compute affected tests execution time to 1 millisecond …
Rd4dev Jun 29, 2024
100d8f1
The actual compute affected test do reflect processTimeout
Rd4dev Jun 29, 2024
4f2d93f
Removing lazy declaration to see if command Executor works that way
Rd4dev Jun 29, 2024
9886da4
Initialize command Executor reference
Rd4dev Jun 29, 2024
4f5d47c
Import CommandExecutor statement added
Rd4dev Jun 29, 2024
69d4583
Added arg names to script calls
Rd4dev Jun 29, 2024
e82f2fd
Trying to make it die in 1L to see if there are any actual reflection…
Rd4dev Jun 29, 2024
a757fd9
Increasing the processTimeout and commandExecutor to high values
Rd4dev Jun 29, 2024
f215839
Setting default and only option as 100L in RunCoverage
Rd4dev Jun 29, 2024
d3105cd
Attempting with main caLL
Rd4dev Jun 29, 2024
f4b305f
Intentionally causing delay in computeAffectedTestsTest to see if pro…
Rd4dev Jun 30, 2024
d78df95
Bumping time to 550 because 350 worked
Rd4dev Jun 30, 2024
c1bfbe1
Completely cleaned up RunCoverageTest for checking with just one test…
Rd4dev Jun 30, 2024
043fcfc
Making RunCoverage default to 0 while passing processTimeout value
Rd4dev Jun 30, 2024
9e3a16a
Intentionally making RunCoverageTest sleep
Rd4dev Jun 30, 2024
f40793c
Last commit overrided the processTimeout with 10 minutes while defaul…
Rd4dev Jun 30, 2024
8d6a10f
Defaulting processTimeout to 1
Rd4dev Jun 30, 2024
1a69432
Reverting all local changes
Rd4dev Jun 30, 2024
9437d67
Adding test timeout, yet this is for failures just trying out
Rd4dev Jun 30, 2024
3787ea9
Intentionally delaying in MavenDependenciesListCheck to see if same e…
Rd4dev Jun 30, 2024
7ad2668
Importing kotlin coroutines
Rd4dev Jun 30, 2024
876152d
Tried delaying in MavenDependenciesCheckTest and that still passes
Rd4dev Jun 30, 2024
0e99588
Testing timeouts
Rd4dev Jun 30, 2024
67e5fb9
Adding withTimeout to see if it can allow the coroutine to run upto t…
Rd4dev Jun 30, 2024
35e79da
Using longCommandExecutor
Rd4dev Jun 30, 2024
2abf259
Adding --test_timeout flag to bazel test run
Rd4dev Jun 30, 2024
3123047
Reverting to old sample test removing fibonacci test
Rd4dev Jun 30, 2024
c6cf052
Fixed the testRunCoverage_invalidFormat_throwsException by updating t…
Rd4dev Jun 30, 2024
f967850
Bumping up the default processTimeout for RunCoverage to 20 MINUTES
Rd4dev Jun 30, 2024
f1f24f0
Fixed ignoreCaseHTMLArgument test case with proper file creation and …
Rd4dev Jul 1, 2024
935662f
Fixed lint checks for max line length
Rd4dev Jul 1, 2024
eab7f1a
Fixed lint checks for max line length
Rd4dev Jul 1, 2024
4526517
Setting a timeout of 600seconds on both bazel tests and processTimeout
Rd4dev Jul 1, 2024
8ec6b7c
Adding --test_timeout to coverage executor
Rd4dev Jul 1, 2024
fe642a6
Reverting the addition of timeout in bazel execute as that wasn't ref…
Rd4dev Jul 1, 2024
f92e821
Remove redundant code and clean up
Rd4dev Jul 1, 2024
7132b7a
Fixed Lint checks on redundant brances and spaces
Rd4dev Jul 1, 2024
5cffdc4
Fixed testRunCoverage_localTestsMarkdownFormat_returnsCoverageData te…
Rd4dev Jul 1, 2024
e38c940
Fix testRunCoverage_ignoreCaseHTMLArgument_returnsCoverageData test w…
Rd4dev Jul 1, 2024
a136d86
Merge branch 'develop' of https://github.com/Rd4dev/oppia-android int…
Rd4dev Jul 1, 2024
073599d
Added print statment for exemption test file scenario
Rd4dev Jul 5, 2024
fecb7d9
Merge branch 'develop' of https://github.com/Rd4dev/oppia-android int…
Rd4dev Jul 5, 2024
f9d1910
Fix Test file exemption test case and simplified print and return sta…
Rd4dev Jul 5, 2024
2e47173
Fix static check - needless blank line
Rd4dev Jul 5, 2024
a724461
Calculate an aggregated coverage report for many : one test target files
Rd4dev Jul 6, 2024
5f19114
Generating reports with aggregated coverage report instead of list of…
Rd4dev Jul 6, 2024
9f9f9c6
Updated tests for multiple test target and restyles/formatted the htm…
Rd4dev Jul 6, 2024
5f9ae7a
Code cleanup - removed debugging statments, kept the mock multi cover…
Rd4dev Jul 6, 2024
45067f7
Code cleanup and fix lint checks for missing spaces
Rd4dev Jul 6, 2024
b3e4c0f
Updated the visibility of the calculateAggregateCoverageReport function
Rd4dev Jul 6, 2024
2bca7e0
Fix Lint check max line lenght exceeded
Rd4dev Jul 6, 2024
c367957
Triggering CI due to error with repo fetching and insufficient write …
Rd4dev Jul 6, 2024
1929c74
Retriggering CI builds as the test pass locally and suspecting any do…
Rd4dev Jul 6, 2024
c5c11f6
Retriggering CI builds :/ just to see if the issue still persists
Rd4dev Jul 7, 2024
2ac7b04
Fixed the asynchronous flow, which was earlier not actually running a…
Rd4dev Jul 7, 2024
5a57677
Fix Lint check, code clean up and removed the static test targets
Rd4dev Jul 7, 2024
a09057b
Added missed Deferred import
Rd4dev Jul 7, 2024
49b8e0f
Moving the coverage analysis to a else condition removing return
Rd4dev Jul 7, 2024
179e8a7
Replaced the TwoSum sample test class name with AddNums
Rd4dev Jul 7, 2024
f82c35c
Fix Lint check max line length exceeded
Rd4dev Jul 7, 2024
c38f2e8
Updated sha hash value as the sample test class name was changed
Rd4dev Jul 7, 2024
a811947
Retriggering CI builds as latest build crashed or didn't report properly
Rd4dev Jul 7, 2024
e784657
Used kotlin idiomatic way to check for requirements and corrected Cam…
Rd4dev Jul 9, 2024
56809bf
Your commit message here
Rd4dev Jul 9, 2024
48c9d1b
Retriggering ci checks to see if the error on downloading remote jdk …
Rd4dev Jul 10, 2024
4c87573
Specifying jdk version for TestBazelWorkspace build to see if this is…
Rd4dev Jul 10, 2024
3d810b2
Update TestBazelWorkspace tests to include jdk version in the bazelrc…
Rd4dev Jul 10, 2024
595e9df
Fix Lint checks on indentation
Rd4dev Jul 10, 2024
4bc533f
Refactored execute's return value to unit
Rd4dev Jul 11, 2024
138a141
Reverting --test_timeout flag to see other possible fixes
Rd4dev Jul 11, 2024
75e28e2
Add size large to RunCoverageTest to set timeout to 900 seconds
Rd4dev Jul 11, 2024
aaf3caf
Resolve merge conflict after test timeout and fetch error fixes in ed…
Rd4dev Jul 12, 2024
d3eb372
Updated processTimeout to set as standard 5 minutes and moved outCont…
Rd4dev Jul 12, 2024
9b5995e
Merge branch 'code_coverage_fix_edge_cases' of https://github.com/opp…
Rd4dev Jul 12, 2024
6710f66
Retriggering since localTestHtmlFormat pass locally and to confirm if…
Rd4dev Jul 12, 2024
756bed8
Adding shard_count to see if that is making any difference
Rd4dev Jul 12, 2024
ab60123
Addition of dividing tests with shards did help with ci checks, now r…
Rd4dev Jul 12, 2024
d25ea9c
Adding back shards since that significantly lessens the test run time…
Rd4dev Jul 12, 2024
8802b27
Merge branch 'code_coverage_fix_edge_cases' of https://github.com/opp…
Rd4dev Jul 12, 2024
66a387e
Merge branch 'develop' of https://github.com/Rd4dev/oppia-android int…
Rd4dev Jul 13, 2024
50574ae
Merge branch 'code_coverage_fix_edge_cases' of https://github.com/opp…
Rd4dev Jul 13, 2024
f170487
Changed base branch to develop in the repo and added reference comment
Rd4dev Jul 13, 2024
8955775
Merge branch 'develop' of https://github.com/Rd4dev/oppia-android int…
Rd4dev Jul 24, 2024
10d9acd
Updated the sharedAndLocalTest case to sync in with updated multi tar…
Rd4dev Jul 24, 2024
be8ff1c
Removing the mock data for multi target aggregation implementation
Rd4dev Jul 26, 2024
7d76b89
Added test cases for coverage data missing and retrieval failure cases
Rd4dev Jul 26, 2024
c2eddfb
Trigger Build since ExplorationActiveTimeControllerTest seems to fail
Rd4dev Jul 26, 2024
ffe7768
Removed asynchronous flow in both source and test files for CoverageR…
Rd4dev Jul 28, 2024
8e88c35
Renaming the runWithCoverageAsync to runCoverageForTestTarget, update…
Rd4dev Jul 28, 2024
c1f012c
Trying to find the coverage path with regex pattern as they mismatch
Rd4dev Jul 29, 2024
aa0de7f
Save lobby before switching to a side branch to test permission error…
Rd4dev Jul 29, 2024
800ccda
Trying to hit a certain line n number of times in different ways yet …
Rd4dev Jul 29, 2024
ad611b8
Reverted changes with sample test data that were added for testing pu…
Rd4dev Jul 29, 2024
84c5336
Reverting the shard count to 4 which was introducing while testing
Rd4dev Jul 29, 2024
5561b4e
Merge branch 'develop' of https://github.com/Rd4dev/oppia-android int…
Rd4dev Jul 29, 2024
07184ee
Lint fixes for exceeding max line length
Rd4dev Jul 29, 2024
3974ce0
Fixes Missing Coverage Data Test Case
Rd4dev Jul 29, 2024
360dc4b
Fixed the retrieve coverage failure test case :) by reproducing the s…
Rd4dev Jul 30, 2024
565f2f5
Clean up and refactored the test cases
Rd4dev Jul 30, 2024
05a007b
Updating the coverage missing test case while removing the job and re…
Rd4dev Jul 31, 2024
a3a661e
Clean up and changed the test case names to be more specific on what …
Rd4dev Jul 31, 2024
8a12cf4
Added validation to ensure exactly one unique value of filePath and f…
Rd4dev Jul 31, 2024
e72179a
Clean up of aggreagation code and replaced conditional error statment…
Rd4dev Jul 31, 2024
f00ebc6
Removed the mock data used for coverage report with n:1 file target a…
Rd4dev Jul 31, 2024
824c406
Reference point for mock data with new repeated bazel test target pro…
Rd4dev Aug 1, 2024
5ee99c0
Clean up and simplification of usage of single usage entry
Rd4dev Aug 1, 2024
372ae95
Fix lint checks and failing test case with update to the proto strucu…
Rd4dev Aug 1, 2024
6499311
Added missing import for BazelTestTarget
Rd4dev Aug 1, 2024
5e528fe
Merge branch 'develop' of https://github.com/Rd4dev/oppia-android int…
Rd4dev Aug 6, 2024
e72eec3
Added the copy of local and shared test to ensure the multiple test f…
Rd4dev Aug 6, 2024
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 @@ -142,7 +142,8 @@ class BazelClient(private val rootDirectory: File, private val commandExecutor:
* or null if the coverage data file could not be parsed
*/
fun runCoverageForTestTarget(bazelTestTarget: String): List<String>? {
val computeInstrumentation = bazelTestTarget.split("/").let { "//${it[2]}/..." }
val instrumentation = bazelTestTarget.split(":")[0]
val computeInstrumentation = instrumentation.split("/").let { "//${it[2]}/..." }
val coverageCommandOutputLines = executeBazelCommand(
"coverage",
bazelTestTarget,
Expand All @@ -159,7 +160,7 @@ class BazelClient(private val rootDirectory: File, private val commandExecutor:
val match = regex.find(line)
val extractedPath = match?.value?.substringAfterLast(",")?.trim()
if (extractedPath != null) {
println("Parsed Coverage Data File: $extractedPath")
println("Raw Coverage Data: $extractedPath")
return extractedPath
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,21 @@ import java.io.File
* Class responsible for generating rich text coverage report.
*
* @param repoRoot the root directory of the repository
* @param coverageReportList the list of coverage data proto
* @param coverageReport the coverage data proto
* @param reportFormat the format in which the report will be generated
*/
class CoverageReporter(
private val repoRoot: String,
private val coverageReportList: List<CoverageReport>,
private val coverageReport: CoverageReport,
private val reportFormat: ReportFormat,
) {
private val computedCoverageRatio = computeCoverageRatio()
private val formattedCoveragePercentage = "%.2f".format(computedCoverageRatio * 100)

private val filePath = coverageReportList.firstOrNull()?.filePath ?: "Unknown"
private val filePath = coverageReport.filePath

private val totalLinesFound = coverageReportList.getOrNull(0)?.linesFound ?: 0
private val totalLinesHit = coverageReportList.getOrNull(0)?.linesHit ?: 0
private val totalLinesFound = coverageReport.linesFound
private val totalLinesHit = coverageReport.linesHit

/**
* Generates a rich text report for the analysed coverage data based on the specified format.
Expand All @@ -32,7 +32,7 @@ class CoverageReporter(
* and the second value is the generated report text
*/
fun generateRichTextReport(): Pair<Float, String> {
println("report format: $reportFormat")
println("Report format: $reportFormat")
return when (reportFormat) {
ReportFormat.MARKDOWN -> generateMarkdownReport()
ReportFormat.HTML -> generateHtmlReport()
Expand Down Expand Up @@ -66,6 +66,7 @@ class CoverageReporter(
<style>
body {
font-family: Arial, sans-serif;
font-size: 12px;
line-height: 1.6;
padding: 20px;
}
Expand All @@ -78,24 +79,20 @@ class CoverageReporter(
padding: 8px;
margin-left: 20px;
text-align: left;
border-bottom: 1px solid #fdfdfd;
white-space: pre-wrap;
border-bottom: 1px solid #e3e3e3;
}
.line-number-col {
width: 2%;
width: 4%;
}
.line-number-row {
border-right: 1px dashed #000000
border-right: 1px solid #ababab
}
.source-code-col {
width: 98%;
width: 96%;
}
.covered-line, .not-covered-line, .uncovered-line {
white-space: pre-wrap;
word-wrap: break-word;
box-sizing: border-box;
border-radius: 4px;
padding: 2px 8px 2px 4px;
display: inline-block;
/*white-space: pre-wrap;*/
}
.covered-line {
background-color: #c8e6c9; /* Light green */
Expand All @@ -104,7 +101,7 @@ class CoverageReporter(
background-color: #ffcdd2; /* Light red */
}
.uncovered-line {
background-color: #f1f1f1; /* light gray */
background-color: #f7f7f7; /* light gray */
}
.coverage-summary {
margin-bottom: 20px;
Expand All @@ -118,7 +115,6 @@ class CoverageReporter(
text-align: center;
}
.summary-box {
background-color: #f0f0f0;
border: 1px solid #ccc;
border-radius: 8px;
padding: 10px;
Expand Down Expand Up @@ -152,12 +148,12 @@ class CoverageReporter(
background-color: #ffcdd2; /* Light red */
}
@media screen and (max-width: 768px) {
body {
padding: 10px;
}
table {
width: auto;
}
body {
padding: 10px;
}
table {
width: auto;
}
}
</style>
</head>
Expand Down Expand Up @@ -189,12 +185,11 @@ class CoverageReporter(
""".trimIndent()

val fileContent = File(repoRoot, filePath).readLines()
val coverageMap = coverageReportList
.firstOrNull()?.coveredLineList?.associateBy { it.lineNumber }
val coverageMap = coverageReport.coveredLineList.associateBy { it.lineNumber }

fileContent.forEachIndexed { index, line ->
val lineNumber = index + 1
val lineClass = when (coverageMap?.get(lineNumber)?.coverage) {
val lineClass = when (coverageMap.get(lineNumber)?.coverage) {
Coverage.FULL -> "covered-line"
Coverage.NONE -> "not-covered-line"
else -> "uncovered-line"
Expand All @@ -218,9 +213,8 @@ class CoverageReporter(
}

private fun computeCoverageRatio(): Float {
val report = coverageReportList.getOrNull(0)
return if (report != null && report.linesFound != 0) {
report.linesHit.toFloat() / report.linesFound.toFloat()
return if (coverageReport.linesFound != 0) {
coverageReport.linesHit.toFloat() / coverageReport.linesFound.toFloat()
} else {
0f
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package org.oppia.android.scripts.coverage

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async
import org.oppia.android.scripts.common.BazelClient
import org.oppia.android.scripts.common.CommandExecutor
import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher
import org.oppia.android.scripts.proto.BazelTestTarget
import org.oppia.android.scripts.proto.Coverage
import org.oppia.android.scripts.proto.CoverageReport
import org.oppia.android.scripts.proto.CoveredLine
Expand Down Expand Up @@ -34,15 +32,13 @@ class CoverageRunner(
* @param bazelTestTarget Bazel test target to analyze coverage
* @return a deferred value that contains the coverage data
*/
fun runWithCoverageAsync(
fun retrieveCoverageDataForTestTarget(
bazelTestTarget: String
): Deferred<CoverageReport> {
return CoroutineScope(scriptBgDispatcher).async {
val coverageResult = retrieveCoverageResult(bazelTestTarget)
?: error("Failed to retrieve coverage result for $bazelTestTarget")
): CoverageReport {
val coverageResult = retrieveCoverageResult(bazelTestTarget)
?: error("Failed to retrieve coverage result for $bazelTestTarget")

coverageDataFileLines(coverageResult, bazelTestTarget)
}
return coverageDataFileLines(coverageResult, bazelTestTarget)
}

private fun retrieveCoverageResult(
Expand Down Expand Up @@ -93,8 +89,12 @@ class CoverageRunner(
val file = File(repoRoot, filePath)
val fileSha1Hash = calculateSha1(file.absolutePath)

val bazelTestTargetName = BazelTestTarget.newBuilder()
.setTestTargetName(bazelTestTarget)
.build()

return CoverageReport.newBuilder()
.setBazelTestTarget(bazelTestTarget)
.addBazelTestTargets(bazelTestTargetName)
.setFilePath(filePath)
.setFileSha1Hash(fileSha1Hash)
.addAllCoveredLine(coveredLines)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package org.oppia.android.scripts.coverage

import kotlinx.coroutines.runBlocking
import org.oppia.android.scripts.common.BazelClient
import org.oppia.android.scripts.common.CommandExecutor
import org.oppia.android.scripts.common.CommandExecutorImpl
import org.oppia.android.scripts.common.ScriptBackgroundCoroutineDispatcher
import org.oppia.android.scripts.proto.Coverage
import org.oppia.android.scripts.proto.CoverageReport
import org.oppia.android.scripts.proto.CoveredLine
import org.oppia.android.scripts.proto.TestFileExemptions
import java.io.File
import java.util.concurrent.TimeUnit
Expand All @@ -27,7 +28,7 @@ import java.util.concurrent.TimeUnit
* utility/src/main/java/org/oppia/android/util/parser/math/MathModel.kt format=HTML
* Example with custom process timeout:
* bazel run //scripts:run_coverage -- $(pwd)
* utility/src/main/java/org/oppia/android/util/parser/math/MathModel.kt processTimeout=10
* utility/src/main/java/org/oppia/android/util/parser/math/MathModel.kt processTimeout=15
*
*/
fun main(vararg args: String) {
Expand All @@ -46,8 +47,8 @@ fun main(vararg args: String) {

val reportOutputPath = getReportOutputPath(repoRoot, filePath, reportFormat)

if (!File(repoRoot, filePath).exists()) {
error("File doesn't exist: $filePath.")
check(File(repoRoot, filePath).exists()) {
"File doesn't exist: $filePath."
}

ScriptBackgroundCoroutineDispatcher().use { scriptBgDispatcher ->
Expand Down Expand Up @@ -110,22 +111,21 @@ class RunCoverage(

if (filePath in testFileExemptionList) {
println("This file is exempted from having a test file; skipping coverage check.")
return
}

val testFilePaths = findTestFile(repoRoot, filePath)
if (testFilePaths.isEmpty()) {
error("No appropriate test file found for $filePath")
}
} else {
val testFilePaths = findTestFiles(repoRoot, filePath)
check(testFilePaths.isNotEmpty()) {
"No appropriate test file found for $filePath"
}

val testTargets = bazelClient.retrieveBazelTargets(testFilePaths)
val testTargets = bazelClient.retrieveBazelTargets(testFilePaths)

val coverageReports = testTargets.mapNotNull { testTarget ->
runCoverageForTarget(testTarget)
}
val coverageReports = testTargets.map { testTarget ->
CoverageRunner(rootDirectory, scriptBgDispatcher, commandExecutor)
.retrieveCoverageDataForTestTarget(testTarget.removeSuffix(".kt"))
}

coverageReports.takeIf { it.isNotEmpty() }?.run {
val reporter = CoverageReporter(repoRoot, this, reportFormat)
val aggregatedCoverageReport = calculateAggregateCoverageReport(coverageReports)
val reporter = CoverageReporter(repoRoot, aggregatedCoverageReport, reportFormat)
val (computedCoverageRatio, reportText) = reporter.generateRichTextReport()

File(reportOutputPath).apply {
Expand All @@ -137,19 +137,50 @@ class RunCoverage(
println("\nComputed Coverage Ratio is: $computedCoverageRatio")
println("\nGenerated report at: $reportOutputPath\n")
}
} ?: println("No coverage reports generated.")
}

private fun runCoverageForTarget(testTarget: String): CoverageReport {
return runBlocking {
CoverageRunner(rootDirectory, scriptBgDispatcher, commandExecutor)
.runWithCoverageAsync(testTarget.removeSuffix(".kt"))
.await()
println("COVERAGE ANALYSIS COMPLETED.")
}
}
}

private fun findTestFile(repoRoot: String, filePath: String): List<String> {
private fun calculateAggregateCoverageReport(
coverageReports: List<CoverageReport>
): CoverageReport {
fun aggregateCoverage(coverages: List<Coverage>): Coverage {
return coverages.find { it == Coverage.FULL } ?: Coverage.NONE
}

val groupedCoverageReports = coverageReports.groupBy {
Pair(it.filePath, it.fileSha1Hash)
}

val (key, reports) = groupedCoverageReports.entries.single()
val (filePath, fileSha1Hash) = key

val allBazelTestTargets = reports.flatMap { it.bazelTestTargetsList }
val allCoveredLines = reports.flatMap { it.coveredLineList }
val groupedCoveredLines = allCoveredLines.groupBy { it.lineNumber }
val aggregatedCoveredLines = groupedCoveredLines.map { (lineNumber, coveredLines) ->
CoveredLine.newBuilder()
.setLineNumber(lineNumber)
.setCoverage(aggregateCoverage(coveredLines.map { it.coverage }))
.build()
}
BenHenning marked this conversation as resolved.
Show resolved Hide resolved

val totalLinesFound = aggregatedCoveredLines.size
val totalLinesHit = aggregatedCoveredLines.count { it.coverage == Coverage.FULL }

return CoverageReport.newBuilder()
.addAllBazelTestTargets(allBazelTestTargets)
.setFilePath(filePath)
.setFileSha1Hash(fileSha1Hash)
.addAllCoveredLine(aggregatedCoveredLines)
.setLinesFound(totalLinesFound)
.setLinesHit(totalLinesHit)
.build()
}

private fun findTestFiles(repoRoot: String, filePath: String): List<String> {
val possibleTestFilePaths = when {
filePath.startsWith("scripts/") -> {
listOf(filePath.replace("/java/", "/javatests/").replace(".kt", "Test.kt"))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ option java_multiple_files = true;
// Bazel coverage execution.
message CoverageReport {
// The test target for which the coverage report is generated.
string bazel_test_target = 1;
repeated BazelTestTarget bazel_test_targets = 1;
// The relative path of the covered file.
string file_path = 2;
// SHA-1 hash of the file content at the time of report (to guard against changes).
Expand All @@ -22,6 +22,12 @@ message CoverageReport {
int32 lines_hit = 6;
}

// Represents a single bazel test target corresponding to a test file.
message BazelTestTarget {
// The name of the bazel test target.
string test_target_name = 1;
}

// Information about a single line that was covered during the tests.
message CoveredLine {
// The line number of the covered line.
Expand All @@ -33,8 +39,8 @@ message CoveredLine {
enum Coverage {
// Coverage status is unspecified.
UNSPECIFIED = 0;
// The line, branch, or function is fully covered, ie. executed atleast once.
// The line is fully covered in a test, that is, it was executed at least once.
FULL = 1;
// The line, branch, or function is not covered at all.
// The line is not covered at all, that is, it was never executed during a test.
NONE = 2;
}
Loading
Loading