mirror of https://github.com/cirruslabs/tart.git
145 lines
4.8 KiB
Swift
145 lines
4.8 KiB
Swift
import Foundation
|
|
import XCTest
|
|
@testable import tart
|
|
|
|
final class VMDirectoryLayoutTests: XCTestCase {
|
|
func testStandaloneLayoutWithPinnedManifest() throws {
|
|
let vmDir = try temporaryVMDirectory()
|
|
|
|
try touch(vmDir.configURL)
|
|
try touch(vmDir.nvramURL)
|
|
try touch(vmDir.diskURL)
|
|
try touch(vmDir.manifestURL)
|
|
|
|
XCTAssertEqual(vmDir.layout, .standalone)
|
|
XCTAssertTrue(vmDir.initialized)
|
|
XCTAssertTrue(vmDir.isCachedImage)
|
|
XCTAssertNoThrow(try vmDir.validateCachedImage(userFriendlyName: "standalone"))
|
|
}
|
|
|
|
func testStackedVMLayout() throws {
|
|
let vmDir = try temporaryVMDirectory()
|
|
|
|
try touch(vmDir.configURL)
|
|
try touch(vmDir.nvramURL)
|
|
try touch(vmDir.manifestURL)
|
|
try touch(vmDir.overlayURL)
|
|
|
|
XCTAssertEqual(vmDir.layout, .stackedLocal)
|
|
XCTAssertTrue(vmDir.initialized)
|
|
XCTAssertFalse(vmDir.isCachedImage)
|
|
}
|
|
|
|
func testStackedCachedImageLayout() throws {
|
|
let vmDir = try temporaryVMDirectory()
|
|
|
|
try touch(vmDir.configURL)
|
|
try touch(vmDir.nvramURL)
|
|
try touch(vmDir.manifestURL)
|
|
|
|
XCTAssertEqual(vmDir.layout, .stackedOCIRecord)
|
|
XCTAssertFalse(vmDir.initialized)
|
|
XCTAssertTrue(vmDir.isCachedImage)
|
|
XCTAssertNoThrow(try vmDir.validateCachedImage(userFriendlyName: "stacked"))
|
|
}
|
|
|
|
func testAmbiguousDiskAndOverlayIsNotInitialized() throws {
|
|
let vmDir = try temporaryVMDirectory()
|
|
|
|
try touch(vmDir.configURL)
|
|
try touch(vmDir.nvramURL)
|
|
try touch(vmDir.diskURL)
|
|
try touch(vmDir.manifestURL)
|
|
try touch(vmDir.overlayURL)
|
|
|
|
XCTAssertNil(vmDir.layout)
|
|
XCTAssertFalse(vmDir.initialized)
|
|
XCTAssertFalse(vmDir.isCachedImage)
|
|
}
|
|
|
|
func testStackedVMAccountingUsesOverlay() throws {
|
|
let vmDir = try temporaryVMDirectory()
|
|
|
|
try Data("config".utf8).write(to: vmDir.configURL)
|
|
try Data("nvram".utf8).write(to: vmDir.nvramURL)
|
|
try Data("overlay".utf8).write(to: vmDir.overlayURL)
|
|
try stackedManifest(blockSize: 512, blockCount: 8).toJSON().write(to: vmDir.manifestURL)
|
|
|
|
XCTAssertEqual(
|
|
try vmDir.sizeBytes(),
|
|
try vmDir.configURL.sizeBytes() + vmDir.overlayURL.sizeBytes() + vmDir.nvramURL.sizeBytes()
|
|
)
|
|
XCTAssertEqual(
|
|
try vmDir.allocatedSizeBytes(),
|
|
try vmDir.configURL.allocatedSizeBytes() + vmDir.overlayURL.allocatedSizeBytes() + vmDir.nvramURL.allocatedSizeBytes()
|
|
)
|
|
}
|
|
|
|
func testStackedExportIsRejected() throws {
|
|
let vmDir = try temporaryVMDirectory()
|
|
try touch(vmDir.configURL)
|
|
try touch(vmDir.nvramURL)
|
|
try touch(vmDir.manifestURL)
|
|
try touch(vmDir.overlayURL)
|
|
let archiveURL = vmDir.baseURL.appendingPathComponent("export.tvm")
|
|
|
|
XCTAssertThrowsError(try vmDir.exportToArchive(path: archiveURL.path)) { error in
|
|
guard case RuntimeError.ExportFailed(let message) = error else {
|
|
return XCTFail("unexpected error: \(error)")
|
|
}
|
|
XCTAssertEqual(message, "exporting stacked VMs is not supported yet")
|
|
}
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: archiveURL.path))
|
|
|
|
try FileManager.default.removeItem(at: vmDir.overlayURL)
|
|
XCTAssertTrue(vmDir.isStackedCachedImage)
|
|
XCTAssertThrowsError(try vmDir.exportToArchive(path: archiveURL.path)) { error in
|
|
guard case RuntimeError.ExportFailed(let message) = error else {
|
|
return XCTFail("unexpected error: \(error)")
|
|
}
|
|
XCTAssertEqual(message, "exporting stacked VMs is not supported yet")
|
|
}
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: archiveURL.path))
|
|
}
|
|
|
|
private func temporaryVMDirectory() throws -> VMDirectory {
|
|
let url = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
|
try FileManager.default.createDirectory(at: url, withIntermediateDirectories: false)
|
|
addTeardownBlock {
|
|
try? FileManager.default.removeItem(at: url)
|
|
}
|
|
|
|
return VMDirectory(baseURL: url)
|
|
}
|
|
|
|
private func touch(_ url: URL) throws {
|
|
XCTAssertTrue(FileManager.default.createFile(atPath: url.path, contents: Data()))
|
|
}
|
|
|
|
private func stackedManifest(blockSize: UInt64, blockCount: UInt64) -> OCIManifest {
|
|
var disk = OCIManifestLayer(
|
|
mediaType: diskV2MediaType,
|
|
size: 1,
|
|
digest: "sha256:transport",
|
|
uncompressedSize: blockSize * blockCount,
|
|
uncompressedContentDigest: "sha256:chunk"
|
|
)
|
|
disk.annotations?[diskFileContentDigestAnnotation] = "sha256:base"
|
|
|
|
var manifest = OCIManifest(
|
|
config: OCIManifestConfig(size: 1, digest: "sha256:oci-config"),
|
|
layers: [
|
|
OCIManifestLayer(mediaType: configMediaType, size: 1, digest: "sha256:config"),
|
|
disk,
|
|
OCIManifestLayer(mediaType: nvramMediaType, size: 1, digest: "sha256:nvram"),
|
|
]
|
|
)
|
|
manifest.annotations = [
|
|
uncompressedDiskSizeAnnotation: String(blockSize * blockCount),
|
|
diskBlockSizeAnnotation: String(blockSize),
|
|
]
|
|
|
|
return manifest
|
|
}
|
|
}
|