Skip to content

Commit e398858

Browse files
committed
Added standalone tests for SBT import
1 parent c8a2ab6 commit e398858

File tree

8 files changed

+274
-0
lines changed

8 files changed

+274
-0
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package mill.standalone
2+
3+
import utest.*
4+
5+
object MillInitCatsTests extends GitRepoStandaloneTestSuite {
6+
7+
def gitRepoUrl = "[email protected]:typelevel/cats.git"
8+
def gitRepoBranch = "v2.13.0"
9+
10+
def tests = Tests {
11+
test - standaloneTest { tester =>
12+
import tester.*
13+
14+
eval("init").isSuccess ==> true
15+
eval("__.compile").isSuccess ==> true
16+
eval("__.test").isSuccess ==> true
17+
/*
18+
[6380] 6 tasks failed
19+
[6380] kernel-laws.native.resolvedMvnDeps java.lang.RuntimeException:
20+
[6380] Resolution failed for 7 modules:
21+
[6380] --------------------------------------------
22+
[6380] org.scala-native:auxlib_2.13:0.5.6
23+
*/
24+
}
25+
}
26+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package mill.standalone
2+
3+
import utest.*
4+
5+
object MillInitLilaTests extends GitRepoStandaloneTestSuite {
6+
7+
def gitRepoUrl = "[email protected]:lichess-org/lila.git"
8+
def gitRepoBranch = "master"
9+
10+
def tests = Tests {
11+
test - standaloneTest { tester =>
12+
import tester.*
13+
14+
eval("init").isSuccess ==> true
15+
eval("__.compile").isSuccess ==> true
16+
/*
17+
[6380] [error] -- [E8] .../mill/out/standalone/migrating/sbt/packaged/nodaemon/testOnly.dest/sandbox/clone/lila/modules/analyse/package.mill:73:69
18+
[6380] [error] 73 │ def moduleDeps = super.moduleDeps ++ Seq(build.modules.coreI18n.test)
19+
[6380] [error] │ ^^^^
20+
[6380] [error] │value test is not a member of object build_.modules.coreI18n.package_
21+
*/
22+
}
23+
}
24+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package mill.standalone
2+
3+
import utest.*
4+
5+
object MillInitScala3Tests extends GitRepoStandaloneTestSuite {
6+
7+
def gitRepoUrl = "[email protected]:scala/scala3.git"
8+
def gitRepoBranch = "3.7.1"
9+
10+
def tests = Tests {
11+
test - standaloneTest { tester =>
12+
import tester.*
13+
14+
eval("init").isSuccess ==> true
15+
eval("__.compile").isSuccess ==> true
16+
/*
17+
[6380] Exception in thread "main" java.lang.IllegalArgumentException: Project at duplicate locations
18+
*/
19+
}
20+
}
21+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package mill.standalone
2+
3+
import utest.*
4+
5+
object MillInitScalaPBTests extends GitRepoStandaloneTestSuite {
6+
7+
def gitRepoUrl = "[email protected]:scalapb/ScalaPB.git"
8+
def gitRepoBranch = "v0.11.19"
9+
10+
def tests = Tests {
11+
test - standaloneTest { tester =>
12+
import tester.*
13+
14+
eval("init").isSuccess ==> true
15+
eval("__.compile").isSuccess ==> true
16+
eval("__.test").isSuccess ==> true
17+
/*
18+
[6380] Cannot resolve __.test. Try `mill resolve _` to see what's available.
19+
*/
20+
}
21+
}
22+
}

standalone/package.mill

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package build.standalone
2+
3+
import mill.scalalib.TestModule
4+
import mill.{Cross, Module}
5+
import millbuild._
6+
7+
object `package` extends Module {
8+
9+
trait StandaloneTestModule extends Cross.Module[String] with MillBaseTestsModule
10+
with TestModule.Utest {
11+
def moduleDir = super.moduleDir / crossValue
12+
def moduleDeps = Seq(build.core.eval, testkit)
13+
def mvnDeps = Seq(Deps.TestDeps.utest)
14+
15+
def forkArgs = super.forkArgs() ++ build.dist.forkArgs()
16+
def forkEnv = super.forkEnv() ++
17+
Map(
18+
"MILL_STANDALONE_EXECUTABLE" -> build.dist.launcher().path.toString(),
19+
"MILL_STANDALONE_DAEMON_MODE" -> "false"
20+
) ++
21+
build.dist.localTestOverridesEnv()
22+
}
23+
24+
object migrating extends Cross[StandaloneCrossTestModule](build.listCross)
25+
trait StandaloneCrossTestModule extends MillScalaModule with StandaloneTestModule {
26+
override def moduleDeps = super[StandaloneTestModule].moduleDeps
27+
def scalaVersion = Deps.scalaVersion
28+
}
29+
30+
object testkit extends MillScalaModule {
31+
def moduleDeps = Seq(build.core.eval)
32+
def mvnDeps = Seq(Deps.TestDeps.utest)
33+
}
34+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package mill.standalone
2+
3+
trait GitRepoStandaloneTestSuite extends utest.TestSuite, StandaloneTestSuite {
4+
5+
def gitRepoUrl: String
6+
def gitRepoBranch: String
7+
def gitRepoDepth: Int = 1
8+
9+
def workspacePath = {
10+
val cwd = os.temp.dir(dir = os.pwd, deleteOnExit = false)
11+
// preserve repo dir name for a realistic reproduction
12+
os.proc("git", "clone", gitRepoUrl, "--depth", gitRepoDepth, "--branch", gitRepoBranch)
13+
.call(cwd = cwd)
14+
os.list(cwd).head
15+
}
16+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package mill.standalone
2+
3+
trait StandaloneTestSuite {
4+
5+
protected def millExecutable: os.Path =
6+
os.Path(System.getenv("MILL_STANDALONE_EXECUTABLE"), os.pwd)
7+
8+
protected def daemonMode: Boolean =
9+
sys.env("MILL_STANDALONE_DAEMON_MODE").toBoolean
10+
11+
def debugLog = false
12+
13+
protected def propagateJavaHome: Boolean = true
14+
15+
def workspacePath: os.Path
16+
17+
def standaloneTest[T](block: StandaloneTester => T): T = {
18+
val tester = StandaloneTester(
19+
millExecutable,
20+
daemonMode,
21+
debugLog,
22+
workspacePath,
23+
propagateJavaHome
24+
)
25+
block(tester)
26+
}
27+
}
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
package mill.standalone
2+
3+
import mill.constants.DaemonFiles.processId
4+
import mill.constants.OutFiles.{millDaemon, millNoDaemon, out}
5+
import os.{Path, ProcessInput, ProcessOutput, Shellable}
6+
7+
class StandaloneTester(
8+
val millExecutable: os.Path,
9+
val daemonMode: Boolean,
10+
val debugLog: Boolean = false,
11+
val workspacePath: os.Path = os.pwd,
12+
val propagateJavaHome: Boolean = true
13+
) extends StandaloneTester.Impl
14+
15+
object StandaloneTester {
16+
17+
case class EvalResult(exitCode: Int, out: String, err: String) {
18+
def isSuccess: Boolean = exitCode == 0
19+
20+
def debugString: String = {
21+
s"""Success: $isSuccess (exit code: $exitCode)
22+
|
23+
|stdout:
24+
|$out
25+
|
26+
|stderr:
27+
|$err
28+
|""".stripMargin
29+
}
30+
}
31+
32+
trait Impl extends AutoCloseable {
33+
34+
def workspacePath: os.Path
35+
36+
def millExecutable: os.Path
37+
38+
def daemonMode: Boolean
39+
40+
def debugLog: Boolean
41+
42+
def propagateJavaHome: Boolean
43+
44+
def millTestSuiteEnv: Map[String, String] = Option.when(propagateJavaHome)(
45+
"JAVA_HOME" -> sys.props("java.home")
46+
).toMap
47+
48+
def eval(
49+
cmd: Shellable,
50+
env: Map[String, String] = Map(),
51+
cwd: Path = workspacePath,
52+
stdin: ProcessInput = os.Pipe,
53+
stdout: ProcessOutput = os.Pipe,
54+
stderr: ProcessOutput = os.Pipe,
55+
mergeErrIntoOut: Boolean = false,
56+
timeout: Long = -1,
57+
check: Boolean = false,
58+
shutdownGracePeriod: Long = 100
59+
) = {
60+
val serverArgs = Option.when(!daemonMode)("--no-daemon")
61+
val debugArgs = Option.when(debugLog)("--debug")
62+
val cmd0: os.Shellable = (millExecutable, serverArgs, debugArgs, cmd)
63+
64+
val callEnv = millTestSuiteEnv ++ env
65+
66+
val res0 = os.call(
67+
cmd0,
68+
env = callEnv,
69+
cwd = cwd,
70+
stdin = stdin,
71+
stdout = stdout,
72+
stderr = stderr,
73+
mergeErrIntoOut = mergeErrIntoOut,
74+
timeout = timeout,
75+
check = check,
76+
shutdownGracePeriod = shutdownGracePeriod
77+
)
78+
79+
EvalResult(
80+
res0.exitCode,
81+
fansi.Str(res0.out.text(), errorMode = fansi.ErrorMode.Strip).plainText.trim,
82+
fansi.Str(res0.err.text(), errorMode = fansi.ErrorMode.Strip).plainText.trim
83+
)
84+
}
85+
86+
def close() = removeProcessIdFile()
87+
88+
def removeProcessIdFile() = {
89+
val outDir = os.Path(out, workspacePath)
90+
if (os.exists(outDir)) {
91+
if (daemonMode) {
92+
val serverPath = outDir / millDaemon
93+
os.remove(serverPath / processId)
94+
} else {
95+
val serverPath0 = outDir / millNoDaemon
96+
97+
for (serverPath <- os.list.stream(serverPath0)) os.remove(serverPath / processId)
98+
99+
}
100+
Thread.sleep(500) // give a moment for the server to notice the file is gone and exit
101+
}
102+
}
103+
}
104+
}

0 commit comments

Comments
 (0)