| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- //===----------------------------------------------------------------------===//
- //
- // 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 ArgumentParser
- import ArgumentParserTestHelpers
- import XCTest
- final class ValidationEndToEndTests: XCTestCase {
- }
- private enum UserValidationError: LocalizedError {
- case userValidationError
- var errorDescription: String? {
- switch self {
- case .userValidationError:
- return "UserValidationError"
- }
- }
- }
- private struct Foo: ParsableArguments {
- static let usageString: String = """
- Usage: foo [--count <count>] [<names> ...] [--version] [--throw]
- See 'foo --help' for more information.
- """
- static let helpString: String = """
- USAGE: foo [--count <count>] [<names> ...] [--version] [--throw]
- ARGUMENTS:
- <names>
- OPTIONS:
- --count <count>
- --version
- --throw
- -h, --help Show help information.
- """
- @Option()
- var count: Int?
- @Argument()
- var names: [String] = []
- @Flag
- var version: Bool = false
- @Flag(name: [.customLong("throw")])
- var throwCustomError: Bool = false
- @Flag(help: .hidden)
- var showUsageOnly: Bool = false
- @Flag(help: .hidden)
- var failValidationSilently: Bool = false
- @Flag(help: .hidden)
- var failSilently: Bool = false
- mutating func validate() throws {
- if version {
- throw CleanExit.message("0.0.1")
- }
- if names.isEmpty {
- throw ValidationError("Must specify at least one name.")
- }
- if let count = count, names.count != count {
- throw ValidationError(
- "Number of names (\(names.count)) doesn't match count (\(count)).")
- }
- if throwCustomError {
- throw UserValidationError.userValidationError
- }
- if showUsageOnly {
- throw ValidationError("")
- }
- if failValidationSilently {
- throw ExitCode.validationFailure
- }
- if failSilently {
- throw ExitCode.failure
- }
- }
- }
- // swift-format-ignore: AlwaysUseLowerCamelCase
- // https://github.com/apple/swift-argument-parser/issues/710
- extension ValidationEndToEndTests {
- func testValidation() throws {
- AssertParse(Foo.self, ["Joe"]) { foo in
- XCTAssertEqual(foo.names, ["Joe"])
- XCTAssertNil(foo.count)
- }
- AssertParse(Foo.self, ["Joe", "Moe", "--count", "2"]) { foo in
- XCTAssertEqual(foo.names, ["Joe", "Moe"])
- XCTAssertEqual(foo.count, 2)
- }
- }
- func testValidation_Version() throws {
- AssertErrorMessage(Foo.self, ["--version"], "0.0.1")
- AssertFullErrorMessage(Foo.self, ["--version"], "0.0.1")
- }
- func testValidation_Fails() throws {
- AssertErrorMessage(Foo.self, [], "Must specify at least one name.")
- AssertFullErrorMessage(
- Foo.self, [],
- """
- Error: Must specify at least one name.
- \(Foo.helpString)
- """)
- AssertErrorMessage(
- Foo.self, ["--count", "3", "Joe"],
- """
- Number of names (1) doesn't match count (3).
- """)
- AssertFullErrorMessage(
- Foo.self, ["--count", "3", "Joe"],
- """
- Error: Number of names (1) doesn't match count (3).
- \(Foo.usageString)
- """)
- }
- func testCustomErrorValidation() {
- // verify that error description is printed if available via LocalizedError
- AssertErrorMessage(
- Foo.self, ["--throw", "Joe"],
- UserValidationError.userValidationError.errorDescription!)
- }
- func testEmptyErrorValidation() {
- AssertErrorMessage(Foo.self, ["--show-usage-only", "Joe"], "")
- AssertFullErrorMessage(
- Foo.self, ["--show-usage-only", "Joe"], Foo.usageString)
- AssertFullErrorMessage(Foo.self, ["--fail-validation-silently", "Joe"], "")
- AssertFullErrorMessage(Foo.self, ["--fail-silently", "Joe"], "")
- }
- }
- private struct FooCommand: ParsableCommand {
- @Flag(help: .hidden)
- var foo = false
- @Flag(help: .hidden)
- var bar = false
- mutating func validate() throws {
- if foo {
- // --foo implies --bar
- bar = true
- }
- }
- func run() throws {
- XCTAssertEqual(foo, bar)
- }
- }
- extension ValidationEndToEndTests {
- func testMutationsPreserved() throws {
- var foo = try FooCommand.parseAsRoot(["--foo"])
- try foo.run()
- }
- }
|