Skip to content

Commit d46768a

Browse files
Add re-attempt mechanism to BSP-related tests
Which tend to be flaky on the CI :/
1 parent 26edbe6 commit d46768a

File tree

1 file changed

+44
-23
lines changed

1 file changed

+44
-23
lines changed

modules/integration/src/test/scala/scala/cli/integration/BspTestDefinitions.scala

Lines changed: 44 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,15 @@ import java.nio.charset.Charset
88
import java.nio.file.Paths
99
import java.util.concurrent.TimeoutException
1010

11+
import scala.annotation.tailrec
1112
import scala.async.Async.{async, await}
1213
import scala.collection.JavaConverters._
1314
import scala.concurrent.{Await, Future, Promise}
1415
import scala.concurrent.ExecutionContext.Implicits.global
1516
import scala.concurrent.duration._
1617
import scala.io.Codec
1718
import scala.util.control.NonFatal
18-
import scala.util.Properties
19+
import scala.util.{Failure, Properties, Success, Try}
1920

2021
abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
2122
extends munit.FunSuite with TestScalaVersionArgs {
@@ -59,7 +60,8 @@ abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
5960

6061
def withBsp[T](
6162
inputs: TestInputs,
62-
args: Seq[String]
63+
args: Seq[String],
64+
attempts: Int = 3
6365
)(
6466
f: (
6567
os.Path,
@@ -68,31 +70,50 @@ abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
6870
) => Future[T]
6971
): T = {
7072

71-
val root = inputs.root()
73+
def attempt(): Try[T] = Try {
74+
val root = inputs.root()
7275

73-
val proc = os.proc(TestUtil.cli, "bsp", extraOptions, args)
74-
.spawn(cwd = root)
75-
var remoteServer: b.BuildServer with b.ScalaBuildServer with b.JavaBuildServer = null
76+
val proc = os.proc(TestUtil.cli, "bsp", extraOptions, args)
77+
.spawn(cwd = root)
78+
var remoteServer: b.BuildServer with b.ScalaBuildServer with b.JavaBuildServer = null
7679

77-
try {
78-
val (localClient, remoteServer0, shutdownFuture) =
79-
TestBspClient.connect(proc.stdout, proc.stdin, pool)
80-
remoteServer = remoteServer0
81-
Await.result(remoteServer.buildInitialize(initParams(root)).asScala, 3.minutes)
82-
Await.result(f(root, localClient, remoteServer), 3.minutes)
80+
try {
81+
val (localClient, remoteServer0, shutdownFuture) =
82+
TestBspClient.connect(proc.stdout, proc.stdin, pool)
83+
remoteServer = remoteServer0
84+
Await.result(remoteServer.buildInitialize(initParams(root)).asScala, 3.minutes)
85+
Await.result(f(root, localClient, remoteServer), 3.minutes)
86+
}
87+
finally {
88+
if (remoteServer != null)
89+
try Await.result(remoteServer.buildShutdown().asScala, 20.seconds)
90+
catch {
91+
case NonFatal(e) =>
92+
System.err.println(s"Ignoring $e while shutting down BSP server")
93+
}
94+
proc.join(2.seconds.toMillis)
95+
proc.destroy()
96+
proc.join(2.seconds.toMillis)
97+
proc.destroyForcibly()
98+
}
8399
}
84-
finally {
85-
if (remoteServer != null)
86-
try Await.result(remoteServer.buildShutdown().asScala, 20.seconds)
87-
catch {
88-
case NonFatal(e) =>
89-
System.err.println(s"Ignoring $e while shutting down BSP server")
100+
101+
@tailrec
102+
def helper(count: Int): T =
103+
if (count <= 1)
104+
attempt() match {
105+
case Success(t) => t
106+
case Failure(ex) => throw new Exception(ex)
90107
}
91-
proc.join(2.seconds.toMillis)
92-
proc.destroy()
93-
proc.join(2.seconds.toMillis)
94-
proc.destroyForcibly()
95-
}
108+
else
109+
attempt() match {
110+
case Success(t) => t
111+
case Failure(ex) =>
112+
System.err.println(s"Caught $ex, trying again…")
113+
helper(count - 1)
114+
}
115+
116+
helper(attempts)
96117
}
97118

98119
def checkTargetUri(root: os.Path, uri: String): Unit = {

0 commit comments

Comments
 (0)