diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 2dfd83eb..2c6bfb77 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -20,10 +20,10 @@ jobs: steps: - name: Checkout uses: actions/checkout@v6 - - name: Build + - name: Build and test run: | - docker compose run --build --rm xtool bash -c \ - "swift build --product xtool && .build/debug/xtool --help" + docker compose run --build xtool bash -c \ + "swift build --product xtool && .build/debug/xtool --help && swift test" build-macos: runs-on: macos-26 steps: @@ -33,6 +33,9 @@ jobs: - name: Build run: | swift build --product xtool && .build/debug/xtool --help + - name: Run tests + run: | + swift test build-ios: runs-on: macos-26 steps: diff --git a/.vscode/settings.json b/.vscode/settings.json index 7d368574..cd011586 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,3 +1,13 @@ { "swiftlint.path": "./.tmp/swiftlint/swiftlint", + "files.watcherExclude":{ + "*/.git/**": true, + "*/.build/**": true, + "*/.tmp/**": true, + }, + "search.exclude": { + "*/.git/**": true, + "*/.build/**": true, + "*/.tmp/**": true, + } } diff --git a/Package.swift b/Package.swift index 5954c047..01fe34fb 100644 --- a/Package.swift +++ b/Package.swift @@ -138,20 +138,6 @@ let package = Package( "XToolSupport", ] ), - .testTarget( - name: "XKitTests", - dependencies: [ - "XKit", - .product(name: "SuperutilsTestSupport", package: "xtool-core") - ], - exclude: [ - "config/config-template.json", - ], - resources: [ - .copy("config/config.json"), - .copy("config/test.app"), - ] - ), .target( name: "XToolSupport", dependencies: [ diff --git a/Tests/XKitTests/Tests/XKitDeveloperServicesTests.swift b/Tests/XKitTests/Tests/XKitDeveloperServicesTests.swift deleted file mode 100644 index ab1b8746..00000000 --- a/Tests/XKitTests/Tests/XKitDeveloperServicesTests.swift +++ /dev/null @@ -1,71 +0,0 @@ -// -// XKitDeveloperServicesTests.swift -// XKitTests -// -// Created by Kabir Oberai on 30/10/19. -// Copyright © 2019 Kabir Oberai. All rights reserved. -// - -import XCTest -import SuperutilsTestSupport -import XKit - -// swiftlint:disable force_try - -class XKitDeveloperServicesTests: XCTestCase { - - var storage: KeyValueStorage! - var client: DeveloperServicesClient! - - override func setUp() { - super.setUp() - _ = addMockSigner - storage = MemoryKeyValueStorage() - client = try! .test(storage: storage) - } - - override func tearDown() { - super.tearDown() - client = nil - } - - // integration test for provisioning - @MainActor func testProvisioningIntegration() async throws { - let listTeams = DeveloperServicesListTeamsRequest() - let teams = try await client.send(listTeams) - let team = teams.first { $0.status == "active" && $0.memberships.contains { $0.platform == .iOS } }! - - let source = try XCTUnwrap(Bundle.module.url(forResource: "test", withExtension: "app")) - - let context = try XCTTry(SigningContext( - udid: Config.current.udid, - deviceName: SigningContext.hostName, - teamID: team.id, - client: client, - signingInfoManager: MemoryBackedSigningInfoManager() - )) - - let response = try await DeveloperServicesProvisioningOperation( - context: context, - app: source, - confirmRevocation: { _ in true }, - progress: { _ in } - ).perform() - print(response) - } - - func testListTeams() async throws { - let listTeams = DeveloperServicesListTeamsRequest() - let teams = try await client.send(listTeams) - XCTAssertFalse(teams.isEmpty, "No teams found") - - let team = try XCTUnwrap( - teams.first { $0.id.rawValue == Config.current.preferredTeam }, - "Could not find preferred team" - ) - - XCTAssertEqual(team.status, "active", "Expected team status active. Got: \(team.status)") - XCTAssert(team.memberships.contains { $0.platform == .iOS }, "Team does not have iOS membership") - } - -} diff --git a/Tests/XKitTests/Tests/XKitGrandSlamTests.swift b/Tests/XKitTests/Tests/XKitGrandSlamTests.swift deleted file mode 100644 index af9f92de..00000000 --- a/Tests/XKitTests/Tests/XKitGrandSlamTests.swift +++ /dev/null @@ -1,67 +0,0 @@ -// -// XKitGrandSlamTests.swift -// XKitTests -// -// Created by Kabir Oberai on 10/04/20. -// Copyright © 2020 Kabir Oberai. All rights reserved. -// - -// swiftlint:disable force_try - -import XCTest -import SuperutilsTestSupport -@testable import XKit - -final class TwoFactorAuthenticator: TwoFactorAuthDelegate { - func fetchCode() async -> String? { - print("Code: ", terminator: "") - return readLine() ?? "" - } -} - -class XKitGrandSlamTests: XCTestCase { - - var authenticator: TwoFactorAuthenticator! - var storage: KeyValueStorage! - var client: GrandSlamClient! - - override func setUp() { - super.setUp() - _ = addMockSigner - storage = MemoryKeyValueStorage() - client = try! .test(storage: storage) - authenticator = TwoFactorAuthenticator() - } - - override func tearDown() { - super.tearDown() - client = nil - authenticator = nil - } - - func testAuthentication() async throws { - let loginData = try await GrandSlamAuthenticateOperation( - client: client, - username: Config.current.appleID.username, - password: Config.current.appleID.password, - twoFactorDelegate: authenticator - ).authenticate() - XCTAssertFalse(loginData.adsid.isEmpty) - XCTAssertFalse(loginData.cookie.isEmpty) - XCTAssertFalse(loginData.identityToken.isEmpty) - XCTAssertFalse(loginData.idmsToken.isEmpty) - XCTAssertFalse(loginData.sk.isEmpty) - - let now = Date() // *before* the actual request is made - - let tokens = try await GrandSlamFetchAppTokensOperation( - client: client, - apps: [.xcode], - loginData: loginData - ).perform() - let token = try XCTUnwrap(tokens[.xcode], "Xcode token absent from response") - XCTAssertGreaterThanOrEqual(token.expiry, now) - XCTAssertFalse(token.value.isEmpty) - } - -} diff --git a/Tests/XKitTests/Tests/XKitSigningTests.swift b/Tests/XKitTests/Tests/XKitSigningTests.swift deleted file mode 100644 index bdfead8c..00000000 --- a/Tests/XKitTests/Tests/XKitSigningTests.swift +++ /dev/null @@ -1,90 +0,0 @@ -// -// XKitSigningTests.swift -// XKitTests -// -// Created by Kabir Oberai on 06/11/19. -// Copyright © 2019 Kabir Oberai. All rights reserved. -// - -// TODO: Test using mock signer - -#if false - -import XCTest -import SuperutilsTestSupport -import XKit - -class XKitSigningTests: XCTestCase { - - var client: DeveloperServicesClient! - var signerImpl: SignerImpl! - var app: URL! - - // swiftlint:disable force_try - override func setUp() { - super.setUp() - _ = addMockSigner - client = .test() - signerImpl = try! SignerImpl.first() - - let source = try! XCTUnwrap(Bundle.module.url(forResource: "test", withExtension: "app")) - let tmp = FileManager.default.temporaryDirectory - app = tmp.appendingPathComponent(source.lastPathComponent) - if FileManager.default.fileExists(atPath: app.path) { - try! FileManager.default.removeItem(at: app) - } - try! FileManager.default.copyItem(at: source, to: app) - } - - override func tearDown() { - super.tearDown() - client = nil - signerImpl = nil - try! FileManager.default.removeItem(at: app) - app = nil - } - // swiftlint:enable force_try - - // integration test for signing - @MainActor func testSigningIntegration() throws { - let listTeams = DeveloperServicesListTeamsRequest() - let teams = try XCTTry(client.sendTest(listTeams)) - let team = teams.first { $0.status == "active" && $0.memberships.contains { $0.platform == .iOS } }! - - let context = try XCTTry(SigningContext( - udid: Config.current.udid, - deviceName: SigningContext.hostName, - teamID: team.id, - client: client, - signingInfoManager: MemoryBackedSigningInfoManager(), - signerImpl: signerImpl - )) - let signer = Signer(context: context) - - let signingWaiter = ResultWaiter<()>(description: "Failed to sign app") - signer.sign(app: app, status: { _ in }, progress: { _ in }, completion: signingWaiter.completion) - try XCTTry(signingWaiter.wait(timeout: 10000)) - - // TODO: Ensure entitlements are correct in new app, also codesign -vvvv - } - - func testAnalyze() throws { - let infoURL = app.appendingPathComponent("Info.plist") - let info = try XCTUnwrap(NSDictionary(contentsOf: infoURL)) - let execName = try XCTUnwrap(info[kCFBundleExecutableKey as String] as? String) - let exec = app.appendingPathComponent(execName) - - let ents = try XCTUnwrap(signerImpl.analyze(executable: exec)) - let entsPlist = try XCTTry(PropertyListDecoder().decode(Entitlements.self, from: ents)) - - XCTAssertFalse(try XCTTry(entsPlist.entitlements().isEmpty)) - } - - func testSign() throws { - let signingWaiter = ResultWaiter<()>(description: "Failed to sign app") - // TODO: Get cert, key, ents from fixtures - } - -} - -#endif diff --git a/Tests/XKitTests/Utilities/Config.swift b/Tests/XKitTests/Utilities/Config.swift deleted file mode 100644 index a85bcd83..00000000 --- a/Tests/XKitTests/Utilities/Config.swift +++ /dev/null @@ -1,32 +0,0 @@ -// -// Config.swift -// XKitTests -// -// Created by Kabir Oberai on 05/11/19. -// Copyright © 2019 Kabir Oberai. All rights reserved. -// - -import Foundation -import XKit - -struct Config: Decodable { - struct AppleID: Decodable { - let username: String - let password: String - /// for non-login tests, just provide a token already - let token: DeveloperServicesLoginToken - } - - let appleID: AppleID - let deviceInfo: DeviceInfo - let preferredTeam: String - let udid: String - - static let current: Config = { - let url = Bundle.module.url(forResource: "config", withExtension: "json")! - // swiftlint:disable:next force_try - let data = try! Data(contentsOf: url) - // swiftlint:disable:next force_try - return try! JSONDecoder().decode(Config.self, from: data) - }() -} diff --git a/Tests/XKitTests/Utilities/DeveloperServicesClient+Testing.swift b/Tests/XKitTests/Utilities/DeveloperServicesClient+Testing.swift deleted file mode 100644 index 03b6b1f9..00000000 --- a/Tests/XKitTests/Utilities/DeveloperServicesClient+Testing.swift +++ /dev/null @@ -1,62 +0,0 @@ -// -// DeveloperServicesTestClient.swift -// XKitTests -// -// Created by Kabir Oberai on 06/11/19. -// Copyright © 2019 Kabir Oberai. All rights reserved. -// - -import Foundation -import XCTest -@testable import XKit - -#if false - -extension TCPAnisetteDataProvider { - - static func test() -> TCPAnisetteDataProvider { - TCPAnisetteDataProvider(localPort: 4321) - } - -} - -extension NetcatAnisetteDataProvider { - - static func test() -> NetcatAnisetteDataProvider { - NetcatAnisetteDataProvider(localPort: 4322, deviceInfo: Config.current.deviceInfo) - } - -} - -#endif - -extension ADIDataProvider { - - static func test(storage: KeyValueStorage) throws -> ADIDataProvider { - try adiProvider(deviceInfo: Config.current.deviceInfo, storage: storage) - } - -} - -extension GrandSlamClient { - - static func test(storage: KeyValueStorage) throws -> GrandSlamClient { - try GrandSlamClient( - deviceInfo: Config.current.deviceInfo, - anisetteProvider: ADIDataProvider.test(storage: storage) - ) - } - -} - -extension DeveloperServicesClient { - - static func test(storage: KeyValueStorage) throws -> DeveloperServicesClient { - try DeveloperServicesClient( - loginToken: Config.current.appleID.token, - deviceInfo: Config.current.deviceInfo, - anisetteProvider: ADIDataProvider.test(storage: storage) - ) - } - -} diff --git a/Tests/XKitTests/Utilities/MockSigner.swift b/Tests/XKitTests/Utilities/MockSigner.swift deleted file mode 100644 index 908eadcd..00000000 --- a/Tests/XKitTests/Utilities/MockSigner.swift +++ /dev/null @@ -1,16 +0,0 @@ -import Foundation -import SignerSupport - -let addMockSigner: () = { - add_signer( - "MockSigner", - { _, _, _, _, _, _, _, _, _, exception in - exception.initialize(to: strdup("Mock signer not implemented")) - return 1 - }, - { _, _, exception in - exception.initialize(to: strdup("Mock analyzer not implemented")) - return nil - } - ) -}() diff --git a/Tests/XKitTests/config/config-template.json b/Tests/XKitTests/config/config-template.json deleted file mode 100644 index e577670a..00000000 --- a/Tests/XKitTests/config/config-template.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "appleID": { - "username": "", - "password": "", - "token": { - "adsid": "", - "token": "", - "expiry": 0 - } - }, - "deviceInfo": { - "clientInfo": { - "macOSBuild": "", - "darwinVersion": "", - "macOSVersion": "", - "akdVersion": "", - "cfNetworkVersion": "", - "authKitVersion": "", - "modelID": "", - }, - "xcodeInfo": { - "version": "", - "build": "" - }, - "deviceID": "", - "mlbSerialNumber": "", - "romAddress": "", - "serialNumber": "" - }, - "preferredTeam": "", - "udid": "", -}