summaryrefslogtreecommitdiff
path: root/test/files/jvm/duration-tck.scala
diff options
context:
space:
mode:
authorRoland <rk@rkuhn.info>2012-09-07 16:04:52 +0200
committerRoland <rk@rkuhn.info>2012-09-07 16:04:52 +0200
commit7a833f94296849c0e2a6cbacb7e513599c831f38 (patch)
treeca34eeab89215ce3b44db39583bd012baaa7a7ac /test/files/jvm/duration-tck.scala
parent9da135880d0b78b440f4ce62dd8b7dc156571d71 (diff)
downloadscala-7a833f94296849c0e2a6cbacb7e513599c831f38.tar.gz
scala-7a833f94296849c0e2a6cbacb7e513599c831f38.tar.bz2
scala-7a833f94296849c0e2a6cbacb7e513599c831f38.zip
second round of Duration cleanup
- make Duration behave consistent with Double's non-finite semantics - add ScalaDoc - add complete test suite - change overflow protection impl after review comments - clean up code
Diffstat (limited to 'test/files/jvm/duration-tck.scala')
-rw-r--r--test/files/jvm/duration-tck.scala236
1 files changed, 157 insertions, 79 deletions
diff --git a/test/files/jvm/duration-tck.scala b/test/files/jvm/duration-tck.scala
index 679712aa59..aa1ac50078 100644
--- a/test/files/jvm/duration-tck.scala
+++ b/test/files/jvm/duration-tck.scala
@@ -10,7 +10,13 @@ import java.util.concurrent.TimeUnit._
object Test extends App {
implicit class Assert(val left: Any) extends AnyVal {
- def =!=(right: Any) = assert(left == right, s"$left was not equal to $right")
+ import Duration.Undefined
+ def mustBe(right: Any) = right match {
+ case r: Double if r.isNaN => assert(left.asInstanceOf[Double].isNaN, s"$left was not NaN")
+ case r: Double if r == 0 && r.compareTo(0) == -1 => assert(left == 0 && left.asInstanceOf[Double].compareTo(0) == -1, s"$left was not -0.0")
+ case Undefined => assert(left.asInstanceOf[AnyRef] eq Undefined, s"$left was not Undefined")
+ case _ => assert(left == right, s"$left was not equal to $right")
+ }
}
def intercept[T <: Exception : ClassTag](code: => Unit) =
@@ -19,89 +25,161 @@ object Test extends App {
case ex: Exception => if (classTag[T].runtimeClass isAssignableFrom ex.getClass) () else throw ex
}
- { // test field ops
- val zero = 0 seconds
- val one = 1 second
- val two = one + one
- val three = 3 * one
- (0 * one) =!= (zero)
- (2 * one) =!= (two)
- (three - two) =!= (one)
- (three / 3) =!= (one)
- (two / one) =!= (2)
- (one + zero) =!= (one)
- (one / 1000000) =!= (1.micro)
- }
+ val zero = 0 seconds
+ val one = 1 second
+ val two = one + one
+ val three = 3 * one
+ val inf = Duration.Inf
+ val minf = Duration.MinusInf
+ val undef = Duration.Undefined
+ val inputs = List(zero, one, inf, minf, undef)
+ val nan = Double.NaN
- { // test infinities
- val one = 1.second
- val inf = Duration.Inf
- val minf = Duration.MinusInf
- (-inf) =!= (minf)
- intercept[IllegalArgumentException] { minf + inf }
- intercept[IllegalArgumentException] { inf - inf }
- intercept[IllegalArgumentException] { inf + minf }
- intercept[IllegalArgumentException] { minf - minf }
- (inf + inf) =!= (inf)
- (inf - minf) =!= (inf)
- (minf - inf) =!= (minf)
- (minf + minf) =!= (minf)
- assert(inf == inf)
- assert(minf == minf)
- inf.compareTo(inf) =!= (0)
- inf.compareTo(one) =!= (1)
- minf.compareTo(minf) =!= (0)
- minf.compareTo(one) =!= (-1)
- assert(inf != minf)
- assert(minf != inf)
- assert(one != inf)
- assert(minf != one)
- inf =!= (minf * -1d)
- inf =!= (minf / -1d)
- }
+ // test field ops
+ one.isFinite mustBe true
+ 0 * one mustBe zero
+ 2 * one mustBe two
+ three - two mustBe one
+ three / 3 mustBe one
+ two / one mustBe 2
+ one + zero mustBe one
+ one / 1000000 mustBe 1.micro
+
+
+ // test infinities
+
+ inf.isFinite mustBe false
+ minf.isFinite mustBe false
+
+ inf mustBe inf
+ minf mustBe minf
+ -inf mustBe minf
+ -minf mustBe inf
+
+ minf + inf mustBe undef
+ inf - inf mustBe undef
+ inf + minf mustBe undef
+ minf - minf mustBe undef
+
+ inf + inf mustBe inf
+ inf - minf mustBe inf
+ minf - inf mustBe minf
+ minf + minf mustBe minf
+
+ inf.compareTo(inf) mustBe 0
+ inf.compareTo(one) mustBe 1
+ inf.compareTo(minf) mustBe 1
+ minf.compareTo(minf) mustBe 0
+ minf.compareTo(one) mustBe -1
+ minf.compareTo(inf) mustBe -1
+
+ assert(inf != minf)
+ assert(minf != inf)
+ assert(one != inf)
+ assert(minf != one)
+
+ inf mustBe (minf * -1d)
+ inf mustBe (minf / -1d)
+
+ one / inf mustBe 0d
+ -one / inf mustBe -0d
+ one / minf mustBe -0d
+ -one / minf mustBe 0d
+
+ inputs filterNot (_.isFinite) foreach (x => x / zero mustBe x.toUnit(DAYS))
+ inputs filterNot (_.isFinite) foreach (_ * 0d mustBe undef)
+ inputs filterNot (_.isFinite) foreach (x => x * Double.PositiveInfinity mustBe x)
+ inputs filterNot (_.isFinite) foreach (x => x * Double.NegativeInfinity mustBe -x)
+
+ inf.toUnit(SECONDS) mustBe Double.PositiveInfinity
+ minf.toUnit(MINUTES) mustBe Double.NegativeInfinity
+ Duration.fromNanos(Double.PositiveInfinity) mustBe inf
+ Duration.fromNanos(Double.NegativeInfinity) mustBe minf
+
- { // test overflow protection
- for (unit ← Seq(DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS)) {
- val x = unit.convert(Long.MaxValue, NANOSECONDS)
- val dur = Duration(x, unit)
- val mdur = Duration(-x, unit)
- -mdur =!= (dur)
- intercept[IllegalArgumentException] { Duration(x + 10000000d, unit) }
- intercept[IllegalArgumentException] { Duration(-x - 10000000d, unit) }
- if (unit != NANOSECONDS) {
- intercept[IllegalArgumentException] { Duration(x + 1, unit) }
- intercept[IllegalArgumentException] { Duration(-x - 1, unit) }
- }
- intercept[IllegalArgumentException] { dur + 1.day }
- intercept[IllegalArgumentException] { mdur - 1.day }
- intercept[IllegalArgumentException] { dur * 1.1 }
- intercept[IllegalArgumentException] { mdur * 1.1 }
- intercept[IllegalArgumentException] { dur * 2.1 }
- intercept[IllegalArgumentException] { mdur * 2.1 }
- intercept[IllegalArgumentException] { dur / 0.9 }
- intercept[IllegalArgumentException] { mdur / 0.9 }
- intercept[IllegalArgumentException] { dur / 0.4 }
- intercept[IllegalArgumentException] { mdur / 0.4 }
- Duration(x + unit.toString.toLowerCase)
- Duration("-" + x + unit.toString.toLowerCase)
- intercept[IllegalArgumentException] { Duration("%.0f".format(x + 10000000d) + unit.toString.toLowerCase) }
- intercept[IllegalArgumentException] { Duration("-%.0f".format(x + 10000000d) + unit.toString.toLowerCase) }
+ // test undefined & NaN
+
+ undef.isFinite mustBe false
+ -undef mustBe undef
+ assert(undef != undef)
+ assert(undef eq undef)
+
+ inputs foreach (_ + undef mustBe undef)
+ inputs foreach (_ - undef mustBe undef)
+ inputs foreach (_ / undef mustBe nan)
+ inputs foreach (_ / nan mustBe undef)
+ inputs foreach (_ * nan mustBe undef)
+ inputs foreach (undef + _ mustBe undef)
+ inputs foreach (undef - _ mustBe undef)
+ inputs foreach (undef / _ mustBe nan)
+ inputs filter (_.isFinite) foreach (x => x / zero mustBe x.toUnit(SECONDS) / 0d)
+
+ inputs filterNot (_ eq undef) foreach (_ compareTo undef mustBe -1)
+ inputs filterNot (_ eq undef) foreach (undef compareTo _ mustBe 1)
+ undef compare undef mustBe 0
+
+ undef.toUnit(DAYS) mustBe nan
+ Duration.fromNanos(nan) mustBe undef
+
+
+ // test overflow protection
+ for (unit ← Seq(DAYS, HOURS, MINUTES, SECONDS, MILLISECONDS, MICROSECONDS, NANOSECONDS)) {
+ val x = unit.convert(Long.MaxValue, NANOSECONDS)
+ val dur = Duration(x, unit)
+ val mdur = Duration(-x, unit)
+ -mdur mustBe (dur)
+ intercept[IllegalArgumentException] { Duration(x + 10000000d, unit) }
+ intercept[IllegalArgumentException] { Duration(-x - 10000000d, unit) }
+ if (unit != NANOSECONDS) {
+ intercept[IllegalArgumentException] { Duration(x + 1, unit) }
+ intercept[IllegalArgumentException] { Duration(-x - 1, unit) }
}
+ intercept[IllegalArgumentException] { dur + 1.day }
+ intercept[IllegalArgumentException] { mdur - 1.day }
+ intercept[IllegalArgumentException] { dur * 1.1 }
+ intercept[IllegalArgumentException] { mdur * 1.1 }
+ intercept[IllegalArgumentException] { dur * 2.1 }
+ intercept[IllegalArgumentException] { mdur * 2.1 }
+ intercept[IllegalArgumentException] { dur / 0.9 }
+ intercept[IllegalArgumentException] { mdur / 0.9 }
+ intercept[IllegalArgumentException] { dur / 0.4 }
+ intercept[IllegalArgumentException] { mdur / 0.4 }
+ Duration(x + unit.toString.toLowerCase)
+ Duration("-" + x + unit.toString.toLowerCase)
+ intercept[IllegalArgumentException] { Duration("%.0f".format(x + 10000000d) + unit.toString.toLowerCase) }
+ intercept[IllegalArgumentException] { Duration("-%.0f".format(x + 10000000d) + unit.toString.toLowerCase) }
}
+ intercept[IllegalArgumentException] { Duration.fromNanos(1e20) }
+ intercept[IllegalArgumentException] { Duration.fromNanos(-1e20) }
+
- { // test Deadline
- val dead = 2.seconds.fromNow
- val dead2 = 2 seconds fromNow
- // view bounds vs. very local type inference vs. operator precedence: sigh
- assert(dead.timeLeft > (1 second: Duration))
- assert(dead2.timeLeft > (1 second: Duration))
- Thread.sleep(1.second.toMillis)
- assert(dead.timeLeft < (1 second: Duration))
- assert(dead2.timeLeft < (1 second: Duration))
- }
+ // test precision
+ 1.second + 1.millisecond mustBe 1001.milliseconds
+ 100000.days + 1.nanosecond mustBe 8640000000000000001L.nanoseconds
+ 1.5.seconds.toSeconds mustBe 1
+ (-1.5).seconds.toSeconds mustBe -1
+
- { // check statically retaining finite-ness
- val d: FiniteDuration = 1.second * 2 / 1.4 mul 1.1 div 2.1 plus 3.seconds minus 1.millisecond min 1.second max 1.second
- }
+ // test unit stability
+ 1000.millis.unit mustBe MILLISECONDS
+ (1000.millis + 0.days).unit mustBe MILLISECONDS
+ 1.second.unit mustBe SECONDS
+ (1.second + 1.millisecond).unit mustBe MILLISECONDS
+
+
+ // test Deadline
+ val dead = 2.seconds.fromNow
+ val dead2 = 2 seconds fromNow
+ // view bounds vs. very local type inference vs. operator precedence: sigh
+ assert(dead.timeLeft > (1 second: Duration))
+ assert(dead2.timeLeft > (1 second: Duration))
+ Thread.sleep(1.second.toMillis)
+ assert(dead.timeLeft < (1 second: Duration))
+ assert(dead2.timeLeft < (1 second: Duration))
+
+
+ // check statically retaining finite-ness
+ val finiteDuration: FiniteDuration = 1.second plus 3.seconds minus 1.millisecond min 1.second max 1.second
+
}