Skip to content

Add ScalaCheck specs #110

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

Closed
wants to merge 11 commits into from
5 changes: 4 additions & 1 deletion build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -107,11 +107,14 @@ lazy val xml = crossProject(JSPlatform, JVMPlatform)
libraryDependencies += "junit" % "junit" % "4.12" % Test,
libraryDependencies += "com.novocode" % "junit-interface" % "0.11" % Test,
libraryDependencies += "org.apache.commons" % "commons-lang3" % "3.9" % Test,
libraryDependencies += "org.scalacheck" %% "scalacheck" % "1.14.0" % Test,
libraryDependencies += ("org.scala-lang" % "scala-compiler" % scalaVersion.value % Test).exclude("org.scala-lang.modules", s"scala-xml_${scalaBinaryVersion.value}")
)
.jsSettings(
// Scala.js cannot run forked tests
fork in Test := false
fork in Test := false,

libraryDependencies += "org.scalacheck" %%% "scalacheck" % "1.14.0" % Test
)
.jsConfigure(_.enablePlugins(ScalaJSJUnitPlugin))

Expand Down
161 changes: 161 additions & 0 deletions jvm/src/test/scala/scala/xml/NodeSeqSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2018, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */

package scala.xml

import org.scalacheck.Prop
import org.scalacheck.{ Properties => PropertiesFor }
import org.scalacheck.Prop.AnyOperators

object NodeSeqSpec extends PropertiesFor("NodeSeq")
with NodeSeqGen {

property("theSeq") = {
Prop.forAll { n: NodeSeq =>
n.theSeq ne null
}
}

property("length") = {
Prop.forAll { n: NodeSeq =>
n.length >= 0
}
}

property("\\ \"\".throws[Exception]") = {
Prop.forAll { n: NodeSeq =>
Prop.throws(classOf[IllegalArgumentException]) {
(n \ "")
}
}
}

property("\\ _.throws[Exception]") = {
Prop.forAll { n: NodeSeq =>
Prop.iff[NodeSeq](n, {
// FIXME: Exception thrown in NodeSeq.\.makeSeq
case g @ Group(_) =>
Prop.throws(classOf[UnsupportedOperationException]) {
(g \ "_")
}
case _ => {
(n \ "_")
Prop.passed
}
})
}
}

property("\\ @.throws[Exception]") = {
Prop.forAll { n: NodeSeq =>
Prop.iff[NodeSeq](n, {
case n: NodeSeq =>
Prop.throws(classOf[IllegalArgumentException]) {
(n \ "@")
}
})
}
}

property("\\") = {
Prop.forAll { (n: NodeSeq, s: String) =>
Prop.iff[String](s, {
// FIXME: Should be IllegalArgumentException, regardless of theSeq.
case "" =>
Prop.throws(classOf[IllegalArgumentException]) {
(n \ s)
}
case "@" =>
Prop.throws(classOf[IllegalArgumentException]) {
(n \ s)
}
case s =>
(n \ s)
Prop.passed
})
}
}

property("\\\\ \"\".throws[Exception]") = {
Prop.forAll { n: NodeSeq =>
Prop.throws(classOf[IllegalArgumentException]) {
(n \\ "")
}
}
}

property("\\\\ @.throws[Exception]") = {
Prop.forAll { n: NodeSeq =>
Prop.iff[NodeSeq](n, {
// FIXME: Should be IllegalArgumentException, regardless of theSeq
case n if n.filter(!_.isAtom).length == 0 =>
(n \\ "@") ?= NodeSeq.Empty
case n =>
Prop.throws(classOf[IllegalArgumentException]) {
(n \\ "@")
}
})
}
}

property("\\\\") = {
Prop.forAll { (n: NodeSeq, s: String) =>
Prop.iff[String](s, {
case "" | "@" =>
Prop.throws(classOf[IllegalArgumentException]) {
(n \\ s)
}
case s =>
(n \\ s)
Prop.passed
})
}
}

property("\\@ \"\".throws[Exception]") = {
Prop.forAll { n: NodeSeq =>
Prop.iff[NodeSeq](n, {
case s =>
Prop.throws(classOf[IllegalArgumentException]) {
(n \@ "")
}
})
}
}

property("\\@ _.throws[Exception]") = {
Prop.forAll { n: NodeSeq =>
Prop.iff[NodeSeq](n, {
// FIXME: Exception thrown in NodeSeq.\.makeSeq
case g @ Group(_) =>
Prop.throws(classOf[UnsupportedOperationException]) {
(g \@ "_")
}
case _ => {
(n \@ "_")
Prop.passed
}
})
}
}

property("\\@") = {
Prop.forAll { (n: NodeSeq, s: String) =>
// FIXME: Should be IllegalArgumentException, regardless of theSeq.
Prop.throws(classOf[IllegalArgumentException]) {
(n \@ s)
} || Prop.passed // FIXME: Error conditions are too complex.
}
}

property("text") = {
Prop.forAll { n: NodeSeq =>
n.text.length >= 0
}
}
}
27 changes: 27 additions & 0 deletions jvm/src/test/scala/scala/xml/NodeSerializationSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2018, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */

package scala.xml

import org.scalacheck.Prop
import org.scalacheck.{ Properties => CheckProperties }
import org.scalacheck.Prop.AnyOperators
import org.scalacheck.Prop.BooleanOperators

object NodeSerializationSpec extends CheckProperties("NodeSerialization")
with NodeGen {

property("serialization") = {
Prop.forAll { n: Node =>
Prop.iff[Node](n, {
case n =>
JavaByteSerialization.roundTrip(n) ?= n
})
}
}
}
30 changes: 30 additions & 0 deletions jvm/src/test/scala/scala/xml/XmlStringGen.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2018, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */

package scala.xml

import org.scalacheck.Arbitrary
import org.scalacheck.Gen

trait XmlStringGen extends DocumentGen {

def xmlDeclGen(version: String, encoding: String): Gen[String] =
Gen.oneOf(
Gen.const(""),
Gen.const(s"<?xml version='$version' encoding='$encoding'?>")
)

val genXmlString: Gen[String] = for {
document <- Arbitrary.arbitrary[Document]
encoding <- Gen.const("UTF-8") // java.nio.charset.StandardCharsets.UTF_8.name
xmlDecl <- xmlDeclGen("1.0", encoding)
} yield {
val str = xmlDecl + Group(document.children ++ Seq(document.docElem)).toString
str
}
}
73 changes: 73 additions & 0 deletions jvm/src/test/scala/scala/xml/dtd/ExternalIDSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/* __ *\
** ________ ___ / / ___ Scala API **
** / __/ __// _ | / / / _ | (c) 2003-2018, LAMP/EPFL **
** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ **
** /____/\___/_/ |_/____/_/ | | **
** |/ **
\* */

package scala.xml
package dtd

import org.scalacheck.Prop
import org.scalacheck.{ Properties => PropertiesFor }
import org.scalacheck.Prop.AnyOperators

object ExternalIDSpec extends PropertiesFor("dtd.ExternalID")
with ExternalIDGen {

property("PublicID.throws[Exception]") = {
Prop.forAll(genNonPubIdStr) { s: String =>
Prop.throws(classOf[IllegalArgumentException]) {
PublicID(s, s)
}
}
}

property("SystemID.throws[Exception]") = {
Prop.forAll(genNonSysIdStr) { s: String =>
Prop.throws(classOf[IllegalArgumentException]) {
SystemID(s)
}
}
}

property("SystemID(null).throws[Exception]") = {
Prop.throws(classOf[NullPointerException]) {
SystemID(null)
}
}

property("label") = {
Prop.forAll { p: PublicID =>
p.label ?= "#PI"
}
}

property("attribute") = {
Prop.forAll { p: PublicID =>
p.attribute ?= Node.NoAttributes
}
}

property("child") = {
Prop.forAll { p: PublicID =>
p.child ?= Nil
}
}

property("toString") = Prop.forAll { e: ExternalID =>
val str = e.toString
Prop.atLeastOne(
str ?= "",
str ?= s"""SYSTEM '${e.systemId}'""",
str ?= s"""SYSTEM "${e.systemId}"""",
str ?= s"""PUBLIC '${e.publicId}'""",
str ?= s"""PUBLIC "${e.publicId}"""",
str ?= s"""PUBLIC '${e.publicId}' '${e.systemId}'""",
str ?= s"""PUBLIC "${e.publicId}" "${e.systemId}"""",
str ?= s"""PUBLIC '${e.publicId}' "${e.systemId}"""",
str ?= s"""PUBLIC "${e.publicId}" '${e.systemId}'"""
)
}
}
Loading