mirror of
https://github.com/shadowsocks/ShadowsocksX-NG.git
synced 2026-11-08 10:44:50 +00:00
98 lines
4.9 KiB
Swift
98 lines
4.9 KiB
Swift
import XCTest
|
|
|
|
@testable import ShadowsocksX_NG2
|
|
|
|
@MainActor
|
|
final class RulesWorkflowCoverageTests: XCTestCase {
|
|
func testCoverageUsesAllSourcesAndDistinguishesPartialFromFull() async throws {
|
|
let broad = ProxyRule(action: .direct, match: try RuleMatch(domainSuffix: "example.com"))
|
|
let narrow = CustomRule(action: .direct, match: try RuleMatch(domainExact: "www.example.com"))
|
|
let workflow = RulesWorkflow(
|
|
preset: .chinaDirect, loadCustom: { [narrow] },
|
|
builtinSnapshots: BuiltinRuleSnapshots(loader: {
|
|
rulesFixture($0, rules: $0 == .geolocationCN ? [broad] : [])
|
|
}))
|
|
await workflow.refresh()
|
|
workflow.query(RulesQuery(source: .geolocationCN))
|
|
let broadRow = try XCTUnwrap(workflow.snapshot.rows.first { $0.identity == broad })
|
|
XCTAssertTrue(
|
|
broadRow.relationships.contains {
|
|
$0.kind == .absorption && $0.extent == .partial && $0.covering == [narrow.identity]
|
|
})
|
|
workflow.query(RulesQuery(source: .custom))
|
|
let narrowRow = try XCTUnwrap(workflow.snapshot.rows.first)
|
|
XCTAssertTrue(
|
|
narrowRow.relationships.contains {
|
|
$0.kind == .absorption && $0.extent == .full && $0.covering == [broad]
|
|
})
|
|
XCTAssertTrue(narrowRow.relationships.allSatisfy { $0.kind != .shadowing })
|
|
}
|
|
|
|
func testMappedIPAndCombinedNarrowRangesExplainCoverageThroughWorkflow() async throws {
|
|
let broad = CustomRule(action: .direct, match: try RuleMatch(ipv6CIDR: "::ffff:8.8.8.0/120"))
|
|
let lower = CustomRule(action: .direct, match: try RuleMatch(ipv4CIDR: "8.8.8.0/25"))
|
|
let upper = CustomRule(action: .direct, match: try RuleMatch(ipv4CIDR: "8.8.8.128/25"))
|
|
let workflow = RulesWorkflow(
|
|
preset: .chinaDirect, loadCustom: { [broad, lower, upper] },
|
|
builtinSnapshots: BuiltinRuleSnapshots(loader: { rulesFixture($0) }))
|
|
await workflow.refresh()
|
|
workflow.query(RulesQuery(action: .direct, source: .custom))
|
|
let row = try XCTUnwrap(workflow.snapshot.rows.first)
|
|
XCTAssertEqual(row.identity, broad.identity)
|
|
XCTAssertEqual(row.relationships.count, 1)
|
|
XCTAssertEqual(row.relationships.first?.kind, .absorption)
|
|
XCTAssertEqual(row.relationships.first?.extent, .full)
|
|
XCTAssertEqual(Set(row.relationships.first?.covering ?? []), [lower.identity, upper.identity])
|
|
}
|
|
|
|
func testFixedProtectionExplainsSimpleHostsAndPreventsFalseLocalShadowing() async throws {
|
|
let simple = ProxyRule(
|
|
action: .direct, match: try RuleMatch(domainExact: "printer"))
|
|
let simpleSuffix = ProxyRule(action: .direct, match: try RuleMatch(nationalDomainSuffix: "cn"))
|
|
let localProxy = ProxyRule(
|
|
action: .direct, match: try RuleMatch(domainExact: "device.local"))
|
|
let localDirect = CustomRule(action: .direct, match: try RuleMatch(domainExact: "device.local"))
|
|
let nationalDirect = CustomRule(
|
|
action: .direct, match: try RuleMatch(nationalDomainSuffix: "cn"))
|
|
let workflow = RulesWorkflow(
|
|
preset: .chinaDirect,
|
|
loadCustom: { [localDirect, nationalDirect] },
|
|
builtinSnapshots: BuiltinRuleSnapshots(loader: { requested in
|
|
rulesFixture(
|
|
requested, rules: requested == .geolocationCN ? [simple, simpleSuffix, localProxy] : [])
|
|
}))
|
|
await workflow.refresh()
|
|
workflow.query(RulesQuery(source: .geolocationCN))
|
|
let simpleRow = try XCTUnwrap(workflow.snapshot.rows.first { $0.identity == simple })
|
|
XCTAssertEqual(simpleRow.fixedCoverage?.extent, .full)
|
|
let suffixRow = try XCTUnwrap(
|
|
workflow.snapshot.rows.first { $0.identity == simpleSuffix })
|
|
XCTAssertEqual(suffixRow.fixedCoverage?.extent, .partial)
|
|
workflow.query(RulesQuery(source: .custom))
|
|
let localRow = try XCTUnwrap(
|
|
workflow.snapshot.rows.first { $0.identity == localDirect.identity })
|
|
XCTAssertEqual(localRow.fixedCoverage?.extent, .full)
|
|
XCTAssertFalse(localRow.relationships.contains { $0.kind == .shadowing })
|
|
let nationalRow = try XCTUnwrap(
|
|
workflow.snapshot.rows.first { $0.identity == nationalDirect.identity })
|
|
XCTAssertEqual(nationalRow.fixedCoverage?.extent, .partial)
|
|
XCTAssertFalse(nationalRow.relationships.contains { $0.kind == .shadowing })
|
|
}
|
|
|
|
func testFixedLocalCoverageDoesNotShadowPublicPartOfDirectSuffix() async throws {
|
|
let direct = CustomRule(action: .direct, match: try RuleMatch(nationalDomainSuffix: "cn"))
|
|
let proxy = ProxyRule(action: .proxy, match: try RuleMatch(domainExact: "cn"))
|
|
let workflow = RulesWorkflow(
|
|
preset: .chinaDirect,
|
|
loadCustom: { [direct] },
|
|
builtinSnapshots: BuiltinRuleSnapshots(loader: { requested in
|
|
rulesFixture(requested, rules: requested == .gfwlist ? [proxy] : [])
|
|
}))
|
|
await workflow.refresh()
|
|
workflow.query(RulesQuery(source: .custom))
|
|
let row = try XCTUnwrap(workflow.snapshot.rows.first)
|
|
XCTAssertFalse(row.relationships.contains { $0.kind == .shadowing })
|
|
XCTAssertEqual(row.fixedCoverage?.extent, .partial)
|
|
}
|
|
}
|