@@ -15,6 +15,7 @@ import Basics
1515@_spi ( SwiftPMInternal)
1616@testable import PackageModel
1717
18+ import _InternalTestSupport
1819import func TSCBasic. withTemporaryFile
1920import XCTest
2021
@@ -199,4 +200,90 @@ final class PackageModelTests: XCTestCase {
199200 XCTAssertEqual ( compilers. compile, binDirs. first? . appending ( expectedExecuable) )
200201 }
201202 }
203+
204+ func testDetermineSwiftCompilersWarnsOnInvalidSWIFT_EXEC( ) throws {
205+ let fs = localFileSystem
206+ try withTemporaryDirectory ( removeTreeOnDeinit: true ) { tmp in
207+ let toolchainPath = tmp. appending ( " swift.xctoolchain " )
208+ let toolchainBinDir = toolchainPath. appending ( components: " usr " , " bin " )
209+ try fs. createDirectory ( toolchainBinDir, recursive: true )
210+
211+ #if os(Windows)
212+ let exeSuffix = " .exe "
213+ #else
214+ let exeSuffix = " "
215+ #endif
216+
217+ // Create a valid swiftc in the toolchain
218+ let validSwiftc = toolchainBinDir. appending ( " swiftc \( exeSuffix) " )
219+ try fs. writeFileContents ( validSwiftc, bytes: ByteString ( Self . tinyPEBytes) )
220+ #if !os(Windows)
221+ try fs. chmod ( . executable, path: validSwiftc, options: [ ] )
222+ #endif
223+
224+ // Test 1: SWIFT_EXEC points to non-existent file
225+ do {
226+ let observability = ObservabilitySystem . makeForTesting ( )
227+ let nonExistentPath = tmp. appending ( components: " nonexistent " , " path " , " to " , " swiftc " )
228+ let environment : Environment = [ " SWIFT_EXEC " : nonExistentPath. pathString]
229+
230+ _ = try UserToolchain . determineSwiftCompilers (
231+ binDirectories: [ toolchainBinDir] ,
232+ useXcrun: false ,
233+ environment: environment,
234+ searchPaths: [ ] ,
235+ fileSystem: fs,
236+ observabilityScope: observability. topScope
237+ )
238+
239+ testDiagnostics ( observability. diagnostics) { result in
240+ result. check ( diagnostic: . contains( " SWIFT_EXEC is set to ' \( nonExistentPath. pathString) ' but the file does not exist; ignoring " ) , severity: . warning)
241+ }
242+ }
243+
244+ // Test 2: SWIFT_EXEC points to file that exists but is not executable
245+ do {
246+ let observability = ObservabilitySystem . makeForTesting ( )
247+ let notExecutablePath = tmp. appending ( " not-executable " )
248+ try fs. writeFileContents ( notExecutablePath, bytes: " " )
249+ #if !os(Windows)
250+ try fs. chmod ( . userUnWritable, path: notExecutablePath, options: [ ] )
251+ #endif
252+
253+ let environment : Environment = [ " SWIFT_EXEC " : notExecutablePath. pathString]
254+
255+ _ = try UserToolchain . determineSwiftCompilers (
256+ binDirectories: [ toolchainBinDir] ,
257+ useXcrun: false ,
258+ environment: environment,
259+ searchPaths: [ ] ,
260+ fileSystem: fs,
261+ observabilityScope: observability. topScope
262+ )
263+
264+ testDiagnostics ( observability. diagnostics) { result in
265+ result. check ( diagnostic: . contains( " SWIFT_EXEC is set to ' \( notExecutablePath. pathString) ' which exists but is not executable; ignoring " ) , severity: . warning)
266+ }
267+ }
268+
269+ // Test 3: SWIFT_EXEC is not an absolute path and not found in search paths
270+ do {
271+ let observability = ObservabilitySystem . makeForTesting ( )
272+ let environment : Environment = [ " SWIFT_EXEC " : " nonexistent-compiler " ]
273+
274+ _ = try UserToolchain . determineSwiftCompilers (
275+ binDirectories: [ toolchainBinDir] ,
276+ useXcrun: false ,
277+ environment: environment,
278+ searchPaths: [ ] ,
279+ fileSystem: fs,
280+ observabilityScope: observability. topScope
281+ )
282+
283+ testDiagnostics ( observability. diagnostics) { result in
284+ result. check ( diagnostic: . contains( " SWIFT_EXEC is set to 'nonexistent-compiler' but no executable was found in search paths; ignoring " ) , severity: . warning)
285+ }
286+ }
287+ }
288+ }
202289}
0 commit comments