@@ -8,14 +8,15 @@ import java.nio.charset.Charset
8
8
import java .nio .file .Paths
9
9
import java .util .concurrent .TimeoutException
10
10
11
+ import scala .annotation .tailrec
11
12
import scala .async .Async .{async , await }
12
13
import scala .collection .JavaConverters ._
13
14
import scala .concurrent .{Await , Future , Promise }
14
15
import scala .concurrent .ExecutionContext .Implicits .global
15
16
import scala .concurrent .duration ._
16
17
import scala .io .Codec
17
18
import scala .util .control .NonFatal
18
- import scala .util .Properties
19
+ import scala .util .{ Failure , Properties , Success , Try }
19
20
20
21
abstract class BspTestDefinitions (val scalaVersionOpt : Option [String ])
21
22
extends munit.FunSuite with TestScalaVersionArgs {
@@ -58,38 +59,61 @@ abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
58
59
}
59
60
60
61
def withBsp [T ](
61
- root : os.Path ,
62
- args : Seq [String ]
62
+ inputs : TestInputs ,
63
+ args : Seq [String ],
64
+ attempts : Int = 3
63
65
)(
64
- f : (TestBspClient , b.BuildServer with b.ScalaBuildServer with b.JavaBuildServer ) => Future [T ]
66
+ f : (
67
+ os.Path ,
68
+ TestBspClient ,
69
+ b.BuildServer with b.ScalaBuildServer with b.JavaBuildServer
70
+ ) => Future [T ]
65
71
): T = {
66
72
67
- val proc = os.proc(TestUtil .cli, " bsp" , extraOptions, args)
68
- .spawn(cwd = root)
69
- var remoteServer : b.BuildServer with b.ScalaBuildServer with b.JavaBuildServer = null
70
-
71
- try {
72
- val (localClient, remoteServer0, shutdownFuture) =
73
- TestBspClient .connect(proc.stdout, proc.stdin, pool)
74
- remoteServer = remoteServer0
75
- val f0 = async {
76
- await(remoteServer.buildInitialize(initParams(root)).asScala)
77
- await(f(localClient, remoteServer))
73
+ def attempt (): Try [T ] = Try {
74
+ val root = inputs.root()
75
+
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
79
+
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()
78
98
}
79
- Await .result(f0, 3 .minutes)
80
99
}
81
- finally {
82
- if (remoteServer != null )
83
- try Await .result(remoteServer.buildShutdown().asScala, 20 .seconds)
84
- catch {
85
- case NonFatal (e) =>
86
- 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)
87
107
}
88
- proc.join(2 .seconds.toMillis)
89
- proc.destroy()
90
- proc.join(2 .seconds.toMillis)
91
- proc.destroyForcibly()
92
- }
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)
93
117
}
94
118
95
119
def checkTargetUri (root : os.Path , uri : String ): Unit = {
@@ -135,9 +159,8 @@ abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
135
159
| """ .stripMargin
136
160
)
137
161
)
138
- val root = inputs.root()
139
162
140
- withBsp(root , Seq (" ." )) { (localClient, remoteServer) =>
163
+ withBsp(inputs , Seq (" ." )) { (root, localClient, remoteServer) =>
141
164
async {
142
165
val buildTargetsResp = await(remoteServer.workspaceBuildTargets().asScala)
143
166
val target = {
@@ -263,9 +286,8 @@ abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
263
286
| """ .stripMargin
264
287
)
265
288
)
266
- val root = inputs.root()
267
289
268
- withBsp(root , Seq (" ." )) { (localClient, remoteServer) =>
290
+ withBsp(inputs , Seq (" ." )) { (root, localClient, remoteServer) =>
269
291
async {
270
292
val buildTargetsResp = await(remoteServer.workspaceBuildTargets().asScala)
271
293
val target = {
@@ -331,9 +353,8 @@ abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
331
353
| """ .stripMargin
332
354
)
333
355
)
334
- val root = inputs.root()
335
356
336
- withBsp(root , Seq (" ." )) { (localClient, remoteServer) =>
357
+ withBsp(inputs , Seq (" ." )) { (root, localClient, remoteServer) =>
337
358
async {
338
359
val buildTargetsResp = await(remoteServer.workspaceBuildTargets().asScala)
339
360
val target = {
@@ -400,12 +421,11 @@ abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
400
421
| """ .stripMargin
401
422
)
402
423
)
403
- val root = inputs.root()
404
-
405
424
val extraArgs =
406
425
if (Properties .isWin) Seq (" -v" , " -v" , " -v" )
407
426
else Nil
408
- withBsp(root, Seq (" ." ) ++ extraArgs) { (localClient, remoteServer) =>
427
+
428
+ withBsp(inputs, Seq (" ." ) ++ extraArgs) { (root, localClient, remoteServer) =>
409
429
async {
410
430
val buildTargetsResp = await(remoteServer.workspaceBuildTargets().asScala)
411
431
val target = {
@@ -518,9 +538,8 @@ abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
518
538
| """ .stripMargin
519
539
)
520
540
)
521
- val root = inputs.root()
522
541
523
- withBsp(root , Seq (" ." )) { (localClient, remoteServer) =>
542
+ withBsp(inputs , Seq (" ." )) { (root, localClient, remoteServer) =>
524
543
async {
525
544
val buildTargetsResp = await(remoteServer.workspaceBuildTargets().asScala)
526
545
val target = {
0 commit comments