mirror of
https://github.com/xweiba/location-spoofer.git
synced 2026-09-21 22:30:46 +08:00
141 lines
6.8 KiB
Swift
141 lines
6.8 KiB
Swift
import XCTest
|
|
@testable import PaopaoLocationSpoofer
|
|
|
|
final class CertificateAuthorityStoreTests: XCTestCase {
|
|
private let validAuthority = CertificateAuthority(certPEM: "valid-cert", keyPEM: "valid-key")
|
|
|
|
func testEnsureCreatesOnceThenReusesValidKeychainPair() throws {
|
|
let keychain = InMemoryCertificateAuthorityKeychain()
|
|
var generations = 0
|
|
let store = makeStore(keychain: keychain) {
|
|
generations += 1
|
|
return self.validAuthority
|
|
}
|
|
|
|
XCTAssertEqual(try store.ensure(), validAuthority)
|
|
XCTAssertEqual(try store.ensure(), validAuthority)
|
|
XCTAssertEqual(keychain.stored, validAuthority)
|
|
XCTAssertEqual(generations, 1)
|
|
}
|
|
|
|
func testEnsureMigratesValidLegacyPairThenDeletesLegacyFiles() throws {
|
|
let directory = try makeLegacyDirectory(authority: validAuthority)
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
let keychain = InMemoryCertificateAuthorityKeychain()
|
|
let store = makeStore(directory: directory, keychain: keychain) {
|
|
XCTFail("A valid legacy pair must be migrated instead of regenerated")
|
|
return self.validAuthority
|
|
}
|
|
|
|
XCTAssertEqual(try store.ensure(), validAuthority)
|
|
XCTAssertEqual(keychain.stored, validAuthority)
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: directory.appendingPathComponent("ca-cert.pem").path))
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: directory.appendingPathComponent("ca-key.pem").path))
|
|
}
|
|
|
|
func testFailedKeychainMigrationPreservesLegacyFiles() throws {
|
|
let directory = try makeLegacyDirectory(authority: validAuthority)
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
let keychain = InMemoryCertificateAuthorityKeychain()
|
|
keychain.shouldFailSave = true
|
|
let store = makeStore(directory: directory, keychain: keychain) { self.validAuthority }
|
|
|
|
XCTAssertThrowsError(try store.ensure())
|
|
XCTAssertTrue(FileManager.default.fileExists(atPath: directory.appendingPathComponent("ca-cert.pem").path))
|
|
XCTAssertTrue(FileManager.default.fileExists(atPath: directory.appendingPathComponent("ca-key.pem").path))
|
|
}
|
|
|
|
func testInvalidKeychainPairFallsBackToLegacyPair() throws {
|
|
let directory = try makeLegacyDirectory(authority: validAuthority)
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
let keychain = InMemoryCertificateAuthorityKeychain()
|
|
keychain.stored = CertificateAuthority(certPEM: "invalid-cert", keyPEM: "invalid-key")
|
|
let store = makeStore(directory: directory, keychain: keychain) { self.validAuthority }
|
|
|
|
XCTAssertEqual(try store.ensure(), validAuthority)
|
|
XCTAssertEqual(keychain.stored, validAuthority)
|
|
}
|
|
|
|
func testValidKeychainPairRetriesCleanupOfLegacyFiles() throws {
|
|
let directory = try makeLegacyDirectory(authority: validAuthority)
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
let keychain = InMemoryCertificateAuthorityKeychain()
|
|
keychain.stored = validAuthority
|
|
let store = makeStore(directory: directory, keychain: keychain) {
|
|
XCTFail("A valid Keychain pair must not be regenerated")
|
|
return self.validAuthority
|
|
}
|
|
|
|
XCTAssertEqual(try store.ensure(), validAuthority)
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: directory.appendingPathComponent("ca-cert.pem").path))
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: directory.appendingPathComponent("ca-key.pem").path))
|
|
}
|
|
|
|
func testInvalidLegacyFilesAreRemovedOnlyAfterReplacementIsPersisted() throws {
|
|
let invalidAuthority = CertificateAuthority(certPEM: "invalid-cert", keyPEM: "invalid-key")
|
|
let directory = try makeLegacyDirectory(authority: invalidAuthority)
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
let keychain = InMemoryCertificateAuthorityKeychain()
|
|
let store = makeStore(directory: directory, keychain: keychain) { self.validAuthority }
|
|
|
|
XCTAssertEqual(try store.ensure(), validAuthority)
|
|
XCTAssertEqual(keychain.stored, validAuthority)
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: directory.appendingPathComponent("ca-cert.pem").path))
|
|
XCTAssertFalse(FileManager.default.fileExists(atPath: directory.appendingPathComponent("ca-key.pem").path))
|
|
}
|
|
|
|
func testFailedReplacementPersistencePreservesInvalidLegacyFiles() throws {
|
|
let invalidAuthority = CertificateAuthority(certPEM: "invalid-cert", keyPEM: "invalid-key")
|
|
let directory = try makeLegacyDirectory(authority: invalidAuthority)
|
|
defer { try? FileManager.default.removeItem(at: directory) }
|
|
let keychain = InMemoryCertificateAuthorityKeychain()
|
|
keychain.shouldFailSave = true
|
|
let store = makeStore(directory: directory, keychain: keychain) { self.validAuthority }
|
|
|
|
XCTAssertThrowsError(try store.ensure())
|
|
XCTAssertTrue(FileManager.default.fileExists(atPath: directory.appendingPathComponent("ca-cert.pem").path))
|
|
XCTAssertTrue(FileManager.default.fileExists(atPath: directory.appendingPathComponent("ca-key.pem").path))
|
|
}
|
|
|
|
private func makeStore(
|
|
directory: URL = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString),
|
|
keychain: InMemoryCertificateAuthorityKeychain,
|
|
generator: @escaping () throws -> CertificateAuthority
|
|
) -> CertificateAuthorityStore {
|
|
CertificateAuthorityStore(
|
|
directory: directory,
|
|
keychain: keychain,
|
|
generator: generator,
|
|
validator: { $0 == self.validAuthority }
|
|
)
|
|
}
|
|
|
|
private func makeLegacyDirectory(authority: CertificateAuthority) throws -> URL {
|
|
let directory = FileManager.default.temporaryDirectory.appendingPathComponent(UUID().uuidString)
|
|
try FileManager.default.createDirectory(at: directory, withIntermediateDirectories: true)
|
|
try authority.certPEM.write(to: directory.appendingPathComponent("ca-cert.pem"), atomically: true, encoding: .utf8)
|
|
try authority.keyPEM.write(to: directory.appendingPathComponent("ca-key.pem"), atomically: true, encoding: .utf8)
|
|
return directory
|
|
}
|
|
}
|
|
|
|
private enum CertificateAuthorityStoreTestError: Error {
|
|
case saveFailed
|
|
}
|
|
|
|
private final class InMemoryCertificateAuthorityKeychain: CertificateAuthorityKeychain {
|
|
var stored: CertificateAuthority?
|
|
var shouldFailSave = false
|
|
|
|
func load() throws -> CertificateAuthority? { stored }
|
|
|
|
func save(_ authority: CertificateAuthority) throws {
|
|
guard !shouldFailSave else { throw CertificateAuthorityStoreTestError.saveFailed }
|
|
stored = authority
|
|
}
|
|
|
|
func remove() throws {
|
|
stored = nil
|
|
}
|
|
}
|