Skip to content

Commit

Permalink
Merge pull request #161 from alexarchambault/bump-jsonrpc4s
Browse files Browse the repository at this point in the history
Update jsonrpc4s (via a fork)
  • Loading branch information
alexarchambault committed Mar 15, 2024
2 parents 1b24bf2 + 3b113c5 commit 82003e6
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 13 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/ci.yml
Expand Up @@ -84,11 +84,9 @@ jobs:
with:
jvm: "zulu:17"
- run: |
./mill -i __.publishLocal &&\
./mill -i integration.test.jvm
if: runner.os != 'Windows'
- run: |
@call ./mill.bat -i __.publishLocal
@call ./mill.bat -i integration.test.jvm
shell: cmd
if: runner.os == 'Windows'
Expand Down Expand Up @@ -127,11 +125,9 @@ jobs:
if-no-files-found: error
retention-days: 1
- run: |
./mill -i __.publishLocal &&\
./mill -i "integration.test.native"
if: github.event_name == 'push' && runner.os != 'Windows'
- run: |
./mill.bat -i __.publishLocal
./mill.bat -i integration.test.native
if: github.event_name == 'push' && runner.os == 'Windows'
shell: bash
Expand Down
30 changes: 26 additions & 4 deletions build.sc
Expand Up @@ -19,6 +19,8 @@ object Dependencies {

def scalaVersions = Seq(scala212, scala213)

def serverScalaVersion = scala212

def asmVersion = "9.6"
def coursierVersion = "2.1.0-M6-53-gb4f448130"
def graalvmVersion = "22.2.0"
Expand Down Expand Up @@ -46,6 +48,7 @@ object Dependencies {
ivy"com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-core:$jsoniterVersion"
def jsoniterMacros =
ivy"com.github.plokhotnyuk.jsoniter-scala::jsoniter-scala-macros:$jsoniterVersion"
def jsonrpc4s = ivy"io.github.alexarchambault.bleep::jsonrpc4s:0.1.1"
def junit = ivy"com.github.sbt:junit-interface:0.13.3"
def libdaemonjvm = ivy"io.github.alexarchambault.libdaemon::libdaemon:0.0.11"
def libraryManagement = ivy"org.scala-sbt::librarymanagement-ivy:1.9.3"
Expand Down Expand Up @@ -156,7 +159,11 @@ class Shared(val crossScalaVersion: String) extends BloopCrossSbtModule with Pub
emptyZip()
}
def ivyDeps = super.ivyDeps() ++ Agg(
Dependencies.bsp4s.exclude(("com.github.plokhotnyuk.jsoniter-scala", "*")),
Dependencies.bsp4s
.exclude(("com.github.plokhotnyuk.jsoniter-scala", "*"))
.exclude(("me.vican.jorge", "jsonrpc4s_2.12"))
.exclude(("me.vican.jorge", "jsonrpc4s_2.13")),
Dependencies.jsonrpc4s,
Dependencies.coursierInterface,
Dependencies.jsoniterCore,
Dependencies.log4j,
Expand Down Expand Up @@ -532,8 +539,8 @@ object `bloop-rifle` extends BloopCliModule {
|
|/** Build-time constants. Generated by mill. */
|object Constants {
| def bloopVersion = "${frontend(Dependencies.scala212).publishVersion()}"
| def bloopScalaVersion = "${Dependencies.scala212}"
| def bloopVersion = "${frontend(Dependencies.serverScalaVersion).publishVersion()}"
| def bloopScalaVersion = "${Dependencies.serverScalaVersion}"
| def bspVersion = "${Dependencies.bsp4j.dep.version}"
|}
|""".stripMargin
Expand Down Expand Up @@ -607,6 +614,19 @@ object integration extends BloopCliModule {
Dependencies.pprint
)

private def repoRoot = os.pwd / "out" / "repo"
def localRepo = T {
val modules = Seq(
frontend(Dependencies.serverScalaVersion),
backend(Dependencies.serverScalaVersion),
shared(Dependencies.serverScalaVersion)
)
os.remove.all(repoRoot)
os.makeDir.all(repoRoot)
val tasks = modules.map(_.publishLocalNoFluff(repoRoot.toString))
define.Target.sequence(tasks)
}

def forkEnv = super.forkEnv() ++ Seq(
"BLOOP_CLI_TESTS_TMP_DIR" -> tmpDir()
)
Expand All @@ -615,8 +635,10 @@ object integration extends BloopCliModule {
def test(args: String*) = {
val argsTask = T.task {
val launcher = launcherTask().path
localRepo()
val extraArgs = Seq(
s"-Dtest.bloop-cli.path=$launcher"
s"-Dtest.bloop-cli.path=$launcher",
s"-Dtest.bloop-cli.repo=$repoRoot"
)
args ++ extraArgs
}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/main/scala/bloop/bsp/BspServer.scala
Expand Up @@ -163,6 +163,8 @@ object BspServer {
case scala.util.Success(socket: ServerSocket) =>
listenToConnection(handle, socket).onErrorRecover {
case t =>
System.err.println("Exiting BSP server with:")
t.printStackTrace(System.err)
state.withError(s"Exiting BSP server with ${t.getMessage}", t)
}
case scala.util.Failure(t: Throwable) =>
Expand Down
Expand Up @@ -9,22 +9,21 @@ class BloopCliTests extends munit.FunSuite {
val dirArgs = Seq[os.Shellable]("--daemon-dir", root / "daemon")

os.proc(Launcher.launcher, "exit", dirArgs)
.call(cwd = root)
.call(cwd = root, stdin = os.Inherit, stdout = os.Inherit)
val statusCheck0 = os.proc(Launcher.launcher, "status", dirArgs)
.call(cwd = root)
.out.trim()
expect(statusCheck0 == "stopped")

val res = os.proc(Launcher.launcher, dirArgs, "about")
.call(cwd = root)
expect(res.out.text().startsWith("bloop v"))
os.proc(Launcher.launcher, dirArgs, "about")
.call(cwd = root, stdin = os.Inherit, stdout = os.Inherit, env = Launcher.extraEnv)
val statusCheck1 = os.proc(Launcher.launcher, "status", dirArgs)
.call(cwd = root)
.out.trim()
expect(statusCheck1 == "running")

os.proc(Launcher.launcher, "exit", dirArgs)
.call(cwd = root)
.call(cwd = root, stdin = os.Inherit, stdout = os.Inherit)
val statusCheck2 = os.proc(Launcher.launcher, "status", dirArgs)
.call(cwd = root)
.out.trim()
Expand Down
134 changes: 134 additions & 0 deletions integration/test/src/bloop/cli/integration/BspTests.scala
@@ -0,0 +1,134 @@
package bloop.cli.integration

import java.net.{StandardProtocolFamily, UnixDomainSocketAddress}
import java.nio.channels.SocketChannel
import java.nio.charset.StandardCharsets
import java.nio.ByteBuffer

class BspTests extends munit.FunSuite {

test("no JSON junk in errors") {
TmpDir.fromTmpDir { root =>
val dirArgs = Seq[os.Shellable]("--daemon-dir", root / "daemon")
val bspFile = root / "bsp-socket"

val dummyMsg =
"""{
| "jsonrpc": "2.0",
| "method": "workspace/buildTargetz",
| "params": null,
| "id": 2
|}""".stripMargin

var bspProc: os.SubProcess = null
var socket: SocketChannel = null

try {
os.proc(Launcher.launcher, dirArgs, "about")
.call(cwd = root, stdin = os.Inherit, stdout = os.Inherit, env = Launcher.extraEnv)

bspProc =
os.proc(Launcher.launcher, dirArgs, "bsp", "--protocol", "local", "--socket", bspFile)
.spawn(cwd = root, stdin = os.Inherit, stdout = os.Inherit)

val addr = UnixDomainSocketAddress.of(bspFile.toNIO)
var connected = false
var attemptCount = 0

while (!connected && bspProc.isAlive() && attemptCount < 10) {
if (attemptCount > 0)
Thread.sleep(1000L)
attemptCount += 1

if (os.exists(bspFile)) {
socket = SocketChannel.open(StandardProtocolFamily.UNIX)
socket.connect(addr)
socket.finishConnect()
connected = true
}
}

if (!connected)
sys.error("Not connected to Bloop server via BSP :|")

def sendMsg(msg: String): Unit = {
val bytes = msg.getBytes(StandardCharsets.UTF_8)

def doWrite(buf: ByteBuffer): Unit =
if (buf.position() < buf.limit()) {
val written = socket.write(buf)
if (written == 0)
Thread.sleep(100L)
doWrite(buf)
}

doWrite(ByteBuffer.wrap(
(s"Content-Length: ${bytes.length}" + "\r\n\r\n").getBytes(StandardCharsets.UTF_8)
))
doWrite(ByteBuffer.wrap(bytes))
}

sendMsg(dummyMsg)

val arr = Array.ofDim[Byte](10 * 1024)
val buf = ByteBuffer.wrap(arr)

// seems to do the job…
def doRead(buf: ByteBuffer, count: Int): Int = {
val read = socket.read(buf)
if (read <= 0 && count < 100) {
Thread.sleep(100L)
doRead(buf, count + 1)
}
else
read
}

val read = doRead(buf, 0)
assert(read > 0)

val resp = new String(arr, 0, read, StandardCharsets.UTF_8)

def validateJson(content: String): Boolean = {
assert(content.startsWith("{"))
assert(content.endsWith("}"))
val chars = content.toCharArray
val objCount = Array.ofDim[Int](chars.length)
for (i <- 0 until chars.length) {
val previous = if (i == 0) 0 else objCount(i - 1)
val count = previous + (if (chars(i) == '{') 1 else if (chars(i) == '}') -1 else 0)
objCount(i) = count
}
objCount.dropRight(1).forall(_ > 0)
}

resp.linesWithSeparators.toVector match {
case Seq(cl, empty, other @ _*)
if cl.startsWith("Content-Length:") && empty.trim.isEmpty =>
val json = other.mkString
val validated = validateJson(json)
if (!validated)
pprint.err.log(json)
assert(validated, "Unexpected JSON response shape")
case _ =>
pprint.err.log(resp)
sys.error("Unexpected response shape")
}
}
finally {
if (socket != null)
socket.close()

if (bspProc != null) {
bspProc.waitFor(1000L)
if (bspProc.isAlive())
bspProc.close()

os.proc(Launcher.launcher, dirArgs, "exit")
.call(cwd = root, stdin = os.Inherit, stdout = os.Inherit, check = false)
}
}
}
}

}
10 changes: 10 additions & 0 deletions integration/test/src/bloop/cli/integration/Launcher.scala
Expand Up @@ -7,4 +7,14 @@ object Launcher {
sys.error("test.bloop-cli.path not set")
)

lazy val repoRoot = os.Path(sys.props.getOrElse(
"test.bloop-cli.repo",
sys.error("test.bloop-cli.repo not set")
))

lazy val extraEnv =
Map(
"COURSIER_REPOSITORIES" -> s"ivy:${repoRoot.toNIO.toUri.toASCIIString}/[defaultPattern]|ivy2Local|central"
)

}

0 comments on commit 82003e6

Please sign in to comment.