diff options
Diffstat (limited to 'test/files/jvm')
-rw-r--r-- | test/files/jvm/concurrent-future.check | 16 | ||||
-rw-r--r-- | test/files/jvm/concurrent-future.scala | 122 | ||||
-rwxr-xr-x | test/files/jvm/interpreter.check | 738 | ||||
-rw-r--r-- | test/files/jvm/interpreter.scala | 9 | ||||
-rw-r--r-- | test/files/jvm/manifests.check.temporarily.disabled (renamed from test/files/jvm/manifests.check) | 0 | ||||
-rw-r--r-- | test/files/jvm/manifests.scala.temporarily.disabled (renamed from test/files/jvm/manifests.scala) | 10 | ||||
-rw-r--r-- | test/files/jvm/scala-concurrent-tck.scala | 290 |
7 files changed, 648 insertions, 537 deletions
diff --git a/test/files/jvm/concurrent-future.check b/test/files/jvm/concurrent-future.check deleted file mode 100644 index c55e824818..0000000000 --- a/test/files/jvm/concurrent-future.check +++ /dev/null @@ -1,16 +0,0 @@ -test1: hai world -test1: kthxbye -test2: hai world -test2: awsum thx -test2: kthxbye -test3: hai world -test4: hai world -test4: kthxbye -test5: hai world -test5: kthxbye -test6: hai world -test6: kthxbye -test7: hai world -test7: kthxbye -test8: hai world -test8: im in yr loop diff --git a/test/files/jvm/concurrent-future.scala b/test/files/jvm/concurrent-future.scala deleted file mode 100644 index b44d054219..0000000000 --- a/test/files/jvm/concurrent-future.scala +++ /dev/null @@ -1,122 +0,0 @@ - - - -import scala.concurrent._ - - - -object Test extends App { - - def once(body: (() => Unit) => Unit) { - val sv = new SyncVar[Boolean] - body(() => sv put true) - sv.take() - } - - def output(num: Int, msg: String) { - println("test" + num + ": " + msg) - } - - def testOnSuccess(): Unit = once { - done => - val f = future { - output(1, "hai world") - } - f onSuccess { case _ => - output(1, "kthxbye") - done() - } - } - - def testOnSuccessWhenCompleted(): Unit = once { - done => - val f = future { - output(2, "hai world") - } - f onSuccess { case _ => - output(2, "awsum thx") - f onSuccess { case _ => - output(2, "kthxbye") - done() - } - } - } - - def testOnSuccessWhenFailed(): Unit = once { - done => - val f = future[Unit] { - output(3, "hai world") - done() - throw new Exception - } - f onSuccess { case _ => - output(3, "onoes") - } - } - - def testOnFailure(): Unit = once { - done => - val f = future[Unit] { - output(4, "hai world") - throw new Exception - } - f onSuccess { case _ => - output(4, "onoes") - done() - } - f onFailure { case _ => - output(4, "kthxbye") - done() - } - } - - def testOnFailureWhenSpecialThrowable(num: Int, cause: Throwable): Unit = once { - done => - val f = future[Unit] { - output(num, "hai world") - throw cause - } - f onSuccess { case _ => - output(num, "onoes") - done() - } - f onFailure { - case e: ExecutionException if (e.getCause == cause) => - output(num, "kthxbye") - done() - case _ => - output(num, "onoes") - done() - } - } - - def testOnFailureWhenFutureTimeoutException(): Unit = once { - done => - val f = future[Unit] { - output(8, "hai world") - throw new FutureTimeoutException(null) - } - f onSuccess { case _ => - output(8, "onoes") - done() - } - f onFailure { - case e: FutureTimeoutException => - output(8, "im in yr loop") - done() - case other => - output(8, "onoes: " + other) - done() - } - } - - testOnSuccess() - testOnSuccessWhenCompleted() - testOnSuccessWhenFailed() - testOnFailure() - testOnFailureWhenSpecialThrowable(5, new Error) - testOnFailureWhenSpecialThrowable(6, new scala.util.control.ControlThrowable { }) - testOnFailureWhenSpecialThrowable(7, new InterruptedException) - testOnFailureWhenFutureTimeoutException() - -} diff --git a/test/files/jvm/interpreter.check b/test/files/jvm/interpreter.check index 243c9aa3be..d93e314d8e 100755 --- a/test/files/jvm/interpreter.check +++ b/test/files/jvm/interpreter.check @@ -1,372 +1,372 @@ -Type in expressions to have them evaluated. -Type :help for more information. - -scala> - -scala> // basics - -scala> 3+4 -res0: Int = 7 - -scala> def gcd(x: Int, y: Int): Int = { - if (x == 0) y - else if (y == 0) x - else gcd(y%x, x) -} -gcd: (x: Int, y: Int)Int - -scala> val five = gcd(15,35) -five: Int = 5 - -scala> var x = 1 -x: Int = 1 - -scala> x = 2 -x: Int = 2 - -scala> val three = x+1 -three: Int = 3 - -scala> type anotherint = Int -defined type alias anotherint - -scala> val four: anotherint = 4 -four: anotherint = 4 - -scala> val bogus: anotherint = "hello" -<console>:8: error: type mismatch; - found : String("hello") - required: anotherint - (which expands to) Int - val bogus: anotherint = "hello" - ^ - -scala> trait PointlessTrait -defined trait PointlessTrait - -scala> val (x,y) = (2,3) -x: Int = 2 -y: Int = 3 - -scala> println("hello") -hello - -scala> - -scala> // ticket #1513 - -scala> val t1513 = Array(null) -t1513: Array[Null] = Array(null) - -scala> // ambiguous toString problem from #547 - -scala> val atom = new scala.xml.Atom() -atom: scala.xml.Atom[Unit] = () - -scala> // overriding toString problem from #1404 - -scala> class S(override val toString : String) -defined class S - -scala> val fish = new S("fish") -fish: S = fish - -scala> // Test that arrays pretty print nicely. - -scala> val arr = Array("What's", "up", "doc?") -arr: Array[String] = Array(What's, up, doc?) - -scala> // Test that arrays pretty print nicely, even when we give them type Any - -scala> val arrInt : Any = Array(1,2,3) -arrInt: Any = Array(1, 2, 3) - -scala> // Test that nested arrays are pretty-printed correctly - -scala> val arrArrInt : Any = Array(Array(1, 2), Array(3, 4)) -arrArrInt: Any = Array(Array(1, 2), Array(3, 4)) - -scala> - -scala> // implicit conversions - -scala> case class Foo(n: Int) -defined class Foo - -scala> case class Bar(n: Int) -defined class Bar - -scala> implicit def foo2bar(foo: Foo) = Bar(foo.n) -foo2bar: (foo: Foo)Bar - -scala> val bar: Bar = Foo(3) -bar: Bar = Bar(3) - -scala> - -scala> // importing from a previous result - -scala> import bar._ -import bar._ - -scala> val m = n -m: Int = 3 - -scala> - -scala> // stressing the imports mechanism - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> val one = 1 -one: Int = 1 - -scala> - -scala> - -scala> val x1 = 1 -x1: Int = 1 - -scala> val x2 = 1 -x2: Int = 1 - -scala> val x3 = 1 -x3: Int = 1 - -scala> val x4 = 1 -x4: Int = 1 - -scala> val x5 = 1 -x5: Int = 1 - -scala> val x6 = 1 -x6: Int = 1 - -scala> val x7 = 1 -x7: Int = 1 - -scala> val x8 = 1 -x8: Int = 1 - -scala> val x9 = 1 -x9: Int = 1 - -scala> val x10 = 1 -x10: Int = 1 - -scala> val x11 = 1 -x11: Int = 1 - -scala> val x12 = 1 -x12: Int = 1 - -scala> val x13 = 1 -x13: Int = 1 - -scala> val x14 = 1 -x14: Int = 1 - -scala> val x15 = 1 -x15: Int = 1 - -scala> val x16 = 1 -x16: Int = 1 - -scala> val x17 = 1 -x17: Int = 1 - -scala> val x18 = 1 -x18: Int = 1 - -scala> val x19 = 1 -x19: Int = 1 - -scala> val x20 = 1 -x20: Int = 1 - -scala> - -scala> val two = one + x5 -two: Int = 2 - -scala> - -scala> // handling generic wildcard arrays (#2386) - -scala> // It's put here because type feedback is an important part of it. - -scala> val xs: Array[_] = Array(1, 2) -xs: Array[_] = Array(1, 2) - -scala> xs.size -res2: Int = 2 - -scala> xs.head -res3: Any = 1 - -scala> xs filter (_ == 2) -res4: Array[_] = Array(2) - -scala> xs map (_ => "abc") -res5: Array[String] = Array(abc, abc) - -scala> xs map (x => x) -res6: scala.collection.mutable.ArraySeq[_] = ArraySeq(1, 2) - -scala> xs map (x => (x, x)) -res7: Array[(_$1, _$1)] forSome { type _$1 } = Array((1,1), (2,2)) - -scala> - -scala> // interior syntax errors should *not* go into multi-line input mode. - -scala> // both of the following should abort immediately: - -scala> def x => y => z -<console>:1: error: '=' expected but '=>' found. - def x => y => z - ^ - -scala> [1,2,3] -<console>:1: error: illegal start of definition - [1,2,3] - ^ - -scala> - -scala> - -scala> // multi-line XML - -scala> <a> -<b - c="c" - d="dd" -/></a> -res8: scala.xml.Elem = -<a> -<b c="c" d="dd"/></a> - -scala> - -scala> - -scala> /* - /* - multi-line comment - */ -*/ - -scala> - -scala> - -scala> // multi-line string - -scala> """ -hello -there -""" -res9: String = -" -hello -there -" - -scala> - -scala> (1 + // give up early by typing two blank lines - - -You typed two blank lines. Starting a new command. - -scala> // defining and using quoted names should work (ticket #323) - -scala> def `match` = 1 -match: Int - -scala> val x = `match` -x: Int = 1 - -scala> - -scala> // multiple classes defined on one line - -scala> sealed class Exp; class Fact extends Exp; class Term extends Exp -defined class Exp -defined class Fact -defined class Term - -scala> def f(e: Exp) = e match { // non-exhaustive warning here - case _:Fact => 3 -} -<console>:18: warning: match is not exhaustive! -missing combination Exp -missing combination Term - - def f(e: Exp) = e match { // non-exhaustive warning here - ^ -f: (e: Exp)Int - -scala> - -scala> +Type in expressions to have them evaluated.
+Type :help for more information.
+
+scala>
+
+scala> // basics
+
+scala> 3+4
+res0: Int = 7
+
+scala> def gcd(x: Int, y: Int): Int = {
+ if (x == 0) y
+ else if (y == 0) x
+ else gcd(y%x, x)
+}
+gcd: (x: Int, y: Int)Int
+
+scala> val five = gcd(15,35)
+five: Int = 5
+
+scala> var x = 1
+x: Int = 1
+
+scala> x = 2
+x: Int = 2
+
+scala> val three = x+1
+three: Int = 3
+
+scala> type anotherint = Int
+defined type alias anotherint
+
+scala> val four: anotherint = 4
+four: anotherint = 4
+
+scala> val bogus: anotherint = "hello"
+<console>:8: error: type mismatch;
+ found : String("hello")
+ required: anotherint
+ (which expands to) Int
+ val bogus: anotherint = "hello"
+ ^
+
+scala> trait PointlessTrait
+defined trait PointlessTrait
+
+scala> val (x,y) = (2,3)
+x: Int = 2
+y: Int = 3
+
+scala> println("hello")
+hello
+
+scala>
+
+scala> // ticket #1513
+
+scala> val t1513 = Array(null)
+t1513: Array[Null] = Array(null)
+
+scala> // ambiguous toString problem from #547
+
+scala> val atom = new scala.xml.Atom()
+atom: scala.xml.Atom[Unit] = ()
+
+scala> // overriding toString problem from #1404
+
+scala> class S(override val toString : String)
+defined class S
+
+scala> val fish = new S("fish")
+fish: S = fish
+
+scala> // Test that arrays pretty print nicely.
+
+scala> val arr = Array("What's", "up", "doc?")
+arr: Array[String] = Array(What's, up, doc?)
+
+scala> // Test that arrays pretty print nicely, even when we give them type Any
+
+scala> val arrInt : Any = Array(1,2,3)
+arrInt: Any = Array(1, 2, 3)
+
+scala> // Test that nested arrays are pretty-printed correctly
+
+scala> val arrArrInt : Any = Array(Array(1, 2), Array(3, 4))
+arrArrInt: Any = Array(Array(1, 2), Array(3, 4))
+
+scala>
+
+scala> // implicit conversions
+
+scala> case class Foo(n: Int)
+defined class Foo
+
+scala> case class Bar(n: Int)
+defined class Bar
+
+scala> implicit def foo2bar(foo: Foo) = Bar(foo.n)
+foo2bar: (foo: Foo)Bar
+
+scala> val bar: Bar = Foo(3)
+bar: Bar = Bar(3)
+
+scala>
+
+scala> // importing from a previous result
+
+scala> import bar._
+import bar._
+
+scala> val m = n
+m: Int = 3
+
+scala>
+
+scala> // stressing the imports mechanism
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala> val one = 1
+one: Int = 1
+
+scala>
+
+scala>
+
+scala> val x1 = 1
+x1: Int = 1
+
+scala> val x2 = 1
+x2: Int = 1
+
+scala> val x3 = 1
+x3: Int = 1
+
+scala> val x4 = 1
+x4: Int = 1
+
+scala> val x5 = 1
+x5: Int = 1
+
+scala> val x6 = 1
+x6: Int = 1
+
+scala> val x7 = 1
+x7: Int = 1
+
+scala> val x8 = 1
+x8: Int = 1
+
+scala> val x9 = 1
+x9: Int = 1
+
+scala> val x10 = 1
+x10: Int = 1
+
+scala> val x11 = 1
+x11: Int = 1
+
+scala> val x12 = 1
+x12: Int = 1
+
+scala> val x13 = 1
+x13: Int = 1
+
+scala> val x14 = 1
+x14: Int = 1
+
+scala> val x15 = 1
+x15: Int = 1
+
+scala> val x16 = 1
+x16: Int = 1
+
+scala> val x17 = 1
+x17: Int = 1
+
+scala> val x18 = 1
+x18: Int = 1
+
+scala> val x19 = 1
+x19: Int = 1
+
+scala> val x20 = 1
+x20: Int = 1
+
+scala>
+
+scala> val two = one + x5
+two: Int = 2
+
+scala>
+
+scala> // handling generic wildcard arrays (#2386)
+
+scala> // It's put here because type feedback is an important part of it.
+
+scala> val xs: Array[_] = Array(1, 2)
+xs: Array[_] = Array(1, 2)
+
+scala> xs.size
+res2: Int = 2
+
+scala> xs.head
+res3: Any = 1
+
+scala> xs filter (_ == 2)
+res4: Array[_] = Array(2)
+
+scala> xs map (_ => "abc")
+res5: Array[String] = Array(abc, abc)
+
+scala> xs map (x => x)
+res6: scala.collection.mutable.ArraySeq[_] = ArraySeq(1, 2)
+
+scala> xs map (x => (x, x))
+res7: Array[(_$1, _$1)] forSome { type _$1 } = Array((1,1), (2,2))
+
+scala>
+
+scala> // interior syntax errors should *not* go into multi-line input mode.
+
+scala> // both of the following should abort immediately:
+
+scala> def x => y => z
+<console>:1: error: '=' expected but '=>' found.
+ def x => y => z
+ ^
+
+scala> [1,2,3]
+<console>:1: error: illegal start of definition
+ [1,2,3]
+ ^
+
+scala>
+
+scala>
+
+scala> // multi-line XML
+
+scala> <a>
+<b
+ c="c"
+ d="dd"
+/></a>
+res8: scala.xml.Elem =
+<a>
+<b c="c" d="dd"/></a>
+
+scala>
+
+scala>
+
+scala> /*
+ /*
+ multi-line comment
+ */
+*/
+
+scala>
+
+scala>
+
+scala> // multi-line string
+
+scala> """
+hello
+there
+"""
+res9: String =
+"
+hello
+there
+"
+
+scala>
+
+scala> (1 + // give up early by typing two blank lines
+
+
+You typed two blank lines. Starting a new command.
+
+scala> // defining and using quoted names should work (ticket #323)
+
+scala> def `match` = 1
+match: Int
+
+scala> val x = `match`
+x: Int = 1
+
+scala>
+
+scala> // multiple classes defined on one line
+
+scala> sealed class Exp; class Fact extends Exp; class Term extends Exp
+defined class Exp
+defined class Fact
+defined class Term
+
+scala> def f(e: Exp) = e match { // non-exhaustive warning here
+ case _:Fact => 3
+}
+<console>:18: warning: match is not exhaustive!
+missing combination Exp
+missing combination Term
+
+ def f(e: Exp) = e match { // non-exhaustive warning here
+ ^
+f: (e: Exp)Int
+
+scala>
+
+scala>
plusOne: (x: Int)Int res0: Int = 6 res0: String = after reset diff --git a/test/files/jvm/interpreter.scala b/test/files/jvm/interpreter.scala index f0bc8b5818..1f289d9335 100644 --- a/test/files/jvm/interpreter.scala +++ b/test/files/jvm/interpreter.scala @@ -2,6 +2,7 @@ import scala.tools.nsc._ import scala.tools.partest.ReplTest object Test extends ReplTest { + override def extraSettings = "-deprecation" def code = <code> // basics 3+4 @@ -29,7 +30,7 @@ val atom = new scala.xml.Atom() class S(override val toString : String) val fish = new S("fish") // Test that arrays pretty print nicely. -val arr = Array("What's", "up", "doc?") +val arr = Array("What's", "up", "doc?") // Test that arrays pretty print nicely, even when we give them type Any val arrInt : Any = Array(1,2,3) // Test that nested arrays are pretty-printed correctly @@ -132,8 +133,8 @@ there // defining and using quoted names should work (ticket #323) -def `match` = 1 -val x = `match` +def `match` = 1 +val x = `match` // multiple classes defined on one line sealed class Exp; class Fact extends Exp; class Term extends Exp @@ -153,6 +154,6 @@ def f(e: Exp) = e match {{ // non-exhaustive warning here interp.interpret("\"after reset\"") interp.interpret("plusOne(5) // should be undefined now") } - + appendix() } diff --git a/test/files/jvm/manifests.check b/test/files/jvm/manifests.check.temporarily.disabled index 54f504b929..54f504b929 100644 --- a/test/files/jvm/manifests.check +++ b/test/files/jvm/manifests.check.temporarily.disabled diff --git a/test/files/jvm/manifests.scala b/test/files/jvm/manifests.scala.temporarily.disabled index 6bbea4d052..241966fd9d 100644 --- a/test/files/jvm/manifests.scala +++ b/test/files/jvm/manifests.scala.temporarily.disabled @@ -1,7 +1,6 @@ object Test extends App { Test1 Test2 - //Test3 // Java 1.5+ only } class Foo[T](x: T) @@ -88,15 +87,6 @@ object Test2 { println() } -object Test3 extends TestUtil { - import scala.reflect.Manifest._ - val ct1 = classType(classOf[Char]) - val ct2 = classType(classOf[List[_]], ct1) - print(ct1) - //print(ct2) // ??? x=scala.List[char], m=scala.reflect.Manifest[scala.runtime.Nothing$] - println() -} - trait TestUtil { import java.io._ def write[A](o: A): Array[Byte] = { diff --git a/test/files/jvm/scala-concurrent-tck.scala b/test/files/jvm/scala-concurrent-tck.scala index b3470d275d..f0ca438774 100644 --- a/test/files/jvm/scala-concurrent-tck.scala +++ b/test/files/jvm/scala-concurrent-tck.scala @@ -147,59 +147,185 @@ trait FutureCallbacks extends TestBase { trait FutureCombinators extends TestBase { - // map: stub def testMapSuccess(): Unit = once { done => - 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) + } } def testMapFailure(): Unit = once { done => - done() + val f = future { + 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") + } } - // flatMap: stub def testFlatMapSuccess(): Unit = once { done => - 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) + } } def testFlatMapFailure(): Unit = once { done => - done() + val f = future { + throw new Exception("exception message") + } + val g = f flatMap { _ => future { 10 } } + g onSuccess { + case _ => + done() + assert(false) + } + g onFailure { + case t => + done() + assert(t.getMessage() == "exception message") + } } - // filter: stub def testFilterSuccess(): Unit = once { done => - 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) + } } def testFilterFailure(): Unit = once { done => - done() + val f = future { 4 } + val g = f filter { _ % 2 == 1 } + g onSuccess { + case x: Int => + done() + assert(false) + } + g onFailure { + case e: NoSuchElementException => + done() + assert(true) + case _ => + done() + assert(false) + } } - // collect: stub def testCollectSuccess(): Unit = once { done => - 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) + } } def testCollectFailure(): Unit = once { done => - done() + val f = future { -5 } + val g = f collect { + case x if x > 0 => x * 2 + } + g onSuccess { + case _ => + done() + assert(false) + } + g onFailure { + case e: NoSuchElementException => + done() + assert(true) + case _ => + done() + assert(false) + } } - // foreach: stub def testForeachSuccess(): Unit = once { done => - done() + val p = promise[Int]() + val f = future[Int] { 5 } + 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) + } } def testForeachFailure(): Unit = once { done => - done() + val p = promise[Int]() + val f = future[Int] { throw new Exception } + f foreach { x => p.success(x * 2) } + f onFailure { case _ => p.failure(new Exception) } + val g = p.future + + g.onSuccess { + case _ => + done() + assert(false) + } + g.onFailure { + case _ => + done() + assert(true) + } } def testRecoverSuccess(): Unit = once { @@ -237,6 +363,132 @@ trait FutureCombinators extends TestBase { } } + def testRecoverWithSuccess(): Unit = once { + done => + val cause = new RuntimeException + val f = future { + throw cause + } recoverWith { + case re: RuntimeException => + future { "recovered" } + } onSuccess { + case x => + done() + assert(x == "recovered") + } onFailure { case any => + done() + assert(false) + } + } + + def testRecoverWithFailure(): Unit = once { + done => + val cause = new RuntimeException + val f = future { + throw cause + } recoverWith { + case te: TimeoutException => + future { "timeout" } + } onSuccess { + case x => + done() + assert(false) + } onFailure { case any => + done() + assert(any == cause) + } + } + + def testZipSuccess(): Unit = once { + done => + 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) + } + } + + def testZipFailureLeft(): Unit = once { + done => + val cause = new Exception("exception message") + 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") + } + } + + def testZipFailureRight(): Unit = once { + done => + val cause = new Exception("exception message") + 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") + } + } + + def testFallbackTo(): Unit = once { + done => + 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) + } + } + + def testFallbackToFailure(): Unit = once { + done => + val cause = new Exception + val f = future { throw cause } + val g = future { sys.error("failed") } + val h = f fallbackTo g + + h onSuccess { + case _ => + done() + assert(false) + } + h onFailure { + case e: Exception => + done() + assert(e == cause) + } + } + testMapSuccess() testMapFailure() testFlatMapSuccess() @@ -249,7 +501,13 @@ trait FutureCombinators extends TestBase { testForeachFailure() testRecoverSuccess() testRecoverFailure() - + testRecoverWithSuccess() + testRecoverWithFailure() + testZipSuccess() + testZipFailureLeft() + testZipFailureRight() + testFallbackTo() + testFallbackToFailure() } |