summaryrefslogtreecommitdiff
path: root/test/files
diff options
context:
space:
mode:
authorRoland <rk@rkuhn.info>2012-09-19 08:17:40 +0200
committerRoland <rk@rkuhn.info>2012-09-19 08:17:40 +0200
commit625377f53ffc9244c96b17b3fc086bf81c3215d1 (patch)
tree0b212237899294aac0071a1f88f8e8ca92f49e1c /test/files
parentc555ff56db737bc65097add317946ee6d6166cd8 (diff)
downloadscala-625377f53ffc9244c96b17b3fc086bf81c3215d1.tar.gz
scala-625377f53ffc9244c96b17b3fc086bf81c3215d1.tar.bz2
scala-625377f53ffc9244c96b17b3fc086bf81c3215d1.zip
improve performance of integer multiplication overflow check on Duration
- also rename divisor arguments to “divisor” - and add a scalacheck for multiplication overflow detection
Diffstat (limited to 'test/files')
-rw-r--r--test/files/scalacheck/duration.scala69
1 files changed, 69 insertions, 0 deletions
diff --git a/test/files/scalacheck/duration.scala b/test/files/scalacheck/duration.scala
new file mode 100644
index 0000000000..8037720f69
--- /dev/null
+++ b/test/files/scalacheck/duration.scala
@@ -0,0 +1,69 @@
+import org.scalacheck._
+import Prop._
+import Gen._
+import Arbitrary._
+import math._
+import concurrent.util.Duration.fromNanos
+
+object Test extends Properties("Division of Duration by Long") {
+
+ val weightedLong =
+ frequency(
+ 1 -> choose(-128L, 127L),
+ 1 -> (arbitrary[Byte] map (_.toLong << 8)),
+ 1 -> (arbitrary[Byte] map (_.toLong << 16)),
+ 1 -> (arbitrary[Byte] map (_.toLong << 24)),
+ 1 -> (arbitrary[Byte] map (_.toLong << 32)),
+ 1 -> (arbitrary[Byte] map (_.toLong << 40)),
+ 1 -> (arbitrary[Byte] map (_.toLong << 48)),
+ 1 -> (choose(-127L, 127L) map (_ << 56))
+ )
+
+ val genTwoSmall = for {
+ a <- weightedLong
+ b <- choose(-(Long.MaxValue / max(1, abs(a))), Long.MaxValue / max(1, abs(a)))
+ } yield (a, b)
+
+ val genTwoLarge = for {
+ a <- weightedLong
+ b <- arbitrary[Long] suchThat (b => (abs(b) > Long.MaxValue / max(1, abs(a))))
+ } yield (a, b)
+
+ val genClose = for {
+ a <- weightedLong
+ if a != 0
+ b <- choose(Long.MaxValue / a - 10, Long.MaxValue / a + 10)
+ } yield (a, b)
+
+ val genBorderline =
+ frequency(
+ 1 -> (Long.MinValue, 0L),
+ 1 -> (Long.MinValue, 1L),
+ 1 -> (Long.MinValue, -1L),
+ 1 -> (0L, Long.MinValue),
+ 1 -> (1L, Long.MinValue),
+ 1 -> (-1L, Long.MinValue),
+ 90 -> genClose
+ )
+
+ def mul(a: Long, b: Long): Long = {
+ (fromNanos(a) * b).toNanos
+ }
+
+ property("without overflow") = forAll(genTwoSmall) { case (a, b) =>
+ a * b == mul(a, b)
+ }
+
+ property("with overflow") = forAll(genTwoLarge) { case (a, b) =>
+ try { mul(a, b); false } catch { case _: IllegalArgumentException => true }
+ }
+
+ property("on overflow edge cases") = forAll(genBorderline) { case (a, b) =>
+ val shouldFit =
+ a != Long.MinValue && // must fail due to illegal duration length
+ (b != Long.MinValue || a == 0) && // Long factor may only be MinValue if the duration is zero, otherwise the result will be illegal
+ (abs(b) <= Long.MaxValue / max(1, abs(a))) // check the rest against the “safe” division method
+ try { mul(a, b); shouldFit }
+ catch { case _: IllegalArgumentException => !shouldFit }
+ }
+}