summaryrefslogtreecommitdiff
path: root/test/files/jvm/scala-concurrent-tck.scala
diff options
context:
space:
mode:
authorViktor Klang <viktor.klang@gmail.com>2014-09-26 12:05:37 +0200
committerViktor Klang <viktor.klang@gmail.com>2014-10-20 23:55:44 +0200
commitfa0743c32338f147eaf7a5d69566bbc15d193f85 (patch)
tree24f6b6d5cbab337174d48f0d0876ac0de93141f5 /test/files/jvm/scala-concurrent-tck.scala
parentc0ceffb865ff4b2146aacec547cc42bb7605ee93 (diff)
downloadscala-fa0743c32338f147eaf7a5d69566bbc15d193f85.tar.gz
scala-fa0743c32338f147eaf7a5d69566bbc15d193f85.tar.bz2
scala-fa0743c32338f147eaf7a5d69566bbc15d193f85.zip
Add missing canonical combinators:
- `def transform[S](f: Try[T] => Try[S])(implicit executor: ExecutionContext): Future[S]` - `def transformWith[S](f: Try[T] => Future[S])(implicit executor: ExecutionContext): Future[S]` - `def flatten[S](implicit ev: T <:< Future[S]): Future[S]` - `def zipWith[U, R](that: Future[U])(f: (T, U) => R)(implicit executor: ExecutionContext): Future[R]` Add missing utilities: - `val unit: Future[Unit]` in `object Future` - `object never extends Future[Nothing]` in `object Future` - `def defaultBlockContext: BlockContext` in `object BlockContext` - `def toString: String` on stdlib implementations of `Future` Refactors: - the `scala.concurrent.Future` trait to not explicit create any `Promises`, so that implementations can control implementation type, this is mainly facilitated through adding of the `transform` and `transformWith` methods. - the implementation of `ExecutionContextImpl` has been cleaned up - the `scala.concurrent.impl.DefaultPromise` has been reimplemented to not use `sun.misc.Unsafe` Securing: - Add a self-check in `completeWith` and `tryCompleteWith` to avoid cycles in trait Promise - Capping the maximum number of threads for the global `ExecutionContext` to the max parallelism - Implementing (almost) all `Future` combinators on `transformWith` and `transform` means that `DefaultPromise` linking works on both `(flat)map` and `recover(With)` - Nested `blocking {}` should not spawn extra threads beyond the first. Removes: - the private `internalExecutor` method in favor of an import in trait `Future` - the private `internalExecutor` method in favor of an import in trait `Promise` - the `AtomicReferenceFieldUpdater` in `AbstractPromise` since we're using `Unsafe` - `scala.concurrent.impl.Future` is no longer needed Deprecates: - `Future.onSuccess` - discourage the use of callbacks (and is also redundant considering `foreach` and `onComplete`) - `Future.onFailure` - discourage the use of callbacks (and is also redundant considering `onComplete` and `failed.foreach`) - `ExecutionContext.prepare` - it was ill specced and it is too easy to forget to call it (or even know when to call it or call it more times than needed) - All classes in scala.concurrent.forkjoin. Scala 2.12 will be Java 8+ and as such the jsr166e should be used as included in java.util.concurrent. Reimplements: - `failed` - in terms of `transform` - `map` - in terms of `transform` - `flatMap` - in terms of `transformWith` - `recover` - in terms of `transform` - `recoverWith` - in terms of `transformWith` - `zip` - in terms of `flatMap` + `map` - `fallbackTo` - in terms of `recoverWith` + `recoverWith` - `andThen` - in terms of `transform` Miscellaneous: - Giving the threads of `ExecutionContext.global` sensible names - Optimizes `object Future.successful` and `object Future.failed` are now separate implementations, to optimize for the result, avoiding doing work for the "other branch". - Optimizes `compressedRoot()` by avoiding double-calls to volatile get. Documentation: - Almost all methods on `Future` and `Promise` have been revisited and had their ScalaDoc updated Tests: - Yes
Diffstat (limited to 'test/files/jvm/scala-concurrent-tck.scala')
-rw-r--r--test/files/jvm/scala-concurrent-tck.scala124
1 files changed, 124 insertions, 0 deletions
diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala
index ce86d4aef0..ba405e97bd 100644
--- a/test/files/jvm/scala-concurrent-tck.scala
+++ b/test/files/jvm/scala-concurrent-tck.scala
@@ -165,6 +165,100 @@ def testTransformFailure(): Unit = once {
g onFailure { case e => done(e eq transformed) }
}
+ def testTransformResultToResult(): Unit = once {
+ done =>
+ Future("foo").transform {
+ case Success(s) => Success(s.toUpperCase)
+ case Failure(f) => throw new Exception("test failed")
+ } onComplete {
+ case Success("FOO") => done(true)
+ case _ => done(false)
+ }
+ }
+
+ def testTransformResultToFailure(): Unit = once {
+ done =>
+ val e = new Exception("expected")
+ Future("foo").transform {
+ case Success(s) => Failure(e)
+ case Failure(f) => throw new Exception("test failed")
+ } onComplete {
+ case Failure(`e`) => done(true)
+ case _ => done(false)
+ }
+ }
+
+ def testTransformFailureToResult(): Unit = once {
+ done =>
+ val e = "foo"
+ Future(throw new Exception("initial")).transform {
+ case Success(s) => throw new Exception("test failed")
+ case Failure(f) => Success(e)
+ } onComplete {
+ case Success(`e`) => done(true)
+ case _ => done(false)
+ }
+ }
+
+ def testTransformFailureToFailure(): Unit = once {
+ done =>
+ val e = new Exception("expected")
+ Future(throw new Exception("initial")).transform {
+ case Success(s) => throw new Exception("test failed")
+ case Failure(f) => Failure(e)
+ } onComplete {
+ case Failure(`e`) => done(true)
+ case _ => done(false)
+ }
+ }
+
+ def testTransformWithResultToResult(): Unit = once {
+ done =>
+ Future("foo").transformWith {
+ case Success(s) => Future(s.toUpperCase)
+ case Failure(f) => throw new Exception("test failed")
+ } onComplete {
+ case Success("FOO") => done(true)
+ case _ => done(false)
+ }
+ }
+
+ def testTransformWithResultToFailure(): Unit = once {
+ done =>
+ val e = new Exception("expected")
+ Future("foo").transformWith {
+ case Success(s) => Future(throw e)
+ case Failure(f) => throw new Exception("test failed")
+ } onComplete {
+ case Failure(`e`) => done(true)
+ case _ => done(false)
+ }
+ }
+
+ def testTransformWithFailureToResult(): Unit = once {
+ done =>
+ val e = "foo"
+ Future(throw new Exception("initial")).transformWith {
+ case Success(s) => throw new Exception("test failed")
+ case Failure(f) => Future(e)
+ } onComplete {
+ case Success(`e`) => done(true)
+ case _ => done(false)
+ }
+ }
+
+ def testTransformWithFailureToFailure(): Unit = once {
+ done =>
+ val e = new Exception("expected")
+ Future(throw new Exception("initial")).transformWith {
+ case Success(s) => throw new Exception("test failed")
+ case Failure(f) => Future(throw e)
+ } onComplete {
+ case Failure(`e`) => done(true)
+ case _ => done(false)
+ }
+ }
+
def testFoldFailure(): Unit = once {
done =>
val f = Future[Unit] { throw new Exception("expected") }
@@ -352,6 +446,14 @@ def testTransformFailure(): Unit = once {
h onFailure { case e => done(e eq cause) }
}
+ def testFallbackToThis(): Unit = {
+ def check(f: Future[Int]) = assert((f fallbackTo f) eq f)
+
+ check(Future { 1 })
+ check(Future.successful(1))
+ check(Future.failed[Int](new Exception))
+ }
+
testMapSuccess()
testMapFailure()
testFlatMapSuccess()
@@ -373,6 +475,16 @@ def testTransformFailure(): Unit = once {
testFallbackToFailure()
testTransformSuccess()
testTransformSuccessPF()
+ testTransformFailure()
+ testTransformFailurePF()
+ testTransformResultToResult()
+ testTransformResultToFailure()
+ testTransformFailureToResult()
+ testTransformFailureToFailure()
+ testTransformWithResultToResult()
+ testTransformWithResultToFailure()
+ testTransformWithFailureToResult()
+ testTransformWithFailureToFailure()
}
@@ -593,6 +705,17 @@ trait Exceptions extends TestBase {
}
+trait GlobalExecutionContext extends TestBase {
+ def testNameOfGlobalECThreads(): Unit = once {
+ done => Future({
+ val expectedName = "scala-execution-context-global-"+ Thread.currentThread.getId
+ done(expectedName == Thread.currentThread.getName)
+ })(ExecutionContext.global)
+ }
+
+ testNameOfGlobalECThreads()
+}
+
trait CustomExecutionContext extends TestBase {
import scala.concurrent.{ ExecutionContext, Awaitable }
@@ -772,6 +895,7 @@ with FutureProjections
with Promises
with BlockContexts
with Exceptions
+with GlobalExecutionContext
with CustomExecutionContext
with ExecutionContextPrepare
{