From d69b0282944da0aeab2f2bb1843aa57fd005eda3 Mon Sep 17 00:00:00 2001 From: Liam Nichols Date: Thu, 6 Feb 2020 10:45:21 +0000 Subject: [PATCH] Update SpecValidation to validate TargetReference definitions in the Scheme.Test action. Add additional coverate to ProjectSpectTests --- Sources/ProjectSpec/SpecValidation.swift | 33 ++++++++++++------- Sources/ProjectSpec/SpecValidationError.swift | 6 ++-- Tests/ProjectSpecTests/ProjectSpecTests.swift | 5 ++- 3 files changed, 28 insertions(+), 16 deletions(-) diff --git a/Sources/ProjectSpec/SpecValidation.swift b/Sources/ProjectSpec/SpecValidation.swift index 8dc4f19b..4d4e5849 100644 --- a/Sources/ProjectSpec/SpecValidation.swift +++ b/Sources/ProjectSpec/SpecValidation.swift @@ -194,24 +194,21 @@ extension Project { } for scheme in schemes { - for buildTarget in scheme.build.targets { - switch buildTarget.target.location { - case .local: - if getProjectTarget(buildTarget.target.name) == nil { - errors.append(.invalidSchemeTarget(scheme: scheme.name, target: buildTarget.target.name)) - } - case .project(let project): - if getProjectReference(project) == nil { - errors.append(.invalidProjectReference(scheme: scheme.name, reference: project)) - } - } - } + errors.append( + contentsOf: scheme.build.targets.compactMap({ validationError(for: $0.target, in: scheme, action: "build") }) + ) if let action = scheme.run, let config = action.config, getConfig(config) == nil { errors.append(.invalidSchemeConfig(scheme: scheme.name, config: config)) } if let action = scheme.test, let config = action.config, getConfig(config) == nil { errors.append(.invalidSchemeConfig(scheme: scheme.name, config: config)) } + errors.append( + contentsOf: scheme.test?.targets.compactMap({ validationError(for: $0.targetReference, in: scheme, action: "test") }) ?? [] + ) + errors.append( + contentsOf: scheme.test?.coverageTargets.compactMap({ validationError(for: $0, in: scheme, action: "test") }) ?? [] + ) if let action = scheme.profile, let config = action.config, getConfig(config) == nil { errors.append(.invalidSchemeConfig(scheme: scheme.name, config: config)) } @@ -233,4 +230,16 @@ extension Project { throw SpecValidationError.ValidationError.invalidXcodeGenVersion(minimumVersion: minimumXcodeGenVersion, version: xcodeGenVersion) } } + + /// Returns a descriptive error if the given target reference was invalid otherwise `nil`. + private func validationError(for targetReference: TargetReference, in scheme: Scheme, action: String) -> SpecValidationError.ValidationError? { + switch targetReference.location { + case .local where getProjectTarget(targetReference.name) == nil: + return .invalidSchemeTarget(scheme: scheme.name, target: targetReference.name, action: action) + case .project(let project) where getProjectReference(project) == nil: + return .invalidProjectReference(scheme: scheme.name, reference: project) + case .local, .project: + return nil + } + } } diff --git a/Sources/ProjectSpec/SpecValidationError.swift b/Sources/ProjectSpec/SpecValidationError.swift index 64df979d..8011fca8 100644 --- a/Sources/ProjectSpec/SpecValidationError.swift +++ b/Sources/ProjectSpec/SpecValidationError.swift @@ -16,7 +16,7 @@ public struct SpecValidationError: Error, CustomStringConvertible { case invalidTargetConfigFile(target: String, configFile: String, config: String) case invalidTargetSchemeConfigVariant(target: String, configVariant: String, configType: ConfigType) case invalidTargetSchemeTest(target: String, testTarget: String) - case invalidSchemeTarget(scheme: String, target: String) + case invalidSchemeTarget(scheme: String, target: String, action: String) case invalidSchemeConfig(scheme: String, config: String) case invalidSwiftPackage(name: String, target: String) case invalidLocalPackage(String) @@ -50,8 +50,8 @@ public struct SpecValidationError: Error, CustomStringConvertible { return "Target \(target.quoted) scheme has invalid test \(test.quoted)" case let .invalidConfigFile(configFile, config): return "Invalid config file \(configFile.quoted) for config \(config.quoted)" - case let .invalidSchemeTarget(scheme, target): - return "Scheme \(scheme.quoted) has invalid build target \(target.quoted)" + case let .invalidSchemeTarget(scheme, target, action): + return "Scheme \(scheme.quoted) has invalid \(action) target \(target.quoted)" case let .invalidSchemeConfig(scheme, config): return "Scheme \(scheme.quoted) has invalid build configuration \(config.quoted)" case let .invalidBuildSettingConfig(config): diff --git a/Tests/ProjectSpecTests/ProjectSpecTests.swift b/Tests/ProjectSpecTests/ProjectSpecTests.swift index e213d3b3..39b4f50a 100644 --- a/Tests/ProjectSpecTests/ProjectSpecTests.swift +++ b/Tests/ProjectSpecTests/ProjectSpecTests.swift @@ -209,12 +209,15 @@ class ProjectSpecTests: XCTestCase { name: "scheme1", build: .init(targets: [.init(target: "invalidTarget")]), run: .init(config: "debugInvalid"), + test: .init(config: "testInvalid", coverageTargets: ["SubProject/Yams"], targets: [.init(targetReference: "invalidTarget")]), archive: .init(config: "releaseInvalid") )] - try expectValidationError(project, .invalidSchemeTarget(scheme: "scheme1", target: "invalidTarget")) + try expectValidationError(project, .invalidSchemeTarget(scheme: "scheme1", target: "invalidTarget", action: "build")) try expectValidationError(project, .invalidSchemeConfig(scheme: "scheme1", config: "debugInvalid")) try expectValidationError(project, .invalidSchemeConfig(scheme: "scheme1", config: "releaseInvalid")) + try expectValidationError(project, .invalidSchemeTarget(scheme: "scheme1", target: "invalidTarget", action: "test")) + try expectValidationError(project, .invalidProjectReference(scheme: "scheme1", reference: "SubProject")) } $0.it("fails with invalid project reference in scheme") {