From a9eecb003ed4c245031f5f7e899eb450f4de5f54 Mon Sep 17 00:00:00 2001 From: Rob Vesse Date: Mon, 15 Apr 2019 17:30:41 +0100 Subject: [PATCH] First unit tests for positional args (#91) --- .../annotations/PositionalArgument.java | 26 ++++++++---- .../rvesse/airline/model/MetadataLoader.java | 7 +++- .../rvesse/airline/TestPositionalArgs.java | 40 +++++++++++++++++++ .../rvesse/airline/args/ArgsPositional.java | 38 ++++++++++++++++++ .../airline/args/ArgsPositionalGap.java | 38 ++++++++++++++++++ 5 files changed, 139 insertions(+), 10 deletions(-) create mode 100644 airline-core/src/test/java/com/github/rvesse/airline/TestPositionalArgs.java create mode 100644 airline-core/src/test/java/com/github/rvesse/airline/args/ArgsPositional.java create mode 100644 airline-core/src/test/java/com/github/rvesse/airline/args/ArgsPositionalGap.java diff --git a/airline-core/src/main/java/com/github/rvesse/airline/annotations/PositionalArgument.java b/airline-core/src/main/java/com/github/rvesse/airline/annotations/PositionalArgument.java index 85853a192..fa7fbc062 100644 --- a/airline-core/src/main/java/com/github/rvesse/airline/annotations/PositionalArgument.java +++ b/airline-core/src/main/java/com/github/rvesse/airline/annotations/PositionalArgument.java @@ -34,6 +34,14 @@ @Target({ FIELD }) @Documented public @interface PositionalArgument { + + /** + * Helper constants for more explicitly specifying the positional index of + * the argument + */ + public static final int FIRST = 0, SECOND = 1, THIRD = 2, FOURTH = 3, FIFTH = 4, SIXTH = 5, SEVENTH = 6, EIGTH = 7, + NINTH = 8, TENTH = 9; + /** * Name of the argument * @@ -49,29 +57,31 @@ String description() default ""; /** - * The positional index (one-based) for the argument + * The positional index (zero-based) for the argument *

- * So {@code 1} represents the first argument, {@code 3} the third argument - * and so forth + * So {@code 0} represents the first argument, {@code 3} the fourth argument + * and so forth. Helper constants are provided on the annotation class e.g. + * {@link #SECOND} for making uses of this annotation more clear *

* * @return */ int position(); - + /** * If true this parameter can override parameters of the same index (set via - * the {@link PositionalArgument#position()} property) declared by parent classes assuming - * the argument definitions are compatible. + * the {@link PositionalArgument#position()} property) declared by parent + * classes assuming the argument definitions are compatible. *

* See * {@link PositionalArgumentMetadata#override(PositionalArgumentMetadata, PositionalArgumentMetadata)} * for legal overrides *

*

- * Note that where the child argument definition is an exact duplicate of the - * parent then overriding is implicitly permitted + * Note that where the child argument definition is an exact duplicate of + * the parent then overriding is implicitly permitted *

+ * * @return True if an override, false otherwise */ boolean override() default false; diff --git a/airline-core/src/main/java/com/github/rvesse/airline/model/MetadataLoader.java b/airline-core/src/main/java/com/github/rvesse/airline/model/MetadataLoader.java index 8da72bb6b..0ef7cb336 100644 --- a/airline-core/src/main/java/com/github/rvesse/airline/model/MetadataLoader.java +++ b/airline-core/src/main/java/com/github/rvesse/airline/model/MetadataLoader.java @@ -956,8 +956,11 @@ private static List overridePositionalArgumentSet(Li } } - List posArgs = new ArrayList<>(maxIndex); - for (int i = 0; i < maxIndex; i++) { + List posArgs = new ArrayList<>(maxIndex + 1); + for (int i = 0; i <= maxIndex; i++) { + while (posArgs.size() <= i) { + posArgs.add(null); + } posArgs.set(i, argsIndex.get(i)); if (posArgs.get(i) == null) { throw new IllegalStateException(String.format( diff --git a/airline-core/src/test/java/com/github/rvesse/airline/TestPositionalArgs.java b/airline-core/src/test/java/com/github/rvesse/airline/TestPositionalArgs.java new file mode 100644 index 000000000..6bd8dd992 --- /dev/null +++ b/airline-core/src/test/java/com/github/rvesse/airline/TestPositionalArgs.java @@ -0,0 +1,40 @@ +package com.github.rvesse.airline; + +import com.github.rvesse.airline.args.ArgsPositional; +import com.github.rvesse.airline.args.ArgsPositionalGap; +import com.github.rvesse.airline.model.PositionalArgumentMetadata; +import com.github.rvesse.airline.parser.command.SingleCommandParser; + +import static com.github.rvesse.airline.TestingUtil.singleCommandParser; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertTrue; + +import org.testng.Assert; +import org.testng.annotations.Test; + +public class TestPositionalArgs { + + @Test + public void positional_args_01() { + SingleCommand parser = singleCommandParser(ArgsPositional.class); + assertFalse(parser.getCommandMetadata().getPositionalArguments().isEmpty()); + assertEquals(parser.getCommandMetadata().getPositionalArguments().size(), 2); + + PositionalArgumentMetadata posArg = parser.getCommandMetadata().getPositionalArguments().get(0); + assertEquals(posArg.getZeroBasedPosition(), 0); + assertEquals(posArg.getOneBasedPosition(), 1); + assertEquals(posArg.getJavaType(), String.class); + + posArg = parser.getCommandMetadata().getPositionalArguments().get(1); + assertEquals(posArg.getZeroBasedPosition(), 1); + assertEquals(posArg.getOneBasedPosition(), 2); + assertEquals(posArg.getJavaType(), Integer.class); + + } + + @Test(expectedExceptions = IllegalStateException.class) + public void positional_args_gap_01() { + singleCommandParser(ArgsPositionalGap.class); + } +} diff --git a/airline-core/src/test/java/com/github/rvesse/airline/args/ArgsPositional.java b/airline-core/src/test/java/com/github/rvesse/airline/args/ArgsPositional.java new file mode 100644 index 000000000..d16694f0b --- /dev/null +++ b/airline-core/src/test/java/com/github/rvesse/airline/args/ArgsPositional.java @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2010-16 the original author or authors. + * + * Licensed 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 com.github.rvesse.airline.args; + +import com.github.rvesse.airline.annotations.Arguments; +import com.github.rvesse.airline.annotations.Command; +import com.github.rvesse.airline.annotations.PositionalArgument; +import com.github.rvesse.airline.annotations.restrictions.Required; + +import java.util.ArrayList; +import java.util.List; + +@Command(name = "ArgsPositional", description = "ArgsPositional description") +public class ArgsPositional +{ + @PositionalArgument(position = PositionalArgument.FIRST, title = "File") + @Required + public String file; + + @PositionalArgument(position = PositionalArgument.SECOND, title = "Mode") + public Integer mode; + + @Arguments + public List parameters = new ArrayList<>(); +} diff --git a/airline-core/src/test/java/com/github/rvesse/airline/args/ArgsPositionalGap.java b/airline-core/src/test/java/com/github/rvesse/airline/args/ArgsPositionalGap.java new file mode 100644 index 000000000..50ee50563 --- /dev/null +++ b/airline-core/src/test/java/com/github/rvesse/airline/args/ArgsPositionalGap.java @@ -0,0 +1,38 @@ +/** + * Copyright (C) 2010-16 the original author or authors. + * + * Licensed 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 com.github.rvesse.airline.args; + +import com.github.rvesse.airline.annotations.Arguments; +import com.github.rvesse.airline.annotations.Command; +import com.github.rvesse.airline.annotations.PositionalArgument; +import com.github.rvesse.airline.annotations.restrictions.Required; + +import java.util.ArrayList; +import java.util.List; + +@Command(name = "ArgsPositional", description = "ArgsPositional description") +public class ArgsPositionalGap +{ + @PositionalArgument(position = PositionalArgument.FIRST, title = "File") + @Required + public String file; + + @PositionalArgument(position = PositionalArgument.THIRD, title = "Mode") + public Integer mode; + + @Arguments + public List parameters = new ArrayList<>(); +}