Skip to content

Commit

Permalink
WIP Shrink
Browse files Browse the repository at this point in the history
  • Loading branch information
nrinaudo committed Apr 24, 2020
1 parent a96657c commit 915b70c
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 15 deletions.
29 changes: 29 additions & 0 deletions laws/shared/src/main/scala/kantan/codecs/laws/CodecValue.scala
Original file line number Diff line number Diff line change
Expand Up @@ -78,4 +78,33 @@ object CodecValue {
): Arbitrary[IllegalValue[E, D, T]] =
Arbitrary(imp[Arbitrary[E]].arbitrary.map(aiv.asIllegalValue))

// - Shrink instances ------------------------------------------------------------------------------------------------
// -------------------------------------------------------------------------------------------------------------------

implicit def shrinkCodecValue[E, D, T](
implicit shrinkLegal: Shrink[LegalValue[E, D, T]],
shrinkIllegal: Shrink[IllegalValue[E, D, T]]
): Shrink[CodecValue[E, D, T]] =
Shrink {
case legal @ LegalValue(_, _) => shrinkLegal.shrink(legal)
case illegal @ IllegalValue(_) => shrinkIllegal.shrink(illegal)
}

implicit def shrinkLegalValue[E, D: Shrink, T](implicit alv: HasLegalValues[E, D, T]): Shrink[LegalValue[E, D, T]] =
Shrink { value =>
imp[Shrink[D]]
.shrink(value.decoded)
.map(alv.asLegalValue)
}

implicit def shrinkIllegalValue[E: Shrink, D, T](
implicit aiv: HasIllegalValues[E, D, T]
): Shrink[IllegalValue[E, D, T]] =
Shrink { value =>
imp[Shrink[E]]
.shrink(value.encoded)
.filter(aiv.isInvalid)
.map(IllegalValue.apply[E, D, T])
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,17 @@ import imp.imp
import kantan.codecs.Codec
import kantan.codecs.laws.{CodecLaws, CodecValue}
import kantan.codecs.laws.CodecValue.{IllegalValue, LegalValue}
import kantan.codecs.laws.discipline.arbitrary._
import org.scalacheck.{Arbitrary, Cogen}
import org.scalacheck.{Arbitrary, Cogen, Shrink}
import org.scalacheck.Prop.forAll

trait CodecTests[Encoded, Decoded, Failure, Tag]
extends DecoderTests[Encoded, Decoded, Failure, Tag] with EncoderTests[Encoded, Decoded, Tag] {
def laws: CodecLaws[Encoded, Decoded, Failure, Tag]

private def coreRules[A: Arbitrary: Cogen, B: Arbitrary: Cogen](
implicit av: Arbitrary[CodecValue[Encoded, Decoded, Tag]]
private def coreRules[A: Arbitrary: Cogen: Shrink, B: Arbitrary: Cogen: Shrink](
implicit av: Arbitrary[CodecValue[Encoded, Decoded, Tag]],
shrinkFoo: Shrink[IllegalValue[Encoded, Decoded, Tag]],
shrinkBar: Shrink[LegalValue[Encoded, Decoded, Tag]]
): RuleSet =
new DefaultRuleSet(
"round trip",
Expand All @@ -48,7 +49,7 @@ trait CodecTests[Encoded, Decoded, Failure, Tag]
"imapEncoded composition(decoding)" -> forAll(laws.imapEncodedCompositionDecoding[A, B] _)
)

def bijectiveCodec[A: Arbitrary: Cogen, B: Arbitrary: Cogen]: RuleSet = new RuleSet {
def bijectiveCodec[A: Arbitrary: Cogen: Shrink, B: Arbitrary: Cogen: Shrink]: RuleSet = new RuleSet {
implicit val arbValues: Arbitrary[CodecValue[Encoded, Decoded, Tag]] = Arbitrary(arbLegal.arbitrary)

val name = "bijective codec"
Expand All @@ -57,8 +58,10 @@ trait CodecTests[Encoded, Decoded, Failure, Tag]
val props = Seq.empty
}

def codec[A: Arbitrary: Cogen, B: Arbitrary: Cogen](
implicit ai: Arbitrary[IllegalValue[Encoded, Decoded, Tag]]
def codec[A: Arbitrary: Cogen: Shrink, B: Arbitrary: Cogen: Shrink](
implicit ai: Arbitrary[IllegalValue[Encoded, Decoded, Tag]],
shrinkFoo: Shrink[IllegalValue[Encoded, Decoded, Tag]],
shrinkBar: Shrink[LegalValue[Encoded, Decoded, Tag]]
): RuleSet =
new RuleSet {
val name = "codec"
Expand All @@ -69,7 +72,7 @@ trait CodecTests[Encoded, Decoded, Failure, Tag]
}

object CodecTests {
def apply[E: Arbitrary: Cogen, D: Arbitrary: Cogen, F: Cogen: Arbitrary, T](
def apply[E: Arbitrary: Cogen, D: Arbitrary: Cogen: Shrink, F: Cogen: Arbitrary, T](
implicit c: Codec[E, D, F, T],
al: Arbitrary[LegalValue[E, D, T]]
): CodecTests[E, D, F, T] =
Expand All @@ -82,5 +85,6 @@ object CodecTests {
override val cogenE = Cogen[E]
override val arbD = imp[Arbitrary[D]]
override val arbE = imp[Arbitrary[E]]
override val shrinkD = imp[Shrink[D]]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@ import imp.imp
import kantan.codecs.Decoder
import kantan.codecs.laws.{CodecValue, DecoderLaws}
import kantan.codecs.laws.CodecValue.{IllegalValue, LegalValue}
import kantan.codecs.laws.discipline.arbitrary._
import org.scalacheck.{Arbitrary, Cogen}
import org.scalacheck.{Arbitrary, Cogen, Shrink}
import org.scalacheck.Prop.forAll
import org.typelevel.discipline.Laws

Expand All @@ -32,12 +31,15 @@ trait DecoderTests[Encoded, Decoded, Failure, Tag] extends Laws {

implicit def arbF: Arbitrary[Failure]
implicit val arbD: Arbitrary[Decoded]
implicit val shrinkD: Shrink[Decoded]
implicit val arbE: Arbitrary[Encoded]
implicit val cogenF: Cogen[Failure]
implicit val cogenD: Cogen[Decoded]

private def coreRules[A: Arbitrary: Cogen, B: Arbitrary: Cogen](
implicit arbED: Arbitrary[CodecValue[Encoded, Decoded, Tag]]
private def coreRules[A: Arbitrary: Cogen: Shrink, B: Arbitrary: Cogen: Shrink](
implicit arbED: Arbitrary[CodecValue[Encoded, Decoded, Tag]],
shrinkFoo: Shrink[IllegalValue[Encoded, Decoded, Tag]],
shrinkBar: Shrink[LegalValue[Encoded, Decoded, Tag]]
) =
new SimpleRuleSet(
"core",
Expand All @@ -52,7 +54,10 @@ trait DecoderTests[Encoded, Decoded, Failure, Tag] extends Laws {
"leftMap composition" -> forAll(laws.leftMapComposition[A, B] _)
)

def bijectiveDecoder[A: Arbitrary: Cogen, B: Arbitrary: Cogen]: RuleSet = {
def bijectiveDecoder[A: Arbitrary: Cogen, B: Arbitrary: Cogen](
implicit shrinkFoo: Shrink[IllegalValue[Encoded, Decoded, Tag]],
shrinkBar: Shrink[LegalValue[Encoded, Decoded, Tag]]
): RuleSet = {
implicit val arbValues: Arbitrary[CodecValue[Encoded, Decoded, Tag]] = Arbitrary(arbLegal.arbitrary)
new DefaultRuleSet(
"bijective decoder",
Expand All @@ -61,7 +66,9 @@ trait DecoderTests[Encoded, Decoded, Failure, Tag] extends Laws {
}

def decoder[A: Arbitrary: Cogen, B: Arbitrary: Cogen](
implicit ai: Arbitrary[IllegalValue[Encoded, Decoded, Tag]]
implicit ai: Arbitrary[IllegalValue[Encoded, Decoded, Tag]],
shrinkFoo: Shrink[IllegalValue[Encoded, Decoded, Tag]],
shrinkBar: Shrink[LegalValue[Encoded, Decoded, Tag]]
): RuleSet =
new DefaultRuleSet(
"decoder",
Expand All @@ -71,7 +78,7 @@ trait DecoderTests[Encoded, Decoded, Failure, Tag] extends Laws {
}

object DecoderTests {
def apply[E: Arbitrary, D: Arbitrary: Cogen, F: Cogen: Arbitrary, T](
def apply[E: Arbitrary, D: Arbitrary: Cogen: Shrink, F: Cogen: Arbitrary, T](
implicit d: Decoder[E, D, F, T],
al: Arbitrary[LegalValue[E, D, T]]
): DecoderTests[E, D, F, T] =
Expand All @@ -83,5 +90,6 @@ object DecoderTests {
override val cogenD = Cogen[D]
override val arbD = imp[Arbitrary[D]]
override val arbE = imp[Arbitrary[E]]
override val shrinkD = imp[Shrink[D]]
}
}

0 comments on commit 915b70c

Please sign in to comment.