Skip to content

Commit 0667405

Browse files
authored
Merge pull request #156 from Adyen/fix-swiftmodule-path-resolution
Correctly generating swiftmodule path
2 parents 3b73dbb + 9d1fc99 commit 0667405

3 files changed

Lines changed: 257 additions & 18 deletions

File tree

Sources/Shared/Public/PADSwiftInterfaceFileLocator/SwiftInterfaceFileLocator.swift

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,37 +49,32 @@ public struct SwiftInterfaceFileLocator {
4949

5050
let swiftModulePathsForScheme = shell.execute("cd '\(derivedDataPath)'; find . -type d -name '\(schemeSwiftModuleName)'")
5151
.components(separatedBy: .newlines)
52-
.map { URL(filePath: $0) }
52+
.map { URL(filePath: derivedDataPath).appending(path: $0) }
5353

5454
guard let swiftModulePath = swiftModulePathsForScheme.first?.path() else {
5555
throw FileHandlerError.pathDoesNotExist(path: "find . -type d -name '\(schemeSwiftModuleName)'")
5656
}
5757

58-
let completeSwiftModulePath = derivedDataPath + "/" + swiftModulePath
59-
60-
let swiftModuleContent = try fileHandler.contentsOfDirectory(atPath: completeSwiftModulePath)
58+
let swiftModuleContent = try fileHandler.contentsOfDirectory(atPath: swiftModulePath)
6159

6260
let swiftInterfacePaths: [String]
6361
switch type {
64-
case .private:
65-
swiftInterfacePaths = swiftModuleContent.filter { $0.hasSuffix(".private.swiftinterface") }
66-
case .package:
67-
swiftInterfacePaths = swiftModuleContent.filter { $0.hasSuffix(".package.swiftinterface") }
62+
case .private, .package:
63+
swiftInterfacePaths = swiftModuleContent.filter { $0.hasSuffix(".\(type.fileExtension)") }
6864
case .public:
69-
swiftInterfacePaths = swiftModuleContent.filter { $0.hasSuffix(".swiftinterface") && !$0.hasSuffix(".private.swiftinterface") && !$0.hasSuffix(".package.swiftinterface") }
65+
swiftInterfacePaths = swiftModuleContent.filter {
66+
$0.hasSuffix(".\(SwiftInterfaceType.public.fileExtension)") &&
67+
!$0.hasSuffix(".\(SwiftInterfaceType.private.fileExtension)") &&
68+
!$0.hasSuffix(".\(SwiftInterfaceType.package.fileExtension)")
69+
}
7070
}
7171

7272
guard let swiftInterfacePath = swiftInterfacePaths.first else {
73-
switch type {
74-
case .private:
75-
throw FileHandlerError.pathDoesNotExist(path: "'\(completeSwiftModulePath)/\(scheme).private.swiftinterface'")
76-
case .package:
77-
throw FileHandlerError.pathDoesNotExist(path: "'\(completeSwiftModulePath)/\(scheme).package.swiftinterface'")
78-
case .public:
79-
throw FileHandlerError.pathDoesNotExist(path: "'\(completeSwiftModulePath)/\(scheme).swiftinterface'")
80-
}
73+
throw FileHandlerError.pathDoesNotExist(
74+
path: "'\(swiftModulePath)/\(scheme).\(type.fileExtension)'"
75+
)
8176
}
8277

83-
return URL(filePath: "\(completeSwiftModulePath)/\(swiftInterfacePath)")
78+
return URL(filePath: swiftModulePath).appending(path: swiftInterfacePath)
8479
}
8580
}

Sources/Shared/Public/PADSwiftInterfaceFileLocator/SwiftInterfaceType.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,12 @@ public enum SwiftInterfaceType {
1919
case .package: "package"
2020
}
2121
}
22+
23+
var fileExtension: String {
24+
switch self {
25+
case .private: "private.swiftinterface"
26+
case .public: "swiftinterface"
27+
case .package: "package.swiftinterface"
28+
}
29+
}
2230
}
Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
//
2+
// Copyright (c) 2024 Adyen N.V.
3+
//
4+
// This file is open source and available under the MIT license. See the LICENSE file for more info.
5+
//
6+
7+
@testable import FileHandlingModule
8+
@testable import PADSwiftInterfaceFileLocator
9+
import XCTest
10+
11+
class SwiftInterfaceFileLocatorTests: XCTestCase {
12+
13+
func test_locate_public_swiftinterface() throws {
14+
let scheme = "MyModule"
15+
let derivedDataPath = "/path/to/derived/data"
16+
let findResult = "./Build/Products/MyModule.swiftmodule"
17+
18+
var mockShell = MockShell()
19+
mockShell.handleExecute = { command in
20+
XCTAssertEqual(command, "cd '\(derivedDataPath)'; find . -type d -name '\(scheme).swiftmodule'")
21+
return findResult
22+
}
23+
24+
var mockFileHandler = MockFileHandler()
25+
mockFileHandler.handleContentsOfDirectory = { path in
26+
XCTAssertEqual(path, "/path/to/derived/data/./Build/Products/MyModule.swiftmodule")
27+
return [
28+
"arm64-apple-ios.swiftinterface",
29+
"arm64-apple-ios.private.swiftinterface",
30+
"x86_64-apple-ios-simulator.swiftinterface"
31+
]
32+
}
33+
34+
let locator = SwiftInterfaceFileLocator(
35+
fileHandler: mockFileHandler,
36+
shell: mockShell,
37+
logger: nil
38+
)
39+
40+
let result = try locator.locate(for: scheme, derivedDataPath: derivedDataPath, type: .public)
41+
42+
XCTAssertEqual(
43+
result.path(),
44+
"/path/to/derived/data/./Build/Products/MyModule.swiftmodule/arm64-apple-ios.swiftinterface"
45+
)
46+
}
47+
48+
func test_locate_private_swiftinterface() throws {
49+
let scheme = "MyModule"
50+
let derivedDataPath = "/path/to/derived/data"
51+
let findResult = "./Build/Products/MyModule.swiftmodule"
52+
53+
var mockShell = MockShell()
54+
mockShell.handleExecute = { _ in findResult }
55+
56+
var mockFileHandler = MockFileHandler()
57+
mockFileHandler.handleContentsOfDirectory = { _ in
58+
[
59+
"arm64-apple-ios.swiftinterface",
60+
"arm64-apple-ios.private.swiftinterface",
61+
"x86_64-apple-ios-simulator.private.swiftinterface"
62+
]
63+
}
64+
65+
let locator = SwiftInterfaceFileLocator(
66+
fileHandler: mockFileHandler,
67+
shell: mockShell,
68+
logger: nil
69+
)
70+
71+
let result = try locator.locate(for: scheme, derivedDataPath: derivedDataPath, type: .private)
72+
73+
XCTAssertEqual(
74+
result.path(),
75+
"/path/to/derived/data/./Build/Products/MyModule.swiftmodule/arm64-apple-ios.private.swiftinterface"
76+
)
77+
}
78+
79+
func test_locate_package_swiftinterface() throws {
80+
let scheme = "MyModule"
81+
let derivedDataPath = "/path/to/derived/data"
82+
let findResult = "./Build/Products/MyModule.swiftmodule"
83+
84+
var mockShell = MockShell()
85+
mockShell.handleExecute = { _ in findResult }
86+
87+
var mockFileHandler = MockFileHandler()
88+
mockFileHandler.handleContentsOfDirectory = { _ in
89+
[
90+
"arm64-apple-ios.swiftinterface",
91+
"arm64-apple-ios.package.swiftinterface",
92+
"x86_64-apple-ios-simulator.package.swiftinterface"
93+
]
94+
}
95+
96+
let locator = SwiftInterfaceFileLocator(
97+
fileHandler: mockFileHandler,
98+
shell: mockShell,
99+
logger: nil
100+
)
101+
102+
let result = try locator.locate(for: scheme, derivedDataPath: derivedDataPath, type: .package)
103+
104+
XCTAssertEqual(
105+
result.path(),
106+
"/path/to/derived/data/./Build/Products/MyModule.swiftmodule/arm64-apple-ios.package.swiftinterface"
107+
)
108+
}
109+
110+
func test_locate_withTrailingSlashInDerivedDataPath() throws {
111+
let scheme = "MyModule"
112+
let derivedDataPath = "/path/to/derived/data/"
113+
let findResult = "./Build/Products/MyModule.swiftmodule"
114+
115+
var mockShell = MockShell()
116+
mockShell.handleExecute = { _ in findResult }
117+
118+
var mockFileHandler = MockFileHandler()
119+
mockFileHandler.handleContentsOfDirectory = { path in
120+
XCTAssertFalse(path.contains("//"), "Path should not contain double slashes: \(path)")
121+
return ["arm64-apple-ios.swiftinterface"]
122+
}
123+
124+
let locator = SwiftInterfaceFileLocator(
125+
fileHandler: mockFileHandler,
126+
shell: mockShell,
127+
logger: nil
128+
)
129+
130+
let result = try locator.locate(for: scheme, derivedDataPath: derivedDataPath, type: .public)
131+
132+
let resultPath = result.path()
133+
XCTAssertFalse(resultPath.contains("//"), "Result path should not contain double slashes: \(resultPath)")
134+
}
135+
136+
func test_locate_pathConstructionWithoutTrailingSlash() throws {
137+
let scheme = "MyModule"
138+
let derivedDataPath = "/Users/test/DerivedData"
139+
let findResult = "./MyModule.swiftmodule"
140+
141+
var mockShell = MockShell()
142+
mockShell.handleExecute = { _ in findResult }
143+
144+
var mockFileHandler = MockFileHandler()
145+
mockFileHandler.handleContentsOfDirectory = { path in
146+
XCTAssertEqual(path, "/Users/test/DerivedData/./MyModule.swiftmodule")
147+
return ["arm64-apple-ios.swiftinterface"]
148+
}
149+
150+
let locator = SwiftInterfaceFileLocator(
151+
fileHandler: mockFileHandler,
152+
shell: mockShell,
153+
logger: nil
154+
)
155+
156+
let result = try locator.locate(for: scheme, derivedDataPath: derivedDataPath, type: .public)
157+
158+
XCTAssertEqual(
159+
result.path(),
160+
"/Users/test/DerivedData/./MyModule.swiftmodule/arm64-apple-ios.swiftinterface"
161+
)
162+
}
163+
164+
func test_locate_public_excludesPrivateAndPackage() throws {
165+
let scheme = "MyModule"
166+
let derivedDataPath = "/path/to/derived/data"
167+
let findResult = "./MyModule.swiftmodule"
168+
169+
var mockShell = MockShell()
170+
mockShell.handleExecute = { _ in findResult }
171+
172+
var mockFileHandler = MockFileHandler()
173+
mockFileHandler.handleContentsOfDirectory = { _ in
174+
[
175+
"arm64-apple-ios.private.swiftinterface",
176+
"arm64-apple-ios.package.swiftinterface",
177+
"arm64-apple-ios.swiftinterface"
178+
]
179+
}
180+
181+
let locator = SwiftInterfaceFileLocator(
182+
fileHandler: mockFileHandler,
183+
shell: mockShell,
184+
logger: nil
185+
)
186+
187+
let result = try locator.locate(for: scheme, derivedDataPath: derivedDataPath, type: .public)
188+
189+
XCTAssertTrue(result.path().hasSuffix("arm64-apple-ios.swiftinterface"))
190+
XCTAssertFalse(result.path().hasSuffix(".private.swiftinterface"))
191+
XCTAssertFalse(result.path().hasSuffix(".package.swiftinterface"))
192+
}
193+
194+
func test_locate_throwsWhenSwiftModuleNotFound() throws {
195+
let scheme = "MyModule"
196+
let derivedDataPath = "/path/to/derived/data"
197+
198+
var mockShell = MockShell()
199+
mockShell.handleExecute = { _ in "" }
200+
201+
var mockFileHandler = MockFileHandler()
202+
mockFileHandler.handleContentsOfDirectory = { _ in
203+
throw FileHandlerError.pathDoesNotExist(path: "")
204+
}
205+
206+
let locator = SwiftInterfaceFileLocator(
207+
fileHandler: mockFileHandler,
208+
shell: mockShell,
209+
logger: nil
210+
)
211+
212+
XCTAssertThrowsError(try locator.locate(for: scheme, derivedDataPath: derivedDataPath, type: .public))
213+
}
214+
215+
func test_locate_throwsWhenSwiftInterfaceNotFound() throws {
216+
let scheme = "MyModule"
217+
let derivedDataPath = "/path/to/derived/data"
218+
let findResult = "./MyModule.swiftmodule"
219+
220+
var mockShell = MockShell()
221+
mockShell.handleExecute = { _ in findResult }
222+
223+
var mockFileHandler = MockFileHandler()
224+
mockFileHandler.handleContentsOfDirectory = { _ in
225+
[]
226+
}
227+
228+
let locator = SwiftInterfaceFileLocator(
229+
fileHandler: mockFileHandler,
230+
shell: mockShell,
231+
logger: nil
232+
)
233+
234+
XCTAssertThrowsError(try locator.locate(for: scheme, derivedDataPath: derivedDataPath, type: .public))
235+
}
236+
}

0 commit comments

Comments
 (0)