Files

206 lines
6.2 KiB
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 ArgumentParser
import ArgumentParserTestHelpers
import XCTest
final class TransformEndToEndTests: XCTestCase {}
private enum FooBarError: Error {
case outOfBounds
}
private protocol Convert {
static func convert(_ str: String) throws -> Int
}
extension Convert {
static func convert(_ str: String) throws -> Int {
guard let converted = Int(argument: str) else {
throw ValidationError("Could not transform to an Int.")
}
guard converted < 1000 else { throw FooBarError.outOfBounds }
return converted
}
}
// MARK: - Options
private struct FooOption: Convert, ParsableArguments {
static let usageString: String = """
Usage: foo_option --string <int_str>
See 'foo_option --help' for more information.
"""
static let help: String =
"Help: --string <int_str> Convert string to integer\n"
@Option(
help: ArgumentHelp("Convert string to integer", valueName: "int_str"),
transform: { try convert($0) })
var string: Int
}
private struct BarOption: Convert, ParsableCommand {
static let usageString: String = """
Usage: bar-option [--strings <int_str> ...]
See 'bar-option --help' for more information.
"""
static let help: String =
"Help: --strings <int_str> Convert a list of strings to an array of integers\n"
@Option(
help: ArgumentHelp(
"Convert a list of strings to an array of integers", valueName: "int_str"),
transform: { try convert($0) })
var strings: [Int] = []
}
// swift-format-ignore: AlwaysUseLowerCamelCase
// https://github.com/apple/swift-argument-parser/issues/710
extension TransformEndToEndTests {
// MARK: Single Values
func testSingleOptionTransform() throws {
AssertParse(FooOption.self, ["--string", "42"]) { foo in
XCTAssertEqual(foo.string, 42)
}
}
func testSingleOptionValidation_Fail_CustomErrorMessage() throws {
AssertFullErrorMessage(
FooOption.self, ["--string", "Forty Two"],
"Error: The value 'Forty Two' is invalid for '--string <int_str>': Could not transform to an Int.\n"
+ FooOption.help + FooOption.usageString)
}
func testSingleOptionValidation_Fail_DefaultErrorMessage() throws {
AssertFullErrorMessage(
FooOption.self, ["--string", "4827"],
"Error: The value '4827' is invalid for '--string <int_str>': outOfBounds\n"
+ FooOption.help + FooOption.usageString)
}
// MARK: Arrays
func testOptionArrayTransform() throws {
AssertParse(
BarOption.self, ["--strings", "42", "--strings", "72", "--strings", "99"]
) { bar in
XCTAssertEqual(bar.strings, [42, 72, 99])
}
}
func testOptionArrayValidation_Fail_CustomErrorMessage() throws {
AssertFullErrorMessage(
BarOption.self,
["--strings", "Forty Two", "--strings", "72", "--strings", "99"],
"Error: The value 'Forty Two' is invalid for '--strings <int_str>': Could not transform to an Int.\n"
+ BarOption.help + BarOption.usageString)
}
func testOptionArrayValidation_Fail_DefaultErrorMessage() throws {
AssertFullErrorMessage(
BarOption.self,
["--strings", "4827", "--strings", "72", "--strings", "99"],
"Error: The value '4827' is invalid for '--strings <int_str>': outOfBounds\n"
+ BarOption.help + BarOption.usageString)
}
}
// MARK: - Arguments
private struct FooArgument: Convert, ParsableArguments {
static let usageString: String = """
Usage: foo_argument <int_str>
See 'foo_argument --help' for more information.
"""
static let help: String = "Help: <int_str> Convert string to integer\n"
enum FooError: Error {
case outOfBounds
}
@Argument(
help: ArgumentHelp("Convert string to integer", valueName: "int_str"),
transform: { try convert($0) })
var string: Int
}
private struct BarArgument: Convert, ParsableCommand {
static let usageString: String = """
Usage: bar-argument [<int_str> ...]
See 'bar-argument --help' for more information.
"""
static let help: String =
"Help: <int_str> Convert a list of strings to an array of integers\n"
@Argument(
help: ArgumentHelp(
"Convert a list of strings to an array of integers", valueName: "int_str"),
transform: { try convert($0) })
var strings: [Int] = []
}
// swift-format-ignore: AlwaysUseLowerCamelCase
// https://github.com/apple/swift-argument-parser/issues/710
extension TransformEndToEndTests {
// MARK: Single Values
func testArgumentTransform() throws {
AssertParse(FooArgument.self, ["42"]) { foo in
XCTAssertEqual(foo.string, 42)
}
}
func testArgumentValidation_Fail_CustomErrorMessage() throws {
AssertFullErrorMessage(
FooArgument.self, ["Forty Two"],
"Error: The value 'Forty Two' is invalid for '<int_str>': Could not transform to an Int.\n"
+ FooArgument.help + FooArgument.usageString)
}
func testArgumentValidation_Fail_DefaultErrorMessage() throws {
AssertFullErrorMessage(
FooArgument.self, ["4827"],
"Error: The value '4827' is invalid for '<int_str>': outOfBounds\n"
+ FooArgument.help + FooArgument.usageString)
}
// MARK: Arrays
func testArgumentArrayTransform() throws {
AssertParse(BarArgument.self, ["42", "72", "99"]) { bar in
XCTAssertEqual(bar.strings, [42, 72, 99])
}
}
func testArgumentArrayValidation_Fail_CustomErrorMessage() throws {
AssertFullErrorMessage(
BarArgument.self, ["Forty Two", "72", "99"],
"Error: The value 'Forty Two' is invalid for '<int_str>': Could not transform to an Int.\n"
+ BarArgument.help + BarArgument.usageString)
}
func testArgumentArrayValidation_Fail_DefaultErrorMessage() throws {
AssertFullErrorMessage(
BarArgument.self, ["4827", "72", "99"],
"Error: The value '4827' is invalid for '<int_str>': outOfBounds\n"
+ BarArgument.help + BarArgument.usageString)
}
}