package gs.test.v0 import cats.effect.IO import cats.effect.unsafe.IORuntime import gs.timing.v0.ElapsedTime import gs.timing.v0.Timing import java.util.concurrent.TimeUnit import munit.* import scala.concurrent.duration.FiniteDuration class TimingTests extends FunSuite: given IORuntime = IORuntime.global iotest("should retrieve monotonic time") { for (provider, timing) <- Timing.manual[IO] t1 <- timing.monotonic() t2 <- timing.monotonic() _ <- provider.tick() t3 <- timing.monotonic() _ <- provider.tick() t4 <- timing.monotonic() _ <- provider.reset() t5 <- timing.monotonic() yield assertEquals(t1, 0L) assertEquals(t2, 0L) assertEquals(t3, 1L) assertEquals(t4, 2L) assertEquals(t5, 0L) } iotest("should create a timer based on the current provider") { val start = 0L val end = 1000000L * 2000L // 2 seconds, 2000 millis val nanos = end - start val millis = nanos / 1000000L val seconds = millis / 1000L for (provider, timing) <- Timing.manual[IO] timer <- timing.start() e1 <- timer.checkpoint() _ <- provider.set(end) e2 <- timer.checkpoint() yield assertEquals( e1, ElapsedTime(start, 0L, FiniteDuration(0L, TimeUnit.NANOSECONDS)) ) assertEquals( e2, ElapsedTime(start, end, FiniteDuration(nanos, TimeUnit.NANOSECONDS)) ) assertEquals(e2.toMilliseconds(), millis) assertEquals(e2.toSeconds(), seconds) } iotest("should capture system time") { for timing <- IO(Timing.system[IO]) t1 <- timing.monotonic() _ <- IO.sleep(FiniteDuration(1L, TimeUnit.MILLISECONDS)) t2 <- timing.monotonic() yield assert( t2 > t1, "The system clock should detect that at least 1 nanosecond has passed after sleeping for 1 millisecond." ) } private def iotest( name: String )( body: => IO[Any] )( implicit loc: Location ): Unit = test(name)(body.unsafeRunSync())