From 96bf175464b4f8d5eb5c7f04cc0479dbd41f89cb Mon Sep 17 00:00:00 2001 From: Bruno Bieth Date: Mon, 24 Feb 2014 17:54:16 +0100 Subject: [PATCH] escape CData ]]> in sysout --- project/Sbt.scala | 2 +- project/Util.scala | 3 ++- .../scala/sbt/JUnitXmlTestsListener.scala | 8 +++++-- .../scala/sbt/JUnitXmlTestsListenerTest.scala | 22 +++++++++++++++++++ testing/src/test/scala/sbt/SimpleEvent.scala | 22 +++++++++++++++++++ 5 files changed, 53 insertions(+), 4 deletions(-) create mode 100644 testing/src/test/scala/sbt/JUnitXmlTestsListenerTest.scala create mode 100644 testing/src/test/scala/sbt/SimpleEvent.scala diff --git a/project/Sbt.scala b/project/Sbt.scala index b4c820dea..9186c7e55 100644 --- a/project/Sbt.scala +++ b/project/Sbt.scala @@ -79,7 +79,7 @@ object Sbt extends Build // Apache Ivy integration lazy val ivySub = baseProject(file("ivy"), "Ivy") dependsOn(interfaceSub, launchInterfaceSub, crossSub, logSub % "compile;test->test", ioSub % "compile;test->test", launchSub % "test->test") settings(ivy, jsch, testExclusive) // Runner for uniform test interface - lazy val testingSub = baseProject(file("testing"), "Testing") dependsOn(ioSub, classpathSub, logSub, launchInterfaceSub, testAgentSub) settings(testInterface) + lazy val testingSub = testedBaseProject(file("testing"), "Testing") dependsOn(ioSub, classpathSub, logSub, launchInterfaceSub, testAgentSub) settings(testInterface) // Testing agent for running tests in a separate process. lazy val testAgentSub = minProject(file("testing/agent"), "Test Agent") settings(testInterface) diff --git a/project/Util.scala b/project/Util.scala index 125d46b81..9478b8e32 100644 --- a/project/Util.scala +++ b/project/Util.scala @@ -52,7 +52,8 @@ object Util if(incl) Seq( "org.scalacheck" %% "scalacheck" % "1.11.1" % "test", "org.specs2" %% "specs2" % "1.12.3" % "test", - "junit" % "junit" % "4.11" % "test" + "junit" % "junit" % "4.11" % "test", + "org.backuity" %% "matchete" % "1.8" % "test" ) else Seq() } diff --git a/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala b/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala index f66ae0b73..b9aff43eb 100644 --- a/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala +++ b/testing/src/main/scala/sbt/JUnitXmlTestsListener.scala @@ -4,7 +4,7 @@ import java.io.{StringWriter, PrintWriter, File} import java.net.InetAddress import scala.collection.mutable.ListBuffer import scala.util.DynamicVariable -import scala.xml.{Elem, Node, XML} +import scala.xml.{PCData, Elem, Node, XML} import testing.{Event => TEvent, Status => TStatus, OptionalThrowable, TestSelector} /** @@ -32,7 +32,11 @@ class JUnitXmlTestsListener(val outputDir:String, logger: Logger) extends TestsL } - private def cdata(content: String) = scala.xml.Unparsed("".format(content)) + private def cdata(content: String) : Node = { + val escapedCData = content.replaceAll("]]>", "]]]]>") + // unfortunately PCData does not escape ']]>' + PCData(escapedCData) + } private def stackTraceToString(t: Throwable) : String = { val stringWriter = new StringWriter() diff --git a/testing/src/test/scala/sbt/JUnitXmlTestsListenerTest.scala b/testing/src/test/scala/sbt/JUnitXmlTestsListenerTest.scala new file mode 100644 index 000000000..652bcb86a --- /dev/null +++ b/testing/src/test/scala/sbt/JUnitXmlTestsListenerTest.scala @@ -0,0 +1,22 @@ +package sbt + +import org.backuity.matchete.{XmlMatchers, JunitMatchers} +import org.junit.Test + +class JUnitXmlTestsListenerTest extends JunitMatchers with XmlMatchers { + + @Test + def sysoutCDataShouldBeEscaped() { + val listener = new JUnitXmlTestsListener("/", ConsoleLogger()) + val event = new JUnitEvent(1234L, "org.the.ATest") + val xml = listener.toXml("a test", SuiteReport(Seq(TestReport(" ME! AND ]]> ME!!", event)))) + + xml \ "testcase" must containExactly( + a("'a test' test-case") { case tc => + tc must haveAttribute("classname", equalTo("a test")) + tc must haveAttribute("name", equalTo("ATest")) + (tc \ "system-out").toString must_== " ME! AND ]]]]> ME!!]]>" + }) + } + +} diff --git a/testing/src/test/scala/sbt/SimpleEvent.scala b/testing/src/test/scala/sbt/SimpleEvent.scala new file mode 100644 index 000000000..51081bc29 --- /dev/null +++ b/testing/src/test/scala/sbt/SimpleEvent.scala @@ -0,0 +1,22 @@ +package sbt + +import sbt.testing._ + +class SimpleEvent(val duration: Long, val fullyQualifiedName: String, val fingerprint: Fingerprint, + val status: Status = Status.Success, error: Option[Throwable] = None) extends Event { + + final val throwable: OptionalThrowable = error match { + case Some(err) => new OptionalThrowable(err) + case None => new OptionalThrowable + } + + val selector: Selector = new TestSelector(fullyQualifiedName) +} + +object JUnitAnnotation extends AnnotatedFingerprint { + override def annotationName(): String = "org.junit.Test" + override def isModule: Boolean = false +} + +class JUnitEvent(duration: Long, fullyQualifiedName: String, status: Status = Status.Success, error: Option[Throwable] = None) extends SimpleEvent( + duration, fullyQualifiedName, JUnitAnnotation, status, error) \ No newline at end of file