Skip to content

Refactored TimerSpec. Fixed scalajs implicit which had been set to null. #14

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
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
2 changes: 1 addition & 1 deletion odelay-core/js/src/main/scala/platform.scala
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
package odelay

private[odelay] object platform {
implicit val defaultTimer: Timer = null
implicit val defaultTimer: Timer = odelay.js.JsTimer.newTimer
}
87 changes: 5 additions & 82 deletions odelay-testing/js/src/test/scala/TimerSpec.scala
Original file line number Diff line number Diff line change
@@ -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"
}
86 changes: 4 additions & 82 deletions odelay-testing/jvm/src/test/scala/TimerSpec.scala
Original file line number Diff line number Diff line change
@@ -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()
}
}
23 changes: 23 additions & 0 deletions odelay-testing/shared/src/test/scala/ImplicitSpec.scala
Original file line number Diff line number Diff line change
@@ -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)
}
}
}
86 changes: 86 additions & 0 deletions odelay-testing/shared/src/test/scala/TimerSpec.scala
Original file line number Diff line number Diff line change
@@ -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()
}
}