Skip to content

Commit

Permalink
Run the functional tests, to ensure they're correct (#444)
Browse files Browse the repository at this point in the history
Run the functional tests, to ensure they're correct
  • Loading branch information
dwijnand authored Jan 18, 2020
2 parents 8778a79 + fb23c17 commit cbbb510
Show file tree
Hide file tree
Showing 161 changed files with 952 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ private[analyze] object MethodChecker {

/** Analyze incompatibilities that may derive from new methods in `newclazz`. */
private def checkNew(oldclazz: ClassInfo, newclazz: ClassInfo): List[Problem] = {
checkEmulatedConcreteMethodsProblems(oldclazz, newclazz) :::
(if (newclazz.isClass) Nil else checkEmulatedConcreteMethodsProblems(oldclazz, newclazz)) :::
checkDeferredMethodsProblems(oldclazz, newclazz) :::
checkInheritedNewAbstractMethodProblems(oldclazz, newclazz)
}
Expand Down Expand Up @@ -108,30 +108,28 @@ private[analyze] object MethodChecker {
methods.groupBy(_.parametersDesc).values.collect { case method :: _ => method }.toList

private def checkEmulatedConcreteMethodsProblems(oldclazz: ClassInfo, newclazz: ClassInfo): List[Problem] = {
if (oldclazz.isClass && newclazz.isClass) Nil else {
for {
newmeth <- newclazz.emulatedConcreteMethods.iterator
if !oldclazz.hasStaticImpl(newmeth)
problem <- {
if (oldclazz.lookupMethods(newmeth).exists(_.descriptor == newmeth.descriptor)) {
// a static implementation for the same method existed already, therefore
// class that mixed-in the trait already have a forwarder to the implementation
// class. Mind that, despite no binary incompatibility arises, program's
// semantic may be severely affected.
None
} else {
// this means that the method is brand new and therefore the implementation
// has to be injected
Some(ReversedMissingMethodProblem(newmeth))
}
for {
newmeth <- newclazz.emulatedConcreteMethods.iterator
if !oldclazz.hasStaticImpl(newmeth)
problem <- {
if (oldclazz.lookupMethods(newmeth).exists(_.descriptor == newmeth.descriptor)) {
// a static implementation for the same method existed already, therefore
// classes that mixed-in the trait already have a forwarder to the implementation
// class. Mind that, despite no binary incompatibility arises, program's
// semantic may be severely affected.
None
} else {
// this means that the method is brand new
// and therefore the implementation has to be injected
Some(ReversedMissingMethodProblem(newmeth))
}
} yield problem
}.toList
}
}
} yield problem
}.toList

private def checkDeferredMethodsProblems(oldclazz: ClassInfo, newclazz: ClassInfo): List[Problem] = {
for {
newmeth <- newclazz.deferredMethods
newmeth <- newclazz.deferredMethods.iterator
problem <- oldclazz.lookupMethods(newmeth).find(_.descriptor == newmeth.descriptor) match {
case None => Some(ReversedMissingMethodProblem(newmeth))
case Some(oldmeth) =>
Expand All @@ -140,7 +138,7 @@ private[analyze] object MethodChecker {
else None
}
} yield problem
}
}.toList

private def checkInheritedNewAbstractMethodProblems(oldclazz: ClassInfo, newclazz: ClassInfo): List[Problem] = {
def allInheritedTypes(clazz: ClassInfo) = clazz.superClasses ++ clazz.allInterfaces
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import scala.tools.nsc.classpath.AggregateClassPath
object CollectProblemsTest {

// Called via reflection from TestsPlugin
def runTest(testClasspath: Array[File], testName: String, oldJarOrDir: File, newJarOrDir: File, baseDir: File, scalaVersion: String): Unit = {
def runTest(testClasspath: Array[File], testName: String, oldJarOrDir: File, newJarOrDir: File, baseDir: File, oracleFile: File): Unit = {
val testClassPath = aggregateClassPath(testClasspath)
val classpath = AggregateClassPath.createAggregate(testClassPath, Config.baseClassPath)
val mima = new MiMaLib(classpath)
Expand All @@ -25,16 +25,6 @@ object CollectProblemsTest {
val problems = mima.collectProblems(oldJarOrDir, newJarOrDir).filter(problemFilter)

// load oracle
val oracleFile = {
val p = new File(baseDir, "problems.txt")
val p211 = new File(baseDir, "problems-2.11.txt")
val p212 = new File(baseDir, "problems-2.12.txt")
scalaVersion.take(4) match {
case "2.11" => if (p211.exists()) p211 else if (p212.exists()) p212 else p
case "2.12" => if (p212.exists()) p212 else p
case _ => p
}
}
val source = Source.fromFile(oracleFile)
val expectedProblems = try source.getLines.filter(!_.startsWith("#")).toList finally source.close()

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(Usage.use(new A {}))
}
}
Original file line number Diff line number Diff line change
@@ -1 +1,5 @@
abstract class A
abstract class A

object Usage {
def use(a: A) = ()
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
abstract class A {
def foo(): Unit
}

object Usage {
def use(a: A) = a.foo()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
object App {
def main(args: Array[String]): Unit = {
println(new A {}.foo(new A {}))
println(new C)
println(new D)

println(new E { def bar(): E = new E { def bar() = this } }.bar())
println(new F)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A {}.foo(new A {}))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A { def foo = () }.foo)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A {}.foo(new A {}))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object App {
def main(args: Array[String]): Unit = {
println(Usage.use(new A {}))
println(Usage.use(new B {}))
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,6 @@ abstract class C extends B {
}
abstract class D extends C

object Usage {
def use(a: A) = ()
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,7 @@ abstract class C extends B {
def foo(): Unit
}
abstract class D extends C

object Usage {
def use(a: A) = a.foo()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object App {
def main(args: Array[String]): Unit = {
println(Usage.useA(new A {}) + 10)
println(Usage.useB(new B {}) + 11)
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
abstract method foo()Unit in interface AA is inherited by class B in new version.
abstract method foo()Unit in interface AA is inherited by class A in new version.
abstract method foo()Int in interface AA is inherited by class A in new version.
abstract method foo()Int in interface AA is inherited by class B in new version.
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
trait A
abstract class B
abstract class B

object Usage {
def useA(a: A) = 0
def useB(b: B) = 1
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
trait AA {
def foo(): Unit
def foo(): Int
}

trait A extends AA
abstract class B extends A

object Usage {
def useA(a: A) = a.foo() + 1
def useB(b: B) = b.foo() + 2
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
object App {
def main(args: Array[String]): Unit = {
println(Usage.useA(new A {}) + 10)
println(Usage.useB(new B {}) + 11)
println(Usage.useC(new C {}) + 12)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,8 @@ trait A
trait B
abstract class C extends A with B

object Usage {
def useA(a: A) = 0
def useB(b: B) = 0
def useC(c: C) = 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,9 @@ trait AA {
trait A extends AA
trait B extends A
abstract class C extends B

object Usage {
def useA(a: A) = a.foo + 1
def useB(b: B) = b.foo + 2
def useC(c: C) = c.foo + 3
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object App {
def main(args: Array[String]): Unit = () // v1 is (fundamentally) empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object App {
def main(args: Array[String]): Unit = () // v1 is empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object App {
def main(args: Array[String]): Unit = () // v1 is empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
object App {
def main(args: Array[String]): Unit = () // v1 is (fundamentally) empty
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object App {
def main(args: Array[String]): Unit = {
println(new A() {})
println(new A() {}.copy())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A { def baz = 2 }.baz)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object App {
def main(args: Array[String]): Unit = {
println(new A)
println(A())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(A())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A {})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A().f())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A().f)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A().foo)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new me.A)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A { def baz = 2 }.baz)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object App {
def main(args: Array[String]): Unit = {
println(new A)
println(new A {})
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object App {
def main(args: Array[String]): Unit = {
println(new A)
println(new A().foo)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
object App {
def main(args: Array[String]): Unit = {
println(new A().f())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
object App {
def main(args: Array[String]): Unit = {
println(new A().foo)
println(new A { override def foo = 3 }.foo)
println(new A { override val foo = 4 }.foo)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object App {
def main(args: Array[String]): Unit = {
println(new A().foo)
println(new A { override def foo = 3 }.foo)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object App {
def main(args: Array[String]): Unit = {
val x: Int = new A().foo
println(x + 1)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
object App {
def main(args: Array[String]): Unit = {
println(new A().foo)
println(new A { override val foo = 1 }.foo)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
object App {
def main(args: Array[String]): Unit = {
val a = new A
a.foo = 3
println(a.foo + 1)
}
}
Loading

0 comments on commit cbbb510

Please sign in to comment.