@@ -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 {
@@ -59,7 +60,8 @@ abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
59
60
60
61
def withBsp [T ](
61
62
inputs : TestInputs ,
62
- args : Seq [String ]
63
+ args : Seq [String ],
64
+ attempts : Int = 3
63
65
)(
64
66
f : (
65
67
os.Path ,
@@ -68,31 +70,50 @@ abstract class BspTestDefinitions(val scalaVersionOpt: Option[String])
68
70
) => Future [T ]
69
71
): T = {
70
72
71
- val root = inputs.root()
73
+ def attempt (): Try [T ] = Try {
74
+ val root = inputs.root()
72
75
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
76
79
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
+ }
83
99
}
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)
90
107
}
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)
96
117
}
97
118
98
119
def checkTargetUri (root : os.Path , uri : String ): Unit = {
0 commit comments