87 lines
3.4 KiB
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
|
|
}
|
|
}
|