Files
trycua--cua/libs/lume/tests/LumeControllerTests.swift
wehub-resource-sync 91e75e620b
CI: cua-driver distro-compat matrix / debian:12 (glibc 2.36) (push) Has been cancelled
CI: SPDX Headers / Check SPDX headers (warn-only) (push) Has been cancelled
CD: Docs MCP Server / build (linux/amd64) (push) Has been cancelled
CD: Docs MCP Server / build (linux/arm64) (push) Has been cancelled
CD: Docs MCP Server / merge (push) Has been cancelled
CI: cua-driver distro-compat matrix / Resolve release version (push) Has been cancelled
CI: cua-driver distro-compat matrix / fedora:41 (glibc 2.40) (push) Has been cancelled
CI: cua-driver distro-compat matrix / rockylinux:9 (glibc 2.34) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:22.04 (glibc 2.35) (push) Has been cancelled
CI: cua-driver distro-compat matrix / ubuntu:24.04 (glibc 2.39) (push) Has been cancelled
CI: cua-driver distro-compat matrix / Distro compat summary (push) Has been cancelled
CI: Rust Linux unit / Rust Linux unit and compile (push) Has been cancelled
CI: Rust Windows unit / Rust Windows unit and compile (push) Has been cancelled
CI: Nix Linux Rust source / Nix / compositor build (push) Has been cancelled
CI: Nix Linux Rust source / Nix / driver package (push) Has been cancelled
CI: Nix Linux Rust source / Nix / Rust unit tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:03:19 +08:00

171 lines
5.5 KiB
Swift

import Foundation
import Testing
@testable import lume
private enum TestCreateError: Error {
case setupFailed
}
@MainActor
private final class FailingVM: MockVM {
override func setup(
ipswPath: String,
cpuCount: Int,
memorySize: UInt64,
diskSize: UInt64,
display: String
) async throws {
throw TestCreateError.setupFailed
}
}
@MainActor
private final class FailingVMFactory: VMFactory {
func createVM(
vmDirContext: VMDirContext,
imageLoader: ImageLoader?
) throws -> VM {
FailingVM(
vmDirContext: vmDirContext,
virtualizationServiceFactory: { _ in MockVMVirtualizationService() },
vncServiceFactory: { MockVNCService(vmDirectory: $0) }
)
}
}
@MainActor
private final class TestVMFactory: VMFactory {
func createVM(
vmDirContext: VMDirContext,
imageLoader: ImageLoader?
) throws -> VM {
MockVM(
vmDirContext: vmDirContext,
virtualizationServiceFactory: { _ in MockVMVirtualizationService() },
vncServiceFactory: { MockVNCService(vmDirectory: $0) }
)
}
}
@MainActor
@Test("create cleans up pre-created VM directory when setup fails")
func testCreateCleansUpPrecreatedDirectoryOnFailure() async throws {
let tempConfigDir = try createTempDirectory()
let tempHomeDir = try createTempDirectory()
let tempStorageDir = try createTempDirectory()
defer {
try? FileManager.default.removeItem(at: tempConfigDir)
try? FileManager.default.removeItem(at: tempHomeDir)
try? FileManager.default.removeItem(at: tempStorageDir)
}
let previousXDGConfigHome = ProcessInfo.processInfo.environment["XDG_CONFIG_HOME"]
setenv("XDG_CONFIG_HOME", tempConfigDir.path, 1)
defer {
if let previousXDGConfigHome {
setenv("XDG_CONFIG_HOME", previousXDGConfigHome, 1)
} else {
unsetenv("XDG_CONFIG_HOME")
}
}
let settingsManager = SettingsManager(fileManager: .default)
try settingsManager.setHomeDirectory(path: tempHomeDir.path)
let controller = LumeController(
home: Home(settingsManager: settingsManager, fileManager: .default),
vmFactory: FailingVMFactory()
)
let orphanVMDir = VMDirectory(Path(tempStorageDir.path).directory("orphan-vm"))
do {
try await controller.create(
name: "orphan-vm",
os: "linux",
diskSize: 64 * 1024 * 1024,
cpuCount: 1,
memorySize: 1024 * 1024 * 1024,
display: "1024x768",
ipsw: nil,
storage: tempStorageDir.path
)
#expect(Bool(false), "Expected create to fail with the injected VM factory")
} catch TestCreateError.setupFailed {
// Expected failure from the injected VM factory.
} catch {
#expect(Bool(false), "Expected setupFailed error but got \(error)")
}
#expect(!orphanVMDir.exists())
}
@MainActor
@Test("clone preserves paired disk and auxiliary storage")
func testClonePreservesPairedBootPolicyState() throws {
let tempConfigDir = try createTempDirectory()
let tempHomeDir = try createTempDirectory()
defer {
try? FileManager.default.removeItem(at: tempConfigDir)
try? FileManager.default.removeItem(at: tempHomeDir)
}
let previousXDGConfigHome = ProcessInfo.processInfo.environment["XDG_CONFIG_HOME"]
setenv("XDG_CONFIG_HOME", tempConfigDir.path, 1)
defer {
if let previousXDGConfigHome {
setenv("XDG_CONFIG_HOME", previousXDGConfigHome, 1)
} else {
unsetenv("XDG_CONFIG_HOME")
}
}
let settingsManager = SettingsManager(fileManager: .default)
try settingsManager.setHomeDirectory(path: tempHomeDir.path)
let home = Home(settingsManager: settingsManager, fileManager: .default)
let controller = LumeController(home: home, vmFactory: TestVMFactory())
let sourceDir = try home.getVMDirectory("sip-off-seed")
try FileManager.default.createDirectory(
at: sourceDir.dir.url,
withIntermediateDirectories: true
)
let diskData = Data(repeating: 0xA5, count: 1024 * 1024)
let nvramData = Data((0..<4096).map { UInt8($0 % 251) })
try diskData.write(to: sourceDir.diskPath.url)
try nvramData.write(to: sourceDir.nvramPath.url)
let sourceMachineIdentifier = Data(repeating: 0x11, count: 32)
let sourceMacAddress = "02:00:00:00:00:01"
let sourceConfig = try VMConfig(
os: "macOS",
cpuCount: 4,
memorySize: 8 * 1024 * 1024 * 1024,
diskSize: UInt64(diskData.count),
macAddress: sourceMacAddress,
display: "1024x768",
hardwareModel: Data(repeating: 0x22, count: 32),
machineIdentifier: sourceMachineIdentifier
)
try sourceDir.saveConfig(sourceConfig)
try controller.clone(name: "sip-off-seed", newName: "worker-001")
let cloneDir = try home.getVMDirectory("worker-001")
let cloneConfig = try cloneDir.loadConfig()
#expect(try Data(contentsOf: cloneDir.diskPath.url) == diskData)
#expect(try Data(contentsOf: cloneDir.nvramPath.url) == nvramData)
#expect(cloneConfig.machineIdentifier != sourceMachineIdentifier)
#expect(cloneConfig.macAddress != sourceMacAddress)
}
private func createTempDirectory() throws -> URL {
let tempDir = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
try FileManager.default.createDirectory(at: tempDir, withIntermediateDirectories: true)
return tempDir
}