Files

56 lines
3.0 KiB
Swift

import Foundation
import Testing
@Test func installationRefusesToReplaceAnUnrelatedApplication() throws {
let manager = FileManager.default
let root = manager.temporaryDirectory.appendingPathComponent(UUID().uuidString, isDirectory: true)
defer { try? manager.removeItem(at: root) }
let source = root.appendingPathComponent("Source/Conjure.app", isDirectory: true)
let contents = source.appendingPathComponent("Contents", isDirectory: true)
let executables = contents.appendingPathComponent("MacOS", isDirectory: true)
try manager.createDirectory(at: executables, withIntermediateDirectories: true)
try manager.copyItem(at: URL(fileURLWithPath: "/usr/bin/true"), to: executables.appendingPathComponent("Conjure"))
let info: [String: Any] = [
"CFBundleIdentifier": "dev.conjure.launcher",
"CFBundleExecutable": "Conjure",
"CFBundlePackageType": "APPL",
"CFBundleName": "Conjure",
]
try PropertyListSerialization.data(fromPropertyList: info, format: .xml, options: 0)
.write(to: contents.appendingPathComponent("Info.plist"))
let signing = try installationCommand("/usr/bin/codesign", ["--force", "--sign", "-", source.path])
guard signing.status == 0 else { throw InstallationFixtureError(output: signing.output) }
let directory = root.appendingPathComponent("Applications", isDirectory: true)
let unrelated = directory.appendingPathComponent("Conjure.app", isDirectory: true)
let unrelatedContents = unrelated.appendingPathComponent("Contents", isDirectory: true)
try manager.createDirectory(at: unrelatedContents, withIntermediateDirectories: true)
try PropertyListSerialization.data(fromPropertyList: ["CFBundleIdentifier": "example.unrelated"], format: .xml, options: 0)
.write(to: unrelatedContents.appendingPathComponent("Info.plist"))
let marker = unrelated.appendingPathComponent("UserData.txt")
try Data("Keep this unrelated app".utf8).write(to: marker)
let repository = URL(fileURLWithPath: #filePath).deletingLastPathComponent()
.deletingLastPathComponent().deletingLastPathComponent()
let result = try installationCommand("/usr/bin/swift", [repository.appendingPathComponent("Scripts/install.swift").path, source.path, directory.path])
#expect(result.status != 0)
#expect(try String(contentsOf: marker, encoding: .utf8) == "Keep this unrelated app")
#expect(Bundle(url: unrelated)?.bundleIdentifier == "example.unrelated")
}
private struct InstallationFixtureError: Error {
let output: String
}
private func installationCommand(_ executable: String, _ arguments: [String]) throws -> (status: Int32, output: String) {
let process = Process()
process.executableURL = URL(fileURLWithPath: executable)
process.arguments = arguments
let output = Pipe()
process.standardOutput = output
process.standardError = output
try process.run()
let data = output.fileHandleForReading.readDataToEndOfFile()
process.waitUntilExit()
return (process.terminationStatus, String(decoding: data, as: UTF8.self))
}