From d2c5324cfdc5a06a848d7001963a3f465e34beb8 Mon Sep 17 00:00:00 2001 From: Viktor Klang Date: Wed, 19 Jun 2013 23:20:30 +0200 Subject: Refactoring to the scala-concurrent-tck.scala - there were numerous logical issues with the former implementation - failed assertions may not fail the build - there was a lot of ceremony and noise --- test/files/jvm/scala-concurrent-tck.scala | 562 ++++++++---------------------- 1 file changed, 153 insertions(+), 409 deletions(-) (limited to 'test/files/jvm') diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala index b2b4183564..6e2b8ca033 100644 --- a/test/files/jvm/scala-concurrent-tck.scala +++ b/test/files/jvm/scala-concurrent-tck.scala @@ -15,21 +15,17 @@ import scala.reflect.{ classTag, ClassTag } import scala.tools.partest.TestUtil.intercept trait TestBase { - - def once(body: (() => Unit) => Unit) { - val sv = new SyncVar[Boolean] - body(() => sv put true) - sv.take(2000) + trait Done { def apply(proof: => Boolean): Unit } + def once(body: Done => Unit) { + import java.util.concurrent.{ LinkedBlockingQueue, TimeUnit } + val q = new LinkedBlockingQueue[Try[Boolean]] + body(new Done { + def apply(proof: => Boolean): Unit = q offer Try(proof) + }) + assert(q.poll(2000, TimeUnit.MILLISECONDS).get) + // Check that we don't get more than one completion + assert(q.poll(50, TimeUnit.MILLISECONDS) eq null) } - - // def assert(cond: => Boolean) { - // try { - // Predef.assert(cond) - // } catch { - // case e => e.printStackTrace() - // } - // } - } @@ -39,99 +35,52 @@ trait FutureCallbacks extends TestBase { def testOnSuccess(): Unit = once { done => var x = 0 - val f = future { - x = 1 - } - f onSuccess { - case _ => - done() - assert(x == 1) - } + val f = future { x = 1 } + f onSuccess { case _ => done(x == 1) } } def testOnSuccessWhenCompleted(): Unit = once { done => var x = 0 - val f = future { - x = 1 - } + val f = future { x = 1 } f onSuccess { - case _ => - assert(x == 1) + case _ if x == 1 => x = 2 - f onSuccess { - case _ => - assert(x == 2) - done() - } + f onSuccess { case _ => done(x == 2) } } } def testOnSuccessWhenFailed(): Unit = once { done => - val f = future[Unit] { - done() - throw new Exception - } - f onSuccess { - case _ => assert(false) - } + val f = future[Unit] { throw new Exception } + f onSuccess { case _ => done(false) } + f onFailure { case _ => done(true) } } def testOnFailure(): Unit = once { done => - var x = 0 - val f = future[Unit] { - x = 1 - throw new Exception - } - f onSuccess { - case _ => - done() - assert(false) - } - f onFailure { - case _ => - done() - assert(x == 1) - } + val f = future[Unit] { throw new Exception } + f onSuccess { case _ => done(false) } + f onFailure { case _ => done(true) } } def testOnFailureWhenSpecialThrowable(num: Int, cause: Throwable): Unit = once { done => - val f = future[Unit] { - throw cause - } - f onSuccess { - case _ => - done() - assert(false) - } + val f = future[Unit] { throw cause } + f onSuccess { case _ => done(false) } f onFailure { - case e: ExecutionException if (e.getCause == cause) => - done() - case _ => - done() - assert(false) + case e: ExecutionException if e.getCause == cause => done(true) + case _ => done(false) } } def testOnFailureWhenTimeoutException(): Unit = once { done => - val f = future[Unit] { - throw new TimeoutException() - } - f onSuccess { - case _ => - done() - assert(false) - } + val f = future[Unit] { throw new TimeoutException() } + f onSuccess { case _ => done(false) } f onFailure { - case e: TimeoutException => - done() - case other => - done() - assert(false) + case e: TimeoutException => done(true) + case _ => done(false) } } @@ -151,7 +100,6 @@ trait FutureCallbacks extends TestBase { //testOnFailureWhenSpecialThrowable(7, new InterruptedException) testThatNestedCallbacksDoNotYieldStackOverflow() testOnFailureWhenTimeoutException() - } @@ -162,207 +110,120 @@ trait FutureCombinators extends TestBase { done => val f = future { 5 } val g = f map { x => "result: " + x } - g onSuccess { - case s => - done() - assert(s == "result: 5") - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case s => done(s == "result: 5") } + g onFailure { case _ => done(false) } } def testMapFailure(): Unit = once { done => - val f = future { - throw new Exception("exception message") - } + val f = future[Unit] { throw new Exception("exception message") } val g = f map { x => "result: " + x } - g onSuccess { - case _ => - done() - assert(false) - } - g onFailure { - case t => - done() - assert(t.getMessage() == "exception message") - } + g onSuccess { case _ => done(false) } + g onFailure { case t => done(t.getMessage() == "exception message") } } def testMapSuccessPF(): Unit = once { done => val f = future { 5 } val g = f map { case r => "result: " + r } - g onSuccess { - case s => - done() - assert(s == "result: 5") - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case s => done(s == "result: 5") } + g onFailure { case _ => done(false) } } def testTransformSuccess(): Unit = once { done => val f = future { 5 } val g = f.transform(r => "result: " + r, identity) - g onSuccess { - case s => - done() - assert(s == "result: 5") - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case s => done(s == "result: 5") } + g onFailure { case _ => done(false) } } def testTransformSuccessPF(): Unit = once { done => val f = future { 5 } val g = f.transform( { case r => "result: " + r }, identity) - g onSuccess { - case s => - done() - assert(s == "result: 5") - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case s => done(s == "result: 5") } + g onFailure { case _ => done(false) } + } + +def testTransformFailure(): Unit = once { + done => + val transformed = new Exception("transformed") + val f = future { throw new Exception("expected") } + val g = f.transform(identity, _ => transformed) + g onSuccess { case _ => done(false) } + g onFailure { case e => done(e eq transformed) } + } + + def testTransformFailurePF(): Unit = once { + done => + val e = new Exception("expected") + val transformed = new Exception("transformed") + val f = future[Unit] { throw e } + val g = f.transform(identity, { case `e` => transformed }) + g onSuccess { case _ => done(false) } + g onFailure { case e => done(e eq transformed) } } def testFoldFailure(): Unit = once { done => - val f = future { - throw new Exception("exception message") - } + val f = future[Unit] { throw new Exception("expected") } val g = f.transform(r => "result: " + r, identity) - g onSuccess { - case _ => - done() - assert(false) - } - g onFailure { - case t => - done() - assert(t.getMessage() == "exception message") - } + g onSuccess { case _ => done(false) } + g onFailure { case t => done(t.getMessage() == "expected") } } def testFlatMapSuccess(): Unit = once { done => val f = future { 5 } val g = f flatMap { _ => future { 10 } } - g onSuccess { - case x => - done() - assert(x == 10) - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case x => done(x == 10) } + g onFailure { case _ => done(false) } } def testFlatMapFailure(): Unit = once { done => - val f = future { - throw new Exception("exception message") - } + val f = future[Unit] { throw new Exception("expected") } val g = f flatMap { _ => future { 10 } } - g onSuccess { - case _ => - done() - assert(false) - } - g onFailure { - case t => - done() - assert(t.getMessage() == "exception message") - } + g onSuccess { case _ => done(false) } + g onFailure { case t => done(t.getMessage() == "expected") } } def testFilterSuccess(): Unit = once { done => val f = future { 4 } val g = f filter { _ % 2 == 0 } - g onSuccess { - case x: Int => - done() - assert(x == 4) - } - g onFailure { - case _ => - done() - assert(false) - } + g onSuccess { case x: Int => done(x == 4) } + g onFailure { case _ => done(false) } } def testFilterFailure(): Unit = once { done => val f = future { 4 } val g = f filter { _ % 2 == 1 } - g onSuccess { - case x: Int => - done() - assert(false) - } + g onSuccess { case x: Int => done(false) } g onFailure { - case e: NoSuchElementException => - done() - assert(true) - case _ => - done() - assert(false) + case e: NoSuchElementException => done(true) + case _ => done(false) } } def testCollectSuccess(): Unit = once { done => val f = future { -5 } - val g = f collect { - case x if x < 0 => -x - } - g onSuccess { - case x: Int => - done() - assert(x == 5) - } - g onFailure { - case _ => - done() - assert(false) - } + val g = f collect { case x if x < 0 => -x } + g onSuccess { case x: Int => done(x == 5) } + g onFailure { case _ => done(false) } } def testCollectFailure(): Unit = once { done => val f = future { -5 } - val g = f collect { - case x if x > 0 => x * 2 - } - g onSuccess { - case _ => - done() - assert(false) - } + val g = f collect { case x if x > 0 => x * 2 } + g onSuccess { case _ => done(false) } g onFailure { - case e: NoSuchElementException => - done() - assert(true) - case _ => - done() - assert(false) + case e: NoSuchElementException => done(true) + case _ => done(false) } } @@ -376,16 +237,8 @@ trait FutureCombinators extends TestBase { f foreach { x => p.success(x * 2) } val g = p.future - g.onSuccess { - case res: Int => - done() - assert(res == 10) - } - g.onFailure { - case _ => - done() - assert(false) - } + g.onSuccess { case res: Int => done(res == 10) } + g.onFailure { case _ => done(false) } } def testForeachFailure(): Unit = once { @@ -396,16 +249,8 @@ trait FutureCombinators extends TestBase { f onFailure { case _ => p.failure(new Exception) } val g = p.future - g.onSuccess { - case _ => - done() - assert(false) - } - g.onFailure { - case _ => - done() - assert(true) - } + g.onSuccess { case _ => done(false) } + g.onFailure { case _ => done(true) } } def testRecoverSuccess(): Unit = once { @@ -415,18 +260,9 @@ trait FutureCombinators extends TestBase { throw cause } recover { case re: RuntimeException => - "recovered" - } - f onSuccess { - case x => - done() - assert(x == "recovered") - } - f onFailure { case any => - done() - assert(false) - } - f + "recovered" } + f onSuccess { case x => done(x == "recovered") } + f onFailure { case any => done(false) } } def testRecoverFailure(): Unit = once { @@ -437,15 +273,8 @@ trait FutureCombinators extends TestBase { } recover { case te: TimeoutException => "timeout" } - f onSuccess { - case x => - done() - assert(false) - } - f onFailure { case any => - done() - assert(any == cause) - } + f onSuccess { case _ => done(false) } + f onFailure { case any => done(any == cause) } } def testRecoverWithSuccess(): Unit = once { @@ -457,15 +286,8 @@ trait FutureCombinators extends TestBase { case re: RuntimeException => future { "recovered" } } - f onSuccess { - case x => - done() - assert(x == "recovered") - } - f onFailure { case any => - done() - assert(false) - } + f onSuccess { case x => done(x == "recovered") } + f onFailure { case any => done(false) } } def testRecoverWithFailure(): Unit = once { @@ -477,15 +299,8 @@ trait FutureCombinators extends TestBase { case te: TimeoutException => future { "timeout" } } - f onSuccess { - case x => - done() - assert(false) - } - f onFailure { case any => - done() - assert(any == cause) - } + f onSuccess { case x => done(false) } + f onFailure { case any => done(any == cause) } } def testZipSuccess(): Unit = once { @@ -493,52 +308,28 @@ trait FutureCombinators extends TestBase { val f = future { 5 } val g = future { 6 } val h = f zip g - h onSuccess { - case (l: Int, r: Int) => - done() - assert(l+r == 11) - } - h onFailure { - case _ => - done() - assert(false) - } + h onSuccess { case (l: Int, r: Int) => done(l+r == 11) } + h onFailure { case _ => done(false) } } def testZipFailureLeft(): Unit = once { done => - val cause = new Exception("exception message") + val cause = new Exception("expected") val f = future { throw cause } val g = future { 6 } val h = f zip g - h onSuccess { - case _ => - done() - assert(false) - } - h onFailure { - case e: Exception => - done() - assert(e.getMessage == "exception message") - } + h onSuccess { case _ => done(false) } + h onFailure { case e: Exception => done(e.getMessage == "expected") } } def testZipFailureRight(): Unit = once { done => - val cause = new Exception("exception message") + val cause = new Exception("expected") val f = future { 5 } val g = future { throw cause } val h = f zip g - h onSuccess { - case _ => - done() - assert(false) - } - h onFailure { - case e: Exception => - done() - assert(e.getMessage == "exception message") - } + h onSuccess { case _ => done(false) } + h onFailure { case e: Exception => done(e.getMessage == "expected") } } def testFallbackTo(): Unit = once { @@ -546,17 +337,8 @@ trait FutureCombinators extends TestBase { val f = future { sys.error("failed") } val g = future { 5 } val h = f fallbackTo g - - h onSuccess { - case x: Int => - done() - assert(x == 5) - } - h onFailure { - case _ => - done() - assert(false) - } + h onSuccess { case x: Int => done(x == 5) } + h onFailure { case _ => done(false) } } def testFallbackToFailure(): Unit = once { @@ -566,16 +348,8 @@ trait FutureCombinators extends TestBase { val g = future { throw cause } val h = f fallbackTo g - h onSuccess { - case _ => - done() - assert(false) - } - h onFailure { - case e: Exception => - done() - assert(e == cause) - } + h onSuccess { case _ => done(false) } + h onFailure { case e => done(e eq cause) } } testMapSuccess() @@ -597,6 +371,8 @@ trait FutureCombinators extends TestBase { testZipFailureRight() testFallbackTo() testFallbackToFailure() + testTransformSuccess() + testTransformSuccessPF() } @@ -606,40 +382,26 @@ trait FutureProjections extends TestBase { def testFailedFailureOnComplete(): Unit = once { done => val cause = new RuntimeException - val f = future { - throw cause - } + val f = future { throw cause } f.failed onComplete { - case Success(t) => - assert(t == cause) - done() - case Failure(t) => - assert(false) + case Success(t) => done(t == cause) + case Failure(t) => done(false) } } def testFailedFailureOnSuccess(): Unit = once { done => val cause = new RuntimeException - val f = future { - throw cause - } - f.failed onSuccess { - case t => - assert(t == cause) - done() - } + val f = future { throw cause } + f.failed onSuccess { case t => done(t == cause) } } def testFailedSuccessOnComplete(): Unit = once { done => val f = future { 0 } f.failed onComplete { - case Success(t) => - assert(false) - case Failure(t) => - assert(t.isInstanceOf[NoSuchElementException]) - done() + case Failure(_: NoSuchElementException) => done(true) + case _ => done(false) } } @@ -647,19 +409,17 @@ trait FutureProjections extends TestBase { done => val f = future { 0 } f.failed onFailure { - case nsee: NoSuchElementException => - done() + case e: NoSuchElementException => done(true) + case _ => done(false) } + f.failed onSuccess { case _ => done(false) } } def testFailedFailureAwait(): Unit = once { done => val cause = new RuntimeException - val f = future { - throw cause - } - assert(Await.result(f.failed, Duration(500, "ms")) == cause) - done() + val f = future { throw cause } + done(Await.result(f.failed, Duration(500, "ms")) == cause) } def testFailedSuccessAwait(): Unit = once { @@ -667,9 +427,10 @@ trait FutureProjections extends TestBase { val f = future { 0 } try { Await.result(f.failed, Duration(500, "ms")) - assert(false) + done(false) } catch { - case nsee: NoSuchElementException => done() + case nsee: NoSuchElementException => done(true) + case _: Throwable => done(false) } } @@ -682,8 +443,8 @@ trait FutureProjections extends TestBase { Await.ready(f, Duration.Zero) Await.ready(f, Duration(500, "ms")) Await.ready(f, Duration.Inf) - done() - } onFailure { case x => throw x } + done(true) + } onFailure { case x => done(throw x) } } def testAwaitNegativeDuration(): Unit = once { done => @@ -692,8 +453,8 @@ trait FutureProjections extends TestBase { intercept[TimeoutException] { Await.ready(f, Duration.Zero) } intercept[TimeoutException] { Await.ready(f, Duration.MinusInf) } intercept[TimeoutException] { Await.ready(f, Duration(-500, "ms")) } - done() - } onFailure { case x => throw x } + done(true) + } onFailure { case x => done(throw x) } } testFailedFailureOnComplete() @@ -704,7 +465,6 @@ trait FutureProjections extends TestBase { testFailedSuccessAwait() testAwaitPositiveDuration() testAwaitNegativeDuration() - } @@ -714,33 +474,25 @@ trait Blocking extends TestBase { def testAwaitSuccess(): Unit = once { done => val f = future { 0 } - Await.result(f, Duration(500, "ms")) - done() + done(Await.result(f, Duration(500, "ms")) == 0) } def testAwaitFailure(): Unit = once { done => val cause = new RuntimeException - val f = future { - throw cause - } + val f = future { throw cause } try { Await.result(f, Duration(500, "ms")) - assert(false) + done(false) } catch { - case t => - assert(t == cause) - done() + case t: Throwable => done(t == cause) } } def testFQCNForAwaitAPI(): Unit = once { done => - - assert(classOf[CanAwait].getName == "scala.concurrent.CanAwait") - assert(Await.getClass.getName == "scala.concurrent.Await") - - done() + done(classOf[CanAwait].getName == "scala.concurrent.CanAwait" && + Await.getClass.getName == "scala.concurrent.Await") } testAwaitSuccess() @@ -813,22 +565,26 @@ trait Promises extends TestBase { val p = promise[Int]() val f = p.future - f onSuccess { - case x => - done() - assert(x == 5) - } - f onFailure { - case any => - done() - assert(false) - } + f onSuccess { case x => done(x == 5) } + f onFailure { case any => done(false) } p.success(5) } - testSuccess() + def testFailure(): Unit = once { + done => + val e = new Exception("expected") + val p = promise[Int]() + val f = p.future + + f onSuccess { case x => done(false) } + f onFailure { case any => done(any eq e) } + + p.failure(e) + } + testSuccess() + testFailure() } @@ -888,11 +644,11 @@ trait CustomExecutionContext extends TestBase { val count = countExecs { implicit ec => blocking { once { done => - val f = future({ assertNoEC() })(defaultEC) + val f = future(assertNoEC())(defaultEC) f onSuccess { case _ => assertEC() - done() + done(true) } assertNoEC() } @@ -911,7 +667,7 @@ trait CustomExecutionContext extends TestBase { f onSuccess { case _ => assertEC() - done() + done(true) } } } @@ -935,15 +691,10 @@ trait CustomExecutionContext extends TestBase { Promise.successful(x + 1).future.map(addOne).map(addOne) } onComplete { case Failure(t) => - try { - throw new AssertionError("error in test: " + t.getMessage, t) - } finally { - done() - } + done(throw new AssertionError("error in test: " + t.getMessage, t)) case Success(x) => assertEC() - assert(x == 14) - done() + done(x == 14) } assertNoEC() } @@ -999,21 +750,14 @@ trait ExecutionContextPrepare extends TestBase { done => theLocal.set("secret") val fut = future { 42 } - fut onComplete { - case _ => - assert(theLocal.get == "secret") - done() - } + fut onComplete { case _ => done(theLocal.get == "secret") } } def testMap(): Unit = once { done => theLocal.set("secret2") val fut = future { 42 } - fut map { x => - assert(theLocal.get == "secret2") - done() - } + fut map { x => done(theLocal.get == "secret2") } } testOnComplete() -- cgit v1.2.3