You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2018/05/19 14:02:07 UTC
[1/3] groovy git commit: GROOVY-8556 consolidate tests/doco a bit more
Repository: groovy
Updated Branches:
refs/heads/GROOVY_2_5_X 997938a93 -> 3fbd0b6f6
GROOVY-8556 consolidate tests/doco a bit more
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/926b24a4
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/926b24a4
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/926b24a4
Branch: refs/heads/GROOVY_2_5_X
Commit: 926b24a431689e91727b43d9aba3e362b02d4276
Parents: 997938a
Author: Paul King <pa...@asert.com.au>
Authored: Sat May 19 23:07:55 2018 +1000
Committer: Paul King <pa...@asert.com.au>
Committed: Sun May 20 00:01:52 2018 +1000
----------------------------------------------------------------------
.../doc/core-domain-specific-languages.adoc | 117 +++---
src/spec/test/cli/CliBuilderTestCase.groovy | 380 +++++++++++++++++++
src/spec/test/cli/GreeterC.groovy | 39 ++
src/spec/test/cli/GreeterI.groovy | 30 ++
src/spec/test/cli/TypeCheckedI.groovy | 30 ++
src/spec/test/cli/ValSepI.groovy | 31 ++
src/spec/test/cli/WithArgsI.groovy | 31 ++
src/spec/test/cli/WithConvertI.groovy | 31 ++
src/spec/test/cli/WithDefaultValueI.groovy | 28 ++
subprojects/groovy-cli-commons/build.gradle | 1 +
.../src/spec/test/builder/CliBuilderTest.groovy | 344 +----------------
.../spec/test/groovy/util/CliBuilderTest.groovy | 28 ++
subprojects/groovy-cli-picocli/build.gradle | 1 +
.../src/spec/test/builder/CliBuilderTest.groovy | 370 ++----------------
14 files changed, 716 insertions(+), 745 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/src/spec/doc/core-domain-specific-languages.adoc
----------------------------------------------------------------------
diff --git a/src/spec/doc/core-domain-specific-languages.adoc b/src/spec/doc/core-domain-specific-languages.adoc
index 6db531f..06f9e8d 100644
--- a/src/spec/doc/core-domain-specific-languages.adoc
+++ b/src/spec/doc/core-domain-specific-languages.adoc
@@ -1103,22 +1103,27 @@ Here is a simple example `Greeter.groovy` script illustrating usage:
[source,groovy]
---------------------------
+// import of CliBuilder not shown <1>
// specify parameters
-def cli = new CliBuilder(usage: 'groovy Greeter [option]') <1>
-cli.a(longOpt: 'audience', args: 1, 'greeting audience') <2>
-cli.h(longOpt: 'help', 'display usage') <3>
+def cli = new CliBuilder(usage: 'groovy Greeter [option]') <2>
+cli.a(longOpt: 'audience', args: 1, 'greeting audience') <3>
+cli.h(longOpt: 'help', 'display usage') <4>
// parse and process parameters
-def options = cli.parse(args) <4>
-if (options.h) cli.usage() <5>
-else println "Hello ${options.a ? options.a : 'World'}" <6>
+def options = cli.parse(args) <5>
+if (options.h) cli.usage() <6>
+else println "Hello ${options.a ? options.a : 'World'}" <7>
---------------------------
-<1> define a new `CliBuilder` instance specifying an optional usage string
-<2> specify a `-a` option taking a single argument with an optional long variant `--audience`
-<3> specify a `-h` option taking no arguments with an optional long variant `--help`
-<4> parse the commandline parameters supplied to the script
-<5> if the `h` option is found display a usage message
-<6> display a standard greeting or, if the `a` option is found, a customized greeting
+<1> Earlier versions of Groovy had a CliBuilder in the groovy.util package and no import was necessary.
+While still supported, this approach is now deprecated and you should instead choose the groovy.cli.picocli
+or groovy.cli.commons version. The groovy.util version points to the commons-cli version for backwards compatibility
+but will be removed in a future version of Groovy.
+<2> define a new `CliBuilder` instance specifying an optional usage string
+<3> specify a `-a` option taking a single argument with an optional long variant `--audience`
+<4> specify a `-h` option taking no arguments with an optional long variant `--help`
+<5> parse the commandline parameters supplied to the script
+<6> if the `h` option is found display a usage message
+<7> display a standard greeting or, if the `a` option is found, a customized greeting
Running this script with no commandline parameters, i.e.:
@@ -1178,13 +1183,13 @@ properties are supported when specifying an allowed commandline option:
| Name | Description | Type
| argName | the name of the argument for this option used in output | `String`
| longOpt | the long representation or long name of the option | `String`
-| args | the number of argument values | `int` or `String`<1>
+| args | the number of argument values | `int` or `String` <1>
| optionalArg | whether the argument value is optional | `boolean`
| required | whether the option is mandatory | `boolean`
| type | the type of this option | `Class`
-| valueSeparator | the character that is the value separator | `char`<2>
+| valueSeparator | the character that is the value separator | `char` <2>
| defaultValue | a default value | `String`
-| convert | converts the incoming String to the required type | `Closure`<1>
+| convert | converts the incoming String to the required type | `Closure` <1>
|======================
<1> More details later
<2> Single character Strings are coerced to chars in special cases in Groovy
@@ -1206,7 +1211,7 @@ Here is how such a specification can be defined:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=annotationInterfaceSpec,indent=0]
+include::{projectdir}/src/spec/test/cli/GreeterI.groovy[tags=annotationInterfaceSpec,indent=0]
----
<1> Specify a Boolean option set using `-h` or `--help`
<2> Specify a String option set using `-a` or `--audience`
@@ -1221,7 +1226,7 @@ Here is how you could use the interface specification:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=annotationInterface,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=annotationInterface,indent=0]
----
<1> Create a `CliBuilder` instance as before with optional properties
<2> Parse parameters using the interface specification
@@ -1243,7 +1248,7 @@ Here is how such a specification can be defined:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=annotationClassSpec,indent=0]
+include::{projectdir}/src/spec/test/cli/GreeterC.groovy[tags=annotationClassSpec,indent=0]
----
<1> Indicate that a Boolean property is an option
<2> Indicate that a String property (with explicit setter) is an option
@@ -1253,7 +1258,7 @@ And here is how you could use the specification:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=annotationClass,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=annotationClass,indent=0]
----
<1> Create a `CliBuilder` instance as before with optional parameters
<2> Create an instance for `CliBuilder` to populate
@@ -1277,7 +1282,7 @@ with the same arguments as shown for the instance example earlier:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=annotationScript,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=annotationScript,indent=0]
----
===== Options with arguments
@@ -1289,7 +1294,7 @@ Here is an example involving those cases:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withArgument,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=withArgument,indent=0]
----
<1> An option that is simply a flag - the default; setting args to 0 is allowed but not needed.
<2> An option with exactly one argument
@@ -1306,14 +1311,14 @@ illustrating such a definition:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withArgumentInterfaceSpec,indent=0]
+include::{projectdir}/src/spec/test/cli/WithArgsI.groovy[tags=withArgumentInterfaceSpec,indent=0]
----
And here is how it is used:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withArgumentInterface,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=withArgumentInterface,indent=0]
----
This example makes use of an array-typed option specification. We cover this in more detail shortly when we discuss
@@ -1334,7 +1339,7 @@ Here is an example using types with the dynamic api argument definition style:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withType,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=withType,indent=0]
----
Primitives, numeric types, files, enums and arrays thereof, are supported (they are converted using
@@ -1347,7 +1352,7 @@ for you. Here is a sample using the dynamic api style:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withConvert,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=withConvert,indent=0]
----
Alternatively, you can use the annotation style by supplying the conversion closure as an annotation parameter.
@@ -1355,14 +1360,14 @@ Here is an example specification:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withConvertInterfaceSpec,indent=0]
+include::{projectdir}/src/spec/test/cli/WithConvertI.groovy[tags=withConvertInterfaceSpec,indent=0]
----
And an example using that specification:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withConvertInterface,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=withConvertInterface,indent=0]
----
===== Options with multiple arguments
@@ -1388,7 +1393,7 @@ Here is an excerpt highlighting the use of multiple arguments:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=multipleArgs,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=multipleArgs,indent=0]
----
<1> Args value supplied as a String and comma value separator specified
<2> One or more arguments are allowed
@@ -1408,14 +1413,14 @@ array type for the annotated class member (method or property) as this example s
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=multipleArgsInterfaceSpec,indent=0]
+include::{projectdir}/src/spec/test/cli/ValSepI.groovy[tags=multipleArgsInterfaceSpec,indent=0]
----
And used as follows:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=multipleArgsInterface,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=multipleArgsInterface,indent=0]
----
===== Types and multiple arguments
@@ -1424,7 +1429,7 @@ Here is an example using types and multiple arguments with the dynamic api argum
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withTypeMultiple,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=withTypeMultiple,indent=0]
----
<1> For an array type, the trailing 's' can be used but isn't needed
@@ -1439,7 +1444,7 @@ Here is how you could use it using the dynamic api style:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withDefaultValue,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=withDefaultValue,indent=0]
----
Similarly, you might want such a specification using the annotation style. Here is an example using an interface
@@ -1447,14 +1452,14 @@ specification:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withDefaultValueInterfaceSpec,indent=0]
+include::{projectdir}/src/spec/test/cli/WithDefaultValueI.groovy[tags=withDefaultValueInterfaceSpec,indent=0]
----
Which would be used like this:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withDefaultValueInterface,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=withDefaultValueInterface,indent=0]
----
You can also use the `defaultValue` annotation attribute when using annotations with an instance,
@@ -1468,14 +1473,14 @@ annotation style, for example, here is an interface option specification:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withTypeCheckedInterfaceSpec,indent=0]
+include::{projectdir}/src/spec/test/cli/TypeCheckedI.groovy[tags=withTypeCheckedInterfaceSpec,indent=0]
----
-And it can be used in combination with `@TypeChecked` as shown here:
+And it can be used in combination with `@TypeChecked` as shown here:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withTypeCheckedInterface,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=withTypeCheckedInterface,indent=0]
----
Secondly, there is a feature of the dynamic api style which offers some support. The definition statements
@@ -1508,7 +1513,7 @@ the following example:
[source,groovy]
----
-include::{projectdir}/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy[tags=withTypeChecked,indent=0]
+include::{projectdir}/src/spec/test/cli/CliBuilderTestCase.groovy[tags=withTypeChecked,indent=0]
----
===== Advanced CLI Usage
@@ -1549,13 +1554,14 @@ assert !cli.parse('-d -o'.split()) // <1>
<1> The parse will fail since only one option from a group can be used at a time.
====== Picocli
+
Below are some features available in the picocli version of `CliBuilder`.
*New property: errorWriter*
When users of your application give invalid command line arguments,
CliBuilder writes an error message and the usage help message to the `stderr` output stream.
-It doesn’t use the `stdout` stream to prevent the error message from being parsed when your program's
+It doesn't use the `stdout` stream to prevent the error message from being parsed when your program's
output is used as input for another process.
You can customize the destination by setting the `errorWriter` to a different value.
@@ -1588,28 +1594,12 @@ which gives fine-grained control over various sections of the usage help message
[source,groovy]
----
-def cli = new CliBuilder()
-cli.name = "myapp"
-cli.usageMessage.with {
- headerHeading("@|bold,underline Header heading:|@%n")
- header("Header 1", "Header 2") // before the synopsis
- synopsisHeading("%n@|bold,underline Usage:|@ ")
- descriptionHeading("%n@|bold,underline Description heading:|@%n")
- description("Description 1", "Description 2") // after the synopsis
- optionListHeading("%n@|bold,underline Options heading:|@%n")
- footerHeading("%n@|bold,underline Footer heading:|@%n")
- footer("Footer 1", "Footer 2")
-}
-cli.a('option a description')
-cli.b('option b description')
-cli.c(args: '*', 'option c description')
-cli.usage()
+include::{projectdir}/subprojects/groovy-cli-picocli/src/spec/test/builder/CliBuilderTest.groovy[tags=withUsageMessageSpec,indent=0]
----
Gives this output:
image::assets/img/usageMessageSpec.png[]
-
*New property: parser*
The `parser` property gives access to the picocli `ParserSpec` object that can be used to customize the parser behavior.
@@ -1621,19 +1611,9 @@ Finally, if your application has options that are key-value pairs, you may be in
[source,groovy]
----
-import java.util.concurrent.TimeUnit
-import static java.util.concurrent.TimeUnit.DAYS
-import static java.util.concurrent.TimeUnit.HOURS
+include::{projectdir}/subprojects/groovy-cli-picocli/src/spec/test/builder/CliBuilderTest.groovy[tags=mapOptionImports,indent=0]
-def cli = new CliBuilder()
-cli.D(args: 2, valueSeparator: '=', 'the old way') // <1>
-cli.X(type: Map, 'the new way') // <2>
-cli.Z(type: Map, auxiliaryTypes: [TimeUnit, Integer].toArray(), 'typed map') // <3>
-
-def options = cli.parse('-Da=b -Dc=d -Xx=y -Xi=j -ZDAYS=2 -ZHOURS=23'.split())// <4>
-assert options.Ds == ['a', 'b', 'c', 'd'] // <5>
-assert options.Xs == [ 'x':'y', 'i':'j' ] // <6>
-assert options.Zs == [ (DAYS as TimeUnit):2, (HOURS as TimeUnit):23 ] // <7>
+include::{projectdir}/subprojects/groovy-cli-picocli/src/spec/test/builder/CliBuilderTest.groovy[tags=mapOption,indent=0]
----
<1> Previously, `key=value` pairs were split up into parts and added to a list
<2> Picocli map support: simply specify `Map` as the type of the option
@@ -1644,7 +1624,6 @@ assert options.Zs == [ (DAYS as TimeUnit):2, (HOURS as TimeUnit):23 ] //
<7> Both keys and values of the map can be strongly typed
-
==== ObjectGraphBuilder
`ObjectGraphBuilder` is a builder for an arbitrary graph of beans that
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/src/spec/test/cli/CliBuilderTestCase.groovy
----------------------------------------------------------------------
diff --git a/src/spec/test/cli/CliBuilderTestCase.groovy b/src/spec/test/cli/CliBuilderTestCase.groovy
new file mode 100644
index 0000000..1b6c9cc
--- /dev/null
+++ b/src/spec/test/cli/CliBuilderTestCase.groovy
@@ -0,0 +1,380 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package cli
+
+abstract class CliBuilderTestCase extends GroovyTestCase {
+
+ abstract String getImportCliBuilder()
+
+ void testAnnotationsInterface() {
+ assertScript """
+ import cli.GreeterI
+ $importCliBuilder
+ // tag::annotationInterface[]
+ // import CliBuilder not shown
+ def cli = new CliBuilder(usage: 'groovy Greeter') // <1>
+ def argz = '--audience Groovologist'.split()
+ def options = cli.parseFromSpec(GreeterI, argz) // <2>
+ assert options.audience() == 'Groovologist' // <3>
+
+ argz = '-h Some Other Args'.split()
+ options = cli.parseFromSpec(GreeterI, argz) // <4>
+ assert options.help()
+ assert options.remaining() == ['Some', 'Other', 'Args'] // <5>
+ // end::annotationInterface[]
+ """
+ }
+
+ void testAnnotationsClass() {
+ assertScript """
+ import cli.GreeterC
+ $importCliBuilder
+ // tag::annotationClass[]
+ // import CliBuilder not shown
+ def cli = new CliBuilder(usage: 'groovy Greeter [option]') // <1>
+ def options = new GreeterC() // <2>
+ def argz = '--audience Groovologist foo'.split()
+ cli.parseFromInstance(options, argz) // <3>
+ assert options.audience == 'Groovologist' // <4>
+ assert options.remaining == ['foo'] // <5>
+ // end::annotationClass[]
+ """
+ }
+
+ // performs toString comparison of usage help - this isn't because we guarantee any specific output
+ // (hence expected is provided as a parameter) but we want to know when it changes significantly and
+ // in particular we want to ensure that no information that we expect to be there just disappears
+ protected void doTestAnnotationsInterfaceToString(String key, String expected) {
+ assertScript """
+ import cli.GreeterI
+ $importCliBuilder
+ def cli = new CliBuilder($key: 'groovy Greeter')
+
+ def options = cli.parseFromSpec(GreeterI, ['-h', 'Some', 'Other', 'Args'] as String[])
+ assert options.help()
+ assert options.remaining() == ['Some', 'Other', 'Args']
+ StringWriter sw = new StringWriter()
+ cli.writer = new PrintWriter(sw)
+ cli.usage()
+
+ assert '$expected'.normalize() == sw.toString().normalize()
+ """
+ }
+
+ void testParseScript() {
+ def argz = '--audience Groovologist foo'.split()
+ new GroovyShell().run("""
+ $importCliBuilder
+ // tag::annotationScript[]
+ // import CliBuilder not shown
+ import groovy.cli.OptionField
+ import groovy.cli.UnparsedField
+
+ @OptionField String audience
+ @OptionField Boolean help
+ @UnparsedField List remaining
+ new CliBuilder().parseFromInstance(this, args)
+ assert audience == 'Groovologist'
+ assert remaining == ['foo']
+ // end::annotationScript[]
+ """, 'TestScript.groovy', argz)
+ }
+
+ void testWithArgument() {
+ assertScript """
+ $importCliBuilder
+ // tag::withArgument[]
+ // import CliBuilder not shown
+ def cli = new CliBuilder()
+ cli.a(args: 0, 'a arg') // <1>
+ cli.b(args: 1, 'b arg') // <2>
+ cli.c(args: 1, optionalArg: true, 'c arg') // <3>
+ def options = cli.parse('-a -b foo -c bar baz'.split()) // <4>
+
+ assert options.a == true
+ assert options.b == 'foo'
+ assert options.c == 'bar'
+ assert options.arguments() == ['baz']
+
+ options = cli.parse('-a -c -b foo bar baz'.split()) // <5>
+
+ assert options.a == true
+ assert options.c == true
+ assert options.b == 'foo'
+ assert options.arguments() == ['bar', 'baz']
+ // end::withArgument[]
+ """
+ }
+
+ void testMultipleArgsAndOptionalValueSeparator() {
+ assertScript """
+ $importCliBuilder
+ // tag::multipleArgs[]
+ // import CliBuilder not shown
+ def cli = new CliBuilder()
+ cli.a(args: 2, 'a-arg')
+ cli.b(args: '2', valueSeparator: ',', 'b-arg') // <1>
+ cli.c(args: '+', valueSeparator: ',', 'c-arg') // <2>
+
+ def options = cli.parse('-a 1 2 3 4'.split()) // <3>
+ assert options.a == '1' // <4>
+ assert options.as == ['1', '2'] // <5>
+ assert options.arguments() == ['3', '4']
+
+ options = cli.parse('-a1 -a2 3'.split()) // <6>
+ assert options.as == ['1', '2']
+ assert options.arguments() == ['3']
+
+ options = cli.parse(['-b1,2']) // <7>
+ assert options.bs == ['1', '2']
+
+ options = cli.parse(['-c', '1'])
+ assert options.cs == ['1']
+
+ options = cli.parse(['-c1'])
+ assert options.cs == ['1']
+
+ options = cli.parse(['-c1,2,3'])
+ assert options.cs == ['1', '2', '3']
+ // end::multipleArgs[]
+ """
+ }
+
+ void testWithArgumentInterface() {
+ assertScript """
+ import cli.WithArgsI
+ $importCliBuilder
+ // tag::withArgumentInterface[]
+ def cli = new CliBuilder()
+ def options = cli.parseFromSpec(WithArgsI, '-a -b foo -c bar baz'.split())
+ assert options.a()
+ assert options.b() == 'foo'
+ assert options.c() == ['bar']
+ assert options.remaining() == ['baz']
+
+ options = cli.parseFromSpec(WithArgsI, '-a -c -b foo bar baz'.split())
+ assert options.a()
+ assert options.c() == []
+ assert options.b() == 'foo'
+ assert options.remaining() == ['bar', 'baz']
+ // end::withArgumentInterface[]
+ """
+ }
+
+ void testMultipleArgsAndOptionalValueSeparatorInterface() {
+ assertScript """
+ import cli.ValSepI
+ $importCliBuilder
+ // tag::multipleArgsInterface[]
+ def cli = new CliBuilder()
+
+ def options = cli.parseFromSpec(ValSepI, '-a 1 2 3 4'.split())
+ assert options.a() == ['1', '2']
+ assert options.remaining() == ['3', '4']
+
+ options = cli.parseFromSpec(ValSepI, '-a1 -a2 3'.split())
+ assert options.a() == ['1', '2']
+ assert options.remaining() == ['3']
+
+ options = cli.parseFromSpec(ValSepI, ['-b1,2'] as String[])
+ assert options.b() == ['1', '2']
+
+ options = cli.parseFromSpec(ValSepI, ['-c', '1'] as String[])
+ assert options.c() == ['1']
+
+ options = cli.parseFromSpec(ValSepI, ['-c1'] as String[])
+ assert options.c() == ['1']
+
+ options = cli.parseFromSpec(ValSepI, ['-c1,2,3'] as String[])
+ assert options.c() == ['1', '2', '3']
+ // end::multipleArgsInterface[]
+ """
+ }
+
+ void testType() {
+ assertScript """
+ import java.math.RoundingMode
+ $importCliBuilder
+ // tag::withType[]
+ def argz = '''-a John -b -d 21 -e 1980 -f 3.5 -g 3.14159
+ -h cv.txt -i DOWN and some more'''.split()
+ def cli = new CliBuilder()
+ cli.a(type: String, 'a-arg')
+ cli.b(type: boolean, 'b-arg')
+ cli.c(type: Boolean, 'c-arg')
+ cli.d(type: int, 'd-arg')
+ cli.e(type: Long, 'e-arg')
+ cli.f(type: Float, 'f-arg')
+ cli.g(type: BigDecimal, 'g-arg')
+ cli.h(type: File, 'h-arg')
+ cli.i(type: RoundingMode, 'i-arg')
+ def options = cli.parse(argz)
+ assert options.a == 'John'
+ assert options.b
+ assert !options.c
+ assert options.d == 21
+ assert options.e == 1980L
+ assert options.f == 3.5f
+ assert options.g == 3.14159
+ assert options.h == new File('cv.txt')
+ assert options.i == RoundingMode.DOWN
+ assert options.arguments() == ['and', 'some', 'more']
+ // end::withType[]
+ """
+ }
+
+ void testTypeMultiple() {
+ assertScript """
+ $importCliBuilder
+ // tag::withTypeMultiple[]
+ def argz = '''-j 3 4 5 -k1.5,2.5,3.5 and some more'''.split()
+ def cli = new CliBuilder()
+ cli.j(args: 3, type: int[], 'j-arg')
+ cli.k(args: '+', valueSeparator: ',', type: BigDecimal[], 'k-arg')
+ def options = cli.parse(argz)
+ assert options.js == [3, 4, 5] // <1>
+ assert options.j == [3, 4, 5] // <1>
+ assert options.k == [1.5, 2.5, 3.5]
+ assert options.arguments() == ['and', 'some', 'more']
+ // end::withTypeMultiple[]
+ """
+ }
+
+ void testConvert() {
+ assertScript """
+ $importCliBuilder
+ // tag::withConvert[]
+ def argz = '''-a John -b Mary -d 2016-01-01 and some more'''.split()
+ def cli = new CliBuilder()
+ def lower = { it.toLowerCase() }
+ cli.a(convert: lower, 'a-arg')
+ cli.b(convert: { it.toUpperCase() }, 'b-arg')
+ cli.d(convert: { Date.parse('yyyy-MM-dd', it) }, 'd-arg')
+ def options = cli.parse(argz)
+ assert options.a == 'john'
+ assert options.b == 'MARY'
+ assert options.d.format('dd-MMM-yyyy') == '01-Jan-2016'
+ assert options.arguments() == ['and', 'some', 'more']
+ // end::withConvert[]
+ """
+ }
+
+ void testConvertInterface() {
+ assertScript """
+ import cli.WithConvertI
+ $importCliBuilder
+ // tag::withConvertInterface[]
+ Date newYears = Date.parse("yyyy-MM-dd", "2016-01-01")
+ def argz = '''-a John -b Mary -d 2016-01-01 and some more'''.split()
+ def cli = new CliBuilder()
+ def options = cli.parseFromSpec(WithConvertI, argz)
+ assert options.a() == 'john'
+ assert options.b() == 'MARY'
+ assert options.d() == newYears
+ assert options.remaining() == ['and', 'some', 'more']
+ // end::withConvertInterface[]
+ """
+ }
+
+ void testDefaultValue() {
+ assertScript """
+ $importCliBuilder
+ // tag::withDefaultValue[]
+ def cli = new CliBuilder()
+ cli.f longOpt: 'from', type: String, args: 1, defaultValue: 'one', 'f option'
+ cli.t longOpt: 'to', type: int, defaultValue: '35', 't option'
+
+ def options = cli.parse('-f two'.split())
+ assert options.hasOption('f')
+ assert options.f == 'two'
+ assert !options.hasOption('t')
+ assert options.t == 35
+
+ options = cli.parse('-t 45'.split())
+ assert !options.hasOption('from')
+ assert options.from == 'one'
+ assert options.hasOption('to')
+ assert options.to == 45
+ // end::withDefaultValue[]
+ """
+ }
+
+ void testDefaultValueInterface() {
+ assertScript """
+ $importCliBuilder
+ import cli.WithDefaultValueI
+ // tag::withDefaultValueInterface[]
+ def cli = new CliBuilder()
+
+ def options = cli.parseFromSpec(WithDefaultValueI, '-f two'.split())
+ assert options.from() == 'two'
+ assert options.to() == 35
+
+ options = cli.parseFromSpec(WithDefaultValueI, '-t 45'.split())
+ assert options.from() == 'one'
+ assert options.to() == 45
+ // end::withDefaultValueInterface[]
+ """
+ }
+
+ void testTypeCheckedInterfaceRunner() {
+ assertScript """
+ $importCliBuilder
+ import cli.TypeCheckedI
+ import groovy.transform.TypeChecked
+ // tag::withTypeCheckedInterface[]
+ @TypeChecked
+ void testTypeCheckedInterface() {
+ def argz = "--name John --age 21 and some more".split()
+ def cli = new CliBuilder()
+ def options = cli.parseFromSpec(TypeCheckedI, argz)
+ String n = options.name()
+ int a = options.age()
+ assert n == 'John' && a == 21
+ assert options.remaining() == ['and', 'some', 'more']
+ }
+ // end::withTypeCheckedInterface[]
+ testTypeCheckedInterface()
+ """
+ }
+
+ void testTypeCheckedRunner() {
+ assertScript """
+ $importCliBuilder
+ // tag::withTypeChecked[]
+ import groovy.cli.TypedOption
+ import groovy.transform.TypeChecked
+
+ @TypeChecked
+ void testTypeChecked() {
+ def cli = new CliBuilder()
+ TypedOption<String> name = cli.option(String, opt: 'n', longOpt: 'name', 'name option')
+ TypedOption<Integer> age = cli.option(Integer, longOpt: 'age', 'age option')
+ def argz = "--name John --age 21 and some more".split()
+ def options = cli.parse(argz)
+ String n = options[name]
+ int a = options[age]
+ assert n == 'John' && a == 21
+ assert options.arguments() == ['and', 'some', 'more']
+ }
+ // end::withTypeChecked[]
+ testTypeChecked()
+ """
+ }
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/src/spec/test/cli/GreeterC.groovy
----------------------------------------------------------------------
diff --git a/src/spec/test/cli/GreeterC.groovy b/src/spec/test/cli/GreeterC.groovy
new file mode 100644
index 0000000..500819a
--- /dev/null
+++ b/src/spec/test/cli/GreeterC.groovy
@@ -0,0 +1,39 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package cli
+
+import groovy.cli.Option
+import groovy.cli.Unparsed
+
+// tag::annotationClassSpec[]
+class GreeterC {
+ @Option(shortName='h', description='display usage')
+ Boolean help // <1>
+
+ private String audience
+ @Option(shortName='a', description='greeting audience')
+ void setAudience(String audience) { // <2>
+ this.audience = audience
+ }
+ String getAudience() { audience }
+
+ @Unparsed(description = "positional parameters")
+ List remaining // <3>
+}
+// end::annotationClassSpec[]
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/src/spec/test/cli/GreeterI.groovy
----------------------------------------------------------------------
diff --git a/src/spec/test/cli/GreeterI.groovy b/src/spec/test/cli/GreeterI.groovy
new file mode 100644
index 0000000..bf9ca3d
--- /dev/null
+++ b/src/spec/test/cli/GreeterI.groovy
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package cli
+
+import groovy.cli.Option
+import groovy.cli.Unparsed
+
+// tag::annotationInterfaceSpec[]
+interface GreeterI {
+ @Option(shortName='h', description='display usage') Boolean help() // <1>
+ @Option(shortName='a', description='greeting audience') String audience() // <2>
+ @Unparsed(description = "positional parameters") List remaining() // <3>
+}
+// end::annotationInterfaceSpec[]
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/src/spec/test/cli/TypeCheckedI.groovy
----------------------------------------------------------------------
diff --git a/src/spec/test/cli/TypeCheckedI.groovy b/src/spec/test/cli/TypeCheckedI.groovy
new file mode 100644
index 0000000..9569364
--- /dev/null
+++ b/src/spec/test/cli/TypeCheckedI.groovy
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package cli
+
+import groovy.cli.Option
+import groovy.cli.Unparsed
+
+// tag::withTypeCheckedInterfaceSpec[]
+interface TypeCheckedI{
+ @Option String name()
+ @Option int age()
+ @Unparsed List remaining()
+}
+// end::withTypeCheckedInterfaceSpec[]
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/src/spec/test/cli/ValSepI.groovy
----------------------------------------------------------------------
diff --git a/src/spec/test/cli/ValSepI.groovy b/src/spec/test/cli/ValSepI.groovy
new file mode 100644
index 0000000..3dc4a2d
--- /dev/null
+++ b/src/spec/test/cli/ValSepI.groovy
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package cli
+
+import groovy.cli.Option
+import groovy.cli.Unparsed
+
+// tag::multipleArgsInterfaceSpec[]
+interface ValSepI {
+ @Option(numberOfArguments=2) String[] a()
+ @Option(numberOfArgumentsString='2', valueSeparator=',') String[] b()
+ @Option(numberOfArgumentsString='+', valueSeparator=',') String[] c()
+ @Unparsed remaining()
+}
+// end::multipleArgsInterfaceSpec[]
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/src/spec/test/cli/WithArgsI.groovy
----------------------------------------------------------------------
diff --git a/src/spec/test/cli/WithArgsI.groovy b/src/spec/test/cli/WithArgsI.groovy
new file mode 100644
index 0000000..aff71c0
--- /dev/null
+++ b/src/spec/test/cli/WithArgsI.groovy
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package cli
+
+import groovy.cli.Option
+import groovy.cli.Unparsed
+
+// tag::withArgumentInterfaceSpec[]
+interface WithArgsI {
+ @Option boolean a()
+ @Option String b()
+ @Option(optionalArg=true) String[] c()
+ @Unparsed List remaining()
+}
+// end::withArgumentInterfaceSpec[]
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/src/spec/test/cli/WithConvertI.groovy
----------------------------------------------------------------------
diff --git a/src/spec/test/cli/WithConvertI.groovy b/src/spec/test/cli/WithConvertI.groovy
new file mode 100644
index 0000000..1f3d97b
--- /dev/null
+++ b/src/spec/test/cli/WithConvertI.groovy
@@ -0,0 +1,31 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package cli
+
+import groovy.cli.Option
+import groovy.cli.Unparsed
+
+// tag::withConvertInterfaceSpec[]
+interface WithConvertI {
+ @Option(convert={ it.toLowerCase() }) String a()
+ @Option(convert={ it.toUpperCase() }) String b()
+ @Option(convert={ Date.parse("yyyy-MM-dd", it) }) Date d()
+ @Unparsed List remaining()
+}
+// end::withConvertInterfaceSpec[]
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/src/spec/test/cli/WithDefaultValueI.groovy
----------------------------------------------------------------------
diff --git a/src/spec/test/cli/WithDefaultValueI.groovy b/src/spec/test/cli/WithDefaultValueI.groovy
new file mode 100644
index 0000000..2d27379
--- /dev/null
+++ b/src/spec/test/cli/WithDefaultValueI.groovy
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package cli
+
+import groovy.cli.Option
+
+// tag::withDefaultValueInterfaceSpec[]
+interface WithDefaultValueI {
+ @Option(shortName='f', defaultValue='one') String from()
+ @Option(shortName='t', defaultValue='35') int to()
+}
+// end::withDefaultValueInterfaceSpec[]
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/subprojects/groovy-cli-commons/build.gradle
----------------------------------------------------------------------
diff --git a/subprojects/groovy-cli-commons/build.gradle b/subprojects/groovy-cli-commons/build.gradle
index c77cf10..ccb91ab 100644
--- a/subprojects/groovy-cli-commons/build.gradle
+++ b/subprojects/groovy-cli-commons/build.gradle
@@ -19,6 +19,7 @@
dependencies {
compile rootProject
compile "commons-cli:commons-cli:$commonsCliVersion"
+ testCompile rootProject.sourceSets.test.output
testCompile project(':groovy-test')
testCompile project(':groovy-dateutil')
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy b/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy
index c0b760a..7985159 100644
--- a/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy
+++ b/subprojects/groovy-cli-commons/src/spec/test/builder/CliBuilderTest.groovy
@@ -18,351 +18,35 @@
*/
package builder
-import groovy.cli.Option
+import cli.CliBuilderTestCase
import groovy.cli.TypedOption
-import groovy.cli.Unparsed
+import groovy.cli.commons.CliBuilder
import groovy.transform.TypeChecked
-import java.math.RoundingMode
+class CliBuilderTest extends CliBuilderTestCase {
-class CliBuilderTest extends GroovyTestCase {
-// void tearDown() {
-// }
+ String getImportCliBuilder() { 'import groovy.cli.commons.CliBuilder\n' }
- // tag::annotationInterfaceSpec[]
- interface GreeterI {
- @Option(shortName='h', description='display usage') Boolean help() // <1>
- @Option(shortName='a', description='greeting audience') String audience() // <2>
- @Unparsed List remaining() // <3>
+ // don't expect toString values to be the same, so test per CliBuilder implementation
+ void testAnnotationsInterfaceToString() {
+ doTestAnnotationsInterfaceToString('usage', '''\
+usage: groovy Greeter
+ -a,--audience <arg> greeting audience
+ -h,--help display usage
+''')
}
- // end::annotationInterfaceSpec[]
- // tag::annotationClassSpec[]
- class GreeterC {
- @Option(shortName='h', description='display usage')
- Boolean help // <1>
-
- private String audience
- @Option(shortName='a', description='greeting audience')
- void setAudience(String audience) { // <2>
- this.audience = audience
- }
- String getAudience() { audience }
-
- @Unparsed
- List remaining // <3>
- }
- // end::annotationClassSpec[]
-
- void testAnnotationsInterface() {
- // tag::annotationInterface[]
- def cli = new CliBuilder(usage: 'groovy Greeter [option]') // <1>
- def argz = '--audience Groovologist'.split()
- def options = cli.parseFromSpec(GreeterI, argz) // <2>
- assert options.audience() == 'Groovologist' // <3>
-
- argz = '-h Some Other Args'.split()
- options = cli.parseFromSpec(GreeterI, argz) // <4>
- assert options.help()
- assert options.remaining() == ['Some', 'Other', 'Args'] // <5>
- // end::annotationInterface[]
- }
-
- void testAnnotationsClass() {
- // tag::annotationClass[]
- def cli = new CliBuilder(usage: 'groovy Greeter [option]') // <1>
- def options = new GreeterC() // <2>
- def argz = '--audience Groovologist foo'.split()
- cli.parseFromInstance(options, argz) // <3>
- assert options.audience == 'Groovologist' // <4>
- assert options.remaining == ['foo'] // <5>
- // end::annotationClass[]
- }
-
- void testParseScript() {
- def argz = '--audience Groovologist foo'.split()
- new GroovyShell().run('''
- // tag::annotationScript[]
- import groovy.cli.OptionField
- import groovy.cli.UnparsedField
-
- @OptionField String audience
- @OptionField Boolean help
- @UnparsedField List remaining
- new CliBuilder().parseFromInstance(this, args)
- assert audience == 'Groovologist'
- assert remaining == ['foo']
- // end::annotationScript[]
- ''', 'TestScript.groovy', argz)
- }
-
- void testWithArgument() {
- // tag::withArgument[]
- def cli = new CliBuilder()
- cli.a(args: 0, 'a arg') // <1>
- cli.b(args: 1, 'b arg') // <2>
- cli.c(args: 1, optionalArg: true, 'c arg') // <3>
- def options = cli.parse('-a -b foo -c bar baz'.split()) // <4>
-
- assert options.a == true
- assert options.b == 'foo'
- assert options.c == 'bar'
- assert options.arguments() == ['baz']
-
- options = cli.parse('-a -c -b foo bar baz'.split()) // <5>
-
- assert options.a == true
- assert options.c == true
- assert options.b == 'foo'
- assert options.arguments() == ['bar', 'baz']
- // end::withArgument[]
- }
-
- // tag::withArgumentInterfaceSpec[]
- interface WithArgsI {
- @Option boolean a()
- @Option String b()
- @Option(optionalArg=true) String[] c()
- @Unparsed List remaining()
- }
- // end::withArgumentInterfaceSpec[]
-
- void testWithArgumentInterface() {
- // tag::withArgumentInterface[]
- def cli = new CliBuilder()
- def options = cli.parseFromSpec(WithArgsI, '-a -b foo -c bar baz'.split())
- assert options.a()
- assert options.b() == 'foo'
- assert options.c() == ['bar']
- assert options.remaining() == ['baz']
-
- options = cli.parseFromSpec(WithArgsI, '-a -c -b foo bar baz'.split())
- assert options.a()
- assert options.c() == []
- assert options.b() == 'foo'
- assert options.remaining() == ['bar', 'baz']
- // end::withArgumentInterface[]
- }
-
- void testMultipleArgsAndOptionalValueSeparator() {
- // tag::multipleArgs[]
- def cli = new CliBuilder()
- cli.a(args: 2, 'a-arg')
- cli.b(args: '2', valueSeparator: ',', 'b-arg') // <1>
- cli.c(args: '+', valueSeparator: ',', 'c-arg') // <2>
-
- def options = cli.parse('-a 1 2 3 4'.split()) // <3>
- assert options.a == '1' // <4>
- assert options.as == ['1', '2'] // <5>
- assert options.arguments() == ['3', '4']
-
- options = cli.parse('-a1 -a2 3'.split()) // <6>
- assert options.as == ['1', '2']
- assert options.arguments() == ['3']
-
- options = cli.parse(['-b1,2']) // <7>
- assert options.bs == ['1', '2']
-
- options = cli.parse(['-c', '1'])
- assert options.cs == ['1']
-
- options = cli.parse(['-c1'])
- assert options.cs == ['1']
-
- options = cli.parse(['-c1,2,3'])
- assert options.cs == ['1', '2', '3']
- // end::multipleArgs[]
- }
-
- // tag::multipleArgsInterfaceSpec[]
- interface ValSepI {
- @Option(numberOfArguments=2) String[] a()
- @Option(numberOfArgumentsString='2', valueSeparator=',') String[] b()
- @Option(numberOfArgumentsString='+', valueSeparator=',') String[] c()
- @Unparsed remaining()
- }
- // end::multipleArgsInterfaceSpec[]
-
- void testMultipleArgsAndOptionalValueSeparatorInterface() {
- // tag::multipleArgsInterface[]
- def cli = new CliBuilder()
-
- def options = cli.parseFromSpec(ValSepI, '-a 1 2 3 4'.split())
- assert options.a() == ['1', '2']
- assert options.remaining() == ['3', '4']
-
- options = cli.parseFromSpec(ValSepI, '-a1 -a2 3'.split())
- assert options.a() == ['1', '2']
- assert options.remaining() == ['3']
-
- options = cli.parseFromSpec(ValSepI, ['-b1,2'] as String[])
- assert options.b() == ['1', '2']
-
- options = cli.parseFromSpec(ValSepI, ['-c', '1'] as String[])
- assert options.c() == ['1']
-
- options = cli.parseFromSpec(ValSepI, ['-c1'] as String[])
- assert options.c() == ['1']
-
- options = cli.parseFromSpec(ValSepI, ['-c1,2,3'] as String[])
- assert options.c() == ['1', '2', '3']
- // end::multipleArgsInterface[]
- }
-
- void testType() {
- // tag::withType[]
- def argz = '''-a John -b -d 21 -e 1980 -f 3.5 -g 3.14159
- -h cv.txt -i DOWN and some more'''.split()
- def cli = new CliBuilder()
- cli.a(type: String, 'a-arg')
- cli.b(type: boolean, 'b-arg')
- cli.c(type: Boolean, 'c-arg')
- cli.d(type: int, 'd-arg')
- cli.e(type: Long, 'e-arg')
- cli.f(type: Float, 'f-arg')
- cli.g(type: BigDecimal, 'g-arg')
- cli.h(type: File, 'h-arg')
- cli.i(type: RoundingMode, 'i-arg')
- def options = cli.parse(argz)
- assert options.a == 'John'
- assert options.b
- assert !options.c
- assert options.d == 21
- assert options.e == 1980L
- assert options.f == 3.5f
- assert options.g == 3.14159
- assert options.h == new File('cv.txt')
- assert options.i == RoundingMode.DOWN
- assert options.arguments() == ['and', 'some', 'more']
- // end::withType[]
- }
-
- void testTypeMultiple() {
- // tag::withTypeMultiple[]
- def argz = '''-j 3 4 5 -k1.5,2.5,3.5 and some more'''.split()
- def cli = new CliBuilder()
- cli.j(args: 3, type: int[], 'j-arg')
- cli.k(args: '+', valueSeparator: ',', type: BigDecimal[], 'k-arg')
- def options = cli.parse(argz)
- assert options.js == [3, 4, 5] // <1>
- assert options.j == [3, 4, 5] // <1>
- assert options.k == [1.5, 2.5, 3.5]
- assert options.arguments() == ['and', 'some', 'more']
- // end::withTypeMultiple[]
- }
-
- void testConvert() {
- // tag::withConvert[]
- def argz = '''-a John -b Mary -d 2016-01-01 and some more'''.split()
- def cli = new CliBuilder()
- def lower = { it.toLowerCase() }
- cli.a(convert: lower, 'a-arg')
- cli.b(convert: { it.toUpperCase() }, 'b-arg')
- cli.d(convert: { Date.parse('yyyy-MM-dd', it) }, 'd-arg')
- def options = cli.parse(argz)
- assert options.a == 'john'
- assert options.b == 'MARY'
- assert options.d.format('dd-MMM-yyyy') == '01-Jan-2016'
- assert options.arguments() == ['and', 'some', 'more']
- // end::withConvert[]
- }
-
- // tag::withConvertInterfaceSpec[]
- interface WithConvertI {
- @Option(convert={ it.toLowerCase() }) String a()
- @Option(convert={ it.toUpperCase() }) String b()
- @Option(convert={ Date.parse("yyyy-MM-dd", it) }) Date d()
- @Unparsed List remaining()
- }
- // end::withConvertInterfaceSpec[]
-
- void testConvertInterface() {
- // tag::withConvertInterface[]
- Date newYears = Date.parse("yyyy-MM-dd", "2016-01-01")
- def argz = '''-a John -b Mary -d 2016-01-01 and some more'''.split()
- def cli = new CliBuilder()
- def options = cli.parseFromSpec(WithConvertI, argz)
- assert options.a() == 'john'
- assert options.b() == 'MARY'
- assert options.d() == newYears
- assert options.remaining() == ['and', 'some', 'more']
- // end::withConvertInterface[]
- }
-
- void testDefaultValue() {
- // tag::withDefaultValue[]
- def cli = new CliBuilder()
- cli.f longOpt: 'from', type: String, args: 1, defaultValue: 'one', 'f option'
- cli.t longOpt: 'to', type: int, defaultValue: '35', 't option'
-
- def options = cli.parse('-f two'.split())
- assert options.hasOption('f')
- assert options.f == 'two'
- assert !options.hasOption('t')
- assert options.t == 35
-
- options = cli.parse('-t 45'.split())
- assert !options.hasOption('from')
- assert options.from == 'one'
- assert options.hasOption('to')
- assert options.to == 45
- // end::withDefaultValue[]
- }
-
- // tag::withDefaultValueInterfaceSpec[]
- interface WithDefaultValueI {
- @Option(shortName='f', defaultValue='one') String from()
- @Option(shortName='t', defaultValue='35') int to()
- }
- // end::withDefaultValueInterfaceSpec[]
-
- void testDefaultValueInterface() {
- // tag::withDefaultValueInterface[]
- def cli = new CliBuilder()
-
- def options = cli.parseFromSpec(WithDefaultValueI, '-f two'.split())
- assert options.from() == 'two'
- assert options.to() == 35
-
- options = cli.parseFromSpec(WithDefaultValueI, '-t 45'.split())
- assert options.from() == 'one'
- assert options.to() == 45
- // end::withDefaultValueInterface[]
- }
-
- // tag::withTypeCheckedInterfaceSpec[]
- interface TypeCheckedI{
- @Option String name()
- @Option int age()
- @Unparsed List remaining()
- }
- // end::withTypeCheckedInterfaceSpec[]
-
- // tag::withTypeCheckedInterface[]
- @TypeChecked
- void testTypeCheckedInterface() {
- def argz = "--name John --age 21 and some more".split()
- def cli = new CliBuilder()
- def options = cli.parseFromSpec(TypeCheckedI, argz)
- String n = options.name()
- int a = options.age()
- assert n == 'John' && a == 21
- assert options.remaining() == ['and', 'some', 'more']
- }
- // end::withTypeCheckedInterface[]
-
- // tag::withTypeChecked[]
@TypeChecked
- void testTypeChecked() {
+ void testTypeChecked_showingSingleHyphenForLongOptSupport() {
def cli = new CliBuilder()
TypedOption<String> name = cli.option(String, opt: 'n', longOpt: 'name', 'name option')
TypedOption<Integer> age = cli.option(Integer, longOpt: 'age', 'age option')
- def argz = "--name John --age 21 and some more".split()
+ def argz = "--name John -age 21 and some more".split()
def options = cli.parse(argz)
String n = options[name]
int a = options[age]
assert n == 'John' && a == 21
assert options.arguments() == ['and', 'some', 'more']
}
- // end::withTypeChecked[]
+
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/subprojects/groovy-cli-commons/src/spec/test/groovy/util/CliBuilderTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-cli-commons/src/spec/test/groovy/util/CliBuilderTest.groovy b/subprojects/groovy-cli-commons/src/spec/test/groovy/util/CliBuilderTest.groovy
new file mode 100644
index 0000000..a0d513c
--- /dev/null
+++ b/subprojects/groovy-cli-commons/src/spec/test/groovy/util/CliBuilderTest.groovy
@@ -0,0 +1,28 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package groovy.util
+
+import cli.CliBuilderTestCase
+
+// test groovy.util legacy delegate
+class CliBuilderTest extends CliBuilderTestCase {
+
+ String getImportCliBuilder() { '' }
+
+}
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/subprojects/groovy-cli-picocli/build.gradle
----------------------------------------------------------------------
diff --git a/subprojects/groovy-cli-picocli/build.gradle b/subprojects/groovy-cli-picocli/build.gradle
index dececa0..d83ddfd 100644
--- a/subprojects/groovy-cli-picocli/build.gradle
+++ b/subprojects/groovy-cli-picocli/build.gradle
@@ -19,6 +19,7 @@
dependencies {
compile rootProject
compile "info.picocli:picocli:$picocliVersion"
+ testCompile rootProject.sourceSets.test.output
testCompile project(':groovy-test')
testCompile project(':groovy-dateutil')
}
http://git-wip-us.apache.org/repos/asf/groovy/blob/926b24a4/subprojects/groovy-cli-picocli/src/spec/test/builder/CliBuilderTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-cli-picocli/src/spec/test/builder/CliBuilderTest.groovy b/subprojects/groovy-cli-picocli/src/spec/test/builder/CliBuilderTest.groovy
index 195ac0d..62e00fd 100644
--- a/subprojects/groovy-cli-picocli/src/spec/test/builder/CliBuilderTest.groovy
+++ b/subprojects/groovy-cli-picocli/src/spec/test/builder/CliBuilderTest.groovy
@@ -18,366 +18,45 @@
*/
package builder
+import cli.CliBuilderTestCase
import groovy.cli.picocli.CliBuilder
-import groovy.cli.Option
import groovy.cli.TypedOption
-import groovy.cli.Unparsed
import groovy.transform.TypeChecked
-import java.math.RoundingMode
-import java.text.SimpleDateFormat
+// tag::mapOptionImports[]
import java.util.concurrent.TimeUnit
import static java.util.concurrent.TimeUnit.DAYS
import static java.util.concurrent.TimeUnit.HOURS
+// end::mapOptionImports[]
-//import java.math.RoundingMode
+// Core functionality we expect to remain the same for all implementations is tested in the base test case
+// here we also add any functionality specific to this implementation that we value highly
+class CliBuilderTest extends CliBuilderTestCase {
-class CliBuilderTest extends GroovyTestCase {
-// void tearDown() {
-// }
+ String getImportCliBuilder() { 'import groovy.cli.picocli.CliBuilder\n' }
- // tag::annotationInterfaceSpec[]
- interface GreeterI {
- @Option(shortName='h', description='display usage') Boolean help() // <1>
- @Option(shortName='a', description='greeting audience') String audience() // <2>
- @Unparsed(description = "positional parameters") List remaining() // <3>
- }
- // end::annotationInterfaceSpec[]
-
- // tag::annotationClassSpec[]
- class GreeterC {
- @Option(shortName='h', description='display usage')
- Boolean help // <1>
-
- private String audience
- @Option(shortName='a', description='greeting audience')
- void setAudience(String audience) { // <2>
- this.audience = audience
- }
- String getAudience() { audience }
-
- @Unparsed(description = "positional parameters")
- List remaining // <3>
+ void testAnnotationsInterfaceToStringWithUsage() {
+ doTestAnnotationsInterfaceToString('usage', '''\
+Usage: groovy Greeter
+ [<remaining>...] positional parameters
+ -a, --audience=<audience>
+ greeting audience
+ -h, --help display usage
+''')
}
- // end::annotationClassSpec[]
-
- void testAnnotationsInterface() {
- // tag::annotationInterface[]
- def cli = new CliBuilder(name: 'groovy Greeter') // <1>
- def argz = '--audience Groovologist'.split()
- def options = cli.parseFromSpec(GreeterI, argz) // <2>
- assert options.audience() == 'Groovologist' // <3>
-
- argz = '-h Some Other Args'.split()
- options = cli.parseFromSpec(GreeterI, argz) // <4>
- assert options.help()
- assert options.remaining() == ['Some', 'Other', 'Args'] // <5>
- // end::annotationInterface[]
-
- options = cli.parseFromSpec(GreeterI, ['-h', 'Some', 'Other', 'Args'] as String[])
- assert options.help()
- assert options.remaining() == ['Some', 'Other', 'Args']
- StringWriter sw = new StringWriter()
- cli.writer = new PrintWriter(sw)
- cli.usage()
- String expected = '''\
+ void testAnnotationsInterfaceToStringWithName() {
+ doTestAnnotationsInterfaceToString('name', '''\
Usage: groovy Greeter [-h] [-a=<audience>] [<remaining>...]
[<remaining>...] positional parameters
-a, --audience=<audience>
greeting audience
-h, --help display usage
-'''
- assert expected.normalize() == sw.toString().normalize()
- }
-
- void testAnnotationsClass() {
- // tag::annotationClass[]
- def cli = new CliBuilder(usage: 'groovy Greeter [option]') // <1>
- def options = new GreeterC() // <2>
- def argz = '--audience Groovologist foo'.split()
- cli.parseFromInstance(options, argz) // <3>
- assert options.audience == 'Groovologist' // <4>
- assert options.remaining == ['foo'] // <5>
- // end::annotationClass[]
- }
-
- void testParseScript() {
- def argz = '--audience Groovologist foo'.split()
- new GroovyShell().run('''
- // tag::annotationScript[]
- import groovy.cli.picocli.CliBuilder
- import groovy.cli.OptionField
- import groovy.cli.UnparsedField
-
- @OptionField String audience
- @OptionField Boolean help
- @UnparsedField List remaining
- new CliBuilder().parseFromInstance(this, args)
- assert audience == 'Groovologist'
- assert remaining == ['foo']
- // end::annotationScript[]
- ''', 'TestScript.groovy', argz)
- }
-
- void testWithArgument() {
- // tag::withArgument[]
- def cli = new CliBuilder()
- cli.a(args: 0, 'a arg') // <1>
- cli.b(args: 1, 'b arg') // <2>
- cli.c(args: 1, optionalArg: true, 'c arg') // <3>
- def options = cli.parse('-a -b foo -c bar baz'.split()) // <4>
-
- assert options.a == true
- assert options.b == 'foo'
- assert options.c == 'bar'
- assert options.arguments() == ['baz']
-
- options = cli.parse('-a -c -b foo bar baz'.split()) // <5>
-
- assert options.a == true
- assert options.c == true
- assert options.b == 'foo'
- assert options.arguments() == ['bar', 'baz']
- // end::withArgument[]
- }
-
- // tag::withArgumentInterfaceSpec[]
- interface WithArgsI {
- @Option boolean a()
- @Option String b()
- @Option(optionalArg=true) String[] c()
- @Unparsed List remaining()
- }
- // end::withArgumentInterfaceSpec[]
-
- void testWithArgumentInterface() {
- // tag::withArgumentInterface[]
- def cli = new CliBuilder()
- def options = cli.parseFromSpec(WithArgsI, '-a -b foo -c bar baz'.split())
- assert options.a()
- assert options.b() == 'foo'
- assert options.c() == ['bar']
- assert options.remaining() == ['baz']
-
- options = cli.parseFromSpec(WithArgsI, '-a -c -b foo bar baz'.split())
- assert options.a()
- assert options.c() == []
- assert options.b() == 'foo'
- assert options.remaining() == ['bar', 'baz']
- // end::withArgumentInterface[]
- }
-
- void testMultipleArgsAndOptionalValueSeparator() {
- // tag::multipleArgs[]
- def cli = new CliBuilder()
- cli.a(args: 2, 'a-arg')
- cli.b(args: '2', valueSeparator: ',', 'b-arg') // <1>
- cli.c(args: '+', valueSeparator: ',', 'c-arg') // <2>
-
- def options = cli.parse('-a 1 2 3 4'.split()) // <3>
- assert options.a == '1' // <4>
- assert options.as == ['1', '2'] // <5>
- assert options.arguments() == ['3', '4']
-
- options = cli.parse('-a1 -a2 3'.split()) // <6>
- assert options.as == ['1', '2']
- assert options.arguments() == ['3']
-
- options = cli.parse(['-b1,2']) // <7>
- assert options.bs == ['1', '2']
-
- options = cli.parse(['-c', '1'])
- assert options.cs == ['1']
-
- options = cli.parse(['-c1'])
- assert options.cs == ['1']
-
- options = cli.parse(['-c1,2,3'])
- assert options.cs == ['1', '2', '3']
- // end::multipleArgs[]
- }
-
- // tag::multipleArgsInterfaceSpec[]
- interface ValSepI {
- @Option(numberOfArguments=2) String[] a()
- @Option(numberOfArgumentsString='2', valueSeparator=',') String[] b()
- @Option(numberOfArgumentsString='+', valueSeparator=',') String[] c()
- @Unparsed remaining()
- }
- // end::multipleArgsInterfaceSpec[]
-
- void testMultipleArgsAndOptionalValueSeparatorInterface() {
- // tag::multipleArgsInterface[]
- def cli = new CliBuilder()
-
- def options = cli.parseFromSpec(ValSepI, '-a 1 2 3 4'.split())
- assert options.a() == ['1', '2']
- assert options.remaining() == ['3', '4']
-
- options = cli.parseFromSpec(ValSepI, '-a1 -a2 3'.split())
- assert options.a() == ['1', '2']
- assert options.remaining() == ['3']
-
- options = cli.parseFromSpec(ValSepI, ['-b1,2'] as String[])
- assert options.b() == ['1', '2']
-
- options = cli.parseFromSpec(ValSepI, ['-c', '1'] as String[])
- assert options.c() == ['1']
-
- options = cli.parseFromSpec(ValSepI, ['-c1'] as String[])
- assert options.c() == ['1']
-
- options = cli.parseFromSpec(ValSepI, ['-c1,2,3'] as String[])
- assert options.c() == ['1', '2', '3']
- // end::multipleArgsInterface[]
- }
-
- void testType() {
- // tag::withType[]
- def argz = '''-a John -b -d 21 -e 1980 -f 3.5 -g 3.14159
- -h cv.txt -i DOWN and some more'''.split()
- def cli = new CliBuilder()
- cli.a(type: String, 'a-arg')
- cli.b(type: boolean, 'b-arg')
- cli.c(type: Boolean, 'c-arg')
- cli.d(type: int, 'd-arg')
- cli.e(type: Long, 'e-arg')
- cli.f(type: Float, 'f-arg')
- cli.g(type: BigDecimal, 'g-arg')
- cli.h(type: File, 'h-arg')
- cli.i(type: RoundingMode, 'i-arg')
- def options = cli.parse(argz)
- assert options.a == 'John'
- assert options.b
- assert !options.c
- assert options.d == 21
- assert options.e == 1980L
- assert options.f == 3.5f
- assert options.g == 3.14159
- assert options.h == new File('cv.txt')
- assert options.i == RoundingMode.DOWN
- assert options.arguments() == ['and', 'some', 'more']
- // end::withType[]
- }
-
- void testTypeMultiple() {
- // tag::withTypeMultiple[]
- def argz = '''-j 3 4 5 -k1.5,2.5,3.5 and some more'''.split()
- def cli = new CliBuilder()
- cli.j(args: 3, type: int[], 'j-arg')
- cli.k(args: '+', valueSeparator: ',', type: BigDecimal[], 'k-arg')
- def options = cli.parse(argz)
- assert options.js == [3, 4, 5] // <1>
- assert options.j == [3, 4, 5] // <1>
- assert options.k == [1.5, 2.5, 3.5]
- assert options.arguments() == ['and', 'some', 'more']
- // end::withTypeMultiple[]
- }
-
- void testConvert() {
- // tag::withConvert[]
- def argz = '''-a John -b Mary -d 2016-01-01 and some more'''.split()
- def cli = new CliBuilder()
- def lower = { it.toLowerCase() }
- cli.a(convert: lower, 'a-arg')
- cli.b(convert: { it.toUpperCase() }, 'b-arg')
- cli.d(convert: { new SimpleDateFormat("yyyy-MM-dd").parse(it) }, 'd-arg')
- def options = cli.parse(argz)
- assert options.a == 'john'
- assert options.b == 'MARY'
- assert new SimpleDateFormat("dd-MMM-yyyy").format(options.d) == '01-Jan-2016'
- assert options.arguments() == ['and', 'some', 'more']
- // end::withConvert[]
- }
-
- // tag::withConvertInterfaceSpec[]
- interface WithConvertI {
- @Option(convert={ it.toLowerCase() }) String a()
- @Option(convert={ it.toUpperCase() }) String b()
- @Option(convert={ new SimpleDateFormat("yyyy-MM-dd").parse(it) }) Date d()
- @Unparsed List remaining()
- }
- // end::withConvertInterfaceSpec[]
-
- void testConvertInterface() {
- // tag::withConvertInterface[]
- Date newYears = new SimpleDateFormat("yyyy-MM-dd").parse("2016-01-01")
- def argz = '''-a John -b Mary -d 2016-01-01 and some more'''.split()
- def cli = new CliBuilder()
- def options = cli.parseFromSpec(WithConvertI, argz)
- assert options.a() == 'john'
- assert options.b() == 'MARY'
- assert options.d() == newYears
- assert options.remaining() == ['and', 'some', 'more']
- // end::withConvertInterface[]
- }
-
- void testDefaultValue() {
- // tag::withDefaultValue[]
- def cli = new CliBuilder()
- cli.f longOpt: 'from', type: String, args: 1, defaultValue: 'one', 'f option'
- cli.t longOpt: 'to', type: int, defaultValue: '35', 't option'
-
- def options = cli.parse('-f two'.split())
- assert options.hasOption('f')
- assert options.f == 'two'
- assert !options.hasOption('t')
- assert options.t == 35
-
- options = cli.parse('-t 45'.split())
- assert !options.hasOption('from')
- assert options.from == 'one'
- assert options.hasOption('to')
- assert options.to == 45
- // end::withDefaultValue[]
- }
-
- // tag::withDefaultValueInterfaceSpec[]
- interface WithDefaultValueI {
- @Option(shortName='f', defaultValue='one') String from()
- @Option(shortName='t', defaultValue='35') int to()
- }
- // end::withDefaultValueInterfaceSpec[]
-
- void testDefaultValueInterface() {
- // tag::withDefaultValueInterface[]
- def cli = new CliBuilder()
-
- def options = cli.parseFromSpec(WithDefaultValueI, '-f two'.split())
- assert options.from() == 'two'
- assert options.to() == 35
-
- options = cli.parseFromSpec(WithDefaultValueI, '-t 45'.split())
- assert options.from() == 'one'
- assert options.to() == 45
- // end::withDefaultValueInterface[]
- }
-
- // tag::withTypeCheckedInterfaceSpec[]
- interface TypeCheckedI{
- @Option String name()
- @Option int age()
- @Unparsed List remaining()
- }
- // end::withTypeCheckedInterfaceSpec[]
-
- // tag::withTypeCheckedInterface[]
- @TypeChecked
- void testTypeCheckedInterface() {
- def argz = "--name John --age 21 and some more".split()
- def cli = new CliBuilder()
- def options = cli.parseFromSpec(TypeCheckedI, argz)
- String n = options.name()
- int a = options.age()
- assert n == 'John' && a == 21
- assert options.remaining() == ['and', 'some', 'more']
+''')
}
- // end::withTypeCheckedInterface[]
- // tag::withTypeChecked[]
@TypeChecked
- void testTypeChecked() {
+ void testTypeChecked_addingSingleHyphenForLongOptSupport() {
def cli = new CliBuilder(acceptLongOptionsWithSingleHyphen: true)
TypedOption<String> name = cli.option(String, opt: 'n', longOpt: 'name', 'name option')
TypedOption<Integer> age = cli.option(Integer, longOpt: 'age', 'age option')
@@ -388,7 +67,6 @@ Usage: groovy Greeter [-h] [-a=<audience>] [<remaining>...]
assert n == 'John' && a == 21
assert options.arguments() == ['and', 'some', 'more']
}
- // end::withTypeChecked[]
@TypeChecked
void testTypeChecked_defaultOnlyDoubleHyphen() {
@@ -450,8 +128,8 @@ Footer 2
assertEquals(expected.normalize(), baos.toString().normalize())
}
- public void testMapOption() {
- // tag::MapOption[]
+ void testMapOption() {
+ // tag::mapOption[]
def cli = new CliBuilder()
cli.D(args: 2, valueSeparator: '=', 'the old way') // <1>
cli.X(type: Map, 'the new way') // <2>
@@ -461,10 +139,10 @@ Footer 2
assert options.Ds == ['a', 'b', 'c', 'd'] // <5>
assert options.Xs == [ 'x':'y', 'i':'j' ] // <6>
assert options.Zs == [ (DAYS as TimeUnit):2, (HOURS as TimeUnit):23 ] // <7>
- // end::MapOption[]
+ // end::mapOption[]
}
- public void testGroovyDocAntExample() {
+ void testGroovyDocAntExample() {
def cli = new CliBuilder(usage:'ant [options] [targets]',
header:'Options:')
cli.help('print this message')
@@ -493,7 +171,7 @@ Options:
assertEquals(expected.normalize(), sw.toString().normalize())
}
- public void testGroovyDocCurlExample() {
+ void testGroovyDocCurlExample() {
// suppress ANSI escape codes to make this test pass on all environments
System.setProperty("picocli.ansi", "false")
ByteArrayOutputStream baos = new ByteArrayOutputStream()
[2/3] groovy git commit: GROOVY-8569 minor tweak (fix tests for
previous change)
Posted by pa...@apache.org.
GROOVY-8569 minor tweak (fix tests for previous change)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/ae40032b
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/ae40032b
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/ae40032b
Branch: refs/heads/GROOVY_2_5_X
Commit: ae40032b9e8c6f441ec5b575ba7858c9b2a8fb63
Parents: 926b24a
Author: Paul King <pa...@asert.com.au>
Authored: Sat May 19 23:33:54 2018 +1000
Committer: Paul King <pa...@asert.com.au>
Committed: Sun May 20 00:01:56 2018 +1000
----------------------------------------------------------------------
src/test/groovy/ui/GroovyMainTest.groovy | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/ae40032b/src/test/groovy/ui/GroovyMainTest.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/ui/GroovyMainTest.groovy b/src/test/groovy/ui/GroovyMainTest.groovy
index ab788ac..018bc41 100644
--- a/src/test/groovy/ui/GroovyMainTest.groovy
+++ b/src/test/groovy/ui/GroovyMainTest.groovy
@@ -27,13 +27,13 @@ class GroovyMainTest extends GroovyTestCase {
GroovyMain.processArgs(args, ps)
def out = baos.toString()
assert out.contains('Usage: groovy')
- ['-a', '-c', '-d', '-e', '-h', '-i', '-l', '-n', '-p', '-V'].each{
+ ['-a', '-c', '-d', '-e', '-h', '-i', '-l', '-n', '-p', '-v'].each{
assert out.contains(it)
}
}
void testVersion() {
- String[] args = ['-V']
+ String[] args = ['-v']
GroovyMain.processArgs(args, ps)
def out = baos.toString()
assert out.contains('Groovy Version:')
[3/3] groovy git commit: GROOVY-8579: No bytecode level check is done
before producing JDK8+ bytecode (avoid fix for DGM methods)
Posted by pa...@apache.org.
GROOVY-8579: No bytecode level check is done before producing JDK8+ bytecode (avoid fix for DGM methods)
Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/3fbd0b6f
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/3fbd0b6f
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/3fbd0b6f
Branch: refs/heads/GROOVY_2_5_X
Commit: 3fbd0b6f638165242d97ba4b372ba0593c80800c
Parents: ae40032
Author: Paul King <pa...@asert.com.au>
Authored: Sat May 19 23:57:11 2018 +1000
Committer: Paul King <pa...@asert.com.au>
Committed: Sun May 20 00:01:57 2018 +1000
----------------------------------------------------------------------
.../codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/groovy/blob/3fbd0b6f/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index d82b414..61d2f23 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3252,7 +3252,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
storeType(call, returnType);
storeTargetMethod(call, directMethodCallCandidate);
ClassNode declaringClass = directMethodCallCandidate.getDeclaringClass();
- if (declaringClass.isInterface() && directMethodCallCandidate.isStatic()) {
+ if (declaringClass.isInterface() && directMethodCallCandidate.isStatic() && !(directMethodCallCandidate instanceof ExtensionMethodNode)) {
typeCheckingContext.getEnclosingClassNode().putNodeMetaData(MINIMUM_BYTECODE_VERSION, Opcodes.V1_8);
}
String data = chosenReceiver.getData();