Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added TestControl, with first-class support for time mocking #2276

Merged
merged 31 commits into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
6a81288
Completely reworked TestContext API
djspiewak Aug 29, 2021
7c143dd
Added `TestControl` for creating and controlling a mock runtime
djspiewak Aug 30, 2021
125ad7e
Added support for reading (and configuring) the source of randomness …
djspiewak Aug 30, 2021
c902d9e
Removed unnecessary import
djspiewak Aug 30, 2021
579f468
Added mima exclusion for new `TestContext` constructor
djspiewak Aug 30, 2021
0a62cbd
Fixed scaladoc reference
djspiewak Aug 30, 2021
fe9502f
Adjusted bincompat shim to be closer to the same semantics
djspiewak Aug 30, 2021
fc65cc2
Made everything blocking and stuff
djspiewak Aug 30, 2021
9168ec3
Removed negative epoch since a) it was confusing, and b) we no longer…
djspiewak Aug 30, 2021
fab668b
Merge branch 'series/3.x' into feature/time-mocking
djspiewak Sep 8, 2021
851ce12
Get a new ticker for each test iteration to avoid flakiness
djspiewak Sep 8, 2021
360dff3
Removed `blocking` from `TestContext`
djspiewak Sep 8, 2021
73b667a
Merge branch 'series/3.x' into feature/time-mocking
djspiewak Sep 9, 2021
e4945f4
Fixed silly oversight
djspiewak Sep 9, 2021
a5d05b2
Added `TestControl.execute` and `executeFully`
djspiewak Sep 9, 2021
aba30df
Added tests and infix syntax for `TestControl`
djspiewak Sep 9, 2021
48193be
Added macrotask-executor exclusions via specs2
djspiewak Sep 9, 2021
7e86798
Fixed excludes hopefully
djspiewak Sep 9, 2021
baf65a4
Removed unneeded syntax import
djspiewak Sep 9, 2021
7eed1d3
Sigh…
djspiewak Sep 9, 2021
ae53396
Added `replicateA` override
djspiewak Sep 9, 2021
eec8680
Face, meet keyboard
djspiewak Sep 9, 2021
c458766
More... dependencies...
djspiewak Sep 9, 2021
81e0685
Refactored `TestControl` API to be pure
djspiewak Sep 10, 2021
6c48c92
Ensure blocking tasks get appropriately marked
djspiewak Sep 10, 2021
b15d57b
Adjusted scaladoc on `TestContext` to clarify its low-level nature
djspiewak Sep 10, 2021
d227caa
Replaced "unknown" with dots to mirror `IO`'s Show
djspiewak Sep 12, 2021
154f2d1
Revised API to work in terms of `Outcome` rather than `Either`
djspiewak Sep 12, 2021
4e6597e
Replaced `executeFully` with `executeEmbed`
djspiewak Sep 12, 2021
09d830c
Merge branch 'series/3.x' into feature/time-mocking
djspiewak Sep 12, 2021
2022ef9
Adjusted the signature of `executeEmbed` to produce an `IO[A]`
djspiewak Sep 16, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 52 additions & 8 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@ val ScalaCheckVersion = "1.15.4"
val DisciplineVersion = "1.2.2"
val CoopVersion = "1.1.1"

val MacrotaskExecutorVersion = "0.2.0"

replaceCommandAlias("ci", CI.AllCIs.map(_.toString).mkString)

addCommandAlias(CI.JVM.command, CI.JVM.toString)
Expand Down Expand Up @@ -264,9 +266,23 @@ lazy val kernel = crossProject(JSPlatform, JVMPlatform)
.in(file("kernel"))
.settings(
name := "cats-effect-kernel",
libraryDependencies ++= Seq(
("org.specs2" %%% "specs2-core" % Specs2Version % Test).cross(CrossVersion.for3Use2_13),
"org.typelevel" %%% "cats-core" % CatsVersion)
libraryDependencies += "org.typelevel" %%% "cats-core" % CatsVersion)
.jvmSettings(libraryDependencies += {
if (isDotty.value)
("org.specs2" %%% "specs2-core" % Specs2Version % Test).cross(CrossVersion.for3Use2_13)
else
"org.specs2" %%% "specs2-core" % Specs2Version % Test
})
.jsSettings(
libraryDependencies += {
if (isDotty.value)
("org.specs2" %%% "specs2-core" % Specs2Version % Test)
.cross(CrossVersion.for3Use2_13)
.exclude("org.scala-js", "scala-js-macrotask-executor_sjs1_2.13")
else
"org.specs2" %%% "specs2-core" % Specs2Version % Test
},
libraryDependencies += "org.scala-js" %%% "scala-js-macrotask-executor" % MacrotaskExecutorVersion % Test
)

/**
Expand All @@ -281,7 +297,10 @@ lazy val kernelTestkit = crossProject(JSPlatform, JVMPlatform)
libraryDependencies ++= Seq(
"org.typelevel" %%% "cats-free" % CatsVersion,
"org.scalacheck" %%% "scalacheck" % ScalaCheckVersion,
"org.typelevel" %%% "coop" % CoopVersion)
"org.typelevel" %%% "coop" % CoopVersion),
mimaBinaryIssueFilters ++= Seq(
ProblemFilters.exclude[DirectMissingMethodProblem](
"cats.effect.kernel.testkit.TestContext.this"))
)

/**
Expand Down Expand Up @@ -380,8 +399,7 @@ lazy val core = crossProject(JSPlatform, JVMPlatform)
javacOptions ++= Seq("-source", "1.8", "-target", "1.8")
)
.jsSettings(
libraryDependencies += "org.scala-js" %%% "scala-js-macrotask-executor" % "0.2.0"
)
libraryDependencies += "org.scala-js" %%% "scala-js-macrotask-executor" % MacrotaskExecutorVersion)

/**
* Test support for the core project, providing various helpful instances like ScalaCheck
Expand All @@ -392,7 +410,21 @@ lazy val testkit = crossProject(JSPlatform, JVMPlatform)
.dependsOn(core, kernelTestkit)
.settings(
name := "cats-effect-testkit",
libraryDependencies ++= Seq("org.scalacheck" %%% "scalacheck" % ScalaCheckVersion))
libraryDependencies += "org.scalacheck" %%% "scalacheck" % ScalaCheckVersion)
.jvmSettings(libraryDependencies += {
if (isDotty.value)
("org.specs2" %%% "specs2-core" % Specs2Version % Test).cross(CrossVersion.for3Use2_13)
else
"org.specs2" %%% "specs2-core" % Specs2Version % Test
})
.jsSettings(libraryDependencies += {
if (isDotty.value)
("org.specs2" %%% "specs2-core" % Specs2Version % Test)
.cross(CrossVersion.for3Use2_13)
.exclude("org.scala-js", "scala-js-macrotask-executor_sjs1_2.13")
else
"org.specs2" %%% "specs2-core" % Specs2Version % Test
})

/**
* Unit tests for the core project, utilizing the support provided by testkit.
Expand Down Expand Up @@ -422,16 +454,28 @@ lazy val std = crossProject(JSPlatform, JVMPlatform)
.dependsOn(kernel)
.settings(
name := "cats-effect-std",
libraryDependencies += "org.scalacheck" %%% "scalacheck" % ScalaCheckVersion % Test)
.jvmSettings(libraryDependencies += {
if (isDotty.value)
("org.specs2" %%% "specs2-scalacheck" % Specs2Version % Test)
.cross(CrossVersion.for3Use2_13)
.exclude("org.scalacheck", "scalacheck_2.13")
.exclude("org.scalacheck", "scalacheck_sjs1_2.13")
else
"org.specs2" %%% "specs2-scalacheck" % Specs2Version % Test
})
.jsSettings(
libraryDependencies += {
if (isDotty.value)
("org.specs2" %%% "specs2-scalacheck" % Specs2Version % Test)
.cross(CrossVersion.for3Use2_13)
.exclude("org.scala-js", "scala-js-macrotask-executor_sjs1_2.13")
.exclude("org.scalacheck", "scalacheck_2.13")
.exclude("org.scalacheck", "scalacheck_sjs1_2.13")
else
"org.specs2" %%% "specs2-scalacheck" % Specs2Version % Test
},
libraryDependencies += "org.scalacheck" %%% "scalacheck" % ScalaCheckVersion % Test
libraryDependencies += "org.scala-js" %%% "scala-js-macrotask-executor" % MacrotaskExecutorVersion % Test
)

/**
Expand Down
16 changes: 16 additions & 0 deletions core/shared/src/main/scala/cats/effect/IO.scala
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,19 @@ sealed abstract class IO[+A] private () extends IOPlatform[A] {
def redeemWith[B](recover: Throwable => IO[B], bind: A => IO[B]): IO[B] =
attempt.flatMap(_.fold(recover, bind))

def replicateA(n: Int): IO[List[A]] =
if (n <= 0)
IO.pure(Nil)
else
flatMap(a => replicateA(n - 1).map(a :: _))

// TODO PR to cats
def replicateA_(n: Int): IO[Unit] =
if (n <= 0)
IO.unit
else
flatMap(_ => replicateA_(n - 1))

/**
* Returns an IO that will delay the execution of the source by the given duration.
*/
Expand Down Expand Up @@ -1450,6 +1463,9 @@ object IO extends IOCompanionPlatform with IOLowPriorityImplicits {
override def productR[A, B](left: IO[A])(right: IO[B]): IO[B] =
left.productR(right)

override def replicateA[A](n: Int, fa: IO[A]): IO[List[A]] =
fa.replicateA(n)

def start[A](fa: IO[A]): IO[FiberIO[A]] =
fa.start

Expand Down
2 changes: 0 additions & 2 deletions example/js/src/main/scala/cats/effect/example/Example.scala
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@
package cats.effect
package example

import cats.syntax.all._

object Example extends IOApp {

def run(args: List[String]): IO[ExitCode] =
Expand Down
Loading