Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
lihaoyi committed Sep 8, 2024
1 parent de06ff3 commit 540c548
Show file tree
Hide file tree
Showing 8 changed files with 71 additions and 51 deletions.
20 changes: 12 additions & 8 deletions main/api/src/mill/api/Retry.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
*
Expand All @@ -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))
Expand Down
34 changes: 17 additions & 17 deletions testkit/src/mill/testkit/ExampleTester.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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

Expand Down Expand Up @@ -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()
}
}
}
25 changes: 20 additions & 5 deletions testkit/src/mill/testkit/IntegrationTestSuite.scala
Original file line number Diff line number Diff line change
@@ -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()
}
}
18 changes: 0 additions & 18 deletions testkit/src/mill/testkit/IntegrationTestSuiteBase.scala

This file was deleted.

3 changes: 2 additions & 1 deletion testkit/src/mill/testkit/IntegrationTester.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Expand Down
2 changes: 1 addition & 1 deletion testkit/src/mill/testkit/IntegrationTesterBase.scala
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 11 additions & 1 deletion testkit/src/mill/testkit/UtestExampleTestSuite.scala
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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"
)
}
}
}
}
8 changes: 8 additions & 0 deletions testkit/src/mill/testkit/UtestIntegrationTestSuite.scala
Original file line number Diff line number Diff line change
@@ -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)
}

0 comments on commit 540c548

Please sign in to comment.