feat: remove persistence connection and SFTP history

This commit is contained in:
Kaede Akino committed 2026-10-03 04:18:14 +08:00
1 parent 5d5a3585ac
commit aa5a92c352
54 files changed
+1790 -1811

No files matched your search

@@ -0,0 +1,108 @@
#if os(macOS)
import Foundation
import TermindApplication
import TermindDomain
import Testing
@testable import TermindRemoteInfrastructure
@Suite
struct RemoteShellHistoryLoaderTests {
@Test func execReadsQuotedPathsAsDataAndWorksWithoutIntegration() async throws {
let folder = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
try FileManager.default.createDirectory(at: folder, withIntermediateDirectories: true)
defer { try? FileManager.default.removeItem(at: folder) }
let file = folder.appendingPathComponent("history ' quoted; $(false)")
try Data("pwd\necho $(false)\n".utf8).write(to: file)
let loader = RemoteShellHistoryLoader(
charset: .utf8, resolveSource: { nil },
execute: { command, _ in
try Self.execute(command, environment: ["SHELL": "/bin/bash", "HISTFILE": file.path])
})
let standard = try await loader.load(source: nil)
let custom = try await loader.load(source: .init(shell: .bash, path: file.path))
#expect(standard.map(\.command) == ["pwd", "echo $(false)"])
#expect(custom == standard)
#expect(standard.allSatisfy { $0.executedAt == nil })
#expect(try String(contentsOf: file, encoding: .utf8) == "pwd\necho $(false)\n")
}
@Test func readsOnlyBoundedTailAndKeepsCompleteRecentRecords() async throws {
let file = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
defer { try? FileManager.default.removeItem(at: file) }
var content = Data(String(repeating: "x", count: RemoteShellHistoryLoader.maximumFileBytes + 100).utf8)
content.append(Data("\n#123\npwd\n#124\nwhoami\n".utf8))
try content.write(to: file)
let loader = RemoteShellHistoryLoader(
charset: .utf8, resolveSource: { nil },
execute: { command, _ in
try Self.execute(command)
})
let records = try await loader.load(source: .init(shell: .bash, path: file.path))
#expect(records.map(\.command) == ["pwd", "whoami"])
}
@Test func missingAndExplicitlyDisabledFilesAreSuccessfulEmptyReads() async throws {
let loader = RemoteShellHistoryLoader(
charset: .utf8, resolveSource: { nil },
execute: { command, _ in
try Self.execute(command)
})
#expect(try await loader.load(source: .init(shell: .zsh, path: "/nonexistent-\(UUID())")).isEmpty)
#expect(try await loader.load(source: .init(shell: .bash, path: "")).isEmpty)
}
@Test func zshMetaficationAndRemoteCharsetAreDecodedBeforeParsing() async throws {
let file = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
defer { try? FileManager.default.removeItem(at: file) }
let bytes = try RemoteCharsetStreamConverter.encode(": 123:0;echo 中文\n", charset: .gb18030)
var metafied = Data()
for byte in bytes {
if byte >= 0x80 {
metafied.append(0x83)
metafied.append(byte ^ 0x20)
} else {
metafied.append(byte)
}
}
try metafied.write(to: file)
let loader = RemoteShellHistoryLoader(
charset: .gb18030, resolveSource: { nil },
execute: { command, _ in
try Self.execute(command)
})
#expect(try await loader.load(source: .init(shell: .zsh, path: file.path)).map(\.command) == ["echo 中文"])
}
@Test func execFailureDoesNotReturnAPartialSnapshot() async {
let loader = RemoteShellHistoryLoader(
charset: .utf8, resolveSource: { nil },
execute: { _, _ in
SSHExecResult(
stdout: "partial", stderr: "denied", exitCode: 1, stdoutTruncated: false, stderrTruncated: false
)
})
await #expect(throws: (any Error).self) { try await loader.load(source: nil) }
}
private nonisolated static func execute(_ command: String, environment: [String: String] = [:]) throws
-> SSHExecResult
{
let process = Process()
process.executableURL = URL(fileURLWithPath: "/bin/sh")
process.arguments = ["-c", command]
process.environment = ProcessInfo.processInfo.environment.merging(environment) { _, replacement in
replacement
}
let output = Pipe()
process.standardOutput = output
process.standardError = FileHandle.nullDevice
try process.run()
let bytes = output.fileHandleForReading.readDataToEndOfFile()
process.waitUntilExit()
return SSHExecResult(
stdout: String(decoding: bytes, as: UTF8.self), stderr: "", exitCode: process.terminationStatus,
stdoutTruncated: false, stderrTruncated: false)
}
}
#endif