summaryrefslogtreecommitdiff
path: root/main/test/src/util
diff options
context:
space:
mode:
Diffstat (limited to 'main/test/src/util')
-rw-r--r--main/test/src/util/ParseArgsTest.scala254
-rw-r--r--main/test/src/util/ScriptTestSuite.scala53
-rw-r--r--main/test/src/util/TestEvaluator.scala80
-rw-r--r--main/test/src/util/TestGraphs.scala271
-rw-r--r--main/test/src/util/TestUtil.scala86
5 files changed, 744 insertions, 0 deletions
diff --git a/main/test/src/util/ParseArgsTest.scala b/main/test/src/util/ParseArgsTest.scala
new file mode 100644
index 00000000..e31baf4f
--- /dev/null
+++ b/main/test/src/util/ParseArgsTest.scala
@@ -0,0 +1,254 @@
+package mill.util
+
+import mill.define.{Segment, Segments}
+import mill.define.Segment.{Cross, Label}
+import utest._
+
+object ParseArgsTest extends TestSuite {
+
+ val tests = Tests {
+ 'extractSelsAndArgs - {
+ def check(input: Seq[String],
+ expectedSelectors: Seq[String],
+ expectedArgs: Seq[String],
+ multiSelect: Boolean) = {
+ val (selectors, args) = ParseArgs.extractSelsAndArgs(input, multiSelect)
+
+ assert(
+ selectors == expectedSelectors,
+ args == expectedArgs
+ )
+ }
+
+ 'empty - check(input = Seq.empty,
+ expectedSelectors = Seq.empty,
+ expectedArgs = Seq.empty,
+ multiSelect = false)
+ 'singleSelector - check(
+ input = Seq("core.compile"),
+ expectedSelectors = Seq("core.compile"),
+ expectedArgs = Seq.empty,
+ multiSelect = false
+ )
+ 'singleSelectorWithArgs - check(
+ input = Seq("application.run", "hello", "world"),
+ expectedSelectors = Seq("application.run"),
+ expectedArgs = Seq("hello", "world"),
+ multiSelect = false
+ )
+ 'singleSelectorWithAllInArgs - check(
+ input = Seq("application.run", "hello", "world", "--all"),
+ expectedSelectors = Seq("application.run"),
+ expectedArgs = Seq("hello", "world", "--all"),
+ multiSelect = false
+ )
+ 'multiSelectors - check(
+ input = Seq("core.jar", "core.docJar", "core.sourcesJar"),
+ expectedSelectors = Seq("core.jar", "core.docJar", "core.sourcesJar"),
+ expectedArgs = Seq.empty,
+ multiSelect = true
+ )
+ 'multiSelectorsSeq - check(
+ input = Seq("core.jar", "core.docJar", "core.sourcesJar"),
+ expectedSelectors = Seq("core.jar", "core.docJar", "core.sourcesJar"),
+ expectedArgs = Seq.empty,
+ multiSelect = true
+ )
+ 'multiSelectorsWithArgs - check(
+ input = Seq("core.compile",
+ "application.runMain",
+ "--",
+ "Main",
+ "hello",
+ "world"),
+ expectedSelectors = Seq("core.compile", "application.runMain"),
+ expectedArgs = Seq("Main", "hello", "world"),
+ multiSelect = true
+ )
+ 'multiSelectorsWithArgsWithAllInArgs - check(
+ input = Seq("core.compile",
+ "application.runMain",
+ "--",
+ "Main",
+ "--all",
+ "world"),
+ expectedSelectors = Seq("core.compile", "application.runMain"),
+ expectedArgs = Seq("Main", "--all", "world"),
+ multiSelect = true
+ )
+ }
+ 'expandBraces - {
+ def check(input: String, expectedExpansion: List[String]) = {
+ val Right(expanded) = ParseArgs.expandBraces(input)
+
+ assert(expanded == expectedExpansion)
+ }
+
+ 'expandLeft - check(
+ "{application,core}.compile",
+ List("application.compile", "core.compile")
+ )
+ 'expandRight - check(
+ "application.{jar,docJar,sourcesJar}",
+ List("application.jar", "application.docJar", "application.sourcesJar")
+ )
+ 'expandBoth - check(
+ "{core,application}.{jar,docJar}",
+ List(
+ "core.jar",
+ "core.docJar",
+ "application.jar",
+ "application.docJar"
+ )
+ )
+ 'expandNested - {
+ check("{hello,world.{cow,moo}}",
+ List("hello", "world.cow", "world.moo"))
+ check("{a,b{c,d}}", List("a", "bc", "bd"))
+ check("{a,b,{c,d}}", List("a", "b", "c", "d"))
+ check("{a,b{c,d{e,f}}}", List("a", "bc", "bde", "bdf"))
+ check("{a{b,c},d}", List("ab", "ac", "d"))
+ check("{a,{b,c}d}", List("a", "bd", "cd"))
+ check("{a{b,c},d{e,f}}", List("ab", "ac", "de", "df"))
+ check("{a,b{c,d},e{f,g}}", List("a", "bc", "bd", "ef", "eg"))
+ }
+ 'expandMixed - check(
+ "{a,b}.{c}.{}.e",
+ List("a.{c}.{}.e", "b.{c}.{}.e")
+ )
+ 'malformed - {
+ val malformed = Seq("core.{compile", "core.{compile,test]")
+
+ malformed.foreach { m =>
+ val Left(error) = ParseArgs.expandBraces(m)
+ assert(error.contains("Parsing exception"))
+ }
+ }
+ 'dontExpand - {
+ check("core.compile", List("core.compile"))
+ check("{}.compile", List("{}.compile"))
+ check("{core}.compile", List("{core}.compile"))
+ }
+ 'keepUnknownSymbols - {
+ check("{a,b}.e<>", List("a.e<>", "b.e<>"))
+ check("a[99]&&", List("a[99]&&"))
+ check(
+ "{a,b}.<%%>.{c,d}",
+ List("a.<%%>.c", "a.<%%>.d", "b.<%%>.c", "b.<%%>.d")
+ )
+ }
+ }
+
+ 'apply - {
+ def check(input: Seq[String],
+ expectedSelectors: List[(Option[List[Segment]], List[Segment])],
+ expectedArgs: Seq[String],
+ multiSelect: Boolean) = {
+ val Right((selectors0, args)) = ParseArgs(input, multiSelect)
+
+ val selectors = selectors0.map{
+ case (Some(v1), v2) => (Some(v1.value), v2.value)
+ case (None, v2) => (None, v2.value)
+ }
+ assert(
+ selectors == expectedSelectors,
+ args == expectedArgs
+ )
+ }
+
+ 'rejectEmpty {
+ assert(ParseArgs(Seq.empty, multiSelect = false) == Left("Selector cannot be empty"))
+ }
+ 'singleSelector - check(
+ input = Seq("core.compile"),
+ expectedSelectors = List(
+ None -> List(Label("core"), Label("compile"))
+ ),
+ expectedArgs = Seq.empty,
+ multiSelect = false
+ )
+ 'externalSelector - check(
+ input = Seq("foo.bar/core.compile"),
+ expectedSelectors = List(
+ Some(List(Label("foo"), Label("bar"))) -> List(Label("core"), Label("compile"))
+ ),
+ expectedArgs = Seq.empty,
+ multiSelect = false
+ )
+ 'singleSelectorWithArgs - check(
+ input = Seq("application.run", "hello", "world"),
+ expectedSelectors = List(
+ None -> List(Label("application"), Label("run"))
+ ),
+ expectedArgs = Seq("hello", "world"),
+ multiSelect = false
+ )
+ 'singleSelectorWithCross - check(
+ input = Seq("bridges[2.12.4,jvm].compile"),
+ expectedSelectors = List(
+ None -> List(Label("bridges"), Cross(Seq("2.12.4", "jvm")), Label("compile"))
+ ),
+ expectedArgs = Seq.empty,
+ multiSelect = false
+ )
+ 'multiSelectorsBraceExpansion - check(
+ input = Seq("{core,application}.compile"),
+ expectedSelectors = List(
+ None -> List(Label("core"), Label("compile")),
+ None -> List(Label("application"), Label("compile"))
+ ),
+ expectedArgs = Seq.empty,
+ multiSelect = true
+ )
+ 'multiSelectorsBraceExpansionWithArgs - check(
+ input = Seq("{core,application}.run", "--", "hello", "world"),
+ expectedSelectors = List(
+ None -> List(Label("core"), Label("run")),
+ None -> List(Label("application"), Label("run"))
+ ),
+ expectedArgs = Seq("hello", "world"),
+ multiSelect = true
+ )
+ 'multiSelectorsBraceExpansionWithCross - check(
+ input = Seq("bridges[2.12.4,jvm].{test,jar}"),
+ expectedSelectors = List(
+ None -> List(Label("bridges"), Cross(Seq("2.12.4", "jvm")), Label("test")),
+ None -> List(Label("bridges"), Cross(Seq("2.12.4", "jvm")), Label("jar"))
+ ),
+ expectedArgs = Seq.empty,
+ multiSelect = true
+ )
+ 'multiSelectorsBraceExpansionInsideCross - check(
+ input = Seq("bridges[{2.11.11,2.11.8,2.13.0-M3}].jar"),
+ expectedSelectors = List(
+ None -> List(Label("bridges"), Cross(Seq("2.11.11")), Label("jar")),
+ None -> List(Label("bridges"), Cross(Seq("2.11.8")), Label("jar")),
+ None -> List(Label("bridges"), Cross(Seq("2.13.0-M3")), Label("jar"))
+ ),
+ expectedArgs = Seq.empty,
+ multiSelect = true
+ )
+ 'multiSelectorsBraceExpansionWithoutAll - {
+ val res = ParseArgs(Seq("{core,application}.compile"), multiSelect = false)
+ val expected = Right(
+ List(
+ None -> Segments(Label("core"), Label("compile")),
+ None -> Segments(Label("application"), Label("compile"))
+ ),
+ Nil
+ )
+ assert(res == expected)
+ }
+ 'multiSelectorsWithoutAllAsSingle - check(
+ // this is how it works when we pass multiple tasks without --all flag
+ input = Seq("core.compile", "application.compile"),
+ expectedSelectors = List(
+ None -> List(Label("core"), Label("compile"))
+ ),
+ expectedArgs = Seq("application.compile"),
+ multiSelect = false
+ )
+ }
+ }
+
+}
diff --git a/main/test/src/util/ScriptTestSuite.scala b/main/test/src/util/ScriptTestSuite.scala
new file mode 100644
index 00000000..f448aaaf
--- /dev/null
+++ b/main/test/src/util/ScriptTestSuite.scala
@@ -0,0 +1,53 @@
+package mill.util
+
+import java.io.{ByteArrayInputStream, ByteArrayOutputStream, PrintStream}
+
+import utest._
+
+abstract class ScriptTestSuite(fork: Boolean) extends TestSuite{
+ def workspaceSlug: String
+ def scriptSourcePath: os.Path
+ def buildPath: os.RelPath = "build.sc"
+
+ val workspacePath = os.pwd / 'target / 'workspace / workspaceSlug
+ val wd = workspacePath / buildPath / os.up
+ val stdOutErr = System.out // new PrintStream(new ByteArrayOutputStream())
+ val stdIn = new ByteArrayInputStream(Array())
+ val disableTicker = false
+ val debugLog = false
+ lazy val runner = new mill.main.MainRunner(
+ ammonite.main.Cli.Config(wd = wd), disableTicker,
+ stdOutErr, stdOutErr, stdIn, None, Map.empty,
+ b => (), debugLog
+ )
+ def eval(s: String*) = {
+ if (!fork) runner.runScript(workspacePath / buildPath , s.toList)
+ else{
+ try {
+ os.proc(os.home / "mill-release", "-i", s).call(
+ wd,
+ stdin = os.Inherit,
+ stdout = os.Inherit,
+ stderr = os.Inherit,
+ )
+ true
+ }catch{case e: Throwable => false}
+ }
+ }
+ def meta(s: String) = {
+ val (List(selector), args) = ParseArgs.apply(Seq(s), multiSelect = false).right.get
+
+ os.read(wd / "out" / selector._2.value.flatMap(_.pathSegments) / "meta.json")
+ }
+
+
+ def initWorkspace() = {
+ os.remove.all(workspacePath)
+ os.makeDir.all(workspacePath / os.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.
+
+ os.copy(scriptSourcePath, workspacePath)
+ }
+}
diff --git a/main/test/src/util/TestEvaluator.scala b/main/test/src/util/TestEvaluator.scala
new file mode 100644
index 00000000..9a235679
--- /dev/null
+++ b/main/test/src/util/TestEvaluator.scala
@@ -0,0 +1,80 @@
+package mill.util
+
+import mill.define.{Input, Target, Task}
+import mill.api.Result.OuterStack
+import mill.eval.{Evaluator, Result}
+import mill.util.Strict.Agg
+import utest.assert
+import utest.framework.TestPath
+
+import language.experimental.macros
+object TestEvaluator{
+ val externalOutPath = os.pwd / 'target / 'external
+
+
+ def static(module: TestUtil.BaseModule)(implicit fullName: sourcecode.FullName) = {
+ new TestEvaluator(module)(fullName, TestPath(Nil))
+ }
+}
+
+class TestEvaluator(module: TestUtil.BaseModule)
+ (implicit fullName: sourcecode.FullName,
+ tp: TestPath){
+ val outPath = TestUtil.getOutPath()
+
+// val logger = DummyLogger
+ val logger = new PrintLogger(
+ colored = true, disableTicker=false,
+ ammonite.util.Colors.Default, System.out, System.out, System.err, System.in, debugEnabled = false
+ )
+ val evaluator = new Evaluator(Ctx.defaultHome, outPath, TestEvaluator.externalOutPath, module, logger)
+
+ def apply[T](t: Task[T]): Either[Result.Failing[T], (T, Int)] = {
+ val evaluated = evaluator.evaluate(Agg(t))
+
+ if (evaluated.failing.keyCount == 0) {
+ Right(
+ Tuple2(
+ evaluated.rawValues.head.asInstanceOf[Result.Success[T]].value,
+ evaluated.evaluated.collect {
+ case t: Target[_]
+ if module.millInternal.targets.contains(t)
+ && !t.isInstanceOf[Input[_]]
+ && !t.ctx.external => t
+ case t: mill.define.Command[_] => t
+ }.size
+ ))
+ } else {
+ Left(
+ evaluated.failing.lookupKey(evaluated.failing.keys().next).items.next()
+ .asInstanceOf[Result.Failing[T]]
+ )
+ }
+ }
+
+ def fail(target: Target[_], expectedFailCount: Int, expectedRawValues: Seq[Result[_]]) = {
+
+ val res = evaluator.evaluate(Agg(target))
+
+ val cleaned = res.rawValues.map{
+ case Result.Exception(ex, _) => Result.Exception(ex, new OuterStack(Nil))
+ case x => x
+ }
+
+ assert(
+ cleaned == expectedRawValues,
+ res.failing.keyCount == expectedFailCount
+ )
+
+ }
+
+ def check(targets: Agg[Task[_]], expected: Agg[Task[_]]) = {
+ val evaluated = evaluator.evaluate(targets)
+ .evaluated
+ .flatMap(_.asTarget)
+ .filter(module.millInternal.targets.contains)
+ .filter(!_.isInstanceOf[Input[_]])
+ assert(evaluated == expected)
+ }
+
+}
diff --git a/main/test/src/util/TestGraphs.scala b/main/test/src/util/TestGraphs.scala
new file mode 100644
index 00000000..d3b35ddc
--- /dev/null
+++ b/main/test/src/util/TestGraphs.scala
@@ -0,0 +1,271 @@
+package mill.util
+import TestUtil.test
+import mill.define.{Cross, Discover}
+import mill.{Module, T}
+
+/**
+ * Example dependency graphs for us to use in our test suite.
+ *
+ * The graphs using `test()` live in the `class` and need to be instantiated
+ * every time you use them, because they are mutable (you can poke at the
+ * `test`'s `counter`/`failure`/`exception` fields to test various graph
+ * evaluation scenarios.
+ *
+ * The immutable graphs, used for testing discovery & target resolution,
+ * live in the companion object.
+ */
+class TestGraphs(){
+ // single
+ object singleton extends TestUtil.BaseModule {
+ val single = test()
+ }
+
+ object bactickIdentifiers extends TestUtil.BaseModule {
+ val `up-target` = test()
+ val `a-down-target` = test(`up-target`)
+ val `invisible&` = test()
+ object `nested-module` extends TestUtil.BaseModule {
+ val `nested-target` = test()
+ }
+ }
+
+ // up---down
+ object pair extends TestUtil.BaseModule{
+ val up = test()
+ val down = test(up)
+ }
+
+ // up---o---down
+ object anonTriple extends TestUtil.BaseModule {
+ val up = test()
+ val down = test(test.anon(up))
+ }
+
+ // left
+ // / \
+ // up down
+ // \ /
+ // right
+ object diamond extends TestUtil.BaseModule {
+ val up = test()
+ val left = test(up)
+ val right = test(up)
+ val down = test(left, right)
+ }
+
+ // o
+ // / \
+ // up down
+ // \ /
+ // o
+ object anonDiamond extends TestUtil.BaseModule {
+ val up = test()
+ val down = test(test.anon(up), test.anon(up))
+ }
+
+ object defCachedDiamond extends TestUtil.BaseModule {
+ def up = T{ test() }
+ def left = T{ test(up) }
+ def right = T{ test(up) }
+ def down = T{ test(left, right) }
+ }
+
+
+ object borkedCachedDiamond2 extends TestUtil.BaseModule {
+ def up = test()
+ def left = test(up)
+ def right = test(up)
+ def down = test(left, right)
+ }
+
+ object borkedCachedDiamond3 extends TestUtil.BaseModule {
+ def up = test()
+ def left = test(up)
+ def right = test(up)
+ def down = test(left, right)
+ }
+
+ // o g-----o
+ // \ \ \
+ // o o h-----I---o
+ // \ / \ / \ / \ \
+ // A---c--o E o-o \ \
+ // / \ / \ / \ o---J
+ // o d o--o o / /
+ // \ / \ / /
+ // o o---F---o
+ // / /
+ // o--B o
+ object bigSingleTerminal extends TestUtil.BaseModule {
+ val a = test(test.anon(), test.anon())
+ val b = test(test.anon())
+ val e = {
+ val c = test.anon(a)
+ val d = test.anon(a)
+ test(
+ test.anon(test.anon(), test.anon(c)),
+ test.anon(test.anon(c, test.anon(d, b)))
+ )
+ }
+ val f = test(test.anon(test.anon(), test.anon(e)))
+
+ val i = {
+ val g = test.anon()
+ val h = test.anon(g, e)
+ test(test.anon(g), test.anon(test.anon(h)))
+ }
+ val j = test(test.anon(i), test.anon(i, f), test.anon(f))
+ }
+ // _ left _
+ // / \
+ // task1 -------- right
+ // _/
+ // change - task2
+ object separateGroups extends TestUtil.BaseModule {
+ val task1 = T.task{ 1 }
+ def left = T{ task1() }
+ val change = test()
+ val task2 = T.task{ change() }
+ def right = T{ task1() + task2() + left() + 1 }
+
+ }
+}
+
+
+object TestGraphs{
+ // _ left _
+ // / \
+ // task -------- right
+ object triangleTask extends TestUtil.BaseModule {
+ val task = T.task{ 1 }
+ def left = T{ task() }
+ def right = T{ task() + left() + 1 }
+ }
+
+
+ // _ left
+ // /
+ // task -------- right
+ object multiTerminalGroup extends TestUtil.BaseModule {
+ val task = T.task{ 1 }
+ def left = T{ task() }
+ def right = T{ task() }
+ }
+
+ // _ left _____________
+ // / \ \
+ // task1 -------- right ----- task2
+ object multiTerminalBoundary extends TestUtil.BaseModule {
+ val task1 = T.task{ 1 }
+ def left = T{ task1() }
+ def right = T{ task1() + left() + 1 }
+ val task2 = T.task{ left() + right() }
+ }
+
+
+ trait CanNest extends Module{
+ def single = T{ 1 }
+ def invisible: Any = T{ 2 }
+ def invisible2: mill.define.Task[Int] = T{ 3 }
+ def invisible3: mill.define.Task[_] = T{ 4 }
+ }
+ object nestedModule extends TestUtil.BaseModule {
+ def single = T{ 5 }
+ def invisible: Any = T{ 6 }
+ object nested extends Module{
+ def single = T{ 7 }
+ def invisible: Any = T{ 8 }
+
+ }
+ object classInstance extends CanNest
+
+ }
+
+ trait BaseModule extends Module {
+ def foo = T{ Seq("base") }
+ def cmd(i: Int) = T.command{ Seq("base" + i) }
+ }
+
+ object canOverrideSuper extends TestUtil.BaseModule with BaseModule {
+ override def foo = T{ super.foo() ++ Seq("object") }
+ override def cmd(i: Int) = T.command{ super.cmd(i)() ++ Seq("object" + i) }
+ override lazy val millDiscover: Discover[this.type] = Discover[this.type]
+ }
+
+ trait TraitWithModule extends Module{ outer =>
+ object TraitModule extends Module{
+ def testFrameworks = T{ Seq("mill.UTestFramework") }
+ def test() = T.command{ ()/*donothing*/ }
+ }
+ }
+
+
+ // Make sure nested objects inherited from traits work
+ object TraitWithModuleObject extends TestUtil.BaseModule with TraitWithModule{
+ override lazy val millDiscover: Discover[this.type] = Discover[this.type]
+ }
+
+ object nullTasks extends TestUtil.BaseModule{
+ val nullString: String = null
+ def nullTask1 = T.task{ nullString }
+ def nullTask2 = T.task{ nullTask1() }
+
+ def nullTarget1 = T{ nullString }
+ def nullTarget2 = T{ nullTarget1() }
+ def nullTarget3 = T{ nullTask1() }
+ def nullTarget4 = T{ nullTask2() }
+
+ def nullCommand1() = T.command{ nullString }
+ def nullCommand2() = T.command{ nullTarget1() }
+ def nullCommand3() = T.command{ nullTask1() }
+ def nullCommand4() = T.command{ nullTask2() }
+
+ override lazy val millDiscover: Discover[this.type] = Discover[this.type]
+ }
+
+ object singleCross extends TestUtil.BaseModule {
+ object cross extends mill.Cross[Cross]("210", "211", "212")
+ class Cross(scalaVersion: String) extends Module{
+ def suffix = T{ scalaVersion }
+ }
+ }
+ object crossResolved extends TestUtil.BaseModule {
+ trait MyModule extends Module{
+ def crossVersion: String
+ implicit object resolver extends mill.define.Cross.Resolver[MyModule]{
+ def resolve[V <: MyModule](c: Cross[V]): V = c.itemMap(List(crossVersion))
+ }
+ }
+
+ object foo extends mill.Cross[FooModule]("2.10", "2.11", "2.12")
+ class FooModule(val crossVersion: String) extends MyModule{
+ def suffix = T{ crossVersion }
+ }
+
+ object bar extends mill.Cross[BarModule]("2.10", "2.11", "2.12")
+ class BarModule(val crossVersion: String) extends MyModule{
+ def longSuffix = T{ "_" + foo().suffix() }
+ }
+ }
+ object doubleCross extends TestUtil.BaseModule {
+ val crossMatrix = for{
+ scalaVersion <- Seq("210", "211", "212")
+ platform <- Seq("jvm", "js", "native")
+ if !(platform == "native" && scalaVersion != "212")
+ } yield (scalaVersion, platform)
+ object cross extends mill.Cross[Cross](crossMatrix:_*)
+ class Cross(scalaVersion: String, platform: String) extends Module{
+ def suffix = T{ scalaVersion + "_" + platform }
+ }
+ }
+
+ object nestedCrosses extends TestUtil.BaseModule {
+ object cross extends mill.Cross[Cross]("210", "211", "212")
+ class Cross(scalaVersion: String) extends mill.Module{
+ object cross2 extends mill.Cross[Cross]("jvm", "js", "native")
+ class Cross(platform: String) extends mill.Module{
+ def suffix = T{ scalaVersion + "_" + platform }
+ }
+ }
+ }
+}
diff --git a/main/test/src/util/TestUtil.scala b/main/test/src/util/TestUtil.scala
new file mode 100644
index 00000000..baab2992
--- /dev/null
+++ b/main/test/src/util/TestUtil.scala
@@ -0,0 +1,86 @@
+package mill.util
+
+import mill.util.Router.Overrides
+import mill.define._
+import mill.api.Result
+import mill.api.Result.OuterStack
+import utest.assert
+import mill.util.Strict.Agg
+import utest.framework.TestPath
+
+import scala.collection.mutable
+
+object TestUtil {
+ def getOutPath()(implicit fullName: sourcecode.FullName,
+ tp: TestPath) = {
+ os.pwd / 'target / 'workspace / (fullName.value.split('.') ++ tp.value)
+ }
+ def getOutPathStatic()(implicit fullName: sourcecode.FullName) = {
+ os.pwd / 'target / 'workspace / fullName.value.split('.')
+ }
+
+ def getSrcPathStatic()(implicit fullName: sourcecode.FullName) = {
+ os.pwd / 'target / 'worksources / fullName.value.split('.')
+ }
+ def getSrcPathBase() = {
+ os.pwd / 'target / 'worksources
+ }
+
+ class BaseModule(implicit millModuleEnclosing0: sourcecode.Enclosing,
+ millModuleLine0: sourcecode.Line,
+ millName0: sourcecode.Name,
+ overrides: Overrides)
+ extends mill.define.BaseModule(getSrcPathBase() / millModuleEnclosing0.value.split("\\.| |#"))(
+ implicitly, implicitly, implicitly, implicitly, implicitly){
+ lazy val millDiscover: Discover[this.type] = Discover[this.type]
+ }
+
+ object test{
+
+ def anon(inputs: Task[Int]*) = new Test(inputs)
+ def apply(inputs: Task[Int]*)
+ (implicit ctx: mill.define.Ctx)= {
+ new TestTarget(inputs, pure = inputs.nonEmpty)
+ }
+ }
+
+ class Test(val inputs: Seq[Task[Int]]) extends Task[Int]{
+ var counter = 0
+ var failure = Option.empty[String]
+ var exception = Option.empty[Throwable]
+ override def evaluate(args: Ctx) = {
+ failure.map(Result.Failure(_)) orElse
+ exception.map(Result.Exception(_, new OuterStack(Nil))) getOrElse
+ Result.Success(counter + args.args.map(_.asInstanceOf[Int]).sum)
+ }
+ override def sideHash = counter + failure.hashCode() + exception.hashCode()
+ }
+ /**
+ * A dummy target that takes any number of inputs, and whose output can be
+ * controlled externally, so you can construct arbitrary dataflow graphs and
+ * test how changes propagate.
+ */
+ class TestTarget(inputs: Seq[Task[Int]],
+ val pure: Boolean)
+ (implicit ctx0: mill.define.Ctx)
+ extends Test(inputs) with Target[Int]{
+ val ctx = ctx0.copy(segments = ctx0.segments ++ Seq(ctx0.segment))
+ val readWrite = upickle.default.readwriter[Int]
+
+
+ }
+ def checkTopological(targets: Agg[Task[_]]) = {
+ val seen = mutable.Set.empty[Task[_]]
+ for(t <- targets.indexed.reverseIterator){
+ seen.add(t)
+ for(upstream <- t.inputs){
+ assert(!seen(upstream))
+ }
+ }
+ }
+ def disableInJava9OrAbove(f: => Any): Unit = {
+ if (!ammonite.util.Util.java9OrAbove) {
+ f
+ }
+ }
+}