mirror of https://github.com/sbt/sbt.git
Don't leak the sbt boot scala library into tests
It was reported in https://github.com/sbt/sbt/issues/4608 that there was a regression that tests run against scala 2.11 would fail. This was because the interface loader incorrectly contained the scala library. To fix this, I needed to find the xsbt.boot.BootFilteredLoader in the classloading hierarchy and put the sbt testing interface library in between that loader and the scala library loader.
This commit is contained in:
parent
c9aec02d05
commit
fc715cab44
|
|
@ -21,6 +21,8 @@ import sbt.internal.util.Attributed.data
|
||||||
import sbt.io.IO
|
import sbt.io.IO
|
||||||
import sbt.librarymanagement.Configurations.{ Runtime, Test }
|
import sbt.librarymanagement.Configurations.{ Runtime, Test }
|
||||||
|
|
||||||
|
import scala.annotation.tailrec
|
||||||
|
|
||||||
private[sbt] object ClassLoaders {
|
private[sbt] object ClassLoaders {
|
||||||
private[this] val interfaceLoader = classOf[sbt.testing.Framework].getClassLoader
|
private[this] val interfaceLoader = classOf[sbt.testing.Framework].getClassLoader
|
||||||
/*
|
/*
|
||||||
|
|
@ -214,9 +216,15 @@ private[sbt] object SbtMetaBuildClassLoader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
def apply(libraryLoader: ClassLoader, fullLoader: ClassLoader): ClassLoader = {
|
def apply(libraryLoader: ClassLoader, fullLoader: ClassLoader): ClassLoader = {
|
||||||
|
@tailrec
|
||||||
|
def bootLoader(classLoader: ClassLoader): ClassLoader = classLoader.getParent match {
|
||||||
|
case null => classLoader
|
||||||
|
case c if c.getClass.getCanonicalName == "xsbt.boot.BootFilteredLoader" => c
|
||||||
|
case c => bootLoader(c)
|
||||||
|
}
|
||||||
val interfaceFilter: URL => Boolean = _.getFile.endsWith("test-interface-1.0.jar")
|
val interfaceFilter: URL => Boolean = _.getFile.endsWith("test-interface-1.0.jar")
|
||||||
val (interfaceURL, rest) = fullLoader.urls.partition(interfaceFilter)
|
val (interfaceURL, rest) = fullLoader.urls.partition(interfaceFilter)
|
||||||
val interfaceLoader = new URLClassLoader(interfaceURL, libraryLoader.getParent) {
|
val interfaceLoader = new URLClassLoader(interfaceURL, bootLoader(libraryLoader)) {
|
||||||
override def toString: String = s"SbtTestInterfaceClassLoader(${getURLs.head})"
|
override def toString: String = s"SbtTestInterfaceClassLoader(${getURLs.head})"
|
||||||
}
|
}
|
||||||
val updatedLibraryLoader = new URLClassLoader(libraryLoader.urls, interfaceLoader) {
|
val updatedLibraryLoader = new URLClassLoader(libraryLoader.urls, interfaceLoader) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
val scalatest = "org.scalatest" %% "scalatest" % "3.0.5"
|
||||||
|
|
||||||
|
lazy val root = (project in file("."))
|
||||||
|
.settings(
|
||||||
|
// Verifies that a different scala library version still works in test
|
||||||
|
scalaVersion := "2.11.12",
|
||||||
|
libraryDependencies += scalatest % Test
|
||||||
|
)
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
import java.io.File
|
||||||
|
import org.scalatest.FlatSpec
|
||||||
|
|
||||||
|
class Test extends FlatSpec {
|
||||||
|
"a test" should "pass" in {
|
||||||
|
assert(true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
> test
|
||||||
|
|
@ -255,7 +255,9 @@ final class ScriptedTests(
|
||||||
case "source-dependencies/linearization" => LauncherBased // sbt/Package$
|
case "source-dependencies/linearization" => LauncherBased // sbt/Package$
|
||||||
case "source-dependencies/named" => LauncherBased // sbt/Package$
|
case "source-dependencies/named" => LauncherBased // sbt/Package$
|
||||||
case "source-dependencies/specialized" => LauncherBased // sbt/Package$
|
case "source-dependencies/specialized" => LauncherBased // sbt/Package$
|
||||||
case _ => RunFromSourceBased
|
case "tests/test-cross" =>
|
||||||
|
LauncherBased // the sbt metabuild classpath leaks into the test interface classloader in older versions of sbt
|
||||||
|
case _ => RunFromSourceBased
|
||||||
}
|
}
|
||||||
// sbt/Package$ means:
|
// sbt/Package$ means:
|
||||||
// java.lang.NoClassDefFoundError: sbt/Package$ (wrong name: sbt/package$)
|
// java.lang.NoClassDefFoundError: sbt/Package$ (wrong name: sbt/package$)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue