diff --git a/build.sbt b/build.sbt index ad3c5347fe..bff9d42636 100644 --- a/build.sbt +++ b/build.sbt @@ -92,26 +92,29 @@ lazy val catsJVM = project.in(file(".catsJVM")) .settings(moduleName := "cats") .settings(catsSettings) .settings(commonJvmSettings) - .aggregate(macrosJVM, coreJVM, lawsJVM, freeJVM, stateJVM, testsJVM, docs, bench) - .dependsOn(macrosJVM, coreJVM, lawsJVM, freeJVM, stateJVM, testsJVM % "test-internal -> test", bench% "compile-internal;test-internal -> test") + .aggregate(macrosJVM, coreJVM, lawsJVM, freeJVM, stateJVM, testsJVM, jvm, docs, bench) + .dependsOn(macrosJVM, coreJVM, lawsJVM, freeJVM, stateJVM, testsJVM % "test-internal -> test", jvm, bench % "compile-internal;test-internal -> test") lazy val catsJS = project.in(file(".catsJS")) .settings(moduleName := "cats") .settings(catsSettings) .settings(commonJsSettings) - .aggregate(macrosJS, coreJS, lawsJS, freeJS, stateJS, testsJS) - .dependsOn(macrosJS, coreJS, lawsJS, freeJS, stateJS, testsJS % "test-internal -> test") + .aggregate(macrosJS, coreJS, lawsJS, freeJS, stateJS, testsJS, js) + .dependsOn(macrosJS, coreJS, lawsJS, freeJS, stateJS, testsJS % "test-internal -> test", js) .enablePlugins(ScalaJSPlugin) + lazy val macros = crossProject.crossType(CrossType.Pure) .settings(moduleName := "cats-macros") .settings(catsSettings:_*) .jsSettings(commonJsSettings:_*) .jvmSettings(commonJvmSettings:_*) + .settings(scalacOptions := scalacOptions.value.filter(_ != "-Xfatal-warnings")) -lazy val macrosJVM = macros.jvm +lazy val macrosJVM = macros.jvm lazy val macrosJS = macros.js + lazy val core = crossProject.crossType(CrossType.Pure) .dependsOn(macros) .settings(moduleName := "cats-core") @@ -125,25 +128,20 @@ lazy val core = crossProject.crossType(CrossType.Pure) lazy val coreJVM = core.jvm lazy val coreJS = core.js -lazy val laws = crossProject +lazy val laws = crossProject.crossType(CrossType.Pure) .dependsOn(macros, core) .settings(moduleName := "cats-laws") .settings(catsSettings:_*) .settings(disciplineDependencies:_*) - .settings(libraryDependencies += "org.spire-math" %%% "algebra-laws" % "0.3.1") + .settings(libraryDependencies ++= Seq( + "org.spire-math" %%% "algebra-laws" % "0.3.1", + "com.github.inthenow" %%% "bricks-platform" % "0.0.1")) .jsSettings(commonJsSettings:_*) .jvmSettings(commonJvmSettings:_*) lazy val lawsJVM = laws.jvm lazy val lawsJS = laws.js -lazy val bench = project.dependsOn(macrosJVM, coreJVM, freeJVM, lawsJVM) - .settings(moduleName := "cats-bench") - .settings(catsSettings) - .settings(noPublishSettings) - .settings(jmhSettings) - .settings(commonJvmSettings) - lazy val free = crossProject.crossType(CrossType.Pure) .dependsOn(macros, core, tests % "test-internal -> test") .settings(moduleName := "cats-free") @@ -164,19 +162,43 @@ lazy val state = crossProject.crossType(CrossType.Pure) lazy val stateJVM = state.jvm lazy val stateJS = state.js -lazy val tests = crossProject +lazy val tests = crossProject.crossType(CrossType.Pure) .dependsOn(macros, core, laws) .settings(moduleName := "cats-tests") .settings(catsSettings:_*) .settings(disciplineDependencies:_*) .settings(noPublishSettings:_*) - .settings(libraryDependencies += "org.scalatest" %%% "scalatest" % "3.0.0-M7" % "test") + .settings(libraryDependencies ++= Seq( + "org.scalatest" %%% "scalatest" % "3.0.0-M7" % "test", + "com.github.inthenow" %%% "bricks-platform" % "0.0.1" % "test")) .jsSettings(commonJsSettings:_*) .jvmSettings(commonJvmSettings:_*) lazy val testsJVM = tests.jvm lazy val testsJS = tests.js +// cats-jvm is JVM-only +lazy val jvm = project + .dependsOn(macrosJVM, coreJVM, testsJVM % "test-internal -> test") + .settings(moduleName := "cats-jvm") + .settings(catsSettings:_*) + .settings(commonJvmSettings:_*) + +// bench is currently JVM-only +lazy val bench = project.dependsOn(macrosJVM, coreJVM, freeJVM, lawsJVM) + .settings(moduleName := "cats-bench") + .settings(catsSettings) + .settings(noPublishSettings) + .settings(jmhSettings) + .settings(commonJvmSettings) + +// cats-js is JS-only +lazy val js = project + .dependsOn(macrosJS, coreJS, testsJS % "test-internal -> test") + .settings(moduleName := "cats-js") + .settings(catsSettings:_*) + .settings(commonJsSettings:_*) + lazy val publishSettings = Seq( homepage := Some(url("https://github.com/non/cats")), licenses := Seq("MIT" -> url("http://opensource.org/licenses/MIT")), diff --git a/core/src/main/scala/cats/data/Streaming.scala b/core/src/main/scala/cats/data/Streaming.scala index 235d241624..7193e2ca7f 100644 --- a/core/src/main/scala/cats/data/Streaming.scala +++ b/core/src/main/scala/cats/data/Streaming.scala @@ -473,7 +473,8 @@ sealed abstract class Streaming[A] { lhs => if (n <= 0) Empty() else this match { case Empty() => Empty() case Wait(lt) => Wait(lt.map(_.take(n))) - case Cons(a, lt) => Cons(a, lt.map(_.take(n - 1))) + case Cons(a, lt) => + Cons(a, if (n == 1) Now(Empty()) else lt.map(_.take(n - 1))) } /** diff --git a/core/src/main/scala/cats/std/future.scala b/core/src/main/scala/cats/std/future.scala index 2be0b41599..2e3cd4dee5 100644 --- a/core/src/main/scala/cats/std/future.scala +++ b/core/src/main/scala/cats/std/future.scala @@ -1,9 +1,9 @@ package cats package std -import cats.syntax.eq._ +import cats.syntax.all._ -import scala.concurrent.{Await, ExecutionContext, Future} +import scala.concurrent.{ExecutionContext, Future} import scala.concurrent.duration.FiniteDuration trait FutureInstances extends FutureInstances1 { @@ -23,39 +23,38 @@ trait FutureInstances extends FutureInstances1 { override def map[A, B](fa: Future[A])(f: A => B): Future[B] = fa.map(f) } - implicit def futureSemigroup[A](implicit A: Semigroup[A], ec: ExecutionContext): Semigroup[Future[A]] = - new FutureSemigroup[A]() - - def futureEq[A](atMost: FiniteDuration)(implicit A: Eq[A], ec: ExecutionContext): Eq[Future[A]] = - new Eq[Future[A]] { - def eqv(fx: Future[A], fy: Future[A]): Boolean = - Await.result((fx zip fy).map { case (x, y) => x === y }, atMost) - } + implicit def futureGroup[A: Group](implicit ec: ExecutionContext): Group[Future[A]] = + new FutureGroup[A] } -trait FutureInstances1 { - - def futureComonad(atMost: FiniteDuration)(implicit ec: ExecutionContext): Comonad[Future] = - new FutureCoflatMap with Comonad[Future] { - - def extract[A](x: Future[A]): A = Await.result(x, atMost) - - def map[A, B](fa: Future[A])(f: A => B): Future[B] = fa.map(f) - } - - implicit def futureMonoid[A](implicit A: Monoid[A], ec: ExecutionContext): Monoid[Future[A]] = - new FutureSemigroup[A] with Monoid[Future[A]] { - - def empty: Future[A] = Future.successful(A.empty) - } +trait FutureInstances1 extends FutureInstances2 { + implicit def futureMonoid[A: Monoid](implicit ec: ExecutionContext): Monoid[Future[A]] = + new FutureMonoid[A] } -private[std] abstract class FutureCoflatMap(implicit ec: ExecutionContext) extends CoflatMap[Future] { +trait FutureInstances2 { + implicit def futureSemigroup[A: Semigroup](implicit ec: ExecutionContext): Semigroup[Future[A]] = + new FutureSemigroup[A] +} +private[cats] abstract class FutureCoflatMap(implicit ec: ExecutionContext) extends CoflatMap[Future] { + def map[A, B](fa: Future[A])(f: A => B): Future[B] = fa.map(f) def coflatMap[A, B](fa: Future[A])(f: Future[A] => B): Future[B] = Future(f(fa)) } -private[std] class FutureSemigroup[A](implicit A: Semigroup[A], ec: ExecutionContext) extends Semigroup[Future[A]] { +private[cats] class FutureSemigroup[A: Semigroup](implicit ec: ExecutionContext) extends Semigroup[Future[A]] { + def combine(fx: Future[A], fy: Future[A]): Future[A] = + (fx zip fy).map { case (x, y) => x |+| y } +} + +private[cats] class FutureMonoid[A](implicit A: Monoid[A], ec: ExecutionContext) extends FutureSemigroup[A] with Monoid[Future[A]] { + def empty: Future[A] = + Future.successful(A.empty) +} - def combine(fx: Future[A], fy: Future[A]): Future[A] = (fx zip fy).map((A.combine _).tupled) +private[cats] class FutureGroup[A](implicit A: Group[A], ec: ExecutionContext) extends FutureMonoid[A] with Group[Future[A]] { + def inverse(fx: Future[A]): Future[A] = + fx.map(_.inverse) + override def remove(fx: Future[A], fy: Future[A]): Future[A] = + (fx zip fy).map { case (x, y) => x |-| y } } diff --git a/core/src/main/scala/cats/syntax/package.scala b/core/src/main/scala/cats/syntax/package.scala index 345e25d3c3..f94e6d9e36 100644 --- a/core/src/main/scala/cats/syntax/package.scala +++ b/core/src/main/scala/cats/syntax/package.scala @@ -13,6 +13,7 @@ package object syntax { object flatMap extends FlatMapSyntax object foldable extends FoldableSyntax object functor extends FunctorSyntax + object group extends GroupSyntax object invariant extends InvariantSyntax object monadCombine extends MonadCombineSyntax object monadFilter extends MonadFilterSyntax diff --git a/free/src/main/scala/cats/free/Coyoneda.scala b/free/src/main/scala/cats/free/Coyoneda.scala index 6f8b5c33ea..20f9c9852d 100644 --- a/free/src/main/scala/cats/free/Coyoneda.scala +++ b/free/src/main/scala/cats/free/Coyoneda.scala @@ -50,22 +50,6 @@ object Coyoneda { /** `F[A]` converts to `Coyoneda[F,A]` for any `F` */ def lift[F[_], A](fa: F[A]): Coyoneda[F, A] = apply(fa)(identity[A]) - /** - * Represents a partially-built Coyoneda instance. Used in the `by` method. - */ - final class By[F[_]] { - def apply[A, B](k: A => B)(implicit F: F[A]): Aux[F, B, A] = Coyoneda(F)(k) - } - - /** - * Partial application of type parameters to `apply`. - * - * It can be nicer to say `Coyoneda.by[F]{ x: X => ... }` - * - * ...instead of `Coyoneda[...](...){ x => ... }`. - */ - def by[F[_]]: By[F] = new By[F] - /** Like `lift(fa).map(_k)`. */ def apply[F[_], A, B](fa: F[A])(k0: A => B): Aux[F, B, A] = new Coyoneda[F, B] { diff --git a/free/src/main/scala/cats/free/FreeApplicative.scala b/free/src/main/scala/cats/free/FreeApplicative.scala index 0029de156c..399ae67eaf 100644 --- a/free/src/main/scala/cats/free/FreeApplicative.scala +++ b/free/src/main/scala/cats/free/FreeApplicative.scala @@ -23,13 +23,6 @@ sealed abstract class FreeApplicative[F[_], A] extends Product with Serializable case x@Ap() => apply(x.pivot)(x.fn.map(f compose _)) } - /** Natural Transformation of FreeApplicative based on given Natural Transformation */ - final def hoist[G[_]](f: F ~> G): FA[G, A] = - this match { - case Pure(a) => Pure[G, A](a) - case x@Ap() => apply(f(x.pivot))(x.fn.hoist(f)) - } - /** Interprets/Runs the sequence of operations using the semantics of Applicative G * Tail recursive only if G provides tail recursive interpretation (ie G is FreeMonad) */ @@ -45,7 +38,8 @@ sealed abstract class FreeApplicative[F[_], A] extends Product with Serializable final def fold(implicit F: Applicative[F]): F[A] = foldMap(NaturalTransformation.id[F]) - final def compile[G[_]](f: F ~> G)(implicit G: Applicative[G]): FA[G, A] = + /** Interpret this algebra into another FreeApplicative */ + final def compile[G[_]](f: F ~> G): FA[G, A] = foldMap[FA[G, ?]] { new NaturalTransformation[F, FA[G, ?]] { def apply[B](fa: F[B]): FA[G, B] = lift(f(fa)) diff --git a/free/src/test/scala/cats/free/CoyonedaTests.scala b/free/src/test/scala/cats/free/CoyonedaTests.scala new file mode 100644 index 0000000000..3193bc12c9 --- /dev/null +++ b/free/src/test/scala/cats/free/CoyonedaTests.scala @@ -0,0 +1,43 @@ +package cats +package free + +import cats.arrow.NaturalTransformation +import cats.tests.CatsSuite +import cats.laws.discipline.{ArbitraryK, FunctorTests, SerializableTests} + +import org.scalacheck.{Arbitrary, Gen} +import org.scalacheck.Arbitrary.arbitrary +import org.scalacheck.Prop.forAll + +class CoyonedaTests extends CatsSuite { + implicit def coyonedaArbitraryK[F[_] : Functor](implicit F: ArbitraryK[F]): ArbitraryK[Coyoneda[F, ?]] = + new ArbitraryK[Coyoneda[F, ?]]{ + def synthesize[A: Arbitrary]: Arbitrary[Coyoneda[F, A]] = coyonedaArbitrary[F, A] + } + + implicit def coyonedaArbitrary[F[_] : Functor, A : Arbitrary](implicit F: ArbitraryK[F]): Arbitrary[Coyoneda[F, A]] = + Arbitrary(F.synthesize[A].arbitrary.map(Coyoneda.lift)) + + implicit def coyonedaEq[F[_]: Functor, A](implicit FA: Eq[F[A]]): Eq[Coyoneda[F, A]] = + new Eq[Coyoneda[F, A]] { + def eqv(a: Coyoneda[F, A], b: Coyoneda[F, A]): Boolean = FA.eqv(a.run, b.run) + } + + checkAll("Coyoneda[Option, ?]", FunctorTests[Coyoneda[Option, ?]].functor[Int, Int, Int]) + checkAll("Functor[Coyoneda[Option, ?]]", SerializableTests.serializable(Functor[Coyoneda[Option, ?]])) + + test("toYoneda and then toCoyoneda is identity")(check { + // Issues inferring syntax for Eq, using instance explicitly + forAll((y: Coyoneda[Option, Int]) => coyonedaEq[Option, Int].eqv(y.toYoneda.toCoyoneda, y)) + }) + + test("transform and run is same as applying natural trans") { + val nt = + new NaturalTransformation[Option, List] { + def apply[A](fa: Option[A]): List[A] = fa.toList + } + val o = Option("hello") + val c = Coyoneda.lift(o) + c.transform(nt).run should === (nt(o)) + } +} diff --git a/free/src/test/scala/cats/free/FreeApplicativeTests.scala b/free/src/test/scala/cats/free/FreeApplicativeTests.scala index 8ae284e109..76eafa4b2f 100644 --- a/free/src/test/scala/cats/free/FreeApplicativeTests.scala +++ b/free/src/test/scala/cats/free/FreeApplicativeTests.scala @@ -40,7 +40,7 @@ class FreeApplicativeTests extends CatsSuite { val y = FreeApplicative.pure[Option, Int](n) val f = x.map(i => (j: Int) => i + j) val r = y.ap(f) - assert(r.fold == Apply[Option].map2(o1, o2)(_ + _)) + r.fold should === (Apply[Option].map2(o1, o2)(_ + _)) } test("FreeApplicative#compile") { @@ -50,7 +50,7 @@ class FreeApplicativeTests extends CatsSuite { val nt = NaturalTransformation.id[Id] val r1 = y.ap(f) val r2 = r1.compile(nt) - assert(r1.foldMap(nt) == r2.foldMap(nt)) + r1.foldMap(nt) should === (r2.foldMap(nt)) } test("FreeApplicative#monad") { @@ -63,6 +63,6 @@ class FreeApplicativeTests extends CatsSuite { new NaturalTransformation[Id, Id] { def apply[A](fa: Id[A]): Id[A] = fa } - assert(r1.foldMap(nt) == r2.foldMap(nt)) + r1.foldMap(nt) should === (r2.foldMap(nt)) } } diff --git a/free/src/test/scala/cats/free/YonedaTests.scala b/free/src/test/scala/cats/free/YonedaTests.scala new file mode 100644 index 0000000000..2f63cc6fc9 --- /dev/null +++ b/free/src/test/scala/cats/free/YonedaTests.scala @@ -0,0 +1,30 @@ +package cats +package free + +import cats.tests.CatsSuite +import cats.laws.discipline.{ArbitraryK, FunctorTests, SerializableTests} + +import org.scalacheck.Arbitrary +import org.scalacheck.Prop.forAll + +class YonedaTests extends CatsSuite { + implicit def yonedaArbitraryK[F[_] : Functor](implicit F: ArbitraryK[F]): ArbitraryK[Yoneda[F, ?]] = + new ArbitraryK[Yoneda[F, ?]]{ + def synthesize[A: Arbitrary]: Arbitrary[Yoneda[F, A]] = + Arbitrary(F.synthesize[A].arbitrary.map(Yoneda(_))) + } + + implicit def yonedaArbitrary[F[_] : Functor : ArbitraryK, A : Arbitrary]: Arbitrary[Yoneda[F, A]] = yonedaArbitraryK[F].synthesize[A] + + implicit def yonedaEq[F[_]: Functor, A](implicit FA: Eq[F[A]]): Eq[Yoneda[F, A]] = + new Eq[Yoneda[F, A]] { + def eqv(a: Yoneda[F, A], b: Yoneda[F, A]): Boolean = FA.eqv(a.run, b.run) + } + + checkAll("Yoneda[Option, ?]", FunctorTests[Yoneda[Option, ?]].functor[Int, Int, Int]) + checkAll("Functor[Yoneda[Option, ?]]", SerializableTests.serializable(Functor[Yoneda[Option, ?]])) + + test("toCoyoneda and then toYoneda is identity")(check { + forAll((y: Yoneda[Option, Int]) => y.toCoyoneda.toYoneda === y) + }) +} diff --git a/jvm/src/main/scala/cats/jvm/std/future.scala b/jvm/src/main/scala/cats/jvm/std/future.scala new file mode 100644 index 0000000000..ac0bc24012 --- /dev/null +++ b/jvm/src/main/scala/cats/jvm/std/future.scala @@ -0,0 +1,43 @@ +package cats +package jvm +package std + +import scala.concurrent.{Await, Future} +import scala.concurrent.{ExecutionContext => E} +import scala.concurrent.duration.FiniteDuration + +import cats.std.FutureCoflatMap +import cats.syntax.all._ + +object future extends FutureInstances0 + +trait FutureInstances0 extends FutureInstances1 { + def futureComonad(atMost: FiniteDuration)(implicit ec: E): Comonad[Future] = + new FutureCoflatMap with Comonad[Future] { + def extract[A](x: Future[A]): A = + Await.result(x, atMost) + } + + def futureOrder[A: Order](atMost: FiniteDuration)(implicit ec: E): Eq[Future[A]] = + new Order[Future[A]] { + def compare(x: Future[A], y: Future[A]): Int = + Await.result((x zip y).map { case (x, y) => x compare y }, atMost) + } +} + +trait FutureInstances1 extends FutureInstances2 { + def futurePartialOrder[A: PartialOrder](atMost: FiniteDuration)(implicit ec: E): PartialOrder[Future[A]] = + new PartialOrder[Future[A]] { + def partialCompare(x: Future[A], y: Future[A]): Double = + Await.result((x zip y).map { case (x, y) => x partialCompare y }, atMost) + } + +} + +trait FutureInstances2 { + def futureEq[A: Eq](atMost: FiniteDuration)(implicit ec: E): Eq[Future[A]] = + new Eq[Future[A]] { + def eqv(x: Future[A], y: Future[A]): Boolean = + Await.result((x zip y).map { case (x, y) => x === y }, atMost) + } +} diff --git a/tests/jvm/src/test/scala/cats/tests/FutureTests.scala b/jvm/src/test/scala/cats/tests/FutureTests.scala similarity index 93% rename from tests/jvm/src/test/scala/cats/tests/FutureTests.scala rename to jvm/src/test/scala/cats/tests/FutureTests.scala index 03fc173d2b..f9822dd747 100644 --- a/tests/jvm/src/test/scala/cats/tests/FutureTests.scala +++ b/jvm/src/test/scala/cats/tests/FutureTests.scala @@ -1,8 +1,11 @@ package cats +package jvm package tests import cats.data.Xor import cats.laws.discipline._ +import cats.jvm.std.future.{futureEq, futureComonad} +import cats.tests.CatsSuite import scala.concurrent.{Await, ExecutionContext, Future} import scala.concurrent.duration._ diff --git a/laws/js/src/main/scala/cats/laws/Platform.scala b/laws/js/src/main/scala/cats/laws/Platform.scala deleted file mode 100644 index 2bcebda707..0000000000 --- a/laws/js/src/main/scala/cats/laws/Platform.scala +++ /dev/null @@ -1,15 +0,0 @@ -package cats -package laws - -import org.scalacheck.{Arbitrary, Prop} -import org.scalacheck.Prop._ -import Prop.{False, Proof, Result} - -private[laws] object Platform { - - // Scala-js does not implement the Serializable interface, so we just return true. - @inline - def serializable[A](m: A): Prop = Prop { _ => - Result(status = Proof) - } -} diff --git a/laws/jvm/src/main/scala/cats/laws/Platform.scala b/laws/jvm/src/main/scala/cats/laws/Platform.scala deleted file mode 100644 index 56f1a00713..0000000000 --- a/laws/jvm/src/main/scala/cats/laws/Platform.scala +++ /dev/null @@ -1,35 +0,0 @@ -package cats -package laws - -import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, ObjectInputStream, ObjectOutputStream } - -import org.scalacheck.Prop -import org.scalacheck.Prop.{ False, Proof, Result } - -private[laws] object Platform { - - // scalastyle:off null - // Scala-js does not implement the Serializable interface, so the real test is for JVM only. - @inline - def serializable[A](a: A): Prop = - Prop { _ => - val baos = new ByteArrayOutputStream() - val oos = new ObjectOutputStream(baos) - var ois: ObjectInputStream = null - try { - oos.writeObject(a) - oos.close() - val bais = new ByteArrayInputStream(baos.toByteArray()) - ois = new ObjectInputStream(bais) - val a2 = ois.readObject() - ois.close() - Result(status = Proof) - } catch { case _: Throwable => - Result(status = False) - } finally { - oos.close() - if (ois != null) ois.close() - } - } - // scalastyle:on null -} diff --git a/laws/shared/src/main/scala/cats/laws/SerializableLaws.scala b/laws/shared/src/main/scala/cats/laws/SerializableLaws.scala deleted file mode 100644 index 596bd72891..0000000000 --- a/laws/shared/src/main/scala/cats/laws/SerializableLaws.scala +++ /dev/null @@ -1,11 +0,0 @@ -package cats -package laws - -import org.scalacheck.Prop - -/** - * Check for Java Serializability. - */ -object SerializableLaws { - def serializable[A](a: A): Prop = Platform.serializable(a) -} diff --git a/laws/shared/src/main/scala/cats/laws/AlternativeLaws.scala b/laws/src/main/scala/cats/laws/AlternativeLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/AlternativeLaws.scala rename to laws/src/main/scala/cats/laws/AlternativeLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/ApplicativeLaws.scala b/laws/src/main/scala/cats/laws/ApplicativeLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/ApplicativeLaws.scala rename to laws/src/main/scala/cats/laws/ApplicativeLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/ApplyLaws.scala b/laws/src/main/scala/cats/laws/ApplyLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/ApplyLaws.scala rename to laws/src/main/scala/cats/laws/ApplyLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/ArrowLaws.scala b/laws/src/main/scala/cats/laws/ArrowLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/ArrowLaws.scala rename to laws/src/main/scala/cats/laws/ArrowLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/BimonadLaws.scala b/laws/src/main/scala/cats/laws/BimonadLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/BimonadLaws.scala rename to laws/src/main/scala/cats/laws/BimonadLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/CategoryLaws.scala b/laws/src/main/scala/cats/laws/CategoryLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/CategoryLaws.scala rename to laws/src/main/scala/cats/laws/CategoryLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/ChoiceLaws.scala b/laws/src/main/scala/cats/laws/ChoiceLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/ChoiceLaws.scala rename to laws/src/main/scala/cats/laws/ChoiceLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/CoflatMapLaws.scala b/laws/src/main/scala/cats/laws/CoflatMapLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/CoflatMapLaws.scala rename to laws/src/main/scala/cats/laws/CoflatMapLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/ComonadLaws.scala b/laws/src/main/scala/cats/laws/ComonadLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/ComonadLaws.scala rename to laws/src/main/scala/cats/laws/ComonadLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/ComposeLaws.scala b/laws/src/main/scala/cats/laws/ComposeLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/ComposeLaws.scala rename to laws/src/main/scala/cats/laws/ComposeLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/ContravariantLaws.scala b/laws/src/main/scala/cats/laws/ContravariantLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/ContravariantLaws.scala rename to laws/src/main/scala/cats/laws/ContravariantLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/FlatMapLaws.scala b/laws/src/main/scala/cats/laws/FlatMapLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/FlatMapLaws.scala rename to laws/src/main/scala/cats/laws/FlatMapLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/FoldableLaws.scala b/laws/src/main/scala/cats/laws/FoldableLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/FoldableLaws.scala rename to laws/src/main/scala/cats/laws/FoldableLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/FunctorLaws.scala b/laws/src/main/scala/cats/laws/FunctorLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/FunctorLaws.scala rename to laws/src/main/scala/cats/laws/FunctorLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/InvariantLaws.scala b/laws/src/main/scala/cats/laws/InvariantLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/InvariantLaws.scala rename to laws/src/main/scala/cats/laws/InvariantLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/IsEq.scala b/laws/src/main/scala/cats/laws/IsEq.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/IsEq.scala rename to laws/src/main/scala/cats/laws/IsEq.scala diff --git a/laws/shared/src/main/scala/cats/laws/MonadCombineLaws.scala b/laws/src/main/scala/cats/laws/MonadCombineLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/MonadCombineLaws.scala rename to laws/src/main/scala/cats/laws/MonadCombineLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/MonadErrorLaws.scala b/laws/src/main/scala/cats/laws/MonadErrorLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/MonadErrorLaws.scala rename to laws/src/main/scala/cats/laws/MonadErrorLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/MonadFilterLaws.scala b/laws/src/main/scala/cats/laws/MonadFilterLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/MonadFilterLaws.scala rename to laws/src/main/scala/cats/laws/MonadFilterLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/MonadLaws.scala b/laws/src/main/scala/cats/laws/MonadLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/MonadLaws.scala rename to laws/src/main/scala/cats/laws/MonadLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/MonadReaderLaws.scala b/laws/src/main/scala/cats/laws/MonadReaderLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/MonadReaderLaws.scala rename to laws/src/main/scala/cats/laws/MonadReaderLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/MonadStateLaws.scala b/laws/src/main/scala/cats/laws/MonadStateLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/MonadStateLaws.scala rename to laws/src/main/scala/cats/laws/MonadStateLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/MonoidKLaws.scala b/laws/src/main/scala/cats/laws/MonoidKLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/MonoidKLaws.scala rename to laws/src/main/scala/cats/laws/MonoidKLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/ProfunctorLaws.scala b/laws/src/main/scala/cats/laws/ProfunctorLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/ProfunctorLaws.scala rename to laws/src/main/scala/cats/laws/ProfunctorLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/SemigroupKLaws.scala b/laws/src/main/scala/cats/laws/SemigroupKLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/SemigroupKLaws.scala rename to laws/src/main/scala/cats/laws/SemigroupKLaws.scala diff --git a/laws/src/main/scala/cats/laws/SerializableLaws.scala b/laws/src/main/scala/cats/laws/SerializableLaws.scala new file mode 100644 index 0000000000..eb532f1cf9 --- /dev/null +++ b/laws/src/main/scala/cats/laws/SerializableLaws.scala @@ -0,0 +1,52 @@ +package cats +package laws + +import org.scalacheck.Prop +import org.scalacheck.Prop.{ False, Proof, Result } + +import bricks.Platform + +/** + * Check for Java Serializability. + * + * This laws is only applicative on the JVM, but is something we want + * to be sure to enforce. Therefore, we use bricks.Platform to do a + * runtime check rather than create a separate jvm-laws project. + */ +object SerializableLaws { + + // This part is a bit tricky. Basically, we only want to test + // serializability on the JVM. + // + // The Platform.isJs macro will give us a literal true or false at + // compile time, so we rely on scalac to prune away the "other" + // branch. Thus, when scala.js look at this method it won't "see" + // the branch which was removed, and will avoid an error trying to + // suport java.io.*. + // + // This ends up being a lot nicer than having to split the entire + // laws project. + + def serializable[A](a: A): Prop = + if (Platform.isJs) Prop(_ => Result(status = Proof)) else Prop { _ => + import java.io.{ ByteArrayInputStream, ByteArrayOutputStream, ObjectInputStream, ObjectOutputStream } + + val baos = new ByteArrayOutputStream() + val oos = new ObjectOutputStream(baos) + var ois: ObjectInputStream = null + try { + oos.writeObject(a) + oos.close() + val bais = new ByteArrayInputStream(baos.toByteArray()) + ois = new ObjectInputStream(bais) + val a2 = ois.readObject() + ois.close() + Result(status = Proof) + } catch { case _: Throwable => + Result(status = False) + } finally { + oos.close() + if (ois != null) ois.close() + } + } +} diff --git a/laws/shared/src/main/scala/cats/laws/SplitLaws.scala b/laws/src/main/scala/cats/laws/SplitLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/SplitLaws.scala rename to laws/src/main/scala/cats/laws/SplitLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/StrongLaws.scala b/laws/src/main/scala/cats/laws/StrongLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/StrongLaws.scala rename to laws/src/main/scala/cats/laws/StrongLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/TraverseLaws.scala b/laws/src/main/scala/cats/laws/TraverseLaws.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/TraverseLaws.scala rename to laws/src/main/scala/cats/laws/TraverseLaws.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/AlternativeTests.scala b/laws/src/main/scala/cats/laws/discipline/AlternativeTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/AlternativeTests.scala rename to laws/src/main/scala/cats/laws/discipline/AlternativeTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/ApplicativeTests.scala b/laws/src/main/scala/cats/laws/discipline/ApplicativeTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/ApplicativeTests.scala rename to laws/src/main/scala/cats/laws/discipline/ApplicativeTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/ApplyTests.scala b/laws/src/main/scala/cats/laws/discipline/ApplyTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/ApplyTests.scala rename to laws/src/main/scala/cats/laws/discipline/ApplyTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/Arbitrary.scala b/laws/src/main/scala/cats/laws/discipline/Arbitrary.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/Arbitrary.scala rename to laws/src/main/scala/cats/laws/discipline/Arbitrary.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/ArbitraryK.scala b/laws/src/main/scala/cats/laws/discipline/ArbitraryK.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/ArbitraryK.scala rename to laws/src/main/scala/cats/laws/discipline/ArbitraryK.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/ArrowTests.scala b/laws/src/main/scala/cats/laws/discipline/ArrowTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/ArrowTests.scala rename to laws/src/main/scala/cats/laws/discipline/ArrowTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/BimonadTests.scala b/laws/src/main/scala/cats/laws/discipline/BimonadTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/BimonadTests.scala rename to laws/src/main/scala/cats/laws/discipline/BimonadTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/CategoryTests.scala b/laws/src/main/scala/cats/laws/discipline/CategoryTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/CategoryTests.scala rename to laws/src/main/scala/cats/laws/discipline/CategoryTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/ChoiceTests.scala b/laws/src/main/scala/cats/laws/discipline/ChoiceTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/ChoiceTests.scala rename to laws/src/main/scala/cats/laws/discipline/ChoiceTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/CoflatMapTests.scala b/laws/src/main/scala/cats/laws/discipline/CoflatMapTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/CoflatMapTests.scala rename to laws/src/main/scala/cats/laws/discipline/CoflatMapTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/ComonadTests.scala b/laws/src/main/scala/cats/laws/discipline/ComonadTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/ComonadTests.scala rename to laws/src/main/scala/cats/laws/discipline/ComonadTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/ComposeTests.scala b/laws/src/main/scala/cats/laws/discipline/ComposeTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/ComposeTests.scala rename to laws/src/main/scala/cats/laws/discipline/ComposeTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/Eq.scala b/laws/src/main/scala/cats/laws/discipline/Eq.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/Eq.scala rename to laws/src/main/scala/cats/laws/discipline/Eq.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/EqK.scala b/laws/src/main/scala/cats/laws/discipline/EqK.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/EqK.scala rename to laws/src/main/scala/cats/laws/discipline/EqK.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/FlatMapTests.scala b/laws/src/main/scala/cats/laws/discipline/FlatMapTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/FlatMapTests.scala rename to laws/src/main/scala/cats/laws/discipline/FlatMapTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/FoldableTests.scala b/laws/src/main/scala/cats/laws/discipline/FoldableTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/FoldableTests.scala rename to laws/src/main/scala/cats/laws/discipline/FoldableTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/FunctorTests.scala b/laws/src/main/scala/cats/laws/discipline/FunctorTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/FunctorTests.scala rename to laws/src/main/scala/cats/laws/discipline/FunctorTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/InvariantTests.scala b/laws/src/main/scala/cats/laws/discipline/InvariantTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/InvariantTests.scala rename to laws/src/main/scala/cats/laws/discipline/InvariantTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/MonadCombineTests.scala b/laws/src/main/scala/cats/laws/discipline/MonadCombineTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/MonadCombineTests.scala rename to laws/src/main/scala/cats/laws/discipline/MonadCombineTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/MonadErrorTests.scala b/laws/src/main/scala/cats/laws/discipline/MonadErrorTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/MonadErrorTests.scala rename to laws/src/main/scala/cats/laws/discipline/MonadErrorTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/MonadFilterTests.scala b/laws/src/main/scala/cats/laws/discipline/MonadFilterTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/MonadFilterTests.scala rename to laws/src/main/scala/cats/laws/discipline/MonadFilterTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/MonadReaderTests.scala b/laws/src/main/scala/cats/laws/discipline/MonadReaderTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/MonadReaderTests.scala rename to laws/src/main/scala/cats/laws/discipline/MonadReaderTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/MonadStateTests.scala b/laws/src/main/scala/cats/laws/discipline/MonadStateTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/MonadStateTests.scala rename to laws/src/main/scala/cats/laws/discipline/MonadStateTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/MonadTests.scala b/laws/src/main/scala/cats/laws/discipline/MonadTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/MonadTests.scala rename to laws/src/main/scala/cats/laws/discipline/MonadTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/MonoidKTests.scala b/laws/src/main/scala/cats/laws/discipline/MonoidKTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/MonoidKTests.scala rename to laws/src/main/scala/cats/laws/discipline/MonoidKTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/ProfunctorTests.scala b/laws/src/main/scala/cats/laws/discipline/ProfunctorTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/ProfunctorTests.scala rename to laws/src/main/scala/cats/laws/discipline/ProfunctorTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/SemigroupKTests.scala b/laws/src/main/scala/cats/laws/discipline/SemigroupKTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/SemigroupKTests.scala rename to laws/src/main/scala/cats/laws/discipline/SemigroupKTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/SerializableTests.scala b/laws/src/main/scala/cats/laws/discipline/SerializableTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/SerializableTests.scala rename to laws/src/main/scala/cats/laws/discipline/SerializableTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/SplitTests.scala b/laws/src/main/scala/cats/laws/discipline/SplitTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/SplitTests.scala rename to laws/src/main/scala/cats/laws/discipline/SplitTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/StrongTests.scala b/laws/src/main/scala/cats/laws/discipline/StrongTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/StrongTests.scala rename to laws/src/main/scala/cats/laws/discipline/StrongTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/TraverseTests.scala b/laws/src/main/scala/cats/laws/discipline/TraverseTests.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/TraverseTests.scala rename to laws/src/main/scala/cats/laws/discipline/TraverseTests.scala diff --git a/laws/shared/src/main/scala/cats/laws/discipline/package.scala b/laws/src/main/scala/cats/laws/discipline/package.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/discipline/package.scala rename to laws/src/main/scala/cats/laws/discipline/package.scala diff --git a/laws/shared/src/main/scala/cats/laws/package.scala b/laws/src/main/scala/cats/laws/package.scala similarity index 100% rename from laws/shared/src/main/scala/cats/laws/package.scala rename to laws/src/main/scala/cats/laws/package.scala diff --git a/project/plugins.sbt b/project/plugins.sbt index fe69c9d4b6..87da7b4a55 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -13,4 +13,4 @@ addSbtPlugin("pl.project13.scala"% "sbt-jmh" % "0.1.10") addSbtPlugin("org.scalastyle" %% "scalastyle-sbt-plugin" % "0.6.0") addSbtPlugin("org.scoverage" % "sbt-scoverage" % "1.2.0") addSbtPlugin("com.typesafe.sbt" % "sbt-git" % "0.8.4") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.4") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.5") diff --git a/state/src/test/scala/cats/state/StateTTests.scala b/state/src/test/scala/cats/state/StateTTests.scala index 7e163bb398..0b28502b8f 100644 --- a/state/src/test/scala/cats/state/StateTTests.scala +++ b/state/src/test/scala/cats/state/StateTTests.scala @@ -10,31 +10,31 @@ class StateTTests extends CatsSuite { import StateTTests._ test("basic state usage"){ - assert(add1.run(1).run == (2 -> 1)) + add1.run(1).run should === (2 -> 1) } test("traversing state is stack-safe"){ val ns = (0 to 100000).toList val x = ns.traverseU(_ => add1) - assert(x.runS(0).run == 100001) + x.runS(0).run should === (100001) } test("State.pure and StateT.pure are consistent")(check { forAll { (s: String, i: Int) => val state: State[String, Int] = State.pure(i) val stateT: State[String, Int] = StateT.pure(i) - state.run(s).run == stateT.run(s).run + state.run(s).run === stateT.run(s).run } }) test("Apply syntax is usable on State") { val x = add1 *> add1 - assert(x.runS(0).run == 2) + x.runS(0).run should === (2) } test("Singleton and instance inspect are consistent")(check { forAll { (s: String, i: Int) => - State.inspect[Int, String](_.toString).run(i).run == + State.inspect[Int, String](_.toString).run(i).run === State.pure[Int, Unit](()).inspect(_.toString).run(i).run } }) diff --git a/state/src/test/scala/cats/state/WordCountTest.scala b/state/src/test/scala/cats/state/WordCountTest.scala index 6b2c616656..0f6b680dae 100644 --- a/state/src/test/scala/cats/state/WordCountTest.scala +++ b/state/src/test/scala/cats/state/WordCountTest.scala @@ -45,8 +45,8 @@ class WordCountTest extends CatsSuite { val lineCount = allResults.first.second val charCount = allResults.second val wordCount = wordCountState.runA(false).run - assert(charCount.getConst == 96 && - lineCount.getConst == 2 && - wordCount.getConst == 17) + charCount.getConst should === (96) + lineCount.getConst should === (2) + wordCount.getConst should === (17) } } diff --git a/task/src/test/scala/cats/task/NondeterminismTests.scala b/task/src/test/scala/cats/task/NondeterminismTests.scala deleted file mode 100644 index 156e9aafb0..0000000000 --- a/task/src/test/scala/cats/task/NondeterminismTests.scala +++ /dev/null @@ -1,71 +0,0 @@ -package cats -package task - -import scala.math.pow -import scala.concurrent.{Await, ExecutionContext, Future} -import scala.concurrent.duration.Duration - -import java.util.concurrent.atomic.AtomicInteger - -import cats.tests.{CatsProps, CatsSuite} - -import org.scalacheck.Arbitrary._ -import org.scalacheck.Prop.BooleanOperators - -class NondeterminismCheck extends CatsProps { - - import cats.std.int._ - import cats.task.std.future._ - implicit val ec: ExecutionContext = ExecutionContext.global - implicit val nf: Nondeterminism[Future] = futureNondeterminism - - def setup(ns: List[Int]): (List[Future[Int]], AtomicInteger, AtomicInteger) = { - val total = new AtomicInteger(0) - val count = new AtomicInteger(0) - def sideEffects(n: Int): Future[Int] = - Future { total.addAndGet(n); count.addAndGet(1); n } - (ns.map(sideEffects), total, count) - } - - def verify[A](ns: List[Int], work: List[Future[Int]] => Future[A], expected: A): Unit = { - val (futures, total, count) = setup(ns) - val future = work(futures) - val result = Await.result(future, Duration("1s")) - result shouldBe expected - total.get shouldBe ns.sum - count.get shouldBe ns.size - } - - property("combineAll") { - forAll { (ns: List[Int]) => - verify(ns, fns => nf.combineAll(fns), ns.sum) - } - } - - property("unorderedGather") { - forAll { (ns: List[Int]) => - verify(ns, fns => nf.unorderedGather(fns).map(_.toSet), ns.toSet) - } - } - - property("orderedGather") { - forAll { (ns: List[Int]) => - verify(ns, fns => nf.orderedGather(fns), ns) - } - } - - property("asyncMap2") { - forAll { (x: Int, y: Int) => - verify(List(x, y), { case List(fx, fy) => nf.asyncMap2(fx, fy)(_ * _) }, x * y) - } - } - - property("foldFirst2") { - forAll { (x: Int, y: Int) => - val (List(fx, fy), _, _) = setup(List(x, y)) - val future = nf.foldFirst2(fx, fy)(_ * 2, _ * 3) - val result = Await.result(future, Duration("1s")) - result should (equal(x * 2) or equal(y * 3)) - } - } -} diff --git a/tests/js/src/test/scala/cats/tests/Platform.scala b/tests/js/src/test/scala/cats/tests/Platform.scala deleted file mode 100644 index 9cf5b60026..0000000000 --- a/tests/js/src/test/scala/cats/tests/Platform.scala +++ /dev/null @@ -1,16 +0,0 @@ -package cats -package tests - -import org.scalactic.anyvals.{PosZDouble, PosInt} - -private[tests] object Platform { - - // Override defaults to mimick scalatest 2.2.5 values - val minSuccessful = PosInt(10) - val maxDiscardedFactor = PosZDouble(50.0) - - trait UltraSlowCatsSuite extends CatsSuite { - implicit override val generatorDrivenConfig: PropertyCheckConfiguration = - PropertyCheckConfig(maxSize = 1, minSuccessful = 1) - } -} diff --git a/tests/jvm/src/test/scala/cats/tests/Platform.scala b/tests/jvm/src/test/scala/cats/tests/Platform.scala deleted file mode 100644 index a3857c491a..0000000000 --- a/tests/jvm/src/test/scala/cats/tests/Platform.scala +++ /dev/null @@ -1,13 +0,0 @@ -package cats -package tests - -import org.scalactic.anyvals.{PosZDouble, PosInt} - -private[tests] object Platform { - - // Override defaults to mimick scalatest 2.2.5 values - val minSuccessful = PosInt(100) - val maxDiscardedFactor = PosZDouble(5.0) - - trait UltraSlowCatsSuite extends CatsSuite {} -} diff --git a/tests/shared/src/test/scala/cats/tests/CatsSuite.scala b/tests/shared/src/test/scala/cats/tests/CatsSuite.scala deleted file mode 100644 index dffeac5b1a..0000000000 --- a/tests/shared/src/test/scala/cats/tests/CatsSuite.scala +++ /dev/null @@ -1,43 +0,0 @@ -package cats -package tests - -import cats.std.AllInstances -import cats.syntax.AllSyntax -import org.scalatest.{ FunSuite, PropSpec, Matchers } -import org.scalatest.prop.PropertyChecks -import org.typelevel.discipline.scalatest.Discipline - -import org.scalacheck.{Arbitrary, Gen} -import org.scalacheck.Arbitrary.arbitrary - -import scala.util.{Failure, Success, Try} - -/** - * An opinionated stack of traits to improve consistency and reduce - * boilerplate in Cats tests. - */ -trait CatsSuite extends FunSuite with Matchers with Discipline with AllInstances with AllSyntax with TestInstances { - implicit override val generatorDrivenConfig: PropertyCheckConfiguration = - PropertyCheckConfiguration( - minSuccessful = Platform.minSuccessful, - maxDiscardedFactor = Platform.maxDiscardedFactor) - // disable scalatest's === - override def convertToEqualizer[T](left: T): Equalizer[T] = ??? -} - -trait CatsProps extends PropSpec with Matchers with PropertyChecks with TestInstances { - implicit override val generatorDrivenConfig: PropertyCheckConfiguration = - PropertyCheckConfiguration( - minSuccessful = Platform.minSuccessful, - maxDiscardedFactor = Platform.maxDiscardedFactor) - // disable scalatest's === - override def convertToEqualizer[T](left: T): Equalizer[T] = ??? -} - -sealed trait TestInstances { - // To be replaced by https://github.com/rickynils/scalacheck/pull/170 - implicit def arbitraryTry[A: Arbitrary]: Arbitrary[Try[A]] = - Arbitrary(Gen.oneOf( - arbitrary[A].map(Success(_)), - arbitrary[Throwable].map(Failure(_)))) -} diff --git a/tests/shared/src/test/scala/cats/tests/AlgebraInvariantTests.scala b/tests/src/test/scala/cats/tests/AlgebraInvariantTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/AlgebraInvariantTests.scala rename to tests/src/test/scala/cats/tests/AlgebraInvariantTests.scala diff --git a/tests/src/test/scala/cats/tests/CatsEquality.scala b/tests/src/test/scala/cats/tests/CatsEquality.scala new file mode 100644 index 0000000000..a45dc9a4e6 --- /dev/null +++ b/tests/src/test/scala/cats/tests/CatsEquality.scala @@ -0,0 +1,29 @@ +package cats +package tests + +import org.scalactic._ +import TripleEqualsSupport.AToBEquivalenceConstraint +import TripleEqualsSupport.BToAEquivalenceConstraint + +// The code in this file was taken and only slightly modified from +// https://github.com/bvenners/equality-integration-demo +// Thanks for the great examples, Bill! + +final class CatsEquivalence[T](T: Eq[T]) extends Equivalence[T] { + def areEquivalent(a: T, b: T): Boolean = T.eqv(a, b) +} + +trait LowPriorityStrictCatsConstraints extends TripleEquals { + implicit def lowPriorityCatsCanEqual[A, B](implicit B: Eq[B], ev: A <:< B): CanEqual[A, B] = + new AToBEquivalenceConstraint[A, B](new CatsEquivalence(B), ev) +} + +trait StrictCatsEquality extends LowPriorityStrictCatsConstraints { + override def convertToEqualizer[T](left: T): Equalizer[T] = super.convertToEqualizer[T](left) + implicit override def convertToCheckingEqualizer[T](left: T): CheckingEqualizer[T] = new CheckingEqualizer(left) + override def unconstrainedEquality[A, B](implicit equalityOfA: Equality[A]): CanEqual[A, B] = super.unconstrainedEquality[A, B] + implicit def catsCanEqual[A, B](implicit A: Eq[A], ev: B <:< A): CanEqual[A, B] = + new BToAEquivalenceConstraint[A, B](new CatsEquivalence(A), ev) +} + +object StrictCatsEquality extends StrictCatsEquality diff --git a/tests/src/test/scala/cats/tests/CatsSuite.scala b/tests/src/test/scala/cats/tests/CatsSuite.scala new file mode 100644 index 0000000000..f0b88659bf --- /dev/null +++ b/tests/src/test/scala/cats/tests/CatsSuite.scala @@ -0,0 +1,63 @@ +package cats +package tests + +import bricks.Platform + +import cats.std.AllInstances +import cats.syntax.{AllSyntax, EqOps} + +import org.scalactic.anyvals.{PosZDouble, PosInt} +import org.scalatest.{FunSuite, PropSpec, Matchers} +import org.scalatest.prop.{Configuration, PropertyChecks} +import org.typelevel.discipline.scalatest.Discipline + +import org.scalacheck.{Arbitrary, Gen} +import org.scalacheck.Arbitrary.arbitrary + +import scala.util.{Failure, Success, Try} + +trait TestSettings extends Configuration with Matchers { + + lazy val checkConfiguration: PropertyCheckConfiguration = + PropertyCheckConfiguration( + minSuccessful = if (Platform.isJvm) PosInt(100) else PosInt(10), + maxDiscardedFactor = if (Platform.isJvm) PosZDouble(5.0) else PosZDouble(50.0)) + + lazy val slowCheckConfiguration: PropertyCheckConfiguration = + if (Platform.isJvm) checkConfiguration + else PropertyCheckConfig(maxSize = 1, minSuccessful = 1) +} + +/** + * An opinionated stack of traits to improve consistency and reduce + * boilerplate in Cats tests. + */ +trait CatsSuite extends FunSuite with Matchers with Discipline with TestSettings with AllInstances with AllSyntax with TestInstances with StrictCatsEquality { + implicit override val generatorDrivenConfig: PropertyCheckConfiguration = + checkConfiguration + + // disable Eq syntax (by making `eqSyntax` not implicit), since it collides + // with scalactic's equality + override def eqSyntax[A: Eq](a: A): EqOps[A] = new EqOps[A](a) +} + +trait CatsProps extends PropSpec with PropertyChecks with TestSettings with TestInstances { + implicit override val generatorDrivenConfig: PropertyCheckConfiguration = + checkConfiguration + + // disable scalatest's === + override def convertToEqualizer[T](left: T): Equalizer[T] = ??? +} + +trait SlowCatsSuite extends CatsSuite { + implicit override val generatorDrivenConfig: PropertyCheckConfiguration = + slowCheckConfiguration +} + +sealed trait TestInstances { + // To be replaced by https://github.com/rickynils/scalacheck/pull/170 + implicit def arbitraryTry[A: Arbitrary]: Arbitrary[Try[A]] = + Arbitrary(Gen.oneOf( + arbitrary[A].map(Success(_)), + arbitrary[Throwable].map(Failure(_)))) +} diff --git a/tests/shared/src/test/scala/cats/tests/CokleisliTests.scala b/tests/src/test/scala/cats/tests/CokleisliTests.scala similarity index 97% rename from tests/shared/src/test/scala/cats/tests/CokleisliTests.scala rename to tests/src/test/scala/cats/tests/CokleisliTests.scala index c550f921aa..f0c91edd3a 100644 --- a/tests/shared/src/test/scala/cats/tests/CokleisliTests.scala +++ b/tests/src/test/scala/cats/tests/CokleisliTests.scala @@ -11,7 +11,7 @@ import cats.laws.discipline.eq._ import org.scalacheck.Arbitrary import cats.laws.discipline.{SemigroupKTests, MonoidKTests} -class CokleisliTests extends Platform.UltraSlowCatsSuite { +class CokleisliTests extends SlowCatsSuite { implicit def cokleisliEq[F[_], A, B](implicit A: Arbitrary[F[A]], FB: Eq[B]): Eq[Cokleisli[F, A, B]] = Eq.by[Cokleisli[F, A, B], F[A] => B](_.run) diff --git a/tests/shared/src/test/scala/cats/tests/ConstTests.scala b/tests/src/test/scala/cats/tests/ConstTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/ConstTests.scala rename to tests/src/test/scala/cats/tests/ConstTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/EitherTests.scala b/tests/src/test/scala/cats/tests/EitherTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/EitherTests.scala rename to tests/src/test/scala/cats/tests/EitherTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/EvalTests.scala b/tests/src/test/scala/cats/tests/EvalTests.scala similarity index 96% rename from tests/shared/src/test/scala/cats/tests/EvalTests.scala rename to tests/src/test/scala/cats/tests/EvalTests.scala index 9b39cebcee..d9e84de10d 100644 --- a/tests/shared/src/test/scala/cats/tests/EvalTests.scala +++ b/tests/src/test/scala/cats/tests/EvalTests.scala @@ -37,10 +37,10 @@ class EvalTests extends CatsSuite { val (spooky, lz) = init(value) (0 until n).foreach { _ => val result = lz.value - assert(result === value) + result should === (value) spin ^= result.## } - assert(spooky.counter == numEvals) + spooky.counter should === (numEvals) } (0 to 2).foreach(n => nTimes(n, numCalls(n))) } diff --git a/tests/shared/src/test/scala/cats/tests/FoldableTests.scala b/tests/src/test/scala/cats/tests/FoldableTests.scala similarity index 91% rename from tests/shared/src/test/scala/cats/tests/FoldableTests.scala rename to tests/src/test/scala/cats/tests/FoldableTests.scala index 6f81e8804c..f23c7da9fc 100644 --- a/tests/shared/src/test/scala/cats/tests/FoldableTests.scala +++ b/tests/src/test/scala/cats/tests/FoldableTests.scala @@ -57,13 +57,13 @@ class FoldableTestsAdditional extends CatsSuite { // some basic sanity checks val ns = (1 to 10).toList val total = ns.sum - assert(F.foldLeft(ns, 0)(_ + _) == total) - assert(F.foldRight(ns, Now(0))((x, ly) => ly.map(x + _)).value == total) - assert(F.fold(ns) == total) + F.foldLeft(ns, 0)(_ + _) should === (total) + F.foldRight(ns, Now(0))((x, ly) => ly.map(x + _)).value should === (total) + F.fold(ns) should === (total) // more basic checks val names = List("Aaron", "Betty", "Calvin", "Deirdra") - assert(F.foldMap(names)(_.length) == names.map(_.length).sum) + F.foldMap(names)(_.length) should === (names.map(_.length).sum) // test trampolining val large = (1 to 10000).toList @@ -71,7 +71,7 @@ class FoldableTestsAdditional extends CatsSuite { // safely build large lists val larger = F.foldRight(large, Now(List.empty[Int]))((x, lxs) => lxs.map((x + 1) :: _)) - assert(larger.value == large.map(_ + 1)) + larger.value should === (large.map(_ + 1)) } test("Foldable[Stream]") { diff --git a/tests/shared/src/test/scala/cats/tests/FuncTests.scala b/tests/src/test/scala/cats/tests/FuncTests.scala similarity index 95% rename from tests/shared/src/test/scala/cats/tests/FuncTests.scala rename to tests/src/test/scala/cats/tests/FuncTests.scala index ed17c4c637..58cc648e0c 100644 --- a/tests/shared/src/test/scala/cats/tests/FuncTests.scala +++ b/tests/src/test/scala/cats/tests/FuncTests.scala @@ -42,12 +42,12 @@ class FuncTests extends CatsSuite { val g = appFunc { (x: Int) => List(x * 2) } val h = f product g val x = h.run(1) - assert((x.first, x.second) == ((Some(11), List(2)))) + (x.first, x.second) should === ((Some(11), List(2))) } test("traverse") { val f = Func.appFunc { (x: Int) => (Some(x + 10): Option[Int]) } val xs = f traverse List(1, 2, 3) - assert(xs == Some(List(11, 12, 13))) + xs should === (Some(List(11, 12, 13))) } } diff --git a/tests/shared/src/test/scala/cats/tests/FunctionTests.scala b/tests/src/test/scala/cats/tests/FunctionTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/FunctionTests.scala rename to tests/src/test/scala/cats/tests/FunctionTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/IorTests.scala b/tests/src/test/scala/cats/tests/IorTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/IorTests.scala rename to tests/src/test/scala/cats/tests/IorTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/KleisliTests.scala b/tests/src/test/scala/cats/tests/KleisliTests.scala similarity index 95% rename from tests/shared/src/test/scala/cats/tests/KleisliTests.scala rename to tests/src/test/scala/cats/tests/KleisliTests.scala index 886dc584d4..29feb692de 100644 --- a/tests/shared/src/test/scala/cats/tests/KleisliTests.scala +++ b/tests/src/test/scala/cats/tests/KleisliTests.scala @@ -109,7 +109,7 @@ class KleisliTests extends CatsSuite { test("lift") { val f = Kleisli.function { (x: Int) => (Some(x + 1): Option[Int]) } val l = f.lift[List] - assert((List(1, 2, 3) >>= l.run) == List(Some(2), Some(3), Some(4))) + (List(1, 2, 3) >>= l.run) should === (List(Some(2), Some(3), Some(4))) } test("transform") { @@ -118,7 +118,7 @@ class KleisliTests extends CatsSuite { val list = opt.transform(optToList) val is = 0.to(10).toList - assert(is.map(list.run) == is.map(Kleisli.function { (x: Int) => List(x.toDouble) }.run)) + is.map(list.run) should === (is.map(Kleisli.function { (x: Int) => List(x.toDouble) }.run)) } test("local") { @@ -129,6 +129,6 @@ class KleisliTests extends CatsSuite { val kconfig2 = Kleisli.function { (c: Config) => Option(c.i.toDouble) } val config = Config(0, "cats") - assert(kconfig1.run(config) == kconfig2.run(config)) + kconfig1.run(config) should === (kconfig2.run(config)) } } diff --git a/tests/shared/src/test/scala/cats/tests/ListTests.scala b/tests/src/test/scala/cats/tests/ListTests.scala similarity index 91% rename from tests/shared/src/test/scala/cats/tests/ListTests.scala rename to tests/src/test/scala/cats/tests/ListTests.scala index e70ce459e4..7e4b983644 100644 --- a/tests/shared/src/test/scala/cats/tests/ListTests.scala +++ b/tests/src/test/scala/cats/tests/ListTests.scala @@ -18,11 +18,11 @@ class ListTests extends CatsSuite with GeneratorDrivenPropertyChecks { test("nel => list => nel returns original nel")( forAll { fa: NonEmptyList[Int] => - assert(fa.unwrap.toNel == Some(fa)) + fa.unwrap.toNel should === (Some(fa)) } ) test("toNel on empty list returns None"){ - assert(List.empty[Int].toNel == None) + List.empty[Int].toNel should === (None) } } diff --git a/tests/shared/src/test/scala/cats/tests/ListWrapper.scala b/tests/src/test/scala/cats/tests/ListWrapper.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/ListWrapper.scala rename to tests/src/test/scala/cats/tests/ListWrapper.scala diff --git a/tests/shared/src/test/scala/cats/tests/MapTests.scala b/tests/src/test/scala/cats/tests/MapTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/MapTests.scala rename to tests/src/test/scala/cats/tests/MapTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/NaturalTransformationTests.scala b/tests/src/test/scala/cats/tests/NaturalTransformationTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/NaturalTransformationTests.scala rename to tests/src/test/scala/cats/tests/NaturalTransformationTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/OneAndTests.scala b/tests/src/test/scala/cats/tests/OneAndTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/OneAndTests.scala rename to tests/src/test/scala/cats/tests/OneAndTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/OptionTTests.scala b/tests/src/test/scala/cats/tests/OptionTTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/OptionTTests.scala rename to tests/src/test/scala/cats/tests/OptionTTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/OptionTests.scala b/tests/src/test/scala/cats/tests/OptionTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/OptionTests.scala rename to tests/src/test/scala/cats/tests/OptionTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/ProdTests.scala b/tests/src/test/scala/cats/tests/ProdTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/ProdTests.scala rename to tests/src/test/scala/cats/tests/ProdTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/RegressionTests.scala b/tests/src/test/scala/cats/tests/RegressionTests.scala similarity index 86% rename from tests/shared/src/test/scala/cats/tests/RegressionTests.scala rename to tests/src/test/scala/cats/tests/RegressionTests.scala index 5484ce91ea..6f5908a643 100644 --- a/tests/shared/src/test/scala/cats/tests/RegressionTests.scala +++ b/tests/src/test/scala/cats/tests/RegressionTests.scala @@ -27,6 +27,7 @@ class RegressionTests extends CatsSuite { val buf = mutable.ListBuffer.empty[String] case class Person(id: Int, name: String) + implicit val personEq: Eq[Person] = Eq.fromUniversalEquals def alloc(name: String): State[Int, Person] = State { id => @@ -38,18 +39,18 @@ class RegressionTests extends CatsSuite { // test result order val ons = List(Option(1), Option(2), Option(3)) - assert(Traverse[List].sequence(ons) == Some(List(1, 2, 3))) + Traverse[List].sequence(ons) should === (Some(List(1, 2, 3))) // test order of effects using a contrived, unsafe state monad. val names = List("Alice", "Bob", "Claire") val allocated = names.map(alloc) val state = Traverse[List].sequence[State[Int, ?],Person](allocated) val (people, counter) = state.run(0) - assert(people == List(Person(0, "Alice"), Person(1, "Bob"), Person(2, "Claire"))) - assert(counter == 3) + people should === (List(Person(0, "Alice"), Person(1, "Bob"), Person(2, "Claire"))) + counter should === (3) // ensure that side-effects occurred in "correct" order - assert(buf.toList == names) + buf.toList should === (names) } test("#167: confirm ap2 order") { @@ -57,7 +58,7 @@ class RegressionTests extends CatsSuite { State[String, Unit](s => ((), s + "1")), State[String, Unit](s => ((), s + "2")) )(State.instance[String].pure((_: Unit, _: Unit) => ())).run("")._2 - assert(twelve == "12") + twelve should === ("12") } test("#167: confirm map2 order") { @@ -65,7 +66,7 @@ class RegressionTests extends CatsSuite { State[String, Unit](s => ((), s + "1")), State[String, Unit](s => ((), s + "2")) )((_: Unit, _: Unit) => ()).run("")._2 - assert(twelve == "12") + twelve should === ("12") } test("#167: confirm map3 order") { @@ -74,7 +75,7 @@ class RegressionTests extends CatsSuite { State[String, Unit](s => ((), s + "2")), State[String, Unit](s => ((), s + "3")) )((_: Unit, _: Unit, _: Unit) => ()).run("")._2 - assert(oneTwoThree == "123") + oneTwoThree should === ("123") } test("#500: foldMap - traverse consistency") { diff --git a/tests/shared/src/test/scala/cats/tests/SetTests.scala b/tests/src/test/scala/cats/tests/SetTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/SetTests.scala rename to tests/src/test/scala/cats/tests/SetTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/StreamTests.scala b/tests/src/test/scala/cats/tests/StreamTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/StreamTests.scala rename to tests/src/test/scala/cats/tests/StreamTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/StreamingTTests.scala b/tests/src/test/scala/cats/tests/StreamingTTests.scala similarity index 99% rename from tests/shared/src/test/scala/cats/tests/StreamingTTests.scala rename to tests/src/test/scala/cats/tests/StreamingTTests.scala index f238e9bcf4..17cea0c2b3 100644 --- a/tests/shared/src/test/scala/cats/tests/StreamingTTests.scala +++ b/tests/src/test/scala/cats/tests/StreamingTTests.scala @@ -50,6 +50,6 @@ class SpecificStreamingTTests extends CatsSuite { val x = fa.flatMap(f).flatMap(g) val y = fa.flatMap(a => f(a).flatMap(g)) - assert(x === y) + x should === (y) } } diff --git a/tests/shared/src/test/scala/cats/tests/StreamingTests.scala b/tests/src/test/scala/cats/tests/StreamingTests.scala similarity index 98% rename from tests/shared/src/test/scala/cats/tests/StreamingTests.scala rename to tests/src/test/scala/cats/tests/StreamingTests.scala index 16adba5406..e566ecd958 100644 --- a/tests/shared/src/test/scala/cats/tests/StreamingTests.scala +++ b/tests/src/test/scala/cats/tests/StreamingTests.scala @@ -262,6 +262,10 @@ class AdHocStreamingTests extends CatsProps { isok(bomb.take(0)) } + property("take up to the last valid element"){ + isok(dangerous.take(3).toList) + } + property("lazy drop") { isok(bomb.drop(10)) isok(bomb.drop(0)) diff --git a/tests/shared/src/test/scala/cats/tests/SyntaxTests.scala b/tests/src/test/scala/cats/tests/SyntaxTests.scala similarity index 97% rename from tests/shared/src/test/scala/cats/tests/SyntaxTests.scala rename to tests/src/test/scala/cats/tests/SyntaxTests.scala index 71ff00640e..098ed3e359 100644 --- a/tests/shared/src/test/scala/cats/tests/SyntaxTests.scala +++ b/tests/src/test/scala/cats/tests/SyntaxTests.scala @@ -1,6 +1,8 @@ package cats package tests +import cats.std.AllInstances +import cats.syntax.AllSyntax import algebra.laws.GroupLaws import cats.functor.{Invariant, Contravariant} import cats.laws.discipline.SerializableTests @@ -27,7 +29,7 @@ import scala.reflect.runtime.universe.TypeTag * * None of these tests should ever run, or do any runtime checks. */ -class SyntaxTests extends CatsSuite with PropertyChecks { +class SyntaxTests extends AllInstances with AllSyntax { // pretend we have a value of type A def mock[A]: A = ??? diff --git a/tests/shared/src/test/scala/cats/tests/UnapplyTests.scala b/tests/src/test/scala/cats/tests/UnapplyTests.scala similarity index 81% rename from tests/shared/src/test/scala/cats/tests/UnapplyTests.scala rename to tests/src/test/scala/cats/tests/UnapplyTests.scala index 5cdaf8873a..4ec202b540 100644 --- a/tests/shared/src/test/scala/cats/tests/UnapplyTests.scala +++ b/tests/src/test/scala/cats/tests/UnapplyTests.scala @@ -9,11 +9,11 @@ class UnapplyTests extends CatsSuite { test("Unapply works for stuff already the right kind") { val x = Traverse[List].traverseU(List(1,2,3))(Option(_)) - assert(x == Some(List(1,2,3))) + x should === (Some(List(1,2,3))) } test("Unapply works for F[_,_] with the left fixed") { val x = Traverse[List].traverseU(List(1,2,3))(Xor.right(_)) - assert(x == Xor.right(List(1,2,3))) + (x: String Xor List[Int]) should === (Xor.right(List(1,2,3))) } } diff --git a/tests/shared/src/test/scala/cats/tests/ValidatedTests.scala b/tests/src/test/scala/cats/tests/ValidatedTests.scala similarity index 96% rename from tests/shared/src/test/scala/cats/tests/ValidatedTests.scala rename to tests/src/test/scala/cats/tests/ValidatedTests.scala index 4b11055dfc..887bcc303e 100644 --- a/tests/shared/src/test/scala/cats/tests/ValidatedTests.scala +++ b/tests/src/test/scala/cats/tests/ValidatedTests.scala @@ -21,7 +21,7 @@ class ValidatedTests extends CatsSuite { test("ap2 combines failures in order") { val plus = (_: Int) + (_: Int) - assert(Applicative[Validated[String, ?]].ap2(Invalid("1"), Invalid("2"))(Valid(plus)) == Invalid("12")) + Applicative[Validated[String, ?]].ap2(Invalid("1"), Invalid("2"))(Valid(plus)) should === (Invalid("12")) } test("fromTryCatch catches matching exceptions") { diff --git a/tests/shared/src/test/scala/cats/tests/VectorTests.scala b/tests/src/test/scala/cats/tests/VectorTests.scala similarity index 100% rename from tests/shared/src/test/scala/cats/tests/VectorTests.scala rename to tests/src/test/scala/cats/tests/VectorTests.scala diff --git a/tests/shared/src/test/scala/cats/tests/XorTTests.scala b/tests/src/test/scala/cats/tests/XorTTests.scala similarity index 81% rename from tests/shared/src/test/scala/cats/tests/XorTTests.scala rename to tests/src/test/scala/cats/tests/XorTTests.scala index 44cadbe744..1c74a680a6 100644 --- a/tests/shared/src/test/scala/cats/tests/XorTTests.scala +++ b/tests/src/test/scala/cats/tests/XorTTests.scala @@ -68,17 +68,13 @@ class XorTTests extends CatsSuite { } test("recover ignores unhandled values") { - assert { - val xort = XorT.left[Id, String, Int]("xort") - xort.recover { case "notxort" => 5 } === xort - } + val xort = XorT.left[Id, String, Int]("xort") + xort.recover { case "notxort" => 5 } should === (xort) } test("recover ignores the right side") { - assert { - val xort = XorT.right[Id, String, Int](10) - xort.recover { case "xort" => 5 } === xort - } + val xort = XorT.right[Id, String, Int](10) + xort.recover { case "xort" => 5 } should === (xort) } test("recoverWith recovers handled values") { @@ -89,16 +85,12 @@ class XorTTests extends CatsSuite { } test("recoverWith ignores unhandled values") { - assert { - val xort = XorT.left[Id, String, Int]("xort") - xort.recoverWith { case "notxort" => XorT.right[Id, String, Int](5) } === xort - } + val xort = XorT.left[Id, String, Int]("xort") + xort.recoverWith { case "notxort" => XorT.right[Id, String, Int](5) } should === (xort) } test("recoverWith ignores the right side") { - assert { - val xort = XorT.right[Id, String, Int](10) - xort.recoverWith { case "xort" => XorT.right[Id, String, Int](5) } === xort - } + val xort = XorT.right[Id, String, Int](10) + xort.recoverWith { case "xort" => XorT.right[Id, String, Int](5) } should === (xort) } } diff --git a/tests/shared/src/test/scala/cats/tests/XorTests.scala b/tests/src/test/scala/cats/tests/XorTests.scala similarity index 89% rename from tests/shared/src/test/scala/cats/tests/XorTests.scala rename to tests/src/test/scala/cats/tests/XorTests.scala index b209792fd2..30d8c86d5b 100644 --- a/tests/shared/src/test/scala/cats/tests/XorTests.scala +++ b/tests/src/test/scala/cats/tests/XorTests.scala @@ -91,17 +91,13 @@ class XorTests extends CatsSuite { } test("recover ignores unhandled values") { - assert { - val xor = Xor.left[String, Int]("xor") - xor.recover { case "notxor" => 5 } === xor - } + val xor = Xor.left[String, Int]("xor") + xor.recover { case "notxor" => 5 } should === (xor) } test("recover ignores the right side") { - assert { - val xor = Xor.right[String, Int](10) - xor.recover { case "xor" => 5 } === xor - } + val xor = Xor.right[String, Int](10) + xor.recover { case "xor" => 5 } should === (xor) } test("recoverWith recovers handled values") { @@ -112,17 +108,13 @@ class XorTests extends CatsSuite { } test("recoverWith ignores unhandled values") { - assert { - val xor = Xor.left[String, Int]("xor") - xor.recoverWith { case "notxor" => Xor.right[String, Int](5) } === xor - } + val xor = Xor.left[String, Int]("xor") + xor.recoverWith { case "notxor" => Xor.right[String, Int](5) } should === (xor) } test("recoverWith ignores the right side") { - assert { - val xor = Xor.right[String, Int](10) - xor.recoverWith { case "xor" => Xor.right[String, Int](5) } === xor - } + val xor = Xor.right[String, Int](10) + xor.recoverWith { case "xor" => Xor.right[String, Int](5) } should === (xor) } check {