/
ParserTests.scala
67 lines (60 loc) · 2.69 KB
/
ParserTests.scala
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
64
65
66
67
package io.circe.testing
import cats.data.{ Validated, ValidatedNel }
import cats.instances.either._
import cats.kernel.laws.SerializableLaws
import cats.laws._
import cats.laws.discipline._
import io.circe.{ Error, Json, Parser, ParsingFailure }
import org.scalacheck.{ Arbitrary, Prop, Shrink }
import org.typelevel.discipline.Laws
case class ParserLaws[P <: Parser](parser: P) {
def parsingRoundTrip[A](json: Json)(
encode: Json => A, decode: P => (A => Either[ParsingFailure, Json])
): IsEq[Either[ParsingFailure, Json]] =
decode(parser)(encode(json)) <-> Right(json)
def decodingRoundTrip[A](json: Json)(
encode: Json => A, decode: P => (A => Either[Error, Json])
): IsEq[Either[Error, Json]] =
decode(parser)(encode(json)) <-> Right(json)
def decodingAccumulatingRoundTrip[A](json: Json)(
encode: Json => A, decode: P => (A => ValidatedNel[Error, Json])
): IsEq[ValidatedNel[Error, Json]] =
decode(parser)(encode(json)) <-> Validated.valid(json)
}
case class ParserTests[P <: Parser](p: P) extends Laws {
def laws: ParserLaws[P] = ParserLaws(p)
def fromString(implicit arbitraryJson: Arbitrary[Json], shrinkJson: Shrink[Json]): RuleSet =
fromFunction[String]("fromString")(
identity, _.parse, _.decode[Json], _.decodeAccumulating[Json]
)
def fromFunction[A](name: String)(
serialize: String => A,
parse: P => A => Either[ParsingFailure, Json],
decode: P => A => Either[Error, Json],
decodeAccumulating: P => A => ValidatedNel[Error, Json]
)(implicit arbitraryJson: Arbitrary[Json], shrinkJson: Shrink[Json]): RuleSet = new DefaultRuleSet(
name = s"parser[$name]",
parent = None,
"parsingRoundTripWithoutSpaces" -> Prop.forAll { (json: Json) =>
laws.parsingRoundTrip[A](json)(json => serialize(json.noSpaces), parse)
},
"parsingRoundTripWithSpaces" -> Prop.forAll { (json: Json) =>
laws.parsingRoundTrip[A](json)(json => serialize(json.spaces2), parse)
},
"decodingRoundTripWithoutSpaces" -> Prop.forAll { (json: Json) =>
laws.decodingRoundTrip[A](json)(json => serialize(json.noSpaces), decode)
},
"decodingRoundTripWithSpaces" -> Prop.forAll { (json: Json) =>
laws.decodingRoundTrip[A](json)(json => serialize(json.spaces2), decode)
},
"decodingAccumulatingRoundTripWithoutSpaces" -> Prop.forAll { (json: Json) =>
laws.decodingAccumulatingRoundTrip[A](json)(json =>
serialize(json.noSpaces), decodeAccumulating)
},
"decodingAccumulatingRoundTripWithSpaces" -> Prop.forAll { (json: Json) =>
laws.decodingAccumulatingRoundTrip[A](json)(json =>
serialize(json.spaces2), decodeAccumulating)
},
"parser serializability" -> SerializableLaws.serializable(p)
)
}