Files
Termind/TFITests/MobileSFTPEditedCopyImporterTests.swift

92 lines
4.2 KiB
Swift

// SPDX-FileCopyrightText: 2026 Kaede Akino
// SPDX-License-Identifier: GPL-3.0-only
import CryptoKit
import Foundation
import TermindApplication
import TermindDomain
import TermindRemoteInfrastructure
import Testing
@testable import TermindIOS
@MainActor
struct MobileSFTPEditedCopyImporterTests {
@Test func importedCopyBecomesAPendingEditWithoutUploadingOrChangingRemoteIdentity() async throws {
let fixture = try Fixture()
defer { fixture.clean() }
let baseline = try #require(fixture.edits.model.file(fixture.id)?.baseline)
await fixture.workspace.importEditedCopy(fixture.source, for: fixture.id)
#expect(fixture.workspace.operationError == nil)
#expect(try Data(contentsOf: fixture.original) == Data([3, 2, 1]))
#expect(try Data(contentsOf: fixture.source) == Data([3, 2, 1]))
let entry = try #require(fixture.edits.model.file(fixture.id))
#expect(entry.localURL == fixture.original)
#expect(entry.remotePath == "/srv/document.txt")
#expect(entry.baseline == baseline)
#expect(entry.isModified)
#expect(fixture.transfers.sftpTransfers.isEmpty)
}
@Test func differentFormatsAndDiscardedRecordsNeverReplaceTheManagedFile() async throws {
let fixture = try Fixture()
defer { fixture.clean() }
let otherFormat = fixture.directory.appending(path: "edited.pdf")
try Data([4]).write(to: otherFormat)
await fixture.workspace.importEditedCopy(otherFormat, for: fixture.id)
#expect(fixture.workspace.operationError != nil)
#expect(try Data(contentsOf: fixture.original) == Data([1, 2, 3]))
await fixture.edits.discard(fixture.id)
await fixture.workspace.importEditedCopy(fixture.source, for: fixture.id)
#expect(try Data(contentsOf: fixture.original) == Data([1, 2, 3]))
}
@Test func invalidatedOrUploadingRecordsKeepTheirCurrentContents() async throws {
let fixture = try Fixture()
defer { fixture.clean() }
fixture.edits.model.update(fixture.id) { $0.transferID = UUID() }
await fixture.workspace.importEditedCopy(fixture.source, for: fixture.id)
#expect(try Data(contentsOf: fixture.original) == Data([1, 2, 3]))
fixture.edits.model.update(fixture.id) {
$0.transferID = nil
$0.isInvalidated = true
}
await fixture.workspace.importEditedCopy(fixture.source, for: fixture.id)
#expect(try Data(contentsOf: fixture.original) == Data([1, 2, 3]))
}
private struct Fixture {
let directory: URL
let original: URL
let source: URL
let edits: SFTPEditService
let transfers: SFTPTransferCoordinator
let workspace: MobileWorkspace
let id: UUID
init() throws {
directory = FileManager.default.temporaryDirectory.appending(path: UUID().uuidString)
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
original = directory.appending(path: "document.txt")
source = directory.appending(path: "edited.txt")
try Data([1, 2, 3]).write(to: original)
try Data([3, 2, 1]).write(to: source)
let host = TermindDomain.Host(name: "Test", host: "example.invalid")
let library = HostLibraryModel(hosts: [host])
transfers = SFTPTransferCoordinator(store: library, clientFactory: { SFTPClient() })
edits = SFTPEditService(transfers: transfers)
edits.setMonitoring(false)
let file = RemoteFile(
path: "/srv/document.txt", name: "document.txt", kind: .file, size: 3,
permissions: 0o644, ownerUID: 0, ownerGID: 0)
let digest = SHA256.hash(data: Data([1, 2, 3])).map { String(format: "%02x", $0) }.joined()
id = edits.model.register(hostID: host.id, file: file, localURL: original, digest: digest)
workspace = MobileWorkspace(
descriptor: MobileWorkspaceDescriptor(hostID: host.id, title: host.name, kind: .sftp),
hosts: library, transfers: transfers, sftpEdits: edits)
}
func clean() { try? FileManager.default.removeItem(at: directory) }
}
}