-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Port tests for InjectK to new tests for Inject
- Loading branch information
Showing
3 changed files
with
119 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package cats | ||
package laws | ||
|
||
trait InjectLaws[A, B] { | ||
def inject: Inject[A, B] | ||
|
||
def injectRoundTripInj(a: A): IsEq[Option[A]] = | ||
(inject.prj compose inject.inj).apply(a) <-> Some(a) | ||
|
||
def injectRoundTripPrj(b: B): IsEq[Option[B]] = | ||
inject.prj(b) match { | ||
case Some(a) => (Some(inject.inj(a)): Option[B]) <-> Some(b) | ||
case None => (None: Option[B]) <-> None | ||
} | ||
} | ||
|
||
object InjectLaws { | ||
def apply[A, B](implicit ev: Inject[A, B]): InjectLaws[A, B] = | ||
new InjectLaws[A, B]{ val inject: Inject[A, B] = ev } | ||
} |
31 changes: 31 additions & 0 deletions
31
laws/src/main/scala/cats/laws/discipline/InjectTests.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
package cats | ||
package laws | ||
package discipline | ||
|
||
import org.scalacheck.Arbitrary | ||
import org.scalacheck.Prop | ||
import Prop._ | ||
import org.typelevel.discipline.Laws | ||
|
||
trait InjectTests[A, B] extends Laws { | ||
def laws: InjectLaws[A, B] | ||
|
||
def inject(implicit | ||
ArbA: Arbitrary[A], | ||
EqOptionA: Eq[Option[A]], | ||
ArbB: Arbitrary[B], | ||
EqOptionB: Eq[Option[B]] | ||
): RuleSet = | ||
new DefaultRuleSet( | ||
"inject", | ||
None, | ||
"inject round trip inj" -> forAll((a: A) => laws.injectRoundTripInj(a)), | ||
"inject round trip prj" -> forAll((b: B) => laws.injectRoundTripPrj(b)) | ||
) | ||
|
||
} | ||
|
||
object InjectTests { | ||
def apply[A, B](implicit ev: Inject[A, B]): InjectTests[A, B] = | ||
new InjectTests[A, B] { val laws: InjectLaws[A, B] = InjectLaws[A, B] } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package cats | ||
|
||
import cats.laws.discipline.{ InjectTests => InjectTypeclassTests } | ||
import cats.tests.CatsSuite | ||
|
||
class InjectTests extends CatsSuite { | ||
|
||
type StringOrInt = Either[String, Int] | ||
|
||
test("inj & prj") { | ||
def distr[F](f1: F, f2: F) | ||
(implicit | ||
I0: Inject[String, F], | ||
I1: Inject[Int, F] | ||
): Option[String] = | ||
for { | ||
x <- I0.prj(f1) | ||
y <- I1.prj(f2) | ||
} yield s"$x $y" | ||
|
||
forAll { (x: String, y: Int) => | ||
val expr1: StringOrInt = Inject[String, StringOrInt].inj(x) | ||
val expr2: StringOrInt = Inject[Int, StringOrInt].inj(y) | ||
val res = distr(expr1, expr2) | ||
res should ===(Some(s"$x $y")) | ||
} | ||
} | ||
|
||
test("apply & unapply") { | ||
def distr[F](f1: F, f2: F) | ||
(implicit | ||
I0: Inject[String, F], | ||
I1: Inject[Int, F] | ||
): Option[String] = | ||
for { | ||
x <- I0.unapply(f1) | ||
y <- I1.unapply(f2) | ||
} yield s"$x $y" | ||
|
||
forAll { (x: String, y: Int) => | ||
val expr1: StringOrInt = Inject[String, StringOrInt].apply(x) | ||
val expr2: StringOrInt = Inject[Int, StringOrInt].apply(y) | ||
val res = distr(expr1, expr2) | ||
res should ===(Some(s"$x $y")) | ||
} | ||
} | ||
|
||
test("apply in left") { | ||
forAll { (y: String) => | ||
Inject[String, StringOrInt].inj(y) == Left(y) should ===(true) | ||
} | ||
} | ||
|
||
test("apply in right") { | ||
forAll { (y: Int) => | ||
Inject[Int, StringOrInt].inj(y) == Right(y) should ===(true) | ||
} | ||
} | ||
|
||
test("null identity") { | ||
val stringNull = null.asInstanceOf[String] | ||
Inject.catsReflexiveInjectInstance[String].inj(stringNull) should ===(stringNull) | ||
Inject.catsReflexiveInjectInstance[String].prj(stringNull) should ===(Some(stringNull)) | ||
} | ||
|
||
checkAll("Inject[String, StringOrInt]", InjectTypeclassTests[String, StringOrInt].inject) | ||
checkAll("Inject[Int, StringOrInt]", InjectTypeclassTests[Int, StringOrInt].inject) | ||
} |