CommonsCliValidateOptionsTest.java
/*
* 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 org.apache.maven.cling.invoker.mvnval;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.cli.ParseException;
import org.apache.maven.api.cli.ParserRequest;
import org.apache.maven.jline.JLineMessageBuilderFactory;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* Unit tests for the {@link CommonsCliValidateOptions} class.
* Tests that POM paths arrive as positional arguments, that the options carrying a value take
* one, and that a bad {@code --format} value reaches the invoker rather than being rejected
* while the options are parsed.
*/
@DisplayName("CommonsCliValidateOptions")
class CommonsCliValidateOptionsTest {
@Test
@DisplayName("should report no poms and no format when given no arguments")
void shouldReportNothingWhenGivenNoArguments() throws ParseException {
CommonsCliValidateOptions options = CommonsCliValidateOptions.parse(new String[0]);
assertTrue(options.poms().isEmpty(), "no positional arguments means no poms");
assertTrue(options.format().isEmpty(), "no --format means no format");
}
@Test
@DisplayName("should take poms from the positional arguments, in order")
void shouldTakePomsFromPositionalArguments() throws ParseException {
CommonsCliValidateOptions options = CommonsCliValidateOptions.parse(new String[] {"a/pom.xml", "b/pom.xml"});
assertEquals(
List.of("a/pom.xml", "b/pom.xml"),
options.poms().orElseThrow(),
"positional arguments should be the poms to validate");
}
@Test
@DisplayName("should read the format from --format")
void shouldReadFormatFromOption() throws ParseException {
assertEquals(
"json",
CommonsCliValidateOptions.parse(new String[] {"--format", "json"})
.format()
.orElseThrow());
}
@Test
@DisplayName("should carry a bad --format through to the invoker rather than failing to parse")
void shouldNotRejectBadFormatWhileParsing() throws ParseException {
// Failing here would mark the invocation unparseable and exit 1, while the tool documents
// 2 for bad usage. ValidateInvoker rejects the value and returns that code.
CommonsCliValidateOptions options = CommonsCliValidateOptions.parse(new String[] {"--format", "xml"});
assertEquals("xml", options.format().orElseThrow());
}
@Test
@DisplayName("should accept the --val flag the launcher script passes through")
void shouldAcceptLauncherFlag() throws ParseException {
// The mvn script selects the tool with --val but does not remove the flag, so the
// whole argument list, --val included, reaches this parser.
CommonsCliValidateOptions options = CommonsCliValidateOptions.parse(new String[] {"--val", "a/pom.xml"});
assertEquals(
List.of("a/pom.xml"),
options.poms().orElseThrow(),
"--val is the launcher's own flag and must not be taken for a pom");
}
@Test
@DisplayName("should keep poms and format independent")
void shouldKeepPomsAndFormatIndependent() throws ParseException {
CommonsCliValidateOptions options =
CommonsCliValidateOptions.parse(new String[] {"--format", "text", "only/pom.xml"});
assertEquals("text", options.format().orElseThrow());
assertEquals(List.of("only/pom.xml"), options.poms().orElseThrow());
}
@Test
@DisplayName("should not offer goals or phases in the usage line")
void shouldNotOfferGoalsInUsage() throws ParseException {
List<String> help = new ArrayList<>();
CommonsCliValidateOptions.parse(new String[] {"--help"})
.displayHelp(
ParserRequest.mvnval(new String[0], new JLineMessageBuilderFactory())
.build(),
help::add);
String usage =
help.stream().filter(l -> l.contains("usage:")).findFirst().orElseThrow();
assertTrue(usage.contains("<pom>"), "mvnval takes POM files: " + usage);
assertFalse(usage.contains("goal"), "mvnval runs no goals or phases: " + usage);
}
@Test
@DisplayName("should take a value for --mode without swallowing the pom")
void shouldTakeModeValue() throws ParseException {
CommonsCliValidateOptions options = CommonsCliValidateOptions.parse(new String[] {"--mode", "raw", "pom.xml"});
assertEquals("raw", options.mode().orElseThrow());
assertEquals(List.of("pom.xml"), options.poms().orElseThrow(), "the value must not swallow the pom");
}
@Test
@DisplayName("should take the local repository path")
void shouldTakeLocalRepositoryPath() throws ParseException {
CommonsCliValidateOptions options =
CommonsCliValidateOptions.parse(new String[] {"--local-repository", "/tmp/repo", "pom.xml"});
assertEquals("/tmp/repo", options.localRepository().orElseThrow());
assertEquals(List.of("pom.xml"), options.poms().orElseThrow(), "the value must not swallow the pom");
assertTrue(options.tempLocalRepository().isEmpty(), "the two options are separate");
}
@Test
@DisplayName("should take the throwaway local repository as a flag with no value")
void shouldTakeTempLocalRepository() throws ParseException {
CommonsCliValidateOptions options =
CommonsCliValidateOptions.parse(new String[] {"--temp-local-repository", "pom.xml"});
assertEquals(true, options.tempLocalRepository().orElseThrow());
assertEquals(List.of("pom.xml"), options.poms().orElseThrow(), "the flag takes no argument");
}
@Test
@DisplayName("should fold the deprecated -gs into the installation settings")
void shouldFoldDeprecatedGlobalSettings() throws ParseException {
// The parser accepts both spellings for one option, which is why the refusal message
// names both: someone who typed -gs would not recognise --install-settings.
CommonsCliValidateOptions options =
CommonsCliValidateOptions.parse(new String[] {"-gs", "settings.xml", "pom.xml"});
assertEquals("settings.xml", options.altInstallationSettings().orElseThrow());
}
@Test
@DisplayName("should leave the mode empty when it is not given")
void shouldLeaveModeEmptyWhenNotGiven() throws ParseException {
CommonsCliValidateOptions options = CommonsCliValidateOptions.parse(new String[] {"pom.xml"});
assertTrue(options.mode().isEmpty(), "empty, not a default, so the invoker decides what the default is");
}
@Test
@DisplayName("should take a context size from -C")
void shouldTakeContextShortOption() throws ParseException {
CommonsCliValidateOptions options = CommonsCliValidateOptions.parse(new String[] {"-C", "5", "pom.xml"});
assertEquals(5, options.context().orElseThrow());
assertEquals(List.of("pom.xml"), options.poms().orElseThrow(), "the value must not swallow the pom");
}
@Test
@DisplayName("should take a context size from --context")
void shouldTakeContextLongOption() throws ParseException {
CommonsCliValidateOptions options = CommonsCliValidateOptions.parse(new String[] {"--context", "0", "pom.xml"});
assertEquals(0, options.context().orElseThrow());
}
@Test
@DisplayName("should leave context empty when not given")
void shouldLeaveContextEmptyWhenNotGiven() throws ParseException {
CommonsCliValidateOptions options = CommonsCliValidateOptions.parse(new String[] {"pom.xml"});
assertTrue(options.context().isEmpty(), "empty, not a default, so the invoker decides what the default is");
}
}