Skip to content

Commit c16e33d

Browse files
committed
Miscellaneous adjustments to make tests pass on Windows
This is mostly test infrastructure that needed adjusting.
1 parent aa0aa92 commit c16e33d

19 files changed

+161
-68
lines changed

Sources/BuildSystemIntegration/CompilationDatabase.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ import struct TSCBasic.RelativePath
3434
import var TSCBasic.localFileSystem
3535
#endif
3636

37+
#if os(Windows)
38+
import WinSDK
39+
#endif
40+
3741
/// A single compilation database command.
3842
///
3943
/// See https://clang.llvm.org/docs/JSONCompilationDatabase.html
@@ -97,7 +101,7 @@ package struct CompilationDatabaseCompileCommand: Equatable, Codable {
97101
/// it falls back to `filename`, which is more likely to be the identifier
98102
/// that a caller will be looking for.
99103
package var uri: DocumentURI {
100-
if filename.hasPrefix("/") || !directory.hasPrefix("/") {
104+
if filename.isAbsolutePath || !directory.isAbsolutePath {
101105
return DocumentURI(filePath: filename, isDirectory: false)
102106
} else {
103107
return DocumentURI(URL(fileURLWithPath: directory).appendingPathComponent(filename, isDirectory: false))
@@ -288,3 +292,15 @@ enum CompilationDatabaseDecodingError: Error {
288292
case missingCommandOrArguments
289293
case fixedDatabaseDecodingError
290294
}
295+
296+
fileprivate extension String {
297+
var isAbsolutePath: Bool {
298+
#if os(Windows)
299+
Array(self.utf16).withUnsafeBufferPointer { buffer in
300+
return !PathIsRelativeW(buffer.baseAddress)
301+
}
302+
#else
303+
return self.hasPrefix("/")
304+
#endif
305+
}
306+
}

Sources/SKSupport/DocumentURI+symlinkTarget.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ extension DocumentURI {
2727
guard let fileUrl = fileURL else {
2828
return nil
2929
}
30-
let realpath = fileUrl.realpath
31-
if realpath == fileURL {
30+
let realpath = DocumentURI(fileUrl.realpath)
31+
if realpath == self {
3232
return nil
3333
}
34-
return DocumentURI(realpath)
34+
return realpath
3535
}
3636
}

Sources/SKTestSupport/BuildServerTestProject.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import XCTest
1717
fileprivate let sdkArgs =
1818
if let defaultSDKPath {
1919
"""
20-
"-sdk", "\(defaultSDKPath)",
20+
"-sdk", "\(defaultSDKPath.replacing(#"\"#, with: #"\\"#))",
2121
"""
2222
} else {
2323
""

Sources/SKTestSupport/FindTool.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,14 @@ package func findTool(name: String) async -> URL? {
4848
return nil
4949
}
5050
#if os(Windows)
51-
path = String((path.split { $0.isNewline })[0])
51+
// where.exe returns all files that match the name. We only care about the first one.
52+
if let newlineIndex = path.firstIndex(where: \.isNewline) {
53+
path = String(path[..<newlineIndex])
54+
}
5255
#endif
5356
path = path.trimmingCharacters(in: .whitespacesAndNewlines)
57+
if path.isEmpty {
58+
return nil
59+
}
5460
return URL(fileURLWithPath: path, isDirectory: false)
5561
}

Sources/SKTestSupport/IndexedSingleSwiftFileTestProject.swift

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,19 @@ package struct IndexedSingleSwiftFileTestProject {
8787

8888
// The following are needed so we can import XCTest
8989
let sdkUrl = URL(fileURLWithPath: sdk)
90+
#if os(Windows)
91+
let xctestModuleDir =
92+
sdkUrl
93+
.deletingLastPathComponent()
94+
.deletingLastPathComponent()
95+
.appendingPathComponent("Library")
96+
.appendingPathComponent("XCTest-development")
97+
.appendingPathComponent("usr")
98+
.appendingPathComponent("lib")
99+
.appendingPathComponent("swift")
100+
.appendingPathComponent("windows")
101+
compilerArguments += ["-I", xctestModuleDir.path]
102+
#else
90103
let usrLibDir =
91104
sdkUrl
92105
.deletingLastPathComponent()
@@ -103,6 +116,7 @@ package struct IndexedSingleSwiftFileTestProject {
103116
"-I", usrLibDir.path,
104117
"-F", frameworksDir.path,
105118
]
119+
#endif
106120
}
107121

108122
let compilationDatabase = JSONCompilationDatabase(

Sources/SKTestSupport/MultiFileTestProject.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,10 @@ package class MultiFileTestProject {
102102

103103
var fileData: [String: FileData] = [:]
104104
for (fileLocation, markedText) in files {
105-
let markedText = markedText.replacingOccurrences(of: "$TEST_DIR", with: scratchDirectory.path)
105+
let markedText =
106+
markedText
107+
.replacingOccurrences(of: "$TEST_DIR_URL", with: scratchDirectory.absoluteString)
108+
.replacingOccurrences(of: "$TEST_DIR", with: scratchDirectory.path)
106109
let fileURL = fileLocation.url(relativeTo: scratchDirectory)
107110
try FileManager.default.createDirectory(
108111
at: fileURL.deletingLastPathComponent(),

Sources/SKTestSupport/Utils.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,17 @@ package func testScratchDir(testName: String = #function) throws -> URL {
6868
if let firstDash = uuid.firstIndex(of: "-") {
6969
uuid = uuid[..<firstDash]
7070
}
71-
let url = FileManager.default.temporaryDirectory
72-
.realpath
71+
// Including the test name in the directory frequently makes path lengths of test files exceed the maximum path length
72+
// on Windows. Choose shorter directory names on that platform to avoid that issue.
73+
#if os(Windows)
74+
let url = FileManager.default.temporaryDirectory.realpath
75+
.appendingPathComponent("lsp-test")
76+
.appendingPathComponent("\(uuid)")
77+
#else
78+
let url = FileManager.default.temporaryDirectory.realpath
7379
.appendingPathComponent("sourcekit-lsp-test-scratch")
7480
.appendingPathComponent("\(testBaseName)-\(uuid)")
81+
#endif
7582
try? FileManager.default.removeItem(at: url)
7683
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: true)
7784
return url

Sources/SourceKitLSP/Clang/ClangLanguageService.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ actor ClangLanguageService: LanguageService, MessageHandler {
326326
// safer, can also indefinitely hang as `CreateRemoteThread` may not be serviced depending on the state of
327327
// the process. This just attempts to terminate the process, risking a deadlock and resource leaks, which is fine
328328
// since we only use `crash` from tests.
329-
_ = TerminateProcess(self.hClangd, 0)
329+
_ = TerminateProcess(self.hClangd, 255)
330330
}
331331
#else
332332
if let pid = self.clangdPid {

Tests/BuildSystemIntegrationTests/BuildServerBuildSystemTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ final class BuildServerBuildSystemTests: XCTestCase {
5353
{
5454
"target": {"uri": "bsp://dummy"},
5555
"sources": [
56-
{"uri": "file://$TEST_DIR/Test.swift", "kind": 1, "generated": False}
56+
{"uri": "$TEST_DIR_URL/Test.swift", "kind": 1, "generated": False}
5757
],
5858
}
5959
]
@@ -123,7 +123,7 @@ final class BuildServerBuildSystemTests: XCTestCase {
123123
{
124124
"target": {"uri": "bsp://dummy"},
125125
"sources": [
126-
{"uri": "file://$TEST_DIR/Test.swift", "kind": 1, "generated": False}
126+
{"uri": "$TEST_DIR_URL/Test.swift", "kind": 1, "generated": False}
127127
],
128128
}
129129
]
@@ -197,7 +197,7 @@ final class BuildServerBuildSystemTests: XCTestCase {
197197
{
198198
"target": {"uri": "bsp://dummy"},
199199
"sources": [
200-
{"uri": "file://$TEST_DIR/Test.swift", "kind": 1, "generated": False}
200+
{"uri": "$TEST_DIR_URL/Test.swift", "kind": 1, "generated": False}
201201
],
202202
}
203203
]
@@ -273,8 +273,8 @@ final class BuildServerBuildSystemTests: XCTestCase {
273273
{
274274
"target": {"uri": "bsp://dummy"},
275275
"sources": [
276-
{"uri": "file://$TEST_DIR/Crash.swift", "kind": 1, "generated": False},
277-
{"uri": "file://$TEST_DIR/Test.swift", "kind": 1, "generated": False},
276+
{"uri": "$TEST_DIR_URL/Crash.swift", "kind": 1, "generated": False},
277+
{"uri": "$TEST_DIR_URL/Test.swift", "kind": 1, "generated": False},
278278
],
279279
}
280280
]

Tests/BuildSystemIntegrationTests/CompilationDatabaseTests.swift

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -152,16 +152,27 @@ final class CompilationDatabaseTests: XCTestCase {
152152
)
153153
}
154154

155-
func testJSONCompilationDatabaseLookup() {
155+
func testJSONCompilationDatabaseLookup() throws {
156+
#if os(Windows)
157+
let fileSystemRoot = "c:/"
158+
#else
159+
let fileSystemRoot = "/"
160+
#endif
161+
156162
let cmd1 = CompilationDatabase.Command(directory: "a", filename: "b", commandLine: [], output: nil)
157-
let cmd2 = CompilationDatabase.Command(directory: "/c", filename: "b", commandLine: [], output: nil)
158-
let cmd3 = CompilationDatabase.Command(directory: "/c", filename: "/b", commandLine: [], output: nil)
163+
let cmd2 = CompilationDatabase.Command(directory: "\(fileSystemRoot)c", filename: "b", commandLine: [], output: nil)
164+
let cmd3 = CompilationDatabase.Command(
165+
directory: "\(fileSystemRoot)c",
166+
filename: "\(fileSystemRoot)b",
167+
commandLine: [],
168+
output: nil
169+
)
159170

160171
let db = JSONCompilationDatabase([cmd1, cmd2, cmd3])
161172

162173
XCTAssertEqual(db[DocumentURI(filePath: "b", isDirectory: false)], [cmd1])
163-
XCTAssertEqual(db[DocumentURI(filePath: "/c/b", isDirectory: false)], [cmd2])
164-
XCTAssertEqual(db[DocumentURI(filePath: "/b", isDirectory: false)], [cmd3])
174+
XCTAssertEqual(db[DocumentURI(filePath: "\(fileSystemRoot)c/b", isDirectory: false)], [cmd2])
175+
XCTAssertEqual(db[DocumentURI(filePath: "\(fileSystemRoot)b", isDirectory: false)], [cmd3])
165176
}
166177

167178
func testJSONCompilationDatabaseFromDirectory() throws {
@@ -250,19 +261,16 @@ final class CompilationDatabaseTests: XCTestCase {
250261
"""
251262
)
252263

253-
let db = try tryLoadCompilationDatabase(
254-
directory: AbsolutePath(validating: "/a"),
255-
fs
256-
)
257-
XCTAssertNotNil(db)
264+
let db = try XCTUnwrap(tryLoadCompilationDatabase(directory: AbsolutePath(validating: "/a"), fs))
258265

266+
// Note: Use `AbsolutePath(validating:).pathString` to normalize forward slashes to backslashes on Windows
259267
XCTAssertEqual(
260-
db![DocumentURI(filePath: "/a/b", isDirectory: false)],
268+
db[DocumentURI(filePath: "/a/b", isDirectory: false)],
261269
[
262270
CompilationDatabase.Command(
263271
directory: try AbsolutePath(validating: "/a").pathString,
264-
filename: "/a/b",
265-
commandLine: ["clang", "-xc++", "-I", "libwidget/include/", "/a/b"],
272+
filename: try AbsolutePath(validating: "/a/b").pathString,
273+
commandLine: ["clang", "-xc++", "-I", "libwidget/include/", try AbsolutePath(validating: "/a/b").pathString],
266274
output: nil
267275
)
268276
]

0 commit comments

Comments
 (0)