Files
swift-argument-parser/Tests/ArgumentParserEndToEndTests/NestedCommandEndToEndTests.swift

200 lines
6.8 KiB
Swift

//===----------------------------------------------------------*- swift -*-===//
//
// This source file is part of the Swift Argument Parser open source project
//
// Copyright (c) 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
//
//===----------------------------------------------------------------------===//
import XCTest
import ArgumentParserTestHelpers
import ArgumentParser
final class NestedCommandEndToEndTests: XCTestCase {
}
// MARK: Single value String
private struct Foo: ParsableCommand {
static var configuration = CommandConfiguration(
shouldPromptForMissing: false,
subcommands: [Build.self, Package.self])
@Flag(name: .short)
var verbose: Bool = false
struct Build: ParsableCommand {
static var configuration = CommandConfiguration(shouldPromptForMissing: false)
@OptionGroup() var foo: Foo
@Argument()
var input: String
}
struct Package: ParsableCommand {
static var configuration = CommandConfiguration(
shouldPromptForMissing: false,
subcommands: [Clean.self, Config.self])
@Flag(name: .short)
var force: Bool = false
struct Clean: ParsableCommand {
static var configuration = CommandConfiguration(shouldPromptForMissing: false)
@OptionGroup() var foo: Foo
@OptionGroup() var package: Package
}
struct Config: ParsableCommand {
static var configuration = CommandConfiguration(shouldPromptForMissing: false)
@OptionGroup() var foo: Foo
@OptionGroup() var package: Package
}
}
}
fileprivate func AssertParseFooCommand<A>(_ type: A.Type, _ arguments: [String], file: StaticString = #file, line: UInt = #line, closure: (A) throws -> Void) where A: ParsableCommand {
AssertParseCommand(Foo.self, type, arguments, file: file, line: line, closure: closure)
}
extension NestedCommandEndToEndTests {
func testParsing_package() throws {
AssertParseFooCommand(Foo.Package.self, ["package"]) { package in
XCTAssertFalse(package.force)
}
AssertParseFooCommand(Foo.Package.Clean.self, ["package", "clean"]) { clean in
XCTAssertEqual(clean.foo.verbose, false)
XCTAssertEqual(clean.package.force, false)
}
AssertParseFooCommand(Foo.Package.Clean.self, ["package", "-f", "clean"]) { clean in
XCTAssertEqual(clean.foo.verbose, false)
XCTAssertEqual(clean.package.force, true)
}
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-v", "config"]) { config in
XCTAssertEqual(config.foo.verbose, true)
XCTAssertEqual(config.package.force, false)
}
AssertParseFooCommand(Foo.Package.Config.self, ["package", "config", "-v"]) { config in
XCTAssertEqual(config.foo.verbose, true)
XCTAssertEqual(config.package.force, false)
}
AssertParseFooCommand(Foo.Package.Config.self, ["-v", "package", "config"]) { config in
XCTAssertEqual(config.foo.verbose, true)
XCTAssertEqual(config.package.force, false)
}
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-f", "config"]) { config in
XCTAssertEqual(config.foo.verbose, false)
XCTAssertEqual(config.package.force, true)
}
AssertParseFooCommand(Foo.Package.Config.self, ["package", "config", "-f"]) { config in
XCTAssertEqual(config.foo.verbose, false)
XCTAssertEqual(config.package.force, true)
}
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-v", "config", "-f"]) { config in
XCTAssertEqual(config.foo.verbose, true)
XCTAssertEqual(config.package.force, true)
}
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-f", "config", "-v"]) { config in
XCTAssertEqual(config.foo.verbose, true)
XCTAssertEqual(config.package.force, true)
}
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-vf", "config"]) { config in
XCTAssertEqual(config.foo.verbose, true)
XCTAssertEqual(config.package.force, true)
}
AssertParseFooCommand(Foo.Package.Config.self, ["package", "-fv", "config"]) { config in
XCTAssertEqual(config.foo.verbose, true)
XCTAssertEqual(config.package.force, true)
}
}
func testParsing_build() throws {
AssertParseFooCommand(Foo.Build.self, ["build", "file"]) { build in
XCTAssertEqual(build.foo.verbose, false)
XCTAssertEqual(build.input, "file")
}
}
func testParsing_fails() throws {
XCTAssertThrowsError(try Foo.parseAsRoot(["clean", "package"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["config", "package"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "c"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "build"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "build", "clean"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "clean", "foo"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "config", "bar"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["package", "clean", "build"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["build"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["build", "-f"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["build", "--build"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["build", "--build", "12"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["-f", "package", "clean"]))
XCTAssertThrowsError(try Foo.parseAsRoot(["-f", "package", "config"]))
}
}
private struct Options: ParsableArguments {
@Option() var firstName: String?
}
private struct UniqueOptions: ParsableArguments {
@Option() var lastName: String?
}
private struct Super: ParsableCommand {
static var configuration: CommandConfiguration {
.init(shouldPromptForMissing: false, subcommands: [Sub1.self, Sub2.self])
}
@OptionGroup() var options: Options
struct Sub1: ParsableCommand {
static var configuration = CommandConfiguration(shouldPromptForMissing: false)
@OptionGroup() var options: Options
}
struct Sub2: ParsableCommand {
static var configuration = CommandConfiguration(shouldPromptForMissing: false)
@OptionGroup() var options: UniqueOptions
}
}
extension NestedCommandEndToEndTests {
func testParsing_SharedOptions() throws {
AssertParseCommand(Super.self, Super.self, []) { sup in
XCTAssertNil(sup.options.firstName)
}
AssertParseCommand(Super.self, Super.self, ["--first-name", "Foo"]) { sup in
XCTAssertEqual("Foo", sup.options.firstName)
}
AssertParseCommand(Super.self, Super.Sub1.self, ["sub1"]) { sub1 in
XCTAssertNil(sub1.options.firstName)
}
AssertParseCommand(Super.self, Super.Sub1.self, ["sub1", "--first-name", "Foo"]) { sub1 in
XCTAssertEqual("Foo", sub1.options.firstName)
}
AssertParseCommand(Super.self, Super.Sub2.self, ["sub2", "--last-name", "Foo"]) { sub2 in
XCTAssertEqual("Foo", sub2.options.lastName)
}
}
}