94 lines
4.8 KiB
Swift
94 lines
4.8 KiB
Swift
import Foundation
|
|
|
|
// Runs against the generated Swift component and host Rust library.
|
|
final class ContractClipboard: MobileClipboard, @unchecked Sendable {
|
|
var text = "previous"
|
|
var writtenBytes = 0
|
|
var timeout: UInt64 = 0
|
|
var newer: String?
|
|
var cancelled = false
|
|
|
|
func read() throws -> MobileClipboardContent { .text(value: Data(text.utf8)) }
|
|
func write(value: Data) throws {
|
|
writtenBytes = max(writtenBytes, value.count)
|
|
text = String(decoding: value, as: UTF8.self)
|
|
}
|
|
func clear() throws { text = "" }
|
|
func waitForTimeout(milliseconds: UInt64) -> MobileClipboardWait {
|
|
timeout = milliseconds
|
|
if let newer { text = newer }
|
|
return cancelled ? .cancelled : .elapsed
|
|
}
|
|
}
|
|
|
|
@main
|
|
enum MobileContractProbe {
|
|
static func main() throws {
|
|
let secret = String(repeating: "contract-payload-", count: 70_000)
|
|
let copy = MobileEntryCopy(value: secret, timeoutSeconds: 45)
|
|
for diagnostic in [String(describing: copy), String(reflecting: copy)] {
|
|
precondition(!diagnostic.contains(secret))
|
|
}
|
|
let error = MobileAuthenticationFfiError.Failed(kind: .entry, title: secret, detail: secret)
|
|
precondition(!String(reflecting: error).contains(secret))
|
|
precondition(!error.localizedDescription.contains(secret))
|
|
precondition(!String(reflecting: MobileClipboardContent.text(value: Data(secret.utf8))).contains(secret))
|
|
precondition(!String(reflecting: MobileSecretLocator.openPgpPassphrase(fingerprint: secret)).contains(secret))
|
|
for state in [MobileShellState.loading, .empty, .ready, .locked, .error] {
|
|
let shell = mobileShellFixture(state: state)
|
|
precondition(shell.pages.count == 5)
|
|
precondition(shell.pages.allSatisfy { $0.state == state })
|
|
precondition(shell.pages.map(\.icon) == [.home, .key, .search, .timer, .settings])
|
|
}
|
|
let clipboard = ContractClipboard()
|
|
let restored = try copyMobileEntry(copy: copy, clipboard: clipboard)
|
|
precondition(restored == .restoredPrevious)
|
|
precondition(clipboard.text == "previous" && clipboard.writtenBytes == secret.utf8.count)
|
|
precondition(clipboard.timeout == 45_000)
|
|
clipboard.newer = "newer"
|
|
let preserved = try copyMobileEntry(copy: copy, clipboard: clipboard)
|
|
precondition(preserved == .preservedNewer)
|
|
precondition(clipboard.text == "newer")
|
|
clipboard.newer = nil
|
|
clipboard.cancelled = true
|
|
do { _ = try copyMobileEntry(copy: copy, clipboard: clipboard); preconditionFailure("cancellation must fail") }
|
|
catch MobilePlatformFfiError.Cancelled {}
|
|
precondition(clipboard.text == "newer")
|
|
DispatchQueue.concurrentPerform(iterations: 16) { _ in
|
|
let operation = mobileTotpOperation()
|
|
operation.cancel()
|
|
precondition(operation.progress().phase == .cancelled)
|
|
}
|
|
let request = try validateMobileCredentialRequest(request: MobileCredentialRequest(requestId: "opaque", package: "de.example.app", signingCertificateSha256: String(repeating: "A", count: 64), origins: ["https://EXAMPLE.test:443/"]))
|
|
precondition(request.origins == ["https://example.test"])
|
|
do { try privateStorageProbe() }
|
|
catch MobilePrivateStorageFfiError.Failed(let kind) {
|
|
print("Swift private storage failed: \(kind)")
|
|
exit(1)
|
|
}
|
|
print("Swift native contract: fixtures/icons, callbacks, large payload, redaction, cancellation, concurrency and private storage passed")
|
|
}
|
|
static func privateStorageProbe() throws {
|
|
let root = URL(fileURLWithPath: "/private/tmp").appendingPathComponent(UUID().uuidString)
|
|
defer { try? FileManager.default.removeItem(at: root) }
|
|
for name in ["files", "no-backup", "cache"] {
|
|
try FileManager.default.createDirectory(at: root.appendingPathComponent(name), withIntermediateDirectories: true)
|
|
}
|
|
let directories = MobilePrivateDirectories(
|
|
files: root.appendingPathComponent("files").path,
|
|
noBackup: root.appendingPathComponent("no-backup").path,
|
|
cache: root.appendingPathComponent("cache").path
|
|
)
|
|
precondition(!String(reflecting: directories).contains(root.path))
|
|
let storage = try openMobilePrivateRuntime(directories: directories)
|
|
precondition(storage.status().version == 1 && !storage.status().configured)
|
|
precondition(storage.shell().pages.first?.state == .empty)
|
|
precondition(!String(reflecting: storage.layout()).contains(root.path))
|
|
try storage.clearDisposableCache()
|
|
let recreated = try openMobilePrivateRuntime(directories: directories)
|
|
precondition(recreated.status() == storage.status())
|
|
precondition(recreated.layout() == storage.layout())
|
|
}
|
|
|
|
}
|