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

Issue 3353: Investigate antisymmetry failure for UpperBounded for Duration #3470

Merged
merged 4 commits into from
Nov 25, 2020
Merged
Changes from all commits
Commits
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
74 changes: 27 additions & 47 deletions kernel-laws/shared/src/test/scala/cats/kernel/laws/LawTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,6 @@ object KernelCheck {
implicit val arbitraryUUID: Arbitrary[UUID] =
Arbitrary(Gen.uuid)

implicit val arbitraryDuration: Arbitrary[Duration] = {
// max range is +/- 292 years, but we give ourselves some extra headroom
// to ensure that we can add these things up. they crash on overflow.
val n = (292L * 365) / 500
Arbitrary(
Gen.oneOf(
Gen.choose(-n, n).map(Duration(_, DAYS)),
Gen.choose(-n * 24L, n * 24L).map(Duration(_, HOURS)),
Gen.choose(-n * 1440L, n * 1440L).map(Duration(_, MINUTES)),
Gen.choose(-n * 86400L, n * 86400L).map(Duration(_, SECONDS)),
Gen.choose(-n * 86400000L, n * 86400000L).map(Duration(_, MILLISECONDS)),
Gen.choose(-n * 86400000000L, n * 86400000000L).map(Duration(_, MICROSECONDS)),
Gen.choose(-n * 86400000000000L, n * 86400000000000L).map(Duration(_, NANOSECONDS))
)
)
}

implicit val arbitraryFiniteDuration: Arbitrary[FiniteDuration] = {
// max range is +/- 292 years, but we give ourselves some extra headroom
// to ensure that we can add these things up. they crash on overflow.
Expand All @@ -64,6 +47,9 @@ object KernelCheck {
)
}

implicit def arbitraryDuration(implicit ev: Arbitrary[FiniteDuration]): Arbitrary[Duration] =
Arbitrary(ev.arbitrary)

// Copied from cats-laws.
implicit def arbitrarySortedMap[K: Arbitrary: Order, V: Arbitrary]: Arbitrary[SortedMap[K, V]] =
Arbitrary(arbitrary[Map[K, V]].map(s => SortedMap.empty[K, V](implicitly[Order[K]].toOrdering) ++ s))
Expand Down Expand Up @@ -101,36 +87,6 @@ object KernelCheck {

implicit val cogenUUID: Cogen[UUID] =
Cogen[(Long, Long)].contramap(u => (u.getMostSignificantBits, u.getLeastSignificantBits))

implicit val cogenDuration: Cogen[Duration] =
Cogen[Long].contramap { d =>
if (d == Duration.Inf) 3896691548866406746L
else if (d == Duration.MinusInf) 1844151880988859955L
else if (d == Duration.Undefined) -7917359255778781894L
else
d.length * (d.unit match {
case DAYS => -6307593037248227856L
case HOURS => -3527447467459552709L
case MINUTES => 5955657079535371609L
case SECONDS => 5314272869665647192L
case MILLISECONDS => -2025740217814855607L
case MICROSECONDS => -2965853209268633779L
case NANOSECONDS => 6128745701389500153L
})
}

implicit val cogenFiniteDuration: Cogen[FiniteDuration] =
Cogen[Long].contramap { d =>
d.length * (d.unit match {
case DAYS => -6307593037248227856L
case HOURS => -3527447467459552709L
case MINUTES => 5955657079535371609L
case SECONDS => 5314272869665647192L
case MILLISECONDS => -2025740217814855607L
case MICROSECONDS => -2965853209268633779L
case NANOSECONDS => 6128745701389500153L
})
}
}

class TestsConfig extends Checkers {
Expand Down Expand Up @@ -514,3 +470,27 @@ class Tests extends TestsConfig with AnyFunSuiteLike with FunSuiteDiscipline wit
Cogen[A].contramap(_.a)
}
}

sealed class LongRunningTestsConfig extends TestsConfig {
// This increases the number of successes to trigger the problem
// described here: https://github.com/typelevel/cats/issues/3353
// With this number of positive cases the problem is systematic
// or at least it happens very often.
final val IncreasedMinSuccessful: PosInt = if (Platform.isJs) 10 else 400 * 1000
implicit override val generatorDrivenConfig: PropertyCheckConfiguration =
PropertyCheckConfiguration(
minSuccessful = IncreasedMinSuccessful,
sizeRange = PropMaxSize,
workers = PropWorkers
)
}

// These tests are not checking the actual laws but they make sure that Gen and
// Cogen for Duration and FiniteDuration don't trigger the problem described here
// https://github.com/typelevel/cats/issues/3353
final class LongRunningTests extends LongRunningTestsConfig with AnyFunSuiteLike with FunSuiteDiscipline {
import KernelCheck._

checkAll("Deeper test of Eq[Duration]", EqTests[Duration].eqv)
checkAll("Deeper test of Eq[FiniteDuration]", EqTests[FiniteDuration].eqv)
}