Yes, it looks the same as in Java.
For a test setup where the test may freeze or run for too long, I use the promise to fail the test (for some reason). For example, a timeout monitor may “cancel” a test runner (interrupt the stream and compare the AndSet flag), and then end the promise with an error. Or, test preparation may fail with a failed test earlier. Or the test passes and gives a result. At a higher level, the test rig simply sees the future and its value.
What makes Java different are your options for composing futures.
val all = Future.traverse(tests)(test => { val toKeep = promise[Result] // promise to keep, or fail by monitor val f = for (w <- feed(prepare(test, toKeep))) yield { monitored(w, toKeep) { listener.start(w) w.runTest() } } f completing consume _ // strip context val g = f map (r => r.copy(context = null)) (toKeep completeWith g).future })
source share