Merge pull request #313 from eed3si9n/wip/eviction

improve "X is evicted completely"
This commit is contained in:
eugene yokota 2019-08-14 12:40:50 -04:00 committed by GitHub
commit 9e1d4295e7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 645 additions and 555 deletions

View File

@ -27,6 +27,7 @@ def commonSettings: Seq[Setting[_]] = Def.settings(
resolvers += Resolver.sonatypeRepo("snapshots"),
resolvers += Resolver.sbtPluginRepo("releases"),
resolvers += "bintray-sbt-maven-releases" at "https://dl.bintray.com/sbt/maven-releases/",
testFrameworks += new TestFramework("verify.runner.Framework"),
// concurrentRestrictions in Global += Util.testExclusiveRestriction,
testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-w", "1"),
javacOptions in compile ++= Seq("-Xlint", "-Xlint:-serial"),
@ -96,7 +97,7 @@ lazy val lmCore = (project in file("core"))
okhttpUrlconnection,
sjsonnewScalaJson.value % Optional,
scalaTest % Test,
scalaCheck % Test
scalaCheck % Test,
),
libraryDependencies += scalaXml,
resourceGenerators in Compile += Def
@ -222,7 +223,7 @@ lazy val lmCommonTest = (project in file("common-test"))
commonSettings,
skip in publish := true,
name := "common-test",
libraryDependencies ++= Seq(scalaTest, scalaCheck),
libraryDependencies ++= Seq(scalaTest, scalaCheck, scalaVerify),
scalacOptions in (Compile, console) --=
Vector("-Ywarn-unused-import", "-Ywarn-unused", "-Xlint"),
mimaSettings,

View File

@ -1,8 +1,9 @@
package sbt.internal.librarymanagement
import sbt.librarymanagement._
import verify.BasicTestSuite
abstract class AbstractEngineSpec extends UnitSpec {
abstract class AbstractEngineSpec extends BasicTestSuite {
def cleanCache(): Unit
def module(

View File

@ -8,7 +8,7 @@ import sbt.librarymanagement.syntax._
abstract class ResolutionSpec extends AbstractEngineSpec {
import ShowLines._
"Resolving the same module twice" should "work" in {
test("Resolving the same module twice should work") {
cleanCache()
val m = module(
exampleModuleId("0.1.0"),
@ -22,10 +22,10 @@ abstract class ResolutionSpec extends AbstractEngineSpec {
println(report)
// second resolution reads from the minigraph
println(report.configurations.head.modules.head.artifacts)
report.configurations.size shouldBe 3
assert(report.configurations.size == 3)
}
"Resolving the unsolvable module should" should "not work" in {
test("Resolving the unsolvable module should should not work") {
// log.setLevel(Level.Debug)
val m = module(
exampleModuleId("0.2.0"),
@ -40,11 +40,15 @@ abstract class ResolutionSpec extends AbstractEngineSpec {
updateEither(m) match {
case Right(_) => sys.error("this should've failed 2")
case Left(uw) =>
uw.lines should contain allOf ("\n\tNote: Unresolved dependencies path:",
"\t\tfoundrylogic.vpp:vpp:2.2.1",
"\t\t +- org.apache.cayenne:cayenne-tools:3.0.2",
"\t\t +- org.apache.cayenne.plugins:maven-cayenne-plugin:3.0.2",
"\t\t +- com.example:foo:0.2.0")
List(
"\n\tNote: Unresolved dependencies path:",
"\t\tfoundrylogic.vpp:vpp:2.2.1",
"\t\t +- org.apache.cayenne:cayenne-tools:3.0.2",
"\t\t +- org.apache.cayenne.plugins:maven-cayenne-plugin:3.0.2",
"\t\t +- com.example:foo:0.2.0"
) foreach { line =>
assert(uw.lines.contains[String](line))
}
}
}
@ -52,7 +56,7 @@ abstract class ResolutionSpec extends AbstractEngineSpec {
// data-avro:1.9.40 depends on avro:1.4.0, which depends on netty:3.2.1.Final.
// avro:1.4.0 will be evicted by avro:1.7.7.
// #2046 says that netty:3.2.0.Final is incorrectly evicted by netty:3.2.1.Final
"Resolving a module with a pseudo-conflict" should "work" in {
test("Resolving a module with a pseudo-conflict should work") {
// log.setLevel(Level.Debug)
cleanCache()
val m = module(
@ -74,7 +78,7 @@ abstract class ResolutionSpec extends AbstractEngineSpec {
}))
}
"Resolving a module with sbt cross build" should "work" in {
test("Resolving a module with sbt cross build should work") {
cleanCache()
val attributes013 = Map("e:sbtVersion" -> "0.13", "e:scalaVersion" -> "2.10")
val attributes10 = Map("e:sbtVersion" -> "1.0", "e:scalaVersion" -> "2.12")
@ -88,11 +92,13 @@ abstract class ResolutionSpec extends AbstractEngineSpec {
Vector(sbtRelease.withExtraAttributes(attributes10)),
Some("2.12.3")
)
update(module013).configurations.head.modules.map(_.toString).loneElement should include(
"com.github.gseitz:sbt-release:1.0.6 (scalaVersion=2.10, sbtVersion=0.13)"
assert(
update(module013).configurations.head.modules.map(_.toString).loneElement
contains "com.github.gseitz:sbt-release:1.0.6 (scalaVersion=2.10, sbtVersion=0.13)"
)
update(module10).configurations.head.modules.map(_.toString).loneElement should include(
"com.github.gseitz:sbt-release:1.0.6 (scalaVersion=2.12, sbtVersion=1.0)"
assert(
update(module10).configurations.head.modules.map(_.toString).loneElement
contains "com.github.gseitz:sbt-release:1.0.6 (scalaVersion=2.12, sbtVersion=1.0)"
)
}

View File

@ -1,5 +0,0 @@
package sbt.internal.librarymanagement
import org.scalatest._
abstract class UnitSpec extends FlatSpec with Matchers

View File

@ -183,7 +183,7 @@ object EvictionPair {
}
val winnerRev = a.winner match {
case Some(r) => s":${r.module.revision} is selected over ${revsStr}"
case _ => " is evicted completely"
case _ => " is evicted for all versions"
}
val title = s"\t* ${a.organization}:${a.name}$winnerRev"
title :: (if (a.showCallers) callers.reverse else Nil) ::: List("")
@ -312,7 +312,9 @@ object EvictionWarning {
binaryIncompatibleEvictionExists = true
}
case p =>
if (!guessCompatible(p)) {
// don't report on a transitive eviction that does not have a winner
// https://github.com/sbt/sbt/issues/4946
if (!guessCompatible(p) && p.winner.isDefined) {
if (options.warnTransitiveEvictions)
transitiveEvictions += p
if (options.warnEvictionSummary)

View File

@ -7,65 +7,83 @@ import sbt.io.IO
import org.apache.ivy.util.ChecksumHelper
import IfMissing.Fail
import xsbti.ComponentProvider
import verify.BasicTestSuite
// 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 {
object ComponentManagerTest extends BasicTestSuite {
val TestID = "manager-test"
"Component manager" should "throw an exception if 'file' is called for a non-existing component" in {
test(
"Component manager should throw an exception if 'file' is called for a non-existing component"
) {
withManager { manager =>
intercept[InvalidComponent] { manager.file(TestID)(Fail) }
()
intercept[InvalidComponent] {
manager.file(TestID)(Fail)
()
}
}
}
it should "throw an exception if 'file' is called for an empty component" in {
test("it should throw an exception if 'file' is called for an empty component") {
withManager { manager =>
manager.define(TestID, Nil)
intercept[InvalidComponent] { manager.file(TestID)(Fail) }
()
intercept[InvalidComponent] {
manager.file(TestID)(Fail)
()
}
}
}
it should "return the file for a single-file component" in {
test("it should return the file for a single-file component") {
withManager { manager =>
val hash = defineFile(manager, TestID, "a")
checksum(manager.file(TestID)(Fail)) shouldBe hash
assert(checksum(manager.file(TestID)(Fail)) == hash)
}
}
it should "throw an exception if 'file' is called for multi-file component" in {
test("it should throw an exception if 'file' is called for multi-file component") {
withManager { manager =>
defineFiles(manager, TestID, "a", "b")
intercept[InvalidComponent] { manager.file(TestID)(Fail) }
()
intercept[InvalidComponent] {
manager.file(TestID)(Fail)
()
}
}
}
it should "return the files for a multi-file component" in {
test("it should return the files for a multi-file component") {
withManager { manager =>
val hashes = defineFiles(manager, TestID, "a", "b")
checksum(manager.files(TestID)(Fail)) should contain theSameElementsAs (hashes)
assert(checksum(manager.files(TestID)(Fail)).toSet == hashes.toSet)
}
}
it should "return the files for a single-file component" in {
test("it should return the files for a single-file component") {
withManager { manager =>
val hashes = defineFiles(manager, TestID, "a")
checksum(manager.files(TestID)(Fail)) should contain theSameElementsAs (hashes)
assert(checksum(manager.files(TestID)(Fail)).toSet == hashes.toSet)
}
}
it should "throw an exception if 'files' is called for a non-existing component" in {
test("it should throw an exception if 'files' is called for a non-existing component") {
withManager { manager =>
intercept[InvalidComponent] { manager.files(TestID)(Fail) }
()
intercept[InvalidComponent] {
manager.files(TestID)(Fail)
()
}
}
}
it should "properly cache a file and then retrieve it to an unresolved component" in {
test("it should properly cache a file and then retrieve it to an unresolved component") {
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
assert(checksum(usingManager.file(TestID)(Fail)) == hash)
}
} finally {
definingManager.clearCache(TestID)

View File

@ -8,9 +8,12 @@ import sbt.librarymanagement._
import sbt.librarymanagement.ivy.{ InlineIvyConfiguration, IvyPaths }
import sbt.io.IO.withTemporaryDirectory
import sbt.internal.util.ConsoleLogger
import verify.BasicTestSuite
class CustomPomParserTest extends UnitSpec {
"CustomPomParser" should "resolve an artifact with packaging 'scala-jar' as a regular jar file." in {
object CustomPomParserTest extends BasicTestSuite {
test(
"CustomPomParser should resolve an artifact with packaging 'scala-jar' as a regular jar file."
) {
val log = ConsoleLogger()
withTemporaryDirectory { cacheDir =>
val repoUrl = getClass.getResource("/test-maven-repo")
@ -28,12 +31,12 @@ class CustomPomParserTest extends UnitSpec {
ivy.resolve(mrid, resolveOpts, true)
}
resolveReport.hasError shouldBe false
resolveReport.getArtifacts.size() shouldBe 1
assert(!resolveReport.hasError)
assert(resolveReport.getArtifacts.size() == 1)
val artifact: IvyArtifact =
resolveReport.getArtifacts.asInstanceOf[java.util.List[IvyArtifact]].get(0)
artifact.getModuleRevisionId shouldBe mrid
artifact.getExt shouldBe "jar"
assert(artifact.getModuleRevisionId == mrid)
assert(artifact.getExt == "jar")
}
}
}

View File

@ -6,47 +6,59 @@ import java.io.File
import sbt.librarymanagement._
import sjsonnew.shaded.scalajson.ast.unsafe._
import sjsonnew._, support.scalajson.unsafe._
import org.scalatest.Assertion
import LibraryManagementCodec._
import verify.BasicTestSuite
class DMSerializationSpec extends UnitSpec {
"CrossVersion.full" should "roundtrip" in {
object DMSerializationSpec extends BasicTestSuite {
test("CrossVersion.full should roundtrip") {
roundtripStr(CrossVersion.full: CrossVersion)
}
"CrossVersion.binary" should "roundtrip" in {
test("CrossVersion.binary should roundtrip") {
roundtripStr(CrossVersion.binary: CrossVersion)
}
"CrossVersion.Disabled" should "roundtrip" in {
test("CrossVersion.Disabled should roundtrip") {
roundtrip(Disabled(): CrossVersion)
}
"""Artifact("foo")""" should "roundtrip" in {
test("""Artifact("foo") should roundtrip""") {
roundtrip(Artifact("foo"))
}
"""Artifact("foo", "sources")""" should "roundtrip" in {
test("""Artifact("foo", "sources") should roundtrip""") {
roundtrip(Artifact("foo", "sources"))
}
"""Artifact.pom("foo")""" should "roundtrip" in {
test("""Artifact.pom("foo") should roundtrip""") {
roundtrip(Artifact.pom("foo"))
}
"""Artifact("foo", url("http://example.com/"))""" should "roundtrip" in {
test("""Artifact("foo", url("http://example.com/")) should roundtrip""") {
roundtrip(Artifact("foo", new URL("http://example.com/")))
}
"""Artifact("foo").extra(("key", "value"))""" should "roundtrip" in {
test("""Artifact("foo").extra(("key", "value")) should roundtrip""") {
roundtrip(Artifact("foo").extra(("key", "value")))
}
"""ModuleID("org", "name", "1.0")""" should "roundtrip" in {
test("""ModuleID("org", "name", "1.0") should roundtrip""") {
roundtrip(ModuleID("org", "name", "1.0"))
}
"""ModuleReport(ModuleID("org", "name", "1.0"), Nil, Nil)""" should "roundtrip" in {
test("""ModuleReport(ModuleID("org", "name", "1.0"), Nil, Nil) should roundtrip""") {
roundtripStr(ModuleReport(ModuleID("org", "name", "1.0"), Vector.empty, Vector.empty))
}
"Organization artifact report" should "roundtrip" in {
test("Organization artifact report should roundtrip") {
roundtripStr(organizationArtifactReportExample)
}
"Configuration report" should "roundtrip" in {
test("Configuration report should roundtrip") {
roundtripStr(configurationReportExample)
}
"Update report" should "roundtrip" in {
test("Update report should roundtrip") {
roundtripStr(updateReportExample)
}
@ -68,13 +80,17 @@ class DMSerializationSpec extends UnitSpec {
lazy val moduleReportExample =
ModuleReport(ModuleID("org", "name", "1.0"), Vector.empty, Vector.empty)
def roundtrip[A: JsonReader: JsonWriter](a: A): Assertion =
roundtripBuilder(a) { _ shouldBe _ }
def roundtrip[A: JsonReader: JsonWriter](a: A): Unit =
roundtripBuilder(a) { (x1, x2) =>
assert(x1 == x2)
}
def roundtripStr[A: JsonReader: JsonWriter](a: A): Assertion =
roundtripBuilder(a) { _.toString shouldBe _.toString }
def roundtripStr[A: JsonReader: JsonWriter](a: A): Unit =
roundtripBuilder(a) { (x1, x2) =>
assert(x1.toString == x2.toString)
}
def roundtripBuilder[A: JsonReader: JsonWriter](a: A)(f: (A, A) => Assertion): Assertion = {
def roundtripBuilder[A: JsonReader: JsonWriter](a: A)(f: (A, A) => Unit): Unit = {
val json = isoString to (Converter toJsonUnsafe a)
println(json)
val obj = Converter fromJsonUnsafe [A] (isoString from json)

View File

@ -4,52 +4,269 @@ import sbt.librarymanagement._
import sbt.internal.librarymanagement.cross.CrossVersionUtil
import sbt.librarymanagement.syntax._
class EvictionWarningSpec extends BaseIvySpecification {
object EvictionWarningSpec extends BaseIvySpecification {
// This is a specification to check the eviction warnings
"""Eviction of non-overridden scala-library whose scalaVersion
""" should "be detected" in scalaVersionWarn1()
it should "not be detected if it's disabled" in scalaVersionWarn2()
it should "print out message about the eviction" in scalaVersionWarn3()
it should "print out message about the eviction with callers" in scalaVersionWarn4()
it should "print out summary about the eviction if warn eviction summary enabled" in scalaVersionWarn5()
import sbt.util.ShowLines._
def scalaVersionDeps = Vector(scala2102, akkaActor230)
"""Non-eviction of overridden scala-library whose scalaVersion
""" should "not be detected if it's enabled" in scalaVersionNoWarn1()
it should "not be detected if it's disabled" in scalaVersionNoWarn2()
test("Eviction of non-overridden scala-library whose scalaVersion should be detected") {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m)
assert(EvictionWarning(m, fullOptions, report).scalaEvictions.size == 1)
}
"""Including two (suspect) binary incompatible Java libraries to direct dependencies
""" should "be detected as eviction" in javaLibWarn1()
it should "not be detected if it's disabled" in javaLibWarn2()
it should "print out message about the eviction" in javaLibWarn3()
it should "print out message about the eviction with callers" in javaLibWarn4()
it should "print out summary about the eviction if warn eviction summary enabled" in javaLibWarn5()
test("it should not be detected if it's disabled") {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m)
assert(
EvictionWarning(m, fullOptions.withWarnScalaVersionEviction(false), report).scalaEvictions.size == 0
)
}
"""Including two (suspect) binary compatible Java libraries to direct dependencies
""" should "not be detected as eviction" in javaLibNoWarn1()
it should "not print out message about the eviction" in javaLibNoWarn2()
test("it should print out message about the eviction") {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m)
assert(
EvictionWarning(m, fullOptions.withShowCallers(false), report).lines ==
List(
"Scala version was updated by one of library dependencies:",
"\t* org.scala-lang:scala-library:2.10.3 is selected over 2.10.2",
"",
"To force scalaVersion, add the following:",
"\tscalaModuleInfo ~= (_.map(_.withOverrideScalaVersion(true)))"
)
)
}
"""Including two (suspect) transitively binary incompatible Java libraries to direct dependencies
""" should "be detected as eviction" in javaLibTransitiveWarn2()
test("it should print out message about the eviction with callers") {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m)
assert(
EvictionWarning(m, fullOptions, report).lines ==
List(
"Scala version was updated by one of library dependencies:",
"\t* org.scala-lang:scala-library:2.10.3 is selected over 2.10.2",
"\t +- com.typesafe.akka:akka-actor_2.10:2.3.0 (depends on 2.10.3)",
"\t +- com.example:foo:0.1.0 (depends on 2.10.2)",
"",
"To force scalaVersion, add the following:",
"\tscalaModuleInfo ~= (_.map(_.withOverrideScalaVersion(true)))"
)
)
}
//it should "print out message about the eviction if it's enabled" in javaLibTransitiveWarn3()
test("it should print out summary about the eviction if warn eviction summary enabled") {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m)
assert(
EvictionWarning(m, EvictionWarningOptions.summary, report).lines ==
List(
"There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings."
)
)
}
"""Including two (suspect) binary incompatible Scala libraries to direct dependencies
""" should "be detected as eviction" in scalaLibWarn1()
it should "print out message about the eviction" in scalaLibWarn2()
it should "print out summary about the eviction if warn eviction summary enabled" in scalaLibWarn3()
test(
"""Non-eviction of overridden scala-library whose scalaVersion should "not be detected if it's enabled""""
) {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
val report = ivyUpdate(m)
assert(EvictionWarning(m, fullOptions, report).scalaEvictions.size == 0)
}
"""Including two (suspect) binary compatible Scala libraries to direct dependencies
""" should "not be detected as eviction" in scalaLibNoWarn1()
it should "not print out message about the eviction" in scalaLibNoWarn2()
it should "not print out summary about the eviction even if warn eviction summary enabled" in scalaLibNoWarn3()
test("it should not be detected if it's disabled") {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
val report = ivyUpdate(m)
assert(
EvictionWarning(m, fullOptions.withWarnScalaVersionEviction(false), report).scalaEvictions.size == 0
)
}
"""Including two (suspect) transitively binary incompatible Scala libraries to direct dependencies
""" should "be detected as eviction" in scalaLibTransitiveWarn2()
it should "print out message about the eviction if it's enabled" in scalaLibTransitiveWarn3()
it should "print out summary about the eviction if warn eviction summary enabled" in scalaLibTransitiveWarn4()
test(
"""Including two (suspect) binary incompatible Java libraries to direct dependencies should be detected as eviction"""
) {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
val report = ivyUpdate(m)
assert(EvictionWarning(m, fullOptions, report).reportedEvictions.size == 1)
}
"Comparing sbt 0.x" should "use Second Segment Variation semantics" in {
test("it should not be detected if it's disabled") {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
val report = ivyUpdate(m)
assert(
EvictionWarning(
m,
fullOptions
.withWarnDirectEvictions(false)
.withWarnTransitiveEvictions(false),
report
).reportedEvictions.size == 0
)
}
test("it should print out message about the eviction") {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
val report = ivyUpdate(m)
assert(
EvictionWarning(m, fullOptions, report).lines ==
List(
"Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:",
"",
"\t* commons-io:commons-io:2.4 is selected over 1.4",
"\t +- com.example:foo:0.1.0 (depends on 1.4)",
""
)
)
}
test("it should print out message about the eviction with callers") {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
val report = ivyUpdate(m)
assert(
EvictionWarning(m, fullOptions.withShowCallers(true), report).lines ==
List(
"Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:",
"",
"\t* commons-io:commons-io:2.4 is selected over 1.4",
"\t +- com.example:foo:0.1.0 (depends on 1.4)",
""
)
)
}
test("it should print out summary about the eviction if warn eviction summary enabled") {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
val report = ivyUpdate(m)
assert(
EvictionWarning(m, EvictionWarningOptions.summary, report).lines ==
List(
"There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings."
)
)
}
test(
"""Including two (suspect) binary compatible Java libraries to direct dependencies should not be detected as eviction"""
) {
val deps = Vector(commonsIo14, commonsIo13)
val m = module(defaultModuleId, deps, Some("2.10.3"))
val report = ivyUpdate(m)
assert(EvictionWarning(m, fullOptions, report).reportedEvictions.size == 0)
}
test("it should not print out message about the eviction") {
val deps = Vector(commonsIo14, commonsIo13)
val m = module(defaultModuleId, deps, Some("2.10.3"))
val report = ivyUpdate(m)
assert(EvictionWarning(m, fullOptions, report).lines == Nil)
}
test(
"""Including two (suspect) transitively binary incompatible Java libraries to direct dependencies should be detected as eviction"""
) {
val m = module(defaultModuleId, javaLibTransitiveDeps, Some("2.10.3"))
val report = ivyUpdate(m)
assert(EvictionWarning(m, fullOptions, report).reportedEvictions.size == 1)
}
test(
"""Including two (suspect) binary incompatible Scala libraries to direct dependencies should be detected as eviction"""
) {
val deps = Vector(scala2104, akkaActor214, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
assert(EvictionWarning(m, fullOptions, report).reportedEvictions.size == 1)
}
test("it should print out message about the eviction") {
val deps = Vector(scala2104, akkaActor214, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
assert(
EvictionWarning(m, fullOptions, report).lines ==
List(
"Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:",
"",
"\t* com.typesafe.akka:akka-actor_2.10:2.3.4 is selected over 2.1.4",
"\t +- com.example:foo:0.1.0 (depends on 2.1.4)",
""
)
)
}
test("it should print out summary about the eviction if warn eviction summary enabled") {
val deps = Vector(scala2104, akkaActor214, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
assert(
EvictionWarning(m, EvictionWarningOptions.summary, report).lines ==
List(
"There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings."
)
)
}
test(
"""Including two (suspect) binary compatible Scala libraries to direct dependencies should not be detected as eviction"""
) {
val deps = Vector(scala2104, akkaActor230, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
assert(EvictionWarning(m, fullOptions, report).reportedEvictions.size == 0)
}
test("it should not print out message about the eviction") {
val deps = Vector(scala2104, akkaActor230, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
assert(EvictionWarning(m, fullOptions, report).lines == Nil)
}
test("it should not print out summary about the eviction even if warn eviction summary enabled") {
val deps = Vector(scala2104, akkaActor230, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
assert(EvictionWarning(m, EvictionWarningOptions.summary, report).lines == Nil)
}
test(
"""Including two (suspect) transitively binary incompatible Scala libraries to direct dependencies should be detected as eviction"""
) {
val m = module(defaultModuleId, scalaLibTransitiveDeps, Some("2.10.4"))
val report = ivyUpdate(m)
assert(EvictionWarning(m, fullOptions, report).reportedEvictions.size == 1)
}
test("it should print out message about the eviction if it's enabled") {
val m = module(defaultModuleId, scalaLibTransitiveDeps, Some("2.10.4"))
val report = ivyUpdate(m)
assert(
EvictionWarning(m, fullOptions, report).lines ==
List(
"Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:",
"",
"\t* com.typesafe.akka:akka-actor_2.10:2.3.4 is selected over 2.1.4",
"\t +- com.typesafe.akka:akka-remote_2.10:2.3.4 (depends on 2.3.4)",
"\t +- org.w3:banana-rdf_2.10:0.4 (depends on 2.1.4)",
"\t +- org.w3:banana-sesame_2.10:0.4 (depends on 2.1.4)",
""
)
)
}
test("it should print out summary about the eviction if warn eviction summary enabled") {
val m = module(defaultModuleId, scalaLibTransitiveDeps, Some("2.10.4"))
val report = ivyUpdate(m)
assert(
EvictionWarning(m, EvictionWarningOptions.summary, report).lines ==
List(
"There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings."
)
)
}
test("Comparing sbt 0.x should use Second Segment Variation semantics") {
val m1 = "org.scala-sbt" % "util-logging" % "0.13.16"
val m2 = "org.scala-sbt" % "util-logging" % "0.13.1"
assert(
@ -57,7 +274,7 @@ class EvictionWarningSpec extends BaseIvySpecification {
)
}
"Comparing sbt 1.x" should "use Semantic Versioning semantics" in {
test("Comparing sbt 1.x should use Semantic Versioning semantics") {
val m1 = "org.scala-sbt" % "util-logging_2.12" % "1.0.0"
val m2 = "org.scala-sbt" % "util-logging_2.12" % "1.1.0"
assert(
@ -91,244 +308,9 @@ class EvictionWarningSpec extends BaseIvySpecification {
ModuleID("com.typesafe.akka", "akka-remote", "2.3.4").withConfigurations(Some("compile")) cross CrossVersion.binary // uses akka-actor 2.3.4
def fullOptions = EvictionWarningOptions.full
import sbt.util.ShowLines._
def scalaVersionDeps = Vector(scala2102, akkaActor230)
def scalaVersionWarn1() = {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).scalaEvictions should have size (1)
}
def scalaVersionWarn2() = {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions.withWarnScalaVersionEviction(false), report).scalaEvictions should have size (0)
}
def scalaVersionWarn3() = {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions.withShowCallers(false), report).lines shouldBe
List(
"Scala version was updated by one of library dependencies:",
"\t* org.scala-lang:scala-library:2.10.3 is selected over 2.10.2",
"",
"To force scalaVersion, add the following:",
"\tscalaModuleInfo ~= (_.map(_.withOverrideScalaVersion(true)))"
)
}
def scalaVersionWarn4() = {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).lines shouldBe
List(
"Scala version was updated by one of library dependencies:",
"\t* org.scala-lang:scala-library:2.10.3 is selected over 2.10.2",
"\t +- com.typesafe.akka:akka-actor_2.10:2.3.0 (depends on 2.10.3)",
"\t +- com.example:foo:0.1.0 (depends on 2.10.2)",
"",
"To force scalaVersion, add the following:",
"\tscalaModuleInfo ~= (_.map(_.withOverrideScalaVersion(true)))"
)
}
def scalaVersionWarn5() = {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"), overrideScalaVersion = false)
val report = ivyUpdate(m)
EvictionWarning(m, EvictionWarningOptions.summary, report).lines shouldBe
List(
"There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings."
)
}
def scalaVersionNoWarn1() = {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).scalaEvictions should have size (0)
}
def scalaVersionNoWarn2() = {
val m = module(defaultModuleId, scalaVersionDeps, Some("2.10.2"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions.withWarnScalaVersionEviction(false), report).scalaEvictions should have size (0)
}
def javaLibDirectDeps = Vector(commonsIo14, commonsIo24)
def javaLibWarn1() = {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).reportedEvictions should have size (1)
}
def javaLibWarn2() = {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(
m,
fullOptions
.withWarnDirectEvictions(false)
.withWarnTransitiveEvictions(false),
report
).reportedEvictions should have size (0)
}
def javaLibWarn3() = {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).lines shouldBe
List(
"Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:",
"",
"\t* commons-io:commons-io:2.4 is selected over 1.4",
"\t +- com.example:foo:0.1.0 (depends on 1.4)",
""
)
}
def javaLibWarn4() = {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions.withShowCallers(true), report).lines shouldBe
List(
"Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:",
"",
"\t* commons-io:commons-io:2.4 is selected over 1.4",
"\t +- com.example:foo:0.1.0 (depends on 1.4)",
""
)
}
def javaLibWarn5() = {
val m = module(defaultModuleId, javaLibDirectDeps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(m, EvictionWarningOptions.summary, report).lines shouldBe
List(
"There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings."
)
}
def javaLibNoWarn1() = {
val deps = Vector(commonsIo14, commonsIo13)
val m = module(defaultModuleId, deps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).reportedEvictions should have size (0)
}
def javaLibNoWarn2() = {
val deps = Vector(commonsIo14, commonsIo13)
val m = module(defaultModuleId, deps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).lines shouldBe Nil
}
def javaLibTransitiveDeps = Vector(unfilteredUploads080, bnfparser10)
def javaLibTransitiveWarn2() = {
val m = module(defaultModuleId, javaLibTransitiveDeps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).reportedEvictions should have size (1)
}
def javaLibTransitiveWarn3() = {
val m = module(defaultModuleId, javaLibTransitiveDeps, Some("2.10.3"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).lines shouldBe
List(
"There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings.",
"Here are some of the libraries that were evicted:",
"\t* commons-io:commons-io:1.4 -> 2.4 (caller: ca.gobits.bnf:bnfparser:1.0, net.databinder:unfiltered-uploads_2.10:0.8.0)"
)
}
def scalaLibWarn1() = {
val deps = Vector(scala2104, akkaActor214, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).reportedEvictions should have size (1)
}
def scalaLibWarn2() = {
val deps = Vector(scala2104, akkaActor214, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).lines shouldBe
List(
"Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:",
"",
"\t* com.typesafe.akka:akka-actor_2.10:2.3.4 is selected over 2.1.4",
"\t +- com.example:foo:0.1.0 (depends on 2.1.4)",
""
)
}
def scalaLibWarn3() = {
val deps = Vector(scala2104, akkaActor214, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, EvictionWarningOptions.summary, report).lines shouldBe
List(
"There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings."
)
}
def scalaLibNoWarn1() = {
val deps = Vector(scala2104, akkaActor230, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).reportedEvictions should have size (0)
}
def scalaLibNoWarn2() = {
val deps = Vector(scala2104, akkaActor230, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).lines shouldBe Nil
}
def scalaLibNoWarn3() = {
val deps = Vector(scala2104, akkaActor230, akkaActor234)
val m = module(defaultModuleId, deps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, EvictionWarningOptions.summary, report).lines shouldBe Nil
}
def scalaLibTransitiveDeps = Vector(scala2104, bananaSesame04, akkaRemote234)
def scalaLibTransitiveWarn2() = {
val m = module(defaultModuleId, scalaLibTransitiveDeps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).reportedEvictions should have size (1)
}
def scalaLibTransitiveWarn3() = {
val m = module(defaultModuleId, scalaLibTransitiveDeps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, fullOptions, report).lines shouldBe
List(
"Found version conflict(s) in library dependencies; some are suspected to be binary incompatible:",
"",
"\t* com.typesafe.akka:akka-actor_2.10:2.3.4 is selected over 2.1.4",
"\t +- com.typesafe.akka:akka-remote_2.10:2.3.4 (depends on 2.3.4)",
"\t +- org.w3:banana-rdf_2.10:0.4 (depends on 2.1.4)",
"\t +- org.w3:banana-sesame_2.10:0.4 (depends on 2.1.4)",
""
)
}
def scalaLibTransitiveWarn4() = {
val m = module(defaultModuleId, scalaLibTransitiveDeps, Some("2.10.4"))
val report = ivyUpdate(m)
EvictionWarning(m, EvictionWarningOptions.summary, report).lines shouldBe
List(
"There may be incompatibilities among your library dependencies; run 'evicted' to see detailed eviction warnings."
)
}
def dummyScalaModuleInfo(v: String): ScalaModuleInfo =
ScalaModuleInfo(
scalaFullVersion = v,

View File

@ -6,7 +6,7 @@ import java.io.File
import sbt.librarymanagement.{ ModuleID, RawRepository, Resolver, UpdateReport, ResolveException }
class FakeResolverSpecification extends BaseIvySpecification {
object FakeResolverSpecification extends BaseIvySpecification {
import FakeResolver._
val myModule =
@ -17,36 +17,42 @@ class FakeResolverSpecification extends BaseIvySpecification {
val nonExisting =
ModuleID("com.example", "does-not-exist", "1.2.3").withConfigurations(Some("compile"))
"The FakeResolver" should "find modules with only one artifact" in {
test("The FakeResolver should find modules with only one artifact") {
val m = getModule(myModule)
val report = ivyUpdate(m)
val allFiles = getAllFiles(report)
report.allModules.length shouldBe 1
report.configurations.length shouldBe 3
allFiles.toSet.size shouldBe 1
allFiles(1).getName shouldBe "artifact1-0.0.1-SNAPSHOT.jar"
assert(report.allModules.length == 1)
assert(report.configurations.length == 3)
assert(allFiles.toSet.size == 1)
assert(allFiles(1).getName == "artifact1-0.0.1-SNAPSHOT.jar")
}
it should "find modules with more than one artifact" in {
test("it should find modules with more than one artifact") {
val m = getModule(example)
val report = ivyUpdate(m)
val allFiles = getAllFiles(report).toSet
report.allModules.length shouldBe 1
report.configurations.length shouldBe 3
allFiles.toSet.size shouldBe 2
allFiles map (_.getName) shouldBe Set("artifact1-1.0.0.jar", "artifact2-1.0.0.txt")
assert(report.allModules.length == 1)
assert(report.configurations.length == 3)
assert(allFiles.toSet.size == 2)
assert(allFiles.map(_.getName) == Set("artifact1-1.0.0.jar", "artifact2-1.0.0.txt"))
}
it should "fail gracefully when asked for unknown modules" in {
test("it should fail gracefully when asked for unknown modules") {
val m = getModule(nonExisting)
a[ResolveException] should be thrownBy ivyUpdate(m)
intercept[ResolveException] {
ivyUpdate(m)
()
}
}
it should "fail gracefully when some artifacts cannot be found" in {
test("it should fail gracefully when some artifacts cannot be found") {
val m = getModule(anotherExample)
the[ResolveException] thrownBy ivyUpdate(m) should have message "download failed: com.example#another-example;1.0.0!non-existing.txt"
intercept[ResolveException] {
ivyUpdate(m)
()
}
}
private def artifact1 = new File(getClass.getResource("/artifact1.jar").toURI.getPath)

View File

@ -4,7 +4,7 @@ import sbt.librarymanagement._
import sbt.librarymanagement.ivy.UpdateOptions
import sbt.librarymanagement.syntax._
class FrozenModeSpec extends BaseIvySpecification {
object FrozenModeSpec extends BaseIvySpecification {
private final val targetDir = Some(currentDependency)
private final val onlineConf = makeUpdateConfiguration(false, targetDir)
private final val frozenConf = makeUpdateConfiguration(false, targetDir).withFrozen(true)
@ -26,7 +26,7 @@ class FrozenModeSpec extends BaseIvySpecification {
"com.lihaoyi" % "sourcecode_2.12" % "0.1.3" % "compile"
)
it should "fail when artifacts are missing in the cache" in {
test("fail when artifacts are missing in the cache") {
cleanIvyCache()
def update(module: IvySbt#Module, conf: UpdateConfiguration) =
IvyActions.updateEither(module, conf, warningConf, log)

View File

@ -2,10 +2,53 @@ package sbt.internal.librarymanagement
import sbt.librarymanagement._
import sbt.librarymanagement.syntax._
import org.scalatest.Assertion
import DependencyBuilders.OrganizationArtifactName
class InclExclSpec extends BaseIvySpecification {
object InclExclSpec extends BaseIvySpecification {
val scala210 = Some("2.10.4")
test("it should exclude any version of lift-json via a new exclusion rule") {
val toExclude = ExclusionRule("net.liftweb", "lift-json_2.10")
val report = getIvyReport(createLiftDep(toExclude), scala210)
testLiftJsonIsMissing(report)
}
test("it should exclude any version of lift-json with explicit Scala version") {
val excluded: OrganizationArtifactName = "net.liftweb" % "lift-json_2.10"
val report = getIvyReport(createLiftDep(excluded), scala210)
testLiftJsonIsMissing(report)
}
test("it should exclude any version of cross-built lift-json") {
val excluded: OrganizationArtifactName = "net.liftweb" %% "lift-json"
val report = getIvyReport(createLiftDep(excluded), scala210)
testLiftJsonIsMissing(report)
}
val scala2122 = Some("2.12.2")
test("it should exclude a concrete version of lift-json when it's full cross version") {
val excluded: ModuleID = ("org.scalameta" % "scalahost" % "1.7.0").cross(CrossVersion.full)
val report = getIvyReport(createMetaDep(excluded), scala2122)
testScalahostIsMissing(report)
}
test("it should exclude any version of lift-json when it's full cross version") {
val excluded = new OrganizationArtifactName("net.liftweb", "lift-json", CrossVersion.full)
val report = getIvyReport(createMetaDep(excluded), scala2122)
testScalahostIsMissing(report)
}
test("it should exclude any version of scala-library via * artifact id") {
val toExclude = ExclusionRule("org.scala-lang", "*")
val report = getIvyReport(createLiftDep(toExclude), scala210)
testScalaLibraryIsMissing(report)
}
test("it should exclude any version of scala-library via * org id") {
val toExclude = ExclusionRule("*", "scala-library")
val report = getIvyReport(createLiftDep(toExclude), scala210)
testScalaLibraryIsMissing(report)
}
def createLiftDep(toExclude: ExclusionRule): ModuleID =
("net.liftweb" %% "lift-mapper" % "2.6-M4" % "compile").excludeAll(toExclude)
@ -20,68 +63,24 @@ class InclExclSpec extends BaseIvySpecification {
ivyUpdate(ivyModule)
}
def testLiftJsonIsMissing(report: UpdateReport): Assertion = {
def testLiftJsonIsMissing(report: UpdateReport): Unit = {
assert(
!report.allModules.exists(_.name.contains("lift-json")),
"lift-json has not been excluded."
)
}
def testScalaLibraryIsMissing(report: UpdateReport): Assertion = {
def testScalaLibraryIsMissing(report: UpdateReport): Unit = {
assert(
!report.allModules.exists(_.name.contains("scala-library")),
"scala-library has not been excluded."
)
}
def testScalahostIsMissing(report: UpdateReport): Assertion = {
def testScalahostIsMissing(report: UpdateReport): Unit = {
assert(
!report.allModules.exists(_.name.contains("scalahost")),
"scalahost has not been excluded."
)
}
val scala210 = Some("2.10.4")
it should "exclude any version of lift-json via a new exclusion rule" in {
val toExclude = ExclusionRule("net.liftweb", "lift-json_2.10")
val report = getIvyReport(createLiftDep(toExclude), scala210)
testLiftJsonIsMissing(report)
}
it should "exclude any version of lift-json with explicit Scala version" in {
val excluded: OrganizationArtifactName = "net.liftweb" % "lift-json_2.10"
val report = getIvyReport(createLiftDep(excluded), scala210)
testLiftJsonIsMissing(report)
}
it should "exclude any version of cross-built lift-json" in {
val excluded: OrganizationArtifactName = "net.liftweb" %% "lift-json"
val report = getIvyReport(createLiftDep(excluded), scala210)
testLiftJsonIsMissing(report)
}
val scala2122 = Some("2.12.2")
it should "exclude a concrete version of lift-json when it's full cross version" in {
val excluded: ModuleID = ("org.scalameta" % "scalahost" % "1.7.0").cross(CrossVersion.full)
val report = getIvyReport(createMetaDep(excluded), scala2122)
testScalahostIsMissing(report)
}
it should "exclude any version of lift-json when it's full cross version" in {
val excluded = new OrganizationArtifactName("net.liftweb", "lift-json", CrossVersion.full)
val report = getIvyReport(createMetaDep(excluded), scala2122)
testScalahostIsMissing(report)
}
it should "exclude any version of scala-library via * artifact id" in {
val toExclude = ExclusionRule("org.scala-lang", "*")
val report = getIvyReport(createLiftDep(toExclude), scala210)
testScalaLibraryIsMissing(report)
}
it should "exclude any version of scala-library via * org id" in {
val toExclude = ExclusionRule("*", "scala-library")
val report = getIvyReport(createLiftDep(toExclude), scala210)
testScalaLibraryIsMissing(report)
}
}

View File

@ -1,23 +1,26 @@
package sbt.internal.librarymanagement
import sbt.librarymanagement._
import verify.BasicTestSuite
// This is a specification to check the inconsistent duplicate warnings
class InconsistentDuplicateSpec extends UnitSpec {
"Duplicate with different version" should "be warned" in {
IvySbt.inconsistentDuplicateWarning(Seq(akkaActor214, akkaActor230)) shouldBe
List(
"Multiple dependencies with the same organization/name but different versions. To avoid conflict, pick one version:",
" * com.typesafe.akka:akka-actor:(2.1.4, 2.3.0)"
)
object InconsistentDuplicateSpec extends BasicTestSuite {
test("Duplicate with different version should be warned") {
assert(
IvySbt.inconsistentDuplicateWarning(Seq(akkaActor214, akkaActor230)) ==
List(
"Multiple dependencies with the same organization/name but different versions. To avoid conflict, pick one version:",
" * com.typesafe.akka:akka-actor:(2.1.4, 2.3.0)"
)
)
}
it should "not be warned if in different configurations" in {
IvySbt.inconsistentDuplicateWarning(Seq(akkaActor214, akkaActor230Test)) shouldBe Nil
test("it should not be warned if in different configurations") {
assert(IvySbt.inconsistentDuplicateWarning(Seq(akkaActor214, akkaActor230Test)) == Nil)
}
"Duplicate with same version" should "not be warned" in {
IvySbt.inconsistentDuplicateWarning(Seq(akkaActor230Test, akkaActor230)) shouldBe Nil
test("Duplicate with same version should not be warned") {
assert(IvySbt.inconsistentDuplicateWarning(Seq(akkaActor230Test, akkaActor230)) == Nil)
}
def akkaActor214 =

View File

@ -5,7 +5,7 @@ import sbt.librarymanagement._
import sbt.librarymanagement.syntax._
import InternalDefaults._
class IvyRepoSpec extends BaseIvySpecification {
object IvyRepoSpec extends BaseIvySpecification {
val ourModuleID = ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile"))
@ -21,7 +21,9 @@ class IvyRepoSpec extends BaseIvySpecification {
)
}
"ivyUpdate from ivy repository" should "resolve only binary artifact from module which also contains a sources artifact under the same configuration." in {
test(
"ivyUpdate from ivy repository should resolve only binary artifact from module which also contains a sources artifact under the same configuration."
) {
cleanIvyCache()
val m = makeModuleForDepWithSources
@ -33,13 +35,15 @@ class IvyRepoSpec extends BaseIvySpecification {
case Some(Seq(mr)) =>
inside(mr.artifacts) {
case Seq((ar, _)) =>
ar.`type` shouldBe "jar"
ar.extension shouldBe "jar"
assert(ar.`type` == "jar")
assert(ar.extension == "jar")
}
}
}
it should "resolve only sources artifact of an acceptable artifact type, \"src\", when calling updateClassifiers." in {
test(
"it should resolve only sources artifact of an acceptable artifact type, \"src\", when calling updateClassifiers."
) {
cleanIvyCache()
val m = makeModuleForDepWithSources
@ -90,9 +94,9 @@ class IvyRepoSpec extends BaseIvySpecification {
case Some(Seq(mr)) =>
inside(mr.artifacts) {
case Seq((ar, _)) =>
ar.name shouldBe "libmodule-source"
ar.`type` shouldBe "src"
ar.extension shouldBe "jar"
assert(ar.name == "libmodule-source")
assert(ar.`type` == "src")
assert(ar.extension == "jar")
}
}
}

View File

@ -1,79 +1,87 @@
package sbt.internal.librarymanagement
import sbt.internal.util.ConsoleLogger
import verify.BasicTestSuite
// http://ant.apache.org/ivy/history/2.3.0/ivyfile/dependency.html
// http://maven.apache.org/enforcer/enforcer-rules/versionRanges.html
class MakePomSpec extends UnitSpec {
object MakePomSpec extends BasicTestSuite {
// This is a specification to check the Ivy revision number conversion to pom.
"1.0" should "convert to 1.0" in convertTo("1.0", "1.0")
test("1.0 should convert to 1.0") {
convertTo("1.0", "1.0")
}
"[1.0,2.0]" should "convert to [1.0,2.0]" in {
test("[1.0,2.0] should convert to [1.0,2.0]") {
convertTo("[1.0,2.0]", "[1.0,2.0]")
}
"[1.0,2.0[" should "convert to [1.0,2.0)" in {
test("[1.0,2.0[ should convert to [1.0,2.0)") {
convertTo("[1.0,2.0[", "[1.0,2.0)")
}
"]1.0,2.0]" should "convert to (1.0,2.0]" in {
test("]1.0,2.0] should convert to (1.0,2.0]") {
convertTo("]1.0,2.0]", "(1.0,2.0]")
}
"]1.0,2.0[" should "convert to (1.0,2.0)" in {
test("]1.0,2.0[ should convert to (1.0,2.0)") {
convertTo("]1.0,2.0[", "(1.0,2.0)")
}
"[1.0,)" should "convert to [1.0,)" in {
test("[1.0,) should convert to [1.0,)") {
convertTo("[1.0,)", "[1.0,)")
}
"]1.0,)" should "convert to (1.0,)" in {
test("]1.0,) should convert to (1.0,)") {
convertTo("]1.0,)", "(1.0,)")
}
"(,2.0]" should "convert to (,2.0]" in {
test("(,2.0] should convert to (,2.0]") {
convertTo("(,2.0]", "(,2.0]")
}
"(,2.0[" should "convert to (,2.0)" in {
test("(,2.0[ should convert to (,2.0)") {
convertTo("(,2.0[", "(,2.0)")
}
"1.+" should "convert to [1,2)" in {
test("1.+ should convert to [1,2)") {
convertTo("1.+", "[1,2)")
}
"1.2.3.4.+" should "convert to [1.2.3.4,1.2.3.5)" in {
test("1.2.3.4.+ should convert to [1.2.3.4,1.2.3.5)") {
convertTo("1.2.3.4.+", "[1.2.3.4,1.2.3.5)")
}
"12.31.42.+" should "convert to [12.31.42,12.31.43)" in {
test("12.31.42.+ should convert to [12.31.42,12.31.43)") {
convertTo("12.31.42.+", "[12.31.42,12.31.43)")
}
"1.1+" should "convert to [1.1,1.2),[1.10,1.20),[1.100,1.200),[1.1000,1.2000),[1.10000,1.20000)" in {
test(
"1.1+ should convert to [1.1,1.2),[1.10,1.20),[1.100,1.200),[1.1000,1.2000),[1.10000,1.20000)"
) {
convertTo("1.1+", "[1.1,1.2),[1.10,1.20),[1.100,1.200),[1.1000,1.2000),[1.10000,1.20000)")
}
"1+" should "convert to [1,2),[10,20),[100,200),[1000,2000),[10000,20000)" in {
test("1+ should convert to [1,2),[10,20),[100,200),[1000,2000),[10000,20000)") {
convertTo("1+", "[1,2),[10,20),[100,200),[1000,2000),[10000,20000)")
}
"+" should "convert to [0,)" in convertTo("+", "[0,)")
test("+ should convert to [0,)") {
convertTo("+", "[0,)")
}
"foo+" should "convert to foo+" in beParsedAsError("foo+")
test("foo+ should convert to foo+") {
beParsedAsError("foo+")
}
val mp = new MakePom(ConsoleLogger())
def convertTo(s: String, expected: String): Unit = {
MakePom.makeDependencyVersion(s) shouldBe expected
()
assert(MakePom.makeDependencyVersion(s) == expected)
}
def beParsedAsError(s: String): Unit = {
intercept[Throwable] {
MakePom.makeDependencyVersion(s)
()
}
()
}
}

View File

@ -7,7 +7,7 @@ import sbt.librarymanagement._
import sbt.librarymanagement.ivy._
import sbt.io.IO
class ManagedChecksumsSpec extends BaseIvySpecification {
object ManagedChecksumsSpec extends BaseIvySpecification {
private final def targetDir = Some(currentDependency)
private final def onlineConf = makeUpdateConfiguration(false, targetDir)
private final def warningConf = UnresolvedWarningConfiguration()
@ -47,7 +47,7 @@ class ManagedChecksumsSpec extends BaseIvySpecification {
assert(shaFile.exists(), s"The checksum $Checksum for $file does not exist")
}
"Managed checksums" should "should download the checksum files" in {
test("Managed checksums should should download the checksum files") {
cleanAll()
val updateOptions = UpdateOptions()
val toResolve = module(defaultModuleId, dependencies, None, updateOptions)

View File

@ -5,8 +5,8 @@ import sbt.librarymanagement._
import sbt.librarymanagement.ivy.UpdateOptions
import sbt.internal.librarymanagement.ivyint._
class MergeDescriptorSpec extends BaseIvySpecification {
"Merging duplicate dependencies" should "work" in {
object MergeDescriptorSpec extends BaseIvySpecification {
test("Merging duplicate dependencies should work") {
cleanIvyCache()
val m = module(
ModuleID("com.example", "foo", "0.1.0").withConfigurations(Some("compile")),
@ -25,8 +25,8 @@ class MergeDescriptorSpec extends BaseIvySpecification {
val a1: DependencyArtifactDescriptor = arts.toList(1)
val configs0 = a0.getConfigurations.toList
val configs1 = a1.getConfigurations.toList
configs0 shouldEqual List("compile")
configs1 shouldEqual List("test")
assert(configs0 == List("compile"))
assert(configs1 == List("test"))
}
}
}

View File

@ -5,7 +5,7 @@ import sbt.librarymanagement.syntax._
import sbt.librarymanagement.ivy.UpdateOptions
import Resolver._
class ModuleResolversTest extends BaseIvySpecification {
object ModuleResolversTest extends BaseIvySpecification {
override final val resolvers = Vector(
DefaultMavenRepository,
JavaNet2Repository,
@ -20,7 +20,7 @@ class ModuleResolversTest extends BaseIvySpecification {
"com.jfrog.bintray.client" % "bintray-client-java-api" % "0.9.2" % "compile"
).map(_.withIsTransitive(false))
"The direct resolvers in update options" should "skip the rest of resolvers" in {
test("The direct resolvers in update options should skip the rest of resolvers") {
cleanIvyCache()
val updateOptions = UpdateOptions()
val ivyModule = module(stubModule, dependencies, None, updateOptions)

View File

@ -2,10 +2,9 @@ package sbt.internal.librarymanagement
import sbt.librarymanagement._
import sbt.librarymanagement.ivy.UpdateOptions
import org.scalatest.{ Assertion, DiagrammedAssertions }
import sbt.io.IO
class OfflineModeSpec extends BaseIvySpecification with DiagrammedAssertions {
object OfflineModeSpec extends BaseIvySpecification {
private final def targetDir = Some(currentDependency)
private final def onlineConf = makeUpdateConfiguration(false, targetDir)
private final def offlineConf = makeUpdateConfiguration(true, targetDir)
@ -26,7 +25,7 @@ class OfflineModeSpec extends BaseIvySpecification with DiagrammedAssertions {
IO.delete(currentDependency)
}
def checkOnlineAndOfflineResolution(updateOptions: UpdateOptions): Assertion = {
def checkOnlineAndOfflineResolution(updateOptions: UpdateOptions): Unit = {
cleanAll()
val toResolve = module(defaultModuleId, dependencies, None, updateOptions)
if (updateOptions.cachedResolution)
@ -46,15 +45,15 @@ class OfflineModeSpec extends BaseIvySpecification with DiagrammedAssertions {
assert(originalResolveTime > resolveTime)
}
"Offline update configuration" should "reuse the caches when offline is enabled" in {
test("Offline update configuration should reuse the caches when offline is enabled") {
checkOnlineAndOfflineResolution(normalOptions)
}
it should "reuse the caches when offline and cached resolution are enabled" in {
test("it should reuse the caches when offline and cached resolution are enabled") {
checkOnlineAndOfflineResolution(cachedOptions)
}
def checkFailingResolution(updateOptions: UpdateOptions): Assertion = {
def checkFailingResolution(updateOptions: UpdateOptions): Unit = {
cleanAll()
val toResolve = module(defaultModuleId, dependencies, None, updateOptions)
if (updateOptions.cachedResolution) cleanCachedResolutionCache(toResolve)
@ -63,11 +62,11 @@ class OfflineModeSpec extends BaseIvySpecification with DiagrammedAssertions {
assert(failedOfflineResolution.isLeft)
}
it should "fail when artifacts are missing in the cache" in {
test("it should fail when artifacts are missing in the cache") {
checkFailingResolution(normalOptions)
}
it should "fail when artifacts are missing in the cache for cached resolution" in {
test("it should fail when artifacts are missing in the cache for cached resolution") {
checkFailingResolution(cachedOptions)
}
}

View File

@ -1,16 +1,18 @@
package sbttest
import java.net.URL
import org.scalatest._
import sbt.librarymanagement._
import sbt.librarymanagement.syntax._
import verify.BasicTestSuite
class ResolverSpec extends FunSuite with DiagrammedAssertions {
class ResolverSpec extends BasicTestSuite {
test("Resolver.url") {
Resolver.url("Test Repo", new URL("http://example.com/"))(Resolver.ivyStylePatterns)
()
}
test("at") {
"something" at "http://example.com"
()
}
}

View File

@ -6,8 +6,9 @@ import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor
import sbt.internal.librarymanagement.IvyScalaUtil.OverrideScalaMediator
import sbt.librarymanagement._
import sbt.librarymanagement.ScalaArtifacts._
import verify.BasicTestSuite
class ScalaOverrideTest extends UnitSpec {
object ScalaOverrideTest extends BasicTestSuite {
val OtherOrgID = "other.org"
def check(org0: String, version0: String)(org1: String, name1: String, version1: String) = {
@ -21,85 +22,126 @@ class ScalaOverrideTest extends UnitSpec {
dd.addDependencyConfiguration("compile", "compile")
val res = osm.mediate(dd)
res.getDependencyRevisionId shouldBe ModuleRevisionId.newInstance(org0, name1, version0)
assert(res.getDependencyRevisionId == ModuleRevisionId.newInstance(org0, name1, version0))
}
"""OverrideScalaMediator
""" should "Override compiler version" in check(Organization, "2.11.8")(
Organization,
CompilerID,
"2.11.9"
)
it should "Override library version" in check(Organization, "2.11.8")(
Organization,
LibraryID,
"2.11.8"
)
it should "Override reflect version" in check(Organization, "2.11.8")(
Organization,
ReflectID,
"2.11.7"
)
it should "Override actors version" in check(Organization, "2.11.8")(
Organization,
ActorsID,
"2.11.6"
)
it should "Override scalap version" in check(Organization, "2.11.8")(
Organization,
ScalapID,
"2.11.5"
)
test("""OverrideScalaMediator should override compiler version""") {
check(Organization, "2.11.8")(
Organization,
CompilerID,
"2.11.9"
)
}
it should "Override default compiler organization" in check(OtherOrgID, "2.11.8")(
Organization,
CompilerID,
"2.11.9"
)
it should "Override default library organization" in check(OtherOrgID, "2.11.8")(
Organization,
LibraryID,
"2.11.8"
)
it should "Override default reflect organization" in check(OtherOrgID, "2.11.8")(
Organization,
ReflectID,
"2.11.7"
)
it should "Override default actors organization" in check(OtherOrgID, "2.11.8")(
Organization,
ActorsID,
"2.11.6"
)
it should "Override default scalap organization" in check(OtherOrgID, "2.11.8")(
Organization,
ScalapID,
"2.11.5"
)
test("it should override library version") {
check(Organization, "2.11.8")(
Organization,
LibraryID,
"2.11.8"
)
}
it should "Override custom compiler organization" in check(Organization, "2.11.8")(
OtherOrgID,
CompilerID,
"2.11.9"
)
it should "Override custom library organization" in check(Organization, "2.11.8")(
OtherOrgID,
LibraryID,
"2.11.8"
)
it should "Override custom reflect organization" in check(Organization, "2.11.8")(
OtherOrgID,
ReflectID,
"2.11.7"
)
it should "Override custom actors organization" in check(Organization, "2.11.8")(
OtherOrgID,
ActorsID,
"2.11.6"
)
it should "Override custom scalap organization" in check(Organization, "2.11.8")(
OtherOrgID,
ScalapID,
"2.11.5"
)
test("it should override reflect version") {
check(Organization, "2.11.8")(
Organization,
ReflectID,
"2.11.7"
)
}
test("it should override actors version") {
check(Organization, "2.11.8")(
Organization,
ActorsID,
"2.11.6"
)
}
test("it should override scalap version") {
check(Organization, "2.11.8")(
Organization,
ScalapID,
"2.11.5"
)
}
test("it should override default compiler organization") {
check(OtherOrgID, "2.11.8")(
Organization,
CompilerID,
"2.11.9"
)
}
test("it should override default library organization") {
check(OtherOrgID, "2.11.8")(
Organization,
LibraryID,
"2.11.8"
)
}
test("it should override default reflect organization") {
check(OtherOrgID, "2.11.8")(
Organization,
ReflectID,
"2.11.7"
)
}
test("it should override default actors organization") {
check(OtherOrgID, "2.11.8")(
Organization,
ActorsID,
"2.11.6"
)
}
test("it should override default scalap organization") {
check(OtherOrgID, "2.11.8")(
Organization,
ScalapID,
"2.11.5"
)
}
test("it should override custom compiler organization") {
check(Organization, "2.11.8")(
OtherOrgID,
CompilerID,
"2.11.9"
)
}
test("it should override custom library organization") {
check(Organization, "2.11.8")(
OtherOrgID,
LibraryID,
"2.11.8"
)
}
test("it should override custom reflect organization") {
check(Organization, "2.11.8")(
OtherOrgID,
ReflectID,
"2.11.7"
)
}
test("it should override custom actors organization") {
check(Organization, "2.11.8")(
OtherOrgID,
ActorsID,
"2.11.6"
)
}
test("it should override custom scalap organization") {
check(Organization, "2.11.8")(
OtherOrgID,
ScalapID,
"2.11.5"
)
}
}

View File

@ -10,7 +10,7 @@ import java.nio.file.Paths
//by default this test is ignored
//to run this you need to change "repo" to point to some sftp repository which contains a dependency referring a dependency in same repo
//it will then attempt to authenticate via key file and fetch the dependency specified via "org" and "module"
class SftpRepoSpec extends BaseIvySpecification {
object SftpRepoSpec extends BaseIvySpecification {
val repo: Option[String] = None
// val repo: Option[String] = Some("some repo")
//a dependency which depends on another in the repo
@ -25,7 +25,7 @@ class SftpRepoSpec extends BaseIvySpecification {
}.toVector ++ super.resolvers
}
"resolving multiple deps from sftp repo" should "not hang or fail" in {
test("resolving multiple deps from sftp repo should not hang or fail") {
repo match {
case Some(repo) =>
IO.delete(currentTarget / "cache" / org(repo))

View File

@ -1,24 +1,26 @@
package sbt.internal.librarymanagement
import sbt.librarymanagement.ivy._
import verify.BasicTestSuite
class UpdateOptionsSpec extends UnitSpec {
"UpdateOptions" should "have proper toString defined" in {
UpdateOptions().toString() should be("""|UpdateOptions(
class UpdateOptionsSpec extends BasicTestSuite {
test("UpdateOptions should have proper toString defined") {
assert(UpdateOptions().toString() == """|UpdateOptions(
| circularDependencyLevel = warn,
| latestSnapshots = true,
| cachedResolution = false
|)""".stripMargin)
UpdateOptions()
.withCircularDependencyLevel(CircularDependencyLevel.Error)
.withCachedResolution(true)
.withLatestSnapshots(false)
.toString() should be("""|UpdateOptions(
assert(
UpdateOptions()
.withCircularDependencyLevel(CircularDependencyLevel.Error)
.withCachedResolution(true)
.withLatestSnapshots(false)
.toString() == """|UpdateOptions(
| circularDependencyLevel = error,
| latestSnapshots = false,
| cachedResolution = true
|)""".stripMargin)
|)""".stripMargin
)
}
}

View File

@ -51,6 +51,7 @@ object Dependencies {
val scalaCompiler = Def.setting { "org.scala-lang" % "scala-compiler" % scalaVersion.value }
val scalaXml = "org.scala-lang.modules" %% "scala-xml" % "1.2.0"
val scalaTest = "org.scalatest" %% "scalatest" % "3.0.6-SNAP5"
val scalaVerify = "com.eed3si9n.verify" %% "verify" % "0.1.0"
val scalaCheck = "org.scalacheck" %% "scalacheck" % "1.14.0"
val sjsonnew = Def.setting {
"com.eed3si9n" %% "sjson-new-core" % contrabandSjsonNewVersion.value