diff --git a/Fixtures/Schemes/RunnableWithoutBuildableReference.xcscheme b/Fixtures/Schemes/RunnableWithoutBuildableReference.xcscheme new file mode 100644 index 000000000..669fdba94 --- /dev/null +++ b/Fixtures/Schemes/RunnableWithoutBuildableReference.xcscheme @@ -0,0 +1,98 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Sources/XcodeProj/Scheme/XCScheme+LaunchAction.swift b/Sources/XcodeProj/Scheme/XCScheme+LaunchAction.swift index 3a4e8edca..28f794df5 100644 --- a/Sources/XcodeProj/Scheme/XCScheme+LaunchAction.swift +++ b/Sources/XcodeProj/Scheme/XCScheme+LaunchAction.swift @@ -148,7 +148,7 @@ extension XCScheme { selectedDebuggerIdentifier = element.attributes["selectedDebuggerIdentifier"] ?? XCScheme.defaultDebugger selectedLauncherIdentifier = element.attributes["selectedLauncherIdentifier"] ?? XCScheme.defaultLauncher launchStyle = element.attributes["launchStyle"].flatMap { Style(rawValue: $0) } ?? .auto - askForAppToLaunch = element.attributes["askForAppToLaunch"].map { $0 == "YES" } + askForAppToLaunch = element.attributes["askForAppToLaunch"].map { $0 == "YES" || $0 == "Yes" } useCustomWorkingDirectory = element.attributes["useCustomWorkingDirectory"] == "YES" ignoresPersistentStateOnLaunch = element.attributes["ignoresPersistentStateOnLaunch"] == "YES" debugDocumentVersioning = element.attributes["debugDocumentVersioning"].map { $0 == "YES" } ?? true diff --git a/Sources/XcodeProj/Scheme/XCScheme+ProfileAction.swift b/Sources/XcodeProj/Scheme/XCScheme+ProfileAction.swift index a91acf98a..c11e06dc8 100644 --- a/Sources/XcodeProj/Scheme/XCScheme+ProfileAction.swift +++ b/Sources/XcodeProj/Scheme/XCScheme+ProfileAction.swift @@ -60,7 +60,7 @@ extension XCScheme { savedToolIdentifier = element.attributes["savedToolIdentifier"] ?? "" useCustomWorkingDirectory = element.attributes["useCustomWorkingDirectory"] == "YES" debugDocumentVersioning = element.attributes["debugDocumentVersioning"].map { $0 == "YES" } ?? true - askForAppToLaunch = element.attributes["askForAppToLaunch"].map { $0 == "YES" } + askForAppToLaunch = element.attributes["askForAppToLaunch"].map { $0 == "YES" || $0 == "Yes" } ignoresPersistentStateOnLaunch = element.attributes["ignoresPersistentStateOnLaunch"].map { $0 == "YES" } ?? false let buildableProductRunnableElement = element["BuildableProductRunnable"] diff --git a/Sources/XcodeProj/Scheme/XCScheme+Runnable.swift b/Sources/XcodeProj/Scheme/XCScheme+Runnable.swift index 6fb8b489e..b7173dc2c 100644 --- a/Sources/XcodeProj/Scheme/XCScheme+Runnable.swift +++ b/Sources/XcodeProj/Scheme/XCScheme+Runnable.swift @@ -6,7 +6,7 @@ extension XCScheme { // MARK: - Attributes public var runnableDebuggingMode: String - public var buildableReference: BuildableReference + public var buildableReference: BuildableReference? // MARK: - Init @@ -18,7 +18,7 @@ extension XCScheme { init(element: AEXMLElement) throws { runnableDebuggingMode = element.attributes["runnableDebuggingMode"] ?? "0" - buildableReference = try BuildableReference(element: element["BuildableReference"]) + buildableReference = try? BuildableReference(element: element["BuildableReference"]) } // MARK: - XML @@ -27,7 +27,9 @@ extension XCScheme { let element = AEXMLElement(name: "Runnable", value: nil, attributes: ["runnableDebuggingMode": runnableDebuggingMode]) - element.addChild(buildableReference.xmlElement()) + if let buildableReference = buildableReference { + element.addChild(buildableReference.xmlElement()) + } return element } diff --git a/Tests/XcodeProjTests/Scheme/XCSchemeTests.swift b/Tests/XcodeProjTests/Scheme/XCSchemeTests.swift index 8a6325a1a..98fcc5190 100644 --- a/Tests/XcodeProjTests/Scheme/XCSchemeTests.swift +++ b/Tests/XcodeProjTests/Scheme/XCSchemeTests.swift @@ -15,6 +15,34 @@ final class XCSchemeIntegrationTests: XCTestCase { modify: { $0 }, assertion: { assert(scheme: $1) }) } + + func test_read_runnableWithoutBuildableReferenceScheme() { + let subject = try? XCScheme(path: runnableWithoutBuildableReferenceSchemePath) + + XCTAssertNotNil(subject) + if let subject = subject { + assert(runnableWithoutBuildableReferenceScheme: subject) + } + } + + func test_remoteRunnable_runnableWithoutBuildableReferenceScheme() throws { + // Given / When + let subject = try XCScheme(path: runnableWithoutBuildableReferenceSchemePath) + + // Then + let launchAction = try XCTUnwrap(subject.launchAction) + let remoteRunnable = try XCTUnwrap(launchAction.runnable as? XCScheme.RemoteRunnable) + XCTAssertEqual(remoteRunnable.bundleIdentifier, "me.ava.Ava-Staging") + XCTAssertEqual(remoteRunnable.runnableDebuggingMode, "1") + XCTAssertEqual(remoteRunnable.remotePath, "/var/containers/Bundle/Application/018F0933-05E8-4359-9955-39E0523C4246/Ava.app") + } + + func test_write_runnableWithoutBuildableReferenceScheme() { + testWrite(from: runnableWithoutBuildableReferenceSchemePath, + initModel: { try? XCScheme(path: $0) }, + modify: { $0 }, + assertion: { assert(runnableWithoutBuildableReferenceScheme: $1) }) + } func test_read_minimalScheme() { let subject = try? XCScheme(path: minimalSchemePath) @@ -372,11 +400,11 @@ final class XCSchemeIntegrationTests: XCTestCase { XCTAssertEqual(scheme.profileAction?.debugDocumentVersioning, true) XCTAssertNil(scheme.profileAction?.askForAppToLaunch) XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.runnableDebuggingMode, "0") - XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference.buildableIdentifier, "primary") - XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference.blueprintIdentifier, "23766C111EAA3484007A9026") - XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference.buildableName, "iOS.app") - XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference.blueprintName, "iOS") - XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference.referencedContainer, "container:Project.xcodeproj") + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference?.buildableIdentifier, "primary") + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference?.blueprintIdentifier, "23766C111EAA3484007A9026") + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference?.buildableName, "iOS.app") + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference?.blueprintName, "iOS") + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference?.referencedContainer, "container:Project.xcodeproj") XCTAssertEqual(scheme.profileAction?.preActions.isEmpty, true) XCTAssertEqual(scheme.profileAction?.postActions.first?.title, "Run Script") XCTAssertEqual(scheme.profileAction?.postActions.first?.scriptText, "echo analysis done") @@ -404,11 +432,11 @@ final class XCSchemeIntegrationTests: XCTestCase { XCTAssertEqual(scheme.launchAction?.debugServiceExtension, "internal") XCTAssertEqual(scheme.launchAction?.allowLocationSimulation, true) XCTAssertEqual(scheme.launchAction?.runnable?.runnableDebuggingMode, "0") - XCTAssertEqual(scheme.launchAction?.runnable?.buildableReference.buildableIdentifier, "primary") - XCTAssertEqual(scheme.launchAction?.runnable?.buildableReference.blueprintIdentifier, "23766C111EAA3484007A9026") - XCTAssertEqual(scheme.launchAction?.runnable?.buildableReference.buildableName, "iOS.app") - XCTAssertEqual(scheme.launchAction?.runnable?.buildableReference.blueprintName, "iOS") - XCTAssertEqual(scheme.launchAction?.runnable?.buildableReference.referencedContainer, "container:Project.xcodeproj") + XCTAssertEqual(scheme.launchAction?.runnable?.buildableReference?.buildableIdentifier, "primary") + XCTAssertEqual(scheme.launchAction?.runnable?.buildableReference?.blueprintIdentifier, "23766C111EAA3484007A9026") + XCTAssertEqual(scheme.launchAction?.runnable?.buildableReference?.buildableName, "iOS.app") + XCTAssertEqual(scheme.launchAction?.runnable?.buildableReference?.blueprintName, "iOS") + XCTAssertEqual(scheme.launchAction?.runnable?.buildableReference?.referencedContainer, "container:Project.xcodeproj") XCTAssertEqual(scheme.launchAction?.locationScenarioReference?.identifier, "com.apple.dt.IDEFoundation.CurrentLocationScenarioIdentifier") XCTAssertEqual(scheme.launchAction?.locationScenarioReference?.referenceType, "1") XCTAssertEqual(scheme.launchAction?.preActions.first?.title, "") @@ -447,6 +475,109 @@ final class XCSchemeIntegrationTests: XCTestCase { XCTAssertTrue(launchCLIArgs.arguments[0].enabled) XCTAssertNil(scheme.launchAction?.customLLDBInitFile) } + + private func assert(runnableWithoutBuildableReferenceScheme scheme: XCScheme) { + XCTAssertEqual(scheme.version, "2.0") + XCTAssertEqual(scheme.lastUpgradeVersion, "1230", "\(scheme.lastUpgradeVersion!) not equals 1230") + + // Build action + XCTAssertTrue(scheme.buildAction?.parallelizeBuild == true) + XCTAssertTrue(scheme.buildAction?.buildImplicitDependencies == true) + XCTAssertNil(scheme.buildAction?.runPostActionsOnFailure) + XCTAssertEqual(scheme.buildAction?.buildActionEntries.count, 2) + XCTAssertTrue(scheme.buildAction?.buildActionEntries[0].buildFor.contains(.testing) == true) + XCTAssertTrue(scheme.buildAction?.buildActionEntries[0].buildFor.contains(.running) == true) + XCTAssertTrue(scheme.buildAction?.buildActionEntries[0].buildFor.contains(.profiling) == true) + XCTAssertTrue(scheme.buildAction?.buildActionEntries[0].buildFor.contains(.archiving) == true) + XCTAssertTrue(scheme.buildAction?.buildActionEntries[0].buildFor.contains(.analyzing) == true) + XCTAssertEqual(scheme.buildAction?.buildActionEntries[0].buildableReference.buildableIdentifier, "primary") + XCTAssertEqual(scheme.buildAction?.buildActionEntries[0].buildableReference.blueprintIdentifier, "FE7C11D21B6DB70D0041DF02") + XCTAssertEqual(scheme.buildAction?.buildActionEntries[0].buildableReference.buildableName, "Ava.app") + XCTAssertEqual(scheme.buildAction?.buildActionEntries[0].buildableReference.blueprintName, "core-ava") + XCTAssertEqual(scheme.buildAction?.buildActionEntries[0].buildableReference.referencedContainer, "container:core-ava.xcodeproj") + + XCTAssertTrue(scheme.buildAction?.buildActionEntries[1].buildFor.contains(.testing) == true) + XCTAssertTrue(scheme.buildAction?.buildActionEntries[1].buildFor.contains(.running) == false) + XCTAssertTrue(scheme.buildAction?.buildActionEntries[1].buildFor.contains(.profiling) == false) + XCTAssertTrue(scheme.buildAction?.buildActionEntries[1].buildFor.contains(.archiving) == false) + XCTAssertTrue(scheme.buildAction?.buildActionEntries[1].buildFor.contains(.analyzing) == false) + XCTAssertEqual(scheme.buildAction?.buildActionEntries[1].buildableReference.buildableIdentifier, "primary") + XCTAssertEqual(scheme.buildAction?.buildActionEntries[1].buildableReference.blueprintIdentifier, "9942115E25C4D3B7000711CE") + XCTAssertEqual(scheme.buildAction?.buildActionEntries[1].buildableReference.buildableName, "AvaTests.xctest") + XCTAssertEqual(scheme.buildAction?.buildActionEntries[1].buildableReference.blueprintName, "AvaTests") + XCTAssertEqual(scheme.buildAction?.buildActionEntries[1].buildableReference.referencedContainer, "container:core-ava.xcodeproj") + + // Test action + XCTAssertEqual(scheme.testAction?.buildConfiguration, "Debug") + XCTAssertEqual(scheme.testAction?.selectedDebuggerIdentifier, "Xcode.DebuggerFoundation.Debugger.LLDB") + XCTAssertEqual(scheme.testAction?.selectedLauncherIdentifier, "Xcode.DebuggerFoundation.Launcher.LLDB") + XCTAssertTrue(scheme.testAction?.shouldUseLaunchSchemeArgsEnv == true) + XCTAssertTrue(scheme.testAction?.codeCoverageEnabled == false) + XCTAssertEqual(scheme.testAction?.onlyGenerateCoverageForSpecifiedTargets, nil) + XCTAssertNil(scheme.testAction?.macroExpansion) + XCTAssertEqual(scheme.testAction?.enableAddressSanitizer, false) + XCTAssertEqual(scheme.testAction?.enableASanStackUseAfterReturn, false) + XCTAssertEqual(scheme.testAction?.enableThreadSanitizer, false) + XCTAssertEqual(scheme.testAction?.enableUBSanitizer, false) + XCTAssertEqual(scheme.testAction?.disableMainThreadChecker, false) + XCTAssertEqual(scheme.testAction?.additionalOptions.isEmpty, true) + XCTAssertNil(scheme.testAction?.commandlineArguments) + XCTAssertNil(scheme.testAction?.environmentVariables) + + // Launch action + XCTAssertEqual(scheme.launchAction?.selectedDebuggerIdentifier, XCScheme.defaultDebugger) + XCTAssertEqual(scheme.launchAction?.selectedLauncherIdentifier, XCScheme.defaultLauncher) + XCTAssertEqual(scheme.launchAction?.buildConfiguration, "Staging") + XCTAssertEqual(scheme.launchAction?.launchStyle, XCScheme.LaunchAction.Style.auto) + XCTAssertTrue(scheme.launchAction?.askForAppToLaunch == true) + XCTAssertTrue(scheme.launchAction?.useCustomWorkingDirectory == false) + XCTAssertTrue(scheme.launchAction?.ignoresPersistentStateOnLaunch == false) + XCTAssertTrue(scheme.launchAction?.debugDocumentVersioning == true) + XCTAssertEqual(scheme.launchAction?.debugServiceExtension, XCScheme.LaunchAction.defaultDebugServiceExtension) + XCTAssertTrue(scheme.launchAction?.allowLocationSimulation == true) + XCTAssertNil(scheme.launchAction?.locationScenarioReference) + XCTAssertNil(scheme.launchAction?.commandlineArguments) + XCTAssertEqual(scheme.launchAction?.enableAddressSanitizer, false) + XCTAssertEqual(scheme.launchAction?.enableASanStackUseAfterReturn, false) + XCTAssertEqual(scheme.launchAction?.enableThreadSanitizer, false) + XCTAssertEqual(scheme.launchAction?.stopOnEveryThreadSanitizerIssue, false) + XCTAssertEqual(scheme.launchAction?.enableUBSanitizer, false) + XCTAssertEqual(scheme.launchAction?.stopOnEveryUBSanitizerIssue, false) + XCTAssertEqual(scheme.launchAction?.disableMainThreadChecker, false) + XCTAssertEqual(scheme.launchAction?.stopOnEveryMainThreadCheckerIssue, false) + XCTAssertEqual(scheme.launchAction?.additionalOptions.isEmpty, true) + XCTAssertNil(scheme.launchAction?.storeKitConfigurationFileReference) + XCTAssertEqual(scheme.launchAction?.macroExpansion?.buildableIdentifier, "primary") + XCTAssertEqual(scheme.launchAction?.macroExpansion?.blueprintIdentifier, "FE7C11D21B6DB70D0041DF02") + XCTAssertEqual(scheme.launchAction?.macroExpansion?.buildableName, "Ava.app") + XCTAssertEqual(scheme.launchAction?.macroExpansion?.blueprintName, "core-ava") + XCTAssertEqual(scheme.launchAction?.macroExpansion?.referencedContainer, "container:core-ava.xcodeproj") + XCTAssertNil(scheme.launchAction?.environmentVariables) + + // Profile action + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.runnableDebuggingMode, "0") + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference?.blueprintIdentifier, "FE7C11D21B6DB70D0041DF02") + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference?.buildableIdentifier, "primary") + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference?.blueprintName, "core-ava") + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference?.buildableName, "Ava.app") + XCTAssertEqual(scheme.profileAction?.buildableProductRunnable?.buildableReference?.referencedContainer, "container:core-ava.xcodeproj") + XCTAssertEqual(scheme.profileAction?.buildConfiguration, "Release") + XCTAssertTrue(scheme.profileAction?.shouldUseLaunchSchemeArgsEnv == true) + XCTAssertEqual(scheme.profileAction?.savedToolIdentifier, "") + XCTAssertTrue(scheme.profileAction?.useCustomWorkingDirectory == false) + XCTAssertTrue(scheme.profileAction?.debugDocumentVersioning == true) + XCTAssertNil(scheme.profileAction?.askForAppToLaunch) + XCTAssertNil(scheme.profileAction?.commandlineArguments) + XCTAssertNil(scheme.profileAction?.environmentVariables) + + // Analyze action + XCTAssertEqual(scheme.analyzeAction?.buildConfiguration, "Debug") + + // Archive action + XCTAssertEqual(scheme.archiveAction?.buildConfiguration, "Release") + XCTAssertTrue(scheme.archiveAction?.revealArchiveInOrganizer == true) + XCTAssertNil(scheme.archiveAction?.customArchiveName) + } private func assert(minimalScheme scheme: XCScheme) { XCTAssertEqual(scheme.version, "1.3") @@ -557,6 +688,10 @@ final class XCSchemeIntegrationTests: XCTestCase { // but minimal in the sense it doesn't have most of the standard elements and attributes. fixturesPath() + "Schemes/MinimalInformation.xcscheme" } + + private var runnableWithoutBuildableReferenceSchemePath: Path { + fixturesPath() + "Schemes/RunnableWithoutBuildableReference.xcscheme" + } /// Path to a scheme with a buildable reference that contains no blueprint identifier private var noBlueprintIDPath: Path {