Files
ShadowsocksX-NG/ShadowsocksX-NG2/Tests/ProxyControlWorkflowIntegrationTests+SystemProxy.swift
T
Qiu Yuzhou 827fb98be3 refactor(ng2): fix all swiftlint warnings
77 → 0 warnings. Split oversized functions and files: controller and
agent extension files, standalone RuleSet/ProxySettingsFileStore/
SslocalListenSettings/LegacyImportService, test classes into topic
extensions. Regroup activation options into RuntimeDocumentOptions and
converter metadata into Provenance.

Runtime controller DI seams widen private → internal so the extension
files stay cohesive; new controller files are registered in the
architecture guard exemption list; Agent target adds RuleSet and
SslocalListenSettings to project.yml. Test JSON literals wrap inside
the string literal only.
2026-09-26 17:13:31 +08:00

105 lines
4.9 KiB
Swift
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import XCTest
@testable import ShadowsocksX_NG2
extension ProxyControlWorkflowIntegrationTests {
// MARK: - 系统代理开关(issue #60)
func testSystemProxyIntentAppliesThroughSnapshot() async throws {
let server = try makeSeededCatalog()
let composition = makeProxies(probe: ProxyRuntimeFixture.FakeProbe.reachable())
_ = try await composition.catalog.activate(server)
_ = await composition.control.setAgentEnabled(true)
let snapshot = await composition.control.setSystemProxyEnabled(true)
XCTAssertTrue(snapshot.systemProxyIntentEnabled)
XCTAssertEqual(snapshot.systemProxyApplication, .applied)
XCTAssertEqual(snapshot.runtime.status, .running, "agent 运行状态不受系统代理影响")
XCTAssertEqual(systemProxy.applied.count, 1)
}
/// 健康门禁:端点不健康时系统代理意图保持待应用(快照呈现 pending)。
func testSystemProxyIntentStaysPendingWhenEndpointsUnhealthy() async throws {
let server = try makeSeededCatalog()
let composition = makeProxies(probe: ProxyRuntimeFixture.FakeProbe.refusing())
_ = try await composition.catalog.activate(server)
_ = await composition.control.setAgentEnabled(true)
let snapshot = await composition.control.setSystemProxyEnabled(true)
XCTAssertTrue(snapshot.systemProxyIntentEnabled)
XCTAssertEqual(snapshot.systemProxyApplication, .pending, "待应用进入 snapshot")
XCTAssertEqual(snapshot.runtime.status, .launchFailed)
XCTAssertTrue(systemProxy.applied.isEmpty, "健康门未过不写系统设置")
}
/// 系统代理写入失败:typed fact 进入 snapshot,agent 继续运行。
func testSystemProxyFailureSurfacesTypedFactInSnapshot() async throws {
let server = try makeSeededCatalog()
systemProxy.applyError = SystemProxyError.applyFailed("denied")
let composition = makeProxies(probe: ProxyRuntimeFixture.FakeProbe.reachable())
_ = try await composition.catalog.activate(server)
_ = await composition.control.setAgentEnabled(true)
let snapshot = await composition.control.setSystemProxyEnabled(true)
XCTAssertTrue(snapshot.systemProxyIntentEnabled)
XCTAssertEqual(
snapshot.systemProxyApplication, .failed(.operation(.applyFailed)))
XCTAssertEqual(snapshot.runtime, ProxyRuntimeFacts(status: .running, isOn: true))
}
/// 关闭系统代理:恢复 NG2 持有的系统设置;本地监听不停止(issue #60)。
func testSystemProxyOffKeepsAgentRunningAndReflectsIdleInSnapshot() async throws {
let server = try makeSeededCatalog()
let composition = makeProxies(probe: ProxyRuntimeFixture.FakeProbe.reachable())
_ = try await composition.catalog.activate(server)
_ = await composition.control.setAgentEnabled(true)
_ = await composition.control.setSystemProxyEnabled(true)
let snapshot = await composition.control.setSystemProxyEnabled(false)
XCTAssertFalse(snapshot.systemProxyIntentEnabled)
XCTAssertEqual(snapshot.systemProxyApplication, .idle)
XCTAssertEqual(snapshot.runtime, ProxyRuntimeFacts(status: .running, isOn: true))
XCTAssertEqual(systemProxy.restoreCount, 1)
XCTAssertEqual(agent.unregisterCount, 0, "不注销 agent")
}
/// 无活动目标:agent 监听,但需要出口的系统代理意图保持待应用。
func testSystemProxyIntentStaysPendingWithoutActiveTarget() async throws {
_ = try makeSeededCatalog()
let composition = makeProxies(
probe: ProxyRuntimeFixture.FakeProbe.reachable(),
settings: ProxySettings(listen: ActivationFixture.listen, agentEnabled: false))
_ = await composition.control.setAgentEnabled(true)
let snapshot = await composition.control.setSystemProxyEnabled(true)
XCTAssertEqual(snapshot.runtime.status, .running, "agent 以空列表监听")
XCTAssertEqual(snapshot.systemProxyApplication, .pending, "无可用出口保持待应用")
XCTAssertTrue(systemProxy.applied.isEmpty)
XCTAssertNil(snapshot.activeTarget)
}
/// 待应用意图在目标激活后自动收敛(issue #60)。目录命令后的 snapshot 更新
/// 经主队列 hop 到达,有界等待收敛。
func testPendingSystemProxyIntentConvergesAfterTargetActivation() async throws {
let server = try makeSeededCatalog()
let composition = makeProxies(probe: ProxyRuntimeFixture.FakeProbe.reachable())
_ = await composition.control.setAgentEnabled(true)
let pending = await composition.control.setSystemProxyEnabled(true)
XCTAssertEqual(pending.systemProxyApplication, .pending)
_ = try await composition.catalog.activate(server)
let deadline = Date().addingTimeInterval(2)
while composition.control.snapshot.systemProxyApplication != .applied && Date() < deadline {
try await Task.sleep(nanoseconds: 10_000_000)
}
XCTAssertEqual(composition.control.snapshot.systemProxyApplication, .applied, "激活后自动收敛")
XCTAssertEqual(systemProxy.applied.count, 1)
}
}