Files
Termind/FrameworkTests/SFTPSettingsTests.swift

87 lines
3.4 KiB
Swift

// SPDX-FileCopyrightText: 2026 Kaede Akino
// SPDX-License-Identifier: GPL-3.0-only
import Foundation
import TermindApplication
import TermindDomain
import Testing
@Suite @MainActor
struct SFTPSettingsTests {
@Test(arguments: [(0, 0, 1, 1), (200, 80, 100, 50), (3, 7, 3, 3), (100, 50, 100, 50), (3, 2, 3, 2)])
func normalizationEnforcesBothLimits(_ input: (Int, Int, Int, Int)) {
let value = SFTPPreferences(globalLimit: input.0, perHostLimit: input.1)
#expect(value.globalLimit == input.2)
#expect(value.perHostLimit == input.3)
#expect(value.isValid)
#expect(value.availablePerHostRange.upperBound == min(50, input.2))
}
@Test func failedSavePreservesPreferencesAndDoesNotNotifyTheRuntime() {
let persistence = TestSFTPPreferencesPersistence()
let model = SFTPSettingsModel(persistence: persistence)
var received: [SFTPPreferences] = []
model.didChange = { received.append($0) }
persistence.fail = true
#expect(!model.set(100, for: \.globalLimit))
#expect(model.preferences == SFTPPreferences())
#expect(persistence.value == SFTPPreferences())
#expect(model.storageError != nil)
#expect(received.isEmpty)
persistence.fail = false
#expect(model.set(100, for: \.globalLimit))
#expect(model.storageError == nil)
#expect(received == [SFTPPreferences(globalLimit: 100, perHostLimit: 10)])
}
@Test func remoteChangesNotifyOnceWithoutSavingAndLocalChangesCommitThePair() {
let persistence = TestSFTPPreferencesPersistence()
let model = SFTPSettingsModel(persistence: persistence)
var received: [SFTPPreferences] = []
model.didChange = { received.append($0) }
let remote = SFTPPreferences(globalLimit: 100, perHostLimit: 50)
model.applyRemoteSnapshot(remote)
model.applyRemoteSnapshot(remote)
#expect(received == [remote])
#expect(persistence.saves == 0)
#expect(model.set(3, for: \.globalLimit))
#expect(persistence.value == SFTPPreferences(globalLimit: 3, perHostLimit: 3))
#expect(persistence.saves == 1)
#expect(received.last == persistence.value)
}
@Test func strategyPersistsAndOlderJSONDefaultsToSmart() throws {
let legacy = try JSONDecoder().decode(
SFTPPreferences.self,
from: Data(#"{"globalLimit":15,"perHostLimit":5}"#.utf8))
#expect(legacy == SFTPPreferences(globalLimit: 15, perHostLimit: 5, strategy: .smart))
let persistence = TestSFTPPreferencesPersistence()
let model = SFTPSettingsModel(persistence: persistence)
#expect(model.setStrategy(.channelsOnly))
#expect(persistence.value.strategy == .channelsOnly)
#expect(persistence.saves == 1)
#expect(throws: DecodingError.self) {
_ = try JSONDecoder().decode(
SFTPPreferences.self,
from: Data(#"{"globalLimit":30,"perHostLimit":10,"strategy":"future"}"#.utf8))
}
}
}
@MainActor
private final class TestSFTPPreferencesPersistence: SFTPPreferencesPersisting {
var value = SFTPPreferences()
var saves = 0
var fail = false
func loadSFTP() throws -> SFTPPreferences { value }
func saveSFTP(_ value: SFTPPreferences) throws {
if fail { throw CocoaError(.fileWriteNoPermission) }
self.value = value
saves += 1
}
}