/
DurationConvertSuite.scala
125 lines (119 loc) · 5.42 KB
/
DurationConvertSuite.scala
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
package pureconfig
import java.util.concurrent.TimeUnit
import com.typesafe.config.ConfigValueFactory
import org.scalatest.{ EitherValues, FlatSpec, Matchers }
import org.scalatest.Inspectors._
import pureconfig.error.CannotConvert
import scala.concurrent.duration._
import DurationConvertSuite._
class DurationConvertSuite extends FlatSpec with Matchers with EitherValues {
"Converting a Duration to a String" should "pick an appropriate unit when dealing with whole units less than the next step up" in {
fromD(Duration(14, TimeUnit.DAYS)) shouldBe "14d"
fromD(Duration(16, TimeUnit.HOURS)) shouldBe "16h"
fromD(Duration(1, TimeUnit.MINUTES)) shouldBe "1m"
fromD(Duration(33, TimeUnit.SECONDS)) shouldBe "33s"
fromD(Duration(555, TimeUnit.MILLISECONDS)) shouldBe "555ms"
fromD(Duration(999, TimeUnit.MICROSECONDS)) shouldBe "999us"
fromD(Duration(222, TimeUnit.NANOSECONDS)) shouldBe "222ns"
}
it should "pick an appropriate unit when dealing with whole units more than, but fractional in, the next step up" in {
fromD(Duration(1, TimeUnit.DAYS)) shouldBe "1d"
fromD(Duration(47, TimeUnit.HOURS)) shouldBe "47h"
fromD(Duration(123, TimeUnit.MINUTES)) shouldBe "123m"
fromD(Duration(489, TimeUnit.SECONDS)) shouldBe "489s"
fromD(Duration(11555, TimeUnit.MILLISECONDS)) shouldBe "11555ms"
fromD(Duration(44999, TimeUnit.MICROSECONDS)) shouldBe "44999us"
fromD(Duration(88222, TimeUnit.NANOSECONDS)) shouldBe "88222ns"
}
it should "write 0 without units" in {
fromD(Duration(0, TimeUnit.DAYS)) shouldBe "0"
}
it should "handle an infinite duration" in {
fromD(Duration.Inf) shouldBe "Inf"
}
it should "round trip negative infinity" in {
val expected = Duration.MinusInf
fromS(fromD(expected)).right.value shouldBe expected
}
"Converting a String to a Duration" should "succeed for known units" in {
fromS("1d") shouldBe Right(Duration(1, TimeUnit.DAYS))
fromS("47h") shouldBe Right(Duration(47, TimeUnit.HOURS))
fromS("123m") shouldBe Right(Duration(123, TimeUnit.MINUTES))
fromS("489s") shouldBe Right(Duration(489, TimeUnit.SECONDS))
fromS("11555ms") shouldBe Right(Duration(11555, TimeUnit.MILLISECONDS))
fromS("44999us") shouldBe Right(Duration(44999, TimeUnit.MICROSECONDS))
fromS("44999µs") shouldBe Right(Duration(44999, TimeUnit.MICROSECONDS))
fromS("88222ns") shouldBe Right(Duration(88222, TimeUnit.NANOSECONDS))
}
it should "succeed when loading 0 without units" in {
val signs = Set("", "-", "+")
val leftSpacing = Set("", " ")
val rightSpacing = Set("", " ")
val leftSpacingSize = Set((0 to 2): _*)
val rightSpacingSize = Set((0 to 2): _*)
val zeroRepeatSize = Set((1 to 2): _*)
forAll(signs) { sign =>
forAll(leftSpacing) { lsc =>
forAll(rightSpacing) { rsc =>
forAll(leftSpacingSize) { ls =>
forAll(rightSpacingSize) { rs =>
forAll(zeroRepeatSize) { zr =>
fromS(lsc * ls + sign + "0" * zr + rsc * rs) shouldBe Right(Duration(0, TimeUnit.DAYS))
}
}
}
}
}
}
}
it should "report a helpful error message when failing to convert a bad duration" in {
val badDuration = "10 lordsALeaping"
val result = BasicReaders.durationConfigReader.from(ConfigValueFactory.fromAnyRef(badDuration))
result match {
case Right(_) => fail("Should be failure")
case Left(ex) =>
ex.toList should have size 1
ex.head shouldBe a[CannotConvert]
}
}
it should "correctly round trip when converting Duration.Undefined" in {
fromS(fromD(Duration.Undefined)) shouldEqual Right(Duration.Undefined)
}
it should "correctly round trip when converting Duration.MinusInf" in {
fromS(fromD(Duration.MinusInf)) shouldEqual Right(Duration.MinusInf)
}
it should "correctly round trip when converting Duration.Inf" in {
fromS(fromD(Duration.Inf)) shouldEqual Right(Duration.Inf)
}
it should "convert a value larger than 2^52" in {
fromS("8092048641075763 ns").right.value shouldBe Duration(8092048641075763L, NANOSECONDS)
}
it should "round trip a value which is greater than 2^52" in {
val expected = Duration(781251341142500992L, NANOSECONDS)
fromS(fromD(expected)).right.value shouldBe expected
}
it should "round trip a value < 2^52 which is > 2^52 when converted to milliseconds" in {
val expected = Duration(781251341142501L, MICROSECONDS)
fromS(fromD(expected)).right.value shouldBe expected
}
it should "freak when given a value larger than 2^64" in {
val result = dcc.from(scc.to("12345678901234567890 ns"))
result shouldBe a[Left[_, _]]
val ex = result.left.value.head.asInstanceOf[error.ThrowableFailure].throwable
ex.getMessage should include regex "trying to construct too large duration"
}
it should "parse a fractional value" in {
val expected = 1.5.minutes
fromS(fromD(expected)).right.value shouldBe expected
}
it should "change the units on a fractional value, failing to round trip in the config representation" in {
val duration = dcc.from(scc.to("1.5 minutes")).right.value
val rep = scc.from(dcc.to(duration)).right.value shouldBe "90s" // Not "1.5 minutes" as we might hope
}
}
object DurationConvertSuite {
val scc = implicitly[ConfigConvert[String]]
val dcc = implicitly[ConfigConvert[Duration]]
val fromD = DurationConvert.fromDuration(_: Duration)
val fromS = DurationConvert.fromString(_: String)(None)
}