summaryrefslogtreecommitdiff
path: root/integration/test
diff options
context:
space:
mode:
authorLi Haoyi <haoyi.sg@gmail.com>2018-01-20 03:49:17 -0800
committerLi Haoyi <haoyi.sg@gmail.com>2018-01-20 03:49:17 -0800
commitd14f56a3fd881f809e58783c49866d1491a5f3fe (patch)
tree4a9f93d3d7f69211aa444ce15837fe6e79b9db7f /integration/test
parentaebd7a144fab5bdb95f6ee4f4bc170be65cd0549 (diff)
downloadmill-d14f56a3fd881f809e58783c49866d1491a5f3fe.tar.gz
mill-d14f56a3fd881f809e58783c49866d1491a5f3fe.tar.bz2
mill-d14f56a3fd881f809e58783c49866d1491a5f3fe.zip
Swap over to simplified Mill module/source layout from SBT's
Removes a lot of useless folders and gives us a chance to exercise this simplified layout. Support for the SBT layout is still verified by our integration tests
Diffstat (limited to 'integration/test')
-rw-r--r--integration/test/resources/acyclic/build.sc37
-rw-r--r--integration/test/resources/ammonite/build.sc177
-rw-r--r--integration/test/resources/better-files/build.sc86
-rw-r--r--integration/test/resources/jawn/build.sc59
-rw-r--r--integration/test/src/mill/integration/AcyclicTests.scala31
-rw-r--r--integration/test/src/mill/integration/AmmoniteTests.scala36
-rw-r--r--integration/test/src/mill/integration/BetterFilesTests.scala26
-rw-r--r--integration/test/src/mill/integration/IntegrationTestSuite.scala37
-rw-r--r--integration/test/src/mill/integration/JawnTests.scala31
9 files changed, 520 insertions, 0 deletions
diff --git a/integration/test/resources/acyclic/build.sc b/integration/test/resources/acyclic/build.sc
new file mode 100644
index 00000000..b8f878ad
--- /dev/null
+++ b/integration/test/resources/acyclic/build.sc
@@ -0,0 +1,37 @@
+import mill.Cross
+import mill.scalalib.{SbtModule, PublishModule, Dep, CrossSbtModule, DepSyntax}
+import mill.scalalib.publish.{PomSettings, License, Developer, SCM}
+
+object acyclic extends Cross[AcyclicModule]("2.10.6", "2.11.8", "2.12.3", "2.12.4")
+class AcyclicModule(val crossScalaVersion: String) extends CrossSbtModule with PublishModule {
+ def basePath = super.basePath / ammonite.ops.up
+ def artifactName = "acyclic"
+ def publishVersion = "0.1.7"
+
+ def pomSettings = PomSettings(
+ description = artifactName(),
+ organization = "com.lihaoyi",
+ url = "https://github.com/lihaoyi/acyclic",
+ licenses = Seq(
+ License("MIT license", "http://www.opensource.org/licenses/mit-license.php")
+ ),
+ scm = SCM(
+ "git://github.com/lihaoyi/acyclic.git",
+ "scm:git://github.com/lihaoyi/acyclic.git"
+ ),
+ developers = Seq(
+ Developer("lihaoyi", "Li Haoyi","https://github.com/lihaoyi")
+ )
+ )
+
+ def ivyDeps = Agg(
+ ivy"org.scala-lang:scala-compiler:${scalaVersion()}"
+ )
+ object test extends Tests{
+ def forkWorkingDir = ammonite.ops.pwd / 'target / 'workspace / 'acyclic
+ def ivyDeps = Agg(
+ ivy"com.lihaoyi::utest:0.6.0"
+ )
+ def testFramework = "utest.runner.Framework"
+ }
+} \ No newline at end of file
diff --git a/integration/test/resources/ammonite/build.sc b/integration/test/resources/ammonite/build.sc
new file mode 100644
index 00000000..cb8d32ab
--- /dev/null
+++ b/integration/test/resources/ammonite/build.sc
@@ -0,0 +1,177 @@
+import mill._, scalalib._
+val binCrossScalaVersions = Seq("2.11.11", "2.12.4")
+val fullCrossScalaVersions = Seq(
+ "2.11.3", "2.11.4", "2.11.5", "2.11.6", "2.11.7", "2.11.8", "2.11.9", "2.11.11",
+ "2.12.0", "2.12.1", "2.12.2", "2.12.3", "2.12.4"
+)
+trait AmmModule extends mill.scalalib.CrossSbtModule{
+ def testFramework = "utest.runner.Framework"
+ def scalacOptions = Seq("-P:acyclic:force", "-target:jvm-1.7")
+ def compileIvyDeps = Agg(ivy"com.lihaoyi::acyclic:0.1.7")
+ def scalacPluginIvyDeps = Agg(ivy"com.lihaoyi::acyclic:0.1.7")
+ trait Tests extends super.Tests{
+ def ivyDeps = Agg(ivy"com.lihaoyi::utest:0.6.0")
+ def testFramework = "utest.runner.Framework"
+ }
+}
+
+object ops extends Cross[OpsModule](binCrossScalaVersions:_*)
+class OpsModule(val crossScalaVersion: String) extends AmmModule{
+ def ivyDeps = Agg(ivy"com.lihaoyi::geny:0.1.2")
+
+ object test extends Tests
+}
+
+object terminal extends Cross[TerminalModule](binCrossScalaVersions:_*)
+class TerminalModule(val crossScalaVersion: String) extends AmmModule{
+ def ivyDeps = Agg(
+ ivy"com.lihaoyi::sourcecode:0.1.3",
+ ivy"com.lihaoyi::fansi:0.2.3"
+ )
+ def compileIvyDeps = Agg(
+ ivy"org.scala-lang:scala-reflect:$crossScalaVersion"
+ )
+
+ object test extends Tests
+}
+
+object amm extends Cross[MainModule](fullCrossScalaVersions:_*){
+ object util extends Cross[UtilModule](binCrossScalaVersions:_*)
+ class UtilModule(val crossScalaVersion: String) extends AmmModule{
+ def moduleDeps = Seq(ops())
+ def ivyDeps = Agg(
+ ivy"com.lihaoyi::upickle:0.5.1",
+ ivy"com.lihaoyi::pprint:0.5.2",
+ ivy"com.lihaoyi::fansi:0.2.4"
+ )
+ }
+
+
+ object runtime extends Cross[RuntimeModule](binCrossScalaVersions:_*)
+ class RuntimeModule(val crossScalaVersion: String) extends AmmModule{
+ def moduleDeps = Seq(ops(), amm.util())
+ def ivyDeps = Agg(
+ ivy"io.get-coursier::coursier:1.0.0",
+ ivy"io.get-coursier::coursier-cache:1.0.0",
+ ivy"org.scalaj::scalaj-http:2.3.0"
+ )
+
+ def generatedSources = T{
+ import ammonite.ops._
+ mkdir(T.ctx().dest)
+ cp(build.basePath/'project/"Constants.scala", T.ctx().dest/"Constants.scala")
+ Seq(PathRef(T.ctx().dest))
+ }
+ }
+
+ object interp extends Cross[InterpModule](fullCrossScalaVersions:_*)
+ class InterpModule(val crossScalaVersion: String) extends AmmModule{
+ def moduleDeps = Seq(ops(), amm.util(), amm.runtime())
+ def ivyDeps = Agg(
+ ivy"org.scala-lang:scala-compiler:$crossScalaVersion",
+ ivy"org.scala-lang:scala-reflect:$crossScalaVersion",
+ ivy"com.lihaoyi::scalaparse:1.0.0",
+ ivy"org.javassist:javassist:3.21.0-GA"
+ )
+ }
+
+ object repl extends Cross[ReplModule](fullCrossScalaVersions:_*)
+ class ReplModule(val crossScalaVersion: String) extends AmmModule{
+ def moduleDeps = Seq(
+ ops(), amm.util(),
+ amm.runtime(), amm.interp(),
+ terminal()
+ )
+ def ivyDeps = Agg(
+ ivy"jline:jline:2.14.3",
+ ivy"com.github.javaparser:javaparser-core:3.2.5",
+ ivy"com.github.scopt::scopt:3.5.0"
+ )
+
+ object test extends Tests{
+ def resources = T.input {
+ super.resources() ++
+ ReplModule.this.sources() ++
+ ReplModule.this.externalCompileDepSources()
+ }
+ }
+ }
+}
+class MainModule(val crossScalaVersion: String) extends AmmModule{
+
+ def mainClass = Some("ammonite.Main")
+
+ def moduleDeps = Seq(
+ terminal(), ops(),
+ amm.util(), amm.runtime(),
+ amm.interp(), amm.repl()
+ )
+ def ivyDeps = Agg(
+ ivy"com.github.scopt::scopt:3.5.0",
+ )
+
+ def runClasspath =
+ super.runClasspath() ++
+ ops().sources() ++
+ terminal().sources() ++
+ amm.util().sources() ++
+ amm.runtime().sources() ++
+ amm.interp().sources() ++
+ amm.repl().sources() ++
+ sources() ++
+ externalCompileDepSources()
+
+
+
+ def prependShellScript =
+ "#!/usr/bin/env sh\n" +
+ """exec java -jar -Xmx500m -XX:+UseG1GC $JAVA_OPTS "$0" "$@""""
+
+
+ object test extends Tests{
+ def moduleDeps = super.moduleDeps ++ Seq(amm.repl().test)
+ def ivyDeps = super.ivyDeps() ++ Agg(
+ ivy"com.chuusai::shapeless:2.3.2"
+ )
+ }
+}
+
+object shell extends Cross[ShellModule](fullCrossScalaVersions:_*)
+class ShellModule(val crossScalaVersion: String) extends AmmModule{
+ def moduleDeps = Seq(ops(), amm())
+ object test extends Tests{
+ def moduleDeps = super.moduleDeps ++ Seq(amm.repl().test)
+ // (test in Test) := (test in Test).dependsOn(packageBin in Compile).value,
+ // (run in Test) := (run in Test).dependsOn(packageBin in Compile).evaluated,
+ // (testOnly in Test) := (testOnly in Test).dependsOn(packageBin in Compile).evaluated
+ }
+}
+object integration extends Cross[IntegrationModule](fullCrossScalaVersions:_*)
+class IntegrationModule(val crossScalaVersion: String) extends AmmModule{
+ def moduleDeps = Seq(ops(), amm())
+ // (test in Test) := (test in Test).dependsOn(integrationTasks:_*).value,
+ // (run in Test) := (run in Test).dependsOn(integrationTasks:_*).evaluated,
+ // (testOnly in Test) := (testOnly in Test).dependsOn(integrationTasks:_*).evaluated,
+ // (console in Test) := (console in Test).dependsOn(integrationTasks:_*).value,
+ // initialCommands in (Test, console) := "ammonite.integration.Main.main(null)"
+ object test extends Tests {
+ }
+}
+
+object sshd extends Cross[SshdModule](fullCrossScalaVersions:_*)
+class SshdModule(val crossScalaVersion: String) extends AmmModule{
+ def moduleDeps = Seq(ops(), amm())
+ def ivyDeps = Agg(
+ // sshd-core 1.3.0 requires java8
+ ivy"org.apache.sshd:sshd-core:1.2.0",
+ ivy"org.bouncycastle:bcprov-jdk15on:1.56",
+ )
+ object test extends Tests {
+ def ivyDeps = super.ivyDeps() ++ Agg(
+ // slf4j-nop makes sshd server use logger that writes into the void
+ ivy"org.slf4j:slf4j-nop:1.7.12",
+ ivy"com.jcraft:jsch:0.1.54",
+ ivy"org.scalacheck::scalacheck:1.12.6"
+ )
+ }
+} \ No newline at end of file
diff --git a/integration/test/resources/better-files/build.sc b/integration/test/resources/better-files/build.sc
new file mode 100644
index 00000000..582d3400
--- /dev/null
+++ b/integration/test/resources/better-files/build.sc
@@ -0,0 +1,86 @@
+import mill.scalalib.{SbtModule, Dep, DepSyntax}
+
+trait BetterFilesModule extends SbtModule{
+ def scalaVersion = "2.12.4"
+ def scalacOptions = Seq(
+ "-deprecation", // Emit warning and location for usages of deprecated APIs.
+ "-encoding", "utf-8", // Specify character encoding used by source files.
+ "-explaintypes", // Explain type errors in more detail.
+ "-feature", // Emit warning and location for usages of features that should be imported explicitly.
+ "-language:existentials", // Existential types (besides wildcard types) can be written and inferred
+ "-language:experimental.macros", // Allow macro definition (besides implementation and application)
+ "-language:higherKinds", // Allow higher-kinded types
+ "-language:implicitConversions", // Allow definition of implicit functions called views
+ "-unchecked", // Enable additional warnings where generated code depends on assumptions.
+ "-Xcheckinit", // Wrap field accessors to throw an exception on uninitialized access.
+ "-Xfatal-warnings", // Fail the compilation if there are any warnings.
+ "-Xfuture", // Turn on future language features.
+ "-Xlint:adapted-args", // Warn if an argument list is modified to match the receiver.
+ "-Xlint:by-name-right-associative", // By-name parameter of right associative operator.
+ "-Xlint:constant", // Evaluation of a constant arithmetic expression results in an error.
+ "-Xlint:delayedinit-select", // Selecting member of DelayedInit.
+ "-Xlint:doc-detached", // A Scaladoc comment appears to be detached from its element.
+ "-Xlint:inaccessible", // Warn about inaccessible types in method signatures.
+ "-Xlint:infer-any", // Warn when a type argument is inferred to be `Any`.
+ "-Xlint:missing-interpolator", // A string literal appears to be missing an interpolator id.
+ "-Xlint:nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
+ "-Xlint:nullary-unit", // Warn when nullary methods return Unit.
+ "-Xlint:option-implicit", // Option.apply used implicit view.
+ "-Xlint:package-object-classes", // Class or object defined in package object.
+ "-Xlint:poly-implicit-overload", // Parameterized overloaded implicit methods are not visible as view bounds.
+ "-Xlint:private-shadow", // A private field (or class parameter) shadows a superclass field.
+ "-Xlint:stars-align", // Pattern sequence wildcard must align with sequence component.
+ "-Xlint:type-parameter-shadow", // A local type parameter shadows a type already in scope.
+ "-Xlint:unsound-match", // Pattern match may not be typesafe.
+ "-Yno-adapted-args", // Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.
+ "-Ypartial-unification", // Enable partial unification in type constructor inference
+ "-Ywarn-dead-code", // Warn when dead code is identified.
+ "-Ywarn-extra-implicit", // Warn when more than one implicit parameter section is defined.
+ "-Ywarn-inaccessible", // Warn about inaccessible types in method signatures.
+ "-Ywarn-infer-any", // Warn when a type argument is inferred to be `Any`.
+ "-Ywarn-nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
+ "-Ywarn-nullary-unit", // Warn when nullary methods return Unit.
+ "-Ywarn-numeric-widen", // Warn when numerics are widened.
+ "-Ywarn-unused:implicits", // Warn if an implicit parameter is unused.
+ "-Ywarn-unused:imports", // Warn if an import selector is not referenced.
+ "-Ywarn-unused:locals", // Warn if a local definition is unused.
+ "-Ywarn-unused:params", // Warn if a value parameter is unused.
+ "-Ywarn-unused:patvars", // Warn if a variable bound in a pattern is unused.
+ "-Ywarn-unused:privates", // Warn if a private member is unused.
+ "-Ywarn-value-discard" // Warn when non-Unit expression results are unused.
+ )
+ override def javacOptions = Seq("-source", "1.8", "-target", "1.8", "-Xlint")
+ object test extends Tests{
+ def moduleDeps =
+ if (this == core.test) super.moduleDeps
+ else super.moduleDeps ++ Seq(core.test)
+ def ivyDeps = Agg(ivy"org.scalatest::scalatest:3.0.4")
+ def testFramework = "org.scalatest.tools.Framework"
+ }
+}
+
+object core extends BetterFilesModule
+
+object akka extends BetterFilesModule{
+ def moduleDeps = Seq(core)
+ def ivyDeps = Agg(ivy"com.typesafe.akka::akka-actor:2.5.6")
+}
+
+object shapeless extends BetterFilesModule{
+ def moduleDeps = Seq(core)
+ def ivyDeps = Agg(ivy"com.chuusai::shapeless:2.3.2")
+}
+
+object benchmarks extends BetterFilesModule{
+ def moduleDeps = Seq(core)
+ def ivyDeps = Agg(
+ ivy"commons-io:commons-io:2.5"
+ )
+ def depClasspath = Agg(
+ mill.modules.Util.download(
+ "https://github.com/williamfiset/FastJavaIO/releases/download/v1.0/fastjavaio.jar",
+ "fastjavaio.jar"
+ )
+ )
+}
+
diff --git a/integration/test/resources/jawn/build.sc b/integration/test/resources/jawn/build.sc
new file mode 100644
index 00000000..4898a3cb
--- /dev/null
+++ b/integration/test/resources/jawn/build.sc
@@ -0,0 +1,59 @@
+import mill.scalalib
+import mill.Cross
+import mill.scalalib.{Dep, TestModule, DepSyntax}
+object jawn extends Cross[JawnModule]("2.10.6", "2.11.11", "2.12.3")
+class JawnModule(crossVersion: String) extends mill.Module{
+ override def basePath = super.basePath / ammonite.ops.up / ammonite.ops.up
+
+ trait JawnModule extends scalalib.SbtModule{
+ def scalaVersion = crossVersion
+ def scalacOptions = Seq(
+ "-deprecation",
+ "-optimize",
+ "-unchecked"
+ )
+ def testModuleDeps: Seq[TestModule] = Nil
+ object test extends Tests{
+ def moduleDeps = super.moduleDeps ++ testModuleDeps
+ def ivyDeps = Agg(
+ ivy"org.scalatest::scalatest:3.0.3",
+ ivy"org.scalacheck::scalacheck:1.13.5"
+ )
+ def testFramework = "org.scalatest.tools.Framework"
+ }
+ }
+ object parser extends JawnModule
+
+ object util extends JawnModule{
+ def moduleDeps = Seq(parser)
+ def testModuleDeps = Seq(parser.test)
+ }
+ object ast extends JawnModule{
+ def moduleDeps = Seq(parser, util)
+ def testModuleDeps = Seq(parser.test, util.test)
+ }
+ class Support(ivyDeps0: Dep*)(implicit ctx: mill.define.Ctx) extends JawnModule{
+ def moduleDeps = Seq(parser)
+ def ivyDeps = Agg.from(ivyDeps0)
+ }
+ object support extends mill.Module{
+ object argonaut extends Support(ivy"io.argonaut::argonaut:6.2")
+ object json4s extends Support(ivy"org.json4s::json4s-ast:3.5.2")
+
+ object play extends Support(){
+ def ivyDeps = mill.T{
+ scalaBinaryVersion() match{
+ case "2.10" => Agg(ivy"com.typesafe.play::play-json:2.4.11")
+ case "2.11" => Agg(ivy"com.typesafe.play::play-json:2.5.15")
+ case _ => Agg(ivy"com.typesafe.play::play-json:2.6.0")
+ }
+ }
+ }
+
+ object rojoma extends Support(ivy"com.rojoma::rojoma-json:2.4.3")
+ object rojomaV3 extends Support(ivy"com.rojoma::rojoma-json-v3:3.7.2"){
+ override def basePath = super.basePath / ammonite.ops.up / "rojoma-v3"
+ }
+ object spray extends Support(ivy"io.spray::spray-json:1.3.3")
+ }
+} \ No newline at end of file
diff --git a/integration/test/src/mill/integration/AcyclicTests.scala b/integration/test/src/mill/integration/AcyclicTests.scala
new file mode 100644
index 00000000..42b5179b
--- /dev/null
+++ b/integration/test/src/mill/integration/AcyclicTests.scala
@@ -0,0 +1,31 @@
+package mill.integration
+
+import ammonite.ops._
+import utest._
+
+object AcyclicTests extends IntegrationTestSuite("MILL_ACYCLIC_REPO", "acyclic") {
+ val tests = Tests{
+ initWorkspace()
+
+ def check(scalaVersion: String) = {
+ val firstCompile = eval(s"acyclic[$scalaVersion].compile")
+
+ assert(
+ firstCompile,
+ ls.rec(workspacePath).exists(_.last == "GraphAnalysis.class"),
+ ls.rec(workspacePath).exists(_.last == "PluginPhase.class")
+ )
+ for(scalaFile <- ls.rec(workspacePath).filter(_.ext == "scala")){
+ write.append(scalaFile, "\n}")
+ }
+
+ val brokenCompile = eval(s"acyclic[$scalaVersion].compile")
+
+ assert(!brokenCompile)
+ }
+
+ 'scala2118 - check("2.11.8")
+ 'scala2124 - check("2.12.4")
+
+ }
+}
diff --git a/integration/test/src/mill/integration/AmmoniteTests.scala b/integration/test/src/mill/integration/AmmoniteTests.scala
new file mode 100644
index 00000000..22bd3cb8
--- /dev/null
+++ b/integration/test/src/mill/integration/AmmoniteTests.scala
@@ -0,0 +1,36 @@
+package mill.integration
+
+import ammonite.ops._
+import utest._
+
+object AmmoniteTests extends IntegrationTestSuite("MILL_AMMONITE_REPO", "ammonite") {
+ val tests = Tests{
+ initWorkspace()
+
+ def check(scalaVersion: String) = {
+ val replTests = eval(
+ s"amm.repl[$scalaVersion].test", "{ammonite.unit,ammonite.session.ProjectTests.guava}"
+ )
+ val replTestMeta = meta(s"amm.repl[$scalaVersion].test.test")
+ assert(
+ replTests,
+ replTestMeta.contains("ammonite.session.ProjectTests.guava"),
+ replTestMeta.contains("ammonite.unit.SourceTests.objectInfo.thirdPartyJava")
+ )
+
+ val compileResult = eval(
+ "--all", s"{shell,sshd,amm,integration}[$scalaVersion].test.compile"
+ )
+
+ assert(
+ compileResult,
+ ls.rec(workspacePath / 'out / 'integration / scalaVersion / 'test / 'compile)
+ .exists(_.name == "ErrorTruncationTests.class")
+ )
+ }
+
+ 'scala2118 - check("2.11.8")
+ 'scala2124 - check("2.12.4")
+
+ }
+}
diff --git a/integration/test/src/mill/integration/BetterFilesTests.scala b/integration/test/src/mill/integration/BetterFilesTests.scala
new file mode 100644
index 00000000..7ee943df
--- /dev/null
+++ b/integration/test/src/mill/integration/BetterFilesTests.scala
@@ -0,0 +1,26 @@
+package mill.integration
+
+import ammonite.ops._
+import utest._
+
+object BetterFilesTests extends IntegrationTestSuite("MILL_BETTERFILES_REPO", "better-files") {
+ val tests = Tests{
+ initWorkspace()
+ 'test - {
+
+ assert(eval("core.test"))
+ assert(eval("akka.test"))
+ assert(eval("benchmarks.test.compile"))
+
+ val coreTestMeta = meta("core.test.test")
+ assert(coreTestMeta.contains("better.files.FileSpec"))
+ assert(coreTestMeta.contains("files should handle BOM"))
+
+ for(scalaFile <- ls.rec(workspacePath).filter(_.ext == "scala")){
+ write.append(scalaFile, "\n}")
+ }
+ assert(!eval("akka.test"))
+ }
+
+ }
+}
diff --git a/integration/test/src/mill/integration/IntegrationTestSuite.scala b/integration/test/src/mill/integration/IntegrationTestSuite.scala
new file mode 100644
index 00000000..4649abdb
--- /dev/null
+++ b/integration/test/src/mill/integration/IntegrationTestSuite.scala
@@ -0,0 +1,37 @@
+package mill.integration
+
+import java.io.{ByteArrayInputStream, ByteArrayOutputStream, InputStream, PrintStream}
+
+import ammonite.ops._
+import mill.define.Segments
+import mill.main.ParseArgs
+import utest._
+
+abstract class IntegrationTestSuite(repoKey: String, workspaceSlug: String) extends TestSuite{
+ val workspacePath = pwd / 'target / 'workspace / workspaceSlug
+ val buildFilePath = pwd / 'integration / 'test / 'resources / workspaceSlug
+ val stdOutErr = new PrintStream(new ByteArrayOutputStream())
+ val stdIn = new ByteArrayInputStream(Array())
+ val runner = new mill.main.MainRunner(
+ ammonite.main.Cli.Config(wd = workspacePath), false,
+ stdOutErr, stdOutErr, stdIn
+ )
+ def eval(s: String*) = runner.runScript(workspacePath / "build.sc", s.toList)
+ def meta(s: String) = {
+ val (List(selector), args) = ParseArgs.apply(Seq(s)).right.get
+
+ read(workspacePath / "out" / selector.flatMap(_.pathSegments) / "meta.json")
+ }
+ def initWorkspace() = {
+ rm(workspacePath)
+ mkdir(workspacePath / up)
+ // The unzipped git repo snapshots we get from github come with a
+ // wrapper-folder inside the zip file, so copy the wrapper folder to the
+ // destination instead of the folder containing the wrapper.
+ val path = sys.props(repoKey)
+ val Seq(wrapper) = ls(Path(path))
+ cp(wrapper, workspacePath)
+ cp(buildFilePath / "build.sc", workspacePath / "build.sc")
+ assert(!ls.rec(workspacePath).exists(_.ext == "class"))
+ }
+}
diff --git a/integration/test/src/mill/integration/JawnTests.scala b/integration/test/src/mill/integration/JawnTests.scala
new file mode 100644
index 00000000..21c9f133
--- /dev/null
+++ b/integration/test/src/mill/integration/JawnTests.scala
@@ -0,0 +1,31 @@
+package mill.integration
+
+import ammonite.ops._
+import utest._
+
+object JawnTests extends IntegrationTestSuite("MILL_JAWN_REPO", "jawn") {
+ val tests = Tests{
+ initWorkspace()
+
+ def check(scalaVersion: String) = {
+ val firstCompile = eval(s"jawn[$scalaVersion].parser.test")
+
+ assert(
+ firstCompile,
+ ls.rec(workspacePath).exists(_.last == "AsyncParser.class"),
+ ls.rec(workspacePath).exists(_.last == "CharBuilderSpec.class")
+ )
+
+ for(scalaFile <- ls.rec(workspacePath).filter(_.ext == "scala")){
+ write.append(scalaFile, "\n}")
+ }
+
+ val brokenCompile = eval(s"jawn[$scalaVersion].parser.test")
+
+ assert(!brokenCompile)
+ }
+
+ 'scala21111 - check("2.11.11")
+ 'scala2123 - check("2.12.3")
+ }
+}