diff --git a/odelay-core/js/src/main/scala/platform.scala b/odelay-core/js/src/main/scala/platform.scala index 8c5a522..a41926f 100644 --- a/odelay-core/js/src/main/scala/platform.scala +++ b/odelay-core/js/src/main/scala/platform.scala @@ -1,5 +1,5 @@ package odelay private[odelay] object platform { - implicit val defaultTimer: Timer = null + implicit val defaultTimer: Timer = odelay.js.JsTimer.newTimer } diff --git a/odelay-testing/js/src/test/scala/TimerSpec.scala b/odelay-testing/js/src/test/scala/TimerSpec.scala index 7fb9814..ea1a99b 100644 --- a/odelay-testing/js/src/test/scala/TimerSpec.scala +++ b/odelay-testing/js/src/test/scala/TimerSpec.scala @@ -1,91 +1,14 @@ package odelay.testing import odelay.{ Delay, Timer } -import org.scalatest.{ BeforeAndAfterAll, AsyncFunSpec } -import scala.concurrent.Await +import org.scalatest.{ BeforeAndAfterAll, AsyncFunSpec, Matchers } +import scala.concurrent._ import scala.concurrent.duration._ import scala.util.control.NonFatal import java.util.concurrent.CancellationException import java.util.concurrent.atomic.AtomicInteger -import odelay.js._ -class TimerSpec extends AsyncFunSpec with BeforeAndAfterAll { - - // needed so we do not get a scalatest EC error - implicit override def executionContext = - scala.concurrent.ExecutionContext.Implicits.global - - val newTimer: Timer = JsTimer.newTimer - val timerName: String = "jstimer" - implicit val timer = newTimer - - describe (timerName) { - it ("should execute an operation after an initial delay") { - val start = System.currentTimeMillis - val fut = Delay(1.seconds) { - System.currentTimeMillis - start - }.future - fut.map(value => assert(value.millis.toSeconds.seconds === 1.seconds)) - } - - it ("should permit cancellation of delayed operations") { - val cancel = Delay(1.seconds)(sys.error("this should never print")) - val fut = Delay(150.millis) { - cancel.cancel() - }.future - fut.map(_ => succeed) - } - - it ("cancellation of delayed operations should result in future failure") { - val cancel = Delay(1.second)(sys.error("this should never print")) - Delay(150.millis) { - cancel.cancel() - } - cancel.future.recover { - case x: CancellationException => succeed - case _ => fail - } - } - - it ("completion of delayed operations should result in a future success") { - val future = Delay(1.second)(true).future - future.recover { - case NonFatal(_) => sys.error("this should never print") - }.map ( value => assert(value === true)) - } - - it ("should repeatedly execute an operation on a fixed delay") { - val start = System.currentTimeMillis - val delay = Delay.every(150.millis)() { - val diff = System.currentTimeMillis - start - print('.') - diff - } - delay.future.failed.foreach { _ => println() } - val cancelit = Delay(5.seconds) { - delay.cancel() - } - cancelit.future.map(_ => succeed) - } - - it ("cancellation of repeatedly delayed operations should result in future failure") { - val cancel = Delay.every(150.seconds)()(true) - val counter = new AtomicInteger(0) - cancel.future.onFailure { - case NonFatal(e) => - assert(e.getClass === classOf[CancellationException]) - counter.incrementAndGet() - } - - val canceltrueloop = Delay(2.seconds) { - cancel.cancel() - } - canceltrueloop.future.map(_ => assert(counter.get() === 1)) - } - - } - - override def afterAll() { - timer.stop() - } +class TimerSpecJS extends TimerSpec { + def newTimer = new odelay.js.JsTimer() + def timerName: String = "jstimer" } diff --git a/odelay-testing/jvm/src/test/scala/TimerSpec.scala b/odelay-testing/jvm/src/test/scala/TimerSpec.scala index af6b35c..aef446f 100644 --- a/odelay-testing/jvm/src/test/scala/TimerSpec.scala +++ b/odelay-testing/jvm/src/test/scala/TimerSpec.scala @@ -1,87 +1,9 @@ package odelay.testing -import odelay.{ Delay, Timer } -import org.scalatest.{ BeforeAndAfterAll, AsyncFunSpec } -import scala.concurrent._ -import scala.concurrent.duration._ -import scala.util.control.NonFatal -import java.util.concurrent.CancellationException -import java.util.concurrent.atomic.AtomicInteger +import odelay.Timer -trait TimerSpec extends AsyncFunSpec with BeforeAndAfterAll { +class TimerSpecJVM extends TimerSpec { + def newTimer = odelay.Timer.default + def timerName = "JVM Timer" - implicit def ec: ExecutionContext = scala.concurrent.ExecutionContext.Implicits.global - - def newTimer: Timer - def timerName: String - implicit val timer = newTimer - - describe (timerName) { - it ("should execute an operation after an initial delay") { - val start = System.currentTimeMillis - val fut = Delay(1.seconds) { - System.currentTimeMillis - start - }.future - fut.map(value => assert(value.millis.toSeconds === 1)) - } - - it ("should permit cancellation of delayed operations") { - val cancel = Delay(1.seconds)(sys.error("this should never print")) - Delay(150.millis) { - cancel.cancel() - }.future.map(_ => succeed) - } - - it ("cancellation of delayed operations should result in future failure") { - val cancel = Delay(1.second)(sys.error("this should never print")) - val cancelF = Delay(150.millis) { - cancel.cancel() - } - for { - cf <- cancelF.future - c <- cancel.future.failed - } yield { - assert(c.getClass === classOf[CancellationException]) - } - } - - it ("completion of delayed operations should result in a future success") { - val future = Delay(1.second)(true).future - future.map { value => assert(value === true)} - } - - it ("should repeatedly execute an operation on a fixed delay") { - val start = System.currentTimeMillis - val delay = Delay.every(150.millis)() { - val diff = System.currentTimeMillis - start - print('.') - diff - } - delay.future.failed.foreach { _ => println() } - Delay(2.seconds) { - delay.cancel() - }.future.map(_ => succeed) - } - - it ("cancellation of repeatedly delayed operations should result in future failure") { - val counter = new AtomicInteger(0) - val cancel = Delay.every(150.seconds)()(true) - val cancelFut = cancel.future.recoverWith { - case e: CancellationException => - counter.incrementAndGet() - Future.successful(true) - case _ => Future.successful(true) - } - val fut = Delay(2.seconds) { - cancel.cancel() - } - - cancelFut.map(_ => assert(counter.get() === 1)) - } - - } - - override def afterAll() { - timer.stop() - } } diff --git a/odelay-testing/shared/src/test/scala/ImplicitSpec.scala b/odelay-testing/shared/src/test/scala/ImplicitSpec.scala new file mode 100644 index 0000000..cf44818 --- /dev/null +++ b/odelay-testing/shared/src/test/scala/ImplicitSpec.scala @@ -0,0 +1,23 @@ +package odelay.testing + +import odelay.{ Delay, Timer } +import org.scalatest.{ BeforeAndAfterAll, FunSpec, Matchers } +import scala.concurrent._ +import scala.concurrent.duration._ +import scala.util.control.NonFatal +import java.util.concurrent.CancellationException +import java.util.concurrent.atomic.AtomicInteger + +class ImplicitSpec extends FunSpec with Matchers with BeforeAndAfterAll { + + implicit def ec: ExecutionContext = scala.concurrent.ExecutionContext.Implicits.global + + describe("implicit test") { + it ("should find the implict") { + import Timer._ + import scala.concurrent._ + val result: Timer = implicitly[Timer] + result should not be (null) + } + } +} diff --git a/odelay-testing/shared/src/test/scala/TimerSpec.scala b/odelay-testing/shared/src/test/scala/TimerSpec.scala new file mode 100644 index 0000000..189c371 --- /dev/null +++ b/odelay-testing/shared/src/test/scala/TimerSpec.scala @@ -0,0 +1,86 @@ +package odelay.testing + +import odelay.{ Delay, Timer } +import org.scalatest.{ BeforeAndAfterAll, AsyncFunSpec, Matchers } +import scala.concurrent._ +import scala.concurrent.duration._ +import scala.util.control.NonFatal +import java.util.concurrent.CancellationException +import java.util.concurrent.atomic.AtomicInteger + +abstract class TimerSpec extends AsyncFunSpec with Matchers with BeforeAndAfterAll { + + implicit override def executionContext = scala.concurrent.ExecutionContext.Implicits.global + + def newTimer: Timer + def timerName: String + implicit val timer = newTimer + + describe (timerName) { + it ("should execute an operation after an initial delay") { + val start = System.currentTimeMillis + val fut = Delay(1.seconds) { + System.currentTimeMillis - start + }.future + fut.map(value => value.millis.toSeconds should equal(1.seconds.toSeconds +- 1.seconds.toSeconds)) + } + + it ("should permit cancellation of delayed operations") { + val cancel = Delay(1.seconds)(sys.error("this should never print")) + Delay(150.millis) { + cancel.cancel() + }.future.map(_ => succeed) + } + + it ("cancellation of delayed operations should result in future failure") { + val cancel = Delay(1.second)(sys.error("this should never print")) + val cancelF = Delay(150.millis) { + cancel.cancel() + } + for { + cf <- cancelF.future + c <- cancel.future.failed + } yield { + assert(c.getClass === classOf[CancellationException]) + } + } + + it ("completion of delayed operations should result in a future success") { + val future = Delay(1.second)(true).future + future.map { value => value should be (true) } + } + + it ("should repeatedly execute an operation on a fixed delay") { + val start = System.currentTimeMillis + val delay = Delay.every(150.millis)() { + val diff = System.currentTimeMillis - start + print('.') + diff + } + delay.future.failed.foreach { _ => println() } + Delay(2.seconds) { + delay.cancel() + }.future.map(_ => succeed) + } + + it ("cancellation of repeatedly delayed operations should result in future failure") { + val counter = new AtomicInteger(0) + val cancel = Delay.every(150.seconds)()(true) + val cancelFut = cancel.future.recoverWith { + case e: CancellationException => + counter.incrementAndGet() + Future.successful(true) + case _ => Future.successful(true) + } + val fut = Delay(2.seconds) { + cancel.cancel() + } + + cancelFut.map(_ => counter.get() should be (1)) + } + } + + override def afterAll() { + timer.stop() + } +}