From 540c5487e479811cd6350e57c59959239b0e1687 Mon Sep 17 00:00:00 2001 From: Li Haoyi Date: Sun, 8 Sep 2024 11:52:42 +0800 Subject: [PATCH] . --- main/api/src/mill/api/Retry.scala | 20 ++++++----- testkit/src/mill/testkit/ExampleTester.scala | 34 +++++++++---------- .../mill/testkit/IntegrationTestSuite.scala | 25 +++++++++++--- .../testkit/IntegrationTestSuiteBase.scala | 18 ---------- .../src/mill/testkit/IntegrationTester.scala | 3 +- .../mill/testkit/IntegrationTesterBase.scala | 2 +- .../mill/testkit/UtestExampleTestSuite.scala | 12 ++++++- .../testkit/UtestIntegrationTestSuite.scala | 8 +++++ 8 files changed, 71 insertions(+), 51 deletions(-) delete mode 100644 testkit/src/mill/testkit/IntegrationTestSuiteBase.scala create mode 100644 testkit/src/mill/testkit/UtestIntegrationTestSuite.scala diff --git a/main/api/src/mill/api/Retry.scala b/main/api/src/mill/api/Retry.scala index 88a495cb25c..1f3cc6957fc 100644 --- a/main/api/src/mill/api/Retry.scala +++ b/main/api/src/mill/api/Retry.scala @@ -4,7 +4,11 @@ import java.util.concurrent.TimeUnit import scala.concurrent.duration.Duration import scala.concurrent.{Await, Promise} -object Retry { +case class Retry(count: Int = 5, + backoffMillis: Long = 10, + backoffMultiplier: Double = 2.0, + timeoutMillis: Long = -1, + filter: (Int, Throwable) => Boolean = (_, _) => true) { /** * Generic retry functionality * @@ -21,18 +25,18 @@ object Retry { * @return the value of evaluating [[t]], or throws an exception if evaluating * [[t]] fails more than [[count]] times */ - def apply[T](count: Int = 5, - backoffMillis: Long = 10, - backoffMultiplier: Double = 2.0, - timeoutMillis: Long = -1, - filter: (Int, Throwable) => Boolean = (_, _) => true)(t: => T): T = { + def apply[T](t: => T): T = { + indexed(i => t) + } + + def indexed[T](t: Int => T): T = { def rec(retryCount: Int, currentBackoffMillis: Long): T = { try { - if(timeoutMillis == -1) t + if(timeoutMillis == -1) t(retryCount) else{ val result = Promise[T] val thread = new Thread(() => { - result.complete(scala.util.Try(t)) + result.complete(scala.util.Try(t(retryCount))) }) thread.start() Await.result(result.future, Duration.apply(timeoutMillis, TimeUnit.MILLISECONDS)) diff --git a/testkit/src/mill/testkit/ExampleTester.scala b/testkit/src/mill/testkit/ExampleTester.scala index 33cd597b37b..7bdb7cd8097 100644 --- a/testkit/src/mill/testkit/ExampleTester.scala +++ b/testkit/src/mill/testkit/ExampleTester.scala @@ -55,14 +55,18 @@ object ExampleTester { clientServerMode: Boolean, workspaceSourcePath: os.Path, millExecutable: os.Path, - bashExecutable: String = defaultBashExecutable() - ): Unit = + bashExecutable: String = defaultBashExecutable(), + workspacePath: os.Path = os.pwd + ): Unit = { new ExampleTester( clientServerMode, workspaceSourcePath, millExecutable, - bashExecutable - ).run() + bashExecutable, + workspacePath + ) + } + def defaultBashExecutable(): String = { if (!mill.main.client.Util.isWindows) "bash" @@ -74,13 +78,10 @@ class ExampleTester( clientServerMode: Boolean, val workspaceSourcePath: os.Path, millExecutable: os.Path, - bashExecutable: String = ExampleTester.defaultBashExecutable() + bashExecutable: String = ExampleTester.defaultBashExecutable(), + val workspacePath: os.Path ) extends IntegrationTesterBase { - os.copy.over(millExecutable, workspacePath / "mill") - - val testTimeout: FiniteDuration = 5.minutes - def processCommandBlock(commandBlock: String): Unit = { val commandBlockLines = commandBlock.linesIterator.toVector @@ -188,18 +189,17 @@ class ExampleTester( } def run(): Any = { + os.copy.over(millExecutable, workspacePath / "mill") val parsed = ExampleParser(workspaceSourcePath) val usageComment = parsed.collect { case ("example", txt) => txt }.mkString("\n\n") val commandBlocks = ("\n" + usageComment.trim).split("\n> ").filter(_.nonEmpty) - Retry(count = 3, timeoutMillis = testTimeout.toMillis) { - try { - initWorkspace() - for (commandBlock <- commandBlocks) processCommandBlock(commandBlock) - } finally { - if (clientServerMode) processCommand(Vector(), "./mill shutdown", check = false) - removeServerIdFile() - } + try { + initWorkspace() + for (commandBlock <- commandBlocks) processCommandBlock(commandBlock) + } finally { + if (clientServerMode) processCommand(Vector(), "./mill shutdown", check = false) + removeServerIdFile() } } } diff --git a/testkit/src/mill/testkit/IntegrationTestSuite.scala b/testkit/src/mill/testkit/IntegrationTestSuite.scala index e488a51542f..fce86b782de 100644 --- a/testkit/src/mill/testkit/IntegrationTestSuite.scala +++ b/testkit/src/mill/testkit/IntegrationTestSuite.scala @@ -1,8 +1,23 @@ package mill.testkit -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) +import os.Path + +trait IntegrationTestSuite { + protected def workspaceSourcePath: os.Path + protected def clientServerMode: Boolean + + protected def millExecutable: Path + + def debugLog: Boolean = false + def integrationTest[T](t: IntegrationTester => T): T = { + val tester = new IntegrationTester( + clientServerMode, + workspaceSourcePath, + millExecutable, + debugLog, + workspacePath = os.pwd + ) + try t(tester) + finally tester.close() + } } diff --git a/testkit/src/mill/testkit/IntegrationTestSuiteBase.scala b/testkit/src/mill/testkit/IntegrationTestSuiteBase.scala deleted file mode 100644 index 24abc745b62..00000000000 --- a/testkit/src/mill/testkit/IntegrationTestSuiteBase.scala +++ /dev/null @@ -1,18 +0,0 @@ -package mill.testkit - -import os.Path - -trait IntegrationTestSuite { - protected def workspaceSourcePath: os.Path - protected def clientServerMode: Boolean - - 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 803ad5f6a06..b55bb335be0 100644 --- a/testkit/src/mill/testkit/IntegrationTester.scala +++ b/testkit/src/mill/testkit/IntegrationTester.scala @@ -22,7 +22,8 @@ class IntegrationTester( val clientServerMode: Boolean, val workspaceSourcePath: os.Path, val millExecutable: os.Path, - override val debugLog: Boolean = false + override val debugLog: Boolean = false, + val workspacePath: os.Path ) extends IntegrationTester.Impl { initWorkspace() } diff --git a/testkit/src/mill/testkit/IntegrationTesterBase.scala b/testkit/src/mill/testkit/IntegrationTesterBase.scala index 9e7ac5ab9c3..45f626cd0d9 100644 --- a/testkit/src/mill/testkit/IntegrationTesterBase.scala +++ b/testkit/src/mill/testkit/IntegrationTesterBase.scala @@ -11,7 +11,7 @@ trait IntegrationTesterBase { * Mill build being tested. Contains the `build.mill` file, any application code, and * the `out/` folder containing the build output */ - val workspacePath: os.Path = os.pwd + val workspacePath: os.Path /** * Initializes the workspace in preparation for integration testing diff --git a/testkit/src/mill/testkit/UtestExampleTestSuite.scala b/testkit/src/mill/testkit/UtestExampleTestSuite.scala index 994a4995a04..bbf7b316ba3 100644 --- a/testkit/src/mill/testkit/UtestExampleTestSuite.scala +++ b/testkit/src/mill/testkit/UtestExampleTestSuite.scala @@ -1,6 +1,9 @@ package mill.testkit +import mill.api.Retry import utest._ +import scala.concurrent.duration.DurationInt + 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 @@ -9,7 +12,14 @@ object UtestExampleTestSuite extends TestSuite { val tests: Tests = Tests { test("exampleTest") { - new ExampleTester(clientServerMode, workspaceSourcePath, millExecutable).run() + Retry(count = 3, timeoutMillis = 5.minutes.toMillis).indexed { i => + ExampleTester.run( + clientServerMode, + workspaceSourcePath, + millExecutable, + workspacePath = os.pwd / s"run-$i" + ) + } } } } diff --git a/testkit/src/mill/testkit/UtestIntegrationTestSuite.scala b/testkit/src/mill/testkit/UtestIntegrationTestSuite.scala new file mode 100644 index 00000000000..e488a51542f --- /dev/null +++ b/testkit/src/mill/testkit/UtestIntegrationTestSuite.scala @@ -0,0 +1,8 @@ +package mill.testkit + +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) +}