Skip to content

Commit

Permalink
Merge pull request #3325 from Gedochao/maintenance/coursier-installat…
Browse files Browse the repository at this point in the history
…ion-tests-on-windows

Support `coursier`-downloaded `scala` wrapper tests on Windows
  • Loading branch information
Gedochao authored Dec 4, 2024
2 parents dfa9f03 + e338513 commit 2f0c7b8
Show file tree
Hide file tree
Showing 4 changed files with 116 additions and 44 deletions.
1 change: 1 addition & 0 deletions build.sc
Original file line number Diff line number Diff line change
Expand Up @@ -1037,6 +1037,7 @@ trait CliIntegration extends SbtModule with ScalaCliPublishModule with HasTests
| def scala3LtsPrefix = "${Scala.scala3LtsPrefix}"
| def scala3Lts = "${Scala.scala3Lts}"
| def scala3NextRc = "${Scala.scala3NextRc}"
| def scala3NextRcAnnounced = "${Scala.scala3NextRcAnnounced}"
| def scala3Next = "${Scala.scala3Next}"
| def scala3NextAnnounced = "${Scala.scala3NextAnnounced}"
| def defaultScala = "${Scala.defaultUser}"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package scala.cli.integration

import com.eed3si9n.expecty.Expecty.expect

import java.nio.charset.Charset

import scala.jdk.CollectionConverters.IteratorHasAsScala
import scala.util.Properties

trait CoursierScalaInstallationTestHelper {
def withScalaRunnerWrapper(
root: os.Path,
localCache: os.Path,
localBin: os.Path,
scalaVersion: String
)(f: os.Path => Unit): Unit = {
os.proc(
TestUtil.cs,
"install",
"--cache",
localCache,
"--install-dir",
localBin,
s"scala:$scalaVersion"
).call(cwd = root)
val (launchScalaPath: os.Path, underlyingScriptPath: os.Path) =
if (Properties.isWin) {
val batchWrapperScript: os.Path = localBin / "scala.bat"
val charset = Charset.defaultCharset().toString
val batchWrapperContent = new String(os.read.bytes(batchWrapperScript), charset)
val setCommandLine = batchWrapperContent
.lines()
.iterator()
.asScala
.toList
.find(_.startsWith("SET CMDLINE="))
.getOrElse("")
val scriptPathRegex = """SET CMDLINE="(.*\\bin\\scala\.bat)" %CMD_LINE_ARGS%""".r
val batchScript =
setCommandLine match { case scriptPathRegex(extractedPath) => extractedPath }
val batchScriptPath = os.Path(batchScript)
val oldContent = os.read(batchScriptPath)
val newContent = oldContent.replace(
"call %SCALA_CLI_CMD_WIN%",
s"""set "SCALA_CLI_CMD_WIN=${TestUtil.cliPath}"
|call %SCALA_CLI_CMD_WIN%""".stripMargin
)
expect(newContent != oldContent)
os.write.over(batchScriptPath, newContent)
batchWrapperScript -> batchScriptPath
}
else {
val scalaBinary: os.Path = localBin / "scala"
val fileBytes = os.read.bytes(scalaBinary)
val shebang = new String(fileBytes.takeWhile(_ != '\n'), "UTF-8")
val binaryData = fileBytes.drop(shebang.length + 1)
val execLine = new String(binaryData.takeWhile(_ != '\n'), "UTF-8")
val scriptPathRegex = """exec "([^"]+/bin/scala).*"""".r
val scalaScript = execLine match { case scriptPathRegex(extractedPath) => extractedPath }
val scalaScriptPath = os.Path(scalaScript)
val lineToChange = "eval \"${SCALA_CLI_CMD_BASH[@]}\" \\"
// FIXME: the way the scala script calls the launcher currently ignores the --debug flag
val newContent = os.read(scalaScriptPath).replace(
lineToChange,
s"""SCALA_CLI_CMD_BASH=(\"\\\"${TestUtil.cliPath}\\\"\")
|$lineToChange""".stripMargin
)
os.write.over(scalaScriptPath, newContent)
scalaBinary -> scalaScriptPath
}
val wrapperVersion = os.proc(launchScalaPath, "version", "--cli-version")
.call(cwd = root).out.trim()
val cliVersion = os.proc(TestUtil.cli, "version", "--cli-version")
.call(cwd = root).out.trim()
expect(wrapperVersion == cliVersion)
f(launchScalaPath)
// clean up cs local binaries
val csPrebuiltBinaryDir =
os.Path(underlyingScriptPath.toString().substring(
0,
underlyingScriptPath.toString().indexOf(scalaVersion) + scalaVersion.length
))
System.err.println(s"Cleaning up, trying to remove $csPrebuiltBinaryDir")
try {
os.remove.all(csPrebuiltBinaryDir)

System.err.println(s"Cleanup complete. Removed $csPrebuiltBinaryDir")
}
catch {
case ex: java.nio.file.FileSystemException =>
System.err.println(s"Failed to remove $csPrebuiltBinaryDir: $ex")
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import os.CommandResult

import scala.util.Properties

class SipScalaTests extends ScalaCliSuite with SbtTestHelper with MillTestHelper {
class SipScalaTests extends ScalaCliSuite
with SbtTestHelper
with MillTestHelper
with CoursierScalaInstallationTestHelper {
implicit class StringEnrichment(s: String) {
def containsExperimentalWarningOf(featureNameAndType: String): Boolean =
s.contains(s"The $featureNameAndType is experimental") ||
Expand Down Expand Up @@ -833,40 +836,20 @@ class SipScalaTests extends ScalaCliSuite with SbtTestHelper with MillTestHelper
}
}

if (!Properties.isWin) // FIXME: run this test on Windows
test("coursier scala installation works in --offline mode") {
TestInputs.empty.fromRoot { root =>
val localCache = root / "local-cache"
val localBin = root / "local-bin"
val sv = "3.5.0-RC4"
os.proc(
TestUtil.cs,
"install",
"--cache",
localCache,
"--install-dir",
localBin,
s"scala:$sv"
).call(cwd = root)
val scalaBinary: os.Path = localBin / "scala"
val fileBytes = os.read.bytes(scalaBinary)
val shebang = new String(fileBytes.takeWhile(_ != '\n'), "UTF-8")
val binaryData = fileBytes.drop(shebang.length + 1)
val execLine = new String(binaryData.takeWhile(_ != '\n'), "UTF-8")
val scriptPathRegex = """exec "([^"]+/bin/scala).*"""".r
val scalaScript = execLine match { case scriptPathRegex(extractedPath) => extractedPath }
val scalaScriptPath = os.Path(scalaScript)
val lineToChange = "eval \"${SCALA_CLI_CMD_BASH[@]}\" \\"
// FIXME: the way the scala script calls the launcher currently ignores the --debug flag
val newContent = os.read(scalaScriptPath).replace(
lineToChange,
s"""SCALA_CLI_CMD_BASH=(\"\\\"${TestUtil.cliPath}\\\"\")
|$lineToChange""".stripMargin
)
os.write.over(scalaScriptPath, newContent)
test("coursier scala installation works in --offline mode") {
TestInputs.empty.fromRoot { root =>
val localCache = root / "local-cache"
val localBin = root / "local-bin"
val scalaVersion = Constants.scala3NextRcAnnounced
withScalaRunnerWrapper(
root = root,
localCache = localCache,
localBin = localBin,
scalaVersion = scalaVersion
) { launchScalaPath =>
val r =
os.proc(
scalaScript,
launchScalaPath,
"--offline",
"--power",
"--with-compiler",
Expand All @@ -877,18 +860,11 @@ class SipScalaTests extends ScalaCliSuite with SbtTestHelper with MillTestHelper
env = Map("COURSIER_CACHE" -> localCache.toString),
check = false // need to clean up even on failure
)
// clean up cs local binaries
val csPrebuiltBinaryDir =
os.Path(scalaScript.substring(0, scalaScript.indexOf(sv) + sv.length))
try os.remove.all(csPrebuiltBinaryDir)
catch {
case ex: java.nio.file.FileSystemException =>
println(s"Failed to remove $csPrebuiltBinaryDir: $ex")
}
expect(r.exitCode == 0)
expect(r.out.trim() == sv)
expect(r.out.trim() == scalaVersion)
}
}
}

// this check is just to ensure this isn't being run for LTS RC jobs
// should be adjusted when a new LTS line is released
Expand Down
5 changes: 3 additions & 2 deletions project/deps.sc
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ object Scala {
def scala3Lts = s"$scala3LtsPrefix.4" // the LTS version currently used in the build
def scala3NextPrefix = "3.5"
def scala3Next = s"$scala3NextPrefix.2" // the newest/next version of Scala
def scala3NextAnnounced = scala3Next // the newest/next version of Scala that's been announced
def scala3NextRc = "3.6.2-RC3" // the latest RC version of Scala Next
def scala3NextAnnounced = scala3Next // the newest/next version of Scala that's been announced
def scala3NextRc = "3.6.2-RC3" // the latest RC version of Scala Next
def scala3NextRcAnnounced = scala3NextRc // the latest RC version of Scala Next

// The Scala version used to build the CLI itself.
def defaultInternal = sys.props.get("scala.version.internal").getOrElse(scala3Lts)
Expand Down

0 comments on commit 2f0c7b8

Please sign in to comment.