diff --git a/scalac-scoverage-plugin/src/main/scala/scoverage/Constants.scala b/scalac-scoverage-plugin/src/main/scala/scoverage/Constants.scala index 3259e3b2..e1b1e57e 100644 --- a/scalac-scoverage-plugin/src/main/scala/scoverage/Constants.scala +++ b/scalac-scoverage-plugin/src/main/scala/scoverage/Constants.scala @@ -2,7 +2,7 @@ package scoverage object Constants { // the file that contains the statement mappings - val CoverageFileName = "scoverage.coverage.xml" + val CoverageFileName = "scoverage.coverage" // the final scoverage report val XMLReportFilename = "scoverage.xml" val XMLReportFilenameWithDebug = "scoverage-debug.xml" diff --git a/scalac-scoverage-plugin/src/main/scala/scoverage/Serializer.scala b/scalac-scoverage-plugin/src/main/scala/scoverage/Serializer.scala index 4d0d4067..39e7da80 100644 --- a/scalac-scoverage-plugin/src/main/scala/scoverage/Serializer.scala +++ b/scalac-scoverage-plugin/src/main/scala/scoverage/Serializer.scala @@ -1,9 +1,8 @@ package scoverage -import java.io._ +import java.io.{BufferedWriter, File, FileOutputStream, OutputStreamWriter, Writer} -import scala.io.Source -import scala.xml.{Utility, XML} +import scala.io.{Codec, Source} object Serializer { @@ -12,147 +11,109 @@ object Serializer { // Write out coverage data to given file. def serialize(coverage: Coverage, file: File): Unit = { - val writer = new BufferedWriter(new FileWriter(file)) - serialize(coverage, writer) - writer.close() + val writer: Writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), Codec.UTF8.name)) + try { + serialize(coverage, writer) + } + finally { + writer.flush() + writer.close() + } } def serialize(coverage: Coverage, writer: Writer): Unit = { + def writeHeader(writer: Writer): Unit = { + writer.write(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 + |# ------------------------------------------ + |""".stripMargin) + } + def writeStatement(stmt: Statement, writer: Writer): Unit = { - writer.write { - val xml = - - {stmt.source} - - - {stmt.location.packageName} - - - {stmt.location.className} - - - {stmt.location.classType.toString} - - - {stmt.location.fullClassName} - - - {stmt.location.method} - - - {stmt.location.sourcePath} - - - {stmt.id.toString} - - - {stmt.start.toString} - - - {stmt.end.toString} - - - {stmt.line.toString} - - - {escape(stmt.desc)} - - - {escape(stmt.symbolName)} - - - {escape(stmt.treeName)} - - - {stmt.branch.toString} - - - {stmt.count.toString} - - - {stmt.ignored.toString} - - - Utility.trim(xml) + "\n" - } + writer.write(s"""${stmt.id} + |${stmt.location.sourcePath} + |${stmt.location.packageName} + |${stmt.location.className} + |${stmt.location.classType} + |${stmt.location.fullClassName} + |${stmt.location.method} + |${stmt.start} + |${stmt.end} + |${stmt.line} + |${stmt.symbolName} + |${stmt.treeName} + |${stmt.branch} + |${stmt.count} + |${stmt.ignored} + |${stmt.desc} + |\f + |""".stripMargin) } - writer.write("\n") - coverage.statements.foreach(stmt => writeStatement(stmt, writer)) - writer.write("") + + writeHeader(writer) + coverage.statements.toSeq.sortBy(_.id).foreach(stmt => writeStatement(stmt, writer)) } def coverageFile(dataDir: File): File = coverageFile(dataDir.getAbsolutePath) def coverageFile(dataDir: String): File = new File(dataDir, Constants.CoverageFileName) - def deserialize(str: String): Coverage = { - val xml = XML.loadString(str) - val statements = xml \ "statement" map (node => { - val source = (node \ "source").text - val count = (node \ "count").text.toInt - val ignored = (node \ "ignored").text.toBoolean - val branch = (node \ "branch").text.toBoolean - val _package = (node \ "package").text - val _class = (node \ "class").text - val fullClassName = (node \ "fullClassName").text - val method = (node \ "method").text - val path = (node \ "path").text - val treeName = (node \ "treeName").text - val symbolName = (node \ "symbolName").text - val id = (node \ "id").text.toInt - val line = (node \ "line").text.toInt - val desc = (node \ "description").text - val start = (node \ "start").text.toInt - val end = (node \ "end").text.toInt - val classType = (node \ "classType").text match { - case "Trait" => ClassType.Trait - case "Object" => ClassType.Object - case _ => ClassType.Class - } - Statement(source, - Location(_package, _class, fullClassName, classType, method, path), - id, - start, - end, - line, - desc, - symbolName, - treeName, branch, count, ignored) - }) - - val coverage = Coverage() - for ( statement <- statements ) - if (statement.ignored) coverage.addIgnoredStatement(statement) - else coverage.add(statement) - coverage - } - def deserialize(file: File): Coverage = { - val str = Source.fromFile(file).mkString - deserialize(str) + deserialize(Source.fromFile(file)(Codec.UTF8).getLines) } - /** - * This method ensures that the output String has only - * valid XML unicode characters as specified by the - * XML 1.0 standard. For reference, please see - * the - * standard. This method will return an empty - * String if the input is null or empty. - * - * @param in The String whose non-valid characters we want to remove. - * @return The in String, stripped of non-valid characters. - * @see http://blog.mark-mclaren.info/2007/02/invalid-xml-characters-when-valid-utf8_5873.html - * - */ - def escape(in: String): String = { - val out = new StringBuilder() - for ( current <- Option(in).getOrElse("").toCharArray ) { - if ((current == 0x9) || (current == 0xA) || (current == 0xD) || - ((current >= 0x20) && (current <= 0xD7FF)) || - ((current >= 0xE000) && (current <= 0xFFFD)) || - ((current >= 0x10000) && (current <= 0x10FFFF))) - out.append(current) + def deserialize(lines: Iterator[String]): Coverage = { + def toStatement(lines: Iterator[String]): Statement = { + val id: Int = lines.next.toInt + val sourcePath = lines.next + val packageName = lines.next + val className = lines.next + val classType = lines.next + val fullClassName = lines.next + val method = lines.next + val loc = Location(packageName, className, fullClassName, ClassType.fromString(classType), method, sourcePath) + val start: Int = lines.next.toInt + val end: Int = lines.next.toInt + val lineNo: Int = lines.next.toInt + val symbolName: String = lines.next + val treeName: String = lines.next + val branch: Boolean = lines.next.toBoolean + val count: Int = lines.next.toInt + val ignored: Boolean = lines.next.toBoolean + val desc = lines.toList.mkString("\n") + Statement(loc, id, start, end, lineNo, desc, symbolName, treeName, branch, count, ignored) + } + + val headerFirstLine = lines.next + require(headerFirstLine == "# Coverage data, format version: 2.0", "Wrong file format") + + val linesWithoutHeader = lines.dropWhile(_.startsWith("#")) + val coverage = Coverage() + while (!linesWithoutHeader.isEmpty) { + val oneStatementLines = linesWithoutHeader.takeWhile(_ != "\f") + val statement = toStatement(oneStatementLines) + if (statement.ignored) + coverage.addIgnoredStatement(statement) + else + coverage.add(statement) } - out.mkString + coverage } + } diff --git a/scalac-scoverage-plugin/src/main/scala/scoverage/coverage.scala b/scalac-scoverage-plugin/src/main/scala/scoverage/coverage.scala index 6591c99e..dfe65258 100644 --- a/scalac-scoverage-plugin/src/main/scala/scoverage/coverage.scala +++ b/scalac-scoverage-plugin/src/main/scala/scoverage/coverage.scala @@ -109,8 +109,7 @@ case class MeasuredFile(source: String, statements: Iterable[Statement]) override def ignoredStatements: Iterable[Statement] = Seq() } -case class Statement(source: String, - location: Location, +case class Statement(location: Location, id: Int, start: Int, end: Int, @@ -121,6 +120,7 @@ case class Statement(source: String, branch: Boolean, var count: Int = 0, ignored: Boolean = false) extends java.io.Serializable { + def source = location.sourcePath def invoked(): Unit = count = count + 1 def isInvoked = count > 0 } diff --git a/scalac-scoverage-plugin/src/main/scala/scoverage/plugin.scala b/scalac-scoverage-plugin/src/main/scala/scoverage/plugin.scala index 609dcebc..ff8e148b 100644 --- a/scalac-scoverage-plugin/src/main/scala/scoverage/plugin.scala +++ b/scalac-scoverage-plugin/src/main/scala/scoverage/plugin.scala @@ -202,7 +202,6 @@ class ScoverageInstrumentationComponent(val global: Global, extraAfterPhase: Opt case Some(source) => val id = statementIds.incrementAndGet val statement = Statement( - source.path, location, id, safeStart(tree), diff --git a/scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageXmlReader.scala b/scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageXmlReader.scala index 75dedaeb..b104695b 100644 --- a/scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageXmlReader.scala +++ b/scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageXmlReader.scala @@ -43,7 +43,6 @@ object ScoverageXmlReader { id = id + 1 coverage add Statement( - source.text, location, id, start.text.toInt, diff --git a/scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageXmlWriter.scala b/scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageXmlWriter.scala index 7d3b8f90..33d63e10 100644 --- a/scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageXmlWriter.scala +++ b/scalac-scoverage-plugin/src/main/scala/scoverage/report/ScoverageXmlWriter.scala @@ -43,12 +43,12 @@ class ScoverageXmlWriter(sourceDirectories: Seq[File], outputDir: File, debug: B start={stmt.start.toString} end={stmt.end.toString} line={stmt.line.toString} - symbol={Serializer.escape(stmt.symbolName)} - tree={Serializer.escape(stmt.treeName)} + symbol={escape(stmt.symbolName)} + tree={escape(stmt.treeName)} branch={stmt.branch.toString} invocation-count={stmt.count.toString} ignored={stmt.ignored.toString}> - {Serializer.escape(stmt.desc)} + {escape(stmt.desc)} case false => } + /** + * This method ensures that the output String has only + * valid XML unicode characters as specified by the + * XML 1.0 standard. For reference, please see + * the + * standard. This method will return an empty + * String if the input is null or empty. + * + * @param in The String whose non-valid characters we want to remove. + * @return The in String, stripped of non-valid characters. + * @see http://blog.mark-mclaren.info/2007/02/invalid-xml-characters-when-valid-utf8_5873.html + * + */ + def escape(in: String): String = { + val out = new StringBuilder() + for ( current <- Option(in).getOrElse("").toCharArray ) { + if ((current == 0x9) || (current == 0xA) || (current == 0xD) || + ((current >= 0x20) && (current <= 0xD7FF)) || + ((current >= 0xE000) && (current <= 0xFFFD)) || + ((current >= 0x10000) && (current <= 0x10FFFF))) + out.append(current) + } + out.mkString + } } diff --git a/scalac-scoverage-plugin/src/test/scala/scoverage/CoberturaXmlWriterTest.scala b/scalac-scoverage-plugin/src/test/scala/scoverage/CoberturaXmlWriterTest.scala index 6a21fac3..101c1999 100644 --- a/scalac-scoverage-plugin/src/test/scala/scoverage/CoberturaXmlWriterTest.scala +++ b/scalac-scoverage-plugin/src/test/scala/scoverage/CoberturaXmlWriterTest.scala @@ -32,29 +32,28 @@ class CoberturaXmlWriterTest extends FunSuite with BeforeAndAfter with OneInstan val coverage = scoverage.Coverage() coverage - .add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create", canonicalPath("a.scala")), + .add(Statement(Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create", canonicalPath("a.scala")), 1, 2, 3, 12, "", "", "", false, 3)) coverage - .add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create2", canonicalPath("a.scala")), + .add(Statement(Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create2", canonicalPath("a.scala")), 2, 2, 3, 16, "", "", "", false, 3)) coverage - .add(Statement(canonicalPath("b.scala"), Location("com.sksamuel.scoverage2", "B", "com.sksamuel.scoverage2.B", ClassType.Object, "retrieve", canonicalPath("b.scala")), + .add(Statement(Location("com.sksamuel.scoverage2", "B", "com.sksamuel.scoverage2.B", ClassType.Object, "retrieve", canonicalPath("b.scala")), 3, 2, 3, 21, "", "", "", false, 0)) coverage - .add(Statement(canonicalPath("b.scala"), - Location("com.sksamuel.scoverage2", "B", "B", ClassType.Object, "retrieve2", canonicalPath("b.scala")), + .add(Statement(Location("com.sksamuel.scoverage2", "B", "B", ClassType.Object, "retrieve2", canonicalPath("b.scala")), 4, 2, 3, 9, "", "", "", false, 3)) coverage - .add(Statement(canonicalPath("c.scala"), Location("com.sksamuel.scoverage3", "C", "com.sksamuel.scoverage3.C", ClassType.Object, "update", canonicalPath("c.scala")), + .add(Statement(Location("com.sksamuel.scoverage3", "C", "com.sksamuel.scoverage3.C", ClassType.Object, "update", canonicalPath("c.scala")), 5, 2, 3, 66, "", "", "", true, 3)) coverage - .add(Statement(canonicalPath("c.scala"), Location("com.sksamuel.scoverage3", "C", "com.sksamuel.scoverage3.C", ClassType.Object, "update2", canonicalPath("c.scala")), + .add(Statement(Location("com.sksamuel.scoverage3", "C", "com.sksamuel.scoverage3.C", ClassType.Object, "update2", canonicalPath("c.scala")), 6, 2, 3, 6, "", "", "", true, 3)) coverage - .add(Statement(canonicalPath("d.scala"), Location("com.sksamuel.scoverage4", "D", "com.sksamuel.scoverage4.D", ClassType.Object, "delete", canonicalPath("d.scala")), + .add(Statement(Location("com.sksamuel.scoverage4", "D", "com.sksamuel.scoverage4.D", ClassType.Object, "delete", canonicalPath("d.scala")), 7, 2, 3, 4, "", "", "", false, 0)) coverage - .add(Statement(canonicalPath("d.scala"), Location("com.sksamuel.scoverage4", "D", "com.sksamuel.scoverage4.D", ClassType.Object, "delete2", canonicalPath("d.scala")), + .add(Statement(Location("com.sksamuel.scoverage4", "D", "com.sksamuel.scoverage4.D", ClassType.Object, "delete2", canonicalPath("d.scala")), 8, 2, 3, 14, "", "", "", false, 0)) val writer = new CoberturaXmlWriter(sourceRoot, dir) @@ -87,13 +86,13 @@ class CoberturaXmlWriterTest extends FunSuite with BeforeAndAfter with OneInstan val coverage = Coverage() coverage - .add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create", canonicalPath("a.scala")), + .add(Statement(Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create", canonicalPath("a.scala")), 1, 2, 3, 12, "", "", "", false)) coverage - .add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create2", canonicalPath("a.scala")), + .add(Statement(Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create2", canonicalPath("a.scala")), 2, 2, 3, 16, "", "", "", true)) coverage - .add(Statement(canonicalPath("a.scala"), Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create3", canonicalPath("a.scala")), + .add(Statement(Location("com.sksamuel.scoverage", "A", "com.sksamuel.scoverage.A", ClassType.Object, "create3", canonicalPath("a.scala")), 3, 3, 3, 20, "", "", "", true, 1)) val writer = new CoberturaXmlWriter(sourceRoot, dir) diff --git a/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageAggregatorTest.scala b/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageAggregatorTest.scala index 711be566..e3daac1b 100644 --- a/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageAggregatorTest.scala +++ b/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageAggregatorTest.scala @@ -24,20 +24,20 @@ class CoverageAggregatorTest extends FreeSpec with Matchers { source) val coverage1 = Coverage() - coverage1.add(Statement(source, location, 1, 155, 176, 4, "", "", "", true, 1)) - coverage1.add(Statement(source, location, 2, 200, 300, 5, "", "", "", false, 2)) + coverage1.add(Statement(location, 1, 155, 176, 4, "", "", "", true, 1)) + coverage1.add(Statement(location, 2, 200, 300, 5, "", "", "", false, 2)) val dir1 = new File(IOUtils.getTempPath, UUID.randomUUID.toString) dir1.mkdir() new ScoverageXmlWriter(sourceRoot, dir1, false).write(coverage1) val coverage2 = Coverage() - coverage2.add(Statement(source, location, 1, 95, 105, 19, "", "", "", false, 0)) + coverage2.add(Statement(location, 1, 95, 105, 19, "", "", "", false, 0)) val dir2 = new File(IOUtils.getTempPath, UUID.randomUUID.toString) dir2.mkdir() new ScoverageXmlWriter(sourceRoot, dir2, false).write(coverage2) val coverage3 = Coverage() - coverage3.add(Statement(source, location, 2, 14, 1515, 544, "", "", "", false, 1)) + coverage3.add(Statement(location, 2, 14, 1515, 544, "", "", "", false, 1)) val dir3 = new File(IOUtils.getTempPath, UUID.randomUUID.toString) dir3.mkdir() new ScoverageXmlWriter(sourceRoot, dir3, false).write(coverage3) diff --git a/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageMetricsTest.scala b/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageMetricsTest.scala index b37ec30a..2992ae1b 100644 --- a/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageMetricsTest.scala +++ b/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageMetricsTest.scala @@ -6,7 +6,7 @@ class CoverageMetricsTest extends FreeSpec with Matchers { "no branches with at least one invoked statement should have 100% branch coverage" in { val metrics = new CoverageMetrics { - override def statements: Iterable[Statement] = Seq(Statement(null, + override def statements: Iterable[Statement] = Seq(Statement( null, 0, 0, @@ -26,7 +26,7 @@ class CoverageMetricsTest extends FreeSpec with Matchers { "no branches with no invoked statements should have 0% branch coverage" in { val metrics = new CoverageMetrics { - override def statements: Iterable[Statement] = Seq(Statement(null, + override def statements: Iterable[Statement] = Seq(Statement( null, 0, 0, diff --git a/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageTest.scala b/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageTest.scala index 4bf5e0af..50f9ee7c 100644 --- a/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageTest.scala +++ b/scalac-scoverage-plugin/src/test/scala/scoverage/CoverageTest.scala @@ -12,16 +12,16 @@ class CoverageTest extends FunSuite with BeforeAndAfter with OneInstancePerTest test("coverage for no invoked statements is 0") { val coverage = Coverage() - coverage.add(Statement("", Location("", "","", ClassType.Object, "", ""), 1, 2, 3, 4, "", "", "", false, 0)) + coverage.add(Statement(Location("", "","", ClassType.Object, "", ""), 1, 2, 3, 4, "", "", "", false, 0)) assert(0 === coverage.statementCoverage) } test("coverage for invoked statements") { val coverage = Coverage() - coverage.add(Statement("", Location("", "","", ClassType.Object, "", ""), 1, 2, 3, 4, "", "", "", false, 3)) - coverage.add(Statement("", Location("", "", "", ClassType.Object, "", ""), 2, 2, 3, 4, "", "", "", false, 0)) - coverage.add(Statement("", Location("", "", "", ClassType.Object, "", ""), 3, 2, 3, 4, "", "", "", false, 0)) - coverage.add(Statement("", Location("", "", "", ClassType.Object, "", ""), 4, 2, 3, 4, "", "", "", false, 0)) + coverage.add(Statement(Location("", "","", ClassType.Object, "", ""), 1, 2, 3, 4, "", "", "", false, 3)) + coverage.add(Statement(Location("", "", "", ClassType.Object, "", ""), 2, 2, 3, 4, "", "", "", false, 0)) + coverage.add(Statement(Location("", "", "", ClassType.Object, "", ""), 3, 2, 3, 4, "", "", "", false, 0)) + coverage.add(Statement(Location("", "", "", ClassType.Object, "", ""), 4, 2, 3, 4, "", "", "", false, 0)) assert(0.25 === coverage.statementCoverage) } } diff --git a/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageHtmlWriterTest.scala b/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageHtmlWriterTest.scala index a7076876..cf3f4e09 100644 --- a/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageHtmlWriterTest.scala +++ b/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageHtmlWriterTest.scala @@ -21,15 +21,15 @@ class ScoverageHtmlWriterTest extends FunSuite { val pathToClassInSubDir = pathToClassFile("subdir/ClassInSubDir.scala") val pathToClassInMainDir = pathToClassFile("ClassInMainDir.scala") - val statementForClassContainingHtml = Statement(pathToClassContainingHtml, - Location("coverage.sample", "ClassContainingHtml", "ClassContainingHtml", ClassType.Class, "some_html", pathToClassInSubDir), + val statementForClassContainingHtml = Statement( + Location("coverage.sample", "ClassContainingHtml", "ClassContainingHtml", ClassType.Class, "some_html", pathToClassContainingHtml), 3, 74, 97, 4, "
HTML content
", "scala.Predef.println", "Apply", false, 0) - val statementForClassInSubDir = Statement(pathToClassInSubDir, + val statementForClassInSubDir = Statement( Location("coverage.sample", "ClassInSubDir", "ClassInSubDir", ClassType.Class, "msg_test", pathToClassInSubDir), 2, 64, 84, 4, "scala.this.Predef.println(\"test code\")", "scala.Predef.println", "Apply", false, 0) - val statementForClassInMainDir = Statement(pathToClassInMainDir, + val statementForClassInMainDir = Statement( Location("coverage.sample", "ClassInMainDir", "ClassInMainDir", ClassType.Class, "msg_coverage", pathToClassInMainDir), 1, 69, 104, 4, "scala.this.Predef.println(\"measure coverage of code\")", "scala.Predef.println", "Apply", false, 0) diff --git a/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageXmlReaderTest.scala b/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageXmlReaderTest.scala index d2033e39..84406d73 100644 --- a/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageXmlReaderTest.scala +++ b/scalac-scoverage-plugin/src/test/scala/scoverage/ScoverageXmlReaderTest.scala @@ -17,7 +17,7 @@ class ScoverageXmlReaderTest extends FreeSpec with Matchers { val coverage = Coverage() - coverage.add(Statement(canonicalPath("com/scoverage/class.scala"), + coverage.add(Statement( Location("com.scoverage", "Test", "com.scoverage.TopLevel.Test", @@ -34,7 +34,7 @@ class ScoverageXmlReaderTest extends FreeSpec with Matchers { true, 2)) - coverage.add(Statement(canonicalPath("com/scoverage/foo/class.scala"), + coverage.add(Statement( Location("com.scoverage.foo", "ServiceState", "com.scoverage.foo.Service.ServiceState", diff --git a/scalac-scoverage-plugin/src/test/scala/scoverage/SerializerTest.scala b/scalac-scoverage-plugin/src/test/scala/scoverage/SerializerTest.scala index 14e1abaf..098f2eeb 100644 --- a/scalac-scoverage-plugin/src/test/scala/scoverage/SerializerTest.scala +++ b/scalac-scoverage-plugin/src/test/scala/scoverage/SerializerTest.scala @@ -5,41 +5,103 @@ import java.io.StringWriter import org.scalatest.{OneInstancePerTest, FunSuite} import org.scalatest.mockito.MockitoSugar -import scala.xml.Utility - class SerializerTest extends FunSuite with MockitoSugar with OneInstancePerTest { - test("coverage should be serializable into xml") { + test("coverage should be serializable into plain text") { val coverage = Coverage() coverage.add( Statement( - "mysource", Location("org.scoverage", "test", "org.scoverage.test", ClassType.Trait, "mymethod", "mypath"), - 14, 100, 200, 4, "def test : String", "test", "DefDef", true, 32 + 14, 100, 200, 4, "def test : String", "test", "DefDef", true, 1 ) ) - val expected = - - mysource org.scoverage test Trait org.scoverage.test mymethod mypath 14 100 200 4 def test : String test DefDef true 32 false - - - val writer = new StringWriter() + 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(Utility.trim(expected) === Utility.trim(xml.XML.loadString(writer.toString))) + assert(expected === writer.toString) } - test("coverage should be deserializable from xml") { - val input = - - mysource org.scoverage test Trait org.scoverage.test mymethod mypath 14 100 200 4 def test : String test DefDef true 32 false - - + test("coverage should be deserializable from plain text") { + 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").toIterator val statements = List(Statement( - "mysource", Location("org.scoverage", "test", "org.scoverage.test", ClassType.Trait, "mymethod", "mypath"), - 14, 100, 200, 4, "def test : String", "test", "DefDef", true, 32 + 14, 100, 200, 4, "def test : String", "test", "DefDef", true, 1 )) - val coverage = Serializer.deserialize(input.toString()) + val coverage = Serializer.deserialize(input) assert(statements === coverage.statements.toList) } }