diff options
Diffstat (limited to 'test')
105 files changed, 2928 insertions, 164 deletions
diff --git a/test/benchmarks/src/scala/collection/parallel/benchmarks/Bench.scala b/test/benchmarks/src/scala/collection/parallel/benchmarks/Bench.scala index e8dfe0ac50..c20bbaeef1 100644 --- a/test/benchmarks/src/scala/collection/parallel/benchmarks/Bench.scala +++ b/test/benchmarks/src/scala/collection/parallel/benchmarks/Bench.scala @@ -78,7 +78,7 @@ trait Bench extends Benchmark { } /** - * Prints results of the benchmark. May be overidden in benchmarks. + * Prints results of the benchmark. May be overridden in benchmarks. */ def printResults {} diff --git a/test/files/jvm/innerClassAttribute/Test.scala b/test/files/jvm/innerClassAttribute/Test.scala index 1c1a0522e4..3820048cb4 100644 --- a/test/files/jvm/innerClassAttribute/Test.scala +++ b/test/files/jvm/innerClassAttribute/Test.scala @@ -84,17 +84,15 @@ object Test extends BytecodeTest { } def testA3() = { - def t(c: String) = { - val List(b1, b2) = innerClassNodes(c) - // the outer class for classes nested inside top-level modules is not the module class, but the mirror class. - // this is a hack for java interop, handled in the backend. see BTypes.scala, comment on "Java Compatibility". - assertMember(b1, "A3", "B1", flags = publicStatic) - assertMember(b2, "A3", "B2$", flags = publicStatic) - } - t("A3$") - // the mirror class has the same inner class attributes as the module - // class (added when the mirror is created in the backend) - t("A3") + // the inner class entries for top-level object members are in the companion class, so nothing in the module class + val List() = innerClassNodes("A3$") + + // inner class entries in the companion class (a backend-generated mirror class in this case) + val List(b1, b2) = innerClassNodes("A3") + // the outer class for classes nested inside top-level modules is not the module class, but the mirror class. + // this is a hack for java interop, handled in the backend. see BTypes.scala, comment on "Java Compatibility". + assertMember(b1, "A3", "B1", flags = publicStatic) + assertMember(b2, "A3", "B2$", flags = publicStatic) } def testA4() = { @@ -164,7 +162,10 @@ object Test extends BytecodeTest { } def testA15() = { - val List(b) = innerClassNodes("A15") + // no member classes, only anonymous / local. these are nested in the module class, not the companion. + val List() = innerClassNodes("A15") + + val List(b) = innerClassNodes("A15$") assertLocal(b, "A15$B$3", "B$3") val List(_, c) = innerClassNodes("A15$B$3") @@ -283,9 +284,7 @@ object Test extends BytecodeTest { assertMember(i3c, "A21", "I3$", flags = publicStatic) assertLocal(j1, "A21$J1$1", "J1$1") - val List(i2m, i3m, j3, j4, j5) = innerClassNodes("A21$") - assertMember(i2m, "A21", "I2", flags = publicStatic) - assertMember(i3m, "A21", "I3$", flags = publicStatic) + val List(j3, j4, j5) = innerClassNodes("A21$") assertLocal(j3, "A21$J3$1", "J3$1") assertLocal(j4, "A21$J4$1", "J4$1") assertLocal(j5, "A21$J5$1", "J5$1") // non-static! diff --git a/test/files/jvm/serialization-new.check b/test/files/jvm/serialization-new.check index 1555135926..cb26446f40 100644 --- a/test/files/jvm/serialization-new.check +++ b/test/files/jvm/serialization-new.check @@ -1,4 +1,4 @@ -warning: there were two deprecation warnings; re-run with -deprecation for details +warning: there were three deprecation warnings; re-run with -deprecation for details a1 = Array[1,2,3] _a1 = Array[1,2,3] arrayEquals(a1, _a1): true diff --git a/test/files/jvm/serialization.check b/test/files/jvm/serialization.check index 1555135926..cb26446f40 100644 --- a/test/files/jvm/serialization.check +++ b/test/files/jvm/serialization.check @@ -1,4 +1,4 @@ -warning: there were two deprecation warnings; re-run with -deprecation for details +warning: there were three deprecation warnings; re-run with -deprecation for details a1 = Array[1,2,3] _a1 = Array[1,2,3] arrayEquals(a1, _a1): true diff --git a/test/files/jvm/t8582.check b/test/files/jvm/t8582.check index 564f482ff8..e388366270 100644 --- a/test/files/jvm/t8582.check +++ b/test/files/jvm/t8582.check @@ -14,10 +14,10 @@ Reflection can find direct nested classes (A2-B2-C2) A2$B2: List(class A2$B2$C2) A2$B2$C2: List() -Mirror classes have the same InnerClass attributes as the corresponding module class: - className[p1/p2/Singleton$Singleton$] outerClassName[p1/p2/Singleton] innerName[Singleton$] access[9] -Module class +The InnerClass attribute of a mirror class contains the members of the module class: className[p1/p2/Singleton$Singleton$] outerClassName[p1/p2/Singleton] innerName[Singleton$] access[9] +The module members are not in the InnerClass table of the module class (unless referenced): + An outer class has a InnerClass attribute for direct nested classes className[A1$B1] outerClassName[A1] innerName[B1] access[1] diff --git a/test/files/jvm/t8582.scala b/test/files/jvm/t8582.scala index 8a57ef7952..e9a01f9016 100644 --- a/test/files/jvm/t8582.scala +++ b/test/files/jvm/t8582.scala @@ -55,9 +55,9 @@ object Test extends BytecodeTest { println(nested(classOf[A2#B2])) println(nested(classOf[A2#B2#C2])) - nprintln("Mirror classes have the same InnerClass attributes as the corresponding module class:") + nprintln("The InnerClass attribute of a mirror class contains the members of the module class:") printInner("p1.p2.Singleton") // mirror class - println("Module class") + println("The module members are not in the InnerClass table of the module class (unless referenced):") printInner("p1.p2.Singleton$") nprintln("An outer class has a InnerClass attribute for direct nested classes") diff --git a/test/files/jvm/t9044.scala b/test/files/jvm/t9044.scala new file mode 100644 index 0000000000..b1073325e8 --- /dev/null +++ b/test/files/jvm/t9044.scala @@ -0,0 +1,6 @@ +trait A +trait B +object Test extends A with B with App { + val is = Test.getClass.getInterfaces.mkString(", ") + assert(is == "interface A, interface B, interface scala.App", is) +} diff --git a/test/files/neg/literals.check b/test/files/neg/literals.check new file mode 100644 index 0000000000..148a9346c5 --- /dev/null +++ b/test/files/neg/literals.check @@ -0,0 +1,40 @@ +literals.scala:6: error: missing integer number + def missingHex: Int = { 0x } // line 4: was: not reported, taken as zero + ^ +literals.scala:8: error: Decimal integer literals may not have a leading zero. (Octal syntax is obsolete.) + def leadingZeros: Int = { 01 } // line 6: no leading zero + ^ +literals.scala:10: error: Decimal integer literals may not have a leading zero. (Octal syntax is obsolete.) + def tooManyZeros: Int = { 00 } // line 8: no leading zero + ^ +literals.scala:12: error: Decimal integer literals may not have a leading zero. (Octal syntax is obsolete.) + def zeroOfNine: Int = { 09 } // line 10: no leading zero + ^ +literals.scala:16: error: Decimal integer literals may not have a leading zero. (Octal syntax is obsolete.) + def zeroOfNineDot: Int = { 09. } // line 14: malformed integer, ident expected + ^ +literals.scala:23: error: missing integer number + def missingHex: Int = 0x // line 22: was: not reported, taken as zero + ^ +literals.scala:27: error: Decimal integer literals may not have a leading zero. (Octal syntax is obsolete.) + def tooManyZeros: Int = 00 // line 26: no leading zero + ^ +literals.scala:14: error: identifier expected but '}' found. + def orphanDot: Int = { 9. } // line 12: ident expected + ^ +literals.scala:16: error: identifier expected but '}' found. + def zeroOfNineDot: Int = { 09. } // line 14: malformed integer, ident expected + ^ +literals.scala:18: error: ';' expected but double literal found. + def noHexFloat: Double = { 0x1.2 } // line 16: ';' expected but double literal found. + ^ +literals.scala:25: error: ';' expected but 'def' found. + def leadingZeros: Int = 01 // line 24: no leading zero + ^ +literals.scala:29: error: ';' expected but 'def' found. + def zeroOfNine: Int = 09 // line 28: no leading zero + ^ +literals.scala:33: error: identifier expected but 'def' found. + def zeroOfNineDot: Int = 09. // line 32: malformed integer, ident expected + ^ +13 errors found diff --git a/test/files/neg/literals.scala b/test/files/neg/literals.scala new file mode 100644 index 0000000000..3df7f0b408 --- /dev/null +++ b/test/files/neg/literals.scala @@ -0,0 +1,36 @@ + +/* This took me literally all day. +*/ +trait RejectedLiterals { + + def missingHex: Int = { 0x } // line 4: was: not reported, taken as zero + + def leadingZeros: Int = { 01 } // line 6: no leading zero + + def tooManyZeros: Int = { 00 } // line 8: no leading zero + + def zeroOfNine: Int = { 09 } // line 10: no leading zero + + def orphanDot: Int = { 9. } // line 12: ident expected + + def zeroOfNineDot: Int = { 09. } // line 14: malformed integer, ident expected + + def noHexFloat: Double = { 0x1.2 } // line 16: ';' expected but double literal found. +} + +trait Braceless { + + def missingHex: Int = 0x // line 22: was: not reported, taken as zero + + def leadingZeros: Int = 01 // line 24: no leading zero + + def tooManyZeros: Int = 00 // line 26: no leading zero + + def zeroOfNine: Int = 09 // line 28: no leading zero + + def orphanDot: Int = 9. // line 30: ident expected + + def zeroOfNineDot: Int = 09. // line 32: malformed integer, ident expected + + def noHexFloat: Double = 0x1.2 // line 34: ';' expected but double literal found. +} diff --git a/test/files/neg/literate_existentials.scala b/test/files/neg/literate_existentials.scala index 8580347bf9..5537c50b3a 100644 --- a/test/files/neg/literate_existentials.scala +++ b/test/files/neg/literate_existentials.scala @@ -187,7 +187,7 @@ object LiterateExistentials { // implicitly[Int <:< (M forSome { type M >: Nothing <: String })] // fails -// The preceeding line causes the compiler to generate an error message. +// The preceding line causes the compiler to generate an error message. diff --git a/test/files/neg/structural.scala b/test/files/neg/structural.scala index d783399317..00459676a9 100644 --- a/test/files/neg/structural.scala +++ b/test/files/neg/structural.scala @@ -11,13 +11,13 @@ object Test extends App { def f2[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: B): Object; val x: B }) = x.m[Tata](x.x) //fail def f3[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: C): Object; val x: C }) = x.m[Tata](x.x) //fail def f4[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: D): Object; val x: D }) = x.m[Tata](x.x) //fail - def f5[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: E): Object; val x: Tata }) = x.m[Tata](x.x) //suceed + def f5[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: E): Object; val x: Tata }) = x.m[Tata](x.x) //succeeds - def f6[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): A }) = x.m[Tata](null) //suceed - def f7[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): B }) = x.m[Tata](null) //suceed - def f8[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): C }) = x.m[Tata](null) //suceed + def f6[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): A }) = x.m[Tata](null) //succeeds + def f7[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): B }) = x.m[Tata](null) //succeeds + def f8[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): C }) = x.m[Tata](null) //succeeds def f9[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): D }) = x.m[Tata](null) //fail - def f0[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): E }) = x.m[Tata](null) //suceed + def f0[C <: Object](x: Object{ type D <: Object; def m[E >: Null <: Object](x: Object): E }) = x.m[Tata](null) //succeeds } diff --git a/test/files/neg/t6582_exhaust_big.check b/test/files/neg/t6582_exhaust_big.check new file mode 100644 index 0000000000..9e2be038b5 --- /dev/null +++ b/test/files/neg/t6582_exhaust_big.check @@ -0,0 +1,7 @@ +t6582_exhaust_big.scala:27: warning: match may not be exhaustive. +It would fail on the following input: Z11() + def foo(z: Z) = z match { + ^ +error: No warnings can be incurred under -Xfatal-warnings. +one warning found +one error found diff --git a/test/files/neg/t6582_exhaust_big.flags b/test/files/neg/t6582_exhaust_big.flags new file mode 100644 index 0000000000..b5a8748652 --- /dev/null +++ b/test/files/neg/t6582_exhaust_big.flags @@ -0,0 +1 @@ +-Xfatal-warnings -unchecked diff --git a/test/files/neg/t6582_exhaust_big.scala b/test/files/neg/t6582_exhaust_big.scala new file mode 100644 index 0000000000..dd639eb56e --- /dev/null +++ b/test/files/neg/t6582_exhaust_big.scala @@ -0,0 +1,32 @@ +sealed abstract class Z +object Z { + object Z0 extends Z + case class Z1() extends Z + object Z2 extends Z + case class Z3() extends Z + object Z4 extends Z + case class Z5() extends Z + object Z6 extends Z + case class Z7() extends Z + object Z8 extends Z + case class Z9() extends Z + object Z10 extends Z + case class Z11() extends Z + object Z12 extends Z + case class Z13() extends Z + object Z14 extends Z + case class Z15() extends Z + object Z16 extends Z + case class Z17() extends Z + object Z18 extends Z + case class Z19() extends Z +} + +object Test { + import Z._ + def foo(z: Z) = z match { + case Z0 | Z1() | Z2 | Z3() | Z4 | Z5() | Z6 | Z7() | Z8 | Z9() | + Z10 | Z12 | Z13() | Z14 | Z15() | Z16 | Z17() | Z18 | Z19() + => + } +} diff --git a/test/files/neg/t7623.check b/test/files/neg/t7623.check new file mode 100644 index 0000000000..db368dd369 --- /dev/null +++ b/test/files/neg/t7623.check @@ -0,0 +1,21 @@ +t7623.scala:19: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). + def f = "" match { case X(s) => } + ^ +t7623.scala:21: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). + def g = "" match { case X(s, t) => } + ^ +t7623.scala:23: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). + def h = "" match { case X(s, t, u @ _*) => } + ^ +t7623.scala:9: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). + def f = C("") match { case C(s) => } + ^ +t7623.scala:11: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). + def g = C("") match { case C(s, t) => } + ^ +t7623.scala:13: warning: A repeated case parameter or extracted sequence should be matched only by a sequence wildcard (_*). + def h = C("") match { case C(s, t, u @ _*) => } + ^ +error: No warnings can be incurred under -Xfatal-warnings. +6 warnings found +one error found diff --git a/test/files/neg/t7623.flags b/test/files/neg/t7623.flags new file mode 100644 index 0000000000..74c9e38323 --- /dev/null +++ b/test/files/neg/t7623.flags @@ -0,0 +1 @@ +-Xlint:stars-align -Xfatal-warnings diff --git a/test/files/neg/t7623.scala b/test/files/neg/t7623.scala new file mode 100644 index 0000000000..5c40f37bc1 --- /dev/null +++ b/test/files/neg/t7623.scala @@ -0,0 +1,38 @@ + + +case class C(s: String, xs: Int*) + +object X { def unapplySeq(a: Any): Option[(String, Seq[Int])] = Some("", List(1,2,3)) } + +// for case classes with varargs, avoid misaligned patterns +trait Ctest { + def f = C("") match { case C(s) => } + + def g = C("") match { case C(s, t) => } + + def h = C("") match { case C(s, t, u @ _*) => } + + def ok = C("") match { case C(s, u @ _*) => } +} +// for extractors that unapplySeq: Option[(Something, Seq[_])], avoid misaligned patterns +trait Xtest { + def f = "" match { case X(s) => } + + def g = "" match { case X(s, t) => } + + def h = "" match { case X(s, t, u @ _*) => } + + def ok = "" match { case X(s, u @ _*) => } +} +// for extractors that unapplySeq: Option[Seq[_]], anything goes +trait Rtest { + val r = "(a+)".r + + def f = "" match { case r(s) => } + + def g = "" match { case r(s, t) => } + + def h = "" match { case r(s, t, u @ _*) => } + + def whatever = "" match { case r(u @ _*) => } +} diff --git a/test/files/neg/t9008.check b/test/files/neg/t9008.check new file mode 100644 index 0000000000..c32bc41baf --- /dev/null +++ b/test/files/neg/t9008.check @@ -0,0 +1,4 @@ +t9008.scala:2: error: type M takes type parameters + def x: List[M forSome { type M[_] }] = ??? + ^ +one error found diff --git a/test/files/neg/t9008.scala b/test/files/neg/t9008.scala new file mode 100644 index 0000000000..c6a5389e42 --- /dev/null +++ b/test/files/neg/t9008.scala @@ -0,0 +1,3 @@ +object Test { + def x: List[M forSome { type M[_] }] = ??? +} diff --git a/test/files/neg/t9008b.check b/test/files/neg/t9008b.check new file mode 100644 index 0000000000..5e911fc138 --- /dev/null +++ b/test/files/neg/t9008b.check @@ -0,0 +1,4 @@ +t9008b.scala:2: error: type M takes type parameters + type T = M forSome { type M[_] } + ^ +one error found diff --git a/test/files/neg/t9008b.scala b/test/files/neg/t9008b.scala new file mode 100644 index 0000000000..58f9d0e8de --- /dev/null +++ b/test/files/neg/t9008b.scala @@ -0,0 +1,3 @@ +object Test { + type T = M forSome { type M[_] } +} diff --git a/test/files/neg/t9093.check b/test/files/neg/t9093.check new file mode 100644 index 0000000000..085a433f0b --- /dev/null +++ b/test/files/neg/t9093.check @@ -0,0 +1,6 @@ +t9093.scala:3: error: polymorphic expression cannot be instantiated to expected type; + found : [C](f: C)Null + required: Unit + val x: Unit = apply2(0)/*(0)*/ + ^ +one error found diff --git a/test/files/neg/t9093.scala b/test/files/neg/t9093.scala new file mode 100644 index 0000000000..d9922ad70e --- /dev/null +++ b/test/files/neg/t9093.scala @@ -0,0 +1,5 @@ +object Main { + def apply2[C](fa: Any)(f: C) = null + val x: Unit = apply2(0)/*(0)*/ +} + diff --git a/test/files/pos/patmat-suppress.flags b/test/files/pos/patmat-suppress.flags new file mode 100644 index 0000000000..a988a5b807 --- /dev/null +++ b/test/files/pos/patmat-suppress.flags @@ -0,0 +1 @@ +-Xfatal-warnings -Xno-patmat-analysis
\ No newline at end of file diff --git a/test/files/pos/patmat-suppress.scala b/test/files/pos/patmat-suppress.scala new file mode 100644 index 0000000000..7c8aded690 --- /dev/null +++ b/test/files/pos/patmat-suppress.scala @@ -0,0 +1,159 @@ +// test that none of these warn due to -Xno-patmat-analysis +// tests taken from test/files/neg/patmatexhaust.scala, test/files/neg/pat_unreachable.scala +class TestSealedExhaustive { // compile only + sealed abstract class Foo + + case class Bar(x:Int) extends Foo + case object Baz extends Foo + + def ma1(x:Foo) = x match { + case Bar(_) => // not exhaustive + } + + def ma2(x:Foo) = x match { + case Baz => // not exhaustive + } + + sealed abstract class Mult + case class Kult(s:Mult) extends Mult + case class Qult() extends Mult + + def ma33(x:Kult) = x match { // exhaustive + case Kult(_) => // exhaustive + } + + def ma3(x:Mult) = (x,x) match { // not exhaustive + case (Kult(_), Qult()) => // Kult missing + //case (Kult(_), Kult(_)) => + case (Qult(), Kult(_)) => // Qult missing + //case (Qult(), Qult()) => + } + + def ma3u(x:Mult) = ((x,x) : @unchecked) match { // not exhaustive, but not checked! + case (Kult(_), Qult()) => + case (Qult(), Kult(_)) => + } + + sealed abstract class Deep + + case object Ga extends Deep + sealed class Gp extends Deep + case object Gu extends Gp + + def zma3(x:Deep) = x match { // exhaustive! + case _ => + } + def zma4(x:Deep) = x match { // exhaustive! + case Ga => + case _ => + } + + def ma4(x:Deep) = x match { // missing cases: Gu, Gp which is not abstract so must be included + case Ga => + } + + def ma5(x:Deep) = x match { + case Gu => + case _ if 1 == 0 => + case Ga => + } + + def ma6() = List(1,2) match { // give up + case List(1,2) => + case x :: xs => + } + + def ma7() = List(1,2) match { //exhaustive + case 1::2::Nil => + case _ => + } + + sealed class B + case class B1() extends B + case object B2 extends B + def ma8(x: B) = x match { + case _: B => true + } + def ma9(x: B) = x match { + case B1() => true // missing B, which is not abstract so must be included + case B2 => true + } + + object ob1 { + sealed abstract class C + sealed abstract class C1 extends C + object C2 extends C + case class C3() extends C + case object C4 extends C + + def ma10(x: C) = x match { // exhaustive: abstract sealed C1 is dead end. + case C3() => true + case C2 | C4 => true + } + } + + object ob2 { + sealed abstract class C + abstract class C1 extends C + object C2 extends C + case class C3() extends C + case object C4 extends C + + def ma10(x: C) = x match { // not exhaustive: C1 is not sealed. + case C3() => true + case C2 | C4 => true + } + } + object ob3 { + sealed abstract class C + sealed abstract class C1 extends C + object D1 extends C1 + case class D2() extends C1 + object C2 extends C + case class C3() extends C + case object C4 extends C + + def ma10(x: C) = x match { // not exhaustive: C1 has subclasses. + case C3() => true + case C2 | C4 => true + } + } + object ob4 { + sealed abstract class C + sealed class C1 extends C + object C2 extends C + case class C3() extends C + case object C4 extends C + + def ma10(x: C) = x match { // not exhaustive: C1 is not abstract. + case C3() => true + case C2 | C4 => true + } + } +} + +object TestUnreachable extends App { + def unreachable1(xs:Seq[Char]) = xs match { + case Seq(x, y, _*) => x::y::Nil + case Seq(x, y, z, w) => List(z,w) // redundant! + } + def unreachable2(xs:Seq[Char]) = xs match { + case Seq(x, y, _*) => x::y::Nil + case Seq(x, y) => List(x, y) + } + + def not_unreachable(xs:Seq[Char]) = xs match { + case Seq(x, y, _*) => x::y::Nil + case Seq(x) => List(x) + } + def not_unreachable2(xs:Seq[Char]) = xs match { + case Seq(x, y) => x::y::Nil + case Seq(x, y, z, _*) => List(x,y) + } + + def contrivedExample[A, B, C](a: A, b: B, c: C): Unit = a match { + case b => println("matched b") + case c => println("matched c") + case _ => println("matched neither") + } +} diff --git a/test/files/pos/t4070.scala b/test/files/pos/t4070.scala index a9777f02ed..11af67a529 100644 --- a/test/files/pos/t4070.scala +++ b/test/files/pos/t4070.scala @@ -20,7 +20,7 @@ package b { /* -// With crash below the clasess: +// With crash below the classes: % scalac -Dscalac.debug.tvar ./a.scala [ create] ?_$1 ( In Foo#crash ) [ setInst] tv[Int] ( In Foo#crash, _$1=tv[Int] ) diff --git a/test/files/pos/t5154.scala b/test/files/pos/t5154.scala new file mode 100644 index 0000000000..2629308f00 --- /dev/null +++ b/test/files/pos/t5154.scala @@ -0,0 +1,9 @@ + +trait Z { + // extra space made the pattern OK + def f = <z> {{3}}</z> match { case <z> {{3}}</z> => } + + // lack of space: error: illegal start of simple pattern + def g = <z>{{3}}</z> match { case <z>{{3}}</z> => } +} + diff --git a/test/files/pos/t6582_exhaust_big.scala b/test/files/pos/t6582_exhaust_big.scala new file mode 100644 index 0000000000..7bb8879805 --- /dev/null +++ b/test/files/pos/t6582_exhaust_big.scala @@ -0,0 +1,33 @@ +sealed abstract class Z +object Z { + object Z0 extends Z + case class Z1() extends Z + object Z2 extends Z + case class Z3() extends Z + object Z4 extends Z + case class Z5() extends Z + object Z6 extends Z + case class Z7() extends Z + object Z8 extends Z + case class Z9() extends Z + object Z10 extends Z + case class Z11() extends Z + object Z12 extends Z + case class Z13() extends Z + object Z14 extends Z + case class Z15() extends Z + object Z16 extends Z + case class Z17() extends Z + object Z18 extends Z + case class Z19() extends Z +} + +// drop any case and it will report an error +object Test { + import Z._ + def foo(z: Z) = z match { + case Z0 | Z1() | Z2 | Z3() | Z4 | Z5() | Z6 | Z7() | Z8 | Z9() | + Z10 | Z11() | Z12 | Z13() | Z14 | Z15() | Z16 | Z17() | Z18 | Z19() + => + } +} diff --git a/test/files/pos/t7459a.scala b/test/files/pos/t7459a.scala new file mode 100644 index 0000000000..5107715e06 --- /dev/null +++ b/test/files/pos/t7459a.scala @@ -0,0 +1,18 @@ +trait SpecialException extends Throwable + +object Test { + def run() { + try { + ??? + } catch { + case e: SpecialException => e.isInstanceOf[SpecialException] + case e => + } + + // OKAY + // (null: Throwable) match { + // case e: SpecialException => e.isInstanceOf[SpecialException] + // case e => + // } + } +}
\ No newline at end of file diff --git a/test/files/pos/t7459b.scala b/test/files/pos/t7459b.scala new file mode 100644 index 0000000000..a4b4fd07a9 --- /dev/null +++ b/test/files/pos/t7459b.scala @@ -0,0 +1,12 @@ +import scala.concurrent._ +import scala.util._ + + +class Test { + (null: Any) match { + case s @ Some(_) => ??? + case f @ _ => + () => f + ??? + } +}
\ No newline at end of file diff --git a/test/files/pos/t7459c.scala b/test/files/pos/t7459c.scala new file mode 100644 index 0000000000..dc2605abe6 --- /dev/null +++ b/test/files/pos/t7459c.scala @@ -0,0 +1,18 @@ +object Test { + trait Universe { + type Type + type TypeTag[A] >: Null <: TypeTagApi[A] + trait TypeTagApi[A] { def tpe: Type } + } + trait JavaUniverse extends Universe + + trait Mirror[U <: Universe] { + def universe: U + } + (null: Mirror[_]).universe match { + case ju: JavaUniverse => + val ju1 = ju + val f = {() => (null: ju.TypeTag[Nothing]).tpe } + } + trait M[A] +} diff --git a/test/files/pos/t7459d.scala b/test/files/pos/t7459d.scala new file mode 100644 index 0000000000..7843156885 --- /dev/null +++ b/test/files/pos/t7459d.scala @@ -0,0 +1,8 @@ +class Test { + (null: Any) match { + case s @ Some(_) => ??? + case f @ _ => + () => f + ??? + } +} diff --git a/test/files/pos/t7683-stop-after-parser/ThePlugin.scala b/test/files/pos/t7683-stop-after-parser/ThePlugin.scala new file mode 100644 index 0000000000..cd800781dc --- /dev/null +++ b/test/files/pos/t7683-stop-after-parser/ThePlugin.scala @@ -0,0 +1,31 @@ +package scala.test.plugins + +import scala.tools.nsc +import nsc.Global +import nsc.Phase +import nsc.plugins.Plugin +import nsc.plugins.PluginComponent + +class ThePlugin(val global: Global) extends Plugin { + import global._ + + val name = "timebomb" + val description = "Explodes if run. Maybe I haven't implemented it yet." + val components = List[PluginComponent](thePhase1) + + private object thePhase1 extends PluginComponent { + val global = ThePlugin.this.global + + val runsAfter = List[String]("parser") + override val runsBefore = List[String]("namer") + val phaseName = ThePlugin.this.name + + def newPhase(prev: Phase) = new ThePhase(prev) + } + + private class ThePhase(prev: Phase) extends Phase(prev) { + override def name = ThePlugin.this.name + override def run = ??? + } +} + diff --git a/test/files/pos/t7683-stop-after-parser/sample_2.flags b/test/files/pos/t7683-stop-after-parser/sample_2.flags new file mode 100644 index 0000000000..99672cdfd3 --- /dev/null +++ b/test/files/pos/t7683-stop-after-parser/sample_2.flags @@ -0,0 +1 @@ +-Xplugin:. -Xplugin-require:timebomb -Ystop-after:parser diff --git a/test/files/pos/t7683-stop-after-parser/sample_2.scala b/test/files/pos/t7683-stop-after-parser/sample_2.scala new file mode 100644 index 0000000000..7eb11b8204 --- /dev/null +++ b/test/files/pos/t7683-stop-after-parser/sample_2.scala @@ -0,0 +1,6 @@ + +package sample + +// just a sample that is compiled with the explosive plugin disabled +object Sample extends App { +} diff --git a/test/files/pos/t7683-stop-after-parser/scalac-plugin.xml b/test/files/pos/t7683-stop-after-parser/scalac-plugin.xml new file mode 100644 index 0000000000..2558d6fd03 --- /dev/null +++ b/test/files/pos/t7683-stop-after-parser/scalac-plugin.xml @@ -0,0 +1,5 @@ +<plugin> + <name>ignored</name> + <classname>scala.test.plugins.ThePlugin</classname> +</plugin> + diff --git a/test/files/pos/t7704.scala b/test/files/pos/t7704.scala new file mode 100644 index 0000000000..cae88d3324 --- /dev/null +++ b/test/files/pos/t7704.scala @@ -0,0 +1,10 @@ +class Attr { type V ; class Val } +class StrAttr extends Attr { type V = String } +class BoolAttr extends Attr { type V = Boolean } + +object Main { + def f(x: Attr) = x match { + case v: StrAttr => new v.Val + case v: BoolAttr => new v.Val + } +} diff --git a/test/files/pos/t8828.scala b/test/files/pos/t8828.scala index 92092b4dd4..182aba54c0 100644 --- a/test/files/pos/t8828.scala +++ b/test/files/pos/t8828.scala @@ -11,7 +11,7 @@ package inner { } // the trait is sealed and doWork is not - // and cannot be overriden: no warning + // and cannot be overridden: no warning private[outer] sealed trait C { def doWork(a: A): A = a } diff --git a/test/files/pos/t8999.flags b/test/files/pos/t8999.flags new file mode 100644 index 0000000000..0f96f1f872 --- /dev/null +++ b/test/files/pos/t8999.flags @@ -0,0 +1 @@ +-nowarn
\ No newline at end of file diff --git a/test/files/pos/t8999.scala b/test/files/pos/t8999.scala new file mode 100644 index 0000000000..99c4b2ad84 --- /dev/null +++ b/test/files/pos/t8999.scala @@ -0,0 +1,271 @@ +object Types { + + abstract sealed class Type + + case object AnyType extends Type + + case object NothingType extends Type + + case object UndefType extends Type + + case object BooleanType extends Type + + case object IntType extends Type + + case object LongType extends Type + + case object FloatType extends Type + + case object DoubleType extends Type + + case object StringType extends Type + + case object NullType extends Type + + sealed abstract class ReferenceType extends Type + + final case class ClassType(className: String) extends ReferenceType + + final case class ArrayType(baseClassName: String, dimensions: Int) extends ReferenceType + + final case class RecordType(fields: List[RecordType.Field]) extends Type + + object RecordType { + final case class Field(name: String, originalName: Option[String], + tpe: Type, mutable: Boolean) + } + + case object NoType extends Type + +} + + +sealed abstract class ClassKind + +object ClassKind { + + case object Class extends ClassKind + + case object ModuleClass extends ClassKind + + case object Interface extends ClassKind + + case object RawJSType extends ClassKind + + case object HijackedClass extends ClassKind + + case object TraitImpl extends ClassKind + +} + +object Trees { + + import Types._ + + abstract sealed class Tree + + case object EmptyTree extends Tree + + sealed trait PropertyName + case class Ident(name: String, originalName: Option[String]) extends PropertyName + object Ident { + def apply(name: String): Ident = + new Ident(name, Some(name)) + } + + case class VarDef(name: Ident, vtpe: Type, mutable: Boolean, rhs: Tree) extends Tree + + case class ParamDef(name: Ident, ptpe: Type, mutable: Boolean) extends Tree + + case class Skip() extends Tree + + class Block private(val stats: List[Tree]) extends Tree + + object Block { + def unapply(block: Block): Some[List[Tree]] = Some(block.stats) + } + + case class Labeled(label: Ident, tpe: Type, body: Tree) extends Tree + + case class Assign(lhs: Tree, rhs: Tree) extends Tree + + case class Return(expr: Tree, label: Option[Ident] = None) extends Tree + + case class If(cond: Tree, thenp: Tree, elsep: Tree) extends Tree + + case class While(cond: Tree, body: Tree, label: Option[Ident] = None) extends Tree + + case class DoWhile(body: Tree, cond: Tree, label: Option[Ident] = None) extends Tree + + case class Try(block: Tree, errVar: Ident, handler: Tree, finalizer: Tree) extends Tree + + case class Throw(expr: Tree) extends Tree + + case class Continue(label: Option[Ident] = None) extends Tree + + case class Match(selector: Tree, cases: List[(List[Literal], Tree)], default: Tree) extends Tree + + case class Debugger() extends Tree + + case class New(cls: ClassType, ctor: Ident, args: List[Tree]) extends Tree + + case class LoadModule(cls: ClassType) extends Tree + + case class StoreModule(cls: ClassType, value: Tree) extends Tree + + case class Select(qualifier: Tree, item: Ident, mutable: Boolean) extends Tree + + case class Apply(receiver: Tree, method: Ident, args: List[Tree]) extends Tree + + case class StaticApply(receiver: Tree, cls: ClassType, method: Ident, args: List[Tree]) extends Tree + + case class TraitImplApply(impl: ClassType, method: Ident, args: List[Tree]) extends Tree + + case class UnaryOp(op: Int, lhs: Tree) extends Tree + + case class BinaryOp(op: Int, lhs: Tree, rhs: Tree) extends Tree + + case class NewArray(tpe: ArrayType, lengths: List[Tree]) extends Tree + + case class ArrayValue(tpe: ArrayType, elems: List[Tree]) extends Tree + + case class ArrayLength(array: Tree) extends Tree + + case class ArraySelect(array: Tree, index: Tree) extends Tree + + case class RecordValue(tpe: RecordType, elems: List[Tree]) extends Tree + + case class IsInstanceOf(expr: Tree, cls: ReferenceType) extends Tree + + case class AsInstanceOf(expr: Tree, cls: ReferenceType) extends Tree + + case class Unbox(expr: Tree, charCode: Char) extends Tree + + case class GetClass(expr: Tree) extends Tree + + case class CallHelper(helper: String, args: List[Tree]) extends Tree + + case class JSNew(ctor: Tree, args: List[Tree]) extends Tree + + case class JSDotSelect(qualifier: Tree, item: Ident) extends Tree + + case class JSBracketSelect(qualifier: Tree, item: Tree) extends Tree + + case class JSFunctionApply(fun: Tree, args: List[Tree]) extends Tree + + case class JSDotMethodApply(receiver: Tree, method: Ident, args: List[Tree]) extends Tree + + case class JSBracketMethodApply(receiver: Tree, method: Tree, args: List[Tree]) extends Tree + + case class JSDelete(prop: Tree) extends Tree + + case class JSUnaryOp(op: String, lhs: Tree) extends Tree + + case class JSBinaryOp(op: String, lhs: Tree, rhs: Tree) extends Tree + + case class JSArrayConstr(items: List[Tree]) extends Tree + + case class JSObjectConstr(fields: List[(PropertyName, Tree)]) extends Tree + + case class JSEnvInfo() extends Tree + + sealed trait Literal extends Tree + + case class Undefined() extends Literal + + case class UndefinedParam() extends Literal + + case class Null() extends Literal + + case class BooleanLiteral(value: Boolean) extends Literal + + case class IntLiteral(value: Int) extends Literal + + case class LongLiteral(value: Long) extends Literal + + case class FloatLiteral(value: Float) extends Literal + + case class DoubleLiteral(value: Double) extends Literal + + case class StringLiteral(value: String) extends Literal with PropertyName + + case class ClassOf(cls: ReferenceType) extends Literal + + case class VarRef(ident: Ident, mutable: Boolean) extends Tree + + case class This() extends Tree + + case class Closure(captureParams: List[ParamDef], params: List[ParamDef], + body: Tree, captureValues: List[Tree]) extends Tree + + case class ClassDef(name: Ident, kind: ClassKind, parent: Option[Ident], ancestors: List[Ident], defs: List[Tree]) extends Tree + + case class MethodDef(name: PropertyName, args: List[ParamDef], resultType: Type, body: Tree) extends Tree + + case class PropertyDef(name: PropertyName, getterBody: Tree, setterArg: ParamDef, setterBody: Tree) extends Tree + + case class ConstructorExportDef(name: String, args: List[ParamDef], body: Tree) extends Tree + + case class ModuleExportDef(fullName: String) extends Tree + + final class TreeHash(val treeHash: Array[Byte], val posHash: Array[Byte]) +} + +object Main { + import Trees._ + import Types._ + + private def transform(tree: Tree) = { + val ObjectClass = "O" + tree match { + case VarDef(_, _, _, rhs) => + case tree: Block => + case Labeled(ident@Ident(label, _), tpe, body) => + case Assign(lhs, rhs) => + case Return(expr, optLabel) => + case If(cond, thenp, elsep) => + case While(cond, body, optLabel) => + case DoWhile(body, cond, None) => + case Try(block, errVar, EmptyTree, finalizer) => + case Try(block, errVar@Ident(name, originalName), handler, finalizer) => + case Throw(expr) => + case Continue(optLabel) => + case Match(selector, cases, default) => + case New(cls, ctor, args) => + case StoreModule(cls, value) => + case tree: Select => + case tree: Apply => + case tree: StaticApply => + case tree: TraitImplApply => + case tree@UnaryOp(_, arg) => + case tree@BinaryOp(op, lhs, rhs) => + case NewArray(tpe, lengths) => + case ArrayValue(tpe, elems) => + case ArrayLength(array) => + case ArraySelect(array, index) => + case RecordValue(tpe, elems) => + case IsInstanceOf(expr, ClassType(ObjectClass)) => + case IsInstanceOf(expr, tpe) => + case AsInstanceOf(expr, ClassType(ObjectClass)) => + case AsInstanceOf(expr, cls) => + case Unbox(arg, charCode) => + case GetClass(expr) => + case JSNew(ctor, args) => + case JSDotSelect(qualifier, item) => + case JSBracketSelect(qualifier, item) => + case tree: JSFunctionApply => + case JSDotMethodApply(receiver, method, args) => + case JSBracketMethodApply(receiver, method, args) => + case JSDelete(JSDotSelect(obj, prop)) => + case JSDelete(JSBracketSelect(obj, prop)) => + case JSUnaryOp(op, lhs) => + case JSBinaryOp(op, lhs, rhs) => + case JSArrayConstr(items) => + case JSObjectConstr(fields) => + case _: VarRef | _: This => + case Closure(captureParams, params, body, captureValues) => + case _: Skip | _: Debugger | _: LoadModule | + _: JSEnvInfo | _: Literal | EmptyTree => + } + } +}
\ No newline at end of file diff --git a/test/files/pos/t9008.scala b/test/files/pos/t9008.scala new file mode 100644 index 0000000000..d11b8604f2 --- /dev/null +++ b/test/files/pos/t9008.scala @@ -0,0 +1,5 @@ +trait Monad[M[_]] + +object Test { + def x: Monad[M forSome { type M[_] }] = ??? +} diff --git a/test/files/pos/t9050.scala b/test/files/pos/t9050.scala new file mode 100644 index 0000000000..b1ab09f901 --- /dev/null +++ b/test/files/pos/t9050.scala @@ -0,0 +1,13 @@ +final class Mu[F](val value: Any) extends AnyVal { + def cata(f: F) { + // crash + ((y: Mu[F]) => y.cata(f)) + // crash + def foo(x : Mu[F]) = x.cata(f) + + // // okay + def x: Mu[F] = ??? + (() => x.cata(f)) + assert(true, cata(f)) + } +} diff --git a/test/files/presentation/visibility/src/Completions.scala b/test/files/presentation/visibility/src/Completions.scala index 8c07934915..69ec3959ad 100644 --- a/test/files/presentation/visibility/src/Completions.scala +++ b/test/files/presentation/visibility/src/Completions.scala @@ -11,7 +11,7 @@ package accessibility { def secretPublic(): Unit def someTests(other: Foo) { - other./*!*/secretPrivate // should be all but scretThis + other./*!*/secretPrivate // should be all but secretThis this./*!*/secretProtected // should hit five completions } @@ -25,7 +25,7 @@ package accessibility { class UnrelatedClass { def someTests(foo: Foo) { - foo./*!*/ // should list public and protected[accessiblity] + foo./*!*/ // should list public and protected[accessibility] } } diff --git a/test/files/res/t9089.check b/test/files/res/t9089.check new file mode 100644 index 0000000000..6cf64f734b --- /dev/null +++ b/test/files/res/t9089.check @@ -0,0 +1,4 @@ + +nsc> +nsc> +nsc> diff --git a/test/files/res/t9089.res b/test/files/res/t9089.res new file mode 100644 index 0000000000..ab5cc8534d --- /dev/null +++ b/test/files/res/t9089.res @@ -0,0 +1,2 @@ +t9089/A.scala +t9089/A.scala diff --git a/test/files/res/t9089/A.scala b/test/files/res/t9089/A.scala new file mode 100644 index 0000000000..bccf269639 --- /dev/null +++ b/test/files/res/t9089/A.scala @@ -0,0 +1 @@ +object O { def f(x: => Int): Int = x } diff --git a/test/files/run/applydynamic_sip.scala b/test/files/run/applydynamic_sip.scala index cf918a82ed..47d0c6a303 100644 --- a/test/files/run/applydynamic_sip.scala +++ b/test/files/run/applydynamic_sip.scala @@ -40,7 +40,7 @@ object Test extends App { // qual.sel(arg = a, a2: _*) // qual.sel(arg, arg2 = "a2", a2: _*) - // If qual.sel appears immediately on the left-hand side of an assigment + // If qual.sel appears immediately on the left-hand side of an assignment // qual.updateDynamic(“sel”)(expr) qual.sel = expr diff --git a/test/files/run/bitsets.check b/test/files/run/bitsets.check index 41c2ccdcb8..c24fd6238f 100644 --- a/test/files/run/bitsets.check +++ b/test/files/run/bitsets.check @@ -1,3 +1,4 @@ +warning: there were three deprecation warnings; re-run with -deprecation for details ms0 = BitSet(2) ms1 = BitSet(2) ms2 = BitSet(2) diff --git a/test/files/run/icode-reader-dead-code.check b/test/files/run/icode-reader-dead-code.check index d1739fed3b..c9de93283e 100644 --- a/test/files/run/icode-reader-dead-code.check +++ b/test/files/run/icode-reader-dead-code.check @@ -1,4 +1,7 @@ Bytecode for method f + + // access flags 0x11 + public final f()I L0 LINENUMBER 4 L0 ICONST_1 @@ -7,7 +10,11 @@ Bytecode for method f LOCALVARIABLE this Lp/A; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 + Bytecode for method f + + // access flags 0x11 + public final f()I L0 LINENUMBER 4 L0 ICONST_1 @@ -17,3 +24,4 @@ Bytecode for method f LOCALVARIABLE this Lp/A; L0 L1 0 MAXSTACK = 1 MAXLOCALS = 1 + diff --git a/test/files/run/literals.check b/test/files/run/literals.check index 62c5fd68ae..092340eead 100644 --- a/test/files/run/literals.check +++ b/test/files/run/literals.check @@ -1,57 +1,12 @@ -warning: there were 5 deprecation warnings; re-run with -deprecation for details -test '\u0024' == '$' was successful -test '\u005f' == '_' was successful -test 65.asInstanceOf[Char] == 'A' was successful -test "\141\142" == "ab" was successful -test "\0x61\0x62".trim() == "x61\0x62" was successful - -test (65 : Byte) == 'A' was successful - -test 0X01 == 1 was successful -test 0x01 == 1 was successful -test 0x10 == 16 was successful -test 0xa == 10 was successful -test 0x0a == 10 was successful -test +0x01 == 1 was successful -test +0x10 == 16 was successful -test +0xa == 10 was successful -test +0x0a == 10 was successful -test -0x01 == -1 was successful -test -0x10 == -16 was successful -test -0xa == -10 was successful -test -0x0a == -10 was successful -test 0x7fffffff == 2147483647 was successful -test 0x80000000 == -2147483648 was successful -test 0xffffffff == -1 was successful - -test 1l == 1L was successful -test 1L == 1l was successful -test 1.asInstanceOf[Long] == 1l was successful -test 0x7fffffffffffffffL == 9223372036854775807L was successful -test 0x8000000000000000L == -9223372036854775808L was successful -test 0xffffffffffffffffL == -1L was successful - -test 1e1f == 10.0f was successful -test .3f == 0.3f was successful -test 0f == 0.0f was successful -test 01.23f == 1.23f was successful -test 3.14f == 3.14f was successful -test 6.022e23f == 6.022e23f was successful -test 09f == 9.0f was successful -test 1.asInstanceOf[Float] == 1.0 was successful -test 1l.asInstanceOf[Float] == 1.0 was successful - -test 1e1 == 10.0 was successful -test .3 == 0.3 was successful -test 0.0 == 0.0 was successful -test 0d == 0.0 was successful -test 01.23 == 1.23 was successful -test 01.23d == 1.23d was successful -test 3.14 == 3.14 was successful -test 1e-9d == 1.0e-9 was successful -test 1e137 == 1.0e137 was successful -test 1.asInstanceOf[Double] == 1.0 was successful -test 1l.asInstanceOf[Double] == 1.0 was successful - -test "".length() was successful -test ggg == 3 was successful +literals.scala:34: warning: Octal escape literals are deprecated, use \u0061 instead. + check_success("\"\\141\\142\" == \"ab\"", "\141\142", "ab") + ^ +literals.scala:34: warning: Octal escape literals are deprecated, use \u0062 instead. + check_success("\"\\141\\142\" == \"ab\"", "\141\142", "ab") + ^ +literals.scala:37: warning: Octal escape literals are deprecated, use \u0000 instead. + "\0x61\0x62".getBytes(io.Codec.UTF8.charSet) sameElements Array[Byte](0, 120, 54, 49, 0, 120, 54, 50), + ^ +literals.scala:37: warning: Octal escape literals are deprecated, use \u0000 instead. + "\0x61\0x62".getBytes(io.Codec.UTF8.charSet) sameElements Array[Byte](0, 120, 54, 49, 0, 120, 54, 50), + ^ diff --git a/test/files/run/literals.flags b/test/files/run/literals.flags new file mode 100644 index 0000000000..dcc59ebe32 --- /dev/null +++ b/test/files/run/literals.flags @@ -0,0 +1 @@ +-deprecation diff --git a/test/files/run/literals.scala b/test/files/run/literals.scala index 5f23e6b492..13fda05876 100644 --- a/test/files/run/literals.scala +++ b/test/files/run/literals.scala @@ -14,21 +14,16 @@ object Test { def \u03b1\u03b1(that: GGG) = i + that.i } - def check_success[a](name: String, closure: => a, expected: a) { - print("test " + name) - try { - val actual: a = closure - if (actual == expected) { - print(" was successful"); - } else { - print(" failed: expected "+ expected +", found "+ actual); + def check_success[A](name: String, closure: => A, expected: A) { + val res: Option[String] = + try { + val actual: A = closure + if (actual == expected) None //print(" was successful") + else Some(s" failed: expected $expected, found $actual") + } catch { + case exception: Throwable => Some(s" raised exception $exception") } - } catch { - case exception: Throwable => { - print(" raised exception " + exception); - } - } - println + for (e <- res) println(s"test $name $e") } def main(args: Array[String]) { @@ -37,15 +32,14 @@ object Test { check_success("'\\u005f' == '_'", '\u005f', '_') check_success("65.asInstanceOf[Char] == 'A'", 65.asInstanceOf[Char], 'A') check_success("\"\\141\\142\" == \"ab\"", "\141\142", "ab") - check_success("\"\\0x61\\0x62\".trim() == \"x61\\0x62\"", "\0x61\0x62".substring(1), "x61\0x62") - - println + //check_success("\"\\0x61\\0x62\".trim() == \"x61\\0x62\"", "\0x61\0x62".substring(1), "x61\0x62") + check_success(""""\0x61\0x62".getBytes == Array(0, 120, ...)""", + "\0x61\0x62".getBytes(io.Codec.UTF8.charSet) sameElements Array[Byte](0, 120, 54, 49, 0, 120, 54, 50), + true) // boolean check_success("(65 : Byte) == 'A'", (65: Byte) == 'A', true) // contrib #176 - println - // int check_success("0X01 == 1", 0X01, 1) check_success("0x01 == 1", 0x01, 1) @@ -67,8 +61,6 @@ object Test { check_success("0x80000000 == -2147483648", 0x80000000, -2147483648) check_success("0xffffffff == -1", 0xffffffff, -1) - println - // long check_success("1l == 1L", 1l, 1L) check_success("1L == 1l", 1L, 1l) @@ -81,8 +73,6 @@ object Test { check_success("0xffffffffffffffffL == -1L", 0xffffffffffffffffL, -1L) - println - // see JLS at address: // http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#230798 @@ -97,8 +87,6 @@ object Test { check_success("1.asInstanceOf[Float] == 1.0", 1.asInstanceOf[Float], 1.0f) check_success("1l.asInstanceOf[Float] == 1.0", 1l.asInstanceOf[Float], 1.0f) - println - // double check_success("1e1 == 10.0", 1e1, 10.0) check_success(".3 == 0.3", .3, 0.3) @@ -112,7 +100,6 @@ object Test { check_success("1.asInstanceOf[Double] == 1.0", 1.asInstanceOf[Double], 1.0) check_success("1l.asInstanceOf[Double] == 1.0", 1l.asInstanceOf[Double], 1.0) - println check_success("\"\".length()", "\u001a".length(), 1) val ggg = GGG(1) \u03b1\u03b1 GGG(2) diff --git a/test/files/run/t5313.scala b/test/files/run/t5313.scala index 0d7168fa89..7f5af74c3f 100644 --- a/test/files/run/t5313.scala +++ b/test/files/run/t5313.scala @@ -11,7 +11,7 @@ object Test extends IcodeComparison { def bar = { var kept1 = new Object val result = new java.lang.ref.WeakReference(kept1) - kept1 = null // we can't eliminate this assigment because result can observe + kept1 = null // we can't eliminate this assignment because result can observe // when the object has no more references. See SI-5313 kept1 = new Object // but we can eliminate this one because kept1 has already been clobbered var erased2 = null // we can eliminate this store because it's never used diff --git a/test/files/run/t6114.scala b/test/files/run/t6114.scala index cb880ece00..8ad02d5bb2 100644 --- a/test/files/run/t6114.scala +++ b/test/files/run/t6114.scala @@ -51,7 +51,7 @@ object Test extends App { val next = list.asScala ++ List(4,5,6) assert(next != list.asScala) - // Note: Clone is hidden at this level, so no overriden cloning. + // Note: Clone is hidden at this level, so no overridden cloning. } testList diff --git a/test/files/run/t6502.scala b/test/files/run/t6502.scala index ced1b5812d..4ce034a482 100644 --- a/test/files/run/t6502.scala +++ b/test/files/run/t6502.scala @@ -1,6 +1,7 @@ -import scala.tools.partest._ -import java.io.File +import scala.tools.nsc.Settings import scala.tools.nsc.interpreter.ILoop +import scala.tools.nsc.settings.ClassPathRepresentationType +import scala.tools.partest._ object Test extends StoreReporterDirectTest { def code = ??? @@ -10,6 +11,14 @@ object Test extends StoreReporterDirectTest { compileString(newCompiler("-cp", classpath, "-d", s"${testOutput.path}/$jarFileName"))(code) } + // TODO flat classpath doesn't support the classpath invalidation yet so we force using the recursive one + // it's the only test which needed such a workaround + override def settings = { + val settings = new Settings + settings.YclasspathImpl.value = ClassPathRepresentationType.Recursive + settings + } + def app1 = """ package test @@ -41,7 +50,8 @@ object Test extends StoreReporterDirectTest { val jar = "test1.jar" compileCode(app1, jar) - val output = ILoop.run(List(s":require ${testOutput.path}/$jar", "test.Test.test()")) + val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar", "test.Test.test()") + val output = ILoop.run(codeToRun, settings) val lines = output.split("\n") val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar") val res2 = lines(lines.length-3).contains("testing...") @@ -56,7 +66,8 @@ object Test extends StoreReporterDirectTest { val jar2 = "test2.jar" compileCode(app2, jar2) - val output = ILoop.run(List(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar2")) + val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar2") + val output = ILoop.run(codeToRun, settings) val lines = output.split("\n") val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar") val res2 = lines(lines.length-3).contains("test2.jar") && lines(lines.length-3).contains("existing classpath entries conflict") @@ -71,7 +82,8 @@ object Test extends StoreReporterDirectTest { val jar3 = "test3.jar" compileCode(app3, jar3) - val output = ILoop.run(List(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar3", "test.Test3.test()")) + val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar3", "test.Test3.test()") + val output = ILoop.run(codeToRun, settings) val lines = output.split("\n") val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar") val res2 = lines(lines.length-3).contains("new object in existing package") @@ -83,7 +95,8 @@ object Test extends StoreReporterDirectTest { def test4(): Unit = { // twice the same jar should be rejected val jar1 = "test1.jar" - val output = ILoop.run(List(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar1")) + val codeToRun = toCodeInSeparateLines(s":require ${testOutput.path}/$jar1", s":require ${testOutput.path}/$jar1") + val output = ILoop.run(codeToRun, settings) val lines = output.split("\n") val res1 = lines(4).contains("Added") && lines(4).contains("test1.jar") val res2 = lines(lines.length-3).contains("test1.jar") && lines(lines.length-3).contains("existing classpath entries conflict") @@ -98,4 +111,6 @@ object Test extends StoreReporterDirectTest { test3() test4() } + + def toCodeInSeparateLines(lines: String*): String = lines.map(_ + "\n").mkString } diff --git a/test/files/run/t6669.scala b/test/files/run/t6669.scala index e18f2514a9..27c4970d60 100644 --- a/test/files/run/t6669.scala +++ b/test/files/run/t6669.scala @@ -1,4 +1,5 @@ import java.io.{ByteArrayOutputStream, PrintStream} +import scala.reflect.io.File object Test extends App { val baos = new ByteArrayOutputStream() @@ -9,9 +10,11 @@ object Test extends App { scala.tools.scalap.Main.main(Array("-verbose", "java.lang.Object")) } + val currentLocationCpFragment = File.pathSeparator + "." + // now make sure we saw the '.' in the classpath val msg1 = baos.toString() - assert(msg1 contains "directory classpath: .", s"Did not see '.' in the default class path. Full results were:\n$msg1") + assert(msg1 contains currentLocationCpFragment, s"Did not see '.' in the default class path. Full results were:\n$msg1") // then test again with a user specified classpath baos.reset @@ -22,5 +25,5 @@ object Test extends App { // now make sure we did not see the '.' in the classpath val msg2 = baos.toString() - assert(!(msg2 contains "directory classpath: ."), s"Did saw '.' in the user specified class path. Full results were:\n$msg2") + assert(!(msg2 contains currentLocationCpFragment), s"Did saw '.' in the user specified class path. Full results were:\n$msg2") } diff --git a/test/files/run/t7459a.scala b/test/files/run/t7459a.scala new file mode 100644 index 0000000000..e9653c6e79 --- /dev/null +++ b/test/files/run/t7459a.scala @@ -0,0 +1,14 @@ +class LM { + class Node[B1] + case class CC(n: LM) + + // crash + val f: (LM => Any) = { + case tttt => + new tttt.Node[Any]() + } +} + +object Test extends App { + new LM().f(new LM()) +} diff --git a/test/files/run/t7459b-optimize.flags b/test/files/run/t7459b-optimize.flags new file mode 100644 index 0000000000..49d036a887 --- /dev/null +++ b/test/files/run/t7459b-optimize.flags @@ -0,0 +1 @@ +-optimize diff --git a/test/files/run/t7459b-optimize.scala b/test/files/run/t7459b-optimize.scala new file mode 100644 index 0000000000..605890962c --- /dev/null +++ b/test/files/run/t7459b-optimize.scala @@ -0,0 +1,21 @@ +class LM { + class Node[B1] + + // crash + val g: (CC => Any) = { + case CC(tttt) => + new tttt.Node[Any]() + } + + val h: (Some[CC] => Any) = { + case Some(CC(tttt)) => + new tttt.Node[Any]() + } +} + +object Test extends App { + new LM().g(new CC(new LM())) + new LM().h(Some(new CC(new LM()))) +} +case class CC(n: LM) + diff --git a/test/files/run/t7459b.scala b/test/files/run/t7459b.scala new file mode 100644 index 0000000000..605890962c --- /dev/null +++ b/test/files/run/t7459b.scala @@ -0,0 +1,21 @@ +class LM { + class Node[B1] + + // crash + val g: (CC => Any) = { + case CC(tttt) => + new tttt.Node[Any]() + } + + val h: (Some[CC] => Any) = { + case Some(CC(tttt)) => + new tttt.Node[Any]() + } +} + +object Test extends App { + new LM().g(new CC(new LM())) + new LM().h(Some(new CC(new LM()))) +} +case class CC(n: LM) + diff --git a/test/files/run/t7459c.scala b/test/files/run/t7459c.scala new file mode 100644 index 0000000000..144c5d793b --- /dev/null +++ b/test/files/run/t7459c.scala @@ -0,0 +1,16 @@ +class LM { + class Node[B1] + + // crash + val g: (CC => Any) = { + case CC(tttt) => + tttt.## // no crash + new tttt.Node[Any]() + } +} + +object Test extends App { + new LM().g(new CC(new LM())) +} +case class CC(n: LM) + diff --git a/test/files/run/t7459d.scala b/test/files/run/t7459d.scala new file mode 100644 index 0000000000..3263701f9d --- /dev/null +++ b/test/files/run/t7459d.scala @@ -0,0 +1,15 @@ +class LM { + class Node[B1] + case class CC(n: LM) + + // crash + val f: (LM => Any) = { + case tttt => + val uuuu: (tttt.type, Any) = (tttt, 0) + new uuuu._1.Node[Any]() + } +} + +object Test extends App { + new LM().f(new LM()) +} diff --git a/test/files/run/t7459f.scala b/test/files/run/t7459f.scala new file mode 100644 index 0000000000..63e2109560 --- /dev/null +++ b/test/files/run/t7459f.scala @@ -0,0 +1,12 @@ +object Test extends App { + class C + + case class FooSeq(x: Int, y: String, z: C*) + + FooSeq(1, "a", new C()) match { + case FooSeq(1, "a", x@_* ) => + //println(x.toList) + x.asInstanceOf[x.type] + assert(x.isInstanceOf[x.type]) + } +} diff --git a/test/files/run/t7965.scala b/test/files/run/t7965.scala new file mode 100644 index 0000000000..df80d4b5bb --- /dev/null +++ b/test/files/run/t7965.scala @@ -0,0 +1,54 @@ +// Test that scala doesn't apply boxing or varargs conversions to the +// @PolymorphicSignature magical methods, MethodHandle#{invoke, invokeExact} +object Test { + val code = """ + +object O { + private def foo = "foo" + private def bar(x: Int): Int = -x + private def baz(x: Box): Unit = x.a = "present" + val lookup = java.lang.invoke.MethodHandles.lookup +} + +import java.lang.invoke._ +class Box(var a: Any) + +object Test { + def main(args: Array[String]): Unit = { + def lookup(name: String, params: Array[Class[_]], ret: Class[_]) = { + val mt = MethodType.methodType(ret, params) + O.lookup.findVirtual(O.getClass, name, mt) + } + val fooResult = (lookup("foo", Array(), classOf[String]).invokeExact(O): Int) + assert(fooResult == "foo") + + val barResult = (lookup("bar", Array(classOf[Int]), classOf[Int]).invokeExact(O, 42): Int) + assert(barResult == -42) + + val box = new Box(null) + (lookup("baz", Array(classOf[Box]), Void.TYPE).invokeExact(O, box) : Unit) + assert(box.a == "present") + + // Note: Application in statement position in a block in Java also infers return type of Unit, + // but we don't support that, ascribe the type to Unit as above. + // as done in Java. + // lookup("baz", Array(classOf[Box]), Void.TYPE).invokeExact(O, box) + () + } +} + +""" + def main(args: Array[String]): Unit = { + if (util.Properties.isJavaAtLeast("1.7")) test() + } + + def test() { + import scala.reflect.runtime._ + import scala.tools.reflect.ToolBox + + val m = currentMirror + val tb = m.mkToolBox() + import tb._ + eval(parse(code)) + } +} diff --git a/test/files/run/t8253.scala b/test/files/run/t8253.scala index c4800b4491..a00d8b91a4 100644 --- a/test/files/run/t8253.scala +++ b/test/files/run/t8253.scala @@ -10,5 +10,5 @@ object Test extends App { show("<sample xmlns:foo={identity(ns1)}/>", q"<sample xmlns:foo={ns1}/>") // `identity(foo)` used to match the overly permissive match in SymbolXMLBuilder - // which was intented to more specifically match `_root_.scala.xml.Text(...)` + // which was intended to more specifically match `_root_.scala.xml.Text(...)` } diff --git a/test/files/run/t9003.flags b/test/files/run/t9003.flags new file mode 100644 index 0000000000..49d036a887 --- /dev/null +++ b/test/files/run/t9003.flags @@ -0,0 +1 @@ +-optimize diff --git a/test/files/run/t9003.scala b/test/files/run/t9003.scala new file mode 100644 index 0000000000..4f24712201 --- /dev/null +++ b/test/files/run/t9003.scala @@ -0,0 +1,71 @@ +object Single { + var i = 0 + def isEmpty = false + def get = i + def unapply(a: Single.type) = this +} + +object Product { + var i = 0 + def _1: Int = i + def _2: String = ??? + def productArity = 2 + def unapply(a: Product.type) = this + def isEmpty = false + def get: this.type = this +} + +object Sequence { + var i = 0 + def apply(n: Int): Int = i + def length = 2 + def unapplySeq(a: Sequence.type) = this + def isEmpty = false + def get = this +} + +object Test { + def main(args: Array[String]): Unit = { + def assertZero(i: Int) = assert(i == 0) + + Single match { + case Single(i) => + Single.i = 1 + assertZero(i) // fails under -optimize + } + + Product match { + case Product(i, _) => + Product.i = 1 + assertZero(i) // fails under -optimize + } + + Sequence match { + case Sequence(i, _ @ _*) => + Sequence.i = 1 + assertZero(i) // okay + } + + Sequence.i = 0 + Sequence match { + case Sequence(_, i) => + Sequence.i = 1 + assertZero(i) // okay + } + + val buffer = collection.mutable.Buffer(0, 0) + buffer match { + case Seq(_, i) => + buffer(1) = 1 + assertZero(i) // failed + } + + case class CaseSequence(as: Int*) + val buffer1 = collection.mutable.Buffer(0, 0) + CaseSequence(buffer1: _*) match { + case CaseSequence(_, i) => + buffer1(1) = 1 + assertZero(i) // failed + } + } +} diff --git a/test/files/run/t9027.check b/test/files/run/t9027.check new file mode 100644 index 0000000000..3429254286 --- /dev/null +++ b/test/files/run/t9027.check @@ -0,0 +1,19 @@ +{ + { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, true)); + $buf.$amp$plus(new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true)); + $buf + }; + println("hello, world.") +} +{ + { + val $buf = new _root_.scala.xml.NodeBuffer(); + $buf.$amp$plus(new _root_.scala.xml.Elem(null, "a", _root_.scala.xml.Null, $scope, true)); + $buf.$amp$plus(new _root_.scala.xml.Elem(null, "b", _root_.scala.xml.Null, $scope, true)); + $buf.$amp$plus(new _root_.scala.xml.Elem(null, "c", _root_.scala.xml.Null, $scope, true)); + $buf + }; + println("hello, world.") +} diff --git a/test/files/run/t9027.scala b/test/files/run/t9027.scala new file mode 100644 index 0000000000..26238147da --- /dev/null +++ b/test/files/run/t9027.scala @@ -0,0 +1,15 @@ + +// used to be parsed as .println +object Test extends App { + import reflect.runtime._, universe._ + + val trees = List( + q"""<a/><b/> + println("hello, world.")""", + q"""<a/> + <b/> + <c/> + println("hello, world.")""" + ) + trees foreach println +} diff --git a/test/files/run/t9030.scala b/test/files/run/t9030.scala new file mode 100644 index 0000000000..48d24e5b54 --- /dev/null +++ b/test/files/run/t9030.scala @@ -0,0 +1,19 @@ +object Test extends App { + + // For these methods, the compiler emits calls to BoxesRuntime.equalsNumNum/equalsNumChar/equalsNumObject directly + + def numNum(a: java.lang.Number, b: java.lang.Number) = assert(a == b) + def numChar(a: java.lang.Number, b: java.lang.Character) = assert(a == b) + def numObject(a: java.lang.Number, b: java.lang.Object) = assert(a == b) + + // The compiler doesn't use equalsCharObject directly, but still adding an example for completeness + + def charObject(a: java.lang.Character, b: java.lang.Object) = assert(a == b) + + numNum(new Integer(1), new Integer(1)) + numChar(new Integer(97), new Character('a')) + numObject(new Integer(1), new Integer(1)) + numObject(new Integer(97), new Character('a')) + + charObject(new Character('a'), new Integer(97)) +} diff --git a/test/files/run/various-flat-classpath-types.check b/test/files/run/various-flat-classpath-types.check new file mode 100644 index 0000000000..401f707d0e --- /dev/null +++ b/test/files/run/various-flat-classpath-types.check @@ -0,0 +1,12 @@ +ZipBin() +JarBin() +DirBin() +ZipSrc() +JarSrc() +DirSrc() +NestedZipBin() +NestedJarBin() +NestedDirBin() +NestedZipSrc() +NestedJarSrc() +NestedDirSrc()
\ No newline at end of file diff --git a/test/files/run/various-flat-classpath-types.scala b/test/files/run/various-flat-classpath-types.scala new file mode 100644 index 0000000000..d39019e885 --- /dev/null +++ b/test/files/run/various-flat-classpath-types.scala @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2014 Contributor. All rights reserved. + */ + +import java.io.{File => JFile, FileInputStream, FileOutputStream} +import java.util.zip.{ZipEntry, ZipOutputStream} +import scala.reflect.io.{Directory, File} +import scala.tools.nsc.classpath.FlatClassPath.RootPackage +import scala.tools.nsc.classpath.PackageNameUtils +import scala.tools.nsc.io.Jar + +/** + * Generates directories, jars and zip files containing sources and classes + * (the result of a compilation which is executed here) + * and use them as a class- and sourcepath during compilation and running + * created application. At the end everything is cleaned up. + * + * It can test also current, recursive classpath. Just right now we force + * flat classpath to test it also when the recursive one would be set as a default. + */ +object Test { + + private implicit class JFileOps(file: JFile) { + + def createDir(newDirName: String) = { + val newDir = new JFile(file, newDirName) + newDir.mkdir() + newDir + } + + def createSrcFile(newFileName: String) = createFile(newFileName + ".scala") + + def createFile(fullFileName: String) = { + val newFile = new JFile(file, fullFileName) + newFile.createNewFile() + newFile + } + + def writeAll(text: String): Unit = File(file) writeAll text + + def moveContentToZip(zipName: String): Unit = { + val newZip = zipsDir createFile s"$zipName.zip" + val outputStream = new ZipOutputStream(new FileOutputStream(newZip)) + + def addFileToZip(dirPrefix: String = "")(fileToAdd: JFile): Unit = + if (fileToAdd.isDirectory) { + val dirEntryName = fileToAdd.getName + "/" + outputStream.putNextEntry(new ZipEntry(dirEntryName)) + fileToAdd.listFiles() foreach addFileToZip(dirEntryName) + } else { + val inputStream = new FileInputStream(fileToAdd) + outputStream.putNextEntry(new ZipEntry(dirPrefix + fileToAdd.getName)) + + val buffer = new Array[Byte](1024) + var count = inputStream.read(buffer) + while (count > 0) { + outputStream.write(buffer, 0, count) + count = inputStream.read(buffer) + } + + inputStream.close() + } + + file.listFiles() foreach addFileToZip() + outputStream.close() + + cleanDir(file) + } + + def moveContentToJar(jarName: String): Unit = { + val newJar = jarsDir createFile s"$jarName.jar" + Jar.create(file = File(newJar), sourceDir = Directory(file), mainClass = "won't be used") + cleanDir(file) + } + + def path: String = file.getAbsolutePath + } + + private case class DirRep(name: String, nestedDirs: Seq[DirRep] = Nil, sourceFiles: Seq[String] = Nil) + + private val compiler = new scala.tools.nsc.MainClass + private val appRunner = new scala.tools.nsc.MainGenericRunner + private val classPathImplFlag = "-YclasspathImpl:flat" + private val javaClassPath = sys.props("java.class.path") + + // creates a test dir in a temporary dir containing compiled files of this test + // root dir will be automatically deleted after the end of test + private val rootDir = new JFile(sys.props("partest.output")) + private val testDir = rootDir createDir s"cp-tests-${System.currentTimeMillis()}" + + private val jarsDir = testDir createDir "jars" + private val zipsDir = testDir createDir "zips" + private val srcDir = testDir createDir "src" + private val binDir = testDir createDir "bin" + private val outDir = testDir createDir "out" + + def main(args: Array[String]): Unit = { + createClassesZipInZipsDir() + createClassesJarInJarsDir() + createClassesInBinDir() + createSourcesZipInZipsDir() + createSourcesJarInJarsDir() + createSourcesInSrcDir() + compileFinalApp() + runApp() + // at the end all created files will be deleted automatically + } + + private def createClassesZipInZipsDir(): Unit = { + val baseFileName = "ZipBin" + createStandardSrcHierarchy(baseFileName) + compileSrc(baseFileName) + outDir moveContentToZip "Bin" + cleanDir(srcDir) + } + + private def createClassesJarInJarsDir(): Unit = { + val baseFileName = "JarBin" + createStandardSrcHierarchy(baseFileName) + compileSrc(baseFileName) + outDir moveContentToJar "Bin" + cleanDir(srcDir) + } + + private def createClassesInBinDir(): Unit = { + val baseFileName = "DirBin" + createStandardSrcHierarchy(baseFileName) + compileSrc(baseFileName, destination = binDir) + cleanDir(srcDir) + } + + private def createSourcesZipInZipsDir(): Unit = { + createStandardSrcHierarchy(baseFileName = "ZipSrc") + srcDir moveContentToZip "Src" + } + + private def createSourcesJarInJarsDir(): Unit = { + createStandardSrcHierarchy(baseFileName = "JarSrc") + srcDir moveContentToJar "Src" + } + + private def createSourcesInSrcDir(): Unit = { + createStandardSrcHierarchy(baseFileName = "DirSrc") + + val appFile = srcDir createSrcFile "Main" + appFile writeAll s"""import nested._ + | object Main extends App { + | println(new ZipBin) + | println(new JarBin) + | println(new DirBin) + | println(new ZipSrc) + | println(new JarSrc) + | println(new DirSrc) + | + | println(new NestedZipBin) + | println(new NestedJarBin) + | println(new NestedDirBin) + | println(new NestedZipSrc) + | println(new NestedJarSrc) + | println(new NestedDirSrc) + | } + """.stripMargin + } + + private def compileFinalApp(): Unit = { + val classPath = mkPath(javaClassPath, binDir.path, zipsDir.path + "/Bin.zip", jarsDir.path + "/Bin.jar") + val sourcePath = mkPath(srcDir.path, zipsDir.path + "/Src.zip", jarsDir.path + "/Src.jar") + + compiler.process(Array(classPathImplFlag, "-cp", classPath, "-sourcepath", sourcePath, + "-d", outDir.path, s"${srcDir.path}/Main.scala")) + } + + private def runApp(): Unit = { + val classPath = mkPath(javaClassPath, outDir.path, binDir.path, zipsDir.path + "/Bin.zip", jarsDir.path + "/Bin.jar") + appRunner.process(Array(classPathImplFlag, "-cp", classPath, "Main")) + } + + private def createStandardSrcHierarchy(baseFileName: String): Unit = + createSources(RootPackage, srcDir, + DirRep("", + nestedDirs = Seq(DirRep("nested", sourceFiles = Seq("Nested" + baseFileName))), + sourceFiles = Seq(baseFileName) + ) + ) + + private def createSources(pkg: String, dirFile: JFile, dirRep: DirRep): Unit = { + dirRep.nestedDirs foreach { rep => + val nestedDir = dirFile createDir rep.name + val nestedPkg = PackageNameUtils.packagePrefix(pkg) + rep.name + createSources(nestedPkg, nestedDir, rep) + } + + val pkgHeader = if (pkg == RootPackage) "" else s"package $pkg\n\n" + dirRep.sourceFiles foreach { srcName => + val text = s"""${pkgHeader}case class $srcName(x: String = "")""" + val srcFile = dirFile createSrcFile srcName + srcFile writeAll text + } + } + + private def compileSrc(baseFileName: String, destination: JFile = outDir): Unit = { + val srcDirPath = srcDir.path + compiler.process(Array(classPathImplFlag, "-cp", javaClassPath, "-d", destination.path, + s"$srcDirPath/$baseFileName.scala", s"$srcDirPath/nested/Nested$baseFileName.scala")) + } + + private def cleanDir(dir: JFile): Unit = + dir.listFiles().foreach { file => + if (file.isDirectory) cleanDir(file) + file.delete() + } + + private def mkPath(pathEntries: String*) = pathEntries.mkString(File.pathSeparator) +} diff --git a/test/files/scalacheck/nan-ordering.scala b/test/files/scalacheck/nan-ordering.scala index 2094a46e37..05e97a13c9 100644 --- a/test/files/scalacheck/nan-ordering.scala +++ b/test/files/scalacheck/nan-ordering.scala @@ -42,16 +42,16 @@ object Test extends Properties("NaN-Ordering") { property("Float equiv") = forAll(specFloats, specFloats) { (d1, d2) => numFloat.equiv(d1, d2) == (d1 == d2) } property("Float reverse.min") = forAll(specFloats, specFloats) { (d1, d2) => { - val mathmin = math.min(d1, d2) + val mathmax = math.max(d1, d2) val numericmin = numFloat.reverse.min(d1, d2) - mathmin == numericmin || mathmin.isNaN && numericmin.isNaN + mathmax == numericmin || mathmax.isNaN && numericmin.isNaN } } property("Float reverse.max") = forAll(specFloats, specFloats) { (d1, d2) => { - val mathmax = math.max(d1, d2) + val mathmin = math.min(d1, d2) val numericmax = numFloat.reverse.max(d1, d2) - mathmax == numericmax || mathmax.isNaN && numericmax.isNaN + mathmin == numericmax || mathmin.isNaN && numericmax.isNaN } } @@ -105,16 +105,16 @@ object Test extends Properties("NaN-Ordering") { property("Double equiv") = forAll(specDoubles, specDoubles) { (d1, d2) => numDouble.equiv(d1, d2) == (d1 == d2) } property("Double reverse.min") = forAll(specDoubles, specDoubles) { (d1, d2) => { - val mathmin = math.min(d1, d2) + val mathmax = math.max(d1, d2) val numericmin = numDouble.reverse.min(d1, d2) - mathmin == numericmin || mathmin.isNaN && numericmin.isNaN + mathmax == numericmin || mathmax.isNaN && numericmin.isNaN } } property("Double reverse.max") = forAll(specDoubles, specDoubles) { (d1, d2) => { - val mathmax = math.max(d1, d2) + val mathmin = math.min(d1, d2) val numericmax = numDouble.reverse.max(d1, d2) - mathmax == numericmax || mathmax.isNaN && numericmax.isNaN + mathmin == numericmax || mathmin.isNaN && numericmax.isNaN } } diff --git a/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala b/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala index 774d6f428b..468bcb6dd1 100644 --- a/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala +++ b/test/files/scalacheck/parallel-collections/ParallelIterableCheck.scala @@ -36,7 +36,7 @@ abstract class ParallelIterableCheck[T](collName: String) extends Properties(col // used to check if constructed collection is valid def checkDataStructureInvariants(orig: Traversable[T], cf: AnyRef) = { - // can be overriden in subclasses + // can be overridden in subclasses true } diff --git a/test/instrumented/library/scala/runtime/ScalaRunTime.scala b/test/instrumented/library/scala/runtime/ScalaRunTime.scala index e474ae737c..6b45a4e9f3 100644 --- a/test/instrumented/library/scala/runtime/ScalaRunTime.scala +++ b/test/instrumented/library/scala/runtime/ScalaRunTime.scala @@ -261,7 +261,7 @@ object ScalaRunTime { * * The primary motivation for this method is to provide a means for * correctly obtaining a String representation of a value, while - * avoiding the pitfalls of naïvely calling toString on said value. + * avoiding the pitfalls of naively calling toString on said value. * In particular, it addresses the fact that (a) toString cannot be * called on null and (b) depending on the apparent type of an * array, toString may or may not print it in a human-readable form. diff --git a/test/junit/scala/StringContextTest.scala b/test/junit/scala/StringContextTest.scala index 608b82bd96..7e9e775d58 100644 --- a/test/junit/scala/StringContextTest.scala +++ b/test/junit/scala/StringContextTest.scala @@ -65,14 +65,23 @@ class StringContextTest { @Test def fIf() = { val res = f"${if (true) 2.5 else 2.5}%.2f" - assertEquals("2.50", res) + val expected = formatUsingCurrentLocale(2.50) + assertEquals(expected, res) } + @Test def fIfNot() = { val res = f"${if (false) 2.5 else 3.5}%.2f" - assertEquals("3.50", res) + val expected = formatUsingCurrentLocale(3.50) + assertEquals(expected, res) } + @Test def fHeteroArgs() = { val res = f"${3.14}%.2f rounds to ${3}%d" - assertEquals("3.14 rounds to 3", res) + val expected = formatUsingCurrentLocale(3.14) + " rounds to 3" + assertEquals(expected, res) } + + // Use this method to avoid problems with a locale-dependent decimal mark. + // The string interpolation is not used here intentionally as this method is used to test string interpolation. + private def formatUsingCurrentLocale(number: Double, decimalPlaces: Int = 2) = ("%." + decimalPlaces + "f").format(number) } diff --git a/test/junit/scala/collection/IterableViewLikeTest.scala b/test/junit/scala/collection/IterableViewLikeTest.scala index 55da02744b..ab09c4930b 100644 --- a/test/junit/scala/collection/IterableViewLikeTest.scala +++ b/test/junit/scala/collection/IterableViewLikeTest.scala @@ -4,6 +4,7 @@ import org.junit.Assert._ import org.junit.Test import org.junit.runner.RunWith import org.junit.runners.JUnit4 +import language.postfixOps @RunWith(classOf[JUnit4]) class IterableViewLikeTest { diff --git a/test/junit/scala/collection/TraversableOnceTest.scala b/test/junit/scala/collection/TraversableOnceTest.scala index 56d8312336..196174c199 100644 --- a/test/junit/scala/collection/TraversableOnceTest.scala +++ b/test/junit/scala/collection/TraversableOnceTest.scala @@ -43,8 +43,8 @@ class TraversableOnceTest { def testReturnTheFirstMatch() = { val d = List(1, 2, 3, 4, 5, 6, 7, 8) def f(x: Int) = x % 3; - assert(d.maxBy(f) == 2, "If multiple elements evaluted to the largest value, maxBy should return the first one.") - assert(d.minBy(f) == 3, "If multiple elements evaluted to the largest value, minBy should return the first one.") + assert(d.maxBy(f) == 2, "If multiple elements evaluated to the largest value, maxBy should return the first one.") + assert(d.minBy(f) == 3, "If multiple elements evaluated to the largest value, minBy should return the first one.") } // Make sure it evaluates f no more than list.length times. @@ -56,7 +56,7 @@ class TraversableOnceTest { evaluatedCountOfMaxBy += 1 x * 10 }) - assert(evaluatedCountOfMaxBy == list.length, s"maxBy: should evaluate f only ${list.length} times, but it evaluted $evaluatedCountOfMaxBy times.") + assert(evaluatedCountOfMaxBy == list.length, s"maxBy: should evaluate f only ${list.length} times, but it evaluated $evaluatedCountOfMaxBy times.") var evaluatedCountOfMinBy = 0 @@ -64,7 +64,7 @@ class TraversableOnceTest { evaluatedCountOfMinBy += 1 x * 10 }) - assert(evaluatedCountOfMinBy == list.length, s"minBy: should evaluate f only ${list.length} times, but it evaluted $evaluatedCountOfMinBy times.") + assert(evaluatedCountOfMinBy == list.length, s"minBy: should evaluate f only ${list.length} times, but it evaluated $evaluatedCountOfMinBy times.") } } diff --git a/test/junit/scala/collection/immutable/ListTest.scala b/test/junit/scala/collection/immutable/ListTest.scala new file mode 100644 index 0000000000..1006801029 --- /dev/null +++ b/test/junit/scala/collection/immutable/ListTest.scala @@ -0,0 +1,49 @@ +package scala.collection.immutable + +import org.junit.{Assert, Test} +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.ref.WeakReference + +@RunWith(classOf[JUnit4]) +class ListTest { + /** + * Test that empty iterator does not hold reference + * to complete List + */ + @Test + def testIteratorGC(): Unit = { + var num = 0 + var emptyIterators = Seq.empty[(Iterator[Int], WeakReference[List[Int]])] + + do { + val list = List.fill(10000)(num) + val ref = WeakReference(list) + + val i = list.iterator + + while (i.hasNext) i.next() + + emptyIterators = (i, ref) +: emptyIterators + + num+=1 + } while (emptyIterators.forall(_._2.get.isDefined) && num<1000) + + // check something is result to protect from JIT optimizations + for ((i, _) <- emptyIterators) { + Assert.assertTrue(i.isEmpty) + } + + // await gc up to ~5 seconds + var forceLoops = 50 + while (emptyIterators.forall(_._2.get.isDefined) && forceLoops>0) { + System.gc() + Thread.sleep(100) + forceLoops -= 1 + } + + // real assertion + Assert.assertTrue(emptyIterators.exists(_._2.get.isEmpty)) + } +} diff --git a/test/junit/scala/collection/immutable/PagedSeqTest.scala b/test/junit/scala/collection/immutable/PagedSeqTest.scala index 5f83cf6f31..2b576a3655 100644 --- a/test/junit/scala/collection/immutable/PagedSeqTest.scala +++ b/test/junit/scala/collection/immutable/PagedSeqTest.scala @@ -5,12 +5,24 @@ import org.junit.runners.JUnit4 import org.junit.Test import org.junit.Assert._ -/* Test for SI-6615 */ @RunWith(classOf[JUnit4]) class PagedSeqTest { + // should not NPE, and should equal the given Seq @Test - def rovingDoesNotNPE(): Unit = { - // should not NPE, and should equal the given Seq + def test_SI6615(): Unit = { assertEquals(Seq('a'), PagedSeq.fromStrings(List.fill(5000)("a")).slice(4096, 4097)) } + + // Slices shouldn't read outside where they belong + @Test + def test_SI6519 { + var readAttempt = 0 + val sideEffectingIterator = new Iterator[Int] { + def hasNext = readAttempt < 65536 + def next = { readAttempt += 1; readAttempt } + } + val s = PagedSeq.fromIterator(sideEffectingIterator).slice(0,2).mkString + assertEquals(s, "12") + assert(readAttempt <= 4096) + } } diff --git a/test/junit/scala/collection/immutable/VectorTest.scala b/test/junit/scala/collection/immutable/VectorTest.scala new file mode 100644 index 0000000000..e7edba3e43 --- /dev/null +++ b/test/junit/scala/collection/immutable/VectorTest.scala @@ -0,0 +1,20 @@ +package scala.collection.immutable + +import org.junit.{Assert, Test} +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(classOf[JUnit4]) +class VectorTest { + /** + * Test Vector ++ with a small parallel collection concatenation (SI-9072). + * + */ + @Test + def testPlusPlus(): Unit = { + val smallVec = (0 to 1) + val smallParVec = smallVec.par + val testElementsSize = (0 to 1000).map( _ => Vector.empty ++ smallParVec ) + Assert.assertTrue(testElementsSize.forall( v => v.size == 2 )) + } +} diff --git a/test/junit/scala/collection/mutable/ArrayBufferTest.scala b/test/junit/scala/collection/mutable/ArrayBufferTest.scala new file mode 100644 index 0000000000..8c83164027 --- /dev/null +++ b/test/junit/scala/collection/mutable/ArrayBufferTest.scala @@ -0,0 +1,36 @@ +package scala.collection.mutable + +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.{Assert, Test} + +import scala.tools.testing.AssertUtil + +/* Test for SI-9043 */ +@RunWith(classOf[JUnit4]) +class ArrayBufferTest { + @Test + def testInsertAll: Unit = { + val traver = ArrayBuffer(2, 4, 5, 7) + val testSeq = List(1, 3, 6, 9) + + def insertAt(x: Int) = { + val clone = traver.clone() + clone.insertAll(x, testSeq) + clone + } + + // Just insert some at position 0 + Assert.assertEquals(ArrayBuffer(1, 3, 6, 9, 2, 4, 5, 7), insertAt(0)) + + // Insert in the middle + Assert.assertEquals(ArrayBuffer(2, 4, 1, 3, 6, 9, 5, 7), insertAt(2)) + + // No strange last position weirdness + Assert.assertEquals(ArrayBuffer(2, 4, 5, 7, 1, 3, 6, 9), insertAt(traver.size)) + + // Overflow is caught + AssertUtil.assertThrows[IndexOutOfBoundsException] { insertAt(-1) } + AssertUtil.assertThrows[IndexOutOfBoundsException] { insertAt(traver.size + 10) } + } +} diff --git a/test/junit/scala/io/SourceTest.scala b/test/junit/scala/io/SourceTest.scala new file mode 100644 index 0000000000..3138a4589c --- /dev/null +++ b/test/junit/scala/io/SourceTest.scala @@ -0,0 +1,86 @@ + +package scala.io + +import org.junit.Test +import org.junit.Assert._ +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.tools.testing.AssertUtil._ + +import java.io.{ Console => _, _ } + +@RunWith(classOf[JUnit4]) +class SourceTest { + + private implicit val `our codec` = Codec.UTF8 + private val charSet = Codec.UTF8.charSet.name + + private def sampler = """ + |Big-endian and little-endian approaches aren't + |readily interchangeable in general, because the + |laws of arithmetic send signals leftward from + |the bits that are "least significant." + |""".stripMargin.trim + + private def in = new ByteArrayInputStream(sampler.getBytes) + + @Test def canIterateLines() = { + assertEquals(sampler.lines.size, (Source fromString sampler).getLines.size) + } + @Test def canCustomizeReporting() = { + class CapitalReporting(is: InputStream) extends BufferedSource(is) { + override def report(pos: Int, msg: String, out: PrintStream): Unit = { + out print f"$pos%04x: ${msg.toUpperCase}" + } + class OffsetPositioner extends Positioner(null) { + override def next(): Char = { + ch = iter.next() + pos = pos + 1 + ch + } + } + withPositioning(new OffsetPositioner) + } + val s = new CapitalReporting(in) + // skip to next line and report an error + do { + val c = s.next() + } while (s.ch != '\n') + s.next() + val out = new ByteArrayOutputStream + val ps = new PrintStream(out, true, charSet) + s.reportError(s.pos, "That doesn't sound right.", ps) + assertEquals("0030: THAT DOESN'T SOUND RIGHT.", out.toString(charSet)) + } + @Test def canAltCustomizeReporting() = { + class CapitalReporting(is: InputStream)(implicit codec: Codec) extends Source { + override val iter = { + val r = new InputStreamReader(is, codec.decoder) + Iterator continually (codec wrap r.read()) takeWhile (_ != -1) map (_.toChar) + } + override def report(pos: Int, msg: String, out: PrintStream): Unit = { + out print f"$pos%04x: ${msg.toUpperCase}" + } + private[this] var _pos: Int = _ + override def pos = _pos + private[this] var _ch: Char = _ + override def ch = _ch + override def next = { + _ch = iter.next() + _pos += 1 + _ch + } + } + val s = new CapitalReporting(in) + // skip to next line and report an error + do { + val c = s.next() + } while (s.ch != '\n') + s.next() + val out = new ByteArrayOutputStream + val ps = new PrintStream(out, true, charSet) + s.reportError(s.pos, "That doesn't sound right.", ps) + assertEquals("0030: THAT DOESN'T SOUND RIGHT.", out.toString(charSet)) + } +} diff --git a/test/junit/scala/math/BigDecimalTest.scala b/test/junit/scala/math/BigDecimalTest.scala index d1ba96fcc8..c7a63da890 100644 --- a/test/junit/scala/math/BigDecimalTest.scala +++ b/test/junit/scala/math/BigDecimalTest.scala @@ -222,4 +222,10 @@ class BigDecimalTest { for (a <- different; b <- different if (a ne b)) assert(a != b, "BigDecimal representations of Double mistakenly conflated") } + + // Make sure hash code agrees with decimal representation of Double + @Test + def test_SI8970() { + assert((0.1).## == BigDecimal(0.1).##) + } } diff --git a/test/junit/scala/math/OrderingTest.scala b/test/junit/scala/math/OrderingTest.scala new file mode 100644 index 0000000000..218622b8b4 --- /dev/null +++ b/test/junit/scala/math/OrderingTest.scala @@ -0,0 +1,61 @@ +package scala.math + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +@RunWith(classOf[JUnit4]) +class OrderingTest { + + /* Test for SI-9077 */ + @Test + def testReverseOrdering { + def check[T: Ordering](t1: T, t2: T): Unit = { + val O = Ordering[T] + val R = O.reverse + assertEquals(O.min(t1, t2), R.max(t1, t2)) + assertEquals(O.max(t1, t2), R.min(t1, t2)) + + assertEquals(O.lteq(t1, t2), R.lteq(t2, t1)) + assertEquals(O.lt(t1, t2), R.lt(t2, t1)) + assertEquals(O.gteq(t1, t2), R.gteq(t2, t1)) + assertEquals(O.gt(t1, t2), R.gt(t2, t1)) + assertEquals(O.compare(t1, t2), R.compare(t2, t1)) + + assertEquals(O.equiv(t1, t2), R.equiv(t1, t2)) + + assertEquals(O.on((x: T) => x).min(t1, t2), R.on((x: T) => x).max(t1, t2)) + + assertEquals(O.tryCompare(t1, t2), R.tryCompare(t2, t1)) + + assertEquals(O.mkOrderingOps(t1).<(t2), R.mkOrderingOps(t2).<(t1)) + assertEquals(O.mkOrderingOps(t1).<=(t2), R.mkOrderingOps(t2).<=(t1)) + assertEquals(O.mkOrderingOps(t1).>(t2), R.mkOrderingOps(t2).>(t1)) + assertEquals(O.mkOrderingOps(t1).>=(t2), R.mkOrderingOps(t2).>=(t1)) + + assertEquals(O.mkOrderingOps(t1).min(t2), R.mkOrderingOps(t1).max(t2)) + assertEquals(O.mkOrderingOps(t1).max(t2), R.mkOrderingOps(t1).min(t2)) + } + def checkAll[T: Ordering](ts: T*): Unit = { + for (t1 <- ts; t2 <- ts) check(t1, t2) + } + checkAll[Unit](()) + checkAll[Boolean](true, false) + checkAll[Byte](Byte.MinValue, -1.toByte, 0.toByte, 1.toByte, Byte.MaxValue) + checkAll[Char](Char.MinValue, -1.toChar, 0.toChar, 1.toChar, Char.MaxValue) + checkAll[Short](Short.MinValue, -1, 0, 1, Short.MaxValue) + checkAll[Int](Int.MinValue, -1, 0, 1, Int.MaxValue) + checkAll[Double](Double.MinValue, -1, -0, 0, 1, Double.MaxValue) + checkAll[Float](Float.MinValue, -1, -0, 0, 1, Float.MaxValue) + + checkAll[BigInt](Int.MinValue, -1, 0, 1, Int.MaxValue) + checkAll[BigDecimal](Int.MinValue, -1, -0, 1, Int.MaxValue) + checkAll[String]("", "a", "b", "bb") + checkAll[String]("", "a", "b", "bb") + checkAll[Option[Int]](None, Some(1), Some(2)) + checkAll[Iterable[Int]](Nil, List(1), List(1, 2)) + checkAll[(Int, Int)]((1, 2), (1, 3), (4, 5)) + } +} + diff --git a/test/junit/scala/reflect/internal/PrintersTest.scala b/test/junit/scala/reflect/internal/PrintersTest.scala index 7043c26d5e..9bfe6eecb8 100644 --- a/test/junit/scala/reflect/internal/PrintersTest.scala +++ b/test/junit/scala/reflect/internal/PrintersTest.scala @@ -125,6 +125,8 @@ trait BasePrintTests { @Test def testName19 = assertPrintedCode("""class `class`""") @Test def testName20 = assertPrintedCode("""class `test name`""") + + @Test def testName21 = assertPrintedCode("""class `test.name`""") @Test def testIfExpr1 = assertResultCode(code = sm""" |val a = 1 diff --git a/test/junit/scala/tools/nsc/SampleTest.scala b/test/junit/scala/tools/nsc/SampleTest.scala index 810c88ef9d..60bb09e98f 100644 --- a/test/junit/scala/tools/nsc/SampleTest.scala +++ b/test/junit/scala/tools/nsc/SampleTest.scala @@ -11,6 +11,6 @@ import org.junit.runners.JUnit4 class SampleTest { @Test def testMath: Unit = { - assert(2+2 == 4, "you didn't get the math right fellow") + assertTrue("you didn't get the math right fellow", 2 + 2 == 4) } } diff --git a/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala b/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala index 221aad6536..2347e8288e 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/BTypesTest.scala @@ -19,7 +19,7 @@ class BTypesTest { val btypes = new BTypesFromSymbols[g.type](g) import btypes._ - duringBackend(btypes.intializeCoreBTypes()) + duringBackend(btypes.initializeCoreBTypes()) def classBTypeFromSymbol(sym: Symbol) = duringBackend(btypes.classBTypeFromSymbol(sym)) diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala new file mode 100644 index 0000000000..2975bd060d --- /dev/null +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/BTypesFromClassfileTest.scala @@ -0,0 +1,95 @@ +package scala.tools.nsc +package backend.jvm +package opt + +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import org.junit.Test +import scala.tools.asm.Opcodes._ +import org.junit.Assert._ + +import scala.tools.nsc.backend.jvm.BTypes.InternalName +import scala.tools.testing.AssertUtil._ + +import CodeGenTools._ +import scala.tools.partest.ASMConverters +import ASMConverters._ + +import scala.collection.convert.decorateAsScala._ + +@RunWith(classOf[JUnit4]) +class BTypesFromClassfileTest { + val compiler = newCompiler(extraArgs = "-Ybackend:GenBCode") + + import compiler._ + import definitions._ + import genBCode.bTypes + import bTypes._ + + def duringBackend[T](f: => T) = compiler.exitingDelambdafy(f) + + val run = new compiler.Run() // initializes some of the compiler + duringBackend(bTypes.initializeCoreBTypes()) + + def clearCache() = bTypes.classBTypeFromInternalName.clear() + + def sameBType(fromSym: ClassBType, fromClassfile: ClassBType, checked: Set[InternalName] = Set.empty): Set[InternalName] = { + if (checked(fromSym.internalName)) checked + else { + assert(fromSym == fromClassfile, s"$fromSym != $fromClassfile") + sameInfo(fromSym.info, fromClassfile.info, checked + fromSym.internalName) + } + } + + def sameBTypes(fromSyms: Iterable[ClassBType], fromClassfiles: Iterable[ClassBType], checked: Set[InternalName]): Set[InternalName] = { + assert(fromSyms.size == fromClassfiles.size, s"\n$fromSyms\n$fromClassfiles") + (fromSyms, fromClassfiles).zipped.foldLeft(checked) { + case (chk, (fromSym, fromClassfile)) => sameBType(fromSym, fromClassfile, chk) + } + } + + def sameInfo(fromSym: ClassInfo, fromClassfile: ClassInfo, checked: Set[InternalName]): Set[InternalName] = { + assert({ + // Nested class symbols can undergo makeNotPrivate (ExplicitOuter). But this is only applied + // for symbols of class symbols that are being compiled, not those read from a pickle. + // So a class may be public in bytecode, but the symbol still says private. + if (fromSym.nestedInfo.isEmpty) fromSym.flags == fromClassfile.flags + else (fromSym.flags | ACC_PRIVATE | ACC_PUBLIC) == (fromClassfile.flags | ACC_PRIVATE | ACC_PUBLIC) + }, s"class flags differ\n$fromSym\n$fromClassfile") + + val chk1 = sameBTypes(fromSym.superClass, fromClassfile.superClass, checked) + + val chk2 = sameBTypes(fromSym.interfaces, fromClassfile.interfaces, chk1) + + // The fromSym info has only member classes, no local or anonymous. The symbol is read from the + // Scala pickle data and only member classes are created / entered. + // (This is different for symbols that are being compiled, there flatten will enter all local + // and anonymous classes as members of the outer class. But not for unpickled symbols). + // The fromClassfile info has all nested classes, including anonymous and local. So we filter + // them out: member classes are identified by having the `outerName` defined. + val memberClassesFromClassfile = fromClassfile.nestedClasses.filter(_.info.nestedInfo.get.outerName.isDefined) + // Sorting is required: the backend sorts all InnerClass entries by internalName before writing + // them to the classfile (to make it deterministic: the entries are collected in a Set during + // code generation). + val chk3 = sameBTypes(fromSym.nestedClasses.sortBy(_.internalName), memberClassesFromClassfile.sortBy(_.internalName), chk2) + sameBTypes(fromSym.nestedInfo.map(_.enclosingClass), fromClassfile.nestedInfo.map(_.enclosingClass), chk3) + } + + def check(classSym: Symbol): Unit = duringBackend { + clearCache() + val fromSymbol = classBTypeFromSymbol(classSym) + clearCache() + val fromClassfile = bTypes.classBTypeFromParsedClassfile(fromSymbol.internalName) + sameBType(fromSymbol, fromClassfile) + } + + @Test + def compareClassBTypes(): Unit = { + // Note that not only these classes are tested, but also all their parents and all nested + // classes in their InnerClass attributes. + check(ObjectClass) + check(JavaNumberClass) + check(ConsClass) + check(ListModule.moduleClass) + } +} diff --git a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala index 5b0f0f238a..5430e33d6c 100644 --- a/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala +++ b/test/junit/scala/tools/nsc/backend/jvm/opt/MethodLevelOpts.scala @@ -74,7 +74,7 @@ class MethodLevelOpts { """.stripMargin val m = singleMethod(methodOptCompiler)(code) assertTrue(m.handlers.length == 2) - assertSameCode(m.instructions.dropNonOp, // drop line numbers and lables that are only used by line numbers + assertSameCode(m.instructions.dropNonOp, // drop line numbers and labels that are only used by line numbers // one single label left :-) List(Op(ICONST_1), VarOp(ISTORE, 2), Jump(GOTO, Label(20)), Op(POP), Op(ICONST_2), VarOp(ISTORE, 2), Jump(GOTO, Label(20)), VarOp(ASTORE, 3), Op(ICONST_2), Op(IRETURN), Label(20), Op(ICONST_2), Op(IRETURN)) diff --git a/test/junit/scala/tools/nsc/classpath/AggregateFlatClassPathTest.scala b/test/junit/scala/tools/nsc/classpath/AggregateFlatClassPathTest.scala new file mode 100644 index 0000000000..9a004d5e0e --- /dev/null +++ b/test/junit/scala/tools/nsc/classpath/AggregateFlatClassPathTest.scala @@ -0,0 +1,208 @@ +/* + * Copyright (c) 2014 Contributor. All rights reserved. + */ +package scala.tools.nsc.classpath + +import java.net.URL +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import scala.reflect.io.VirtualFile +import scala.tools.nsc.io.AbstractFile + +/** + * Tests whether AggregateFlatClassPath returns correct entries taken from + * cp instances used during creating it and whether it preserves the ordering + * (in the case of the repeated entry for a class or a source it returns the first one). + */ +@RunWith(classOf[JUnit4]) +class AggregateFlatClassPathTest { + + private class TestFlatClassPath extends FlatClassPath { + override def packages(inPackage: String): Seq[PackageEntry] = unsupported + override def sources(inPackage: String): Seq[SourceFileEntry] = unsupported + override def classes(inPackage: String): Seq[ClassFileEntry] = unsupported + + override def list(inPackage: String): FlatClassPathEntries = unsupported + override def findClassFile(name: String): Option[AbstractFile] = unsupported + + override def asClassPathStrings: Seq[String] = unsupported + override def asSourcePathString: String = unsupported + override def asURLs: Seq[URL] = unsupported + } + + private case class TestClassPath(virtualPath: String, classesInPackage: EntryNamesInPackage*) extends TestFlatClassPath { + + override def classes(inPackage: String): Seq[ClassFileEntry] = + for { + entriesWrapper <- classesInPackage if entriesWrapper.inPackage == inPackage + name <- entriesWrapper.names + } yield classFileEntry(virtualPath, inPackage, name) + + override def sources(inPackage: String): Seq[SourceFileEntry] = Nil + + // we'll ignore packages + override def list(inPackage: String): FlatClassPathEntries = FlatClassPathEntries(Nil, classes(inPackage)) + } + + private case class TestSourcePath(virtualPath: String, sourcesInPackage: EntryNamesInPackage*) extends TestFlatClassPath { + + override def sources(inPackage: String): Seq[SourceFileEntry] = + for { + entriesWrapper <- sourcesInPackage if entriesWrapper.inPackage == inPackage + name <- entriesWrapper.names + } yield sourceFileEntry(virtualPath, inPackage, name) + + override def classes(inPackage: String): Seq[ClassFileEntry] = Nil + + // we'll ignore packages + override def list(inPackage: String): FlatClassPathEntries = FlatClassPathEntries(Nil, sources(inPackage)) + } + + private case class EntryNamesInPackage(inPackage: String)(val names: String*) + + private val dir1 = "./dir1" + private val dir2 = "./dir2" + private val dir3 = "./dir3" + private val dir4 = "" + + private val pkg1 = "pkg1" + private val pkg2 = "pkg2" + private val pkg3 = "pkg1.nested" + private val nonexistingPkg = "nonexisting" + + private def unsupported = throw new UnsupportedOperationException + + private def classFileEntry(pathPrefix: String, inPackage: String, fileName: String) = + ClassFileEntryImpl(classFile(pathPrefix, inPackage, fileName)) + + private def sourceFileEntry(pathPrefix: String, inPackage: String, fileName: String) = + SourceFileEntryImpl(sourceFile(pathPrefix, inPackage, fileName)) + + private def classFile(pathPrefix: String, inPackage: String, fileName: String) = + virtualFile(pathPrefix, inPackage, fileName, ".class") + + private def sourceFile(pathPrefix: String, inPackage: String, fileName: String) = + virtualFile(pathPrefix, inPackage, fileName, ".scala") + + private def virtualFile(pathPrefix: String, inPackage: String, fileName: String, extension: String) = { + val packageDirs = + if (inPackage == FlatClassPath.RootPackage) "" + else inPackage.split('.').mkString("/", "/", "") + new VirtualFile(fileName + extension, s"$pathPrefix$packageDirs/$fileName$extension") + } + + private def createDefaultTestClasspath() = { + val partialClassPaths = Seq(TestSourcePath(dir1, EntryNamesInPackage(pkg1)("F", "A", "G")), + TestClassPath(dir2, EntryNamesInPackage(pkg1)("C", "B", "A"), EntryNamesInPackage(pkg2)("D", "A", "E")), + TestClassPath(dir3, EntryNamesInPackage(pkg1)("A", "D", "F")), + TestSourcePath(dir4, EntryNamesInPackage(pkg2)("A", "H", "I"), EntryNamesInPackage(pkg1)("A")), + TestSourcePath(dir2, EntryNamesInPackage(pkg3)("J", "K", "L")) + ) + + AggregateFlatClassPath(partialClassPaths) + } + + @Test + def testGettingPackages: Unit = { + case class ClassPathWithPackages(packagesInPackage: EntryNamesInPackage*) extends TestFlatClassPath { + override def packages(inPackage: String): Seq[PackageEntry] = + packagesInPackage.find(_.inPackage == inPackage).map(_.names).getOrElse(Nil) map PackageEntryImpl + } + + val partialClassPaths = Seq(ClassPathWithPackages(EntryNamesInPackage(pkg1)("pkg1.a", "pkg1.d", "pkg1.f")), + ClassPathWithPackages(EntryNamesInPackage(pkg1)("pkg1.c", "pkg1.b", "pkg1.a"), + EntryNamesInPackage(pkg2)("pkg2.d", "pkg2.a", "pkg2.e")) + ) + val cp = AggregateFlatClassPath(partialClassPaths) + + val packagesInPkg1 = Seq("pkg1.a", "pkg1.d", "pkg1.f", "pkg1.c", "pkg1.b") + assertEquals(packagesInPkg1, cp.packages(pkg1).map(_.name)) + + val packagesInPkg2 = Seq("pkg2.d", "pkg2.a", "pkg2.e") + assertEquals(packagesInPkg2, cp.packages(pkg2).map(_.name)) + + assertEquals(Seq.empty, cp.packages(nonexistingPkg)) + } + + @Test + def testGettingClasses: Unit = { + val cp = createDefaultTestClasspath() + + val classesInPkg1 = Seq(classFileEntry(dir2, pkg1, "C"), + classFileEntry(dir2, pkg1, "B"), + classFileEntry(dir2, pkg1, "A"), + classFileEntry(dir3, pkg1, "D"), + classFileEntry(dir3, pkg1, "F") + ) + assertEquals(classesInPkg1, cp.classes(pkg1)) + + val classesInPkg2 = Seq(classFileEntry(dir2, pkg2, "D"), + classFileEntry(dir2, pkg2, "A"), + classFileEntry(dir2, pkg2, "E") + ) + assertEquals(classesInPkg2, cp.classes(pkg2)) + + assertEquals(Seq.empty, cp.classes(pkg3)) + assertEquals(Seq.empty, cp.classes(nonexistingPkg)) + } + + @Test + def testGettingSources: Unit = { + val partialClassPaths = Seq(TestClassPath(dir1, EntryNamesInPackage(pkg1)("F", "A", "G")), + TestSourcePath(dir2, EntryNamesInPackage(pkg1)("C", "B", "A"), EntryNamesInPackage(pkg2)("D", "A", "E")), + TestSourcePath(dir3, EntryNamesInPackage(pkg1)("A", "D", "F")), + TestClassPath(dir4, EntryNamesInPackage(pkg2)("A", "H", "I")), + TestClassPath(dir2, EntryNamesInPackage(pkg3)("J", "K", "L")) + ) + val cp = AggregateFlatClassPath(partialClassPaths) + + val sourcesInPkg1 = Seq(sourceFileEntry(dir2, pkg1, "C"), + sourceFileEntry(dir2, pkg1, "B"), + sourceFileEntry(dir2, pkg1, "A"), + sourceFileEntry(dir3, pkg1, "D"), + sourceFileEntry(dir3, pkg1, "F") + ) + assertEquals(sourcesInPkg1, cp.sources(pkg1)) + + val sourcesInPkg2 = Seq(sourceFileEntry(dir2, pkg2, "D"), + sourceFileEntry(dir2, pkg2, "A"), + sourceFileEntry(dir2, pkg2, "E") + ) + assertEquals(sourcesInPkg2, cp.sources(pkg2)) + + assertEquals(Seq.empty, cp.sources(pkg3)) + assertEquals(Seq.empty, cp.sources(nonexistingPkg)) + } + + @Test + def testList: Unit = { + val cp = createDefaultTestClasspath() + + val classesAndSourcesInPkg1 = Seq( + ClassAndSourceFilesEntry(classFile(dir3, pkg1, "F"), sourceFile(dir1, pkg1, "F")), + ClassAndSourceFilesEntry(classFile(dir2, pkg1, "A"), sourceFile(dir1, pkg1, "A")), + sourceFileEntry(dir1, pkg1, "G"), + classFileEntry(dir2, pkg1, "C"), + classFileEntry(dir2, pkg1, "B"), + classFileEntry(dir3, pkg1, "D") + ) + assertEquals(classesAndSourcesInPkg1, cp.list(pkg1).classesAndSources) + + assertEquals(FlatClassPathEntries(Nil, Nil), cp.list(nonexistingPkg)) + } + + @Test + def testFindClass: Unit = { + val cp = createDefaultTestClasspath() + + assertEquals( + Some(ClassAndSourceFilesEntry(classFile(dir2, pkg1, "A"), sourceFile(dir1, pkg1, "A"))), + cp.findClass(s"$pkg1.A") + ) + assertEquals(Some(classFileEntry(dir3, pkg1, "D")), cp.findClass(s"$pkg1.D")) + assertEquals(Some(sourceFileEntry(dir2, pkg3, "L")), cp.findClass(s"$pkg3.L")) + assertEquals(None, cp.findClass("Nonexisting")) + } +} diff --git a/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala b/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala new file mode 100644 index 0000000000..a37ba31b31 --- /dev/null +++ b/test/junit/scala/tools/nsc/classpath/FlatClassPathResolverTest.scala @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2014 Contributor. All rights reserved. + */ +package scala.tools.nsc.classpath + +import java.io.File +import org.junit.Assert._ +import org.junit._ +import org.junit.rules.TemporaryFolder +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 +import scala.annotation.tailrec +import scala.tools.nsc.io.AbstractFile +import scala.tools.nsc.util.ClassPath +import scala.tools.nsc.Settings +import scala.tools.util.FlatClassPathResolver +import scala.tools.util.PathResolver + +@RunWith(classOf[JUnit4]) +class FlatClassPathResolverTest { + + val tempDir = new TemporaryFolder() + + private val packagesToTest = List(FlatClassPath.RootPackage, "scala", "scala.reflect", "scala.reflect.io") + private val classFilesToFind = List("scala.tools.util.FlatClassPathResolver", + "scala.reflect.io.AbstractFile", + "scala.collection.immutable.List", + "scala.Option", + "scala.collection.immutable.Vector", + "scala.util.hashing.MurmurHash3", + "java.lang.Object", + "java.util.Date") + + private val classesToFind = classFilesToFind ++ List("TestSourceInRootPackage", + "scala.reflect.io.TestScalaSource", + "scala.reflect.io.TestJavaSource") + + private val settings = new Settings + + @Before + def initTempDirAndSourcePath: Unit = { + // In Java TemporaryFolder in JUnit is managed automatically using @Rule. + // It would work also in Scala after adding and extending a class like + // TestWithTempFolder.java containing it. But in this case it doesn't work when running tests + // from the command line - java class is not compiled due to some, misterious reasons. + // That's why such dirs are here created and deleted manually. + tempDir.create() + tempDir.newFile("TestSourceInRootPackage.scala") + val ioDir = tempDir.newFolder("scala", "reflect", "io") + new File(ioDir, "AbstractFile.scala").createNewFile() + new File(ioDir, "ZipArchive.java").createNewFile() + new File(ioDir, "TestScalaSource.scala").createNewFile() + new File(ioDir, "TestJavaSource.java").createNewFile() + + settings.usejavacp.value = true + settings.sourcepath.value = tempDir.getRoot.getAbsolutePath + } + + @After + def deleteTempDir: Unit = tempDir.delete() + + private def createFlatClassPath(settings: Settings) = + new FlatClassPathResolver(settings).result + + @Test + def testEntriesFromListOperationAgainstSeparateMethods: Unit = { + val classPath = createFlatClassPath(settings) + + def compareEntriesInPackage(inPackage: String): Unit = { + val packages = classPath.packages(inPackage) + val classes = classPath.classes(inPackage) + val sources = classPath.sources(inPackage) + val FlatClassPathEntries(packagesFromList, classesAndSourcesFromList) = classPath.list(inPackage) + + val packageNames = packages.map(_.name).sorted + val packageNamesFromList = packagesFromList.map(_.name).sorted + assertEquals(s"Methods list and packages for package '$inPackage' should return the same packages", + packageNames, packageNamesFromList) + + val classFileNames = classes.map(_.name).sorted + val classFileNamesFromList = classesAndSourcesFromList.filter(_.binary.isDefined).map(_.name).sorted + assertEquals(s"Methods list and classes for package '$inPackage' should return entries for the same class files", + classFileNames, classFileNamesFromList) + + val sourceFileNames = sources.map(_.name).sorted + val sourceFileNamesFromList = classesAndSourcesFromList.filter(_.source.isDefined).map(_.name).sorted + assertEquals(s"Methods list and sources for package '$inPackage' should return entries for the same source files", + sourceFileNames, sourceFileNamesFromList) + + val uniqueNamesOfClassAndSourceFiles = (classFileNames ++ sourceFileNames).toSet + assertEquals(s"Class and source entries with the same name obtained via list for package '$inPackage' should be merged into one containing both files", + uniqueNamesOfClassAndSourceFiles.size, classesAndSourcesFromList.length) + } + + packagesToTest foreach compareEntriesInPackage + } + + @Test + def testCreatedEntriesAgainstRecursiveClassPath: Unit = { + val flatClassPath = createFlatClassPath(settings) + val recursiveClassPath = new PathResolver(settings).result + + def compareEntriesInPackage(inPackage: String): Unit = { + + @tailrec + def traverseToPackage(packageNameParts: Seq[String], cp: ClassPath[AbstractFile]): ClassPath[AbstractFile] = { + packageNameParts match { + case Nil => cp + case h :: t => + cp.packages.find(_.name == h) match { + case Some(nestedCp) => traverseToPackage(t, nestedCp) + case _ => throw new Exception(s"There's no package $inPackage in recursive classpath - error when searching for '$h'") + } + } + } + + val packageNameParts = if (inPackage == FlatClassPath.RootPackage) Nil else inPackage.split('.').toList + val recursiveClassPathInPackage = traverseToPackage(packageNameParts, recursiveClassPath) + + val flatCpPackages = flatClassPath.packages(inPackage).map(_.name) + val pkgPrefix = PackageNameUtils.packagePrefix(inPackage) + val recursiveCpPackages = recursiveClassPathInPackage.packages.map(pkgPrefix + _.name) + assertEquals(s"Packages in package '$inPackage' on flat cp should be the same as on the recursive cp", + recursiveCpPackages, flatCpPackages) + + val flatCpSources = flatClassPath.sources(inPackage).map(_.name).sorted + val recursiveCpSources = recursiveClassPathInPackage.classes + .filter(_.source.nonEmpty) + .map(_.name).sorted + assertEquals(s"Source entries in package '$inPackage' on flat cp should be the same as on the recursive cp", + recursiveCpSources, flatCpSources) + + val flatCpClasses = flatClassPath.classes(inPackage).map(_.name).sorted + val recursiveCpClasses = recursiveClassPathInPackage.classes + .filter(_.binary.nonEmpty) + .map(_.name).sorted + assertEquals(s"Class entries in package '$inPackage' on flat cp should be the same as on the recursive cp", + recursiveCpClasses, flatCpClasses) + } + + packagesToTest foreach compareEntriesInPackage + } + + @Test + def testFindClassFile: Unit = { + val classPath = createFlatClassPath(settings) + classFilesToFind foreach { className => + assertTrue(s"File for $className should be found", classPath.findClassFile(className).isDefined) + } + } + + @Test + def testFindClass: Unit = { + val classPath = createFlatClassPath(settings) + classesToFind foreach { className => + assertTrue(s"File for $className should be found", classPath.findClass(className).isDefined) + } + } +} diff --git a/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala b/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala index 524d2e45e0..91f94e09b6 100644 --- a/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala +++ b/test/junit/scala/tools/nsc/symtab/StdNamesTest.scala @@ -19,7 +19,7 @@ class StdNamesTest { } @Test - def testNewTermNameNegativeLenght(): Unit = { + def testNewTermNameNegativeLength(): Unit = { assertEquals(nme.EMPTY, newTermName("foo".toCharArray, 0, -1)) assertEquals(nme.EMPTY, newTermName("foo".toCharArray, 0, 0)) } diff --git a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala index e4be42ac96..f0f20acf07 100644 --- a/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala +++ b/test/junit/scala/tools/nsc/symtab/SymbolTableForUnitTesting.scala @@ -3,6 +3,9 @@ package symtab import scala.reflect.ClassTag import scala.reflect.internal.{Phase, NoPhase, SomePhase} +import scala.tools.nsc.classpath.FlatClassPath +import scala.tools.nsc.settings.ClassPathRepresentationType +import scala.tools.util.FlatClassPathResolver import scala.tools.util.PathResolver import util.ClassPath import io.AbstractFile @@ -26,13 +29,28 @@ class SymbolTableForUnitTesting extends SymbolTable { class LazyTreeCopier extends super.LazyTreeCopier with TreeCopier override def isCompilerUniverse: Boolean = true - def classPath = new PathResolver(settings).result + + def classPath = platform.classPath + def flatClassPath: FlatClassPath = platform.flatClassPath object platform extends backend.Platform { val symbolTable: SymbolTableForUnitTesting.this.type = SymbolTableForUnitTesting.this lazy val loaders: SymbolTableForUnitTesting.this.loaders.type = SymbolTableForUnitTesting.this.loaders + def platformPhases: List[SubComponent] = Nil - val classPath: ClassPath[AbstractFile] = new PathResolver(settings).result + + lazy val classPath: ClassPath[AbstractFile] = { + assert(settings.YclasspathImpl.value == ClassPathRepresentationType.Recursive, + "It's not possible to use the recursive classpath representation, when it's not the chosen classpath scanning method") + new PathResolver(settings).result + } + + private[nsc] lazy val flatClassPath: FlatClassPath = { + assert(settings.YclasspathImpl.value == ClassPathRepresentationType.Flat, + "It's not possible to use the flat classpath representation, when it's not the chosen classpath scanning method") + new FlatClassPathResolver(settings).result + } + def isMaybeBoxed(sym: Symbol): Boolean = ??? def needCompile(bin: AbstractFile, src: AbstractFile): Boolean = ??? def externalEquals: Symbol = ??? @@ -50,7 +68,12 @@ class SymbolTableForUnitTesting extends SymbolTable { class GlobalMirror extends Roots(NoSymbol) { val universe: SymbolTableForUnitTesting.this.type = SymbolTableForUnitTesting.this - def rootLoader: LazyType = new loaders.PackageLoader(classPath) + + def rootLoader: LazyType = settings.YclasspathImpl.value match { + case ClassPathRepresentationType.Flat => new loaders.PackageLoaderUsingFlatClassPath(FlatClassPath.RootPackage, flatClassPath) + case ClassPathRepresentationType.Recursive => new loaders.PackageLoader(classPath) + } + override def toString = "compiler mirror" } @@ -60,7 +83,7 @@ class SymbolTableForUnitTesting extends SymbolTable { rm.asInstanceOf[Mirror] } - def settings: Settings = { + lazy val settings: Settings = { val s = new Settings // initialize classpath using java classpath s.usejavacp.value = true diff --git a/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala b/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala index 11e955a4bb..895ad9d683 100644 --- a/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala +++ b/test/junit/scala/tools/nsc/symtab/SymbolTableTest.scala @@ -44,4 +44,9 @@ class SymbolTableTest { assertFalse("Foo should be a superclass of Foo", fooSymbol.tpe <:< barSymbol.tpe) } + @Test + def noSymbolOuterClass_t9133: Unit = { + import symbolTable._ + assert(NoSymbol.outerClass == NoSymbol) + } } diff --git a/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala b/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala new file mode 100644 index 0000000000..1fff9c9a32 --- /dev/null +++ b/test/junit/scala/tools/nsc/transform/patmat/SolvingTest.scala @@ -0,0 +1,555 @@ +package scala.tools.nsc.transform.patmat + +import org.junit.Assert._ +import org.junit.Test +import org.junit.runner.RunWith +import org.junit.runners.JUnit4 + +import scala.collection.mutable +import scala.tools.nsc.{Global, Settings} + +object TestSolver extends Logic with Solving { + + val global: Global = new Global(new Settings()) + + // disable max recursion depth in order to get all solutions + global.settings.YpatmatExhaustdepth.tryToSet("off" :: Nil) + + object TestSolver extends Solver { + + class Const { + override def toString: String = "Const" + } + + val NullConst = new Const + type Type = Int + + case class TypeConst(i: Int) extends Const + + object TypeConst extends TypeConstExtractor + + case class ValueConst(i: Int) extends Const + + object ValueConst extends ValueConstExtractor { + def apply(t: Tree): Const = ??? + } + + case class Tree(name: String) + + class Var(val x: Tree) extends AbsVar { + + override def equals(other: scala.Any): Boolean = other match { + case that: Var => this.x == that.x + case _ => false + } + + override def hashCode(): Int = x.hashCode() + + override def toString: String = { + s"Var($x)" + } + + def domainSyms = None + + def implications = Nil + + def mayBeNull = false + + def propForEqualsTo(c: Const): Prop = ??? + + def registerEquality(c: Const) = () + + def registerNull() = () + + def symForStaticTp = None + } + + object Var extends VarExtractor { + def apply(x: Tree): Var = new Var(x) + + def unapply(v: Var): Some[Tree] = Some(v.x) + } + + def prepareNewAnalysis() = {} + + def reportWarning(msg: String) = sys.error(msg) + + /** + * The DPLL procedure only returns a minimal mapping from literal to value + * such that the CNF formula is satisfied. + * E.g. for: + * `(a \/ b)` + * The DPLL procedure will find either {a = true} or {b = true} + * as solution. + * + * The expansion step will amend both solutions with the unassigned variable + * i.e., {a = true} will be expanded to {a = true, b = true} and + * {a = true, b = false}. + */ + def expandUnassigned(solution: Solution): List[Model] = { + import solution._ + + // the number of solutions is doubled for every unassigned variable + val expandedModels = 1 << unassigned.size + var current = mutable.ArrayBuffer[Model]() + var next = mutable.ArrayBuffer[Model]() + current.sizeHint(expandedModels) + next.sizeHint(expandedModels) + + current += model + + // we use double buffering: + // read from `current` and create a two models for each model in `next` + for { + s <- unassigned + } { + for { + model <- current + } { + def force(s: Sym, pol: Boolean) = model + (s -> pol) + + next += force(s, pol = true) + next += force(s, pol = false) + } + + val tmp = current + current = next + next = tmp + + next.clear() + } + + current.toList + } + + /** + * Old CNF conversion code, used for reference: + * - convert formula into NNF + * (i.e., no negated terms, only negated variables) + * - use distributive laws to convert into CNF + */ + def eqFreePropToSolvableViaDistribution(p: Prop) = { + val symbolMapping = new SymbolMapping(gatherSymbols(p)) + + type Formula = Array[TestSolver.Clause] + + def formula(c: Clause*): Formula = c.toArray + + def merge(a: Clause, b: Clause) = a ++ b + + def negationNormalFormNot(p: Prop): Prop = p match { + case And(ps) => Or(ps map negationNormalFormNot) + case Or(ps) => And(ps map negationNormalFormNot) + case Not(p) => negationNormalForm(p) + case True => False + case False => True + case s: Sym => Not(s) + } + + def negationNormalForm(p: Prop): Prop = p match { + case Or(ps) => Or(ps map negationNormalForm) + case And(ps) => And(ps map negationNormalForm) + case Not(negated) => negationNormalFormNot(negated) + case True + | False + | (_: Sym) => p + } + + val TrueF: Formula = Array() + val FalseF = Array(clause()) + def lit(sym: Sym) = Array(clause(symbolMapping.lit(sym))) + def negLit(sym: Sym) = Array(clause(-symbolMapping.lit(sym))) + + def conjunctiveNormalForm(p: Prop): Formula = { + def distribute(a: Formula, b: Formula): Formula = + (a, b) match { + // true \/ _ = true + // _ \/ true = true + case (trueA, trueB) if trueA.size == 0 || trueB.size == 0 => TrueF + // lit \/ lit + case (a, b) if a.size == 1 && b.size == 1 => formula(merge(a(0), b(0))) + // (c1 /\ ... /\ cn) \/ d = ((c1 \/ d) /\ ... /\ (cn \/ d)) + // d \/ (c1 /\ ... /\ cn) = ((d \/ c1) /\ ... /\ (d \/ cn)) + case (cs, ds) => + val (big, small) = if (cs.size > ds.size) (cs, ds) else (ds, cs) + big flatMap (c => distribute(formula(c), small)) + } + + p match { + case True => TrueF + case False => FalseF + case s: Sym => lit(s) + case Not(s: Sym) => negLit(s) + case And(ps) => + ps.toArray flatMap conjunctiveNormalForm + case Or(ps) => + ps map conjunctiveNormalForm reduceLeft { (a, b) => + distribute(a, b) + } + } + } + val cnf = conjunctiveNormalForm(negationNormalForm(p)) + Solvable(cnf, symbolMapping) + } + + } + +} + +/** + * Testing CNF conversion via Tseitin vs NNF & expansion. + */ +@RunWith(classOf[JUnit4]) +class SolvingTest { + + import scala.tools.nsc.transform.patmat.TestSolver.TestSolver._ + + implicit val Ord: Ordering[TestSolver.TestSolver.Model] = Ordering.by { + _.toSeq.sortBy(_.toString()).toIterable + } + + private def sym(name: String) = Sym(Var(Tree(name)), NullConst) + + @Test + def testSymCreation() { + val s1 = sym("hello") + val s2 = sym("hello") + assertEquals(s1, s2) + } + + /** + * Simplest possible test: solve a formula and check the solution(s) + */ + @Test + def testUnassigned() { + val pSym = sym("p") + val solvable = propToSolvable(Or(pSym, Not(pSym))) + val solutions = TestSolver.TestSolver.findAllModelsFor(solvable) + val expected = List(Solution(Map(), List(pSym))) + assertEquals(expected, solutions) + } + + /** + * Unassigned variables must be expanded + * for stable results + */ + @Test + def testNoUnassigned() { + val pSym = sym("p") + val qSym = sym("q") + val solvable = propToSolvable(Or(pSym, Not(qSym))) + val solutions = findAllModelsFor(solvable) + val expanded = solutions.flatMap(expandUnassigned).sorted + val expected = Seq( + Map(pSym -> false, qSym -> false), + Map(pSym -> true, qSym -> false), + Map(pSym -> true, qSym -> true) + ).sorted + + assertEquals(expected, expanded) + } + + @Test + def testTseitinVsExpansionFrom_t7020() { + val formulas = Seq( + And(And(And(Not(sym("V1=null")), + sym("V1=scala.collection.immutable.::[?]")), And(Not(sym("V1=null")), + And(Or(sym("V2=4"), Or(sym("V2=5"), sym("V2=6"))), sym("V3=Nil")))), + And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")), + Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"), + Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")), + Not(sym("V3=null"))), + And(Or(Not(sym("V3=scala.collection.immutable.::[?]")), + Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null")))))))), And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))))), + + And(And(And(Not(sym("V1=null")), + sym("V1=scala.collection.immutable.::[?]")), And(Not(sym("V1=null")), + And(sym("V2=7"), sym("V3=Nil")))), + And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")), + Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"), + Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")), + Not(sym("V3=null"))), + And(Or(Not(sym("V3=scala.collection.immutable.::[?]")), + Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null")))))))), And(And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil")))))))), + + And(And(Not(sym("V1=null")), + sym("V1=scala.collection.immutable.::[?]")), And(Not(sym("V1=null")), + And(Or(sym("V2=4"), Or(sym("V2=5"), sym("V2=6"))), sym("V3=Nil")))), + + And(And(Not(sym("V1=null")), sym("V1=scala.collection.immutable.::[?]")), + And(Not(sym("V1=null")), And(sym("V2=7"), sym("V3=Nil")))), + + And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")), + Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"), + Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")), + Not(sym("V3=null"))), + And(Or(Not(sym("V3=scala.collection.immutable.::[?]")), + Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null")))))))), And(And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil"))))))), + + And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")), + Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"), + Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")), + Not(sym("V3=null"))), + And(Or(Not(sym("V3=scala.collection.immutable.::[?]")), + Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null")))))))), And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=2")), Not(sym("V3=Nil"))))))), + + And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")), + Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"), + Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")), + Not(sym("V3=null"))), + And(Or(Not(sym("V3=scala.collection.immutable.::[?]")), + Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null")))))))), And(sym("V1=Nil"), And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil"))))), And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=2")), Not(sym("V3=Nil"))))))))), + + And(And(Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), And(Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil"))))), And(Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(Not(sym("V2=7")), Not(sym("V3=Nil"))))), Not(sym("V1=Nil"))))), + + And(And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil")))))), + + And(And(Or(sym("V3=scala.collection.immutable.::[?]"), sym("V3=Nil")), + Or(sym("V1=scala.collection.immutable.::[?]"), sym("V1=Nil"))), + And(And(Or(Or(False, Not(sym("V1=scala.collection.immutable.::[?]"))), + Or(False, Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), And(Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil"))))), And(Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(Not(sym("V2=7")), Not(sym("V3=Nil"))))), Not(sym("V1=Nil")))))), + + And(Not(sym("V1=null")), And(Or(sym("V2=4"), Or(sym("V2=5"), sym("V2=6"))), + sym("V3=Nil"))), + + And(Not(sym("V1=null")), And(sym("V2=7"), sym("V3=Nil"))), + + And(Not(sym("V1=null")), sym("V1=scala.collection.immutable.::[?]")), + + And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + + And(Not(sym("V2=5")), Not(sym("V2=6"))), + + And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null")))), + + And(Or(Not(sym("V1=scala.collection.immutable.::[?]")), + Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"), + Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")), + Not(sym("V3=null"))), + And(Or(Not(sym("V3=scala.collection.immutable.::[?]")), + Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null")))))))), + + And(Or(Not(sym("V3=Nil")), Not(sym("V3=null"))), + And(Or(Not(sym("V3=scala.collection.immutable.::[?]")), + Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null")))))), + + And(Or(Not(sym("V3=scala.collection.immutable.::[?]")), + Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null"))))), + + And(Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil"))))), And(Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(Not(sym("V2=7")), Not(sym("V3=Nil"))))), Not(sym("V1=Nil")))), + + And(Or(Or(False, Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), + + And(Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(Not(sym("V2=7")), Not(sym("V3=Nil"))))), Not(sym("V1=Nil"))), + + And(Or(Or(sym("V1=null"), Not(sym("V1=scala.collection.immutable.::[?]"))), + Or(sym("V1=null"), Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), + Not(sym("V2=6")))), Not(sym("V3=Nil"))))), And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=2")), Not(sym("V3=Nil"))))))), + + And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))), + + And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=7")), Not(sym("V3=Nil"))))), + And(And(Or(Not(sym("V1=scala.collection.immutable.::[?]")), + Not(sym("V1=null"))), And(Or(sym("V3=scala.collection.immutable.::[?]"), + Or(sym("V3=Nil"), sym("V3=null"))), And(Or(Not(sym("V3=Nil")), + Not(sym("V3=null"))), + And(Or(Not(sym("V3=scala.collection.immutable.::[?]")), + Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null")))))))), And(sym("V1=Nil"), And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil"))))), And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))))))), + + And(Or(sym("V2=4"), Or(sym("V2=5"), sym("V2=6"))), sym("V3=Nil")), + + And(Or(sym("V3=scala.collection.immutable.::[?]"), Or(sym("V3=Nil"), + sym("V3=null"))), And(Or(Not(sym("V3=Nil")), Not(sym("V3=null"))), + And(Or(Not(sym("V3=scala.collection.immutable.::[?]")), + Not(sym("V3=null"))), And(Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + Or(sym("V1=scala.collection.immutable.::[?]"), Or(sym("V1=Nil"), + sym("V1=null"))))))), + + And(Or(sym("V3=scala.collection.immutable.::[?]"), + sym("V3=Nil")), Or(sym("V1=scala.collection.immutable.::[?]"), + sym("V1=Nil"))), + + And(sym("V1=Nil"), And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil"))))), And(Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=2")), Not(sym("V3=Nil")))))))), + + And(sym("V2=7"), sym("V3=Nil")), + + False, + + Not(sym("V1=Nil")), + + Or(And(Not(sym("V2=4")), + And(Not(sym("V2=5")), Not(sym("V2=6")))), Not(sym("V3=Nil"))), + + Or(False, Not(sym("V1=scala.collection.immutable.::[?]"))), + + Or(False, + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil")))), + + Or(False, Or(Not(sym("V2=1")), Not(sym("V3=Nil")))), + + Or(Not(sym("V1=Nil")), Not(sym("V1=null"))), + + Or(Not(sym("V3=scala.collection.immutable.::[?]")), Not(sym("V3=null"))), + + Or(Or(False, Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil"))))), + + Or(Or(False, + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(False, + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), + + Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil"))))), + + Or(Or(sym("V1=null"), + Not(sym("V1=scala.collection.immutable.::[?]"))), Or(sym("V1=null"), + Or(Not(sym("V2=1")), Not(sym("V3=Nil"))))), + + Or(sym("V1=null"), Not(sym("V1=scala.collection.immutable.::[?]"))), + + Or(sym("V1=null"), + Or(And(Not(sym("V2=4")), And(Not(sym("V2=5")), Not(sym("V2=6")))), + Not(sym("V3=Nil")))), + + Or(sym("V1=null"), Or(Not(sym("V2=1")), Not(sym("V3=Nil")))), + + Or(sym("V1=scala.collection.immutable.::[?]"), + Or(sym("V1=Nil"), sym("V1=null"))), + + Or(sym("V1=scala.collection.immutable.::[?]"), sym("V1=Nil")), + + Or(sym("V2=4"), Or(sym("V2=5"), sym("V2=6"))), + + sym("V3=scala.collection.immutable.::[?]") + ) + + formulas foreach { + f => + // build CNF + val tseitinCnf = propToSolvable(f) + val expansionCnf = eqFreePropToSolvableViaDistribution(f) + + // ALL-SAT + val tseitinSolutions = findAllModelsFor(tseitinCnf) + val expansionSolutins = findAllModelsFor(expansionCnf) + + // expand unassigned variables + // (otherwise solutions can not be compared) + val tseitinNoUnassigned = tseitinSolutions.flatMap(expandUnassigned).sorted + val expansionNoUnassigned = expansionSolutins.flatMap(expandUnassigned).sorted + assertEquals(tseitinNoUnassigned, expansionNoUnassigned) + } + } +} + + diff --git a/test/junit/scala/tools/nsc/util/ClassPathImplComparator.scala b/test/junit/scala/tools/nsc/util/ClassPathImplComparator.scala new file mode 100644 index 0000000000..f2926e3e17 --- /dev/null +++ b/test/junit/scala/tools/nsc/util/ClassPathImplComparator.scala @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2014 Contributor. All rights reserved. + */ +package scala.tools.nsc.util + +import scala.reflect.io.AbstractFile +import scala.tools.nsc.Settings +import scala.tools.nsc.settings.ClassPathRepresentationType +import scala.tools.util.PathResolverFactory + +/** + * Simple application to compare efficiency of the recursive and the flat classpath representations + */ +object ClassPathImplComparator { + + private class TestSettings extends Settings { + val checkClasses = PathSetting("-checkClasses", "Specify names of classes which should be found separated with ;", "") + val requiredIterations = IntSetting("-requiredIterations", + "Repeat tests specified number of times (to check e.g. impact of caches)", 1, Some((1, Int.MaxValue)), (_: String) => None) + val cpCreationRepetitions = IntSetting("-cpCreationRepetitions", + "Repeat tests specified number of times (to check e.g. impact of caches)", 1, Some((1, Int.MaxValue)), (_: String) => None) + val cpLookupRepetitions = IntSetting("-cpLookupRepetitions", + "Repeat tests specified number of times (to check e.g. impact of caches)", 1, Some((1, Int.MaxValue)), (_: String) => None) + } + + private class DurationStats(name: String) { + private var sum = 0L + private var iterations = 0 + + def noteMeasuredTime(millis: Long): Unit = { + sum += millis + iterations += 1 + } + + def printResults(): Unit = { + val avg = if (iterations == 0) 0 else sum.toDouble / iterations + println(s"$name - total duration: $sum ms; iterations: $iterations; avg: $avg ms") + } + } + + private lazy val defaultClassesToFind = List( + "scala.collection.immutable.List", + "scala.Option", + "scala.Int", + "scala.collection.immutable.Vector", + "scala.util.hashing.MurmurHash3" + ) + + private val oldCpCreationStats = new DurationStats("Old classpath - create") + private val oldCpSearchingStats = new DurationStats("Old classpath - search") + + private val flatCpCreationStats = new DurationStats("Flat classpath - create") + private val flatCpSearchingStats = new DurationStats("Flat classpath - search") + + def main(args: Array[String]): Unit = { + + if (args contains "-help") + usage() + else { + val oldCpSettings = loadSettings(args.toList, ClassPathRepresentationType.Recursive) + val flatCpSettings = loadSettings(args.toList, ClassPathRepresentationType.Flat) + + val classesToCheck = oldCpSettings.checkClasses.value + val classesToFind = + if (classesToCheck.isEmpty) defaultClassesToFind + else classesToCheck.split(";").toList + + def doTest(classPath: => ClassFileLookup[AbstractFile], cpCreationStats: DurationStats, cpSearchingStats: DurationStats, + cpCreationRepetitions: Int, cpLookupRepetitions: Int)= { + + def createClassPaths() = (1 to cpCreationRepetitions).map(_ => classPath).last + def testClassLookup(cp: ClassFileLookup[AbstractFile]): Boolean = (1 to cpCreationRepetitions).foldLeft(true) { + case (a, _) => a && checkExistenceOfClasses(classesToFind)(cp) + } + + val cp = withMeasuredTime("Creating classpath", createClassPaths(), cpCreationStats) + val result = withMeasuredTime("Searching for specified classes", testClassLookup(cp), cpSearchingStats) + println(s"The end of the test case. All expected classes found = $result \n") + } + + (1 to oldCpSettings.requiredIterations.value) foreach { iteration => + if (oldCpSettings.requiredIterations.value > 1) + println(s"Iteration no $iteration") + + println("Recursive (old) classpath representation:") + doTest(PathResolverFactory.create(oldCpSettings).result, oldCpCreationStats, oldCpSearchingStats, + oldCpSettings.cpCreationRepetitions.value, oldCpSettings.cpLookupRepetitions.value) + + println("Flat classpath representation:") + doTest(PathResolverFactory.create(flatCpSettings).result, flatCpCreationStats, flatCpSearchingStats, + flatCpSettings.cpCreationRepetitions.value, flatCpSettings.cpLookupRepetitions.value) + } + + if (oldCpSettings.requiredIterations.value > 1) { + println("\nOld classpath - summary") + oldCpCreationStats.printResults() + oldCpSearchingStats.printResults() + + println("\nFlat classpath - summary") + flatCpCreationStats.printResults() + flatCpSearchingStats.printResults() + } + } + } + + /** + * Prints usage information + */ + private def usage(): Unit = + println("""Use classpath and sourcepath options like in the case of e.g. 'scala' command. + | There are also two additional options: + | -checkClasses <semicolon separated class names> Specify names of classes which should be found + | -requiredIterations <int value> Repeat tests specified count of times (to check e.g. impact of caches) + | Note: Option -YclasspathImpl will be set automatically for each case. + """.stripMargin.trim) + + private def loadSettings(args: List[String], implType: String) = { + val settings = new TestSettings() + settings.processArguments(args, processAll = true) + settings.YclasspathImpl.value = implType + if (settings.classpath.isDefault) + settings.classpath.value = sys.props("java.class.path") + settings + } + + private def withMeasuredTime[T](operationName: String, f: => T, durationStats: DurationStats): T = { + val startTime = System.currentTimeMillis() + val res = f + val elapsed = System.currentTimeMillis() - startTime + durationStats.noteMeasuredTime(elapsed) + println(s"$operationName - elapsed $elapsed ms") + res + } + + private def checkExistenceOfClasses(classesToCheck: Seq[String])(classPath: ClassFileLookup[AbstractFile]): Boolean = + classesToCheck.foldLeft(true) { + case (res, classToCheck) => + val found = classPath.findClass(classToCheck).isDefined + if (!found) + println(s"Class $classToCheck not found") // of course in this case the measured time will be affected by IO operation + found + } +} diff --git a/test/pending/jvm/cf-attributes.scala b/test/pending/jvm/cf-attributes.scala index f4964b63b1..2d08f22d8b 100644 --- a/test/pending/jvm/cf-attributes.scala +++ b/test/pending/jvm/cf-attributes.scala @@ -62,7 +62,7 @@ object anonymousClasses { //InnerClass: // public final #_; //class anonymousClasses$$anon$1 of class anonymousClasses$ val x = new Foo() { - override def foo() { println("foo (overriden)"); } + override def foo() { println("foo (overridden)"); } def dummy = 0 } } diff --git a/test/pending/jvm/timeout.scala b/test/pending/jvm/timeout.scala index 22b3647dce..8f29f8ddbe 100644 --- a/test/pending/jvm/timeout.scala +++ b/test/pending/jvm/timeout.scala @@ -1,4 +1,4 @@ -// Test is in pending because although it suceeds locally, +// Test is in pending because although it succeeds locally, // it takes too long on the machine which runs nightly tests. // // [partest] EXPECTED: 100 < x < 900 diff --git a/test/scaladoc/resources/SI-3314-diagrams.scala b/test/scaladoc/resources/SI-3314-diagrams.scala index b80a97b522..7d2cc9447c 100644 --- a/test/scaladoc/resources/SI-3314-diagrams.scala +++ b/test/scaladoc/resources/SI-3314-diagrams.scala @@ -7,7 +7,7 @@ package scala.test.scaladoc { * / / / | \ \ \ * Mon Tue Wed Thu Fri Sat Sun * - * - each member should receive an inhertiance diagram: + * - each member should receive an inheritance diagram: * Value * | * | diff --git a/test/scaladoc/resources/implicit-inheritance-override.scala b/test/scaladoc/resources/implicit-inheritance-override.scala index 5d692f59ad..b59d2f410d 100644 --- a/test/scaladoc/resources/implicit-inheritance-override.scala +++ b/test/scaladoc/resources/implicit-inheritance-override.scala @@ -35,7 +35,7 @@ class DerivedC extends Base { class DerivedD extends Base { /** - * @tparam T The overriden type parameter comment + * @tparam T The overridden type parameter comment */ override def function[T](arg1: T, arg2: String): Double = 3.0d }
\ No newline at end of file diff --git a/test/scaladoc/resources/implicits-ambiguating-res.scala b/test/scaladoc/resources/implicits-ambiguating-res.scala index 6ed51366cb..90e43ac2ed 100644 --- a/test/scaladoc/resources/implicits-ambiguating-res.scala +++ b/test/scaladoc/resources/implicits-ambiguating-res.scala @@ -1,5 +1,5 @@ /** - * Test scaladoc implicits distinguishing -- supress all members by implicit conversion that are shadowed by the + * Test scaladoc implicits distinguishing -- suppress all members by implicit conversion that are shadowed by the * class' own members * * {{{ diff --git a/test/scaladoc/resources/implicits-shadowing-res.scala b/test/scaladoc/resources/implicits-shadowing-res.scala index c5e9493bf3..b7f3ceb895 100644 --- a/test/scaladoc/resources/implicits-shadowing-res.scala +++ b/test/scaladoc/resources/implicits-shadowing-res.scala @@ -1,5 +1,5 @@ /** - * Test scaladoc implicits distinguishing -- supress all members by implicit conversion that are shadowed by the + * Test scaladoc implicits distinguishing -- suppress all members by implicit conversion that are shadowed by the * class' own members * * {{{ diff --git a/test/scaladoc/scalacheck/HtmlFactoryTest.scala b/test/scaladoc/scalacheck/HtmlFactoryTest.scala index da0f253a37..51633be440 100644 --- a/test/scaladoc/scalacheck/HtmlFactoryTest.scala +++ b/test/scaladoc/scalacheck/HtmlFactoryTest.scala @@ -485,7 +485,7 @@ object Test extends Properties("HtmlFactory") { """, true), (Some("DerivedD"), """def function[T](arg1: T, arg2: String): Double - T The overriden type parameter comment + T The overridden type parameter comment arg1 The T term comment arg2 The string comment returns The return comment diff --git a/test/script-tests/README b/test/script-tests/README index 3f5c2ce19c..7b3291c407 100755 --- a/test/script-tests/README +++ b/test/script-tests/README @@ -5,4 +5,9 @@ putting self-contained script tests in here to run some way that doesn't depend on all the platform stars aligning all the time. Feel free to join me. --- extempore, Nov 21 2011
\ No newline at end of file +-- extempore, Nov 21 2011 + +But there's a problem that probably nobody would run such tests so they would become outdated quite quickly. +And therefore they wouldn't work (and even compile) after some time - like this one existing currently. + +-- mpociecha, Oct 9 2014
\ No newline at end of file |