diff --git a/.github/workflows/actions.yml b/.github/workflows/actions.yml
index 162cc87bed7..1d05e7d3e14 100644
--- a/.github/workflows/actions.yml
+++ b/.github/workflows/actions.yml
@@ -28,24 +28,30 @@ concurrency:
cancel-in-progress: true
jobs:
-
+ build-linux:
+ uses: ./.github/workflows/run-mill-action.yml
+ with:
+ java-version: 11
+ millargs: __.compile
+ populate_cache: true
+ build-windows:
+ uses: ./.github/workflows/run-mill-action.yml
+ with:
+ os: windows-latest
+ java-version: 11
+ millargs: __.compile
+ populate_cache: true
itest:
+ needs: build-linux
strategy:
fail-fast: false
matrix:
include:
# bootstrap tests
- java-version: 11 # Have one job on oldest JVM
- buildcmd: ci/test-mill-dev.sh
+ buildcmd: ci/test-mill-dev.sh && ci/test-mill-release.sh && ./mill -i -k __.ivyDepsTree && ./mill -i -k __.ivyDepsTree --withRuntime
- java-version: 17 # Have one job on default JVM
- buildcmd: ci/test-mill-release.sh
- - java-version: 17
buildcmd: ci/test-mill-bootstrap.sh
- # Just some reporting to enable reasoning about library upgrades
- - java-version: 11
- buildcmd: |
- ./mill -i -k __.ivyDepsTree
- ./mill -i -k __.ivyDepsTree --withRuntime
uses: ./.github/workflows/run-mill-action.yml
with:
@@ -53,55 +59,48 @@ jobs:
buildcmd: ${{ matrix.buildcmd }}
linux:
+ needs: build-linux
strategy:
fail-fast: false
matrix:
- java-version: [11, 17]
- millargs:
- # Run unit and module tests on both oldest and newest Java versions
- - '"{main,scalalib,testrunner,bsp}.__.test"'
+
include:
- # For most tests, run them arbitrarily on Java 8 or Java 17 on Linux, and
+ # For most tests, run them arbitrarily on Java 11 or Java 17 on Linux, and
# on the opposite version on Windows below, so we get decent coverage of
# each test on each Java version and each operating system
+ # We also try to group tests together to manuaully balance out the runtimes of each jobs
+ - java-version: 17
+ millargs: "'{main,scalalib,testrunner,bsp,testkit}.__.testCached'"
- java-version: 11
- millargs: '"scalajslib.__.test"'
- - java-version: 11
- millargs: '"scalanativelib.__.test"'
+ millargs: "'{scalajslib,scalanativelib}.__.testCached'"
- java-version: 17
- millargs: "contrib._.test"
+ millargs: "contrib.__.testCached"
- # Group these tests together to try and balance out the runtimes of each job
- # Just running in `local` mode since they shouldn't depend on the mode
- java-version: 17
- millargs: "'example.javalib.__.local.test'"
+ millargs: "'example.javalib.__.local.testCached'"
- java-version: 17
- millargs: "'example.scalalib.__.local.test'"
+ millargs: "'example.scalalib.__.local.testCached'"
- java-version: 11
- millargs: "'example.thirdparty[{mockito,acyclic,commons-io}].local.test'"
+ millargs: "'example.thirdparty[{mockito,acyclic,commons-io}].local.testCached'"
- java-version: 17
- millargs: "'example.thirdparty[{fansi,jimfs,netty,gatling}].local.test'"
+ millargs: "'example.thirdparty[{fansi,jimfs,netty,gatling}].local.testCached'"
- java-version: 11
- millargs: "'example.depth.__.local.test'"
- - java-version: 17
- millargs: "'example.extending.__.local.test'"
+ millargs: "'example.{depth,extending}.__.local.testCached'"
# Most of these integration tests should not depend on which mode they
# are run in, so just run them in `local`
- java-version: 11
- millargs: "'integration.{failure,feature,ide}[_].local.test'"
+ millargs: "'integration.{failure,feature,ide}.__.local.testCached'"
- # These invalidation tests need to be exercised in all three execution modes
+ # These invalidation tests need to be exercised in both execution modes
# to make sure they work with and without -i/--no-server being passed
- java-version: 17
- millargs: "'integration.invalidation[_].local.test'"
- - java-version: 17
- millargs: "'integration.invalidation[_].fork.test'"
+ millargs: "'integration.invalidation.__.fork.testCached'"
- java-version: 17
- millargs: "'integration.invalidation[_].server.test'"
+ millargs: "'integration.invalidation.__.server.testCached'"
# Check docsite compiles
- - java-version: 17
+ - java-version: 11
millargs: docs.githubPages
@@ -111,32 +110,22 @@ jobs:
millargs: ${{ matrix.millargs }}
compiler-bridge:
+ needs: build-linux
uses: ./.github/workflows/run-mill-action.yml
with:
java-version: '8'
millargs: bridge.__.publishLocal
env-bridge-versions: 'essential'
- format-check:
- uses: ./.github/workflows/run-mill-action.yml
- with:
- java-version: '11'
- millargs: mill.scalalib.scalafmt.ScalafmtModule/checkFormatAll __.sources
-
- scalafix-check:
+ format-scalafix-bincompat:
+ needs: build-linux
uses: ./.github/workflows/run-mill-action.yml
with:
java-version: '11'
- millargs: -i -k __.fix --check
-
- bincompat-check:
- uses: ./.github/workflows/run-mill-action.yml
- with:
- java-version: '11'
- millargs: __.mimaReportBinaryIssues
- continue-on-error: true
+ buildcmd: ./mill -i mill.scalalib.scalafmt.ScalafmtModule/checkFormatAll __.sources + __.mimaReportBinaryIssues + __.fix --check
windows:
+ needs: build-windows
strategy:
fail-fast: false
matrix:
@@ -145,16 +134,12 @@ jobs:
# the whole suite can take hours on windows v.s. half an hour on linux
- java-version: 11
millargs: '"{main,scalalib,bsp}.__.test"'
- - java-version: 17
- millargs: '"scalajslib.__.test"'
- java-version: 11
- millargs: '"example.scalalib.basic.__.fork.test"'
+ millargs: '"example.scalalib.{basic,web}.__.fork.test"'
- java-version: 17
- millargs: "'integration.feature[_].fork.test'"
+ millargs: "'integration.{feature,failure}[_].fork.test'"
- java-version: 11
millargs: "'integration.invalidation[_].server.test'"
- - java-version: 17
- millargs: "'integration.failure[_].fork.test'"
- java-version: 11
millargs: "contrib.__.test"
@@ -167,7 +152,7 @@ jobs:
publish-sonatype:
# when in master repo, publish all tags and manual runs on main
if: github.repository == 'com-lihaoyi/mill' && (startsWith( github.ref, 'refs/tags/') || (github.ref == 'refs/heads/main' && github.event_name == 'workflow_dispatch' ) )
- needs: [linux, windows, compiler-bridge, format-check, bincompat-check, scalafix-check, itest]
+ needs: [linux, windows, compiler-bridge, format-scalafix-bincompat, itest]
runs-on: ubuntu-latest
diff --git a/.github/workflows/run-mill-action.yml b/.github/workflows/run-mill-action.yml
index 9fef5b49d4e..6d7d9266992 100644
--- a/.github/workflows/run-mill-action.yml
+++ b/.github/workflows/run-mill-action.yml
@@ -18,6 +18,9 @@ on:
continue-on-error:
default: false
type: boolean
+ populate_cache:
+ default: false
+ type: boolean
timeout-minutes:
default: 60
type: number
@@ -38,6 +41,16 @@ jobs:
- uses: actions/checkout@v4
with:
fetch-depth: 0
+ if: ${{ inputs.populate_cache }}
+
+ - uses: actions/download-artifact@v4
+ if: ${{ !inputs.populate_cache }}
+ with:
+ path: .
+ name: ${{ inputs.os }}-artifact
+
+ - name: chmod executable
+ run: "chmod -R +x ."
- uses: coursier/cache-action@v6
@@ -60,5 +73,18 @@ jobs:
if: inputs.millargs != '' && !startsWith(inputs.os, 'windows')
- name: Run Mill (on Windows) '${{ inputs.millargs }}'
- run: cmd /C %GITHUB_WORKSPACE%\ci\mill.bat -i -d -k ${{ inputs.millargs }}
- if: inputs.millargs != '' && startsWith(inputs.os, 'windows')
\ No newline at end of file
+ run: cmd /C %GITHUB_WORKSPACE%\ci\mill.bat -ij1 __.resolvedIvyDeps; cmd /C %GITHUB_WORKSPACE%\ci\mill.bat -i -j1 -k ${{ inputs.millargs }}
+ if: inputs.millargs != '' && startsWith(inputs.os, 'windows')
+
+ - name: Run Mill (on Windows) Worker Cleanup
+ run: 'taskkill -f -im java* && rm -rf out/mill-worker-*'
+ if: inputs.millargs != '' && startsWith(inputs.os, 'windows')
+ shell: bash
+ continue-on-error: true
+
+ - uses: actions/upload-artifact@v4.3.5
+ with:
+ path: .
+ name: ${{ inputs.os }}-artifact
+ include-hidden-files: true
+ if: ${{ inputs.populate_cache }}
\ No newline at end of file
diff --git a/build.mill b/build.mill
index ca4043efb91..1a02d6470eb 100644
--- a/build.mill
+++ b/build.mill
@@ -151,7 +151,7 @@ object Deps {
val log4j2Core = ivy"org.apache.logging.log4j:log4j-core:2.23.1"
val osLib = ivy"com.lihaoyi::os-lib:0.10.5"
val pprint = ivy"com.lihaoyi::pprint:0.9.0"
- val mainargs = ivy"com.lihaoyi::mainargs:0.7.2"
+ val mainargs = ivy"com.lihaoyi::mainargs:0.7.4"
val millModuledefsVersion = "0.11.0-M2"
val millModuledefsString = s"com.lihaoyi::mill-moduledefs:${millModuledefsVersion}"
val millModuledefs = ivy"${millModuledefsString}"
diff --git a/ci/test-mill-dev.sh b/ci/test-mill-dev.sh
index 44828909db0..8ffede49a8c 100755
--- a/ci/test-mill-dev.sh
+++ b/ci/test-mill-dev.sh
@@ -16,3 +16,5 @@ test -d $EXAMPLE/out/foo/3.3.3/compile.dest
./mill -i dist.run $EXAMPLE show "bar[2.13.8].assembly"
test -f $EXAMPLE/out/bar/2.13.8/assembly.dest/out.jar
+
+./mill -i dist.run $EXAMPLE shutdown
\ No newline at end of file
diff --git a/ci/test-mill-release.sh b/ci/test-mill-release.sh
index 562771dff96..56fd55d69c4 100755
--- a/ci/test-mill-release.sh
+++ b/ci/test-mill-release.sh
@@ -19,3 +19,5 @@ test -d $EXAMPLE/out/foo/3.3.3/compile.dest
(cd $EXAMPLE && ../../../../out/dist/assembly.dest/mill show "bar[2.13.8].assembly")
test -f $EXAMPLE/out/bar/2.13.8/assembly.dest/out.jar
+
+(cd $EXAMPLE && ../../../../out/dist/assembly.dest/mill shutdown)
\ No newline at end of file
diff --git a/example/depth/large/11-helper-files/build.mill b/example/depth/large/11-helper-files/build.mill
index 2f7cd012eb8..416c9a0cf55 100644
--- a/example/depth/large/11-helper-files/build.mill
+++ b/example/depth/large/11-helper-files/build.mill
@@ -8,6 +8,7 @@ object `package` extends RootModule with MyModule{
"MY_PROJECT_VERSION" -> versions.myProjectVersion,
)
}
+
/** See Also: util.mill */
/** See Also: foo/package.mill */
/** See Also: foo/versions.mill */
diff --git a/example/depth/large/13-helper-files-mill-sc/build.mill.sc b/example/depth/large/13-helper-files-mill-sc/build.mill.sc
new file mode 100644
index 00000000000..7a757d7b0ba
--- /dev/null
+++ b/example/depth/large/13-helper-files-mill-sc/build.mill.sc
@@ -0,0 +1,39 @@
+package build
+import mill._, scalalib._
+import $file.foo.versions
+import $file.util.MyModule
+object `package` extends RootModule with MyModule{
+ def forkEnv = Map(
+ "MY_SCALA_VERSION" -> build.scalaVersion(),
+ "MY_PROJECT_VERSION" -> versions.myProjectVersion,
+ )
+}
+///** See Also: util.mill.sc */
+///** See Also: foo/package.mill.sc */
+///** See Also: foo/versions.mill.sc */
+
+
+// Apart from having `package` files in subfolders to define modules, Mill
+// also allows you to have helper code in any `*.mill` file in the same folder
+// as your `build.mill` or a `package.mill`.
+//
+// Different helper scripts and ``build.mill``/``package`` files can all refer to
+// each other using the `build` object, which marks the root object of your build.
+// In this example:
+//
+// * `build.mill` can be referred to as simple `build`
+// * `util.mill` can be referred to as simple `$file.util`
+// * `foo/package` can be referred to as simple `build.foo`
+// * `foo/versions.mill` can be referred to as simple `$file.foo.versions`
+
+/** Usage
+
+> ./mill run
+Main Env build.util.myScalaVersion: 2.13.14
+Main Env build.foo.versions.myProjectVersion: 0.0.1
+
+> ./mill foo.run
+Foo Env build.util.myScalaVersion: 2.13.14
+Foo Env build.foo.versions.myProjectVersion: 0.0.1
+
+*/
diff --git a/example/depth/large/13-helper-files-mill-sc/foo/package.mill.sc b/example/depth/large/13-helper-files-mill-sc/foo/package.mill.sc
new file mode 100644
index 00000000000..a28fe0a29ce
--- /dev/null
+++ b/example/depth/large/13-helper-files-mill-sc/foo/package.mill.sc
@@ -0,0 +1,10 @@
+package build.foo
+import mill._, scalalib._
+import $file.util
+import $file.foo.versions.myProjectVersion
+object `package` extends RootModule with build_.util.MyModule {
+ def forkEnv = Map(
+ "MY_SCALA_VERSION" -> util.myScalaVersion,
+ "MY_PROJECT_VERSION" -> myProjectVersion
+ )
+}
diff --git a/example/depth/large/13-helper-files-mill-sc/foo/src/Foo.scala b/example/depth/large/13-helper-files-mill-sc/foo/src/Foo.scala
new file mode 100644
index 00000000000..08fe8028aac
--- /dev/null
+++ b/example/depth/large/13-helper-files-mill-sc/foo/src/Foo.scala
@@ -0,0 +1,8 @@
+package foo
+
+object Foo {
+ def main(args: Array[String]): Unit = {
+ println("Foo Env build.util.myScalaVersion: " + sys.env("MY_SCALA_VERSION"))
+ println("Foo Env build.foo.versions.myProjectVersion: " + sys.env("MY_PROJECT_VERSION"))
+ }
+}
diff --git a/example/depth/large/13-helper-files-mill-sc/foo/versions.mill.sc b/example/depth/large/13-helper-files-mill-sc/foo/versions.mill.sc
new file mode 100644
index 00000000000..d2d0681b67c
--- /dev/null
+++ b/example/depth/large/13-helper-files-mill-sc/foo/versions.mill.sc
@@ -0,0 +1,3 @@
+package build.foo
+
+def myProjectVersion = "0.0.1"
\ No newline at end of file
diff --git a/example/depth/large/13-helper-files-mill-sc/src/Main.scala b/example/depth/large/13-helper-files-mill-sc/src/Main.scala
new file mode 100644
index 00000000000..f8e6fdfa68f
--- /dev/null
+++ b/example/depth/large/13-helper-files-mill-sc/src/Main.scala
@@ -0,0 +1,6 @@
+object Main {
+ def main(args: Array[String]): Unit = {
+ println("Main Env build.util.myScalaVersion: " + sys.env("MY_SCALA_VERSION"))
+ println("Main Env build.foo.versions.myProjectVersion: " + sys.env("MY_PROJECT_VERSION"))
+ }
+}
diff --git a/example/depth/large/13-helper-files-mill-sc/util.mill.sc b/example/depth/large/13-helper-files-mill-sc/util.mill.sc
new file mode 100644
index 00000000000..0e4b102796e
--- /dev/null
+++ b/example/depth/large/13-helper-files-mill-sc/util.mill.sc
@@ -0,0 +1,9 @@
+package build
+
+import mill._, scalalib._
+
+def myScalaVersion = "2.13.14"
+
+trait MyModule extends ScalaModule {
+ def scalaVersion = myScalaVersion
+}
diff --git a/example/javalib/web/2-hello-spring-boot/build.mill b/example/javalib/web/2-hello-spring-boot/build.mill
index da4b7f308c1..cc3ce13aad7 100644
--- a/example/javalib/web/2-hello-spring-boot/build.mill
+++ b/example/javalib/web/2-hello-spring-boot/build.mill
@@ -23,7 +23,7 @@ object `package` extends RootModule with JavaModule {
> mill test
...com.example.HelloSpringBootTest#shouldReturnDefaultMessage() finished...
-> mill runBackground; sleep 10 # give time for server to start
+> mill runBackground; sleep 15 # give time for server to start
> curl http://localhost:8086
...
Hello, World!
...
diff --git a/example/javalib/web/3-todo-spring-boot/build.mill b/example/javalib/web/3-todo-spring-boot/build.mill
index 6b48e5f64af..8f0d5d12abd 100644
--- a/example/javalib/web/3-todo-spring-boot/build.mill
+++ b/example/javalib/web/3-todo-spring-boot/build.mill
@@ -61,7 +61,7 @@ object `package` extends RootModule with JavaModule {
...com.example.TodomvcIntegrationTests#homePageLoads() finished...
...com.example.TodomvcIntegrationTests#addNewTodoItem() finished...
-> mill test.runBackground; sleep 10 # give time for server to start
+> mill test.runBackground; sleep 15 # give time for server to start
> curl http://localhost:8087
...todos
...
diff --git a/example/javalib/web/4-hello-micronaut/build.mill b/example/javalib/web/4-hello-micronaut/build.mill
index 3dba9169676..ff6ffb67a54 100644
--- a/example/javalib/web/4-hello-micronaut/build.mill
+++ b/example/javalib/web/4-hello-micronaut/build.mill
@@ -69,7 +69,7 @@ trait MicronautModule extends MavenModule{
> mill test
...example.micronaut.HelloControllerTest#testHello()...
-> mill runBackground; sleep 2 # give time for server to start
+> mill runBackground; sleep 5 # give time for server to start
> curl http://localhost:8088/hello
...Hello World...
diff --git a/example/javalib/web/5-todo-micronaut/build.mill b/example/javalib/web/5-todo-micronaut/build.mill
index d2b4c180ffe..a81c48a5b88 100644
--- a/example/javalib/web/5-todo-micronaut/build.mill
+++ b/example/javalib/web/5-todo-micronaut/build.mill
@@ -90,7 +90,7 @@ trait MicronautModule extends MavenModule{
...example.micronaut.TodoItemControllerTest...
...example.micronaut.HtmxWebJarsTest...
-> mill runBackground; sleep 2 # give time for server to start
+> mill runBackground; sleep 5 # give time for server to start
> curl http://localhost:8088
...todos
...
diff --git a/integration/failure/build-file-in-subfolder/src/BuildFileInSubfolderTests.scala b/integration/failure/build-file-in-subfolder/src/BuildFileInSubfolderTests.scala
index f5d51acafd0..ea464c3864c 100644
--- a/integration/failure/build-file-in-subfolder/src/BuildFileInSubfolderTests.scala
+++ b/integration/failure/build-file-in-subfolder/src/BuildFileInSubfolderTests.scala
@@ -1,15 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object BuildFileInSubfolderTests extends IntegrationTestSuite {
+object BuildFileInSubfolderTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
- val res = eval(("resolve", "_"))
+ test("success") - integrationTest { tester =>
+ val res = tester.eval(("resolve", "_"))
assert(res.isSuccess == false)
assert(res.err.contains("Mill build.mill files can only be in the project root"))
}
diff --git a/integration/failure/compile-error/src/CompileErrorTests.scala b/integration/failure/compile-error/src/CompileErrorTests.scala
index 6c718d80ae4..999c258a9e9 100644
--- a/integration/failure/compile-error/src/CompileErrorTests.scala
+++ b/integration/failure/compile-error/src/CompileErrorTests.scala
@@ -1,15 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object CompileErrorTests extends IntegrationTestSuite {
+object CompileErrorTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test {
- val res = eval("foo.scalaVersion")
+ test - integrationTest { tester =>
+ val res = tester.eval("foo.scalaVersion")
assert(res.isSuccess == false)
assert(res.err.contains("""bar.mill:15:9: not found: value doesntExist"""))
diff --git a/integration/failure/cross-collisions/src/CrossCollisionsTests.scala b/integration/failure/cross-collisions/src/CrossCollisionsTests.scala
index f964a019fb7..04805609ab5 100644
--- a/integration/failure/cross-collisions/src/CrossCollisionsTests.scala
+++ b/integration/failure/cross-collisions/src/CrossCollisionsTests.scala
@@ -1,15 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object CrossCollisionsTests extends IntegrationTestSuite {
+object CrossCollisionsTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("detect-collision") {
- val res = eval(("resolve", "foo._"))
+ test("detect-collision") - integrationTest { tester =>
+ val res = tester.eval(("resolve", "foo._"))
assert(!res.isSuccess)
assert(res.err.contains("Cross module "))
assert(
diff --git a/integration/failure/invalid-meta-module/src/InvalidMetaModuleTests.scala b/integration/failure/invalid-meta-module/src/InvalidMetaModuleTests.scala
index 3387cc7fbeb..429d22a44c5 100644
--- a/integration/failure/invalid-meta-module/src/InvalidMetaModuleTests.scala
+++ b/integration/failure/invalid-meta-module/src/InvalidMetaModuleTests.scala
@@ -1,15 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object InvalidMetaModuleTests extends IntegrationTestSuite {
+object InvalidMetaModuleTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
- val res = eval(("resolve", "_"))
+ test("success") - integrationTest { tester =>
+ val res = tester.eval(("resolve", "_"))
assert(res.isSuccess == false)
assert(res.err.contains("object `package` "))
assert(res.err.contains("must extend `MillBuildRootModule`"))
diff --git a/integration/failure/invalid-package-declaration/src/InvalidPackageDeclaration.scala b/integration/failure/invalid-package-declaration/src/InvalidPackageDeclaration.scala
index b7afb1dbd2e..f2806779c65 100644
--- a/integration/failure/invalid-package-declaration/src/InvalidPackageDeclaration.scala
+++ b/integration/failure/invalid-package-declaration/src/InvalidPackageDeclaration.scala
@@ -1,15 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object InvalidPackageDeclaration extends IntegrationTestSuite {
+object InvalidPackageDeclaration extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
- val res = eval(("resolve", "_"))
+ test("success") - integrationTest { tester =>
+ val res = tester.eval(("resolve", "_"))
assert(res.isSuccess == false)
assert(res.err.contains(
"""Package declaration "package wrong" in build.mill does not match folder structure. Expected: "package build""""
diff --git a/integration/failure/invalid-root-module/src/InvalidRootModuleTests.scala b/integration/failure/invalid-root-module/src/InvalidRootModuleTests.scala
index 7d1573a2044..fc0831494c9 100644
--- a/integration/failure/invalid-root-module/src/InvalidRootModuleTests.scala
+++ b/integration/failure/invalid-root-module/src/InvalidRootModuleTests.scala
@@ -1,15 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object InvalidRootModuleTests extends IntegrationTestSuite {
+object InvalidRootModuleTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
- val res = eval(("resolve", "_"))
+ test("success") - integrationTest { tester =>
+ val res = tester.eval(("resolve", "_"))
assert(res.isSuccess == false)
assert(res.err.contains("object `package` in "))
assert(res.err.contains("must extend `RootModule`"))
diff --git a/integration/failure/invalid-subfolder-root-module/src/InvalidSubfolderRootModuleTests.scala b/integration/failure/invalid-subfolder-root-module/src/InvalidSubfolderRootModuleTests.scala
index 6cbd9d98f75..8d9c8b11ddc 100644
--- a/integration/failure/invalid-subfolder-root-module/src/InvalidSubfolderRootModuleTests.scala
+++ b/integration/failure/invalid-subfolder-root-module/src/InvalidSubfolderRootModuleTests.scala
@@ -1,15 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object InvalidSubfolderRootModuleTests extends IntegrationTestSuite {
+object InvalidSubfolderRootModuleTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
- val res = eval(("resolve", "_"))
+ test("success") - integrationTest { tester =>
+ val res = tester.eval(("resolve", "_"))
assert(res.isSuccess == false)
assert(res.err.contains("object `package` "))
assert(res.err.contains("must extend `RootModule`"))
diff --git a/integration/failure/misnamed-root-module/src/MisnamedRootModuleTests.scala b/integration/failure/misnamed-root-module/src/MisnamedRootModuleTests.scala
index 466f32784e7..c21e8da6a32 100644
--- a/integration/failure/misnamed-root-module/src/MisnamedRootModuleTests.scala
+++ b/integration/failure/misnamed-root-module/src/MisnamedRootModuleTests.scala
@@ -1,15 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object MisnamedRootModuleTests extends IntegrationTestSuite {
+object MisnamedRootModuleTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
- val res = eval(("resolve", "_"))
+ test("success") - integrationTest { tester =>
+ val res = tester.eval(("resolve", "_"))
assert(!res.isSuccess)
assert(res.err.contains(
"Only one RootModule named `package` can be defined in a build, not: foo"
diff --git a/integration/failure/missing-build-file/src/MissingBuildFileTests.scala b/integration/failure/missing-build-file/src/MissingBuildFileTests.scala
index 412c1766651..2b6f625d991 100644
--- a/integration/failure/missing-build-file/src/MissingBuildFileTests.scala
+++ b/integration/failure/missing-build-file/src/MissingBuildFileTests.scala
@@ -1,15 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object MissingBuildFileTests extends IntegrationTestSuite {
+object MissingBuildFileTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test {
- val res = eval(("resolve", "_"))
+ test - integrationTest { tester =>
+ val res = tester.eval(("resolve", "_"))
assert(!res.isSuccess)
val s"build.mill file not found in $msg. Are you in a Mill project folder?" = res.err
}
diff --git a/integration/failure/module-init-error/src/ModuleInitErrorTests.scala b/integration/failure/module-init-error/src/ModuleInitErrorTests.scala
index a0609b6856d..c06cffab877 100644
--- a/integration/failure/module-init-error/src/ModuleInitErrorTests.scala
+++ b/integration/failure/module-init-error/src/ModuleInitErrorTests.scala
@@ -1,22 +1,20 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object ModuleInitErrorTests extends IntegrationTestSuite {
+object ModuleInitErrorTests extends UtestIntegrationTestSuite {
def captureOutErr = true
val tests: Tests = Tests {
- initWorkspace()
-
- test("resolve") {
+ test("resolve") - integrationTest { tester =>
// Ensure that resolve works even of the modules containing the resolved
// tasks are broken
- val res1 = eval(("resolve", "foo.fooTarget"))
+ val res1 = tester.eval(("resolve", "foo.fooTarget"))
assert(res1.isSuccess == true)
assert(res1.out.contains("foo.fooTarget"))
- val res2 = eval(("resolve", "_._"))
+ val res2 = tester.eval(("resolve", "_._"))
assert(res2.isSuccess == true)
assert(
res2.out.contains("bar.barCommand"),
@@ -26,11 +24,11 @@ object ModuleInitErrorTests extends IntegrationTestSuite {
res2.out.contains("foo.fooCommand")
)
- val res3 = eval(("resolve", "__.fooTarget"))
+ val res3 = tester.eval(("resolve", "__.fooTarget"))
assert(res3.isSuccess == true)
assert(res3.out.contains("foo.fooTarget"))
- val res4 = eval(("resolve", "__"))
+ val res4 = tester.eval(("resolve", "__"))
assert(res4.isSuccess == true)
assert(res4.out.contains("bar"))
assert(res4.out.contains("bar.barCommand"))
@@ -43,21 +41,24 @@ object ModuleInitErrorTests extends IntegrationTestSuite {
assert(res4.out.contains("foo.fooTarget"))
}
- test("rootTarget") {
+ test("rootTarget") - integrationTest { tester =>
+ import tester._
// If we specify a target in the root module, we are not
// affected by the sub-modules failing to initialize
val res = eval("rootTarget")
assert(res.isSuccess == true)
assert(res.out.contains("""Running rootTarget"""))
}
- test("rootCommand") {
+ test("rootCommand") - integrationTest { tester =>
+ import tester._
// If we specify a target in the root module, we are not
// affected by the sub-modules failing to initialize
val res = eval(("rootCommand", "-s", "hello"))
assert(res.isSuccess == true)
assert(res.out.contains("""Running rootCommand hello"""))
}
- test("fooTarget") {
+ test("fooTarget") - integrationTest { tester =>
+ import tester._
val res = eval("foo.fooTarget")
assert(res.isSuccess == false)
assert(fansi.Str(res.err).plainText.contains("""java.lang.Exception: Foo Boom"""))
@@ -65,29 +66,34 @@ object ModuleInitErrorTests extends IntegrationTestSuite {
// frames from the Mill launcher
assert(fansi.Str(res.err).plainText.linesIterator.size < 20)
}
- test("fooCommand") {
+ test("fooCommand") - integrationTest { tester =>
+ import tester._
val res = eval(("foo.fooCommand", "-s", "hello"))
assert(res.isSuccess == false)
assert(fansi.Str(res.err).plainText.contains("""java.lang.Exception: Foo Boom"""))
assert(fansi.Str(res.err).plainText.linesIterator.size < 20)
}
- test("barTarget") {
+ test("barTarget") - integrationTest { tester =>
+ import tester._
val res = eval("bar.barTarget")
assert(res.isSuccess == true)
assert(res.out.contains("""Running barTarget"""))
}
- test("barCommand") {
+ test("barCommand") - integrationTest { tester =>
+ import tester._
val res = eval(("bar.barCommand", "-s", "hello"))
assert(res.isSuccess == true)
assert(res.out.contains("""Running barCommand hello"""))
}
- test("quxTarget") {
+ test("quxTarget") - integrationTest { tester =>
+ import tester._
val res = eval("bar.qux.quxTarget")
assert(res.isSuccess == false)
assert(fansi.Str(res.err).plainText.contains("""java.lang.Exception: Qux Boom"""))
assert(fansi.Str(res.err).plainText.linesIterator.size < 20)
}
- test("quxCommand") {
+ test("quxCommand") - integrationTest { tester =>
+ import tester._
val res = eval(("bar.qux.quxCommand", "-s", "hello"))
assert(res.isSuccess == false)
assert(fansi.Str(res.err).plainText.contains("""java.lang.Exception: Qux Boom"""))
diff --git a/integration/failure/module-outside-top-level-module/src/ModuleOutsideTopLevelModuleTests.scala b/integration/failure/module-outside-top-level-module/src/ModuleOutsideTopLevelModuleTests.scala
index 0633cb930ac..28aac9aea3a 100644
--- a/integration/failure/module-outside-top-level-module/src/ModuleOutsideTopLevelModuleTests.scala
+++ b/integration/failure/module-outside-top-level-module/src/ModuleOutsideTopLevelModuleTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object ModuleOutsideTopLevelModuleTests extends IntegrationTestSuite {
+object ModuleOutsideTopLevelModuleTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
+ test("success") - integrationTest { tester =>
+ import tester._
val res = eval(("resolve", "_"))
assert(!res.isSuccess)
assert(
diff --git a/integration/failure/no-modules-in-helper-file/src/NoModulesInHelperFileTests.scala b/integration/failure/no-modules-in-helper-file/src/NoModulesInHelperFileTests.scala
index 0b5afb37c33..f68f2b874c3 100644
--- a/integration/failure/no-modules-in-helper-file/src/NoModulesInHelperFileTests.scala
+++ b/integration/failure/no-modules-in-helper-file/src/NoModulesInHelperFileTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object NoModulesInHelperFileTests extends IntegrationTestSuite {
+object NoModulesInHelperFileTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
+ test("success") - integrationTest { tester =>
+ import tester._
val res = eval(("resolve", "_"))
assert(res.isSuccess == false)
assert(
diff --git a/integration/failure/package-file-in-root/src/PackageFileInRootTests.scala b/integration/failure/package-file-in-root/src/PackageFileInRootTests.scala
index 87b8f4eddf2..e193c0534fa 100644
--- a/integration/failure/package-file-in-root/src/PackageFileInRootTests.scala
+++ b/integration/failure/package-file-in-root/src/PackageFileInRootTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object PackageFileInRootTests extends IntegrationTestSuite {
+object PackageFileInRootTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
+ test("success") - integrationTest { tester =>
+ import tester._
val res = eval(("resolve", "_"))
assert(res.isSuccess == false)
assert(res.err.contains("Mill package.mill files can only be in subfolders"))
diff --git a/integration/failure/parse-error/src/ParseErrorTests.scala b/integration/failure/parse-error/src/ParseErrorTests.scala
index 772df82f476..8206a60ad60 100644
--- a/integration/failure/parse-error/src/ParseErrorTests.scala
+++ b/integration/failure/parse-error/src/ParseErrorTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object ParseErrorTests extends IntegrationTestSuite {
+object ParseErrorTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test {
+ test - integrationTest { tester =>
+ import tester._
val res = eval("foo.scalaVersion")
assert(res.isSuccess == false)
diff --git a/integration/failure/root-module-compile-error/src/RootModuleCompileErrorTests.scala b/integration/failure/root-module-compile-error/src/RootModuleCompileErrorTests.scala
index 97244a3f8e1..d84b9483a14 100644
--- a/integration/failure/root-module-compile-error/src/RootModuleCompileErrorTests.scala
+++ b/integration/failure/root-module-compile-error/src/RootModuleCompileErrorTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object RootModuleCompileErrorTests extends IntegrationTestSuite {
+object RootModuleCompileErrorTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test {
+ test - integrationTest { tester =>
+ import tester._
val res = eval("foo.scalaVersion")
assert(res.isSuccess == false)
diff --git a/integration/failure/root-subfolder-module-collision/src/RootSubfolderModuleCollisionTests.scala b/integration/failure/root-subfolder-module-collision/src/RootSubfolderModuleCollisionTests.scala
index c33cbf5ff72..2becba29e17 100644
--- a/integration/failure/root-subfolder-module-collision/src/RootSubfolderModuleCollisionTests.scala
+++ b/integration/failure/root-subfolder-module-collision/src/RootSubfolderModuleCollisionTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object RootSubfolderModuleCollisionTests extends IntegrationTestSuite {
+object RootSubfolderModuleCollisionTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
+ test("success") - integrationTest { tester =>
+ import tester._
val res = eval(("resolve", "_"))
assert(res.isSuccess == false)
assert(res.err.contains("cannot override final member"))
diff --git a/integration/failure/subfolder-helper-module-collision/src/SubfolderHelperModuleCollisionTests.scala b/integration/failure/subfolder-helper-module-collision/src/SubfolderHelperModuleCollisionTests.scala
index d694aab1ed0..fde047ca517 100644
--- a/integration/failure/subfolder-helper-module-collision/src/SubfolderHelperModuleCollisionTests.scala
+++ b/integration/failure/subfolder-helper-module-collision/src/SubfolderHelperModuleCollisionTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object SubfolderHelperModuleCollisionTests extends IntegrationTestSuite {
+object SubfolderHelperModuleCollisionTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
+ test("success") - integrationTest { tester =>
+ import tester._
val res = eval(("resolve", "_"))
assert(res.isSuccess == false)
// Not a great error message but it will have to do for now
diff --git a/integration/failure/subfolder-missing-build-prefix/src/SubfolderMissingBuildPrefix.scala b/integration/failure/subfolder-missing-build-prefix/src/SubfolderMissingBuildPrefix.scala
index 7711bbdc64d..02e744e219d 100644
--- a/integration/failure/subfolder-missing-build-prefix/src/SubfolderMissingBuildPrefix.scala
+++ b/integration/failure/subfolder-missing-build-prefix/src/SubfolderMissingBuildPrefix.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object SubfolderMissingBuildPrefix extends IntegrationTestSuite {
+object SubfolderMissingBuildPrefix extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
+ test("success") - integrationTest { tester =>
+ import tester._
val res = eval(("resolve", "_"))
assert(res.isSuccess == false)
assert(res.err.contains("object y is not a member of package build_.sub"))
diff --git a/integration/failure/things-outside-top-level-module/src/ThingsOutsideTopLevelModuleTests.scala b/integration/failure/things-outside-top-level-module/src/ThingsOutsideTopLevelModuleTests.scala
index 564df09a65f..cf71ac33e5c 100644
--- a/integration/failure/things-outside-top-level-module/src/ThingsOutsideTopLevelModuleTests.scala
+++ b/integration/failure/things-outside-top-level-module/src/ThingsOutsideTopLevelModuleTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object ThingsOutsideTopLevelModuleTests extends IntegrationTestSuite {
+object ThingsOutsideTopLevelModuleTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("success") {
+ test("success") - integrationTest { tester =>
+ import tester._
val res = eval(("resolve", "_"))
assert(!res.isSuccess)
assert(
diff --git a/integration/feature/auxiliary-class-files/src/AuxiliaryClassFilesTests.scala b/integration/feature/auxiliary-class-files/src/AuxiliaryClassFilesTests.scala
index 5551fa0f4e1..e481db1bff9 100644
--- a/integration/feature/auxiliary-class-files/src/AuxiliaryClassFilesTests.scala
+++ b/integration/feature/auxiliary-class-files/src/AuxiliaryClassFilesTests.scala
@@ -1,59 +1,60 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
// Regress test for issue https://github.com/com-lihaoyi/mill/issues/1901
-object AuxiliaryClassFilesTests extends IntegrationTestSuite {
+object AuxiliaryClassFilesTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- test("tasty files are deleted together with companion class files") {
- initWorkspace()
- assert(eval("app.jvm.compile").isSuccess)
+ test("tasty files are deleted together with companion class files") - integrationTest {
+ tester =>
+ import tester._
+ assert(eval("app.jvm.compile").isSuccess)
- val classes = workspacePath / "out" / "app" / "jvm" / "compile.dest" / "classes"
- val firstRun = os.list(classes).map(_.last)
+ val classes = workspacePath / "out" / "app" / "jvm" / "compile.dest" / "classes"
+ val firstRun = os.list(classes).map(_.last)
- os.remove(workspacePath / "app" / "src" / "foo.scala")
+ os.remove(workspacePath / "app" / "src" / "foo.scala")
- assert(eval("app.jvm.compile").isSuccess)
+ assert(eval("app.jvm.compile").isSuccess)
- val secondRun = os.list(classes).map(_.last)
+ val secondRun = os.list(classes).map(_.last)
- assert(firstRun == Seq("foo$.class", "foo.class", "foo.tasty"))
- assert(secondRun == Seq.empty)
+ assert(firstRun == Seq("foo$.class", "foo.class", "foo.tasty"))
+ assert(secondRun == Seq.empty)
}
- test("compilation fails when deleting a class used by other files") {
- initWorkspace()
+ test("compilation fails when deleting a class used by other files") - integrationTest {
+ tester =>
+ import tester._
+ os.write(workspacePath / "app" / "src" / "bar.scala", "object bar { println(foo) }")
+ val firstRunSuccessful = eval("app.jvm.compile")
+ assert(firstRunSuccessful.isSuccess)
- os.write(workspacePath / "app" / "src" / "bar.scala", "object bar { println(foo) }")
- val firstRunSuccessful = eval("app.jvm.compile")
- assert(firstRunSuccessful.isSuccess)
+ val classes = workspacePath / "out" / "app" / "jvm" / "compile.dest" / "classes"
+ val firstRun = os.list(classes).map(_.last)
- val classes = workspacePath / "out" / "app" / "jvm" / "compile.dest" / "classes"
- val firstRun = os.list(classes).map(_.last)
+ os.remove(workspacePath / "app" / "src" / "foo.scala")
- os.remove(workspacePath / "app" / "src" / "foo.scala")
+ val secondRunSuccessful = eval("app.jvm.compile")
+ assert(!secondRunSuccessful.isSuccess)
- val secondRunSuccessful = eval("app.jvm.compile")
- assert(!secondRunSuccessful.isSuccess)
+ val secondRun = os.list(classes).map(_.last)
- val secondRun = os.list(classes).map(_.last)
-
- assert(firstRun == Seq(
- "bar$.class",
- "bar.class",
- "bar.tasty",
- "foo$.class",
- "foo.class",
- "foo.tasty"
- ))
- assert(secondRun == Seq.empty)
+ assert(firstRun == Seq(
+ "bar$.class",
+ "bar.class",
+ "bar.tasty",
+ "foo$.class",
+ "foo.class",
+ "foo.tasty"
+ ))
+ assert(secondRun == Seq.empty)
}
- test("nir files are deleted together with companion class files") {
- initWorkspace()
+ test("nir files are deleted together with companion class files") - integrationTest { tester =>
+ import tester._
assert(eval("app.native.compile").isSuccess)
val classes = workspacePath / "out" / "app" / "native" / "compile.dest" / "classes"
@@ -69,21 +70,22 @@ object AuxiliaryClassFilesTests extends IntegrationTestSuite {
assert(secondRun == Seq.empty)
}
- test("sjsir files are deleted together with companion class files") {
- initWorkspace()
- assert(eval("app.js.compile").isSuccess)
+ test("sjsir files are deleted together with companion class files") - integrationTest {
+ tester =>
+ import tester._
+ assert(eval("app.js.compile").isSuccess)
- val classes = workspacePath / "out" / "app" / "js" / "compile.dest" / "classes"
- val firstRun = os.list(classes).map(_.last)
+ val classes = workspacePath / "out" / "app" / "js" / "compile.dest" / "classes"
+ val firstRun = os.list(classes).map(_.last)
- os.remove(workspacePath / "app" / "src" / "foo.scala")
+ os.remove(workspacePath / "app" / "src" / "foo.scala")
- assert(eval("app.js.compile").isSuccess)
+ assert(eval("app.js.compile").isSuccess)
- val secondRun = os.list(classes).map(_.last)
+ val secondRun = os.list(classes).map(_.last)
- assert(firstRun == Seq("foo$.class", "foo$.sjsir", "foo.class", "foo.tasty"))
- assert(secondRun == Seq.empty)
+ assert(firstRun == Seq("foo$.class", "foo$.sjsir", "foo.class", "foo.tasty"))
+ assert(secondRun == Seq.empty)
}
}
}
diff --git a/integration/feature/docannotations/src/DocAnnotationsTests.scala b/integration/feature/docannotations/src/DocAnnotationsTests.scala
index 8c4948e75be..b23fdeb9b36 100644
--- a/integration/feature/docannotations/src/DocAnnotationsTests.scala
+++ b/integration/feature/docannotations/src/DocAnnotationsTests.scala
@@ -1,10 +1,10 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object DocAnnotationsTests extends IntegrationTestSuite {
+object DocAnnotationsTests extends UtestIntegrationTestSuite {
def globMatches(glob: String, input: String): Boolean = {
StringContext
.glob(
@@ -16,8 +16,8 @@ object DocAnnotationsTests extends IntegrationTestSuite {
}
val tests: Tests = Tests {
- initWorkspace()
- test("test") - {
+ test("test") - integrationTest { tester =>
+ import tester._
val res = eval(("inspect", "core.test.ivyDeps"))
assert(res.isSuccess == true)
diff --git a/integration/feature/hygiene/src/HygieneTests.scala b/integration/feature/hygiene/src/HygieneTests.scala
index f805400b1ec..c6094f5f421 100644
--- a/integration/feature/hygiene/src/HygieneTests.scala
+++ b/integration/feature/hygiene/src/HygieneTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object HygieneTests extends IntegrationTestSuite {
+object HygieneTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test {
+ test - integrationTest { tester =>
+ import tester._
val res = eval("scala.foo")
assert(res.isSuccess == true)
val output = out("scala.foo").text
diff --git a/integration/feature/import-ivy-worker-invalidation/src/ImportIvyWorkerInvalidation.scala b/integration/feature/import-ivy-worker-invalidation/src/ImportIvyWorkerInvalidation.scala
index 999015576c9..41c1ec01022 100644
--- a/integration/feature/import-ivy-worker-invalidation/src/ImportIvyWorkerInvalidation.scala
+++ b/integration/feature/import-ivy-worker-invalidation/src/ImportIvyWorkerInvalidation.scala
@@ -1,14 +1,14 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object ImportIvyWorkerInvalidation extends IntegrationTestSuite {
+object ImportIvyWorkerInvalidation extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- test {
- initWorkspace()
+ test - integrationTest { tester =>
+ import tester._
assert(eval("app.compile").isSuccess)
modifyFile(
workspacePath / "build.mill",
diff --git a/integration/feature/init/src/MillInitTests.scala b/integration/feature/init/src/MillInitTests.scala
index c7558d05340..7305917fe21 100644
--- a/integration/feature/init/src/MillInitTests.scala
+++ b/integration/feature/init/src/MillInitTests.scala
@@ -1,13 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object MillInitTests extends IntegrationTestSuite {
+object MillInitTests extends UtestIntegrationTestSuite {
def tests: Tests = Tests {
- test("Mill init works") {
- initWorkspace()
+ test("Mill init works") - integrationTest { tester =>
+ import tester._
eval(("init", "com-lihaoyi/mill-scala-hello.g8", "--name=example")).isSuccess ==> true
val projFile = workspacePath / "example" / "build.sc"
assert(os.exists(projFile))
diff --git a/integration/feature/large-project/src/LargeProjectTests.scala b/integration/feature/large-project/src/LargeProjectTests.scala
index 7bc1585af7b..ad3bba0a3e1 100644
--- a/integration/feature/large-project/src/LargeProjectTests.scala
+++ b/integration/feature/large-project/src/LargeProjectTests.scala
@@ -1,13 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object LargeProjectTests extends IntegrationTestSuite {
+object LargeProjectTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
- test("test") - {
+ test("test") - integrationTest { tester =>
+ import tester._
assert(eval("foo.common.one.compile").isSuccess)
}
diff --git a/integration/feature/mill-jvm-opts/src/MillJvmOptsTests.scala b/integration/feature/mill-jvm-opts/src/MillJvmOptsTests.scala
index b3379e10eb4..4391a7d1322 100644
--- a/integration/feature/mill-jvm-opts/src/MillJvmOptsTests.scala
+++ b/integration/feature/mill-jvm-opts/src/MillJvmOptsTests.scala
@@ -1,13 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object MillJvmOptsTests extends IntegrationTestSuite {
+object MillJvmOptsTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
- test("JVM options from file .mill-jvm-opts are properly read") {
+ test("JVM options from file .mill-jvm-opts are properly read") - integrationTest { tester =>
+ import tester._
assert(eval("checkJvmOpts").isSuccess)
}
}
diff --git a/integration/feature/non-identifier-import/src/NonIdentifierImport.scala b/integration/feature/non-identifier-import/src/NonIdentifierImport.scala
index 29fd1117160..daec95905ab 100644
--- a/integration/feature/non-identifier-import/src/NonIdentifierImport.scala
+++ b/integration/feature/non-identifier-import/src/NonIdentifierImport.scala
@@ -1,13 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object NonIdentifierImport extends IntegrationTestSuite {
+object NonIdentifierImport extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
- test("test") - {
+ test("test") - integrationTest { tester =>
+ import tester._
assert(eval("foo-bar-module.compile").isSuccess)
}
}
diff --git a/integration/feature/plugin-classpath/src/MillPluginClasspathTest.scala b/integration/feature/plugin-classpath/src/MillPluginClasspathTest.scala
index c7062ff0a35..e6589c451a3 100644
--- a/integration/feature/plugin-classpath/src/MillPluginClasspathTest.scala
+++ b/integration/feature/plugin-classpath/src/MillPluginClasspathTest.scala
@@ -1,11 +1,10 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object MillPluginClasspathTest extends IntegrationTestSuite {
- initWorkspace()
+object MillPluginClasspathTest extends UtestIntegrationTestSuite {
val embeddedModules: Seq[(String, String)] = Seq(
("com.lihaoyi", "mill-main-client"),
@@ -31,37 +30,44 @@ object MillPluginClasspathTest extends IntegrationTestSuite {
)
val tests: Tests = Tests {
- test("exclusions") - {
- val res1 = eval(("--meta-level", "1", "resolveDepsExclusions"))
- assert(res1.isSuccess)
- val exclusions = out("mill-build.resolveDepsExclusions").value[Seq[(String, String)]]
- val expectedExclusions = embeddedModules
+ test("exclusions") - integrationTest { tester =>
+ import tester._
+ retry(3) {
+ val res1 = eval(("--meta-level", "1", "resolveDepsExclusions"))
+ assert(res1.isSuccess)
- val diff = expectedExclusions.toSet.diff(exclusions.toSet)
- assert(diff.isEmpty)
+ val exclusions = out("mill-build.resolveDepsExclusions").value[Seq[(String, String)]]
+ val expectedExclusions = embeddedModules
+ val diff = expectedExclusions.toSet.diff(exclusions.toSet)
+ assert(diff.isEmpty)
+ }
}
- test("runClasspath") - {
- // We expect Mill core transitive dependencies to be filtered out
- val res1 = eval(("--meta-level", "1", "runClasspath"))
- assert(res1.isSuccess)
+ test("runClasspath") - integrationTest { tester =>
+ import tester._
+ retry(3) {
+ // We expect Mill core transitive dependencies to be filtered out
+ val res1 = eval(("--meta-level", "1", "runClasspath"))
+ assert(res1.isSuccess)
- val runClasspath = out("mill-build.runClasspath").value[Seq[String]]
+ val runClasspath = out("mill-build.runClasspath").value[Seq[String]]
- val unexpectedArtifacts = embeddedModules.map {
- case (o, n) => s"${o.replaceAll("[.]", "/")}/${n}"
- }
+ val unexpectedArtifacts = embeddedModules.map {
+ case (o, n) => s"${o.replaceAll("[.]", "/")}/${n}"
+ }
- val unexpected = unexpectedArtifacts.flatMap { a =>
- runClasspath.find(p => p.toString.contains(a)).map((a, _))
- }.toMap
- assert(unexpected.isEmpty)
+ val unexpected = unexpectedArtifacts.flatMap { a =>
+ runClasspath.find(p => p.toString.contains(a)).map((a, _))
+ }.toMap
+ assert(unexpected.isEmpty)
- val expected = Seq("com/disneystreaming/smithy4s/smithy4s-mill-codegen-plugin_mill0.11_2.13")
- assert(expected.forall(a =>
- runClasspath.exists(p => p.toString().replace('\\', '/').contains(a))
- ))
+ val expected =
+ Seq("com/disneystreaming/smithy4s/smithy4s-mill-codegen-plugin_mill0.11_2.13")
+ assert(expected.forall(a =>
+ runClasspath.exists(p => p.toString().replace('\\', '/').contains(a))
+ ))
+ }
}
}
diff --git a/integration/feature/private-methods/src/PrivateMethodsTests.scala b/integration/feature/private-methods/src/PrivateMethodsTests.scala
index 122e444bfed..51e1ff35374 100644
--- a/integration/feature/private-methods/src/PrivateMethodsTests.scala
+++ b/integration/feature/private-methods/src/PrivateMethodsTests.scala
@@ -1,13 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object PrivateMethodsTests extends IntegrationTestSuite {
+object PrivateMethodsTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
- test("simple") {
+ test("simple") - integrationTest { tester =>
+ import tester._
// Simple public target depending on private target works
val pub = eval(("show", "pub"))
assert(pub.out == "\"priv\"")
diff --git a/integration/feature/repo-config-via-import/src/ImportRepoTests.scala b/integration/feature/repo-config-via-import/src/ImportRepoTests.scala
index 9a3d233a26c..99b89760b29 100644
--- a/integration/feature/repo-config-via-import/src/ImportRepoTests.scala
+++ b/integration/feature/repo-config-via-import/src/ImportRepoTests.scala
@@ -1,13 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object ImportRepoTests extends IntegrationTestSuite {
+object ImportRepoTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
- test("test") - {
+ test("test") - integrationTest { tester =>
+ import tester._
// Make sure, we propery parse a line:
// ```
// import $repo.`file:///tmp/testrepo`
diff --git a/integration/feature/scoverage/src/ScoverageTests.scala b/integration/feature/scoverage/src/ScoverageTests.scala
index 8b2497e0414..75c78521f9c 100644
--- a/integration/feature/scoverage/src/ScoverageTests.scala
+++ b/integration/feature/scoverage/src/ScoverageTests.scala
@@ -1,13 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object ScoverageTests extends IntegrationTestSuite {
+object ScoverageTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
- test("test") - {
+ test("test") - integrationTest { tester =>
+ import tester._
assert(eval("__.compile").isSuccess)
assert(eval("core[2.13.11].scoverage.xmlReport").isSuccess)
}
diff --git a/integration/feature/subprocess-stdout/src/SubprocessStdoutTests.scala b/integration/feature/subprocess-stdout/src/SubprocessStdoutTests.scala
index cbe745ef2b2..bfdb7219ef4 100644
--- a/integration/feature/subprocess-stdout/src/SubprocessStdoutTests.scala
+++ b/integration/feature/subprocess-stdout/src/SubprocessStdoutTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object SubprocessStdoutTests extends IntegrationTestSuite {
+object SubprocessStdoutTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test {
+ test - integrationTest { tester =>
+ import tester._
val res1 = eval("inheritInterleaved", mergeErrIntoOut = true).out
// Make sure that when a lot of printed/inherited stdout/stderr is printed
// in quick succession, the output ordering is preserved and it doesn't get
@@ -62,7 +61,7 @@ object SubprocessStdoutTests extends IntegrationTestSuite {
// up in the console somewhere and not disappear
//
val res2 = eval("inheritRaw", mergeErrIntoOut = true).out
- if (!clientServerMode) {
+ if (!tester.clientServerMode) {
// For `fork` tests, which represent `-i`/`--interactive`/`--no-server`, the output should
// be properly ordered since it all comes directly from the stdout/stderr of the same process
assert(
diff --git a/integration/ide/bloop/src/BloopTests.scala b/integration/ide/bloop/src/BloopTests.scala
index fe4e7afb5b6..6b342f93453 100644
--- a/integration/ide/bloop/src/BloopTests.scala
+++ b/integration/ide/bloop/src/BloopTests.scala
@@ -1,28 +1,34 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object BloopTests extends IntegrationTestSuite {
- initWorkspace()
-
- val installResult: Boolean = eval("mill.contrib.bloop.Bloop/install").isSuccess
+object BloopTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
test("test") - {
- assert(installResult)
- test("root module bloop config should be created") {
+ test("root module bloop config should be created") - integrationTest { tester =>
+ import tester._
+ val installResult: Boolean = eval("mill.contrib.bloop.Bloop/install").isSuccess
+ assert(installResult)
assert(os.exists(workspacePath / ".bloop" / "root-module.json"))
}
- val millBuildJsonFile = workspacePath / ".bloop" / "mill-build-.json"
- test("mill-build module bloop config should be created") {
+ test("mill-build module bloop config should be created") - integrationTest { tester =>
+ import tester._
+ val installResult: Boolean = eval("mill.contrib.bloop.Bloop/install").isSuccess
+ val millBuildJsonFile = workspacePath / ".bloop" / "mill-build-.json"
+ assert(installResult)
assert(os.exists(millBuildJsonFile))
}
- val config = ujson.read(os.read.stream(millBuildJsonFile))
- test("mill-build config should contain build.mill source") {
+ test("mill-build config should contain build.mill source") - integrationTest { tester =>
+ import tester._
+ val millBuildJsonFile = workspacePath / ".bloop" / "mill-build-.json"
+ val installResult: Boolean = eval("mill.contrib.bloop.Bloop/install").isSuccess
+ val config = ujson.read(os.read.stream(millBuildJsonFile))
+ assert(installResult)
assert(config("project")("sources").arr.exists(path =>
os.Path(path.str).last == "build.mill"
))
diff --git a/integration/ide/bsp-install/src/BspInstallDebugTests.scala b/integration/ide/bsp-install/src/BspInstallDebugTests.scala
index 543c2f6929d..2294dab3571 100644
--- a/integration/ide/bsp-install/src/BspInstallDebugTests.scala
+++ b/integration/ide/bsp-install/src/BspInstallDebugTests.scala
@@ -1,18 +1,18 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import mill.bsp.Constants
import utest._
-object BspInstallDebugTests extends IntegrationTestSuite {
+object BspInstallDebugTests extends UtestIntegrationTestSuite {
val bsp4jVersion: String = sys.props.getOrElse("BSP4J_VERSION", ???)
// we purposely enable debugging in this simulated test env
override val debugLog: Boolean = true
def tests: Tests = Tests {
- test("BSP install forwards --debug option to server") {
- initWorkspace()
+ test("BSP install forwards --debug option to server") - integrationTest { tester =>
+ import tester._
eval("mill.bsp.BSP/install").isSuccess ==> true
val jsonFile = workspacePath / Constants.bspDir / s"${Constants.serverName}.json"
assert(os.exists(jsonFile))
diff --git a/integration/ide/bsp-install/src/BspInstallTests.scala b/integration/ide/bsp-install/src/BspInstallTests.scala
index afeea1d53a1..40f9547da61 100644
--- a/integration/ide/bsp-install/src/BspInstallTests.scala
+++ b/integration/ide/bsp-install/src/BspInstallTests.scala
@@ -1,15 +1,15 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import mill.bsp.Constants
import utest._
-object BspInstallTests extends IntegrationTestSuite {
+object BspInstallTests extends UtestIntegrationTestSuite {
val bsp4jVersion: String = sys.props.getOrElse("BSP4J_VERSION", ???)
def tests: Tests = Tests {
- test("BSP install") {
- initWorkspace()
+ test("BSP install") - integrationTest { tester =>
+ import tester._
assert(eval("mill.bsp.BSP/install").isSuccess)
val jsonFile = workspacePath / Constants.bspDir / s"${Constants.serverName}.json"
assert(os.exists(jsonFile))
diff --git a/integration/ide/bsp-modules/src/BspModulesTests.scala b/integration/ide/bsp-modules/src/BspModulesTests.scala
index 8ffb3d10b28..cadc7e31e98 100644
--- a/integration/ide/bsp-modules/src/BspModulesTests.scala
+++ b/integration/ide/bsp-modules/src/BspModulesTests.scala
@@ -1,21 +1,21 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import mill.bsp.Constants
import utest._
-object BspModulesTests extends IntegrationTestSuite {
+object BspModulesTests extends UtestIntegrationTestSuite {
val bsp4jVersion: String = sys.props.getOrElse("BSP4J_VERSION", ???)
def tests: Tests = Tests {
test("BSP module with foreign modules") {
- test("can be installed") {
- initWorkspace()
+ test("can be installed") - integrationTest { tester =>
+ import tester._
assert(eval("mill.bsp.BSP/install").isSuccess)
os.exists(workspacePath / Constants.bspDir / s"${Constants.serverName}.json") ==> true
}
- test("ModuleUtils resolves all referenced transitive modules") {
- initWorkspace()
+ test("ModuleUtils resolves all referenced transitive modules") - integrationTest { tester =>
+ import tester._
val res = eval("validate")
assert(res.isSuccess)
val file = workspacePath / "out" / "validate.dest" / "transitive-modules.json"
diff --git a/integration/ide/gen-idea/src/GenIdeaExtendedTests.scala b/integration/ide/gen-idea/src/GenIdeaExtendedTests.scala
index f60401bd313..ec4d78de0b3 100644
--- a/integration/ide/gen-idea/src/GenIdeaExtendedTests.scala
+++ b/integration/ide/gen-idea/src/GenIdeaExtendedTests.scala
@@ -1,18 +1,18 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
import scala.util.Try
import os.Path
-object GenIdeaExtendedTests extends IntegrationTestSuite {
+object GenIdeaExtendedTests extends UtestIntegrationTestSuite {
override def workspaceSourcePath: Path = super.workspaceSourcePath / "extended"
def tests: Tests = Tests {
- test("genIdeaTests") {
- initWorkspace()
+ test("genIdeaTests") - integrationTest { tester =>
+ import tester._
val expectedBase = workspacePath / "idea"
val resources = os.walk(expectedBase).filter(os.isFile).map(_.subRelativeTo(expectedBase))
diff --git a/integration/ide/gen-idea/src/GenIdeaTests.scala b/integration/ide/gen-idea/src/GenIdeaTests.scala
index 913b3903995..fa128c045ad 100644
--- a/integration/ide/gen-idea/src/GenIdeaTests.scala
+++ b/integration/ide/gen-idea/src/GenIdeaTests.scala
@@ -3,16 +3,16 @@ package mill.integration
import utest.{Tests, assert, _}
import scala.util.Try
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import GenIdeaUtils._
import os.Path
-object GenIdeaTests extends IntegrationTestSuite {
+object GenIdeaTests extends UtestIntegrationTestSuite {
override def workspaceSourcePath: Path = super.workspaceSourcePath / "hello-idea"
def tests: Tests = Tests {
- test("helper assertPartialContentMatches works") {
+ test("helper assertPartialContentMatches works") - integrationTest { tester =>
val testContent =
s"""line 1
|line 2
@@ -51,8 +51,8 @@ object GenIdeaTests extends IntegrationTestSuite {
()
}
- test("genIdeaTests") {
- initWorkspace()
+ test("genIdeaTests") - integrationTest { tester =>
+ import tester._
val expectedBase = workspacePath / "idea"
val resources = os.walk(expectedBase).filter(os.isFile).map(_.subRelativeTo(expectedBase))
diff --git a/integration/invalidation/codesig-hello/src/CodeSigHelloTests.scala b/integration/invalidation/codesig-hello/src/CodeSigHelloTests.scala
index 25066443a7d..38ff50c4a79 100644
--- a/integration/invalidation/codesig-hello/src/CodeSigHelloTests.scala
+++ b/integration/invalidation/codesig-hello/src/CodeSigHelloTests.scala
@@ -1,13 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object CodeSigHelloTests extends IntegrationTestSuite {
+object CodeSigHelloTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
- test("simple") {
+ test("simple") - integrationTest { tester =>
+ import tester._
// Make sure the simplest case where we have a single target calling a single helper
// method is properly invalidated when either the target body, or the helper method's body
// is changed, or something changed in the constructor
diff --git a/integration/invalidation/codesig-nested/src/CodeSigNestedTests.scala b/integration/invalidation/codesig-nested/src/CodeSigNestedTests.scala
index 04a72f94e7b..3e973af3cb8 100644
--- a/integration/invalidation/codesig-nested/src/CodeSigNestedTests.scala
+++ b/integration/invalidation/codesig-nested/src/CodeSigNestedTests.scala
@@ -1,14 +1,13 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object CodeSigNestedTests extends IntegrationTestSuite {
+object CodeSigNestedTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
-
- test("nested") {
+ test("nested") - integrationTest { tester =>
+ import tester._
// Make sure the code-change invalidation works in more complex cases: multi-step
// target graphs, targets inside module objects, targets inside module traits
@@ -190,7 +189,8 @@ object CodeSigNestedTests extends IntegrationTestSuite {
assert(addedNewlinesInsideCurlies.out == "")
}
- test("trait") {
+ test("trait") - integrationTest { tester =>
+ import tester._
val initial = eval("traitOuter.traitInner.inner")
assert(
initial.out.linesIterator.toSet == Set(
diff --git a/integration/invalidation/codesig-scalamodule/src/CodeSigScalaModuleTests.scala b/integration/invalidation/codesig-scalamodule/src/CodeSigScalaModuleTests.scala
index a14ef8d9603..05e8c68a3dd 100644
--- a/integration/invalidation/codesig-scalamodule/src/CodeSigScalaModuleTests.scala
+++ b/integration/invalidation/codesig-scalamodule/src/CodeSigScalaModuleTests.scala
@@ -1,16 +1,16 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
-object CodeSigScalaModuleTests extends IntegrationTestSuite {
+object CodeSigScalaModuleTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
def filterLines(out: String) = {
out.linesIterator.filter(!_.contains("[info]")).toSet
}
- initWorkspace()
- test("single") {
+ test("single") - integrationTest { tester =>
+ import tester._
// Tests for fine-grained method-based invalidation within a single ScalaModule
// Check normal behavior for initial run and subsequent fully-cached run
@@ -120,7 +120,8 @@ object CodeSigScalaModuleTests extends IntegrationTestSuite {
)
}
- test("multiple") {
+ test("multiple") - integrationTest { tester =>
+ import tester._
// Tests for fine-grained method-based invalidation between multiple ScalaModules,
// some related and some not
diff --git a/integration/invalidation/invalidation/src/ScriptsInvalidationTests.scala b/integration/invalidation/invalidation/src/ScriptsInvalidationTests.scala
index ee3d42890d0..895ec42b096 100644
--- a/integration/invalidation/invalidation/src/ScriptsInvalidationTests.scala
+++ b/integration/invalidation/invalidation/src/ScriptsInvalidationTests.scala
@@ -1,118 +1,108 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.{UtestIntegrationTestSuite, IntegrationTester}
import utest._
-object ScriptsInvalidationTests extends IntegrationTestSuite {
+object ScriptsInvalidationTests extends UtestIntegrationTestSuite {
- def runTask(task: String): Set[String] = {
- val res = eval(task)
+ def runTask(tester: IntegrationTester, task: String): Set[String] = {
+ val res = tester.eval(task)
assert(res.isSuccess)
res.out.linesIterator.map(_.trim).toSet
}
val tests: Tests = Tests {
- test("should not invalidate tasks in different untouched sc files") {
- test("first run") {
- initWorkspace()
-
- val result = runTask("task")
+ test("should not invalidate tasks in different untouched sc files") - integrationTest {
+ tester =>
+ import tester._
+ // first run
+ val result = runTask(tester, "task")
val expected = Set("a", "d", "b", "c")
assert(result == expected)
- }
- test("second run modifying script") {
+ // second run modifying script
modifyFile(
workspacePath / "build.mill",
_.replace("""println("task")""", """System.out.println("task2")""")
)
- val stdout = runTask("task")
+ val stdout = runTask(tester, "task")
assert(stdout.isEmpty)
- }
}
- test("should invalidate tasks if leaf file is changed") {
- test("first run") {
- initWorkspace()
- val result = runTask("task")
- val expected = Set("a", "d", "b", "c")
+ test("should invalidate tasks if leaf file is changed") - integrationTest { tester =>
+ import tester._
+ // first run
- assert(result == expected)
- }
+ val result = runTask(tester, "task")
+ val expected = Set("a", "d", "b", "c")
- test("second run modifying script") {
- modifyFile(
- workspacePath / "b" / "inputD.mill",
- _.replace("""println("d")""", """System.out.println("d2")""")
- )
+ assert(result == expected)
- val result = runTask("task")
- val expected = Set("d2", "b")
+ // second run modifying script
+ modifyFile(
+ workspacePath / "b" / "inputD.mill",
+ _.replace("""println("d")""", """System.out.println("d2")""")
+ )
- assert(result == expected)
- }
- }
- test("should handle submodules in scripts") {
- test("first run") {
- initWorkspace()
+ val result2 = runTask(tester, "task")
+ val expected2 = Set("d2", "b")
- val result = runTask("module.task")
- val expected = Set("a", "d", "b", "c", "task")
+ assert(result2 == expected2)
- assert(result == expected)
- }
+ }
+ test("should handle submodules in scripts") - integrationTest { tester =>
+ import tester._
+ // first run
+ val result = runTask(tester, "module.task")
+ val expected = Set("a", "d", "b", "c", "task")
- test("second run modifying script") {
- modifyFile(
- workspacePath / "build.mill",
- _.replace("""println("task")""", """System.out.println("task2")""")
- )
+ assert(result == expected)
- val result = runTask("module.task")
- val expected = Set("task2")
+ // second run modifying script
+ modifyFile(
+ workspacePath / "build.mill",
+ _.replace("""println("task")""", """System.out.println("task2")""")
+ )
- assert(result == expected)
- }
- }
- test("should handle ammonite ^ imports") {
- test("first run") {
- initWorkspace()
+ val result2 = runTask(tester, "module.task")
+ val expected2 = Set("task2")
- val result = runTask("taskE")
+ assert(result2 == expected2)
+ }
+ test("should handle ammonite ^ imports") - integrationTest { tester =>
+ import tester._
+ retry(3) {
+ // first run
+ val result = runTask(tester, "taskE")
val expected = Set("a", "e", "taskE")
assert(result == expected)
- }
- test("second run modifying script") {
+ // second run modifying script
modifyFile(
workspacePath / "build.mill",
_.replace("""println("taskE")""", """System.out.println("taskE2")""")
)
- val result = runTask("taskE")
- val expected = Set("taskE2")
+ val result2 = runTask(tester, "taskE")
+ val expected2 = Set("taskE2")
- assert(result == expected)
+ assert(result2 == expected2)
}
}
- test("should handle ammonite paths with symbols") {
- initWorkspace()
-
- val result = runTask("taskSymbols")
+ test("should handle ammonite paths with symbols") - integrationTest { tester =>
+ val result = runTask(tester, "taskSymbols")
val expected = Set("taskSymbols")
assert(result == expected)
}
- test("should handle ammonite files with symbols") {
- initWorkspace()
-
- val result = runTask("taskSymbolsInFile")
+ test("should handle ammonite files with symbols") - integrationTest { tester =>
+ val result = runTask(tester, "taskSymbolsInFile")
val expected = Set("taskSymbolsInFile")
assert(result == expected)
diff --git a/integration/invalidation/multi-level-editing/src/MultiLevelBuildTests.scala b/integration/invalidation/multi-level-editing/src/MultiLevelBuildTests.scala
index 53c3628e0b3..954223c7068 100644
--- a/integration/invalidation/multi-level-editing/src/MultiLevelBuildTests.scala
+++ b/integration/invalidation/multi-level-editing/src/MultiLevelBuildTests.scala
@@ -1,6 +1,6 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.{UtestIntegrationTestSuite, IntegrationTester}
import mill.main.client.OutFiles._
import mill.runner.RunnerState
@@ -13,45 +13,44 @@ import scala.util.matching.Regex
// that the proper messages are reported, proper build classloaders are
// re-used or invalidated, and the proper files end up getting watched
// in all cases.
-object MultiLevelBuildTests extends IntegrationTestSuite {
+object MultiLevelBuildTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
- def runAssertSuccess(expected: String) = {
- val res = eval("foo.run")
+ def runAssertSuccess(tester: IntegrationTester, expected: String) = {
+ val res = tester.eval("foo.run")
assert(res.isSuccess == true)
assert(res.out.contains(expected))
}
- val fooPaths = Seq(
- workspacePath / "foo" / "compile-resources",
- workspacePath / "foo" / "resources",
- workspacePath / "foo" / "src"
+ def fooPaths(tester: IntegrationTester) = Seq(
+ tester.workspacePath / "foo" / "compile-resources",
+ tester.workspacePath / "foo" / "resources",
+ tester.workspacePath / "foo" / "src"
)
- val buildPaths = Seq(
- workspacePath / "build.mill",
- workspacePath / "mill-build" / "compile-resources",
- workspacePath / "mill-build" / "resources",
- workspacePath / "mill-build" / "src"
+ def buildPaths(tester: IntegrationTester) = Seq(
+ tester.workspacePath / "build.mill",
+ tester.workspacePath / "mill-build" / "compile-resources",
+ tester.workspacePath / "mill-build" / "resources",
+ tester.workspacePath / "mill-build" / "src"
)
- val buildPaths2 = Seq(
- workspacePath / "mill-build" / "build.mill",
- workspacePath / "mill-build" / "mill-build" / "compile-resources",
- workspacePath / "mill-build" / "mill-build" / "resources",
- workspacePath / "mill-build" / "mill-build" / "src"
+ def buildPaths2(tester: IntegrationTester) = Seq(
+ tester.workspacePath / "mill-build" / "build.mill",
+ tester.workspacePath / "mill-build" / "mill-build" / "compile-resources",
+ tester.workspacePath / "mill-build" / "mill-build" / "resources",
+ tester.workspacePath / "mill-build" / "mill-build" / "src"
)
- val buildPaths3 = Seq(
- workspacePath / "mill-build" / "mill-build" / "build.mill",
- workspacePath / "mill-build" / "mill-build" / "mill-build" / "compile-resources",
- workspacePath / "mill-build" / "mill-build" / "mill-build" / "resources",
- workspacePath / "mill-build" / "mill-build" / "mill-build" / "src"
+ def buildPaths3(tester: IntegrationTester) = Seq(
+ tester.workspacePath / "mill-build" / "mill-build" / "build.mill",
+ tester.workspacePath / "mill-build" / "mill-build" / "mill-build" / "compile-resources",
+ tester.workspacePath / "mill-build" / "mill-build" / "mill-build" / "resources",
+ tester.workspacePath / "mill-build" / "mill-build" / "mill-build" / "src"
)
- def loadFrames(n: Int) = {
+ def loadFrames(tester: IntegrationTester, n: Int) = {
for (depth <- Range(0, n))
yield {
val path =
- workspacePath / "out" / Seq.fill(depth)(millBuild) / millRunnerState
+ tester.workspacePath / "out" / Seq.fill(depth)(millBuild) / millRunnerState
if (os.exists(path)) upickle.default.read[RunnerState.Frame.Logged](os.read(path)) -> path
else RunnerState.Frame.Logged(Map(), Seq(), Seq(), None, Seq(), 0) -> path
}
@@ -61,12 +60,14 @@ object MultiLevelBuildTests extends IntegrationTestSuite {
* Verify that each level of the multi-level build ends upcausing the
* appropriate files to get watched
*/
- def checkWatchedFiles(expected0: Seq[os.Path]*) = {
- for ((expectedWatched0, (frame, path)) <- expected0.zip(loadFrames(expected0.length))) {
+ def checkWatchedFiles(tester: IntegrationTester, expected0: Seq[os.Path]*) = {
+ for (
+ (expectedWatched0, (frame, path)) <- expected0.zip(loadFrames(tester, expected0.length))
+ ) {
val frameWatched = frame
.evalWatched
.map(_.path)
- .filter(_.startsWith(workspacePath))
+ .filter(_.startsWith(tester.workspacePath))
.filter(!_.segments.contains("mill-launcher"))
.sorted
@@ -75,14 +76,14 @@ object MultiLevelBuildTests extends IntegrationTestSuite {
}
}
- def evalCheckErr(expectedSnippets: String*) = {
+ def evalCheckErr(tester: IntegrationTester, expectedSnippets: String*) = {
// Wipe out stale state files to make sure they don't get picked up when
// Mill aborts early and fails to generate a new one
- os.walk(workspacePath / "out").filter(_.last == "mill-runner-state.json").foreach(
+ os.walk(tester.workspacePath / "out").filter(_.last == "mill-runner-state.json").foreach(
os.remove(_)
)
- val res = eval("foo.run")
+ val res = tester.eval("foo.run")
assert(res.isSuccess == false)
// Prepend a "\n" to allow callsites to use "\n" to test for start of
// line, even though the first line doesn't have a "\n" at the start
@@ -100,9 +101,12 @@ object MultiLevelBuildTests extends IntegrationTestSuite {
* the previous classloader was re-used, `null` means there is no
* classloader at that level
*/
- def checkChangedClassloaders(expectedChanged0: java.lang.Boolean*) = {
+ def checkChangedClassloaders(
+ tester: IntegrationTester,
+ expectedChanged0: java.lang.Boolean*
+ ) = {
val currentClassLoaderIds =
- for ((frame, path) <- loadFrames(expectedChanged0.length))
+ for ((frame, path) <- loadFrames(tester, expectedChanged0.length))
yield frame.classLoaderIdentity
val changed = currentClassLoaderIds
@@ -124,197 +128,273 @@ object MultiLevelBuildTests extends IntegrationTestSuite {
savedClassLoaderIds = currentClassLoaderIds
}
- test("validEdits") {
- runAssertSuccess("hello
world
0.8.2
!")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
+ test("validEdits") - integrationTest { tester =>
+ import tester._
+ runAssertSuccess(tester, "hello
world
0.8.2
!")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
// First run all classloaders are new, except level 0 running user code
// which doesn't need generate a classloader which never changes
- checkChangedClassloaders(null, true, true, true)
+ checkChangedClassloaders(tester, null, true, true, true)
modifyFile(workspacePath / "foo" / "src" / "Example.scala", _.replace("!", "?"))
- runAssertSuccess("hello
world
0.8.2
?")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
+ runAssertSuccess(tester, "hello
world
0.8.2
?")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
// Second run with no build changes, all classloaders are unchanged
- checkChangedClassloaders(null, false, false, false)
+ checkChangedClassloaders(tester, null, false, false, false)
modifyFile(workspacePath / "build.mill", _.replace("hello", "HELLO"))
- runAssertSuccess("HELLO
world
0.8.2
?")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, false, false)
+ runAssertSuccess(tester, "HELLO
world
0.8.2
?")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, false, false)
modifyFile(
workspacePath / "mill-build" / "build.mill",
_.replace("def scalatagsVersion = ", "def scalatagsVersion = \"changed-\" + ")
)
- runAssertSuccess("HELLO
world
changed-0.8.2
?")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, true, false)
+ runAssertSuccess(tester, "HELLO
world
changed-0.8.2
?")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, true, false)
modifyFile(
workspacePath / "mill-build" / "mill-build" / "build.mill",
_.replace("0.8.2", "0.12.0")
)
- runAssertSuccess("HELLO
world
changed-0.12.0
?")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, true, true)
+ runAssertSuccess(tester, "HELLO
world
changed-0.12.0
?")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, true, true)
modifyFile(
workspacePath / "mill-build" / "mill-build" / "build.mill",
_.replace("0.12.0", "0.8.2")
)
- runAssertSuccess("HELLO
world
changed-0.8.2
?")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, true, true)
+ runAssertSuccess(tester, "HELLO
world
changed-0.8.2
?")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, true, true)
modifyFile(
workspacePath / "mill-build" / "build.mill",
_.replace("def scalatagsVersion = \"changed-\" + ", "def scalatagsVersion = ")
)
- runAssertSuccess("HELLO
world
0.8.2
?")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, true, false)
+ runAssertSuccess(tester, "HELLO
world
0.8.2
?")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, true, false)
modifyFile(workspacePath / "build.mill", _.replace("HELLO", "hello"))
- runAssertSuccess("hello
world
0.8.2
?")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, false, false)
+ runAssertSuccess(tester, "hello
world
0.8.2
?")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, false, false)
modifyFile(workspacePath / "foo" / "src" / "Example.scala", _.replace("?", "!"))
- runAssertSuccess("hello
world
0.8.2
!")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, false, false, false)
+ runAssertSuccess(tester, "hello
world
0.8.2
!")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, false, false, false)
}
- test("parseErrorEdits") {
+ test("parseErrorEdits") - integrationTest { tester =>
+ import tester._
def causeParseError(p: os.Path) =
modifyFile(p, _.replace("extends", "extendx"))
def fixParseError(p: os.Path) =
modifyFile(p, _.replace("extendx", "extends"))
- runAssertSuccess("hello
world
0.8.2
!")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, true, true)
+ runAssertSuccess(tester, "hello
world
0.8.2
!")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, true, true)
causeParseError(workspacePath / "build.mill")
- evalCheckErr(
- "\n1 targets failed",
- "\ngenerateScriptSources build.mill"
- )
- checkWatchedFiles(Nil, buildPaths, Nil, Nil)
+ evalCheckErr(tester, "\n1 targets failed", "\ngenerateScriptSources build.mill")
+ checkWatchedFiles(tester, Nil, buildPaths(tester), Nil, Nil)
// When one of the meta-builds still has parse errors, all classloaders
// remain null, because none of the meta-builds can evaluate. Only once
// all of them parse successfully do we get a new set of classloaders for
// every level of the meta-build
- checkChangedClassloaders(null, null, null, null)
+ checkChangedClassloaders(tester, null, null, null, null)
fixParseError(workspacePath / "build.mill")
causeParseError(workspacePath / "mill-build" / "build.mill")
- evalCheckErr(
- "\n1 targets failed",
- "\ngenerateScriptSources mill-build/build.mill"
- )
- checkWatchedFiles(Nil, Nil, buildPaths2, Nil)
- checkChangedClassloaders(null, null, null, null)
+ evalCheckErr(tester, "\n1 targets failed", "\ngenerateScriptSources mill-build/build.mill")
+ checkWatchedFiles(tester, Nil, Nil, buildPaths2(tester), Nil)
+ checkChangedClassloaders(tester, null, null, null, null)
fixParseError(workspacePath / "mill-build" / "build.mill")
causeParseError(workspacePath / "mill-build" / "mill-build" / "build.mill")
evalCheckErr(
+ tester,
"\n1 targets failed",
"\ngenerateScriptSources mill-build/mill-build/build.mill"
)
- checkWatchedFiles(Nil, Nil, Nil, buildPaths3)
- checkChangedClassloaders(null, null, null, null)
+ checkWatchedFiles(tester, Nil, Nil, Nil, buildPaths3(tester))
+ checkChangedClassloaders(tester, null, null, null, null)
fixParseError(workspacePath / "mill-build" / "mill-build" / "build.mill")
causeParseError(workspacePath / "mill-build" / "build.mill")
- evalCheckErr(
- "\n1 targets failed",
- "\ngenerateScriptSources mill-build/build.mill"
- )
- checkWatchedFiles(Nil, Nil, buildPaths2, Nil)
- checkChangedClassloaders(null, null, null, null)
+ evalCheckErr(tester, "\n1 targets failed", "\ngenerateScriptSources mill-build/build.mill")
+ checkWatchedFiles(tester, Nil, Nil, buildPaths2(tester), Nil)
+ checkChangedClassloaders(tester, null, null, null, null)
fixParseError(workspacePath / "mill-build" / "build.mill")
causeParseError(workspacePath / "build.mill")
- evalCheckErr(
- "\n1 targets failed",
- "\ngenerateScriptSources build.mill"
- )
- checkWatchedFiles(Nil, buildPaths, Nil, Nil)
- checkChangedClassloaders(null, null, null, null)
+ evalCheckErr(tester, "\n1 targets failed", "\ngenerateScriptSources build.mill")
+ checkWatchedFiles(tester, Nil, buildPaths(tester), Nil, Nil)
+ checkChangedClassloaders(tester, null, null, null, null)
fixParseError(workspacePath / "build.mill")
- runAssertSuccess("hello
world
0.8.2
!")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, true, true)
+ runAssertSuccess(tester, "hello
world
0.8.2
!")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, true, true)
}
- test("compileErrorEdits") {
+ test("compileErrorEdits") - integrationTest { tester =>
+ import tester._
def causeCompileError(p: os.Path) =
modifyFile(p, _ + "\nimport doesnt.exist")
def fixCompileError(p: os.Path) =
modifyFile(p, _.replace("import doesnt.exist", ""))
- runAssertSuccess("hello
world
0.8.2
!")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, true, true)
+ runAssertSuccess(tester, "hello
world
0.8.2
!")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, true, true)
causeCompileError(workspacePath / "build.mill")
evalCheckErr(
+ tester,
"\n1 targets failed",
// Ensure the file path in the compile error is properly adjusted to point
// at the original source file and not the generated file
(workspacePath / "build.mill").toString,
"not found: value doesnt"
)
- checkWatchedFiles(Nil, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, null, false, false)
+ checkWatchedFiles(tester, Nil, buildPaths(tester), buildPaths2(tester), buildPaths3(tester))
+ checkChangedClassloaders(tester, null, null, false, false)
causeCompileError(workspacePath / "mill-build" / "build.mill")
evalCheckErr(
+ tester,
"\n1 targets failed",
(workspacePath / "mill-build" / "build.mill").toString,
"not found: object doesnt"
)
- checkWatchedFiles(Nil, Nil, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, null, null, false)
+ checkWatchedFiles(tester, Nil, Nil, buildPaths2(tester), buildPaths3(tester))
+ checkChangedClassloaders(tester, null, null, null, false)
causeCompileError(workspacePath / "mill-build" / "mill-build" / "build.mill")
evalCheckErr(
+ tester,
"\n1 targets failed",
(workspacePath / "mill-build" / "mill-build" / "build.mill").toString,
"not found: object doesnt"
)
- checkWatchedFiles(Nil, Nil, Nil, buildPaths3)
- checkChangedClassloaders(null, null, null, null)
+ checkWatchedFiles(tester, Nil, Nil, Nil, buildPaths3(tester))
+ checkChangedClassloaders(tester, null, null, null, null)
fixCompileError(workspacePath / "mill-build" / "mill-build" / "build.mill")
evalCheckErr(
+ tester,
"\n1 targets failed",
(workspacePath / "mill-build" / "build.mill").toString,
"not found: object doesnt"
)
- checkWatchedFiles(Nil, Nil, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, null, null, true)
+ checkWatchedFiles(tester, Nil, Nil, buildPaths2(tester), buildPaths3(tester))
+ checkChangedClassloaders(tester, null, null, null, true)
fixCompileError(workspacePath / "mill-build" / "build.mill")
evalCheckErr(
+ tester,
"\n1 targets failed",
(workspacePath / "build.mill").toString,
"not found: value doesnt"
)
- checkWatchedFiles(Nil, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, null, true, false)
+ checkWatchedFiles(tester, Nil, buildPaths(tester), buildPaths2(tester), buildPaths3(tester))
+ checkChangedClassloaders(tester, null, null, true, false)
fixCompileError(workspacePath / "build.mill")
- runAssertSuccess("hello
world
0.8.2
!")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, false, false)
+ runAssertSuccess(tester, "hello
world
0.8.2
!")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, false, false)
}
- test("runtimeErrorEdits") {
+ test("runtimeErrorEdits") - integrationTest { tester =>
+ import tester._
val runErrorSnippet = """{
|override def runClasspath = T{
| throw new Exception("boom")
@@ -327,58 +407,83 @@ object MultiLevelBuildTests extends IntegrationTestSuite {
def fixRuntimeError(p: os.Path) =
modifyFile(p, _.replaceFirst(Regex.quote(runErrorSnippet), "\\{"))
- runAssertSuccess("hello
world
0.8.2
!")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, true, true)
+ runAssertSuccess(tester, "hello
world
0.8.2
!")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, true, true)
causeRuntimeError(workspacePath / "build.mill")
- evalCheckErr(
- "\n1 targets failed",
- "foo.runClasspath java.lang.Exception: boom"
+ evalCheckErr(tester, "\n1 targets failed", "foo.runClasspath java.lang.Exception: boom")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
)
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, false, false)
+ checkChangedClassloaders(tester, null, true, false, false)
causeRuntimeError(workspacePath / "mill-build" / "build.mill")
evalCheckErr(
+ tester,
"\n1 targets failed",
"build.mill",
"runClasspath java.lang.Exception: boom"
)
- checkWatchedFiles(Nil, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, null, true, false)
+ checkWatchedFiles(tester, Nil, buildPaths(tester), buildPaths2(tester), buildPaths3(tester))
+ checkChangedClassloaders(tester, null, null, true, false)
causeRuntimeError(workspacePath / "mill-build" / "mill-build" / "build.mill")
evalCheckErr(
+ tester,
"\n1 targets failed",
"build.mill",
"runClasspath java.lang.Exception: boom"
)
- checkWatchedFiles(Nil, Nil, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, null, null, true)
+ checkWatchedFiles(tester, Nil, Nil, buildPaths2(tester), buildPaths3(tester))
+ checkChangedClassloaders(tester, null, null, null, true)
fixRuntimeError(workspacePath / "mill-build" / "mill-build" / "build.mill")
evalCheckErr(
+ tester,
"\n1 targets failed",
"build.mill",
"runClasspath java.lang.Exception: boom"
)
- checkWatchedFiles(Nil, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, null, true, true)
+ checkWatchedFiles(tester, Nil, buildPaths(tester), buildPaths2(tester), buildPaths3(tester))
+ checkChangedClassloaders(tester, null, null, true, true)
fixRuntimeError(workspacePath / "mill-build" / "build.mill")
evalCheckErr(
+ tester,
"\n1 targets failed",
"build.mill",
"foo.runClasspath java.lang.Exception: boom"
)
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, true, false)
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, true, false)
fixRuntimeError(workspacePath / "build.mill")
- runAssertSuccess("hello
world
0.8.2
!")
- checkWatchedFiles(fooPaths, buildPaths, buildPaths2, buildPaths3)
- checkChangedClassloaders(null, true, false, false)
+ runAssertSuccess(tester, "hello
world
0.8.2
!")
+ checkWatchedFiles(
+ tester,
+ fooPaths(tester),
+ buildPaths(tester),
+ buildPaths2(tester),
+ buildPaths3(tester)
+ )
+ checkChangedClassloaders(tester, null, true, false, false)
}
}
diff --git a/integration/invalidation/watch-source-input/src/WatchSourceInputTests.scala b/integration/invalidation/watch-source-input/src/WatchSourceInputTests.scala
index 6230a43a2fd..09a2205fb05 100644
--- a/integration/invalidation/watch-source-input/src/WatchSourceInputTests.scala
+++ b/integration/invalidation/watch-source-input/src/WatchSourceInputTests.scala
@@ -1,6 +1,6 @@
package mill.integration
-import mill.testkit.{IntegrationTestSuite, IntegrationTester}
+import mill.testkit.{UtestIntegrationTestSuite, IntegrationTester}
import mill.main.client.Util
import utest._
@@ -20,15 +20,13 @@ import scala.concurrent.ExecutionContext.Implicits.global
* 4. `interp.watchValue`
* 5. Implicitly watched files, like `build.mill`
*/
-object WatchSourceInputTests extends IntegrationTestSuite {
+object WatchSourceInputTests extends UtestIntegrationTestSuite {
val maxDuration = 60000
val tests: Tests = Tests {
- initWorkspace()
-
- def awaitCompletionMarker(name: String) = {
+ def awaitCompletionMarker(tester: IntegrationTester, name: String) = {
val maxTime = System.currentTimeMillis() + maxDuration
- while (!os.exists(workspacePath / "out" / name)) {
+ while (!os.exists(tester.workspacePath / "out" / name)) {
if (System.currentTimeMillis() > maxTime) {
sys.error(s"awaitCompletionMarker($name) timed out")
}
@@ -63,14 +61,14 @@ object WatchSourceInputTests extends IntegrationTestSuite {
if (show) assert(shows == expectedShows.map('"' + _ + '"'))
}
- def testWatchSource(show: Boolean) =
+ def testWatchSource(tester: IntegrationTester, show: Boolean) =
testBase(show) { (expectedOut, expectedErr, expectedShows) =>
val showArgs = if (show) Seq("show") else Nil
-
+ import tester._
val evalResult = Future { eval(("--watch", showArgs, "qux"), timeout = maxDuration) }
- awaitCompletionMarker("initialized0")
- awaitCompletionMarker("quxRan0")
+ awaitCompletionMarker(tester, "initialized0")
+ awaitCompletionMarker(tester, "quxRan0")
expectedOut.append(
"Setting up build.mill"
)
@@ -83,7 +81,7 @@ object WatchSourceInputTests extends IntegrationTestSuite {
)
os.write.over(workspacePath / "foo1.txt", "edited-foo1")
- awaitCompletionMarker("quxRan1")
+ awaitCompletionMarker(tester, "quxRan1")
expectedErr.append(
"Running qux foo contents edited-foo1 initial-foo2",
"Running qux bar contents initial-bar"
@@ -93,7 +91,7 @@ object WatchSourceInputTests extends IntegrationTestSuite {
)
os.write.over(workspacePath / "foo2.txt", "edited-foo2")
- awaitCompletionMarker("quxRan2")
+ awaitCompletionMarker(tester, "quxRan2")
expectedErr.append(
"Running qux foo contents edited-foo1 edited-foo2",
"Running qux bar contents initial-bar"
@@ -103,7 +101,7 @@ object WatchSourceInputTests extends IntegrationTestSuite {
)
os.write.over(workspacePath / "bar.txt", "edited-bar")
- awaitCompletionMarker("quxRan3")
+ awaitCompletionMarker(tester, "quxRan3")
expectedErr.append(
"Running qux foo contents edited-foo1 edited-foo2",
"Running qux bar contents edited-bar"
@@ -113,7 +111,7 @@ object WatchSourceInputTests extends IntegrationTestSuite {
)
os.write.append(workspacePath / "build.mill", "\ndef unrelated = true")
- awaitCompletionMarker("initialized1")
+ awaitCompletionMarker(tester, "initialized1")
expectedOut.append(
"Setting up build.mill"
// These targets do not re-evaluate, because the change to the build
@@ -126,7 +124,7 @@ object WatchSourceInputTests extends IntegrationTestSuite {
)
os.write.over(workspacePath / "watchValue.txt", "exit")
- awaitCompletionMarker("initialized2")
+ awaitCompletionMarker(tester, "initialized2")
expectedOut.append("Setting up build.mill")
Await.result(evalResult, Duration.apply(maxDuration, SECONDS))
@@ -135,18 +133,30 @@ object WatchSourceInputTests extends IntegrationTestSuite {
test("sources") {
// Make sure we clean up the workspace between retries
- test("noshow") - retry(3) { if (!Util.isWindows) { initWorkspace(); testWatchSource(false) } }
- test("show") - retry(3) { if (!Util.isWindows) { initWorkspace(); testWatchSource(true) } }
+ test("noshow") - retry(3) {
+ integrationTest { tester =>
+ if (!Util.isWindows) {
+ testWatchSource(tester, false)
+ }
+ }
+ }
+ test("show") - retry(3) {
+ integrationTest { tester =>
+ if (!Util.isWindows) {
+ testWatchSource(tester, true)
+ }
+ }
+ }
}
- def testWatchInput(show: Boolean) =
+ def testWatchInput(tester: IntegrationTester, show: Boolean) =
testBase(show) { (expectedOut, expectedErr, expectedShows) =>
val showArgs = if (show) Seq("show") else Nil
-
+ import tester._
val evalResult = Future { eval(("--watch", showArgs, "lol"), timeout = maxDuration) }
- awaitCompletionMarker("initialized0")
- awaitCompletionMarker("lolRan0")
+ awaitCompletionMarker(tester, "initialized0")
+ awaitCompletionMarker(tester, "lolRan0")
expectedOut.append(
"Setting up build.mill"
)
@@ -156,17 +166,17 @@ object WatchSourceInputTests extends IntegrationTestSuite {
expectedShows.append("Running lol baz contents initial-baz")
os.write.over(workspacePath / "baz.txt", "edited-baz")
- awaitCompletionMarker("lolRan1")
+ awaitCompletionMarker(tester, "lolRan1")
expectedErr.append("Running lol baz contents edited-baz")
expectedShows.append("Running lol baz contents edited-baz")
os.write.over(workspacePath / "watchValue.txt", "edited-watchValue")
- awaitCompletionMarker("initialized1")
+ awaitCompletionMarker(tester, "initialized1")
expectedOut.append("Setting up build.mill")
expectedShows.append("Running lol baz contents edited-baz")
os.write.over(workspacePath / "watchValue.txt", "exit")
- awaitCompletionMarker("initialized2")
+ awaitCompletionMarker(tester, "initialized2")
expectedOut.append("Setting up build.mill")
Await.result(evalResult, Duration.apply(maxDuration, SECONDS))
@@ -175,8 +185,20 @@ object WatchSourceInputTests extends IntegrationTestSuite {
test("input") {
// Make sure we clean up the workspace between retries
- test("noshow") - retry(3) { if (!Util.isWindows) { initWorkspace(); testWatchInput(false) } }
- test("show") - retry(3) { if (!Util.isWindows) { initWorkspace(); testWatchInput(true) } }
+ test("noshow") - retry(3) {
+ integrationTest { tester =>
+ if (!Util.isWindows) {
+ testWatchInput(tester, false)
+ }
+ }
+ }
+ test("show") - retry(3) {
+ integrationTest { tester =>
+ if (!Util.isWindows) {
+ testWatchInput(tester, true)
+ }
+ }
+ }
}
}
}
diff --git a/integration/invalidation/zinc-incremental-compilation/src/ZincIncrementalCompilationTests.scala b/integration/invalidation/zinc-incremental-compilation/src/ZincIncrementalCompilationTests.scala
index cf61225ff9f..a0f902721e2 100644
--- a/integration/invalidation/zinc-incremental-compilation/src/ZincIncrementalCompilationTests.scala
+++ b/integration/invalidation/zinc-incremental-compilation/src/ZincIncrementalCompilationTests.scala
@@ -1,15 +1,15 @@
package mill.integration
-import mill.testkit.IntegrationTestSuite
+import mill.testkit.UtestIntegrationTestSuite
import utest._
// Regress test for issue https://github.com/com-lihaoyi/mill/issues/1901
-object ZincIncrementalCompilationTests extends IntegrationTestSuite {
+object ZincIncrementalCompilationTests extends UtestIntegrationTestSuite {
val tests: Tests = Tests {
- initWorkspace()
- test("incremental compilation only compiles changed files") {
- val successful = eval("app.compile")
+ test("incremental compilation only compiles changed files") - integrationTest { tester =>
+ import tester._
+ val successful = tester.eval("app.compile")
assert(successful.isSuccess)
val appSrc = workspacePath / "app" / "src" / "main" / "scala" / "App.scala"
@@ -25,7 +25,7 @@ object ZincIncrementalCompilationTests extends IntegrationTestSuite {
println("** second run **")
os.write.append(appSrc, "\n ")
- val succ2nd = eval("app.compile")
+ val succ2nd = tester.eval("app.compile")
assert(succ2nd.isSuccess)
val appSrcInfo2 = os.stat(appSrc)
diff --git a/main/api/src/mill/api/Result.scala b/main/api/src/mill/api/Result.scala
index a06cd191c99..ad7af1e051b 100644
--- a/main/api/src/mill/api/Result.scala
+++ b/main/api/src/mill/api/Result.scala
@@ -74,8 +74,10 @@ object Result {
*/
case class Failure[T](msg: String, value: Option[T] = None) extends Failing[T] {
def map[V](f: T => V): Failure[V] = Result.Failure(msg, value.map(f(_)))
- def flatMap[V](f: T => Result[V]): Failure[V] =
+ def flatMap[V](f: T => Result[V]): Failure[V] = {
Failure(msg, value.flatMap(f(_).asSuccess.map(_.value)))
+ }
+ override def toString: String = s"Failure($msg, $value)"
}
/**
diff --git a/main/client/src/mill/main/client/CodeGenConstants.java b/main/client/src/mill/main/client/CodeGenConstants.java
index 1245cfc75ff..71136e2d1dd 100644
--- a/main/client/src/mill/main/client/CodeGenConstants.java
+++ b/main/client/src/mill/main/client/CodeGenConstants.java
@@ -21,17 +21,17 @@ public class CodeGenConstants {
/**
* The name of the root build file
*/
- final public static String[] rootBuildFileNames = {"build.mill", "build.sc"};
+ final public static String[] rootBuildFileNames = {"build.mill", "build.mill.sc", "build.sc"};
/**
* The name of any sub-folder build files
*/
- final public static String[] nestedBuildFileNames = {"package.mill", "package.sc"};
+ final public static String[] nestedBuildFileNames = {"package.mill", "package.mill.sc", "package.sc"};
/**
* The extensions used by build files
*/
- final public static String[] buildFileExtensions = {"mill", "sc"};
+ final public static String[] buildFileExtensions = {"mill", "mill.sc", "sc"};
/**
* The user-facing name for the root of the module tree.
diff --git a/main/client/test/src/mill/main/client/FileToStreamTailerTest.java b/main/client/test/src/mill/main/client/FileToStreamTailerTest.java
index bb960cafc4a..0c68b5e12fe 100644
--- a/main/client/test/src/mill/main/client/FileToStreamTailerTest.java
+++ b/main/client/test/src/mill/main/client/FileToStreamTailerTest.java
@@ -99,12 +99,12 @@ public FileToStreamTailerTest() {
final FileToStreamTailer tailer = new FileToStreamTailer(file, ps, 10);
) {
tailer.start();
- Thread.sleep(100);
+ Thread.sleep(500);
expectEquals(bas.toString(), "");
out.println("log line");
expectTrue(file.exists());
- Thread.sleep(100);
- expectEquals(bas.toString(), "log line" + System.lineSeparator());
+ Thread.sleep(500);
+ expectEquals(bas.toString().trim(), "log line");
}
}
});
diff --git a/main/server/test/src/mill/main/server/ClientServerTests.scala b/main/server/test/src/mill/main/server/ClientServerTests.scala
index d9b14286f5c..e6a0a090696 100644
--- a/main/server/test/src/mill/main/server/ClientServerTests.scala
+++ b/main/server/test/src/mill/main/server/ClientServerTests.scala
@@ -121,9 +121,9 @@ object ClientServerTests extends TestSuite {
}
def tests = Tests {
- val tester = new Tester
- test("hello") - retry(3) {
+ test("hello") - retry(3) {
+ val tester = new Tester
val res1 = tester(args = Array("world"))
assert(
@@ -163,6 +163,7 @@ object ClientServerTests extends TestSuite {
}
test("concurrency") {
+ val tester = new Tester
// Make sure concurrently running client commands results in multiple processes
// being spawned, running in different folders
import concurrent._
@@ -187,6 +188,7 @@ object ClientServerTests extends TestSuite {
}
test("clientLockReleasedOnFailure") {
+ val tester = new Tester
// When the client gets interrupted via Ctrl-C, we exit the server immediately. This
// is because Mill ends up executing arbitrary JVM code, and there is no generic way
// to interrupt such an execution. The two options are to leave the server running
@@ -212,6 +214,7 @@ object ClientServerTests extends TestSuite {
}
test("envVars") - retry(3) {
+ val tester = new Tester
// Make sure the simple "have the client start a server and
// exchange one message" workflow works from end to end.
diff --git a/main/util/src/mill/util/CoursierSupport.scala b/main/util/src/mill/util/CoursierSupport.scala
index 2fa9c7783e3..9fa405f0282 100644
--- a/main/util/src/mill/util/CoursierSupport.scala
+++ b/main/util/src/mill/util/CoursierSupport.scala
@@ -38,8 +38,12 @@ trait CoursierSupport {
)(f: () => T): T = {
val tried = Try(f())
tried match {
- case Failure(e: NoSuchFileException)
- if retryCount > 0 && e.getMessage.contains("__sha1.computed") =>
+ case Failure(e)
+ if retryCount > 0
+ && e.getMessage.contains("__sha1.computed")
+ && (e.isInstanceOf[NoSuchFileException] || e.isInstanceOf[
+ java.nio.file.AccessDeniedException
+ ]) =>
// this one is not detected by coursier itself, so we try-catch handle it
// I assume, this happens when another coursier thread already moved or rename dthe temporary file
ctx.foreach(_.log.debug(
diff --git a/mill-build/src/ExampleParser.scala b/mill-build/src/ExampleParser.scala
index 55db14aa90a..39988ee2a86 100644
--- a/mill-build/src/ExampleParser.scala
+++ b/mill-build/src/ExampleParser.scala
@@ -6,7 +6,7 @@ object ExampleParser {
val states = collection.mutable.Buffer("scala")
val chunks = collection.mutable.Buffer(collection.mutable.Buffer.empty[String])
- val rootBuildFileNames = Seq("build.sc", "build.mill")
+ val rootBuildFileNames = Seq("build.sc", "build.mill", "build.mill.sc")
val buildFile = rootBuildFileNames.map(testRepoRoot / _).find(os.exists)
for (line <- os.read.lines(buildFile.get)) {
val (newState, restOpt) = line match {
diff --git a/runner/linenumbers/src/mill/linenumbers/LineNumberPlugin.scala b/runner/linenumbers/src/mill/linenumbers/LineNumberPlugin.scala
index 591023f796c..b8f0aeee877 100644
--- a/runner/linenumbers/src/mill/linenumbers/LineNumberPlugin.scala
+++ b/runner/linenumbers/src/mill/linenumbers/LineNumberPlugin.scala
@@ -30,7 +30,7 @@ class LineNumberPlugin(val global: Global) extends Plugin {
object LineNumberPlugin {
def apply(g: Global)(unit: g.CompilationUnit): Unit = {
- if (buildFileExtensions.exists(g.currentSource.file.hasExtension(_))) {
+ if (buildFileExtensions.exists(ex => g.currentSource.file.name.endsWith(s".$ex"))) {
val str = new String(g.currentSource.content)
val lines = str.linesWithSeparators.toVector
diff --git a/runner/src/mill/runner/CodeGen.scala b/runner/src/mill/runner/CodeGen.scala
index 3e8c64c4fe5..dbe14739c82 100644
--- a/runner/src/mill/runner/CodeGen.scala
+++ b/runner/src/mill/runner/CodeGen.scala
@@ -18,18 +18,17 @@ object CodeGen {
millTopLevelProjectRoot: os.Path
): Unit = {
for (scriptSource <- scriptSources) {
- // pprint.log(scriptSource)
val scriptPath = scriptSource.path
val specialNames = (nestedBuildFileNames ++ rootBuildFileNames).toSet
val isBuildScript = specialNames(scriptPath.last)
val scriptFolderPath = scriptPath / os.up
- if (scriptFolderPath == projectRoot && scriptPath.baseName == "package") {
+ if (scriptFolderPath == projectRoot && scriptPath.last.split('.').head == "package") {
throw Result.Failure(s"Mill ${scriptPath.last} files can only be in subfolders")
}
- if (scriptFolderPath != projectRoot && scriptPath.baseName == "build") {
+ if (scriptFolderPath != projectRoot && scriptPath.last.split('.').head == "build") {
throw Result.Failure(s"Mill ${scriptPath.last} files can only be in the project root")
}
@@ -86,7 +85,7 @@ object CodeGen {
if (!isBuildScript) {
s"""$pkgLine
|$aliasImports
- |object ${backtickWrap(scriptPath.baseName)} {
+ |object ${backtickWrap(scriptPath.last.split('.').head)} {
|$markerComment
|$scriptCode
|}""".stripMargin
@@ -105,7 +104,7 @@ object CodeGen {
)
}
- os.write(dest, parts, createFolders = true)
+ os.write.over(dest, parts, createFolders = true)
}
}
diff --git a/runner/src/mill/runner/FileImportGraph.scala b/runner/src/mill/runner/FileImportGraph.scala
index 89199a69f3b..fae30b35174 100644
--- a/runner/src/mill/runner/FileImportGraph.scala
+++ b/runner/src/mill/runner/FileImportGraph.scala
@@ -51,7 +51,6 @@ object FileImportGraph {
var millImport = false
def processScript(s: os.Path, useDummy: Boolean = false): Unit = {
-
val readFileEither = scala.util.Try {
val content = if (useDummy) "" else os.read(s)
val fileName = s.relativeTo(topLevelProjectRoot).toString
@@ -67,7 +66,7 @@ object FileImportGraph {
val expectedImportSegments = expectedImportSegments0.map(backtickWrap).mkString(".")
if (
// Legacy `.sc` files have their package build be optional
- s.ext == "mill" &&
+ (s.last.endsWith(".mill") || s.last.endsWith(".mill.sc")) &&
expectedImportSegments != importSegments &&
// Root build.mill file has its `package build` be optional
!(importSegments == "" && rootBuildFileNames.contains(s.last))
@@ -137,7 +136,7 @@ object FileImportGraph {
case ImportTree(Seq(("$file", end0), rest @ _*), mapping, start, end) =>
// Only recursively explore imports from legacy `.sc` files, as new `.mill` files
// do file discovery via scanning folders containing `package.mill` files
- if (s.ext == "sc") {
+ if (s.last.endsWith(".sc") && !s.last.endsWith(".mill.sc")) {
val nextPaths = mapping.map { case (lhs, rhs) =>
nextPathFor(s, rest.map(_._1) :+ lhs)
}
@@ -167,8 +166,10 @@ object FileImportGraph {
val useDummy = rootBuildFiles.isEmpty
val foundRootBuildFileName: String = rootBuildFiles.getOrElse(rootBuildFileNames.head)
- val buildFileExtension = buildFileExtensions.find(foundRootBuildFileName.endsWith).get
- val nestedBuildFileName = nestedBuildFileNames.find(_.endsWith(buildFileExtension)).get
+ val buildFileExtension =
+ buildFileExtensions.find(ex => foundRootBuildFileName.endsWith(s".$ex")).get
+
+ val nestedBuildFileName = s"package.$buildFileExtension"
processScript(projectRoot / foundRootBuildFileName, useDummy)
val buildFiles = os
@@ -184,7 +185,7 @@ object FileImportGraph {
val adjacentScripts = (projectRoot +: buildFiles.map(_ / os.up))
.flatMap(os.list(_))
- .filter(_.ext == buildFileExtension)
+ .filter(_.last.endsWith(s".$buildFileExtension"))
(buildFiles ++ adjacentScripts).foreach(processScript(_))
diff --git a/scalalib/src/mill/scalalib/JavaModule.scala b/scalalib/src/mill/scalalib/JavaModule.scala
index 98fdc303a40..508793a2664 100644
--- a/scalalib/src/mill/scalalib/JavaModule.scala
+++ b/scalalib/src/mill/scalalib/JavaModule.scala
@@ -533,7 +533,13 @@ trait JavaModule
* Resolved dependencies based on [[transitiveIvyDeps]] and [[transitiveCompileIvyDeps]].
*/
def resolvedIvyDeps: T[Agg[PathRef]] = T {
- defaultResolver().resolveDeps(transitiveCompileIvyDeps() ++ transitiveIvyDeps())
+ def resolvedIvyDeps0() =
+ defaultResolver().resolveDeps(transitiveCompileIvyDeps() ++ transitiveIvyDeps())
+ try resolvedIvyDeps0()
+ catch {
+ case e: java.nio.file.AccessDeniedException =>
+ resolvedIvyDeps0() // this is caused by a coursier race condition on windows, just retry
+ }
}
/**
diff --git a/scalalib/src/mill/scalalib/Lib.scala b/scalalib/src/mill/scalalib/Lib.scala
index 556f138a01d..664cf7f52be 100644
--- a/scalalib/src/mill/scalalib/Lib.scala
+++ b/scalalib/src/mill/scalalib/Lib.scala
@@ -132,7 +132,9 @@ object Lib {
root <- sources
if os.exists(root.path)
path <- (if (os.isDir(root.path)) os.walk(root.path) else Seq(root.path))
- if os.isFile(path) && (extensions.exists(path.ext == _) && !isHiddenFile(path))
+ if os.isFile(path) && (extensions.exists(ex => path.last.endsWith(s".$ex")) && !isHiddenFile(
+ path
+ ))
} yield path
}
diff --git a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala
index f10a0595bc6..f28a17624ea 100644
--- a/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala
+++ b/scalalib/src/mill/scalalib/scalafmt/ScalafmtModule.scala
@@ -57,7 +57,9 @@ trait ScalafmtModule extends JavaModule {
file <- {
if (os.isDir(pathRef.path)) {
os.walk(pathRef.path).filter(file =>
- os.isFile(file) && (file.ext == "scala" || buildFileExtensions.contains(file.ext))
+ os.isFile(file) && (file.ext == "scala" || buildFileExtensions.exists(ex =>
+ file.last.endsWith(s".$ex")
+ ))
)
} else {
Seq(pathRef.path)
diff --git a/testkit/src/mill/testkit/ExampleTestSuite.scala b/testkit/src/mill/testkit/ExampleTestSuite.scala
deleted file mode 100644
index 7d15b65d553..00000000000
--- a/testkit/src/mill/testkit/ExampleTestSuite.scala
+++ /dev/null
@@ -1,11 +0,0 @@
-package mill.testkit
-import utest._
-
-object ExampleTestSuite extends IntegrationTestSuiteBase {
- val tests: Tests = Tests {
-
- test("exampleTest") {
- new ExampleTester(clientServerMode, workspaceSourcePath, millExecutable).run()
- }
- }
-}
diff --git a/testkit/src/mill/testkit/IntegrationTestSuite.scala b/testkit/src/mill/testkit/IntegrationTestSuite.scala
index 9ad34228288..e488a51542f 100644
--- a/testkit/src/mill/testkit/IntegrationTestSuite.scala
+++ b/testkit/src/mill/testkit/IntegrationTestSuite.scala
@@ -1,7 +1,8 @@
package mill.testkit
-abstract class IntegrationTestSuite extends IntegrationTestSuiteBase with IntegrationTester.Impl {
- override def utestAfterEach(path: Seq[String]): Unit = {
- if (clientServerMode) close()
- }
+abstract class UtestIntegrationTestSuite extends utest.TestSuite with IntegrationTestSuite {
+ protected def workspaceSourcePath: os.Path = os.Path(sys.env("MILL_TEST_RESOURCE_FOLDER"))
+ protected def clientServerMode: Boolean = sys.env("MILL_INTEGRATION_SERVER_MODE").toBoolean
+ protected def millExecutable: os.Path =
+ os.Path(System.getenv("MILL_INTEGRATION_LAUNCHER"), os.pwd)
}
diff --git a/testkit/src/mill/testkit/IntegrationTestSuiteBase.scala b/testkit/src/mill/testkit/IntegrationTestSuiteBase.scala
index b3a06993be1..24abc745b62 100644
--- a/testkit/src/mill/testkit/IntegrationTestSuiteBase.scala
+++ b/testkit/src/mill/testkit/IntegrationTestSuiteBase.scala
@@ -1,11 +1,18 @@
package mill.testkit
import os.Path
-import utest._
-abstract class IntegrationTestSuiteBase extends TestSuite {
- def workspaceSourcePath: os.Path = os.Path(sys.env("MILL_TEST_RESOURCE_FOLDER"))
- val clientServerMode: Boolean = sys.env("MILL_INTEGRATION_SERVER_MODE").toBoolean
+trait IntegrationTestSuite {
+ protected def workspaceSourcePath: os.Path
+ protected def clientServerMode: Boolean
- def millExecutable: Path = os.Path(System.getenv("MILL_INTEGRATION_LAUNCHER"), os.pwd)
+ protected def millExecutable: Path
+
+ def debugLog: Boolean = false
+ def integrationTest[T](t: IntegrationTester => T): T = {
+ val tester =
+ new IntegrationTester(clientServerMode, workspaceSourcePath, millExecutable, debugLog)
+ try t(tester)
+ finally tester.close()
+ }
}
diff --git a/testkit/src/mill/testkit/IntegrationTester.scala b/testkit/src/mill/testkit/IntegrationTester.scala
index d6bece57248..9ddc8350f88 100644
--- a/testkit/src/mill/testkit/IntegrationTester.scala
+++ b/testkit/src/mill/testkit/IntegrationTester.scala
@@ -23,7 +23,8 @@ import scala.util.control.NonFatal
class IntegrationTester(
val clientServerMode: Boolean,
val workspaceSourcePath: os.Path,
- val millExecutable: os.Path
+ val millExecutable: os.Path,
+ override val debugLog: Boolean = false
) extends IntegrationTester.Impl {
initWorkspace()
}
diff --git a/testkit/src/mill/testkit/IntegrationTesterBase.scala b/testkit/src/mill/testkit/IntegrationTesterBase.scala
index a67f5a7b27d..523fc2728a9 100644
--- a/testkit/src/mill/testkit/IntegrationTesterBase.scala
+++ b/testkit/src/mill/testkit/IntegrationTesterBase.scala
@@ -9,15 +9,17 @@ trait IntegrationTesterBase {
* Mill build being tested. Contains the `build.mill` file, any application code, and
* the `out/` folder containing the build output
*
- * Typically just `pwd`, which is a sandbox directory for test suites run using Mill.
+ * Typically a temp folder inside `pwd`, just in case there's some leftover
+ * files/processes from previous integration tests that may interfere with the current one
*/
- val workspacePath: os.Path = os.pwd
+ val workspacePath: os.Path = os.temp.dir(dir = os.pwd)
/**
* Initializes the workspace in preparation for integration testing
*/
def initWorkspace(): Unit = {
println(s"Copying integration test sources from $workspaceSourcePath to $workspacePath")
+ os.makeDir.all(workspacePath)
os.list(workspacePath).foreach(os.remove.all(_))
os.list(workspaceSourcePath).filter(_.last != out).foreach(os.copy.into(_, workspacePath))
os.remove.all(workspacePath / "out")
diff --git a/testkit/src/mill/testkit/UtestExampleTestSuite.scala b/testkit/src/mill/testkit/UtestExampleTestSuite.scala
new file mode 100644
index 00000000000..994a4995a04
--- /dev/null
+++ b/testkit/src/mill/testkit/UtestExampleTestSuite.scala
@@ -0,0 +1,15 @@
+package mill.testkit
+import utest._
+
+object UtestExampleTestSuite extends TestSuite {
+ val workspaceSourcePath: os.Path = os.Path(sys.env("MILL_TEST_RESOURCE_FOLDER"))
+ val clientServerMode: Boolean = sys.env("MILL_INTEGRATION_SERVER_MODE").toBoolean
+
+ val millExecutable: os.Path = os.Path(System.getenv("MILL_INTEGRATION_LAUNCHER"), os.pwd)
+ val tests: Tests = Tests {
+
+ test("exampleTest") {
+ new ExampleTester(clientServerMode, workspaceSourcePath, millExecutable).run()
+ }
+ }
+}
diff --git a/testkit/test/src/mill/testkit/IntegrationTesterTests.scala b/testkit/test/src/mill/testkit/IntegrationTesterTests.scala
index 13ed31e1a3e..9172a036427 100644
--- a/testkit/test/src/mill/testkit/IntegrationTesterTests.scala
+++ b/testkit/test/src/mill/testkit/IntegrationTesterTests.scala
@@ -2,28 +2,27 @@ package mill.testkit
import utest._
-object IntegrationTesterTests extends TestSuite {
-
+object IntegrationTesterTests extends TestSuite with IntegrationTestSuite {
+ def clientServerMode = true
+ def workspaceSourcePath =
+ os.Path(sys.env("MILL_TEST_RESOURCE_FOLDER")) / "integration-test-example-project"
+ def millExecutable = os.Path(sys.env("MILL_EXECUTABLE_PATH"))
def tests: Tests = Tests {
test("integration") {
- val tester = new IntegrationTester(
- clientServerMode = true,
- workspaceSourcePath =
- os.Path(sys.env("MILL_TEST_RESOURCE_FOLDER")) / "integration-test-example-project",
- millExecutable = os.Path(sys.env("MILL_EXECUTABLE_PATH"))
- )
+ integrationTest { tester =>
+ val res1 = tester.eval("testTask")
+ assert(res1.isSuccess)
+ assert(res1.err.contains("compiling 1 Scala source")) // compiling the `build.mill`
+ assert(tester.out("testTask").value[String] == "HELLO WORLD SOURCE FILE")
- val res1 = tester.eval("testTask")
- assert(res1.isSuccess)
- assert(res1.err.contains("compiling 1 Scala source")) // compiling the `build.mill`
- assert(tester.out("testTask").value[String] == "HELLO WORLD SOURCE FILE")
+ tester.modifyFile(tester.workspacePath / "source-file.txt", _ + "!!!")
- tester.modifyFile(tester.workspacePath / "source-file.txt", _ + "!!!")
+ val res2 = tester.eval("testTask")
+ assert(!res2.err.contains("compiling 1 Scala source")) // no need to re-compile `build.mill`
+ assert(tester.out("testTask").value[String] == "HELLO WORLD SOURCE FILE!!!")
+ }
- val res2 = tester.eval("testTask")
- assert(!res2.err.contains("compiling 1 Scala source")) // no need to re-compile `build.mill`
- assert(tester.out("testTask").value[String] == "HELLO WORLD SOURCE FILE!!!")
}
}
}