mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-08 10:44:50 +00:00
149 lines
4.7 KiB
Swift
149 lines
4.7 KiB
Swift
@testable import ShadowsocksX_NG2
|
|
|
|
/// 系统代理相关替身:从 ProxyRuntimeFixture 主文件分出,
|
|
/// 保持 `ProxyRuntimeFixture.` 限定名不变。
|
|
extension ProxyRuntimeFixture {
|
|
@MainActor
|
|
final class FakeSystemProxy: SystemProxyControlling {
|
|
private(set) var applied: [SystemProxyConfiguration] = []
|
|
private(set) var clearCount = 0
|
|
var services: [SystemProxyServiceState] = [
|
|
SystemProxyServiceState(
|
|
identifier: SystemProxyServiceIdentifier(locationID: "home", serviceID: "wifi"),
|
|
configuration: nil, name: "Wi-Fi")
|
|
]
|
|
var readError: Error?
|
|
var beforeRead: (@MainActor () async -> Void)?
|
|
private(set) var readCount = 0
|
|
private(set) var repairedServices: [SystemProxyServiceIdentifier] = []
|
|
var beforeRepair: (@MainActor () async -> Void)?
|
|
var preserveConfigurationOnApply = false
|
|
var applyError: Error?
|
|
var clearError: Error?
|
|
var onClear: (@MainActor () -> Void)?
|
|
/// 注入返回值:模拟系统值已与期望等价的免授权跳过路径。
|
|
var applyOutcome: SystemProxyWriteOutcome = .written
|
|
/// 可选共享事件日志(次序断言用)。
|
|
weak var eventLog: ProxyRuntimeEventLog?
|
|
|
|
func apply(
|
|
_ configuration: SystemProxyConfiguration
|
|
) async throws -> SystemProxyWriteOutcome {
|
|
eventLog?.record("apply")
|
|
if let applyError { throw applyError }
|
|
applied.append(configuration)
|
|
if !preserveConfigurationOnApply {
|
|
let plan = try SystemProxyPlanner.makeApplyPlan(
|
|
services: services, configuration: configuration)
|
|
for write in plan.writes {
|
|
if let index = services.firstIndex(where: { $0.identifier == write.identifier }) {
|
|
services[index] = SystemProxyServiceState(
|
|
identifier: write.identifier, configuration: write.configuration,
|
|
name: services[index].name)
|
|
}
|
|
}
|
|
}
|
|
return applyOutcome
|
|
}
|
|
|
|
func readServices() async throws -> [SystemProxyServiceState] {
|
|
readCount += 1
|
|
if let readError { throw readError }
|
|
let snapshot = services
|
|
await beforeRead?()
|
|
return snapshot
|
|
}
|
|
|
|
func repair(_ configuration: SystemProxyConfiguration) async throws {
|
|
await beforeRepair?()
|
|
let plan = try SystemProxyPlanner.makeApplyPlan(
|
|
services: services, configuration: configuration)
|
|
repairedServices = plan.writes.map(\.identifier)
|
|
_ = try await apply(configuration)
|
|
}
|
|
|
|
func clear() async throws {
|
|
clearCount += 1
|
|
eventLog?.record("clear")
|
|
onClear?()
|
|
if let clearError { throw clearError }
|
|
services = services.map {
|
|
SystemProxyServiceState(identifier: $0.identifier, configuration: nil, name: $0.name)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// 特权 helper 注册/审批状态可编程替身。
|
|
@MainActor
|
|
final class FakeSystemProxyHelperService: SystemProxyHelperServicing {
|
|
private(set) var currentStatus: SystemProxyHelperStatus
|
|
private(set) var registerCount = 0
|
|
private(set) var unregisterCount = 0
|
|
private(set) var registerError: Error?
|
|
private(set) var unregisterError: Error?
|
|
private(set) var openApprovalPathCount = 0
|
|
/// register 成功后迁移到的状态(模拟 BTM 批准立即达成)。
|
|
var statusAfterRegister: SystemProxyHelperStatus = .approved
|
|
|
|
init(initialStatus: SystemProxyHelperStatus = .approved) {
|
|
currentStatus = initialStatus
|
|
}
|
|
|
|
var status: SystemProxyHelperStatus { currentStatus }
|
|
|
|
func setStatus(_ status: SystemProxyHelperStatus) {
|
|
currentStatus = status
|
|
}
|
|
|
|
func setRegisterError(_ error: Error?) {
|
|
registerError = error
|
|
}
|
|
|
|
func setUnregisterError(_ error: Error?) {
|
|
unregisterError = error
|
|
}
|
|
|
|
func register() throws {
|
|
registerCount += 1
|
|
if let registerError { throw registerError }
|
|
currentStatus = statusAfterRegister
|
|
}
|
|
|
|
func unregister() throws {
|
|
unregisterCount += 1
|
|
if let unregisterError { throw unregisterError }
|
|
currentStatus = .notRegistered
|
|
}
|
|
|
|
func openApprovalPath() {
|
|
openApprovalPathCount += 1
|
|
}
|
|
}
|
|
|
|
@MainActor
|
|
final class FakeSystemProxyNetworkChangeMonitor: SystemProxyNetworkChangeMonitoring {
|
|
private(set) var startCount = 0
|
|
private(set) var stopCount = 0
|
|
private(set) var isObserving = false
|
|
private var handler: (@MainActor @Sendable (SystemProxyNetworkChange) -> Void)?
|
|
|
|
func start(
|
|
handler: @escaping @MainActor @Sendable (SystemProxyNetworkChange) -> Void
|
|
) {
|
|
startCount += 1
|
|
isObserving = true
|
|
self.handler = handler
|
|
}
|
|
|
|
func stop() {
|
|
stopCount += 1
|
|
isObserving = false
|
|
handler = nil
|
|
}
|
|
|
|
func emit(_ change: SystemProxyNetworkChange) {
|
|
handler?(change)
|
|
}
|
|
}
|
|
}
|