mirror of https://github.com/sbt/sbt.git
134 lines
5.6 KiB
Scala
134 lines
5.6 KiB
Scala
package sbt.internal.librarymanagement
|
|
|
|
import java.io.File
|
|
import java.util.concurrent.Callable
|
|
import sbt.io.IO.withTemporaryDirectory
|
|
import sbt.io.IO
|
|
import org.apache.ivy.util.ChecksumHelper
|
|
import IfMissing.Fail
|
|
import xsbti.ComponentProvider
|
|
|
|
// TODO - We need to re-enable this test. Right now, we dont' have a "stub" launcher for this.
|
|
// This is testing something which uses a launcher interface, but was grabbing the underlying class directly
|
|
// when it really should, instead, be stubbing out the underyling class.
|
|
|
|
class ComponentManagerTest extends UnitSpec {
|
|
val TestID = "manager-test"
|
|
"Component manager" should "throw an exception if 'file' is called for a non-existing component" in {
|
|
withManager { manager =>
|
|
intercept[InvalidComponent] { manager.file(TestID)(Fail) }
|
|
()
|
|
}
|
|
}
|
|
it should "throw an exception if 'file' is called for an empty component" in {
|
|
withManager { manager =>
|
|
manager.define(TestID, Nil)
|
|
intercept[InvalidComponent] { manager.file(TestID)(Fail) }
|
|
()
|
|
}
|
|
}
|
|
it should "return the file for a single-file component" in {
|
|
withManager { manager =>
|
|
val hash = defineFile(manager, TestID, "a")
|
|
checksum(manager.file(TestID)(Fail)) shouldBe hash
|
|
}
|
|
}
|
|
it should "throw an exception if 'file' is called for multi-file component" in {
|
|
withManager { manager =>
|
|
defineFiles(manager, TestID, "a", "b")
|
|
intercept[InvalidComponent] { manager.file(TestID)(Fail) }
|
|
()
|
|
}
|
|
}
|
|
it should "return the files for a multi-file component" in {
|
|
withManager { manager =>
|
|
val hashes = defineFiles(manager, TestID, "a", "b")
|
|
checksum(manager.files(TestID)(Fail)) should contain theSameElementsAs (hashes)
|
|
}
|
|
}
|
|
it should "return the files for a single-file component" in {
|
|
withManager { manager =>
|
|
val hashes = defineFiles(manager, TestID, "a")
|
|
checksum(manager.files(TestID)(Fail)) should contain theSameElementsAs (hashes)
|
|
}
|
|
}
|
|
it should "throw an exception if 'files' is called for a non-existing component" in {
|
|
withManager { manager =>
|
|
intercept[InvalidComponent] { manager.files(TestID)(Fail) }
|
|
()
|
|
}
|
|
}
|
|
it should "properly cache a file and then retrieve it to an unresolved component" in {
|
|
withTemporaryDirectory { ivyHome =>
|
|
withManagerHome(ivyHome) { definingManager =>
|
|
val hash = defineFile(definingManager, TestID, "a")
|
|
try {
|
|
definingManager.cache(TestID)
|
|
withManagerHome(ivyHome) { usingManager =>
|
|
checksum(usingManager.file(TestID)(Fail)) shouldBe hash
|
|
}
|
|
} finally { definingManager.clearCache(TestID) }
|
|
}
|
|
}
|
|
}
|
|
|
|
private def checksum(files: Iterable[File]): Seq[String] = files.map(checksum).toSeq
|
|
private def checksum(file: File): String = if (file.exists) ChecksumHelper.computeAsString(file, "sha1") else ""
|
|
private def defineFile(manager: ComponentManager, id: String, name: String): String = createFile(manager, id, name)(checksum)
|
|
private def defineFiles(manager: ComponentManager, id: String, names: String*): Seq[String] = createFiles(manager, id, names: _*)(checksum)
|
|
private def createFile[T](manager: ComponentManager, id: String, name: String)(f: File => T): T = createFiles(manager, id, name)(files => f(files.toList.head))
|
|
private def createFiles[T](manager: ComponentManager, id: String, names: String*)(f: Seq[File] => T): T =
|
|
withTemporaryDirectory { dir =>
|
|
val files = names.map(name => new File(dir, name))
|
|
files.foreach(writeRandomContent)
|
|
manager.define(id, files)
|
|
f(files)
|
|
}
|
|
private def writeRandomContent(file: File) = IO.write(file, randomString)
|
|
private def randomString = "asdf"
|
|
private def withManager[T](f: ComponentManager => T): T =
|
|
withTemporaryDirectory { ivyHome => withManagerHome(ivyHome)(f) }
|
|
|
|
private def withManagerHome[T](ivyHome: File)(f: ComponentManager => T): T =
|
|
TestLogger { logger =>
|
|
withTemporaryDirectory { temp =>
|
|
// The actual classes we'll use at runtime.
|
|
//val mgr = new ComponentManager(xsbt.boot.Locks, new xsbt.boot.ComponentProvider(temp, true), Some(ivyHome), logger)
|
|
|
|
// A stub component manager
|
|
object provider extends ComponentProvider {
|
|
override def componentLocation(id: String): File = new File(temp, id)
|
|
override def lockFile(): File = {
|
|
IO.createDirectory(temp)
|
|
new java.io.File(temp, "sbt.components.lock")
|
|
}
|
|
override def defineComponent(id: String, files: Array[File]): Unit = {
|
|
val location = componentLocation(id)
|
|
if (location.exists)
|
|
throw new RuntimeException(s"Cannot redefine component. ID: $id, files: ${files.mkString(",")}")
|
|
else {
|
|
IO.copy(files.map { f => f -> new java.io.File(location, f.getName) })
|
|
()
|
|
}
|
|
}
|
|
override def addToComponent(id: String, files: Array[File]): Boolean = {
|
|
val location = componentLocation(id)
|
|
IO.copy(files.map { f => f -> new java.io.File(location, f.getName) })
|
|
true
|
|
}
|
|
override def component(id: String): Array[File] =
|
|
Option(componentLocation(id).listFiles()).map(_.filter(_.isFile)).getOrElse(Array.empty)
|
|
}
|
|
// A stubbed locking API.
|
|
object locks extends xsbti.GlobalLock {
|
|
override def apply[U](lockFile: File, run: Callable[U]): U = {
|
|
// TODO - do we need to lock?
|
|
run.call()
|
|
}
|
|
}
|
|
val mgr = new ComponentManager(locks, provider, Some(ivyHome), logger)
|
|
f(mgr)
|
|
}
|
|
}
|
|
}
|