mirror of
https://github.com/Homebrew/BrewUI.git
synced 2026-10-02 08:34:36 +08:00
brew info never auto-updates, so its API data can be up to 7 days old and tap clones never refresh. Automatic loads and the reconcile after an operation run brew update-if-needed, which applies HOMEBREW_NO_AUTO_UPDATE and the update interval itself. A user's refresh runs brew update. Fixes #235
80 lines
2.4 KiB
Swift
80 lines
2.4 KiB
Swift
//
|
|
// CommandRunnerDoubles.swift
|
|
// BrewServicesTestSupport
|
|
//
|
|
|
|
import BrewCore
|
|
import Foundation
|
|
|
|
/// Injects `BrewLookupError.executableNotFound` through the real repository (no disk, no real `brew`).
|
|
public struct MissingBrewExecutableLocator: BrewExecutableLocating {
|
|
public init() {}
|
|
|
|
public func findBrewExecutable() throws -> URL {
|
|
throw BrewLookupError.executableNotFound
|
|
}
|
|
}
|
|
|
|
/// Per-invocation result for ``MockBrewCommandRunner``.
|
|
public enum MockBrewCommandRunnerBehavior: Sendable {
|
|
case output(CommandOutput)
|
|
case `throw`(any Error & Sendable)
|
|
}
|
|
|
|
/// Maps `brew` argument lists to output or thrown errors — fails fast on unexpected invocations.
|
|
public struct MockBrewCommandRunner: BrewCommandRunning {
|
|
private let behaviors: [[String]: MockBrewCommandRunnerBehavior]
|
|
|
|
public init(behaviors: [[String]: MockBrewCommandRunnerBehavior]) {
|
|
self.behaviors = behaviors
|
|
}
|
|
|
|
/// Convenience: every invocation returns the given `CommandOutput`.
|
|
public init(responses: [[String]: CommandOutput]) {
|
|
behaviors = responses.mapValues { .output($0) }
|
|
}
|
|
|
|
public func run(
|
|
executableURL _: URL,
|
|
arguments: [String],
|
|
options _: BrewRunOptions,
|
|
) async throws -> CommandOutput {
|
|
guard let behavior = behaviors[arguments] else {
|
|
throw BrewCommandError.failed(exitCode: 99, stderr: "unmocked: \(arguments.joined(separator: " "))")
|
|
}
|
|
switch behavior {
|
|
case let .output(out):
|
|
return out
|
|
case let .throw(error):
|
|
throw error
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Returns a different `brew info` JSON payload per invocation (last payload repeats), for two-load tests.
|
|
public actor QueuedBrewInfoRunner: BrewCommandRunning {
|
|
private let outputs: [CommandOutput]
|
|
private var index = 0
|
|
|
|
public init(infoJSON: [String]) {
|
|
outputs = infoJSON.map {
|
|
CommandOutput(standardOutput: $0, standardError: "", terminationStatus: 0)
|
|
}
|
|
}
|
|
|
|
public func run(
|
|
executableURL _: URL,
|
|
arguments: [String],
|
|
options _: BrewRunOptions,
|
|
) async throws -> CommandOutput {
|
|
guard arguments.first == "info" else {
|
|
return CommandOutput(standardOutput: "", standardError: "", terminationStatus: 0)
|
|
}
|
|
let output = outputs[min(index, outputs.count - 1)]
|
|
if index < outputs.count - 1 {
|
|
index += 1
|
|
}
|
|
return output
|
|
}
|
|
}
|