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
]

Tests/BuildSystemIntegrationTests/FallbackBuildSettingsTests.swift

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ import struct PackageModel.BuildFlags
2222
final class FallbackBuildSystemTests: XCTestCase {
2323

2424
func testSwift() throws {
25-
let sdk = "/my/sdk"
25+
let sdk = try AbsolutePath(validating: "/my/sdk").pathString
2626
let source = DocumentURI(filePath: "/my/source.swift", isDirectory: false)
2727

2828
XCTAssertEqual(
@@ -32,7 +32,7 @@ final class FallbackBuildSystemTests: XCTestCase {
3232
}
3333

3434
func testSwiftWithCustomFlags() throws {
35-
let sdk = "/my/sdk"
35+
let sdk = try AbsolutePath(validating: "/my/sdk").pathString
3636
let source = DocumentURI(filePath: "/my/source.swift", isDirectory: false)
3737

3838
let options = SourceKitLSPOptions.FallbackBuildSystemOptions(
@@ -49,7 +49,7 @@ final class FallbackBuildSystemTests: XCTestCase {
4949
}
5050

5151
func testSwiftWithCustomSDKFlag() throws {
52-
let sdk = "/my/sdk"
52+
let sdk = try AbsolutePath(validating: "/my/sdk").pathString
5353
let source = DocumentURI(filePath: "/my/source.swift", isDirectory: false)
5454

5555
let options = SourceKitLSPOptions.FallbackBuildSystemOptions(
@@ -63,7 +63,7 @@ final class FallbackBuildSystemTests: XCTestCase {
6363
}
6464

6565
func testCXX() throws {
66-
let sdk = "/my/sdk"
66+
let sdk = try AbsolutePath(validating: "/my/sdk").pathString
6767
let source = DocumentURI(filePath: "/my/source.cpp", isDirectory: false)
6868

6969
XCTAssertEqual(
@@ -77,7 +77,7 @@ final class FallbackBuildSystemTests: XCTestCase {
7777
}
7878

7979
func testCXXWithCustomFlags() throws {
80-
let sdk = "/my/sdk"
80+
let sdk = try AbsolutePath(validating: "/my/sdk").pathString
8181
let source = DocumentURI(filePath: "/my/source.cpp", isDirectory: false)
8282

8383
let options = SourceKitLSPOptions.FallbackBuildSystemOptions(
@@ -92,7 +92,7 @@ final class FallbackBuildSystemTests: XCTestCase {
9292
}
9393

9494
func testCXXWithCustomIsysroot() throws {
95-
let sdk = "/my/sdk"
95+
let sdk = try AbsolutePath(validating: "/my/sdk").pathString
9696
let source = DocumentURI(filePath: "/my/source.cpp", isDirectory: false)
9797

9898
let options = SourceKitLSPOptions.FallbackBuildSystemOptions(
@@ -111,7 +111,7 @@ final class FallbackBuildSystemTests: XCTestCase {
111111
}
112112

113113
func testC() throws {
114-
let sdk = "/my/sdk"
114+
let sdk = try AbsolutePath(validating: "/my/sdk").pathString
115115
let source = DocumentURI(filePath: "/my/source.c", isDirectory: false)
116116

117117
XCTAssertEqual(
@@ -121,7 +121,7 @@ final class FallbackBuildSystemTests: XCTestCase {
121121
}
122122

123123
func testCWithCustomFlags() throws {
124-
let sdk = "/my/sdk"
124+
let sdk = try AbsolutePath(validating: "/my/sdk").pathString
125125
let source = DocumentURI(filePath: "/my/source.c", isDirectory: false)
126126

127127
let options = SourceKitLSPOptions.FallbackBuildSystemOptions(
@@ -136,7 +136,7 @@ final class FallbackBuildSystemTests: XCTestCase {
136136
}
137137

138138
func testObjC() throws {
139-
let sdk = "/my/sdk"
139+
let sdk = try AbsolutePath(validating: "/my/sdk").pathString
140140
let source = DocumentURI(filePath: "/my/source.m", isDirectory: false)
141141

142142
XCTAssertEqual(
@@ -146,7 +146,7 @@ final class FallbackBuildSystemTests: XCTestCase {
146146
}
147147

148148
func testObjCXX() throws {
149-
let sdk = "/my/sdk"
149+
let sdk = try AbsolutePath(validating: "/my/sdk").pathString
150150
let source = DocumentURI(filePath: "/my/source.mm", isDirectory: false)
151151

152152
XCTAssertEqual(

Tests/BuildSystemIntegrationTests/SwiftPMBuildSystemTests.swift

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ final class SwiftPMBuildSystemTests: XCTestCase {
169169
""",
170170
]
171171
)
172-
let packageRoot = try resolveSymlinks(tempDir.appending(component: "pkg"))
172+
let packageRoot = try AbsolutePath(validating: tempDir.appending(component: "pkg").asURL.realpath.path)
173173
let buildSystemManager = await BuildSystemManager(
174174
buildSystemKind: .swiftPM(projectRoot: packageRoot),
175175
toolchainRegistry: .forTesting,
@@ -182,9 +182,15 @@ final class SwiftPMBuildSystemTests: XCTestCase {
182182
let aPlusSomething = packageRoot.appending(components: "Sources", "lib", "a+something.swift")
183183

184184
assertNotNil(await buildSystemManager.initializationData?.indexStorePath)
185+
let pathWithPlusEscaped = "\(aPlusSomething.asURL.path.replacing("+", with: "%2B"))"
186+
#if os(Windows)
187+
let urlWithPlusEscaped = try XCTUnwrap(URL(string: "file:///\(pathWithPlusEscaped)"))
188+
#else
189+
let urlWithPlusEscaped = try XCTUnwrap(URL(string: "file://\(pathWithPlusEscaped)"))
190+
#endif
185191
let arguments = try await unwrap(
186192
buildSystemManager.buildSettingsInferredFromMainFile(
187-
for: DocumentURI(URL(string: "file://\(aPlusSomething.asURL.path.replacing("+", with: "%2B"))")!),
193+
for: DocumentURI(urlWithPlusEscaped),
188194
language: .swift
189195
)
190196
)
@@ -787,6 +793,10 @@ final class SwiftPMBuildSystemTests: XCTestCase {
787793
}
788794

789795
func testPluginArgs() async throws {
796+
#if os(Windows)
797+
// TODO: Enable this test once https://github.com/swiftlang/swift-foundation/issues/973 is fixed
798+
try XCTSkipIf(true, "https://github.com/swiftlang/swift-foundation/issues/973")
799+
#endif
790800
try await withTestScratchDir { tempDir in
791801
try localFileSystem.createFiles(
792802
root: tempDir,

Tests/DiagnoseTests/DiagnoseTests.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ import struct TSCBasic.AbsolutePath
2525
private let sdkArg: String = {
2626
if let sdk = defaultSDKPath {
2727
return """
28-
"-sdk", "\(sdk)",
28+
"-sdk", "\(sdk.replacing(#"\"#, with: #"\\"#))"
2929
"""
3030
} else {
3131
return ""
@@ -36,7 +36,7 @@ private let sdkArg: String = {
3636
/// YAML. Otherwise, return an empty string.
3737
private let sdkArgs: [String] = {
3838
if let sdk = defaultSDKPath {
39-
return ["-sdk", "\(sdk)"]
39+
return ["-sdk", sdk]
4040
} else {
4141
return []
4242
}
@@ -254,7 +254,7 @@ private func assertReduceSourceKitD(
254254

255255
let request =
256256
request
257-
.replacingOccurrences(of: "$FILE", with: testFilePath)
257+
.replacingOccurrences(of: "$FILE", with: testFilePath.replacing(#"\"#, with: #"\\"#))
258258
.replacingOccurrences(of: "$OFFSET", with: String(markerOffset))
259259

260260
let requestInfo = try RequestInfo(request: request)

0 commit comments

Comments
 (0)