diff --git a/main/src/main/scala/sbt/internal/ClassLoaders.scala b/main/src/main/scala/sbt/internal/ClassLoaders.scala index 4bd40814c..6366343c8 100644 --- a/main/src/main/scala/sbt/internal/ClassLoaders.scala +++ b/main/src/main/scala/sbt/internal/ClassLoaders.scala @@ -21,6 +21,8 @@ import sbt.internal.util.Attributed.data import sbt.io.IO import sbt.librarymanagement.Configurations.{ Runtime, Test } +import scala.annotation.tailrec + private[sbt] object ClassLoaders { private[this] val interfaceLoader = classOf[sbt.testing.Framework].getClassLoader /* @@ -214,9 +216,15 @@ private[sbt] object SbtMetaBuildClassLoader { } } 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 (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})" } val updatedLibraryLoader = new URLClassLoader(libraryLoader.urls, interfaceLoader) { diff --git a/sbt/src/sbt-test/tests/test-cross/build.sbt b/sbt/src/sbt-test/tests/test-cross/build.sbt new file mode 100644 index 000000000..dabf9b70b --- /dev/null +++ b/sbt/src/sbt-test/tests/test-cross/build.sbt @@ -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 + ) diff --git a/sbt/src/sbt-test/tests/test-cross/src/test/scala/Test.scala b/sbt/src/sbt-test/tests/test-cross/src/test/scala/Test.scala new file mode 100644 index 000000000..8a6430745 --- /dev/null +++ b/sbt/src/sbt-test/tests/test-cross/src/test/scala/Test.scala @@ -0,0 +1,8 @@ +import java.io.File +import org.scalatest.FlatSpec + +class Test extends FlatSpec { + "a test" should "pass" in { + assert(true) + } +} diff --git a/sbt/src/sbt-test/tests/test-cross/test b/sbt/src/sbt-test/tests/test-cross/test new file mode 100644 index 000000000..dfffb838b --- /dev/null +++ b/sbt/src/sbt-test/tests/test-cross/test @@ -0,0 +1 @@ +> test diff --git a/scripted-sbt-redux/src/main/scala/sbt/scriptedtest/ScriptedTests.scala b/scripted-sbt-redux/src/main/scala/sbt/scriptedtest/ScriptedTests.scala index 128e794ae..fc6dde494 100644 --- a/scripted-sbt-redux/src/main/scala/sbt/scriptedtest/ScriptedTests.scala +++ b/scripted-sbt-redux/src/main/scala/sbt/scriptedtest/ScriptedTests.scala @@ -255,7 +255,9 @@ final class ScriptedTests( case "source-dependencies/linearization" => LauncherBased // sbt/Package$ case "source-dependencies/named" => 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: // java.lang.NoClassDefFoundError: sbt/Package$ (wrong name: sbt/package$)