1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
/**
* Copyright (C) 2012 Typesafe Inc. <http://www.typesafe.com>
*/
import scala.concurrent.duration._
import scala.reflect._
import scala.tools.partest.TestUtil.intercept
import scala.language.{ postfixOps }
object Test extends App {
implicit class Assert(val left: Any) extends AnyVal {
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")
}
}
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 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
for (i <- Seq(zero, one, two, three)) {
i - inf mustBe minf
i - minf mustBe inf
}
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 (_ * -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 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)
undef / 1 mustBe undef
undef / nan mustBe undef
undef * 1 mustBe undef
undef * nan mustBe undef
inputs foreach (x => x / zero mustBe x.toUnit(SECONDS) / 0d)
inputs foreach (x => x / 0d mustBe Duration.fromNanos(x.toUnit(NANOSECONDS) / 0d))
inputs foreach (x => x / -0d mustBe Duration.fromNanos(x.toUnit(NANOSECONDS) / -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 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
// 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
{ val l = dead.timeLeft; assert(l > 1.second, s"$l <= 1.second") }
{ val l = dead2.timeLeft; assert(l > 1.second, s"$l <= 1.second") }
Thread.sleep(1.second.toMillis)
// unfortunately it can happen that the sleep() returns early without throwing
{ val l = dead.timeLeft; assert(l <= 1100.millis, s"$l > 1100.millis") }
{ val l = dead2.timeLeft; assert(l <= 1100.millis, s"$l > 1100.millis") }
// test integer mul/div
500.millis * 2 mustBe 1.second
(500.millis * 2).unit mustBe MILLISECONDS
1.second / 2 mustBe 500.millis
(1.second / 2).unit mustBe MILLISECONDS
// check statically retaining finite-ness
val finiteDuration: FiniteDuration = 1.second * 2 / 3 mul 5 div 4 plus 3.seconds minus 1.millisecond min 1.second max 1.second
val finite2: FiniteDuration = 2 * 1.second + 3L * 2.seconds
finite2 mustBe 8.seconds
((2 seconds fromNow).timeLeft: FiniteDuration) < 4.seconds mustBe true
val finite3: FiniteDuration = 3.5 seconds span
}
|