Skip to content

Commit

Permalink
Backport "Fix the issue with coverage inside of a TypeApply" to LTS (#…
Browse files Browse the repository at this point in the history
…19233)

Backports #18420 to the LTS branch.

PR submitted by the release tooling.
[skip ci]
  • Loading branch information
Kordyjan committed Dec 13, 2023
2 parents 0b33d5b + e8d1bad commit 234d0f2
Show file tree
Hide file tree
Showing 6 changed files with 184 additions and 2 deletions.
Expand Up @@ -234,8 +234,8 @@ class InstrumentCoverage extends MacroTransform with IdentityDenotTransformer:
val InstrumentedParts(pre, coverageCall, expr) = tryInstrument(fun)

if coverageCall.isEmpty then
// `fun` cannot be instrumented, and `args` is a type so we keep this tree as it is
tree
// `fun` cannot be instrumented and `args` is a type, but `expr` may have been transformed
cpy.TypeApply(tree)(expr, args)
else
// expr[T] shouldn't be transformed to:
// {invoked(...), expr}[T]
Expand Down
30 changes: 30 additions & 0 deletions compiler/test/dotty/tools/dotc/coverage/CoverageTests.scala
Expand Up @@ -17,6 +17,8 @@ import scala.language.unsafeNulls
import scala.collection.mutable.Buffer
import dotty.tools.dotc.util.DiffUtil

import java.util.stream.Collectors

@Category(Array(classOf[BootstrappedOnlyTests]))
class CoverageTests:
import CoverageTests.{*, given}
Expand Down Expand Up @@ -61,6 +63,26 @@ class CoverageTests:
val instructions = FileDiff.diffMessage(expectFile.toString, targetFile.toString)
fail(s"Coverage report differs from expected data.\n$instructions")

// measurement files only exist in the "run" category
// as these are generated at runtime by the scala.runtime.coverage.Invoker
val expectMeasurementFile = path.resolveSibling(s"$fileName.measurement.check")
if run && Files.exists(expectMeasurementFile) then

// Note that this assumes that the test invoked was single threaded,
// if that is not the case then this will have to be adjusted
val targetMeasurementFile = findMeasurementFile(targetDir)

if updateCheckFiles then
Files.copy(targetMeasurementFile, expectMeasurementFile, StandardCopyOption.REPLACE_EXISTING)

else
val targetMeasurementFile = findMeasurementFile(targetDir)
val expectedMeasurements = fixWindowsPaths(Files.readAllLines(expectMeasurementFile).asScala)
val obtainedMeasurements = fixWindowsPaths(Files.readAllLines(targetMeasurementFile).asScala)
if expectedMeasurements != obtainedMeasurements then
val instructions = FileDiff.diffMessage(expectMeasurementFile.toString, targetMeasurementFile.toString)
fail(s"Measurement report differs from expected data.\n$instructions")
()
})

/** Generates the coverage report for the given input file, in a temporary directory. */
Expand All @@ -75,6 +97,14 @@ class CoverageTests:
test.checkCompile()
target

private def findMeasurementFile(targetDir: Path): Path = {
val allFilesInTarget = Files.list(targetDir).collect(Collectors.toList).asScala
allFilesInTarget.filter(_.getFileName.toString.startsWith("scoverage.measurements.")).headOption.getOrElse(
throw new AssertionError(s"Expected to find measurement file in targetDir [${targetDir}] but none were found.")
)
}


object CoverageTests extends ParallelTesting:
import scala.concurrent.duration.*

Expand Down
1 change: 1 addition & 0 deletions tests/coverage/run/type-apply/test.check
@@ -0,0 +1 @@
List(List(1), List(2), List(3))
7 changes: 7 additions & 0 deletions tests/coverage/run/type-apply/test.measurement.check
@@ -0,0 +1,7 @@
6
1
3
2
5
4
0
5 changes: 5 additions & 0 deletions tests/coverage/run/type-apply/test.scala
@@ -0,0 +1,5 @@
@main
def Test: Unit =
// verifies a problematic case where the TypeApply instrumentation was added to the coverage file,
// but was never marked as invoked
println(List(1,2,3).map(a => List(a)))
139 changes: 139 additions & 0 deletions tests/coverage/run/type-apply/test.scoverage.check
@@ -0,0 +1,139 @@
# Coverage data, format version: 3.0
# Statement data:
# - id
# - source path
# - package name
# - class name
# - class type (Class, Object or Trait)
# - full class name
# - method name
# - start offset
# - end offset
# - line number
# - symbol name
# - tree name
# - is branch
# - invocations count
# - is ignored
# - description (can be multi-line)
# ' ' sign
# ------------------------------------------
0
type-apply/test.scala
<empty>
test$package$
Object
<empty>.test$package$
Test
163
201
4
println
Apply
false
0
false
println(List(1,2,3).map(a => List(a)))

1
type-apply/test.scala
<empty>
test$package$
Object
<empty>.test$package$
Test
171
200
4
map
Apply
false
0
false
List(1,2,3).map(a => List(a))

2
type-apply/test.scala
<empty>
test$package$
Object
<empty>.test$package$
Test
171
182
4
apply
Apply
false
0
false
List(1,2,3)

3
type-apply/test.scala
<empty>
test$package$
Object
<empty>.test$package$
Test
171
175
4
List
Ident
false
0
false
List

4
type-apply/test.scala
<empty>
test$package$
Object
<empty>.test$package$
$anonfun
192
199
4
apply
Apply
false
0
false
List(a)

5
type-apply/test.scala
<empty>
test$package$
Object
<empty>.test$package$
$anonfun
192
196
4
List
Ident
false
0
false
List

6
type-apply/test.scala
<empty>
test$package$
Object
<empty>.test$package$
Test
0
14
1
Test
DefDef
false
0
false
@main\ndef Test

0 comments on commit 234d0f2

Please sign in to comment.