/*
* Copyright 2015-2017 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.junit.platform.console.options;
import static java.util.Arrays.asList;
import static java.util.Arrays.stream;
import static java.util.Collections.emptyList;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertAll;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.junit.platform.engine.discovery.ClassNameFilter.STANDARD_INCLUDE_PATTERN;
import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Optional;
import java.util.function.Predicate;
import org.junit.jupiter.api.Test;
import org.junit.platform.commons.JUnitException;
/**
* @since 1.0
*/
class JOptSimpleCommandLineOptionsParserTests {
@Test
void parseNoArguments() {
String[] noArguments = {};
CommandLineOptions options = createParser().parse(noArguments);
// @formatter:off
assertAll(
() -> assertFalse(options.isAnsiColorOutputDisabled()),
() -> assertFalse(options.isDisplayHelp()),
() -> assertEquals(CommandLineOptions.DEFAULT_DETAILS, options.getDetails()),
() -> assertFalse(options.isScanClasspath()),
() -> assertEquals(singletonList(STANDARD_INCLUDE_PATTERN), options.getIncludedClassNamePatterns()),
() -> assertEquals(emptyList(), options.getExcludedClassNamePatterns()),
() -> assertEquals(emptyList(), options.getIncludedPackages()),
() -> assertEquals(emptyList(), options.getExcludedPackages()),
() -> assertEquals(emptyList(), options.getIncludedTags()),
() -> assertEquals(emptyList(), options.getExcludedTags()),
() -> assertEquals(emptyList(), options.getAdditionalClasspathEntries()),
() -> assertEquals(Optional.empty(), options.getReportsDir()),
() -> assertEquals(emptyList(), options.getSelectedUris()),
() -> assertEquals(emptyList(), options.getSelectedFiles()),
() -> assertEquals(emptyList(), options.getSelectedDirectories()),
() -> assertEquals(emptyList(), options.getSelectedClasspathEntries())
);
// @formatter:on
}
@Test
void parseSwitches() {
// @formatter:off
assertAll(
() -> assertParses("disable ansi", CommandLineOptions::isAnsiColorOutputDisabled, "--disable-ansi-colors"),
() -> assertParses("help", CommandLineOptions::isDisplayHelp, "-h", "--help"),
() -> assertParses("scan class path", CommandLineOptions::isScanClasspath, "--scan-class-path")
);
// @formatter:on
}
@Test
void parseValidDetails() {
// @formatter:off
assertAll(
() -> assertEquals(Details.VERBOSE, parseArgLine("--details verbose").getDetails()),
() -> assertEquals(Details.TREE, parseArgLine("--details tree").getDetails()),
() -> assertEquals(Details.FLAT, parseArgLine("--details flat").getDetails()),
() -> assertEquals(Details.NONE, parseArgLine("--details NONE").getDetails()),
() -> assertEquals(Details.NONE, parseArgLine("--details none").getDetails()),
() -> assertEquals(Details.NONE, parseArgLine("--details None").getDetails())
);
// @formatter:on
}
@Test
void parseInvalidDetails() throws Exception {
assertOptionWithMissingRequiredArgumentThrowsException("--details");
}
@Test
void parseValidDetailsTheme() {
// @formatter:off
assertAll(
() -> assertEquals(Theme.ASCII, parseArgLine("--details-theme ascii").getTheme()),
() -> assertEquals(Theme.ASCII, parseArgLine("--details-theme ASCII").getTheme()),
() -> assertEquals(Theme.UNICODE, parseArgLine("--details-theme unicode").getTheme()),
() -> assertEquals(Theme.UNICODE, parseArgLine("--details-theme UNICODE").getTheme()),
() -> assertEquals(Theme.UNICODE, parseArgLine("--details-theme uniCode").getTheme())
);
// @formatter:on
}
@Test
void parseInvalidDetailsTheme() throws Exception {
assertOptionWithMissingRequiredArgumentThrowsException("--details-theme");
}
@Test
void parseValidIncludeClassNamePatterns() {
// @formatter:off
assertAll(
() -> assertEquals(singletonList(".*Test"), parseArgLine("-n .*Test").getIncludedClassNamePatterns()),
() -> assertEquals(asList(".*Test", ".*Tests"), parseArgLine("--include-classname .*Test --include-classname .*Tests").getIncludedClassNamePatterns()),
() -> assertEquals(singletonList(".*Test"), parseArgLine("--include-classname=.*Test").getIncludedClassNamePatterns())
);
// @formatter:on
}
@Test
void parseValidExcludeClassNamePatterns() {
// @formatter:off
assertAll(
() -> assertEquals(singletonList(".*Test"), parseArgLine("-N .*Test").getExcludedClassNamePatterns()),
() -> assertEquals(asList(".*Test", ".*Tests"), parseArgLine("--exclude-classname .*Test --exclude-classname .*Tests").getExcludedClassNamePatterns()),
() -> assertEquals(singletonList(".*Test"), parseArgLine("--exclude-classname=.*Test").getExcludedClassNamePatterns())
);
// @formatter:on
}
@Test
void usesDefaultClassNamePatternWithoutExplicitArgument() {
assertEquals(singletonList(STANDARD_INCLUDE_PATTERN), parseArgLine("").getIncludedClassNamePatterns());
}
@Test
void parseInvalidIncludeClassNamePatterns() throws Exception {
assertOptionWithMissingRequiredArgumentThrowsException("-n", "--include-classname");
}
@Test
void parseInvalidExcludeClassNamePatterns() throws Exception {
assertOptionWithMissingRequiredArgumentThrowsException("-N", "--exclude-classname");
}
@Test
void parseValidIncludedPackages() {
// @formatter:off
assertAll(
() -> assertEquals(asList("org.junit.included"),
parseArgLine("--include-package org.junit.included").getIncludedPackages()),
() -> assertEquals(asList("org.junit.included"),
parseArgLine("--include-package=org.junit.included").getIncludedPackages()),
() -> assertEquals(asList("org.junit.included1", "org.junit.included2"),
parseArgLine("--include-package org.junit.included1 --include-package org.junit.included2").getIncludedPackages())
);
// @formatter:on
}
@Test
void parseValidExcludedPackages() {
// @formatter:off
assertAll(
() -> assertEquals(asList("org.junit.excluded"),
parseArgLine("--exclude-package org.junit.excluded").getExcludedPackages()),
() -> assertEquals(asList("org.junit.excluded"),
parseArgLine("--exclude-package=org.junit.excluded").getExcludedPackages()),
() -> assertEquals(asList("org.junit.excluded1", "org.junit.excluded2"),
parseArgLine("--exclude-package org.junit.excluded1 --exclude-package org.junit.excluded2").getExcludedPackages())
);
// @formatter:on
}
@Test
void parseValidIncludedTags() {
// @formatter:off
assertAll(
() -> assertEquals(asList("fast"), parseArgLine("-t fast").getIncludedTags()),
() -> assertEquals(asList("fast"), parseArgLine("--include-tag fast").getIncludedTags()),
() -> assertEquals(asList("fast"), parseArgLine("--include-tag=fast").getIncludedTags()),
() -> assertEquals(asList("fast", "slow"), parseArgLine("-t fast -t slow").getIncludedTags())
);
// @formatter:on
}
@Test
void parseInvalidIncludedTags() {
assertOptionWithMissingRequiredArgumentThrowsException("-t", "--include-tag");
}
@Test
void parseValidExcludedTags() {
// @formatter:off
assertAll(
() -> assertEquals(asList("fast"), parseArgLine("-T fast").getExcludedTags()),
() -> assertEquals(asList("fast"), parseArgLine("--exclude-tag fast").getExcludedTags()),
() -> assertEquals(asList("fast"), parseArgLine("--exclude-tag=fast").getExcludedTags()),
() -> assertEquals(asList("fast", "slow"), parseArgLine("-T fast -T slow").getExcludedTags())
);
// @formatter:on
}
@Test
void parseInvalidExcludedTags() {
assertOptionWithMissingRequiredArgumentThrowsException("-T", "--exclude-tag");
}
@Test
void parseValidIncludedEngines() {
// @formatter:off
assertAll(
() -> assertEquals(asList("junit-jupiter"), parseArgLine("-e junit-jupiter").getIncludedEngines()),
() -> assertEquals(asList("junit-vintage"), parseArgLine("--include-engine junit-vintage").getIncludedEngines()),
() -> assertEquals(emptyList(), parseArgLine("").getIncludedEngines())
);
// @formatter:on
}
@Test
void parseInvalidIncludedEngines() throws Exception {
assertOptionWithMissingRequiredArgumentThrowsException("-e", "--include-engine");
}
@Test
void parseValidExcludedEngines() {
// @formatter:off
assertAll(
() -> assertEquals(asList("junit-jupiter"), parseArgLine("-E junit-jupiter").getExcludedEngines()),
() -> assertEquals(asList("junit-vintage"), parseArgLine("--exclude-engine junit-vintage").getExcludedEngines()),
() -> assertEquals(emptyList(), parseArgLine("").getExcludedEngines())
);
// @formatter:on
}
@Test
void parseInvalidExcludedEngines() throws Exception {
assertOptionWithMissingRequiredArgumentThrowsException("-E", "--exclude-engine");
}
@Test
void parseValidAdditionalClasspathEntries() {
Path dir = Paths.get(".");
// @formatter:off
assertAll(
() -> assertEquals(singletonList(dir), parseArgLine("-cp .").getAdditionalClasspathEntries()),
() -> assertEquals(singletonList(dir), parseArgLine("--cp .").getAdditionalClasspathEntries()),
() -> assertEquals(singletonList(dir), parseArgLine("-classpath .").getAdditionalClasspathEntries()),
() -> assertEquals(singletonList(dir), parseArgLine("-classpath=.").getAdditionalClasspathEntries()),
() -> assertEquals(singletonList(dir), parseArgLine("--classpath .").getAdditionalClasspathEntries()),
() -> assertEquals(singletonList(dir), parseArgLine("--classpath=.").getAdditionalClasspathEntries()),
() -> assertEquals(singletonList(dir), parseArgLine("--class-path .").getAdditionalClasspathEntries()),
() -> assertEquals(singletonList(dir), parseArgLine("--class-path=.").getAdditionalClasspathEntries()),
() -> assertEquals(asList(dir, Paths.get("src", "test", "java")), parseArgLine("-cp . -cp src/test/java").getAdditionalClasspathEntries()),
() -> assertEquals(asList(dir, Paths.get("src", "test", "java")), parseArgLine("-cp ." + File.pathSeparator + "src/test/java").getAdditionalClasspathEntries())
);
// @formatter:on
}
@Test
void parseInvalidAdditionalClasspathEntries() {
assertOptionWithMissingRequiredArgumentThrowsException("-cp", "--classpath", "--class-path");
}
@Test
void parseValidXmlReportsDirs() {
Path dir = Paths.get("build", "test-results");
// @formatter:off
assertAll(
() -> assertEquals(Optional.of(dir), parseArgLine("--reports-dir build/test-results").getReportsDir()),
() -> assertEquals(Optional.of(dir), parseArgLine("--reports-dir=build/test-results").getReportsDir())
);
// @formatter:on
}
@Test
void parseInvalidXmlReportsDirs() throws Exception {
assertOptionWithMissingRequiredArgumentThrowsException("--reports-dir");
}
@Test
void parseValidUriSelectors() {
// @formatter:off
assertAll(
() -> assertEquals(singletonList(new URI("file:///foo.txt")), parseArgLine("-u file:///foo.txt").getSelectedUris()),
() -> assertEquals(singletonList(new URI("file:///foo.txt")), parseArgLine("--u file:///foo.txt").getSelectedUris()),
() -> assertEquals(singletonList(new URI("file:///foo.txt")), parseArgLine("-select-uri file:///foo.txt").getSelectedUris()),
() -> assertEquals(singletonList(new URI("file:///foo.txt")), parseArgLine("-select-uri=file:///foo.txt").getSelectedUris()),
() -> assertEquals(singletonList(new URI("file:///foo.txt")), parseArgLine("--select-uri file:///foo.txt").getSelectedUris()),
() -> assertEquals(singletonList(new URI("file:///foo.txt")), parseArgLine("--select-uri=file:///foo.txt").getSelectedUris()),
() -> assertEquals(asList(new URI("file:///foo.txt"), new URI("http://localhost")), parseArgLine("-u file:///foo.txt -u http://localhost").getSelectedUris())
);
// @formatter:on
}
@Test
void parseInvalidUriSelectors() {
assertOptionWithMissingRequiredArgumentThrowsException("-u", "--select-uri", "-u unknown-scheme:");
}
@Test
void parseValidFileSelectors() {
// @formatter:off
assertAll(
() -> assertEquals(singletonList("foo.txt"), parseArgLine("-f foo.txt").getSelectedFiles()),
() -> assertEquals(singletonList("foo.txt"), parseArgLine("--f foo.txt").getSelectedFiles()),
() -> assertEquals(singletonList("foo.txt"), parseArgLine("-select-file foo.txt").getSelectedFiles()),
() -> assertEquals(singletonList("foo.txt"), parseArgLine("-select-file=foo.txt").getSelectedFiles()),
() -> assertEquals(singletonList("foo.txt"), parseArgLine("--select-file foo.txt").getSelectedFiles()),
() -> assertEquals(singletonList("foo.txt"), parseArgLine("--select-file=foo.txt").getSelectedFiles()),
() -> assertEquals(asList("foo.txt", "bar.csv"), parseArgLine("-f foo.txt -f bar.csv").getSelectedFiles())
);
// @formatter:on
}
@Test
void parseInvalidFileSelectors() {
assertOptionWithMissingRequiredArgumentThrowsException("-f", "--select-file");
}
@Test
void parseValidDirectorySelectors() {
// @formatter:off
assertAll(
() -> assertEquals(singletonList("foo/bar"), parseArgLine("-d foo/bar").getSelectedDirectories()),
() -> assertEquals(singletonList("foo/bar"), parseArgLine("--d foo/bar").getSelectedDirectories()),
() -> assertEquals(singletonList("foo/bar"), parseArgLine("-select-directory foo/bar").getSelectedDirectories()),
() -> assertEquals(singletonList("foo/bar"), parseArgLine("-select-directory=foo/bar").getSelectedDirectories()),
() -> assertEquals(singletonList("foo/bar"), parseArgLine("--select-directory foo/bar").getSelectedDirectories()),
() -> assertEquals(singletonList("foo/bar"), parseArgLine("--select-directory=foo/bar").getSelectedDirectories()),
() -> assertEquals(asList("foo/bar", "bar/qux"), parseArgLine("-d foo/bar -d bar/qux").getSelectedDirectories())
);
// @formatter:on
}
@Test
void parseInvalidDirectorySelectors() {
assertOptionWithMissingRequiredArgumentThrowsException("-d", "--select-directory");
}
@Test
void parseValidPackageSelectors() {
// @formatter:off
assertAll(
() -> assertEquals(singletonList("com.acme.foo"), parseArgLine("-p com.acme.foo").getSelectedPackages()),
() -> assertEquals(singletonList("com.acme.foo"), parseArgLine("--p com.acme.foo").getSelectedPackages()),
() -> assertEquals(singletonList("com.acme.foo"), parseArgLine("-select-package com.acme.foo").getSelectedPackages()),
() -> assertEquals(singletonList("com.acme.foo"), parseArgLine("-select-package=com.acme.foo").getSelectedPackages()),
() -> assertEquals(singletonList("com.acme.foo"), parseArgLine("--select-package com.acme.foo").getSelectedPackages()),
() -> assertEquals(singletonList("com.acme.foo"), parseArgLine("--select-package=com.acme.foo").getSelectedPackages()),
() -> assertEquals(asList("com.acme.foo", "com.example.bar"), parseArgLine("-p com.acme.foo -p com.example.bar").getSelectedPackages())
);
// @formatter:on
}
@Test
void parseInvalidPackageSelectors() {
assertOptionWithMissingRequiredArgumentThrowsException("-p", "--select-package");
}
@Test
void parseValidClassSelectors() {
// @formatter:off
assertAll(
() -> assertEquals(singletonList("com.acme.Foo"), parseArgLine("-c com.acme.Foo").getSelectedClasses()),
() -> assertEquals(singletonList("com.acme.Foo"), parseArgLine("--c com.acme.Foo").getSelectedClasses()),
() -> assertEquals(singletonList("com.acme.Foo"), parseArgLine("-select-class com.acme.Foo").getSelectedClasses()),
() -> assertEquals(singletonList("com.acme.Foo"), parseArgLine("-select-class=com.acme.Foo").getSelectedClasses()),
() -> assertEquals(singletonList("com.acme.Foo"), parseArgLine("--select-class com.acme.Foo").getSelectedClasses()),
() -> assertEquals(singletonList("com.acme.Foo"), parseArgLine("--select-class=com.acme.Foo").getSelectedClasses()),
() -> assertEquals(asList("com.acme.Foo", "com.example.Bar"), parseArgLine("-c com.acme.Foo -c com.example.Bar").getSelectedClasses())
);
// @formatter:on
}
@Test
void parseInvalidClassSelectors() {
assertOptionWithMissingRequiredArgumentThrowsException("-c", "--select-class");
}
@Test
void parseValidMethodSelectors() {
// @formatter:off
assertAll(
() -> assertEquals(singletonList("com.acme.Foo#m()"), parseArgLine("-m com.acme.Foo#m()").getSelectedMethods()),
() -> assertEquals(singletonList("com.acme.Foo#m()"), parseArgLine("--m com.acme.Foo#m()").getSelectedMethods()),
() -> assertEquals(singletonList("com.acme.Foo#m()"), parseArgLine("-select-method com.acme.Foo#m()").getSelectedMethods()),
() -> assertEquals(singletonList("com.acme.Foo#m()"), parseArgLine("-select-method=com.acme.Foo#m()").getSelectedMethods()),
() -> assertEquals(singletonList("com.acme.Foo#m()"), parseArgLine("--select-method com.acme.Foo#m()").getSelectedMethods()),
() -> assertEquals(singletonList("com.acme.Foo#m()"), parseArgLine("--select-method=com.acme.Foo#m()").getSelectedMethods()),
() -> assertEquals(asList("com.acme.Foo#m()", "com.example.Bar#method(java.lang.Object)"),
parseArgLine("-m com.acme.Foo#m() -m com.example.Bar#method(java.lang.Object)").getSelectedMethods())
);
// @formatter:on
}
@Test
void parseInvalidMethodSelectors() {
assertOptionWithMissingRequiredArgumentThrowsException("-m", "--select-method");
}
@Test
void parseValidClasspathResourceSelectors() {
// @formatter:off
assertAll(
() -> assertEquals(singletonList("/foo.csv"), parseArgLine("-r /foo.csv").getSelectedClasspathResources()),
() -> assertEquals(singletonList("/foo.csv"), parseArgLine("--r /foo.csv").getSelectedClasspathResources()),
() -> assertEquals(singletonList("/foo.csv"), parseArgLine("-select-resource /foo.csv").getSelectedClasspathResources()),
() -> assertEquals(singletonList("/foo.csv"), parseArgLine("-select-resource=/foo.csv").getSelectedClasspathResources()),
() -> assertEquals(singletonList("/foo.csv"), parseArgLine("--select-resource /foo.csv").getSelectedClasspathResources()),
() -> assertEquals(singletonList("/foo.csv"), parseArgLine("--select-resource=/foo.csv").getSelectedClasspathResources()),
() -> assertEquals(asList("/foo.csv", "bar.json"), parseArgLine("-r /foo.csv -r bar.json").getSelectedClasspathResources())
);
// @formatter:on
}
@Test
void parseInvalidClasspathResourceSelectors() {
assertOptionWithMissingRequiredArgumentThrowsException("-r", "--select-resource");
}
@Test
void parseClasspathScanningEntries() {
Path dir = Paths.get(".");
// @formatter:off
assertAll(
() -> assertTrue(parseArgLine("--scan-class-path").isScanClasspath()),
() -> assertEquals(emptyList(), parseArgLine("--scan-class-path").getSelectedClasspathEntries()),
() -> assertTrue(parseArgLine("--scan-classpath").isScanClasspath()),
() -> assertEquals(emptyList(), parseArgLine("--scan-classpath").getSelectedClasspathEntries()),
() -> assertTrue(parseArgLine("--scan-class-path .").isScanClasspath()),
() -> assertEquals(singletonList(dir), parseArgLine("--scan-class-path .").getSelectedClasspathEntries()),
() -> assertEquals(singletonList(dir), parseArgLine("--scan-class-path=.").getSelectedClasspathEntries()),
() -> assertEquals(singletonList(dir), parseArgLine("-scan-class-path .").getSelectedClasspathEntries()),
() -> assertEquals(singletonList(dir), parseArgLine("-scan-class-path=.").getSelectedClasspathEntries()),
() -> assertEquals(asList(dir, Paths.get("src/test/java")), parseArgLine("--scan-class-path . --scan-class-path src/test/java").getSelectedClasspathEntries()),
() -> assertEquals(asList(dir, Paths.get("src/test/java")), parseArgLine("--scan-class-path ." + File.pathSeparator + "src/test/java").getSelectedClasspathEntries())
);
// @formatter:on
}
@Test
void printHelpOutputsHelpOption() {
StringWriter writer = new StringWriter();
createParser().printHelp(writer);
assertThat(writer.toString()).contains("--help");
}
@Test
void printHelpPreservesOriginalIOException() {
Writer writer = new Writer() {
@Override
public void write(char[] cbuf, int off, int len) throws IOException {
throw new IOException("Something went wrong");
}
@Override
public void flush() {
}
@Override
public void close() {
}
};
CommandLineOptionsParser parser = createParser();
RuntimeException exception = assertThrows(RuntimeException.class, () -> parser.printHelp(writer));
assertThat(exception).hasCauseInstanceOf(IOException.class);
assertThat(exception.getCause()).hasMessage("Something went wrong");
}
private void assertOptionWithMissingRequiredArgumentThrowsException(String... options) {
assertAll(stream(options).map(opt -> () -> assertThrows(JUnitException.class, () -> parseArgLine(opt))));
}
private void assertParses(String name, Predicate<CommandLineOptions> property, String... argLines) {
stream(argLines).forEach(argLine -> {
CommandLineOptions options = parseArgLine(argLine);
assertTrue(property.test(options), () -> name + " should be enabled by: " + argLine);
});
}
private CommandLineOptions parseArgLine(String argLine) {
String[] arguments = argLine.split("\\s+");
return createParser().parse(arguments);
}
private CommandLineOptionsParser createParser() {
return new JOptSimpleCommandLineOptionsParser();
}
}