Start working on the validation

This commit is contained in:
Pedro Piñera 2018-04-22 22:22:54 +02:00
parent 9347df368e
commit ae82c7d5b0
6 changed files with 112 additions and 8 deletions

View File

@ -92,6 +92,9 @@
B9F1EDEF208D1DB200477835 /* BuildPhase+TestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EDEE208D1DB200477835 /* BuildPhase+TestData.swift */; };
B9F1EDF1208D1F0F00477835 /* Settings+TestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EDF0208D1F0F00477835 /* Settings+TestData.swift */; };
B9F1EDF3208D200C00477835 /* Scheme+TestData.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EDF2208D200C00477835 /* Scheme+TestData.swift */; };
B9F1EDF6208D228600477835 /* ProjectValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EDF5208D228600477835 /* ProjectValidator.swift */; };
B9F1EDF8208D22D900477835 /* TargetValidator.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EDF7208D22D900477835 /* TargetValidator.swift */; };
B9F1EDFB208D24F700477835 /* ProjectValidatorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B9F1EDFA208D24F700477835 /* ProjectValidatorTests.swift */; };
B9FB2DBF2086506E00BC2FB3 /* Basic.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = B9FB2DBB20864FF800BC2FB3 /* Basic.framework */; };
B9FB2DC62086515F00BC2FB3 /* Basic.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B9FB2DBB20864FF800BC2FB3 /* Basic.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
B9FB2DC72086516500BC2FB3 /* POSIX.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = B9FB2DC02086507200BC2FB3 /* POSIX.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
@ -298,6 +301,9 @@
B9F1EDEE208D1DB200477835 /* BuildPhase+TestData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "BuildPhase+TestData.swift"; sourceTree = "<group>"; };
B9F1EDF0208D1F0F00477835 /* Settings+TestData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Settings+TestData.swift"; sourceTree = "<group>"; };
B9F1EDF2208D200C00477835 /* Scheme+TestData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Scheme+TestData.swift"; sourceTree = "<group>"; };
B9F1EDF5208D228600477835 /* ProjectValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectValidator.swift; sourceTree = "<group>"; };
B9F1EDF7208D22D900477835 /* TargetValidator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TargetValidator.swift; sourceTree = "<group>"; };
B9F1EDFA208D24F700477835 /* ProjectValidatorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProjectValidatorTests.swift; sourceTree = "<group>"; };
B9FB2DBB20864FF800BC2FB3 /* Basic.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Basic.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B9FB2DBD2086502100BC2FB3 /* Utility.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Utility.framework; sourceTree = BUILT_PRODUCTS_DIR; };
B9FB2DC02086507200BC2FB3 /* POSIX.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = POSIX.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@ -411,6 +417,7 @@
B915ED3B2063B04C004B6630 /* Tests */ = {
isa = PBXGroup;
children = (
B9F1EDF9208D24EA00477835 /* Validator */,
B9589605208B4E3500F00ACF /* Generator */,
B92BF9FC2075607C00EE4EBD /* Extensions */,
B92BF9ED2075599900EE4EBD /* Models */,
@ -425,6 +432,7 @@
B915ED3E2063B04C004B6630 /* Sources */ = {
isa = PBXGroup;
children = (
B9F1EDF4208D215600477835 /* Validator */,
B95895F1208A2A9E00F00ACF /* Generator */,
B9B6299C20864E2300EE9E07 /* App */,
B9B629BD20864E7D00EE9E07 /* Commands */,
@ -643,6 +651,23 @@
path = Models;
sourceTree = "<group>";
};
B9F1EDF4208D215600477835 /* Validator */ = {
isa = PBXGroup;
children = (
B9F1EDF5208D228600477835 /* ProjectValidator.swift */,
B9F1EDF7208D22D900477835 /* TargetValidator.swift */,
);
path = Validator;
sourceTree = "<group>";
};
B9F1EDF9208D24EA00477835 /* Validator */ = {
isa = PBXGroup;
children = (
B9F1EDFA208D24F700477835 /* ProjectValidatorTests.swift */,
);
path = Validator;
sourceTree = "<group>";
};
B9FB2DCD2086538E00BC2FB3 /* Loader */ = {
isa = PBXGroup;
children = (
@ -961,7 +986,9 @@
B9FB2DE62086544900BC2FB3 /* Scheme.swift in Sources */,
B95895FB208A2FFB00F00ACF /* WorkspaceGenerator.swift in Sources */,
B9589600208A37B700F00ACF /* GraphJSONInitiatable.swift in Sources */,
B9F1EDF8208D22D900477835 /* TargetValidator.swift in Sources */,
B9B6299F20864E2300EE9E07 /* Constants.swift in Sources */,
B9F1EDF6208D228600477835 /* ProjectValidator.swift in Sources */,
B9FB2DCA2086527B00BC2FB3 /* BuildFiles.swift in Sources */,
B9FB2DE1208653F500BC2FB3 /* GraphController.swift in Sources */,
B9B629AA20864E3A00EE9E07 /* TechLogger.swift in Sources */,
@ -986,6 +1013,7 @@
B9F1EDED208D1CFE00477835 /* Target+TestData.swift in Sources */,
B9F1EDD3208CD2E200477835 /* ShellCompletion+Equatable.swift in Sources */,
B9E2DC9E20872D400061DF86 /* AppTests.swift in Sources */,
B9F1EDFB208D24F700477835 /* ProjectValidatorTests.swift in Sources */,
B9E2DC9720872B5D0061DF86 /* MockManifestLoader.swift in Sources */,
B9E2DCC82089B78D0061DF86 /* DumpCommandTests.swift in Sources */,
B9E2DCA32087651D0061DF86 /* Project+TestData.swift in Sources */,

View File

@ -0,0 +1,42 @@
import Basic
import Foundation
enum ProjectValidationError: Error, CustomStringConvertible, Equatable {
case duplicatedTargets([String], AbsolutePath)
var description: String {
switch self {
case let .duplicatedTargets(targets, projectPath):
return "Targets \(targets.joined(separator: ", ")) from project at \(projectPath.asString) have duplicates."
}
}
static func == (lhs: ProjectValidationError, rhs: ProjectValidationError) -> Bool {
switch (lhs, rhs) {
case let (.duplicatedTargets(lhsTargets, lhsPath), .duplicatedTargets(rhsTargets, rhsPath)):
return lhsTargets == rhsTargets && lhsPath == rhsPath
}
}
}
/// Validates the format of the project.
class ProjectValidator {
let targetValidator: TargetValidator = TargetValidator()
func validate(_ project: Project) throws {
try validateTargets(project: project)
}
fileprivate func validateTargets(project: Project) throws {
try project.targets.forEach(targetValidator.validate)
try validateNotDuplicatedTargets(project: project)
}
fileprivate func validateNotDuplicatedTargets(project: Project) throws {
let duplicatedTargets = project.targets.map({ $0.name })
.reduce(into: [String: Int]()) { $0[$1] = ($0[$1] ?? 0) + 1 }
.filter({ $0.value > 1 })
.keys
if duplicatedTargets.count == 0 { return }
throw ProjectValidationError.duplicatedTargets(Array(duplicatedTargets), project.path)
}
}

View File

@ -0,0 +1,6 @@
import Foundation
class TargetValidator {
func validate(_: Target) throws {
}
}

View File

@ -3,12 +3,12 @@ import Foundation
@testable import xcbuddykit
extension Project {
static func testData(path: AbsolutePath = AbsolutePath("/test/"),
name: String = "Project",
config: Config? = nil,
schemes: [Scheme] = [Scheme.test()],
settings: Settings? = Settings.test(),
targets: [Target] = [Target.test()]) -> Project {
static func test(path: AbsolutePath = AbsolutePath("/test/"),
name: String = "Project",
config: Config? = nil,
schemes: [Scheme] = [Scheme.test()],
settings: Settings? = Settings.test(),
targets: [Target] = [Target.test()]) -> Project {
return Project(path: path,
name: name,
config: config,

View File

@ -6,8 +6,8 @@ extension Target {
static func test(name: String = "Target",
platform: Platform = .ios,
product: Product = .module,
infoPlist: AbsolutePath = AbsolutePath("Info.plist"),
entitlements: AbsolutePath? = AbsolutePath("Test.entitlements"),
infoPlist: AbsolutePath = AbsolutePath("/Info.plist"),
entitlements: AbsolutePath? = AbsolutePath("/Test.entitlements"),
settings: Settings? = Settings.test(),
buildPhases: [BuildPhase] = [
SourcesBuildPhase.test(),

View File

@ -0,0 +1,28 @@
import Basic
import Foundation
@testable import xcbuddykit
import XCTest
final class ProjectValidationErrorTests: XCTestCase {
func test_description_whenDuplicatedTargets() {
let error = ProjectValidationError.duplicatedTargets(["A", "B"], AbsolutePath("/test"))
XCTAssertEqual(error.description, "Targets A, B from project at /test have duplicates.")
}
}
final class ProjectValidatorTests: XCTestCase {
var subject: ProjectValidator!
override func setUp() {
super.setUp()
subject = ProjectValidator()
}
func test_validate_throws_when_there_are_duplicated_targets() throws {
let target = Target.test(name: "A")
let project = Project.test(targets: [target, target])
XCTAssertThrowsError(try subject.validate(project)) { error in
XCTAssertEqual(error as? ProjectValidationError, ProjectValidationError.duplicatedTargets(["A"], project.path))
}
}
}