summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
authorJason Zaugg <jzaugg@gmail.com>2013-09-20 14:02:44 +0200
committerJason Zaugg <jzaugg@gmail.com>2013-09-21 09:04:15 +0200
commit7f4b44b612abdc62fba9810194cee17c7d0de37e (patch)
treef4b3268f6cb3d8246f8520571570ee87c022ab14 /test
parente176a1005186f5d6da8ed5a79820d12ca7280e3b (diff)
downloadscala-7f4b44b612abdc62fba9810194cee17c7d0de37e.tar.gz
scala-7f4b44b612abdc62fba9810194cee17c7d0de37e.tar.bz2
scala-7f4b44b612abdc62fba9810194cee17c7d0de37e.zip
SI-7861 Don't execute internal callbacks on the user Executor
Callbacks internal to the implementation of Futures should be executed with the `InternalCallbackExecutor`, rather than the user supplied `Executor`. In a refactoring da54f34a6, `recoverWith` and `flatMap` no longer played by these rules. This was noticed by a persnickety test in Play. Before this patch, the enclosed test outputs: % scala-hash v2.10.3-RC2 test/files/run/future-flatmap-exec-count.scala mapping execute() flatmapping execute() execute() recovering execute() execute()
Diffstat (limited to 'test')
-rw-r--r--test/files/run/future-flatmap-exec-count.check6
-rw-r--r--test/files/run/future-flatmap-exec-count.scala61
2 files changed, 67 insertions, 0 deletions
diff --git a/test/files/run/future-flatmap-exec-count.check b/test/files/run/future-flatmap-exec-count.check
new file mode 100644
index 0000000000..dd9dce64ed
--- /dev/null
+++ b/test/files/run/future-flatmap-exec-count.check
@@ -0,0 +1,6 @@
+mapping
+execute()
+flatmapping
+execute()
+recovering
+execute()
diff --git a/test/files/run/future-flatmap-exec-count.scala b/test/files/run/future-flatmap-exec-count.scala
new file mode 100644
index 0000000000..86c37be938
--- /dev/null
+++ b/test/files/run/future-flatmap-exec-count.scala
@@ -0,0 +1,61 @@
+import scala.concurrent._
+import java.util.concurrent.atomic.AtomicInteger
+
+object Test {
+ def main(args: Array[String]) {
+ test()
+ }
+
+ def test() = {
+ def await(f: Future[Any]) =
+ Await.result(f, duration.Duration.Inf)
+
+ val ec = new TestExecutionContext(ExecutionContext.Implicits.global)
+
+ {
+ val p = Promise[Int]()
+ val fp = p.future
+ println("mapping")
+ val mapped = fp.map(x => x)(ec)
+ p.success(0)
+ await(mapped)
+ }
+
+ {
+ println("flatmapping")
+ val p = Promise[Int]()
+ val fp = p.future
+ val flatMapped = fp.flatMap({ (x: Int) =>
+ Future.successful(2 * x)
+ })(ec)
+ p.success(0)
+ await(flatMapped)
+ }
+
+ {
+ println("recovering")
+ val recovered = Future.failed(new Throwable()).recoverWith {
+ case _ => Future.successful(2)
+ }(ec)
+ await(recovered)
+ }
+ }
+
+ class TestExecutionContext(delegate: ExecutionContext) extends ExecutionContext {
+ def execute(runnable: Runnable): Unit = ???
+
+ def reportFailure(t: Throwable): Unit = ???
+
+ override def prepare(): ExecutionContext = {
+ val preparedDelegate = delegate.prepare()
+ return new ExecutionContext {
+ def execute(runnable: Runnable): Unit = {
+ println("execute()")
+ preparedDelegate.execute(runnable)
+ }
+
+ def reportFailure(t: Throwable): Unit = ???
+ }
+ }
+ }
+}