1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
|
package spray.json
import org.specs2.mutable.Specification
import org.scalacheck._
import org.specs2.matcher.ScalaCheckMatchers
object JsValueGenerators {
import Gen._
import Arbitrary.arbitrary
// some characters have special meaning in parboiled
// see org.parboiled.support.Chars, we have to exclude those
val parseableString: Gen[String] = arbitrary[String].map(_.filterNot(_ > 0xfd00))
val genString: Gen[JsString] = parseableString.map(JsString(_))
val genBoolean: Gen[JsBoolean] = oneOf(JsFalse, JsTrue)
val genLongNumber: Gen[JsNumber] = arbitrary[Long].map(JsNumber(_))
val genIntNumber: Gen[JsNumber] = arbitrary[Long].map(JsNumber(_))
val genDoubleNumber: Gen[JsNumber] = arbitrary[Long].map(JsNumber(_))
def genArray(depth: Int): Gen[JsArray] =
if (depth == 0) JsArray()
else
for {
n <- choose(0, 15)
els <- Gen.containerOfN[List, JsValue](n, genValue(depth - 1))
} yield JsArray(els)
def genField(depth: Int): Gen[(String, JsValue)] =
for {
key <- parseableString
value <- genValue(depth)
} yield key -> value
def genObject(depth: Int): Gen[JsObject] =
if (depth == 0) JsObject()
else
for {
n <- choose(0, 15)
fields <- Gen.containerOfN[List, (String, JsValue)](n, genField(depth - 1))
} yield JsObject(fields)
def genValue(depth: Int): Gen[JsValue] =
oneOf(
JsNull: Gen[JsValue],
genString,
genBoolean,
genLongNumber,
genDoubleNumber,
genIntNumber,
genArray(depth),
genObject(depth))
implicit val arbitraryValue: Arbitrary[JsValue] = Arbitrary(genValue(5))
}
class RoundTripSpecs extends Specification with ScalaCheckMatchers {
import JsValueGenerators.arbitraryValue
"Parsing / Printing round-trip" should {
"starting from JSON using compactPrint" in prop { (json: JsValue) =>
json.compactPrint.parseJson must_== json
}
"starting from JSON using prettyPrint" in prop { (json: JsValue) =>
json.prettyPrint.parseJson must_== json
}
}
}
|