diff --git a/scalac-scoverage-plugin/src/main/scala/scoverage/Serializer.scala b/scalac-scoverage-plugin/src/main/scala/scoverage/Serializer.scala index 39e7da80..9cfae5a7 100644 --- a/scalac-scoverage-plugin/src/main/scala/scoverage/Serializer.scala +++ b/scalac-scoverage-plugin/src/main/scala/scoverage/Serializer.scala @@ -22,6 +22,15 @@ object Serializer { } def serialize(coverage: Coverage, writer: Writer): Unit = { + // Used for getting the relative filepath for [stmt.location.sourcePath] + // instead of the canonical path. This is required to make it work with + // remoting or in a distributed environment. + def getRelativePath(filePath: String): String = { + val base = new File(".").getCanonicalFile.toPath + val relPath = base.relativize(new File(filePath).getCanonicalFile.toPath) + relPath.toString + } + def writeHeader(writer: Writer): Unit = { writer.write(s"""# Coverage data, format version: 2.0 |# Statement data: @@ -48,7 +57,7 @@ object Serializer { def writeStatement(stmt: Statement, writer: Writer): Unit = { writer.write(s"""${stmt.id} - |${stmt.location.sourcePath} + |${getRelativePath(stmt.location.sourcePath)} |${stmt.location.packageName} |${stmt.location.className} |${stmt.location.classType} @@ -79,6 +88,13 @@ object Serializer { } def deserialize(lines: Iterator[String]): Coverage = { + // To integrate it smoothly with rest of the report writers, + // it is necessary to again convert [sourcePath] into a + // canonical one. + def getAbsolutePath(filePath: String): String = { + (new File(filePath)).getCanonicalPath + } + def toStatement(lines: Iterator[String]): Statement = { val id: Int = lines.next.toInt val sourcePath = lines.next @@ -87,7 +103,7 @@ object Serializer { val classType = lines.next val fullClassName = lines.next val method = lines.next - val loc = Location(packageName, className, fullClassName, ClassType.fromString(classType), method, sourcePath) + val loc = Location(packageName, className, fullClassName, ClassType.fromString(classType), method, getAbsolutePath(sourcePath)) val start: Int = lines.next.toInt val end: Int = lines.next.toInt val lineNo: Int = lines.next.toInt diff --git a/scalac-scoverage-plugin/src/test/scala/scoverage/SerializerTest.scala b/scalac-scoverage-plugin/src/test/scala/scoverage/SerializerTest.scala index f67367c8..41bca290 100644 --- a/scalac-scoverage-plugin/src/test/scala/scoverage/SerializerTest.scala +++ b/scalac-scoverage-plugin/src/test/scala/scoverage/SerializerTest.scala @@ -1,6 +1,7 @@ package scoverage import java.io.StringWriter +import java.io.File import org.scalatest.{OneInstancePerTest, FunSuite} @@ -97,7 +98,105 @@ class SerializerTest extends FunSuite with OneInstancePerTest { |\f |""".stripMargin.split("\n").iterator val statements = List(Statement( - Location("org.scoverage", "test", "org.scoverage.test", ClassType.Trait, "mymethod", "mypath"), + Location("org.scoverage", "test", "org.scoverage.test", ClassType.Trait, "mymethod", new File("mypath").getCanonicalPath), + 14, 100, 200, 4, "def test : String", "test", "DefDef", true, 1 + )) + val coverage = Serializer.deserialize(input) + assert(statements === coverage.statements.toList) + } + + test("coverage should serialize sourcePath relatively") { + val coverage = Coverage() + coverage.add( + Statement( + Location("org.scoverage", "test", "org.scoverage.test", ClassType.Trait, "mymethod", new File(".").getCanonicalPath + File.separator + "mypath"), + 14, 100, 200, 4, "def test : String", "test", "DefDef", true, 1 + ) + ) + val expected = s"""# Coverage data, format version: 2.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) + |# '\f' sign + |# ------------------------------------------ + |14 + |mypath + |org.scoverage + |test + |Trait + |org.scoverage.test + |mymethod + |100 + |200 + |4 + |test + |DefDef + |true + |1 + |false + |def test : String + |\f + |""".stripMargin + val writer = new StringWriter()//TODO-use UTF-8 + val actual = Serializer.serialize(coverage, writer) + assert(expected === writer.toString) + } + + test("coverage should deserialize sourcePath by prefixing cwd") { + val input = s"""# Coverage data, format version: 2.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) + |# '\f' sign + |# ------------------------------------------ + |14 + |mypath + |org.scoverage + |test + |Trait + |org.scoverage.test + |mymethod + |100 + |200 + |4 + |test + |DefDef + |true + |1 + |false + |def test : String + |\f + |""".stripMargin.split("\n").iterator + val statements = List(Statement( + Location("org.scoverage", "test", "org.scoverage.test", ClassType.Trait, "mymethod", new File(".").getCanonicalPath + File.separator + "mypath"), 14, 100, 200, 4, "def test : String", "test", "DefDef", true, 1 )) val coverage = Serializer.deserialize(input)