diff options
Diffstat (limited to 'test')
23 files changed, 638 insertions, 18 deletions
diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-b.check b/test/files/neg/macro-override-macro-overrides-abstract-method-b.check index 8c8f039225..c49918c0b7 100644 --- a/test/files/neg/macro-override-macro-overrides-abstract-method-b.check +++ b/test/files/neg/macro-override-macro-overrides-abstract-method-b.check @@ -1,5 +1,11 @@ -Impls_Macros_1.scala:12: error: overriding method foo in trait Foo of type (x: Int)Int; - macro method foo cannot be used here - term macros cannot override abstract methods - def foo(x: Int) = macro Impls.impl - ^ -one error found +Test_2.scala:3: error: anonymous class $anon inherits conflicting members: + macro method t in trait C of type ()Unit and + method t in trait A of type ()Unit +(Note: this can be resolved by declaring an override in anonymous class $anon.) + val c2 = new C with A {} + ^ +Test_2.scala:5: error: overriding macro method t in trait C of type ()Unit; + method t cannot be used here - only term macros can override term macros + val c4 = new C with A { override def t(): Unit = () } + ^ +two errors found diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-b/Impls_Macros_1.scala b/test/files/neg/macro-override-macro-overrides-abstract-method-b/Impls_Macros_1.scala index e43264f52f..f5b2555aa5 100644 --- a/test/files/neg/macro-override-macro-overrides-abstract-method-b/Impls_Macros_1.scala +++ b/test/files/neg/macro-override-macro-overrides-abstract-method-b/Impls_Macros_1.scala @@ -1,13 +1,8 @@ -import scala.reflect.macros.{Context => Ctx} +import scala.reflect.macros.Context +import language.experimental.macros -object Impls { - def impl(c: Ctx)(x: c.Expr[Int]) = x -} +trait T { def t(): Unit } +trait A { def t(): Unit = () } -trait Foo { - def foo(x: Int): Int -} - -object Macros extends Foo { - def foo(x: Int) = macro Impls.impl -} +object Macro { def t(c: Context)(): c.Expr[Unit] = c.universe.reify(()) } +trait C extends T { self: A => override def t(): Unit = macro Macro.t } diff --git a/test/files/neg/macro-override-macro-overrides-abstract-method-b/Test_2.scala b/test/files/neg/macro-override-macro-overrides-abstract-method-b/Test_2.scala index 08fff30baf..9b4c8e35f0 100644 --- a/test/files/neg/macro-override-macro-overrides-abstract-method-b/Test_2.scala +++ b/test/files/neg/macro-override-macro-overrides-abstract-method-b/Test_2.scala @@ -1,4 +1,6 @@ object Test extends App { - val designator: Foo = Macros - designator.foo(42) + val c1 = new A with C {} + val c2 = new C with A {} + val c3 = new C with A { override def t(): Unit = macro Macro.t } + val c4 = new C with A { override def t(): Unit = () } }
\ No newline at end of file diff --git a/test/files/neg/t7636.check b/test/files/neg/t7636.check new file mode 100644 index 0000000000..f70d50bee3 --- /dev/null +++ b/test/files/neg/t7636.check @@ -0,0 +1,10 @@ +t7636.scala:3: error: illegal inheritance; + self-type Main.C does not conform to Main.ResultTable[_$3]'s selftype Main.ResultTable[_$3] + class C extends ResultTable(Left(5):Either[_,_])(5) + ^ +t7636.scala:3: error: type mismatch; + found : Either[_$2,_$3(in constructor C)] where type _$3(in constructor C), type _$2 + required: Either[_, _$3(in object Main)] where type _$3(in object Main) + class C extends ResultTable(Left(5):Either[_,_])(5) + ^ +two errors found diff --git a/test/files/neg/t7636.scala b/test/files/neg/t7636.scala new file mode 100644 index 0000000000..a7b1b90151 --- /dev/null +++ b/test/files/neg/t7636.scala @@ -0,0 +1,7 @@ +object Main extends App{ + class ResultTable[E]( query : Either[_,E] )( columns : Int ) + class C extends ResultTable(Left(5):Either[_,_])(5) +} +// Inference of the existential type for the parent type argument +// E still fails. That looks tricky to fix, see the comments in SI-7636. +// But we at least prevent a cascading NPE.
\ No newline at end of file diff --git a/test/files/pos/t7649.flags b/test/files/pos/t7649.flags new file mode 100644 index 0000000000..fcf951d907 --- /dev/null +++ b/test/files/pos/t7649.flags @@ -0,0 +1 @@ +-Yrangepos
\ No newline at end of file diff --git a/test/files/pos/t7649.scala b/test/files/pos/t7649.scala new file mode 100644 index 0000000000..a1b02f63f1 --- /dev/null +++ b/test/files/pos/t7649.scala @@ -0,0 +1,20 @@ +object Test { + val c: reflect.macros.Context = ??? + import c.universe._ + reify { + // The lookup of the implicit WeakTypeTag[Any] + // was triggering an unpositioned tree. + c.Expr[Any](Literal(Constant(0))).splice + } + + import scala.reflect.ClassTag + def ct[A: ClassTag]: Expr[A] = ??? + def tt[A: TypeTag]: Expr[A] = ??? + def wtt[A: WeakTypeTag]: Expr[A] = ??? + + reify { + ct[String].splice + tt[String].splice + wtt[String].splice + } +} diff --git a/test/files/run/t7265.scala b/test/files/run/t7265.scala new file mode 100644 index 0000000000..c556930303 --- /dev/null +++ b/test/files/run/t7265.scala @@ -0,0 +1,27 @@ + +import scala.util.Properties._ + +object Test extends App { + + setProp("java.specification.version", "1.7") + + assert( isJavaAtLeast("1.5")) + assert( isJavaAtLeast("1.6")) + assert( isJavaAtLeast("1.7")) + assert(!isJavaAtLeast("1.8")) + assert(!isJavaAtLeast("1.71")) + + failing(isJavaAtLeast("1.a")) + failing(isJavaAtLeast("1")) + failing(isJavaAtLeast("")) + failing(isJavaAtLeast(".")) + failing(isJavaAtLeast(".5")) + failing(isJavaAtLeast("1.7.1")) + + def failing(u: =>Unit) = try { + u + assert(false, "Expected Exception") + } catch { + case _: NumberFormatException => + } +} diff --git a/test/files/run/t7336.scala b/test/files/run/t7336.scala new file mode 100644 index 0000000000..ace83f2c1f --- /dev/null +++ b/test/files/run/t7336.scala @@ -0,0 +1,31 @@ +import scala.concurrent.Await +import scala.concurrent.ExecutionContext.Implicits.global +import scala.concurrent.Future +import scala.concurrent.duration.Duration + +/** This test uses recursive calls to Future.flatMap to create arrays whose + * combined size is slightly greater than the JVM heap size. A previous + * implementation of Future.flatMap would retain references to each array, + * resulting in a speedy OutOfMemoryError. Now, each array should be freed soon + * after it is created and the test should complete without problems. + */ +object Test { + def main(args: Array[String]) { + def loop(i: Int, arraySize: Int): Future[Unit] = { + val array = new Array[Byte](arraySize) + Future.successful(i).flatMap { i => + if (i == 0) { + Future.successful(()) + } else { + array.size // Force closure to refer to array + loop(i - 1, arraySize) + } + + } + } + + val arraySize = 1000000 + val tooManyArrays = (Runtime.getRuntime().totalMemory() / arraySize).toInt + 1 + Await.ready(loop(tooManyArrays, arraySize), Duration.Inf) + } +}
\ No newline at end of file diff --git a/test/files/run/t7455.check b/test/files/run/t7455.check new file mode 100644 index 0000000000..0eb9342888 --- /dev/null +++ b/test/files/run/t7455.check @@ -0,0 +1,4 @@ +private[package <empty>] def <init>(x$1: String): Outer[E] +private[package <empty>] def <init>(): Outer$PrivateInner +private[package <empty>] def <init>(): Outer$PrivateStaticInner +private[package <empty>] def <init>(x$2: String): Outer$PublicInner diff --git a/test/files/run/t7455/Outer.java b/test/files/run/t7455/Outer.java new file mode 100644 index 0000000000..10c97a9150 --- /dev/null +++ b/test/files/run/t7455/Outer.java @@ -0,0 +1,31 @@ +public class Outer<E> { + public void elements() { + new C<E>() { + }; + } + + private Outer(String a) {} + + static class SubSelf extends Outer<String> { + public SubSelf() { super(""); } + } + + private class PrivateInner { + } + class SubPrivateInner extends PrivateInner { + } + + private class PublicInner { + private PublicInner(String a) {} + } + class SubPublicInner extends PublicInner { + public SubPublicInner() { super(""); } + } + + private static class PrivateStaticInner { + } + public static class SubPrivateStaticInner extends PrivateStaticInner { + } +} + +class C<E> {} diff --git a/test/files/run/t7455/Test.scala b/test/files/run/t7455/Test.scala new file mode 100644 index 0000000000..b23a724c78 --- /dev/null +++ b/test/files/run/t7455/Test.scala @@ -0,0 +1,30 @@ +import scala.tools.partest._ + +// javac adds dummy parameters of type Outer$1 to synthetic access constructors +// This test shows that we strip them from the signatures. If we don't, we trigger +// parsing of Outer$1 which can fail if it references type parameters of the Outer. +// +// OLD OUTPUT: +// private[package <empty>] def <init>(x$2: Outer$1): Outer$PrivateInner +// error: error while loading Outer$1, class file 't7455-run.obj/Outer$1.class' is broken +// (class java.util.NoSuchElementException/key not found: E) +// ... +object Test extends DirectTest { + override def code = "" + + def show { + val classpath = List(sys.props("partest.lib"), testOutput.path) mkString sys.props("path.separator") + val compiler = newCompiler("-cp", classpath, "-d", testOutput.path) + import compiler._, definitions._ + new compiler.Run + + for { + name <- Seq("Outer", "Outer$PrivateInner", "Outer$PrivateStaticInner", "Outer$PublicInner") + clazz = compiler.rootMirror.staticClass(name) + constr <- clazz.info.member(nme.CONSTRUCTOR).alternatives + } { + println(constr.defString) + fullyInitializeSymbol(constr) + } + } +} diff --git a/test/files/run/t7617a.check b/test/files/run/t7617a.check new file mode 100644 index 0000000000..94954abda4 --- /dev/null +++ b/test/files/run/t7617a.check @@ -0,0 +1,2 @@ +hello +world diff --git a/test/files/run/t7617a/Macros_1.scala b/test/files/run/t7617a/Macros_1.scala new file mode 100644 index 0000000000..f9772c83c0 --- /dev/null +++ b/test/files/run/t7617a/Macros_1.scala @@ -0,0 +1,22 @@ +import scala.reflect.macros.Context +import language.experimental.macros + +object Macros { + def getValueImpl[T](c: Context): c.Expr[T] = { + import c.universe._ + c.Expr[T](Apply(Select(c.prefix.tree, newTermName("getVal")), Nil)) + } + def setValueImpl[T](c: Context)(value: c.Expr[T]): c.Expr[Unit] = { + import c.universe._ + c.Expr[Unit](Apply(Select(c.prefix.tree, newTermName("setVal")), List(value.tree))) + } +} + +object Module { + private var _val: String = "hello" + def setVal(value: String): Unit = this._val = value + def getVal(): String = this._val + + def value: String = macro Macros.getValueImpl[String] + def value_=(value: String): Unit = macro Macros.setValueImpl[String] +} diff --git a/test/files/run/t7617a/Test_2.scala b/test/files/run/t7617a/Test_2.scala new file mode 100644 index 0000000000..da6e34e09d --- /dev/null +++ b/test/files/run/t7617a/Test_2.scala @@ -0,0 +1,5 @@ +object Test extends App { + println(Module.value) + Module.value = "world" + println(Module.value) +}
\ No newline at end of file diff --git a/test/files/run/t7617b.check b/test/files/run/t7617b.check new file mode 100644 index 0000000000..81ec7e8b74 --- /dev/null +++ b/test/files/run/t7617b.check @@ -0,0 +1 @@ +foo = 2 diff --git a/test/files/run/t7617b/Macros_1.scala b/test/files/run/t7617b/Macros_1.scala new file mode 100644 index 0000000000..bc919935c9 --- /dev/null +++ b/test/files/run/t7617b/Macros_1.scala @@ -0,0 +1,8 @@ +import scala.reflect.macros.Context + +object Macros { + def impl(c: Context)(name: c.Expr[String])(value: c.Expr[Any]) = { + import c.universe._ + reify(println(s"${name.splice} = ${value.splice}")) + } +}
\ No newline at end of file diff --git a/test/files/run/t7617b/Test_2.scala b/test/files/run/t7617b/Test_2.scala new file mode 100644 index 0000000000..e27f650e80 --- /dev/null +++ b/test/files/run/t7617b/Test_2.scala @@ -0,0 +1,11 @@ +import scala.language.dynamics +import language.experimental.macros + +class C extends Dynamic { + def updateDynamic(name: String)(value: Any) = macro Macros.impl +} + +object Test extends App { + val c = new C + c.foo = 2 +}
\ No newline at end of file diff --git a/test/files/run/t7657.check b/test/files/run/t7657.check new file mode 100644 index 0000000000..c25d8d1c1b --- /dev/null +++ b/test/files/run/t7657.check @@ -0,0 +1,3 @@ +() +() +() diff --git a/test/files/run/t7657/Macros_1.scala b/test/files/run/t7657/Macros_1.scala new file mode 100644 index 0000000000..b1e31aa2dd --- /dev/null +++ b/test/files/run/t7657/Macros_1.scala @@ -0,0 +1,8 @@ +import scala.reflect.macros.Context +import language.experimental.macros + +trait T { def t(): Unit } +abstract class A extends T { override def t(): Unit = () } + +object Macro { def t(c: Context)(): c.Expr[Unit] = c.universe.reify(()) } +class C extends A { override def t(): Unit = macro Macro.t } diff --git a/test/files/run/t7657/Test_2.scala b/test/files/run/t7657/Test_2.scala new file mode 100644 index 0000000000..5cc46b6aa1 --- /dev/null +++ b/test/files/run/t7657/Test_2.scala @@ -0,0 +1,6 @@ +object Test extends App { + val c = new C() + println(c.t()) + println((c: T).t()) + println((c: A).t()) +}
\ No newline at end of file diff --git a/test/junit/scala/concurrent/impl/DefaultPromiseTest.scala b/test/junit/scala/concurrent/impl/DefaultPromiseTest.scala new file mode 100644 index 0000000000..f3a75e24d0 --- /dev/null +++ b/test/junit/scala/concurrent/impl/DefaultPromiseTest.scala @@ -0,0 +1,344 @@ +package scala.concurrent.impl + +import java.util.concurrent.ConcurrentLinkedQueue +import java.util.concurrent.CountDownLatch +import org.junit.Assert._ +import org.junit.{ After, Before, Test } +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import scala.annotation.tailrec +import scala.concurrent.ExecutionContext +import scala.concurrent.impl.Promise.DefaultPromise +import scala.util.{ Failure, Success, Try } +import scala.util.control.NonFatal + +/** Tests for the private class DefaultPromise */ +@RunWith(classOf[JUnit4]) +class DefaultPromiseTest { + + // Many tests in this class use a helper class, Tester, to track the state of + // promises and to ensure they behave correctly, particularly the complex behaviour + // of linking. + + type Result = Int + type PromiseId = Int + type HandlerId = Int + type ChainId = Int + + /** The state of a set of set of linked promises. */ + case class Chain( + promises: Set[PromiseId], + state: Either[Set[HandlerId],Try[Result]] + ) + + /** A helper class that provides methods for creating, linking, completing and + * adding handlers to promises. With each operation it verifies that handlers + * are called, any expected exceptions are thrown, and that all promises have + * the expected value. + * + * The links between promises are not tracked precisely. Instead, linked promises + * are placed in the same Chain object. Each link in the same chain will share + * the same value. + */ + class Tester { + var promises = Map.empty[PromiseId, DefaultPromise[Result]] + var chains = Map.empty[ChainId, Chain] + + private var counter = 0 + private def freshId(): Int = { + val id = counter + counter += 1 + id + } + + /** Handlers report their activity on this queue */ + private val handlerQueue = new ConcurrentLinkedQueue[(Try[Result], HandlerId)]() + + /** Get the chain for a given promise */ + private def promiseChain(p: PromiseId): Option[(ChainId, Chain)] = { + val found: Iterable[(ChainId, Chain)] = for ((cid, c) <- chains; p0 <- c.promises; if (p0 == p)) yield ((cid, c)) + found.toList match { + case Nil => None + case x::Nil => Some(x) + case _ => throw new IllegalStateException(s"Promise $p found in more than one chain") + } + } + + /** Passed to `checkEffect` to indicate the expected effect of an operation */ + sealed trait Effect + case object NoEffect extends Effect + case class HandlersFired(result: Try[Result], handlers: Set[HandlerId]) extends Effect + case object MaybeIllegalThrown extends Effect + case object IllegalThrown extends Effect + + /** Runs an operation while verifying that the operation has the expected effect */ + private def checkEffect(expected: Effect)(f: => Any) { + assert(handlerQueue.isEmpty()) // Should have been cleared by last usage + val result = Try(f) + + var fireCounts = Map.empty[(Try[Result], HandlerId), Int] + while (!handlerQueue.isEmpty()) { + val key = handlerQueue.poll() + val newCount = fireCounts.getOrElse(key, 0) + 1 + fireCounts = fireCounts.updated(key, newCount) + } + + def assertIllegalResult = result match { + case Failure(e: IllegalStateException) => () + case _ => fail(s"Expected IllegalStateException: $result") + } + + expected match { + case NoEffect => + assertTrue(s"Shouldn't throw exception: $result", result.isSuccess) + assertEquals(Map.empty[(Try[Result], HandlerId), Int], fireCounts) + case HandlersFired(firingResult, handlers) => + assert(result.isSuccess) + val expectedCounts = handlers.foldLeft(Map.empty[(Try[Result], HandlerId), Int]) { + case (map, hid) => map.updated((firingResult, hid), 1) + } + assertEquals(expectedCounts, fireCounts) + case MaybeIllegalThrown => + if (result.isFailure) assertIllegalResult + assertEquals(Map.empty, fireCounts) + case IllegalThrown => + assertIllegalResult + assertEquals(Map.empty, fireCounts) + } + } + + /** Check each promise has the expected value. */ + private def assertPromiseValues() { + for ((cid, chain) <- chains; p <- chain.promises) { + chain.state match { + case Right(result) => assertEquals(Some(result), promises(p).value) + case Left(_) => () + } + } + } + + /** Create a promise, returning a handle. */ + def newPromise(): PromiseId = { + val pid = freshId() + val cid = freshId() + promises = promises.updated(pid, new DefaultPromise[Result]()) + chains = chains.updated(cid, Chain(Set(pid), Left(Set.empty))) + assertPromiseValues() + pid + } + + /** Complete a promise */ + def complete(p: PromiseId) { + val r = Success(freshId()) + val (cid, chain) = promiseChain(p).get + val (completionEffect, newState) = chain.state match { + case Left(handlers) => (HandlersFired(r, handlers), Right(r)) + case Right(completion) => (IllegalThrown, chain.state) + } + checkEffect(completionEffect) { promises(p).complete(r) } + chains = chains.updated(cid, chain.copy(state = newState)) + assertPromiseValues() + } + + /** Attempt to link two promises together */ + def link(a: PromiseId, b: PromiseId): (ChainId, ChainId) = { + val promiseA = promises(a) + val promiseB = promises(b) + val (cidA, chainA) = promiseChain(a).get + val (cidB, chainB) = promiseChain(b).get + + // Examine the state of each promise's chain to work out + // the effect of linking the promises, and to work out + // if the two chains should be merged. + + sealed trait MergeOp + case object NoMerge extends MergeOp + case class Merge(state: Either[Set[HandlerId],Try[Result]]) extends MergeOp + + val (linkEffect, mergeOp) = (chainA.state, chainB.state) match { + case (Left(handlers1), Left(handlers2)) => + (NoEffect, Merge(Left(handlers1 ++ handlers2))) + case (Left(handlers), Right(result)) => + (HandlersFired(result, handlers), Merge(Right(result))) + case (Right(result), Left(handlers)) => + (HandlersFired(result, handlers), Merge(Right(result))) + case (Right(_), Right(_)) if (cidA == cidB) => + (MaybeIllegalThrown, NoMerge) // Won't be thrown if happen to link a promise to itself + case (Right(_), Right(_)) => + (IllegalThrown, NoMerge) + } + + // Perform the linking and merge the chains, if appropriate + + checkEffect(linkEffect) { promiseA.linkRootOf(promiseB) } + + val (newCidA, newCidB) = mergeOp match { + case NoMerge => (cidA, cidB) + case Merge(newState) => { + chains = chains - cidA + chains = chains - cidB + val newCid = freshId() + chains = chains.updated(newCid, Chain(chainA.promises ++ chainB.promises, newState)) + (newCid, newCid) + } + } + assertPromiseValues() + (newCidA, newCidB) + } + + /** Attach an onComplete handler. When called, the handler will + * place an entry into `handlerQueue` with the handler's identity. + * This allows verification of handler calling semantics. + */ + def attachHandler(p: PromiseId): HandlerId = { + val hid = freshId() + val promise = promises(p) + val (cid, chain) = promiseChain(p).get + val (attachEffect, newState) = chain.state match { + case Left(handlers) => + (NoEffect, Left(handlers + hid)) + case Right(result) => + (HandlersFired(result, Set(hid)), Right(result)) + } + implicit val ec = new ExecutionContext { + def execute(r: Runnable) { r.run() } + def reportFailure(t: Throwable) { t.printStackTrace() } + } + + checkEffect(attachEffect) { promise.onComplete(result => handlerQueue.add((result, hid))) } + chains = chains.updated(cid, chain.copy(state = newState)) + assertPromiseValues() + hid + } + } + + // Some methods and objects that build a list of promise + // actions to test and then execute them + + type PromiseKey = Int + + sealed trait Action + case class Complete(p: PromiseKey) extends Action + case class Link(a: PromiseKey, b: PromiseKey) extends Action + case class AttachHandler(p: PromiseKey) extends Action + + /** Tests a sequence of actions on a Tester. Creates promises as needed. */ + private def testActions(actions: Seq[Action]) { + val t = new Tester() + var pMap = Map.empty[PromiseKey, PromiseId] + def byKey(key: PromiseKey): PromiseId = { + if (!pMap.contains(key)) { + pMap = pMap.updated(key, t.newPromise()) + } + pMap(key) + } + + actions foreach { action => + action match { + case Complete(p) => t.complete(byKey(p)) + case Link(a, b) => t.link(byKey(a), byKey(b)) + case AttachHandler(p) => t.attachHandler(byKey(p)) + } + } + } + + /** Tests all permutations of actions for `count` promises */ + private def testPermutations(count: Int) { + val ps = (0 until count).toList + val pPairs = for (a <- ps; b <- ps) yield (a, b) + + var allActions = ps.map(Complete(_)) ++ pPairs.map { case (a, b) => Link(a, b) } ++ ps.map(AttachHandler(_)) + for ((permutation, i) <- allActions.permutations.zipWithIndex) { + testActions(permutation) + } + } + + /** Test all permutations of actions with a single promise */ + @Test + def testPermutations1 { + testPermutations(1) + } + + /** Test all permutations of actions with two promises - about 40 thousand */ + @Test + def testPermutations2 { + testPermutations(2) + } + + /** Link promises in different orders, using the same link structure as is + * used in Future.flatMap */ + @Test + def simulateFlatMapLinking { + val random = new scala.util.Random(1) + for (_ <- 0 until 10) { + val t = new Tester() + val flatMapCount = 100 + + sealed trait FlatMapEvent + case class Link(a: PromiseId, b: PromiseId) extends FlatMapEvent + case class Complete(p: PromiseId) extends FlatMapEvent + + @tailrec + def flatMapEvents(count: Int, p1: PromiseId, acc: List[FlatMapEvent]): List[FlatMapEvent] = { + if (count == 0) { + Complete(p1)::acc + } else { + val p2 = t.newPromise() + flatMapEvents(count - 1, p2, Link(p2, p1)::acc) + } + } + + val events = flatMapEvents(flatMapCount, t.newPromise(), Nil) + assertEquals(flatMapCount + 1, t.chains.size) // All promises are unlinked + val shuffled = random.shuffle(events) + shuffled foreach { + case Link(a, b) => t.link(a, b) + case Complete(p) => t.complete(p) + } + // All promises should be linked together, no matter the order of their linking + assertEquals(1, t.chains.size) + } + } + + /** Link promises together on more than one thread, using the same link + * structure as is used in Future.flatMap */ + @Test + def testFlatMapLinking { + for (_ <- 0 until 100) { + val flatMapCount = 100 + val startLatch = new CountDownLatch(1) + val doneLatch = new CountDownLatch(flatMapCount + 1) + def execute(f: => Unit) { + val ec = ExecutionContext.global + ec.execute(new Runnable { + def run() { + try { + startLatch.await() + f + doneLatch.countDown() + } catch { + case NonFatal(e) => ec.reportFailure(e) + } + } + }) + } + @tailrec + def flatMapTimes(count: Int, p1: DefaultPromise[Int]) { + if (count == 0) { + execute { p1.success(1) } + } else { + val p2 = new DefaultPromise[Int]() + execute { p2.linkRootOf(p1) } + flatMapTimes(count - 1, p2) + } + } + + val p = new DefaultPromise[Int]() + flatMapTimes(flatMapCount, p) + startLatch.countDown() + doneLatch.await() + assertEquals(Some(Success(1)), p.value) + } + } + +} diff --git a/test/pending/junit/scala/util/t7265.scala b/test/pending/junit/scala/util/t7265.scala new file mode 100644 index 0000000000..3b8fa80dbe --- /dev/null +++ b/test/pending/junit/scala/util/t7265.scala @@ -0,0 +1,46 @@ + +package scala.util +package test + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.util.PropertiesTrait + +/** The java version property uses the spec version + * and must work for all "major.minor" and fail otherwise. + */ +@RunWith(classOf[JUnit4]) +class SpecVersionTest { + val sut = new PropertiesTrait { + override def javaSpecVersion = "1.7" + + override protected def pickJarBasedOn: Class[_] = ??? + override protected def propCategory: String = "test" + + // override because of vals like releaseVersion + override lazy val scalaProps = new java.util.Properties + } + + @Test + def comparesCorrectly(): Unit = { + assert(sut isJavaAtLeast "1.5") + assert(sut isJavaAtLeast "1.6") + assert(sut isJavaAtLeast "1.7") + assert(!(sut isJavaAtLeast "1.8")) + } + @Test(expected = classOf[NumberFormatException]) + def badVersion(): Unit = { + sut isJavaAtLeast "1.a" + } + @Test(expected = classOf[NumberFormatException]) + def missingVersion(): Unit = { + sut isJavaAtLeast "1" + } + @Test(expected = classOf[NumberFormatException]) + def notASpec(): Unit = { + sut isJavaAtLeast "1.7.1" + } +} |