Skip to content

Commit 7910520

Browse files
committed
SKCore,SKTestSupport: adjust test server handling
The test system depended on the shebang to locate the python interpreter. However, this is not a portable system. Instead, prefer to explicitly search for the interpreter prior to the execution. This enables supporting execution of the script support on all platforms. A secondary change of the printed string is required for Windows. Python will replace `\n` with `\r\n` resulting in `\r\n` being emitted as `\r\r\n` on Windows breaking the expectations on the receiver. Adjust this by explicitly writing out a binary string to the raw underlying buffer to avoid the translation.
1 parent d4c6e2c commit 7910520

File tree

8 files changed

+43
-26
lines changed
  • Sources

8 files changed

+43
-26
lines changed

Sources/SKCore/BuildServerBuildSystem.swift

Lines changed: 36 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@ import LSPLogging
1818
import SKSupport
1919
import TSCBasic
2020

21+
enum BuildServerTestError: Error {
22+
case executableNotFound(String)
23+
}
24+
25+
func executable(_ name: String) -> String {
26+
#if os(Windows)
27+
guard !name.hasSuffix(".exe") else { return name }
28+
return "\(name).exe"
29+
#else
30+
return name
31+
#endif
32+
}
33+
34+
2135
/// A `BuildSystem` based on communicating with a build server
2236
///
2337
/// Provides build settings from a build server launched based on a
@@ -32,6 +46,8 @@ public final class BuildServerBuildSystem {
3246
var handler: BuildServerHandler?
3347
var buildServer: JSONRPCConnection?
3448

49+
let searchPaths: [AbsolutePath]
50+
3551
public private(set) var indexDatabasePath: AbsolutePath?
3652
public private(set) var indexStorePath: AbsolutePath?
3753

@@ -47,6 +63,15 @@ public final class BuildServerBuildSystem {
4763
public init(projectRoot: AbsolutePath, buildFolder: AbsolutePath?, fileSystem: FileSystem = localFileSystem) throws {
4864
let configPath = projectRoot.appending(component: "buildServer.json")
4965
let config = try loadBuildServerConfig(path: configPath, fileSystem: fileSystem)
66+
#if os(Windows)
67+
self.searchPaths =
68+
getEnvSearchPaths(pathString: ProcessInfo.processInfo.environment["Path"],
69+
currentWorkingDirectory: fileSystem.currentWorkingDirectory)
70+
#else
71+
self.searchPaths =
72+
getEnvSearchPaths(pathString: ProcessInfo.processInfo.environment["PATH"],
73+
currentWorkingDirectory: fileSystem.currentWorkingDirectory)
74+
#endif
5075
self.buildFolder = buildFolder
5176
self.projectRoot = projectRoot
5277
self.requestQueue = DispatchQueue(label: "build_server_request_queue")
@@ -85,8 +110,14 @@ public final class BuildServerBuildSystem {
85110
}
86111

87112
private func initializeBuildServer() throws {
88-
let serverPath = AbsolutePath(serverConfig.argv[0], relativeTo: projectRoot)
89-
let flags = Array(serverConfig.argv[1...])
113+
guard let interpreter =
114+
lookupExecutablePath(filename: executable("python3"),
115+
searchPaths: searchPaths) ??
116+
lookupExecutablePath(filename: executable("python"),
117+
searchPaths: searchPaths) else {
118+
throw BuildServerTestError.executableNotFound("python3")
119+
}
120+
let flags = [AbsolutePath(serverConfig.argv[0], relativeTo: projectRoot).pathString] + Array(serverConfig.argv[1...])
90121
let languages = [
91122
Language.c,
92123
Language.cpp,
@@ -103,7 +134,7 @@ public final class BuildServerBuildSystem {
103134
capabilities: BuildClientCapabilities(languageIds: languages))
104135

105136
let handler = BuildServerHandler()
106-
let buildServer = try makeJSONRPCBuildServer(client: handler, serverPath: serverPath, serverFlags: flags)
137+
let buildServer = try makeJSONRPCBuildServer(client: handler, interpreter: interpreter, serverFlags: flags)
107138
let response = try buildServer.sendSync(initializeRequest)
108139
buildServer.send(InitializedBuildNotification())
109140
log("initialized build server \(response.displayName)")
@@ -269,7 +300,7 @@ struct BuildServerConfig: Codable {
269300
let argv: [String]
270301
}
271302

272-
private func makeJSONRPCBuildServer(client: MessageHandler, serverPath: AbsolutePath, serverFlags: [String]?) throws -> JSONRPCConnection {
303+
private func makeJSONRPCBuildServer(client: MessageHandler, interpreter: AbsolutePath, serverFlags: [String]?) throws -> JSONRPCConnection {
273304
let clientToServer = Pipe()
274305
let serverToClient = Pipe()
275306

@@ -285,7 +316,7 @@ private func makeJSONRPCBuildServer(client: MessageHandler, serverPath: Absolute
285316
withExtendedLifetime((clientToServer, serverToClient)) {}
286317
}
287318
let process = Foundation.Process()
288-
process.executableURL = serverPath.asURL
319+
process.executableURL = interpreter.asURL
289320
process.arguments = serverFlags
290321
process.standardOutput = serverToClient
291322
process.standardInput = clientToServer

Sources/SKTestSupport/INPUTS/BuildServerBuildSystemTests.testBuildTargetOutputs/server.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env python3
2-
31
import json
42
import sys
53

@@ -70,7 +68,7 @@
7068
if response:
7169
responseStr = json.dumps(response)
7270
try:
73-
sys.stdout.write("Content-Length: {}\r\n\r\n{}".format(len(responseStr), responseStr))
71+
sys.stdout.buffer.write(f"Content-Length: {len(responseStr)}\r\n\r\n{responseStr}".encode('utf-8'))
7472
sys.stdout.flush()
7573
except IOError:
7674
# stdout closed, time to quit

Sources/SKTestSupport/INPUTS/BuildServerBuildSystemTests.testBuildTargetSources/server.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env python3
2-
31
import json
42
import sys
53

@@ -93,7 +91,7 @@
9391
if response:
9492
responseStr = json.dumps(response)
9593
try:
96-
sys.stdout.write("Content-Length: {}\r\n\r\n{}".format(len(responseStr), responseStr))
94+
sys.stdout.buffer.write(f"Content-Length: {len(responseStr)}\r\n\r\n{responseStr}".encode('utf-8'))
9795
sys.stdout.flush()
9896
except IOError:
9997
# stdout closed, time to quit

Sources/SKTestSupport/INPUTS/BuildServerBuildSystemTests.testBuildTargets/server.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env python3
2-
31
import json
42
import sys
53

@@ -89,7 +87,7 @@
8987
if response:
9088
responseStr = json.dumps(response)
9189
try:
92-
sys.stdout.write("Content-Length: {}\r\n\r\n{}".format(len(responseStr), responseStr))
90+
sys.stdout.buffer.write(f"Content-Length: {len(responseStr)}\r\n\r\n{responseStr}".encode('utf-8'))
9391
sys.stdout.flush()
9492
except IOError:
9593
# stdout closed, time to quit

Sources/SKTestSupport/INPUTS/BuildServerBuildSystemTests.testBuildTargetsChanged/server.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env python3
2-
31
import json
42
import os
53
import sys
@@ -8,7 +6,7 @@
86
def send(data):
97
dataStr = json.dumps(data)
108
try:
11-
sys.stdout.write("Content-Length: {}\r\n\r\n{}".format(len(dataStr), dataStr))
9+
sys.stdout.buffer.write(f"Content-Length: {len(dataStr)}\r\n\r\n{dataStr}".encode('utf-8'))
1210
sys.stdout.flush()
1311
except IOError:
1412
# stdout closed, time to quit

Sources/SKTestSupport/INPUTS/BuildServerBuildSystemTests.testFileRegistration/server.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env python3
2-
31
import json
42
import os
53
import sys
@@ -8,7 +6,7 @@
86
def send(data):
97
dataStr = json.dumps(data)
108
try:
11-
sys.stdout.write("Content-Length: {}\r\n\r\n{}".format(len(dataStr), dataStr))
9+
sys.stdout.buffer.write(f"Content-Length: {len(dataStr)}\r\n\r\n{dataStr}".encode('utf-8'))
1210
sys.stdout.flush()
1311
except IOError:
1412
# stdout closed, time to quit

Sources/SKTestSupport/INPUTS/BuildServerBuildSystemTests.testServerInitialize/server.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env python3
2-
31
import json
42
import sys
53

@@ -55,7 +53,7 @@
5553
if response:
5654
responseStr = json.dumps(response)
5755
try:
58-
sys.stdout.write("Content-Length: {}\r\n\r\n{}".format(len(responseStr), responseStr))
56+
sys.stdout.buffer.write(f"Content-Length: {len(responseStr)}\r\n\r\n{responseStr}".encode('utf-8'))
5957
sys.stdout.flush()
6058
except IOError:
6159
# stdout closed, time to quit

Sources/SKTestSupport/INPUTS/BuildServerBuildSystemTests.testSettings/server.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
#!/usr/bin/env python3
2-
31
import json
42
import os
53
import sys
@@ -76,7 +74,7 @@
7674
if response:
7775
responseStr = json.dumps(response)
7876
try:
79-
sys.stdout.write("Content-Length: {}\r\n\r\n{}".format(len(responseStr), responseStr))
77+
sys.stdout.buffer.write(f"Content-Length: {len(responseStr)}\r\n\r\n{responseStr}".encode('utf-8'))
8078
sys.stdout.flush()
8179
except IOError:
8280
# stdout closed, time to quit

0 commit comments

Comments
 (0)