| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360 |
- //===----------------------------------------------------------------------===//
- //
- // 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 ArgumentParserTestHelpers
- import XCTest
- @testable import ArgumentParser
- final class ErrorMessageTests: XCTestCase {}
- // MARK: -
- private struct Bar: ParsableArguments {
- @Option() var name: String
- @Option(name: [.short, .long]) var format: String
- }
- // swift-format-ignore: AlwaysUseLowerCamelCase
- // https://github.com/apple/swift-argument-parser/issues/710
- extension ErrorMessageTests {
- func testMissing_1() {
- AssertErrorMessage(
- Bar.self, [], "Missing expected argument '--name <name>'")
- }
- func testMissing_2() {
- AssertErrorMessage(
- Bar.self, ["--name", "a"], "Missing expected argument '--format <format>'"
- )
- }
- func testUnknownOption_1() {
- AssertErrorMessage(
- Bar.self, ["--name", "a", "--format", "b", "--verbose"],
- "Unknown option '--verbose'")
- }
- func testUnknownOption_2() {
- AssertErrorMessage(
- Bar.self, ["--name", "a", "--format", "b", "-q"], "Unknown option '-q'")
- }
- func testUnknownOption_3() {
- AssertErrorMessage(
- Bar.self, ["--name", "a", "--format", "b", "-bar"],
- "Unknown option '-bar'")
- }
- func testUnknownOption_4() {
- AssertErrorMessage(
- Bar.self, ["--name", "a", "-foz", "b"], "Unknown option '-o'")
- }
- func testMissingValue_1() {
- AssertErrorMessage(
- Bar.self, ["--name", "a", "--format"],
- "Missing value for '--format <format>'")
- }
- func testMissingValue_2() {
- AssertErrorMessage(
- Bar.self, ["--name", "a", "-f"], "Missing value for '-f <format>'")
- }
- func testUnusedValue_1() {
- AssertErrorMessage(
- Bar.self, ["--name", "a", "--format", "f", "b"], "Unexpected argument 'b'"
- )
- }
- func testUnusedValue_2() {
- AssertErrorMessage(
- Bar.self, ["--name", "a", "--format", "f", "b", "baz"],
- "2 unexpected arguments: 'b', 'baz'")
- }
- }
- private enum Format: String, Equatable, Decodable, ExpressibleByArgument,
- CaseIterable
- {
- case text
- case json
- case csv
- }
- private enum Name: String, Equatable, Decodable, ExpressibleByArgument,
- CaseIterable
- {
- case bruce
- case clint
- case hulk
- case natasha
- case steve
- case thor
- case tony
- }
- private enum Counter: Int, ExpressibleByArgument, CaseIterable {
- case one = 1
- case two, three, four
- }
- private struct Foo: ParsableArguments {
- @Option(name: [.short, .long])
- var format: Format
- @Option(name: [.short, .long])
- var name: Name?
- }
- private struct EnumWithFewCasesArrayArgument: ParsableArguments {
- @Argument
- var formats: [Format]
- }
- private struct EnumWithManyCasesArrayArgument: ParsableArguments {
- @Argument
- var names: [Name]
- }
- private struct EnumWithIntRawValue: ParsableArguments {
- @Option var counter: Counter
- }
- extension ErrorMessageTests {
- func testWrongEnumValue() {
- AssertErrorMessage(
- Foo.self, ["--format", "png"],
- "The value 'png' is invalid for '--format <format>'. Please provide one of 'text', 'json' or 'csv'."
- )
- AssertErrorMessage(
- Foo.self, ["-f", "png"],
- "The value 'png' is invalid for '-f <format>'. Please provide one of 'text', 'json' or 'csv'."
- )
- AssertErrorMessage(
- Foo.self, ["-f", "text", "--name", "loki"],
- """
- The value 'loki' is invalid for '--name <name>'. Please provide one of the following:
- - bruce
- - clint
- - hulk
- - natasha
- - steve
- - thor
- - tony
- """)
- AssertErrorMessage(
- Foo.self, ["-f", "text", "-n", "loki"],
- """
- The value 'loki' is invalid for '-n <name>'. Please provide one of the following:
- - bruce
- - clint
- - hulk
- - natasha
- - steve
- - thor
- - tony
- """)
- AssertErrorMessage(
- EnumWithFewCasesArrayArgument.self, ["png"],
- "The value 'png' is invalid for '<formats>'. Please provide one of 'text', 'json' or 'csv'."
- )
- AssertErrorMessage(
- EnumWithManyCasesArrayArgument.self, ["loki"],
- """
- The value 'loki' is invalid for '<names>'. Please provide one of the following:
- - bruce
- - clint
- - hulk
- - natasha
- - steve
- - thor
- - tony
- """)
- AssertErrorMessage(
- EnumWithIntRawValue.self, ["--counter", "one"],
- """
- The value 'one' is invalid for '--counter <counter>'. \
- Please provide one of '1', '2', '3' or '4'.
- """)
- }
- }
- private struct Baz: ParsableArguments {
- @Flag
- var verbose: Bool = false
- }
- extension ErrorMessageTests {
- func testUnexpectedValue() {
- AssertErrorMessage(
- Baz.self, ["--verbose=foo"],
- "The option '--verbose' does not take any value, but 'foo' was specified."
- )
- }
- }
- private struct Qux: ParsableArguments {
- @Argument()
- var firstNumber: Int
- @Option(name: .customLong("number-two"))
- var secondNumber: Int
- }
- extension ErrorMessageTests {
- func testMissingArgument() {
- AssertErrorMessage(
- Qux.self, ["--number-two", "2"],
- "Missing expected argument '<first-number>'")
- }
- func testInvalidNumber() {
- AssertErrorMessage(
- Qux.self, ["--number-two", "2", "a"],
- "The value 'a' is invalid for '<first-number>'")
- AssertErrorMessage(
- Qux.self, ["--number-two", "a", "1"],
- "The value 'a' is invalid for '--number-two <number-two>'")
- }
- }
- private struct Qwz: ParsableArguments {
- @Option() var name: String?
- @Option(name: [.customLong("title", withSingleDash: true)]) var title: String?
- }
- // swift-format-ignore: AlwaysUseLowerCamelCase
- // https://github.com/apple/swift-argument-parser/issues/710
- extension ErrorMessageTests {
- func testMispelledArgument_1() {
- AssertErrorMessage(
- Qwz.self, ["--nme"], "Unknown option '--nme'. Did you mean '--name'?")
- AssertErrorMessage(
- Qwz.self, ["-name"], "Unknown option '-name'. Did you mean '--name'?")
- }
- func testMispelledArgument_2() {
- AssertErrorMessage(
- Qwz.self, ["-ttle"], "Unknown option '-ttle'. Did you mean '-title'?")
- AssertErrorMessage(
- Qwz.self, ["--title"], "Unknown option '--title'. Did you mean '-title'?")
- }
- func testMispelledArgument_3() {
- AssertErrorMessage(
- Qwz.self, ["--not-similar"], "Unknown option '--not-similar'")
- }
- func testMispelledArgument_4() {
- AssertErrorMessage(Qwz.self, ["-x"], "Unknown option '-x'")
- }
- }
- private struct Options: ParsableArguments {
- enum OutputBehaviour: String, EnumerableFlag {
- case stats, count, list
- static func name(for value: OutputBehaviour) -> NameSpecification {
- .shortAndLong
- }
- }
- @Flag(help: "Program output")
- var behaviour: OutputBehaviour = .list
- @Flag(inversion: .prefixedNo, exclusivity: .exclusive) var bool: Bool
- }
- private struct OptOptions: ParsableArguments {
- enum OutputBehaviour: String, EnumerableFlag {
- case stats, count, list
- static func name(for value: OutputBehaviour) -> NameSpecification {
- .short
- }
- }
- @Flag(help: "Program output")
- var behaviour: OutputBehaviour?
- }
- extension ErrorMessageTests {
- func testDuplicateFlags() {
- AssertErrorMessage(
- Options.self, ["--list", "--bool", "-s"],
- "Value to be set with flag \'-s\' had already been set with flag \'--list\'"
- )
- AssertErrorMessage(
- Options.self, ["-cbl"],
- "Value to be set with flag \'l\' in \'-cbl\' had already been set with flag \'c\' in \'-cbl\'"
- )
- AssertErrorMessage(
- Options.self, ["-bc", "--stats", "-l"],
- "Value to be set with flag \'--stats\' had already been set with flag \'c\' in \'-bc\'"
- )
- AssertErrorMessage(
- Options.self, ["--no-bool", "--bool"],
- "Value to be set with flag \'--bool\' had already been set with flag \'--no-bool\'"
- )
- AssertErrorMessage(
- OptOptions.self, ["-cbl"],
- "Value to be set with flag \'l\' in \'-cbl\' had already been set with flag \'c\' in \'-cbl\'"
- )
- }
- }
- // (see issue #434).
- private struct EmptyArray: ParsableArguments {
- @Option(parsing: .upToNextOption)
- var array: [String] = []
- @Flag(name: [.short, .long])
- var verbose = false
- }
- extension ErrorMessageTests {
- func testEmptyArrayOption() {
- AssertErrorMessage(
- EmptyArray.self, ["--array"], "Missing value for '--array <array>'")
- AssertErrorMessage(
- EmptyArray.self, ["--array", "--verbose"],
- "Missing value for '--array <array>'")
- AssertErrorMessage(
- EmptyArray.self, ["-verbose", "--array"],
- "Missing value for '--array <array>'")
- AssertErrorMessage(
- EmptyArray.self, ["--array", "-v"], "Missing value for '--array <array>'")
- AssertErrorMessage(
- EmptyArray.self, ["-v", "--array"], "Missing value for '--array <array>'")
- }
- }
- // MARK: -
- private struct Repeat: ParsableArguments {
- @Option() var count: Int?
- @Argument() var phrase: String
- }
- extension ErrorMessageTests {
- func testBadOptionBeforeArgument() {
- AssertErrorMessage(
- Repeat.self,
- ["--cont", "5", "Hello"],
- "Unknown option '--cont'. Did you mean '--count'?")
- }
- }
|