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
|
/**
* Copyright (C) 2012 Typesafe Inc. <http://www.typesafe.com>
*/
import scala.concurrent.util._
import duration._
import scala.reflect._
import java.util.concurrent.TimeUnit._
import scala.tools.partest.TestUtil.intercept
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
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
assert(dead.timeLeft > 1.second)
assert(dead2.timeLeft > 1.second)
Thread.sleep(1.second.toMillis)
assert(dead.timeLeft < 1.second)
assert(dead2.timeLeft < 1.second)
// check statically retaining finite-ness
val finiteDuration: FiniteDuration = 1.second plus 3.seconds minus 1.millisecond min 1.second max 1.second
}
|