Files
ShadowsocksX-NG/ShadowsocksX-NG2/Tests/SystemProxy/SystemProxyHelperContractTests.swift
Qiu YuzhouandDeepSeek Harness 78bafea90f test: drop assertions that restate the language or a fixture
Each removed assertion holds by construction and can never fail:

- jsonData() compared with itself cannot detect cross-run byte stability;
  bindAddress and mode are literal-returning computed properties
- RuleAction/RuleSourceKind allCases assertions pin synthesized enum order
  (neither allCases list is used in production); the persisted action tokens
  stay pinned by the kept rawValue assertions and source-kind tokens by
  fixture decoding through RuleSnapshotStore
- memberwise-constructor echo in RuleSourceIdentity, fixture-guaranteed
  name == id rows, a share draft field pair built from one string, and a
  local struct compared to its own assignment
- the synthesized-Codable round trip through literal JSONEncoder/JSONDecoder

The duplicate-import assertion becomes a real check: Set of node ids instead
of a count that restated roots.count, which is what its comment claims.

Co-Authored-By: DeepSeek Harness <noreply@deepseek.com>
2026-10-21 02:04:21 +08:00

123 lines
4.2 KiB
Swift

import XCTest
@testable import ShadowsocksX_NG2
/// helper XPC 契约测试:引擎应答编码、typed 失败归并与串行
/// last-writer 语义,全部用确定性替身,不触真实 XPC 与 SystemConfiguration。
final class SystemProxyHelperContractTests: XCTestCase {
private let configuration = SystemProxyConfiguration(
socks: .init(host: "127.0.0.1", port: 1086),
http: .init(host: "127.0.0.1", port: 1087),
https: .init(host: "127.0.0.1", port: 1087),
exceptions: ["localhost"])
/// 并发闭包与断言之间的线程安全值交接。
private final class LockedArray<Element>: @unchecked Sendable {
private let lock = NSLock()
private var items: [Element] = []
func append(_ item: Element) {
lock.lock()
items.append(item)
lock.unlock()
}
var all: [Element] {
lock.lock()
defer { lock.unlock() }
return items
}
}
func testEngineAnswersApplyWithTypedOutcome() throws {
let observed = LockedArray<SystemProxyHelperEngine.Request>()
let response = SystemProxyHelperEngine.response(
request: .success(.apply(configuration)),
perform: { request in
observed.append(request)
return .applied(.written)
})
XCTAssertEqual(observed.all, [.apply(configuration)], "helper 收到 closed typed 配置")
XCTAssertEqual(response, .applied(.written))
}
func testEngineAnswersClearWithTypedOutcome() {
let response = SystemProxyHelperEngine.response(
request: .success(.clear), perform: { _ in .cleared })
XCTAssertEqual(response, .cleared)
}
func testEngineEncodesTypedFailuresAndInvalidPayloads() throws {
let failure = SystemProxyHelperEngine.response(
request: .failure(SystemProxyError.commitFailed("busy")),
perform: { _ in .cleared })
XCTAssertEqual(failure, .failure(.commitFailed("busy")))
let genericFailure = SystemProxyHelperEngine.response(
request: .failure(ProxyListeningStoreError.corrupt(detail: "bad")),
perform: { _ in .cleared })
XCTAssertEqual(
genericFailure, .failure(.helperUnavailable("corrupt(detail: \"bad\")")),
"非 SystemProxyError 归并为 helperUnavailable")
XCTAssertThrowsError(
try SystemProxyHelperWire.decodeConfiguration(Data("not json".utf8))
) { error in
guard case SystemProxyError.invalidRequest = error else {
return XCTFail("无效 payload 应为 invalidRequest,实际 \(error)")
}
}
}
/// 串行 last-writer:注入的假写入器在共享串行队列上按
/// 接受顺序执行,最后接受的请求决定最终结果。
func testEngineProcessesRequestsSeriallyWithLastWriterWins() async throws {
let recorder = LockedArray<String>()
let queue = DispatchQueue(label: "test.system-proxy-helper.serial")
let engine = SystemProxyHelperEngine(
perform: { request in
switch request {
case .apply(let applied):
recorder.append("apply:\(applied.socks.port)")
case .clear:
recorder.append("clear")
}
return .applied(.written)
},
queue: queue)
let first = try SystemProxyHelperWire.encodeConfiguration(configuration)
let second = try SystemProxyHelperWire.encodeConfiguration(
SystemProxyConfiguration(
socks: .init(host: "127.0.0.1", port: 2086),
http: .init(host: "127.0.0.1", port: 2087),
https: .init(host: "127.0.0.1", port: 2087),
exceptions: ["localhost"]))
let replies = LockedArray<Data>()
let replyExpectation = expectation(description: "replies")
replyExpectation.expectedFulfillmentCount = 3
engine.apply(first) {
replies.append($0)
replyExpectation.fulfill()
}
engine.clear {
replies.append($0)
replyExpectation.fulfill()
}
engine.apply(second) {
replies.append($0)
replyExpectation.fulfill()
}
await fulfillment(of: [replyExpectation], timeout: 5)
XCTAssertEqual(recorder.all, ["apply:1086", "clear", "apply:2086"], "逐个串行执行")
XCTAssertEqual(replies.all.count, 3)
for reply in replies.all {
XCTAssertEqual(
try SystemProxyHelperWire.decode(reply), .applied(.written), "每个请求都有 typed 应答")
}
}
}