From 99563ff2d1747f6a79e7ddfc52f168ccdcae9644 Mon Sep 17 00:00:00 2001 From: Anton Sviridov Date: Tue, 22 Dec 2020 19:22:53 +0000 Subject: [PATCH] TEMPORARY: verify that implicit conversion is the one to blame --- .../src/weaver/scalacheck/Checkers.scala | 31 ++++++++++--------- .../src/weaver/scalacheck/CheckersTest.scala | 14 ++++----- .../scalacheck/PropertyDogFoodTest.scala | 19 +++++++++--- 3 files changed, 38 insertions(+), 26 deletions(-) diff --git a/modules/scalacheck/src/weaver/scalacheck/Checkers.scala b/modules/scalacheck/src/weaver/scalacheck/Checkers.scala index 06439f96..0b615a8a 100644 --- a/modules/scalacheck/src/weaver/scalacheck/Checkers.scala +++ b/modules/scalacheck/src/weaver/scalacheck/Checkers.scala @@ -22,18 +22,13 @@ trait Checkers[F[_]] { // Configuration for property-based tests def checkConfig: CheckConfig = CheckConfig.default - def forallCheck[A1: Arbitrary: Show](f: A1 => Prop)( - implicit loc: SourceLocation): F[Expectations] = - forall(implicitly[Arbitrary[A1]].arbitrary)(f) - - def forall[A1: Arbitrary: Show](f: A1 => Prop)( implicit loc: SourceLocation): F[Expectations] = - forall(implicitly[Arbitrary[A1]].arbitrary)(f) + forall(implicitly[Arbitrary[A1]].arbitrary).apply(f) def forall[A1: Arbitrary: Show, A2: Arbitrary: Show](f: (A1, A2) => Prop)( implicit loc: SourceLocation): F[Expectations] = - forall(implicitly[Arbitrary[(A1, A2)]].arbitrary)(f.tupled) + forall(implicitly[Arbitrary[(A1, A2)]].arbitrary).apply(f.tupled) def forall[A1: Arbitrary: Show, A2: Arbitrary: Show, A3: Arbitrary: Show]( f: (A1, A2, A3) => Prop)( @@ -41,7 +36,7 @@ trait Checkers[F[_]] { implicit val tuple3Show: Show[(A1, A2, A3)] = { case (a1, a2, a3) => s"(${a1.show},${a2.show},${a3.show})" } - forall(implicitly[Arbitrary[(A1, A2, A3)]].arbitrary)(f.tupled) + forall(implicitly[Arbitrary[(A1, A2, A3)]].arbitrary).apply(f.tupled) } def forall[ @@ -54,7 +49,7 @@ trait Checkers[F[_]] { implicit val tuple3Show: Show[(A1, A2, A3, A4)] = { case (a1, a2, a3, a4) => s"(${a1.show},${a2.show},${a3.show},${a4.show})" } - forall(implicitly[Arbitrary[(A1, A2, A3, A4)]].arbitrary)(f.tupled) + forall(implicitly[Arbitrary[(A1, A2, A3, A4)]].arbitrary).apply(f.tupled) } def forall[ @@ -69,7 +64,8 @@ trait Checkers[F[_]] { case (a1, a2, a3, a4, a5) => s"(${a1.show},${a2.show},${a3.show},${a4.show},${a5.show})" } - forall(implicitly[Arbitrary[(A1, A2, A3, A4, A5)]].arbitrary)(f.tupled) + forall(implicitly[Arbitrary[(A1, A2, A3, A4, A5)]].arbitrary).apply( + f.tupled) } def forall[ @@ -85,15 +81,22 @@ trait Checkers[F[_]] { case (a1, a2, a3, a4, a5, a6) => s"(${a1.show},${a2.show},${a3.show},${a4.show},${a5.show},${a6.show})" } - forall(implicitly[Arbitrary[(A1, A2, A3, A4, A5, A6)]].arbitrary)(f.tupled) + forall(implicitly[Arbitrary[(A1, A2, A3, A4, A5, A6)]].arbitrary).apply( + f.tupled) } /** ScalaCheck test parameters instance. */ val numbers = fs2.Stream.iterate(1)(_ + 1) - def forall[A: Show](gen: Gen[A])(f: A => Prop)( - implicit loc: SourceLocation): F[Expectations] = - Ref[F].of(Status.start[A]).flatMap(forall_(gen, f)) + def forall[A](gen: Gen[A])(implicit sw: Show[A], loc: SourceLocation) = + new PartiallyAppliedGenForall[A](gen) + + class PartiallyAppliedGenForall[A](gen: Gen[A])( + implicit sw: Show[A], + loc: SourceLocation) { + def apply(f: A => Prop) = + Ref[F].of(Status.start[A]).flatMap(forall_(gen, f)) + } private def forall_[A: Show](gen: Gen[A], f: A => Prop)( state: Ref[F, Status[A]])( diff --git a/modules/scalacheck/test/src/weaver/scalacheck/CheckersTest.scala b/modules/scalacheck/test/src/weaver/scalacheck/CheckersTest.scala index e8fbee4e..77704b14 100644 --- a/modules/scalacheck/test/src/weaver/scalacheck/CheckersTest.scala +++ b/modules/scalacheck/test/src/weaver/scalacheck/CheckersTest.scala @@ -14,44 +14,44 @@ object CheckersTest extends SimpleIOSuite with IOCheckers { super.checkConfig.copy(perPropertyParallelism = 100) simpleTest("universal") { - forall(Gen.posNum[Int]) { a => + forall(Gen.posNum[Int]).apply { a => expect(a > 0) } } simpleTest("form 1") { forall { (a: Int) => - expect(a * 2 == 2 * a) + IO(expect(a * 2 == 2 * a)) } } simpleTest("form 2") { forall { (a1: Int, a2: Int) => - expect(a1 * a2 == a2 * a1) + IO(expect(a1 * a2 == a2 * a1)) } } simpleTest("form 3") { forall { (a1: Int, a2: Int, a3: Int) => - expect(a1 * a2 * a3 == a3 * a2 * a1) + IO(expect(a1 * a2 * a3 == a3 * a2 * a1)) } } simpleTest("form 4") { forall { (a1: Int, a2: Int, a3: Int, a4: Int) => - expect(a1 * a2 * a3 * a4 == a4 * a3 * a2 * a1) + IO(expect(a1 * a2 * a3 * a4 == a4 * a3 * a2 * a1)) } } simpleTest("form 5") { forall { (a1: Int, a2: Int, a3: Int, a4: Int, a5: Int) => - expect(a1 * a2 * a3 * a4 * a5 == a5 * a4 * a3 * a2 * a1) + IO(expect(a1 * a2 * a3 * a4 * a5 == a5 * a4 * a3 * a2 * a1)) } } simpleTest("form 6") { forall { (a1: Int, a2: Int, a3: Int, a4: Int, a5: Int, a6: Int) => - expect(a1 * a2 * a3 * a4 * a5 * a6 == a6 * a5 * a4 * a3 * a2 * a1) + IO(expect(a1 * a2 * a3 * a4 * a5 * a6 == a6 * a5 * a4 * a3 * a2 * a1)) } } diff --git a/modules/scalacheck/test/src/weaver/scalacheck/PropertyDogFoodTest.scala b/modules/scalacheck/test/src/weaver/scalacheck/PropertyDogFoodTest.scala index 940019e4..7148688c 100644 --- a/modules/scalacheck/test/src/weaver/scalacheck/PropertyDogFoodTest.scala +++ b/modules/scalacheck/test/src/weaver/scalacheck/PropertyDogFoodTest.scala @@ -7,7 +7,6 @@ import cats.effect.{ IO, Resource } import cats.syntax.all._ import weaver.framework._ -import org.scalacheck.Gen object PropertyDogFoodTest extends IOSuite { @@ -18,14 +17,24 @@ object PropertyDogFoodTest extends IOSuite { test("Failed property tests get reported properly") { dogfood => for { results <- dogfood.runSuite(Meta.FailedChecks) - logs = results._1 + logs = results._1 events = results._2 } yield { val errorLogs = logs.collect { case LoggedEvent.Error(msg) => msg } exists(errorLogs) { log => - val expectedMessage = "Property test failed on try 5 with input 0" + // Go into software engineering they say + // Learn how to make amazing algorithms + // Build robust and deterministic software + val (attempt, value) = + if (ScalaCompat.isScala3) + ("4", "-2147483648") + else + ("2", "0") + + val expectedMessage = + s"Property test failed on try $attempt with input $value" expect(log.contains(expectedMessage)) } } @@ -35,7 +44,7 @@ object PropertyDogFoodTest extends IOSuite { test("Checks are parallelised") { dogfood => for { events <- dogfood.runSuite(Meta.ParallelChecks).map(_._2) - _ <- expect(events.size == 1).failFast + _ <- expect(events.size == 1).failFast } yield { expect(events.headOption.get.duration() < 10000) } @@ -60,7 +69,7 @@ object Meta { object FailedChecks extends SimpleIOSuite with IOCheckers { override def checkConfig: CheckConfig = - super.checkConfig.copy(perPropertyParallelism = 1, initialSeed = Some(1L)) + super.checkConfig.copy(perPropertyParallelism = 1, initialSeed = Some(5L)) simpleTest("foobar") { forall { (x: Int) =>