diff --git a/apache-rat-core/src/it/java/org/apache/rat/ReportTest.java b/apache-rat-core/src/it/java/org/apache/rat/ReportTest.java index b695134a6..7f51935fb 100644 --- a/apache-rat-core/src/it/java/org/apache/rat/ReportTest.java +++ b/apache-rat-core/src/it/java/org/apache/rat/ReportTest.java @@ -80,15 +80,27 @@ * associated with the exception. * */ -public class ReportTest { +class ReportTest { + /** + * Converts an argument lists to an argument array + * @param argsList the list to convert + * @return the array of arguments. + */ private String[] asArgs(final List argsList) { return argsList.toArray(new String[0]); } + /** + * Runs the commands specified by the `commandLine.txt` file in the resources/ReportTest/* directories + * and validate the results using the {@code verify.groovy} dfile in the test directory. + * @param testName the name of the test based on the directory the test was found in. + * @param commandLineDoc the Doucment that is the command line. + * @throws Exception on execution error. + */ @ParameterizedTest(name = "{index} {0}") - @MethodSource("args") - public void integrationTest(String testName, Document commandLineDoc) throws Exception { + @MethodSource("integrationTestData") + void integrationTest(String testName, Document commandLineDoc) throws Exception { DefaultLog.getInstance().log(Log.Level.INFO, "Running test for " + testName); File baseDir = new File(commandLineDoc.getName().getName()).getParentFile(); @@ -119,9 +131,11 @@ public void integrationTest(String testName, Document commandLineDoc) throws Exc File expectedMsg = new File(baseDir, "expected-message.txt"); if (expectedMsg.exists()) { - String msg = IOUtils.readLines(new FileReader(expectedMsg)).get(0).trim(); - assertThrows(RatDocumentAnalysisException.class, () -> Report.main(asArgs(argsList)), - msg); + try (FileReader fr = new FileReader(expectedMsg)) { + String msg = IOUtils.readLines(fr).get(0).trim(); + assertThrows(RatDocumentAnalysisException.class, () -> Report.main(asArgs(argsList)), + msg); + } } else { Report.main(asArgs(argsList)); } @@ -142,7 +156,7 @@ public void integrationTest(String testName, Document commandLineDoc) throws Exc try { Object value = shell.run(groovyScript, new String[]{outputFile.getAbsolutePath(), logFile.getAbsolutePath()}); if (value != null) { - fail(String.format("%s", value)); + fail(String.format("%s: %s", testName, value)); } } catch (AssertionError e) { throw new AssertionError(String.format("%s: %s", testName, e.getMessage()), e); @@ -150,7 +164,13 @@ public void integrationTest(String testName, Document commandLineDoc) throws Exc } } - static Stream args() throws RatException { + /** + * Reads each directory under the ReportTest director in the test resources and creates a test from it + * The {@code commandLine.txt} file is parsed to create the command lien to execute the tests. + * @return a stream of arguments for each test case. + * @throws RatException on parsing error. + */ + static Stream integrationTestData() throws RatException { List results = new ArrayList<>(); URL url = ReportTest.class.getResource("/ReportTest"); @@ -170,11 +190,11 @@ static Stream args() throws RatException { DirectoryWalker walker = new DirectoryWalker(document); RatReport report = new RatReport() { @Override - public void report(Document document) { - if (!document.isIgnored()) { - String[] tokens = DocumentName.FSInfo.getDefault().tokenize(document.getName().localized()); - results.add(Arguments.of(tokens[1], document)); - } + public void report(Document document) { + if (!document.isIgnored()) { + String[] tokens = DocumentName.FSInfo.getDefault().tokenize(document.getName().localized()); + results.add(Arguments.of(tokens[1], document)); + } } }; walker.run(report); @@ -185,7 +205,7 @@ public void report(Document document) { * Log that captures output for later review. */ public static class FileLog implements Log { - + /** the output from the log */ private final PrintStream logFile; /** @@ -193,17 +213,17 @@ public static class FileLog implements Log { */ private Level level; + /** + * Constructor. + * @param logFile the file to write to. + * @throws IOException on Error. + */ FileLog(File logFile) throws IOException { this.logFile = new PrintStream(logFile); level = Level.INFO; } - /** - * Sets the level.Log messages below the specified level will - * not be written to the log. - * - * @param level the level to use when writing messages. - */ + @Override public void setLevel(final Level level) { this.level = level; } @@ -220,6 +240,9 @@ public void log(Level level, String msg) { } } + /** + * Closes the log file. + */ public void close() { logFile.close(); } diff --git a/apache-rat-core/src/it/resources/ReportTest/RAT_406/commandLine.txt b/apache-rat-core/src/it/resources/ReportTest/RAT_406/commandLine.txt index 0d6433f57..cec3b5e30 100644 --- a/apache-rat-core/src/it/resources/ReportTest/RAT_406/commandLine.txt +++ b/apache-rat-core/src/it/resources/ReportTest/RAT_406/commandLine.txt @@ -1,2 +1,3 @@ --licenses-denied DOJO +-- diff --git a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java index a17077e8c..f92f4536b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java +++ b/apache-rat-core/src/main/java/org/apache/rat/ReportConfiguration.java @@ -104,6 +104,10 @@ public enum Processing { */ private final String description; + /** + * Constructor. + * @param description the description for this processing strategy + */ Processing(final String description) { this.description = description; } @@ -139,7 +143,7 @@ public String desc() { /** * The IODescriptor that provides the output stream to write the report to. */ - private IODescriptor out; + private IODescriptor outputDescriptor; /** * The IODescriptor that provides the stylesheet to style the XML output. @@ -205,6 +209,10 @@ public ReportConfiguration() { reportables = new ArrayList<>(); } + /** + * A serializer/deserializer for a ReportConfiguration. + * @return the serializer/deserializer for a ReportConfiguration. + */ public SerDes serDes() { return new SerDes(); } @@ -227,14 +235,21 @@ public void reportExclusions(final Appendable appendable) { * File within the file must be in linux format with a * {@code "/"} file separator. * @param file the file to process. + * @throws ConfigurationException if the file is null. */ public void addSource(final File file) { notNull(file, "File may not be null."); sources.add(file); } - private void notNull(final Object o, final String msg) { - if (o == null) { + /** + * Throws ConfigurationException if the object is null. + * @param object the object to test. + * @param msg the message to create the exception with. + * @throws ConfigurationException if the object is null. + */ + private void notNull(final Object object, final String msg) { + if (object == null) { throw new ConfigurationException(msg); } } @@ -242,6 +257,7 @@ private void notNull(final Object o, final String msg) { /** * Adds a Reportable as a source of files to scan. * @param reportable the reportable to process. + * @throws ConfigurationException if the reportable is null. */ public void addSource(final Reportable reportable) { notNull(reportable, "Reportable may not be null."); @@ -257,8 +273,8 @@ public boolean hasSource() { } /** - * Gets a builder initialized with any files specified as sources. - * @return a configured builder. + * Gets a ReportListWalker.Builder initialized with any files specified as sources. + * @return a configured ReportListWalker.Builder. */ public ReportableListWalker.Builder getSources() { DocumentName name = DocumentName.builder(new File(".")).build(); @@ -527,7 +543,7 @@ public void setStyleSheet(final IODescriptor styleSheet) { */ public void setFrom(final Defaults defaults) { licenseSetFactory.add(defaults.getLicenseSetFactory()); - if (getStyleSheet() == null) { + if (getStyleSheetDescriptor() == null) { setStyleSheet(StyleSheets.PLAIN.getStyleSheet()); } defaults.getStandardExclusion().forEach(this::addExcludedCollection); @@ -571,22 +587,22 @@ public void setStyleSheet(final URL styleSheet) { * times to provide the stream. Suppliers should prepare streams that are * appended to and that can be closed. If an {@code OutputStream} should not be * closed consider wrapping it in a {@code CloseShieldOutputStream} - * @param out the OutputStream supplier that provides the output stream to write + * @param outputDescriptor the OutputStream supplier that provides the output stream to write * the report to. A {@code null} value will use {@code System.out}. * @see CloseShieldOutputStream */ - public void setOut(final IODescriptor out) { - this.out = out; + public void setOutput(final IODescriptor outputDescriptor) { + this.outputDescriptor = outputDescriptor; } /** * Sets the OutputStream supplier to use the specified file. The file may be * opened and closed several times. File is deleted first and then may be * repeatedly opened in append mode. - * @see #setOut(IODescriptor) + * @see #setOutput(IODescriptor) * @param file The file to create the supplier with. */ - public void setOut(final File file) { + public void setOutput(final File file) { Objects.requireNonNull(file, "output file should not be null"); if (file.exists()) { try { @@ -600,7 +616,7 @@ public void setOut(final File file) { if (!parent.mkdirs() && !parent.isDirectory()) { DefaultLog.getInstance().warn("Unable to create directory: " + file.getParentFile()); } - setOut(IODescriptor.output(file)); + setOutput(IODescriptor.output(file)); } /** @@ -618,7 +634,7 @@ public IOSupplier getOutput() { * @return the IODescriptor of the output stream to write the report to. */ public IODescriptor getOutputDescriptor() { - return out == null ? SYSTEM_OUT : out; + return outputDescriptor == null ? SYSTEM_OUT : outputDescriptor; } /** @@ -982,7 +998,7 @@ public void serialize(final Appendable appendable) throws IOException { .attribute("archiveProcessing", getArchiveProcessing().name()) .attribute("standardProcessing", getStandardProcessing().name()) .attribute("stylesheet", styleSheet.name()) - .attribute("output", out.name()); + .attribute("output", outputDescriptor.name()); if (StringUtils.isNotEmpty(copyrightMessage)) { writer.startElement("copyrightMessage").content(copyrightMessage).closeElement(); } @@ -1015,6 +1031,13 @@ public void serialize(final Appendable appendable) throws IOException { } } + /** + * Reads an input stream as an XML document and parses the report configuration from that. + * Note: The reportable objects (Files) in a deserialized ReportConfigurations are not executable. + * @param inputStreamSupplier The XML document written by {@link #serialize(Appendable)} + * @param workingDirectory the directory to resolve short XSLT and output names from. + * @throws IOException on parse error. + */ public void deserialize(final IOSupplier inputStreamSupplier, final DocumentName workingDirectory) throws IOException { org.w3c.dom.Document document; try (InputStream stream = inputStreamSupplier.get()) { @@ -1036,14 +1059,14 @@ public void deserialize(final IOSupplier inputStreamSupplier, final standardProcessing = Processing.valueOf(attributes.get("standardProcessing")); String styleName = attributes.get("stylesheet"); if (styleName != null) { - styleSheet = StyleSheets.getStyleSheet(styleName); + styleSheet = StyleSheets.getStyleSheet(styleName, workingDirectory); } String outputName = attributes.get("output"); if (outputName != null) { if (outputName.equals(ReportConfiguration.SYSTEM_OUT.name())) { - out = ReportConfiguration.SYSTEM_OUT; + outputDescriptor = ReportConfiguration.SYSTEM_OUT; } else { - out = IODescriptor.output(outputName, workingDirectory); + outputDescriptor = IODescriptor.output(outputName, workingDirectory); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/commandline/Arg.java b/apache-rat-core/src/main/java/org/apache/rat/commandline/Arg.java index d1378f119..96ffa1070 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/commandline/Arg.java +++ b/apache-rat-core/src/main/java/org/apache/rat/commandline/Arg.java @@ -165,7 +165,6 @@ public enum Arg { .build()), (context, selected) -> context.getConfiguration().addApprovedLicenseIds(context.getParsedOptionValue(selected)) - ), /** @@ -515,14 +514,14 @@ public enum Arg { if ("x".equals(key)) { // display deprecated message. context.hasOption("x"); - context.getConfiguration().setStyleSheet(StyleSheets.getStyleSheet("xml")); + context.getConfiguration().setStyleSheet(StyleSheets.getStyleSheet("xml", context.getWorkingDirectory())); } else { List style = context.getOptionValues(selected); if (style.size() != 1) { DefaultLog.getInstance().error("Please specify a single stylesheet"); throw new ConfigurationException("Please specify a single stylesheet"); } - context.getConfiguration().setStyleSheet(StyleSheets.getStyleSheet(style.get(0))); + context.getConfiguration().setStyleSheet(StyleSheets.getStyleSheet(style.get(0), context.getWorkingDirectory())); } }), @@ -597,7 +596,7 @@ public enum Arg { .build()), (context, selected) -> { DocumentName documentName = context.getParsedOptionValue(selected, () -> { - context.getConfiguration().setOut(ReportConfiguration.SYSTEM_OUT); + context.getConfiguration().setOutput(ReportConfiguration.SYSTEM_OUT); return null; }); if (documentName != null) { @@ -606,7 +605,7 @@ public enum Arg { if (!parent.mkdirs() && !parent.isDirectory()) { DefaultLog.getInstance().error("Could not create report parent directory " + documentName); } - context.getConfiguration().setOut(document); + context.getConfiguration().setOutput(document); } }), diff --git a/apache-rat-core/src/main/java/org/apache/rat/commandline/Converters.java b/apache-rat-core/src/main/java/org/apache/rat/commandline/Converters.java index becbbcfcf..7dfdce5ed 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/commandline/Converters.java +++ b/apache-rat-core/src/main/java/org/apache/rat/commandline/Converters.java @@ -117,7 +117,7 @@ public DocumentName apply(final String fileName) throws NullPointerException { } else { builder.setBaseName(workingDirectory); } - return builder.setName(normalizedFileName).build(); + return builder.setName(normalizedFileName).build(); } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/commandline/StyleSheets.java b/apache-rat-core/src/main/java/org/apache/rat/commandline/StyleSheets.java index ea0c11133..d3f6df43e 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/commandline/StyleSheets.java +++ b/apache-rat-core/src/main/java/org/apache/rat/commandline/StyleSheets.java @@ -21,12 +21,11 @@ import java.io.InputStream; import java.net.URL; import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; import java.util.Objects; import org.apache.rat.ConfigurationException; import org.apache.rat.ReportConfiguration; +import org.apache.rat.document.DocumentName; import static java.lang.String.format; @@ -49,8 +48,11 @@ public enum StyleSheets { /** * The pretty-printed XML style sheet. */ - XML("xml", "Produces output in pretty-printed XML."); - + XML("xml", "Produces output in pretty-printed XML."), + /** + * Official HTML5 stylesheet. + */ + XHTML5("xhtml5", "Produces a HTML5 report"); /** * The name of the style sheet. Must map to bundled resource XSLT file */ @@ -73,6 +75,7 @@ public enum StyleSheets { /** * Gets the IODescriptor for a style sheet. * @return an IODescriptor for the sheet. + * @throws NullPointerException if the name can not be resolved. */ public ReportConfiguration.IODescriptor getStyleSheet() { URL url = StyleSheets.class.getClassLoader().getResource(format("org/apache/rat/%s.xsl", name)); @@ -83,18 +86,20 @@ public ReportConfiguration.IODescriptor getStyleSheet() { /** * Gets the IODescriptor for a style sheet. * @param name the short name for or the path to a style sheet. + * @param workingDirectory the working directory to resolve the name against. * @return the IODescriptor for the style sheet. + * @throws ConfigurationException if the filesheet can nto be found. */ - public static ReportConfiguration.IODescriptor getStyleSheet(final String name) { + public static ReportConfiguration.IODescriptor getStyleSheet(final String name, final DocumentName workingDirectory) { URL url = StyleSheets.class.getClassLoader().getResource(format("org/apache/rat/%s.xsl", name)); if (url != null) { return new ReportConfiguration.IODescriptor<>(name, url::openStream); } - Path p = Paths.get(name); - if (p.toFile().exists()) { - return new ReportConfiguration.IODescriptor<>(name, () -> Files.newInputStream(p)); + DocumentName xslt = workingDirectory.resolve(name); + if (xslt.asFile().exists()) { + return new ReportConfiguration.IODescriptor<>(xslt.toString(), () -> Files.newInputStream(xslt.asFile().toPath())); } - throw new ConfigurationException(format("Stylesheet file '%s' not found", name)); + throw new ConfigurationException(format("Stylesheet file '%s' not found: %s", name, xslt.getName())); } /** diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java index d57e21181..ae4ce1ca6 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java @@ -66,7 +66,7 @@ public class ExclusionProcessor { private final Set excludedCollections; /** The last generated PathMatcher */ private DocumentNameMatcher lastMatcher; - /** The base dir for the last PathMatcher */ + /** The base document name for the last PathMatcher */ private DocumentName lastMatcherBaseDir; /** @@ -86,7 +86,7 @@ public SerDes serDes() { return new SerDes(); } - /* the following set of methods are here for testing purposes */ + // the following set of methods are here and visible for testing purposes Set getExcludedPatterns() { return new HashSet<>(excludedPatterns); } @@ -122,6 +122,7 @@ DocumentNameMatcher getLastMatcher() { DocumentName getLastMatcherBaseDir() { return lastMatcherBaseDir; } + // END OF TESTING PURPOSES Methods /** * Reset the {@link #lastMatcher} and {@link #lastMatcherBaseDir} to start again. @@ -138,9 +139,9 @@ private void resetLastMatcher() { */ public ExclusionProcessor addIncludedPatterns(final Iterable patterns) { if (patterns != null) { - DefaultLog.getInstance().debug(format("Including patterns: %s", String.join(", ", patterns))); - patterns.forEach(includedPatterns::add); - resetLastMatcher(); + DefaultLog.getInstance().debug(format("Including patterns: %s", String.join(", ", patterns))); + patterns.forEach(includedPatterns::add); + resetLastMatcher(); } return this; } @@ -193,9 +194,9 @@ public ExclusionProcessor addIncludedCollection(final StandardCollection collect */ public ExclusionProcessor addExcludedPatterns(final Iterable patterns) { if (patterns != null) { - DefaultLog.getInstance().debug(format("Excluding patterns: %s", String.join(", ", patterns))); - patterns.forEach(excludedPatterns::add); - resetLastMatcher(); + DefaultLog.getInstance().debug(format("Excluding patterns: %s", String.join(", ", patterns))); + patterns.forEach(excludedPatterns::add); + resetLastMatcher(); } return this; } diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryDocument.java b/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryDocument.java deleted file mode 100644 index dabc848bc..000000000 --- a/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryDocument.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.rat.document; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.Collections; -import java.util.SortedSet; - -import org.apache.rat.api.Document; - -/** - * A Document that wraps an Archive entry. - */ -public class ArchiveEntryDocument extends Document { - - /** The contents of the entry */ - private final byte[] contents; - - /** - * Creates an Archive entry. - * @param entryName the name of this entry from outside the archive. - * @param contents the contents of the entry. - * @param nameMatcher the name matcher to filter contents with. - */ - public ArchiveEntryDocument(final ArchiveEntryName entryName, final byte[] contents, final DocumentNameMatcher nameMatcher) { - super(entryName, nameMatcher); - this.contents = contents; - } - - @Override - public InputStream inputStream() { - return new ByteArrayInputStream(contents); - } - - @Override - public boolean isDirectory() { - return false; - } - - @Override - public SortedSet listChildren() { - return Collections.emptySortedSet(); - } -} diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/FileUtils.java b/apache-rat-core/src/main/java/org/apache/rat/utils/FileUtils.java similarity index 74% rename from apache-rat-core/src/test/java/org/apache/rat/testhelpers/FileUtils.java rename to apache-rat-core/src/main/java/org/apache/rat/utils/FileUtils.java index 5681e7972..a06b305a9 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/FileUtils.java +++ b/apache-rat-core/src/main/java/org/apache/rat/utils/FileUtils.java @@ -16,24 +16,29 @@ * specific language governing permissions and limitations * * under the License. * */ -package org.apache.rat.testhelpers; +package org.apache.rat.utils; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.PrintWriter; +import java.nio.file.Files; import java.util.Arrays; import java.util.Collections; -import static org.assertj.core.api.Fail.fail; - -public class FileUtils { +/** + * A set of utilities to help process files. + */ +public final class FileUtils { + private FileUtils() { + // do not instantiate + } /** * Creates a directory if it does not exist. * @param dir the directory to make. */ - public static void mkDir(File dir) { + public static void mkDir(final File dir) { boolean ignored = dir.mkdirs(); } @@ -41,17 +46,18 @@ public static void mkDir(File dir) { * Deletes a file if it exists. * @param file the file to delete. */ - public static void delete(File file) { + public static void delete(final File file) { if (file.exists()) { - if (file.isDirectory()) { - try { + try { + if (file.isDirectory()) { org.apache.commons.io.FileUtils.deleteDirectory(file); - } catch (IOException ignore) { - // + } else { + Files.delete(file.toPath()); } - } else { - boolean ignored = file.delete(); + } catch (IOException ignore) { + // } + } } @@ -62,15 +68,16 @@ public static void delete(File file) { * @param lines the lines to write into the file. * @return the new File. */ - static public File writeFile(File dir, final String name, final Iterable lines) { + public static File writeFile(final File dir, final String name, final Iterable lines) { if (dir == null) { - fail("base directory not specified"); + throw new IllegalArgumentException("base directory not specified"); } + mkDir(dir); File file = new File(dir, name); try (PrintWriter writer = new PrintWriter(new FileWriter(file))) { lines.forEach(writer::println); } catch (IOException e) { - fail(e.getMessage()); + throw new RuntimeException(e.getMessage(), e); } return file; } @@ -82,7 +89,7 @@ static public File writeFile(File dir, final String name, final Iterable * @param lines the lines to write into the file. * @return the new File. */ - static public File writeFile(File dir, final String name, final String... lines) { + public static File writeFile(final File dir, final String name, final String... lines) { return writeFile(dir, name, Arrays.asList(lines)); } @@ -92,7 +99,7 @@ static public File writeFile(File dir, final String name, final String... lines) * @param name the name of the file. * @return the new file. */ - public static File writeFile(File dir, String name) { + public static File writeFile(final File dir, final String name) { return writeFile(dir, name, Collections.singletonList(name)); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java b/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java index a50aa5ef8..6843812d2 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java +++ b/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java @@ -20,12 +20,15 @@ package org.apache.rat.walker; import java.io.BufferedInputStream; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.SortedSet; import org.apache.commons.compress.archivers.ArchiveEntry; import org.apache.commons.compress.archivers.ArchiveException; @@ -34,9 +37,9 @@ import org.apache.commons.io.IOUtils; import org.apache.rat.api.Document; import org.apache.rat.api.RatException; -import org.apache.rat.document.ArchiveEntryDocument; import org.apache.rat.document.ArchiveEntryName; import org.apache.rat.document.DocumentName; +import org.apache.rat.document.DocumentNameMatcher; import org.apache.rat.report.RatReport; import org.apache.rat.utils.DefaultLog; @@ -56,7 +59,7 @@ public ArchiveWalker(final Document document) { } /** - * Run a report over all files and directories in this GZIPWalker, + * Run a report over all files and directories in the archive * ignoring any files/directories set to be ignored. * * @param report the defined RatReport to run on this GZIP walker. @@ -76,6 +79,7 @@ public void run(final RatReport report) throws RatException { private InputStream createInputStream() throws IOException { return new BufferedInputStream(getDocument().inputStream()); } + /** * Retrieves the documents from the archive. * @return A collection of documents that pass the file filter. @@ -87,13 +91,29 @@ public Collection getDocuments() throws RatException { ArchiveEntry entry; while ((entry = input.getNextEntry()) != null) { if (!entry.isDirectory() && input.canReadEntryData(entry)) { - DocumentName innerName = DocumentName.builder().setName(entry.getName()) + final DocumentName innerName = DocumentName.builder().setName(entry.getName()) .setBaseName(".").build(); - if (this.getDocument().getNameMatcher().matches(innerName)) { + final DocumentNameMatcher documentNameMatcher = getDocument().getNameMatcher(); + if (documentNameMatcher.matches(innerName)) { + ArchiveEntryName entryName = new ArchiveEntryName(getDocument().getName(), entry.getName()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); IOUtils.copy(input, baos); - ArchiveEntryName entryName = new ArchiveEntryName(getDocument().getName(), entry.getName()); - result.add(new ArchiveEntryDocument(entryName, baos.toByteArray(), getDocument().getNameMatcher())); + result.add(new Document(entryName, documentNameMatcher) { + @Override + public InputStream inputStream() { + return new ByteArrayInputStream(baos.toByteArray()); + } + + @Override + public boolean isDirectory() { + return false; + } + + @Override + public SortedSet listChildren() { + return Collections.emptySortedSet(); + } + }); } } } diff --git a/apache-rat-core/src/main/resources/org/apache/rat/xhtml5.xsl b/apache-rat-core/src/main/resources/org/apache/rat/xhtml5.xsl new file mode 100644 index 000000000..b15224605 --- /dev/null +++ b/apache-rat-core/src/main/resources/org/apache/rat/xhtml5.xsl @@ -0,0 +1,354 @@ + + + + + + + + + + 🗜 + 🔠 + 🚫 + + + + 📂 + + + + + + + + + + + + + + + +

Rat Report

+ + + + + + + + + + + + +

Detail

+ +

+ Documents with unapproved licenses will start with a + The first character on the next line identifies the document type. +

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Symbols used in this RAT report +
SymbolType
Archive file
Binary file
Ignored file
Notice file
Standard file
Unknown file
Directory
+ + + + + + + + + +
+ Resources discovered in this RAT report +
+ + + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ + + + +
+ ID: + + UUID + + + + Family: + + Unknown + + + +
+
+
+
+ + +

Summary

+ +
+

Generated at by + +

+ + + + + + + + + + + + + + + +
+ Table 1: A summary of statistics from this RAT report. +
Name:Count:Description:
+ + + + + Unknown + + +
+ +

License Statistics

+
+

Categories

+
+ + + + + + + + + + + + + +
+ Table 2: License categories found in this RAT report. +
Name:Count:
+ + + + + Unknown + + +
+
+ +

Licenses

+
+ + + + + + + + + + + + + +
+ Table 3: Licenses found in this RAT report. +
Name:Count:
+ + + + + Unknown + + +
+
+
+ +

Document types

+
+ + + + + + + + + + + + + +
+ Table 4: Document types found in this RAT report. +
Name:Count:
+
+
+
+ + +

Files with unapproved licenses

+ +
    + +
  • +
    +
+
+ + +

Archives

+
    + +
  • +
    +
+
+ + + + + + + + + + + + + + + + + + +
+ +
+ + +
+
+ +
+ + +
+
diff --git a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionParserTest.java b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionParserTest.java index 761230f33..7b9c7d68f 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionParserTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionParserTest.java @@ -36,6 +36,9 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +/** + * Test for option collection parsers. + */ class OptionCollectionParserTest { @TempDir(cleanup = CleanupMode.NEVER) @@ -65,7 +68,7 @@ void parseCommandLineParseExceptionTest() { TestingLog testingLog = new TestingLog(); try { DefaultLog.setInstance(testingLog); - assertThatThrownBy(() -> OptionCollectionParser.parseCommandLine(options, new String[0])) + assertThatThrownBy(() -> underTest.parseCommandLine(options, new String[0])) .isInstanceOf(ParseException.class); } finally { DefaultLog.setInstance(null); @@ -78,7 +81,7 @@ void printHelpExceptionTest() throws ParseException { Options options = new Options(); ReportConfiguration cfg = new ReportConfiguration(); ArgumentContext ctxt = new ArgumentContext(testPath.toFile(), cfg, options, new String[0]); - cfg.setOut(new ReportConfiguration.IODescriptor("Bad Supplier", () -> { throw new IOException("Bad Supplier");})); + cfg.setOutput(new ReportConfiguration.IODescriptor("Bad Supplier", () -> { throw new IOException("Bad Supplier");})); assertThatThrownBy(() -> underTest.printHelp(ctxt)) .isInstanceOf(RatException.class) .hasMessageContaining("Unable to print help: Bad Supplier"); diff --git a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java index ccc7e3bb8..8adebceaf 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java @@ -42,6 +42,7 @@ import org.apache.rat.testhelpers.TestingLog; import org.apache.rat.utils.CasedString; import org.apache.rat.utils.DefaultLog; +import org.apache.rat.utils.FileUtils; import org.apache.rat.utils.Log; import org.apache.rat.walker.ArchiveWalker; import org.apache.rat.walker.DirectoryWalker; @@ -106,13 +107,22 @@ default String formatMsg(String msg) { return String.format("%s: %s", this, msg); } + /** + * Get the name of the test. + * By default, this method returns {@code toString()}. + * @return the name of the test. + */ + default String name() { + return toString(); + } + /** * Creates a named OptionTest. * @param name the name of the test. * @param test the test to execute. * @return a named option test. */ - static OptionTest namedTest(String name, OptionTest test) { + static OptionTest namedTest(String providerName, String name, OptionTest test) { return new OptionTest() { @Override public void exec() { @@ -120,6 +130,10 @@ public void exec() { } @Override public String toString() { + return String.join(":", providerName, name); + } + @Override + public String name() { return name; } }; @@ -162,7 +176,7 @@ public static Map processTestFunctionAnnotations(Object test name = name.substring(testLength); } name = new CasedString(CasedString.StringCase.CAMEL, name).toCase(CasedString.StringCase.KEBAB).toLowerCase(Locale.ROOT); - result.put(name, OptionTest.namedTest(name, () -> { + result.put(name, OptionTest.namedTest(clazz.getName(), name, () -> { try { method.invoke(testProvider); } catch (IllegalAccessException | InvocationTargetException e) { @@ -179,6 +193,7 @@ public static Map processTestFunctionAnnotations(Object test public void testDeprecatedUseLogged() throws IOException { TestingLog log = new TestingLog(); try { + FileUtils.mkDir(testPath.resolve("target").toFile()); DefaultLog.setInstance(log); String[] args = {"--dir", "target", "-a"}; ReportConfiguration config = OptionCollection.parseCommands(testPath.toFile(), args, o -> fail("Help printed"), true); @@ -186,8 +201,8 @@ public void testDeprecatedUseLogged() throws IOException { } finally { DefaultLog.setInstance(null); } - log.assertContainsExactly(1, "WARN: Option [-d, --dir] used. Deprecated for removal since 0.17: Use the standard '--'"); - log.assertContainsExactly(1, "WARN: Option [-a] used. Deprecated for removal since 0.17: Use --edit-license"); + assertThat(log.getCaptured()).containsOnlyOnce("WARN: Option [-d, --dir] used. Deprecated for removal since 0.17: Use the standard '--'") + .containsOnlyOnce("WARN: Option [-a] used. Deprecated for removal since 0.17: Use --edit-license"); } @Test @@ -203,7 +218,7 @@ public void testDirOptionCapturesDirectoryToScan() throws IOException { DefaultLog.setInstance(null); } assertThat(config).isNotNull(); - log.assertContainsExactly(1,"WARN: Option [-d, --dir] used. Deprecated for removal since 0.17: Use the standard '--'"); + assertThat(log.getCaptured()).containsOnlyOnce("WARN: Option [-d, --dir] used. Deprecated for removal since 0.17: Use the standard '--'"); } @Test @@ -264,7 +279,7 @@ void getReportable() throws IOException { * @param test the option test to execute. */ @ParameterizedTest( name = "{index} {0}") - @ArgumentsSource(CliOptionsProvider.class) + @ArgumentsSource(ArgOptionsProvider.class) public void testOptionsUpdateConfig(String name, OptionTest test) { DefaultLog.getInstance().log(Log.Level.INFO, "Running test for: " + name); test.test(); @@ -273,7 +288,7 @@ public void testOptionsUpdateConfig(String name, OptionTest test) { /** * A class to provide the Options and tests to the testOptionsUpdateConfig. */ - static class CliOptionsProvider extends AbstractConfigurationOptionsProvider implements ArgumentsProvider { + static class ArgOptionsProvider extends AbstractConfigurationOptionsProvider implements ArgumentsProvider { /** A flag to determine if help was called */ final AtomicBoolean helpCalled = new AtomicBoolean(false); @@ -294,9 +309,9 @@ public void helpTest() { /** * Constructor. Sets the baseDir and loads the testMap. */ - public CliOptionsProvider() { - super(Collections.emptyList(), testPath.toFile()); - addTest(OptionCollectionTest.OptionTest.namedTest("help", this::helpTest)); + public ArgOptionsProvider() { + super("ArgsOptionsProvider", Collections.emptyList(), testPath.toFile()); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "help", this::helpTest)); } /** diff --git a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java index f523f55e3..57b0321a9 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/OutputTest.java @@ -30,8 +30,8 @@ import org.apache.rat.license.LicenseSetFactory; import org.apache.rat.report.claim.ClaimStatistic; import org.apache.rat.report.claim.ClaimStatisticTest; +import org.apache.rat.utils.FileUtils; import org.apache.rat.test.utils.Resources; -import org.apache.rat.testhelpers.FileUtils; import org.apache.rat.utils.StandardXmlFactory; import org.apache.rat.utils.StandardXmlFactoryTest; import org.apache.rat.walker.DirectoryWalker; @@ -163,7 +163,7 @@ void configurationReadingTest() throws IOException { underTest.setArchiveProcessing(ReportConfiguration.Processing.NOTIFICATION); underTest.setStandardProcessing(ReportConfiguration.Processing.ABSENCE); underTest.setStyleSheet(StyleSheets.MISSING_HEADERS.getStyleSheet()); - underTest.setOut(new File("/some/file/somewhere")); + underTest.setOutput(new File("/some/file/somewhere")); underTest.setCopyrightMessage("the copyright message"); underTest.addSource(new File("/my/file")); underTest.addSource(new ReportConfigurationTest.TestingReportable()); @@ -211,7 +211,7 @@ private ReportConfiguration initializeConfiguration() throws URISyntaxException void listLicensesReportTest() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); ReportConfiguration configuration = initializeConfiguration(); - configuration.setOut(new ReportConfiguration.IODescriptor<>("listLicensesReportTest", () -> out)); + configuration.setOutput(new ReportConfiguration.IODescriptor<>("listLicensesReportTest", () -> out)); configuration.setStyleSheet(StyleSheets.UNAPPROVED_LICENSES.getStyleSheet()); Reporter.Output output = Reporter.Output.builder() .statistic(new ClaimStatistic()) diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java index 098669e82..22505ee42 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java @@ -43,6 +43,7 @@ import java.util.List; import java.util.SortedSet; import java.util.function.Function; +import java.util.stream.Collectors; import org.apache.commons.io.filefilter.DirectoryFileFilter; import org.apache.commons.io.output.CloseShieldOutputStream; @@ -472,7 +473,7 @@ void outputTest() throws IOException { assertThat(underTest.getWriter()).isNotNull(); ByteArrayOutputStream stream = new ByteArrayOutputStream(); - underTest.setOut(new ReportConfiguration.IODescriptor<>("outputTest", () -> stream)); + underTest.setOutput(new ReportConfiguration.IODescriptor<>("outputTest", () -> stream)); assertThat(underTest.getOutput().get()).isEqualTo(stream); PrintWriter writer = underTest.getWriter().get(); assertThat(writer).isNotNull(); @@ -560,7 +561,7 @@ void testValidate() { void testSetOut() throws IOException { ReportConfiguration config = new ReportConfiguration(); try (OutputStreamInterceptor osi = new OutputStreamInterceptor()) { - config.setOut(new ReportConfiguration.IODescriptor<>("testSetOut",() -> osi)); + config.setOutput(new ReportConfiguration.IODescriptor<>("testSetOut", () -> osi)); assertThat(osi.closeCount).isEqualTo(0); try (OutputStream os = config.getOutput().get()) { assertThat(os).isNotNull(); @@ -591,8 +592,11 @@ void logFamilyCollisionTest() { log.clear(); underTest.logFamilyCollisions(l); underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2")); - assertThat(log.getCaptured().contains("CAT")).as("'CAT' not found").isTrue(); - assertThat(log.getCaptured().contains(l.name())).as("logging not set to "+l).isTrue(); + if (DefaultLog.getInstance().isEnabled(l)) { + assertThat(log.getCaptured()).contains("CAT").contains(l.name()); + } else { + assertThat(log.getCaptured()).doesNotContain("CAT").doesNotContain(l.name()); + } } } @@ -709,21 +713,25 @@ public Appendable append(char c) throws IOException { /** * Validates that the configuration contains the default approved licenses. - * @param config the configuration to test. + * @param config The configuration to test. */ - public static void validateDefaultApprovedLicenses(ReportConfiguration config) { - validateDefaultApprovedLicenses(config, 0); - } - + public static void validateDefaultApprovedLicenses(ReportConfiguration config, String... additionalIds) { + validateLicenses(config, Arrays.asList(additionalIds), LicenseFilter.APPROVED, XMLConfigurationReaderTest.APPROVED_LICENSES); + } + /** - * Validates that the configuration contains the default approved licenses. + * Validates that the configuration contains all the default licenses along with any addiitonal licenses * @param config the configuration to test. + * @param additionalLicenses Additional licence IDs that are expected. */ - public static void validateDefaultApprovedLicenses(ReportConfiguration config, int additionalIdCount) { - assertThat(config.getLicenseCategories(LicenseFilter.APPROVED)).hasSize(XMLConfigurationReaderTest.APPROVED_IDS.length + additionalIdCount); - for (String s : XMLConfigurationReaderTest.APPROVED_IDS) { - assertThat(config.getLicenseCategories(LicenseFilter.APPROVED)).contains(ILicenseFamily.makeCategory(s)); - } + public static void validateDefaultLicenses(ReportConfiguration config, String...additionalLicenses) { + validateLicenses(config, Arrays.asList(additionalLicenses), LicenseFilter.ALL, XMLConfigurationReaderTest.EXPECTED_LICENSES); + } + + private static void validateLicenses(ReportConfiguration config, List additionalIds, LicenseFilter filter, String[] approvedIds) { + List expected = new ArrayList<>(Arrays.asList(approvedIds)); + expected.addAll(additionalIds); + assertThat(config.getLicenses(filter).stream().map(ILicense::getId).collect(Collectors.toSet())).containsExactlyInAnyOrderElementsOf(expected); } /** @@ -731,27 +739,22 @@ public static void validateDefaultApprovedLicenses(ReportConfiguration config, i * @param config the configuration to test. */ public static void validateDefaultLicenseFamilies(ReportConfiguration config, String...additionalIds) { - assertThat(config.getLicenseFamilies(LicenseFilter.ALL)).hasSize(XMLConfigurationReaderTest.EXPECTED_IDS.length + additionalIds.length); - List expected = new ArrayList<>(); - expected.addAll(Arrays.asList(XMLConfigurationReaderTest.EXPECTED_IDS)); - expected.addAll(Arrays.asList(additionalIds)); - for (ILicenseFamily family : config.getLicenseFamilies(LicenseFilter.ALL)) { - assertThat(expected).contains(family.getFamilyCategory().trim()); - } + validateLicenseFamilies(config, Arrays.asList(additionalIds), LicenseFilter.ALL, XMLConfigurationReaderTest.EXPECTED_IDS); } /** - * Validates that the configuration contains the default licenses. + * Validates that the configuration contains the default license families. * @param config the configuration to test. */ - public static void validateDefaultLicenses(ReportConfiguration config, String...additionalLicenses) { - assertThat(config.getLicenses(LicenseFilter.ALL)).hasSize(XMLConfigurationReaderTest.EXPECTED_LICENSES.length + additionalLicenses.length); - List expected = new ArrayList<>(); - expected.addAll(Arrays.asList(XMLConfigurationReaderTest.EXPECTED_LICENSES)); - expected.addAll(Arrays.asList(additionalLicenses)); - for (ILicense license : config.getLicenses(LicenseFilter.ALL)) { - assertThat(expected).contains(license.getId()); + static void validateDefaultApprovedLicenseFamilies(ReportConfiguration config, String...additionalIds) { + validateLicenseFamilies(config, Arrays.asList(additionalIds), LicenseFilter.APPROVED, XMLConfigurationReaderTest.APPROVED_IDS); } + + private static void validateLicenseFamilies(ReportConfiguration config, List additionalIds, LicenseFilter filter, String[] approvedIds) { + List expected = new ArrayList<>(Arrays.asList(approvedIds)); + expected.addAll(additionalIds); + assertThat(config.getLicenseFamilies(filter).stream().map(lf -> lf.getFamilyCategory().trim()) + .collect(Collectors.toSet())).containsExactlyInAnyOrderElementsOf(expected); } /** @@ -767,6 +770,7 @@ public static void validateDefault(ReportConfiguration config) { validateDefaultApprovedLicenses(config); validateDefaultLicenseFamilies(config); validateDefaultLicenses(config); + validateDefaultApprovedLicenses(config); } public static void assertSame(ReportConfiguration actual, ReportConfiguration expected) { @@ -796,7 +800,7 @@ void serDesTest() throws IOException { underTest.setArchiveProcessing(ReportConfiguration.Processing.NOTIFICATION); underTest.setStandardProcessing(ReportConfiguration.Processing.ABSENCE); underTest.setStyleSheet(StyleSheets.MISSING_HEADERS.getStyleSheet()); - underTest.setOut(new File("/some/file/somewhere")); + underTest.setOutput(new File("/some/file/somewhere")); underTest.setCopyrightMessage("the copyright message"); underTest.addSource(new File("/my/file")); underTest.addSource(new TestingReportable()); @@ -837,7 +841,7 @@ static class OutputStreamInterceptor extends OutputStream { public void write(int arg0) { throw new UnsupportedOperationException(); } - + @Override public void close() { ++closeCount; diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java index 56ad9ba7e..e2d545984 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java @@ -20,7 +20,6 @@ import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; @@ -54,7 +53,7 @@ import org.apache.rat.test.AbstractOptionsProvider; import org.apache.rat.test.utils.OptionFormatter; import org.apache.rat.test.utils.Resources; -import org.apache.rat.testhelpers.FileUtils; +import org.apache.rat.utils.FileUtils; import org.apache.rat.testhelpers.TestingLog; import org.apache.rat.testhelpers.TextUtils; import org.apache.rat.testhelpers.XmlUtils; @@ -81,7 +80,7 @@ class ReporterOptionsProvider extends AbstractOptionsProvider implements Argumen final AtomicBoolean helpCalled = new AtomicBoolean(false); public ReporterOptionsProvider() { - super(ReporterOptionsTest.testPath.toFile()); + super("ReporterOptionsProvider", ReporterOptionsTest.testPath.toFile()); processTestFunctionAnnotations(); testMap.put("addLicense", this::addLicenseTest); testMap.remove("add-license"); @@ -115,20 +114,30 @@ protected final ReportConfiguration generateConfig(List> return config; } + /** + * Creates the option/.rat directory + * @param option the name for the sourceDirectory. + */ private File configureRatDir(Option option) { configureSourceDir(option); - File result = new File(sourceDir, ".rat"); - FileUtils.mkDir(result); - return result; + File ratDir = new File(sourceDir, ".rat"); + FileUtils.mkDir(ratDir); + return ratDir; } + /** + * Creates the srcDir.,. + * @param option the name for the srcDir. + */ private void configureSourceDir(Option option) { sourceDir = new File(baseDir, OptionFormatter.getName(option)); FileUtils.mkDir(sourceDir); } + /** + * verify that without args the report is ok. + */ private void validateNoArgSetup() throws IOException, RatException { - // verify that without args the report is ok. TestingLog log = new TestingLog(); DefaultLog.setInstance(log); try { @@ -229,8 +238,7 @@ protected void licensesDeniedTest() { @OptionCollectionTest.TestFunction protected void licensesDeniedFileTest() { Option option = Arg.LICENSES_DENIED_FILE.find("licenses-denied-file"); - File ratDir = configureRatDir(option); - File outputFile = FileUtils.writeFile(ratDir, "licensesDenied.txt", Collections.singletonList("ILLUMOS")); + File outputFile = FileUtils.writeFile(configureRatDir(option), "licensesDenied.txt", Collections.singletonList("ILLUMOS")); execLicensesDeniedTest(option, new String[]{outputFile.getAbsolutePath()}); } @@ -241,7 +249,6 @@ private void noDefaultsTest(final Option option) { "*/\n\n", "class Test {}\n")); validateNoArgSetup(); - ReportConfiguration config = generateConfig(ImmutablePair.of(option, null)); Reporter reporter = new Reporter(config); assertThatThrownBy(reporter::execute) @@ -309,8 +316,13 @@ protected void counterMinTest() { }); } - // exclude tests - private void execExcludeTest(final Option option, final String[] args, final boolean addIgnored) { + /** + * Runs the exclude tests. + * @param option The exclude option to run. + * @param args the arguments for the command line. + * @param includesRatDir @{code true} if the .rat directory was created. + */ + private void execExcludeTest(final Option option, final String[] args, final boolean includesRatDir) { String[] notExcluded = {"notbaz", "well._afile"}; String[] excluded = {"some.foo", "B.bar", "justbaz"}; @@ -326,20 +338,19 @@ private void execExcludeTest(final Option option, final String[] args, final boo Reporter reporter = new Reporter(config); Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(5); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 1 : 0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(includesRatDir ? 1 : 0); // filter out source config = generateConfig(ImmutablePair.of(option, args)); reporter = new Reporter(config); output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(2); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 4 : 3); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(includesRatDir ? 4 : 3); }); } private void excludeFileTest(final Option option) { - File ratDir = configureRatDir(option); - File outputFile = FileUtils.writeFile(ratDir, "exclude.txt", Arrays.asList(EXCLUDE_ARGS)); + File outputFile = FileUtils.writeFile(configureRatDir(option), "exclude.txt", Arrays.asList(EXCLUDE_ARGS)); execExcludeTest(option, new String[]{outputFile.getAbsolutePath()}, true); } @@ -479,8 +490,13 @@ protected void inputExcludeParsedScmTest() { }); } - // include tests - private void execIncludeTest(final Option option, final String[] args, boolean addIgnored) { + /** + * Runs the include tests. + * @param option The include option to run. + * @param args the arguments for the command line. + * @param includesRatDir @{code true} if the .rat directory was created. + */ + private void execIncludeTest(final Option option, final String[] args, final boolean includesRatDir) { Option excludeOption = Arg.EXCLUDE.option(); String[] notExcluded = {"B.bar", "justbaz", "notbaz"}; String[] excluded = {"some.foo"}; @@ -496,7 +512,7 @@ private void execIncludeTest(final Option option, final String[] args, boolean a Reporter reporter = new Reporter(config); Reporter.Output output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(4); - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 1 : 0); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(includesRatDir ? 1 : 0); // verify exclude removes most files. config = generateConfig(ImmutablePair.of(excludeOption, EXCLUDE_ARGS)); @@ -504,7 +520,7 @@ private void execIncludeTest(final Option option, final String[] args, boolean a output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(1); // .gitignore is ignored by default as it is hidden but not counted - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 4 : 3); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(includesRatDir ? 4 : 3); // verify include put them back config = generateConfig(ImmutablePair.of(option, args), ImmutablePair.of(excludeOption, EXCLUDE_ARGS)); @@ -512,13 +528,12 @@ private void execIncludeTest(final Option option, final String[] args, boolean a output = reporter.execute(); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(3); // .gitignore is ignored by default as it is hidden but not counted - assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(addIgnored ? 2 : 1); + assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(includesRatDir ? 2 : 1 ); }); } private void includeFileTest(final Option option) { - File ratDir = configureRatDir(option); - File outputFile = FileUtils.writeFile(ratDir, "include.txt", Arrays.asList(INCLUDE_ARGS)); + File outputFile = FileUtils.writeFile(configureRatDir(option), "include.txt", Arrays.asList(INCLUDE_ARGS)); execIncludeTest(option, new String[]{outputFile.getAbsolutePath()}, true); } @@ -759,8 +774,7 @@ protected void execLicensesApprovedTest(final Option option, String[] args) { @OptionCollectionTest.TestFunction protected void licensesApprovedFileTest() { Option option = Arg.LICENSES_APPROVED_FILE.find("licenses-approved-file"); - File ratDir = configureRatDir(option); - File outputFile = FileUtils.writeFile(ratDir, "licensesApproved.txt", Collections.singletonList("GPL1")); + File outputFile = FileUtils.writeFile(configureRatDir(option), "licensesApproved.txt", Collections.singletonList("GPL1")); execLicensesApprovedTest(option, new String[]{outputFile.getAbsolutePath()}); } @@ -816,8 +830,8 @@ private void outTest(final Option option) { assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isZero(); output.format(config); String actualText = TextUtils.readFile(outFile); - TextUtils.assertContainsExactly(1, "Apache License 2.0: 1 ", actualText); - TextUtils.assertContainsExactly(1, "STANDARD: 1 ", actualText); + assertThat(actualText).containsOnlyOnce("Apache License 2.0: 1 ") + .containsOnlyOnce("STANDARD: 1 "); }); } @@ -858,18 +872,21 @@ private void styleSheetTest(final Option option) { String actualText = baos.toString(StandardCharsets.UTF_8); switch (sheet) { case MISSING_HEADERS: - TextUtils.assertContainsExactly(1, "Files with missing headers:" + System.lineSeparator() + - " /stylesheet", actualText); + assertThat(actualText).containsOnlyOnce("Files with missing headers:" + System.lineSeparator() + + " /stylesheet"); break; case PLAIN: - TextUtils.assertContainsExactly(1, "Unknown license: 1 ", actualText); - TextUtils.assertContainsExactly(1, "?????: 1 ", actualText); + assertThat(actualText).containsOnlyOnce("Unknown license: 1 "); + assertThat(actualText).containsOnlyOnce("?????: 1 "); break; case XML: - TextUtils.assertContainsExactly(1, "", actualText); + assertThat(actualText).containsOnlyOnce(""); break; case UNAPPROVED_LICENSES: - TextUtils.assertContainsExactly(1, "Files with unapproved licenses:" + System.lineSeparator() + " /stylesheet", actualText); + assertThat(actualText).containsOnlyOnce("Files with unapproved licenses:" + System.lineSeparator() + " /stylesheet"); + break; + case XHTML5: + assertThat(actualText).containsPattern("Approved<\\/td>\\s+\\d+<\\/td>\\s+A count of approved licenses.<\\/td>"); break; default: fail("No test for stylesheet " + sheet); @@ -886,7 +903,7 @@ private void styleSheetTest(final Option option) { assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); output.format(config); String actualText = baos.toString(StandardCharsets.UTF_8); - TextUtils.assertContainsExactly(1, "Hello world", actualText); + assertThat(actualText).containsOnlyOnce("Hello world"); } catch (IOException | RatException e) { fail(e.getMessage(), e); } finally { @@ -928,9 +945,10 @@ protected void xmlTest() { assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.UNAPPROVED)).isEqualTo(1); output.format(config); String actualText = baos.toString(StandardCharsets.UTF_8); - TextUtils.assertContainsExactly(1, "", actualText); + assertThat(actualText) + .containsOnlyOnce(""); - try (InputStream expected = StyleSheets.getStyleSheet("xml").ioSupplier().get(); + try (InputStream expected = StyleSheets.getStyleSheet("xml", null).ioSupplier().get(); InputStream actual = config.getStyleSheet().get()) { assertThat(IOUtils.contentEquals(expected, actual)).as("'xml' does not match").isTrue(); } @@ -954,12 +972,12 @@ protected void logLevelTest() { ReportConfiguration config = generateConfig(); Reporter reporter = new Reporter(config); reporter.execute(); - TextUtils.assertNotContains("DEBUG", baos.toString(StandardCharsets.UTF_8)); + assertThat(baos.toString(StandardCharsets.UTF_8)).doesNotContain("DEBUG"); config = generateConfig(ImmutablePair.of(option, new String[]{"debug"})); reporter = new Reporter(config); reporter.execute(); - TextUtils.assertContains("DEBUG", baos.toString(StandardCharsets.UTF_8)); + assertThat(baos.toString(StandardCharsets.UTF_8)).contains("DEBUG"); } catch (IOException | RatException e) { fail(e.getMessage(), e); } finally { @@ -974,16 +992,12 @@ private void listLicenses(final Option option) { assertDoesNotThrow(() -> { configureSourceDir(option); - File outFile = new File(sourceDir, "out.xml"); - FileUtils.delete(outFile); - ImmutablePair outputFile = ImmutablePair.of(Arg.OUTPUT_FILE.option(), new String[]{outFile.getAbsolutePath()}); - ImmutablePair stylesheet = ImmutablePair.of(Arg.OUTPUT_STYLE.option(), new String[]{StyleSheets.XML.arg()}); for (LicenseSetFactory.LicenseFilter filter : LicenseSetFactory.LicenseFilter.values()) { args[0] = filter.name(); - ReportConfiguration config = generateConfig(outputFile, stylesheet, ImmutablePair.of(option, args)); + ReportConfiguration config = generateConfig(ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - reporter.execute().format(config); - Document document = XmlUtils.toDom(new FileInputStream(outFile)); + Reporter.Output output = reporter.execute(); + Document document = output.getDocument(); switch (filter) { case ALL: XmlUtils.assertIsPresent(filter.name(), document, xPath, "/rat-report/rat-config/licenses/license[@id='AL2.0']"); @@ -1020,16 +1034,12 @@ private void listFamilies(final Option option) { assertDoesNotThrow(() -> { configureSourceDir(option); - File outFile = new File(sourceDir, "out.xml"); - FileUtils.delete(outFile); - ImmutablePair outputFile = ImmutablePair.of(Arg.OUTPUT_FILE.option(), new String[]{outFile.getAbsolutePath()}); - ImmutablePair stylesheet = ImmutablePair.of(Arg.OUTPUT_STYLE.option(), new String[]{StyleSheets.XML.arg()}); for (LicenseSetFactory.LicenseFilter filter : LicenseSetFactory.LicenseFilter.values()) { args[0] = filter.name(); - ReportConfiguration config = generateConfig(outputFile, stylesheet, ImmutablePair.of(option, args)); + ReportConfiguration config = generateConfig(ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - reporter.execute().format(config); - Document document = XmlUtils.toDom(Files.newInputStream(outFile.toPath())); + Reporter.Output output = reporter.execute(); + Document document = output.getDocument(); switch (filter) { case ALL: XmlUtils.assertIsPresent(filter.name(), document, xPath, "/rat-report/rat-config/families/family[@id='AL']"); @@ -1083,7 +1093,7 @@ private void archiveTest(final Option option) { Reporter reporter = new Reporter(config); reporter.execute().format(config); - Document document = XmlUtils.toDom(Files.newInputStream(outFile.toPath())); + Document document = reporter.execute().getDocument(); XmlUtils.assertIsPresent(proc.name(), document, xPath, "/rat-report/resource[@name='/dummy.jar']"); switch (proc) { case ABSENCE: @@ -1131,9 +1141,9 @@ private void standardTest(final Option option) { args[0] = proc.name(); ReportConfiguration config = generateConfig(outputFile, stylesheet, ImmutablePair.of(option, args)); Reporter reporter = new Reporter(config); - reporter.execute().format(config); + Reporter.Output output = reporter.execute(); - Document document = XmlUtils.toDom(Files.newInputStream(outFile.toPath())); + Document document = output.getDocument(); XmlUtils.assertIsPresent(proc.name(), document, xPath, testDoc); XmlUtils.assertIsPresent(proc.name(), document, xPath, missingDoc); @@ -1184,7 +1194,7 @@ private void editCopyrightTest(final Option option, final Option extraOption) { reporter.execute(); String actualText = TextUtils.readFile(javaFile); - TextUtils.assertNotContains(myCopyright, actualText); + assertThat(actualText).doesNotContain(myCopyright); Pair arg2 = ImmutablePair.of(Arg.EDIT_ADD.find("edit-license"), null); config = extraArg != null ? generateConfig(arg1, arg2, extraArg) : generateConfig(arg1, arg2); @@ -1193,13 +1203,13 @@ private void editCopyrightTest(final Option option, final Option extraOption) { actualText = TextUtils.readFile(javaFile); if (forced) { - TextUtils.assertContains(myCopyright, actualText); + assertThat(actualText).contains(myCopyright); assertThat(newJavaFile).doesNotExist(); } else if (dryRun) { - TextUtils.assertNotContains(myCopyright, actualText); + assertThat(actualText).doesNotContain(myCopyright); assertThat(newJavaFile).doesNotExist(); } else { - TextUtils.assertNotContains(myCopyright, actualText); + assertThat(actualText).doesNotContain(myCopyright); assertThat(newJavaFile).exists(); } }); @@ -1294,10 +1304,8 @@ protected void helpLicensesTest() { System.setOut(origin); } - assertThat(actualText).isNotNull(); - TextUtils.assertContains("====== Licenses ======", actualText); - TextUtils.assertContains("====== Defined Matchers ======", actualText); - TextUtils.assertContains("====== Defined Families ======", actualText); + assertThat(actualText).isNotNull() + .contains("====== Licenses ======", "====== Defined Matchers ======", "====== Defined Families ======"); } @OptionCollectionTest.TestFunction diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsTest.java index d98a46468..58df937df 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsTest.java @@ -21,13 +21,14 @@ import java.io.File; import java.io.IOException; import java.nio.file.Path; +import java.util.Map; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; import org.apache.rat.api.RatException; import org.apache.rat.report.claim.ClaimStatistic; import org.apache.rat.test.AbstractConfigurationOptionsProvider; -import org.apache.rat.testhelpers.FileUtils; +import org.apache.rat.utils.FileUtils; import org.apache.rat.testhelpers.XmlUtils; import org.apache.rat.utils.DefaultLog; import org.apache.rat.utils.Log; @@ -83,7 +84,7 @@ void testRat362() { XPath xpath = XPathFactory.newInstance().newXPath(); XmlUtils.assertIsPresent(output.getDocument(), xpath, "/rat-report/resource[@name='/foo.md']"); XmlUtils.assertAttributes(output.getDocument(), xpath, "/rat-report/resource[@name='/foo.md']", - XmlUtils.mapOf("type", "IGNORED")); + Map.of("type", "IGNORED")); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.STANDARDS)).isEqualTo(0); assertThat(output.getStatistic().getCounter(ClaimStatistic.Counter.IGNORED)).isEqualTo(2); } catch (IOException | RatException | XPathExpressionException e) { diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java index 4dc54ac7b..4bfeabde6 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReporterTest.java @@ -19,6 +19,7 @@ package org.apache.rat; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.api.Fail.fail; import java.io.ByteArrayOutputStream; @@ -39,6 +40,7 @@ import java.util.Optional; import java.util.TreeMap; import java.util.UUID; +import java.util.stream.Stream; import java.util.regex.Pattern; import javax.xml.XMLConstants; import javax.xml.transform.Source; @@ -66,6 +68,9 @@ import org.apache.rat.testhelpers.BaseOption; import org.apache.rat.testhelpers.BaseOptionCollection; import org.apache.rat.testhelpers.XmlUtils; +import org.apache.rat.testhelpers.data.ReportTestDataProvider; +import org.apache.rat.testhelpers.data.TestData; +import org.apache.rat.testhelpers.data.ValidatorData; import org.apache.rat.utils.StandardXmlFactory; import org.apache.rat.walker.DirectoryWalker; import org.junit.jupiter.api.AfterAll; @@ -73,6 +78,9 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestInfo; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; @@ -134,6 +142,7 @@ void setUpTest(TestInfo testInfo) { @Test void testExecute() throws RatException { File output = testPath.resolve("output.xml").toFile(); + BaseOptionCollection optionCollection = BaseOptionCollection.builder().build(); ArgumentContext ctxt = collectionParser.parseCommands(new File("."), new String[]{"--output-style", "xml", "--output-file", output.getPath(), basedir}); ClaimStatistic statistic = new Reporter(ctxt.getConfiguration()).execute().getStatistic(); @@ -271,7 +280,7 @@ void testXMLOutput() throws Exception { "type", "STANDARD")); File output = testPath.resolve(".rat/testXMLOutput").toFile(); - output.getParentFile().mkdirs(); + org.apache.rat.utils.FileUtils.mkDir(output.getParentFile()); ArgumentContext ctxt = collectionParser.parseCommands(testPath.toFile(), new String[]{"--output-style", "xml", "--output-file", output.getPath(), basedir}); new Reporter(ctxt.getConfiguration()).execute().format(ctxt.getConfiguration()); @@ -503,7 +512,7 @@ void plainReportTest() throws Exception { "Generated at: "; ByteArrayOutputStream out = new ByteArrayOutputStream(); ReportConfiguration configuration = initializeConfiguration(); - configuration.setOut(new ReportConfiguration.IODescriptor<>("plainReportTest", () -> out)); + configuration.setOutput(new ReportConfiguration.IODescriptor<>("plainReportTest", () -> out)); new Reporter(configuration).execute().format(configuration); String document = out.toString(); @@ -519,7 +528,7 @@ void plainReportTest() throws Exception { void unapprovedLicensesReportTest() throws Exception { ByteArrayOutputStream out = new ByteArrayOutputStream(); ReportConfiguration configuration = initializeConfiguration(); - configuration.setOut(new ReportConfiguration.IODescriptor<>("unapprovedLicensesReportTest", () -> out)); + configuration.setOutput(new ReportConfiguration.IODescriptor<>("unapprovedLicensesReportTest", () -> out)); configuration.setStyleSheet(this.getClass().getResource("/org/apache/rat/unapproved-licenses.xsl")); new Reporter(configuration).execute().format(configuration); @@ -546,16 +555,47 @@ void counterMaxTest() throws Exception { .isTrue(); } + static Stream getTestData() { + BaseOptionCollection.Builder builder = BaseOptionCollection.builder() + .unsupported(Arg.OUTPUT_FILE); + return new ReportTestDataProvider().getOptionTests(builder.build()).stream().map(testData -> + Arguments.of(testData.getTestName(), testData)); + } + + @ParameterizedTest( name = "{index} {0}") + @MethodSource("getTestData") + void testReportData(String name, TestData test) throws Exception { + Path invokePath = testPath.resolve(test.getTestName()); + org.apache.rat.utils.FileUtils.mkDir(invokePath.toFile()); + + test.setupFiles(invokePath); + ArgumentContext ctxt = collectionParser.parseCommands(invokePath.toFile(), + test.getCommandLine(invokePath.toString())); + if (test.expectingException()) { + assertThatThrownBy(() -> new Reporter(ctxt.getConfiguration()).execute()).as("Expected throws from " + name) + .hasMessageContaining(test.getExpectedException().getMessage()); + ValidatorData data = new ValidatorData(Reporter.Output.builder().configuration(ctxt.getConfiguration()).build(), + invokePath.toString()); + test.getValidator().accept(data); + } else { + Reporter.Output output = ctxt.getConfiguration() != null ? new Reporter(ctxt.getConfiguration()).execute() : + Reporter.Output.builder().build(); + ValidatorData data = new ValidatorData(output, invokePath.toString()); + data.getOutput().format(data.getConfiguration()); + test.getValidator().accept(data); + } + } + private record LicenseInfo(String id, String family, boolean approval, boolean hasNotes) { - LicenseInfo(String id, boolean approval, boolean hasNotes) { - this(id, id, approval, hasNotes); - } + LicenseInfo(String id, boolean approval, boolean hasNotes) { + this(id, id, approval, hasNotes); + } - private LicenseInfo(String id, String family, boolean approval, boolean hasNotes) { - this.id = id; - this.family = ILicenseFamily.makeCategory(family); - this.approval = approval; - this.hasNotes = hasNotes; - } + private LicenseInfo(String id, String family, boolean approval, boolean hasNotes) { + this.id = id; + this.family = ILicenseFamily.makeCategory(family); + this.approval = approval; + this.hasNotes = hasNotes; } + } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java index 22a4945f3..3fc7098bf 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java @@ -49,12 +49,24 @@ import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; +/** + * A collection of tests for the AnalyserFactory. + */ public class AnalyserFactoryTest { + /** + * The document name for the base directory. + */ private final DocumentName basedir; + /** + * The analyzer created by the factory. + */ private DocumentAnalyser analyser; + /** + * Constructor. + */ AnalyserFactoryTest() { basedir = DocumentName.builder(new File(Files.currentFolder(), Resources.SRC_TEST_RESOURCES)).build(); } @@ -185,9 +197,7 @@ public void RAT147_unix_Test() throws Exception { Resources.getResourceFile("/jira/RAT147/unix-newlines.txt.bin"), DocumentNameMatcher.MATCHES_ALL); analyser.analyse(document); String result = buildReport(document); - TextUtils.assertPatternInTarget( - " e.getKey() != counter) - .map(Map.Entry::getValue).forEach(log::assertContains); + List expectedEntries = required.entrySet().stream().filter(e -> e.getKey() != counter) + .map(Map.Entry::getValue).toList(); + assertThat(log.getCaptured()).contains(expectedEntries); if (required.entrySet().contains(counter)) { - log.assertNotContains(required.get(counter)); + assertThat(log.getCaptured()).doesNotContain(required.get(counter)); } statistic.incCounter(counter, 1); validator.logIssues(statistic); String expectedStr = format("ERROR: Unexpected count for %s, limit is [%s,5]. Count: 6", counter, counter.getDefaultMinValue()); - log.assertContains(expectedStr); + assertThat(log.getCaptured()).contains(expectedStr); log.clear(); statistic.incCounter(counter, -1 - expected); } diff --git a/apache-rat-core/src/test/java/org/apache/rat/configuration/XMLConfigurationReaderTest.java b/apache-rat-core/src/test/java/org/apache/rat/configuration/XMLConfigurationReaderTest.java index f0779b31f..57ce87019 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/configuration/XMLConfigurationReaderTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/configuration/XMLConfigurationReaderTest.java @@ -41,17 +41,36 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; +/** + * Tests and constants for XML reader tests. + */ public class XMLConfigurationReaderTest { + /** + * The expected IDS for the default configuration. + */ public static final String[] EXPECTED_IDS = {"AL", "BSD-3", "CDDL1", "GPL", "MIT", "OASIS", "W3C", "W3CD"}; + /** + * The approved IDs for the default configuraiton. + */ public static final String[] APPROVED_IDS = {"AL", "BSD-3", "CDDL1", "MIT", "OASIS", "W3C", "W3CD"}; + /** + * The expected licenses for the default configuration. + */ public static final String[] EXPECTED_LICENSES = {"AL1.0", "AL1.1", "AL2.0", "BSD-3", "DOJO", "TMF", "CDDL1", "ILLUMOS", "GPL1", "GPL2", "GPL3", "MIT", "OASIS", "W3C", "W3CD"}; + /** + * The approved licenses for the default configuration. + */ + public static final String[] APPROVED_LICENSES = { "AL1.0", "AL1.1", "AL2.0", "BSD-3", "DOJO", "TMF", "CDDL1", "ILLUMOS", + "MIT", "OASIS", "W3C", "W3CD" }; + + @Test void approvedLicenseIdTest() throws URISyntaxException { XMLConfigurationReader reader = new XMLConfigurationReader(); @@ -59,9 +78,8 @@ void approvedLicenseIdTest() throws URISyntaxException { assertThat(url).isNotNull(); reader.read(url.toURI()); - Collection readCategories = reader.approvedLicenseId(); - assertThat(readCategories.toArray(new String[readCategories.size()])) - .containsExactly(APPROVED_IDS); + Collection actual = reader.approvedLicenseId(); + assertThat(actual).containsExactlyInAnyOrder(APPROVED_IDS); } @Test @@ -77,12 +95,19 @@ void LicensesTest() throws URISyntaxException { void LicenseFamiliesTest() throws URISyntaxException { XMLConfigurationReader reader = new XMLConfigurationReader(); URL url = XMLConfigurationReaderTest.class.getResource("/org/apache/rat/default.xml"); + assertThat(url).isNotNull(); reader.read(url.toURI()); - assertThat(reader.readFamilies().stream().map(x -> x.getFamilyCategory().trim()).toArray(String[]::new)) - .containsExactly(EXPECTED_IDS); + Collection actual = reader.readFamilies().stream().map(lf -> lf.getFamilyCategory().trim()) + .toList(); + assertThat(actual).containsExactlyInAnyOrder(EXPECTED_IDS); } + /** + * Checks if a matcher built from the class name is an instance of the provided class. + * @param name the matcher name from the tracker. + * @param clazz the expected class type. + */ private void checkMatcher(String name, Class clazz) { AbstractBuilder builder = MatcherBuilderTracker.getMatcherBuilder(name); assertThat(builder).isNotNull(); diff --git a/apache-rat-core/src/test/java/org/apache/rat/help/HelpTest.java b/apache-rat-core/src/test/java/org/apache/rat/help/HelpTest.java index e3e994765..452799120 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/help/HelpTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/help/HelpTest.java @@ -26,11 +26,15 @@ import java.io.StringWriter; import java.util.Set; +import java.util.regex.Pattern; import static java.lang.String.format; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertTrue; +/** + * Tests to validate CLI help option. + */ public class HelpTest { @Test public void verifyAllOptionsListed() { @@ -42,10 +46,10 @@ public void verifyAllOptionsListed() { for (Option option : opts.getOptions()) { if (option.getOpt() != null) { - TextUtils.assertContains("-" + option.getOpt() + (option.getLongOpt() == null ? " " : ","), result); + assertThat(result).contains("-" + option.getOpt() + (option.getLongOpt() == null ? " " : ",")); } if (option.getLongOpt() != null) { - TextUtils.assertContains("--" + option.getLongOpt() + " ", result); + assertThat(result).contains("--" + option.getLongOpt() + " "); } } @@ -63,7 +67,9 @@ public void verifyArgumentsListed() { for (Option option : opts.getOptions()) { if (option.getArgName() != null) { assertTrue(argTypes.contains(option.getArgName()), () -> format("Argument '%s' is missing from list", option.getArgName())); - TextUtils.assertPatternInTarget(format("^<%s>", option.getArgName()), result); + Pattern pattern = Pattern.compile(format("^<%s>", option.getArgName()), Pattern.MULTILINE); + assertThat(result).as(format("argument name for option `%s`.", option.getKey())) + .containsPattern(pattern); } } assertThat(result).doesNotContain(".."); diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/impl/base/XmlWriterTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/XmlWriterTest.java similarity index 100% rename from apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/impl/base/XmlWriterTest.java rename to apache-rat-core/src/test/java/org/apache/rat/report/xml/writer/XmlWriterTest.java diff --git a/apache-rat-core/src/test/java/org/apache/rat/test/AbstractConfigurationOptionsProvider.java b/apache-rat-core/src/test/java/org/apache/rat/test/AbstractConfigurationOptionsProvider.java index 84e30dc59..866978e8c 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/test/AbstractConfigurationOptionsProvider.java +++ b/apache-rat-core/src/test/java/org/apache/rat/test/AbstractConfigurationOptionsProvider.java @@ -19,6 +19,7 @@ package org.apache.rat.test; import java.io.FileWriter; +import java.nio.charset.StandardCharsets; import java.nio.file.FileSystems; import java.nio.file.Path; import org.apache.commons.cli.Option; @@ -80,7 +81,7 @@ public abstract class AbstractConfigurationOptionsProvider extends AbstractOptio */ public static void preserveData(File baseDir, String targetDir) { final Path recordPath = FileSystems.getDefault().getPath("target", targetDir); - org.apache.rat.testhelpers.FileUtils.mkDir(recordPath.toFile()); + org.apache.rat.utils.FileUtils.mkDir(recordPath.toFile()); try { FileUtils.copyDirectory(baseDir, recordPath.toFile()); } catch (IOException e) { @@ -103,57 +104,63 @@ public static File setup(final File baseDir) { return baseDir; } - protected AbstractConfigurationOptionsProvider(final Collection unsupportedArgs, final File baseDir) { - super(setup(baseDir)); - addTest(OptionCollectionTest.OptionTest.namedTest("addLicense", this::addLicenseTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("config", this::configTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("configuration-no-defaults", this::configurationNoDefaultsTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("copyright", this::copyrightTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("counter-min", this::counterMinTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("counter-max", this::counterMaxTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("dir", () -> DefaultLog.getInstance().info("--dir has no valid test"))); - addTest(OptionCollectionTest.OptionTest.namedTest("dry-run", this::dryRunTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("edit-copyright", this::editCopyrightTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("edit-license", this::editLicenseTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("edit-overwrite", this::editOverwriteTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("exclude", this::excludeTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("exclude-file", this::excludeFileTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("force", this::forceTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("help-licenses", this::helpLicenses)); - addTest(OptionCollectionTest.OptionTest.namedTest("include", this::includeTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("includes-file", this::includesFileTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("input-exclude", this::inputExcludeTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("input-exclude-file", this::inputExcludeFileTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("input-exclude-parsed-scm", this::inputExcludeParsedScmTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("input-exclude-std", this::inputExcludeStdTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("input-exclude-size", this::inputExcludeSizeTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("input-include", this::inputIncludeTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("input-include-file", this::inputIncludeFileTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("input-include-std", this::inputIncludeStdTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("input-source", this::inputSourceTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("license-families-approved", this::licenseFamiliesApprovedTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("license-families-approved-file", this::licenseFamiliesApprovedFileTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("license-families-denied", this::licenseFamiliesDeniedTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("license-families-denied-file", this::licenseFamiliesDeniedFileTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("licenses", this::licensesTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("licenses-approved", this::licensesApprovedTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("licenses-approved-file", this::licensesApprovedFileTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("licenses-denied", this::licensesDeniedTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("licenses-denied-file", this::licensesDeniedFileTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("list-families", this::listFamiliesTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("list-licenses", this::listLicensesTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("log-level", this::logLevelTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("no-default-licenses", this::noDefaultsTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("out", this::outTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("output-archive", this::outputArchiveTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("output-families", this::outputFamiliesTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("output-file", this::outputFileTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("output-licenses", this::outputLicensesTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("output-standard", this::outputStandardTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("output-style", this::outputStyleTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("scan-hidden-directories", this::scanHiddenDirectoriesTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("stylesheet", this::styleSheetTest)); - addTest(OptionCollectionTest.OptionTest.namedTest("xml", this::xmlTest)); + /** + * Construct the tests. + * @param providerName the common name of the provider under test. + * @param unsupportedArgs the list of unsupported arguments. + * @param baseDir the base directory for the tests. Tests and test data will be copied to directories under this directory. + */ + protected AbstractConfigurationOptionsProvider(final String providerName, final Collection unsupportedArgs, final File baseDir) { + super(providerName, setup(baseDir)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "addLicense", this::addLicenseTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "config", this::configTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "configuration-no-defaults", this::configurationNoDefaultsTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "copyright", this::copyrightTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "counter-min", this::counterMinTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "counter-max", this::counterMaxTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "dir", () -> DefaultLog.getInstance().info("--dir has no valid test"))); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "dry-run", this::dryRunTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "edit-copyright", this::editCopyrightTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "edit-license", this::editLicenseTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "edit-overwrite", this::editOverwriteTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "exclude", this::excludeTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "exclude-file", this::excludeFileTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "force", this::forceTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "help-licenses", this::helpLicenses)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "include", this::includeTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "includes-file", this::includesFileTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-exclude", this::inputExcludeTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-exclude-file", this::inputExcludeFileTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-exclude-parsed-scm", this::inputExcludeParsedScmTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-exclude-std", this::inputExcludeStdTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-exclude-size", this::inputExcludeSizeTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-include", this::inputIncludeTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-include-file", this::inputIncludeFileTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-include-std", this::inputIncludeStdTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "input-source", this::inputSourceTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "license-families-approved", this::licenseFamiliesApprovedTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "license-families-approved-file", this::licenseFamiliesApprovedFileTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "license-families-denied", this::licenseFamiliesDeniedTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "license-families-denied-file", this::licenseFamiliesDeniedFileTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "licenses", this::licensesTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "licenses-approved", this::licensesApprovedTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "licenses-approved-file", this::licensesApprovedFileTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "licenses-denied", this::licensesDeniedTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "licenses-denied-file", this::licensesDeniedFileTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "list-families", this::listFamiliesTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "list-licenses", this::listLicensesTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "log-level", this::logLevelTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "no-default-licenses", this::noDefaultsTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "out", this::outTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-archive", this::outputArchiveTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-families", this::outputFamiliesTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-file", this::outputFileTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-licenses", this::outputLicensesTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-standard", this::outputStandardTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "output-style", this::outputStyleTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "scan-hidden-directories", this::scanHiddenDirectoriesTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "stylesheet", this::styleSheetTest)); + addTest(OptionCollectionTest.OptionTest.namedTest(providerName, "xml", this::xmlTest)); super.validate(unsupportedArgs); } @@ -232,10 +239,10 @@ protected void inputExcludeParsedScmTest() { writeFile(".gitignore", Arrays.asList(lines)); File dir = new File(baseDir, "red"); - org.apache.rat.testhelpers.FileUtils.mkDir(dir); + org.apache.rat.utils.FileUtils.mkDir(dir); dir = new File(baseDir, "blue"); dir = new File(dir, "fish"); - org.apache.rat.testhelpers.FileUtils.mkDir(dir); + org.apache.rat.utils.FileUtils.mkDir(dir); assertDoesNotThrow(() -> { ReportConfiguration config = generateConfig(ImmutablePair.of(option, args)); @@ -381,9 +388,7 @@ protected void helpLicenses() { System.setOut(origin); } String txt = output.toString(); - TextUtils.assertContains("====== Licenses ======", txt); - TextUtils.assertContains("====== Defined Matchers ======", txt); - TextUtils.assertContains("====== Defined Families ======", txt); + assertThat(txt).contains("====== Licenses ======", "====== Defined Matchers ======", "====== Defined Families ======"); } protected void licensesApprovedFileTest() { @@ -800,6 +805,7 @@ protected void outputStandardTest() { private void styleSheetTest(final Option option) { // copy the dummy stylesheet so that we have a local file for users of the testing jar. File file = new File(baseDir, "stylesheet-" + option.getLongOpt()); + DocumentName xsltFile = DocumentName.builder(file).build(); try ( InputStream in = ReporterTest.class.getResourceAsStream("MatcherContainerResource.txt"); OutputStream out = Files.newOutputStream(file.toPath())) { @@ -815,12 +821,16 @@ private void styleSheetTest(final Option option) { // run the test String[] args = {null}; assertDoesNotThrow(() -> { - for (String sheet : new String[]{"plain-rat", "missing-headers", "unapproved-licenses", file.getAbsolutePath()}) { + for (String sheet : new String[]{"plain-rat", "missing-headers", "unapproved-licenses", xsltFile.getName()}) { args[0] = sheet; ReportConfiguration config = generateConfig(ImmutablePair.of(option, args)); - try (InputStream expected = StyleSheets.getStyleSheet(sheet).ioSupplier().get(); + try (InputStream expected = StyleSheets.getStyleSheet(sheet, xsltFile.getBaseDocumentName()).ioSupplier().get(); InputStream actual = config.getStyleSheet().get()) { - assertThat(IOUtils.contentEquals(expected, actual)).as(() -> String.format("'%s' does not match", sheet)).isTrue(); + String expectedStr = IOUtils.toString(expected, StandardCharsets.UTF_8); + String actualStr = IOUtils.toString(actual, StandardCharsets.UTF_8); + assertThat(actualStr).as(() -> String.format("'%s' is not correct: %s != %s", + config.getStyleSheetDescriptor().name(), + actualStr, expectedStr)).isEqualTo(expectedStr); } } }); @@ -845,7 +855,7 @@ protected void scanHiddenDirectoriesTest() { protected void xmlTest() { assertDoesNotThrow(() -> { ReportConfiguration config = generateConfig(ImmutablePair.of(Arg.OUTPUT_STYLE.find("xml"), null)); - try (InputStream expected = StyleSheets.getStyleSheet("xml").ioSupplier().get(); + try (InputStream expected = StyleSheets.getStyleSheet("xml", null).ioSupplier().get(); InputStream actual = config.getStyleSheet().get()) { assertThat(IOUtils.contentEquals(expected, actual)).as("'xml' does not match").isTrue(); } diff --git a/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java b/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java index f4a188099..477e074c1 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java +++ b/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java @@ -64,6 +64,10 @@ public abstract class AbstractOptionsProvider implements ArgumentsProvider { * The directory to place test data in. */ protected final File baseDir; + /** + * THe name of the provider of the options + */ + protected final String providerName; /** * Copy the runtime data to the "target" directory. @@ -72,7 +76,7 @@ public abstract class AbstractOptionsProvider implements ArgumentsProvider { */ public static void preserveData(File baseDir, String targetDir) { final Path recordPath = FileSystems.getDefault().getPath("target", targetDir); - recordPath.toFile().mkdirs(); + org.apache.rat.utils.FileUtils.mkDir(recordPath.toFile()); try { FileUtils.copyDirectory(baseDir, recordPath.toFile()); } catch (IOException e) { @@ -85,7 +89,7 @@ protected void processTestFunctionAnnotations() { } protected void addTest(OptionCollectionTest.OptionTest test) { - testMap.put(test.toString(), test); + testMap.put(test.name(), test); } /** @@ -96,12 +100,17 @@ protected DocumentName baseName() { return DocumentName.builder(baseDir).build(); } - protected AbstractOptionsProvider(final File baseDir) { + protected AbstractOptionsProvider(final String providerName, final File baseDir) { + this.providerName = providerName; this.baseDir = baseDir; } - protected void validate(final Collection unsupportedArgs) { + private void removeUnsupportedArgs(final Collection unsupportedArgs) { unsupportedArgs.forEach(testMap::remove); + } + + protected void validate(final Collection unsupportedArgs) { + removeUnsupportedArgs(unsupportedArgs); verifyAllMethodsDefinedAndNeeded(unsupportedArgs); } @@ -131,7 +140,7 @@ private void verifyAllMethodsDefinedAndNeeded(final Collection unsupport if (!argNames.isEmpty()) { fail("Extra methods defined: " + String.join(", ", argNames)); } - unsupportedArgs.forEach(testMap::remove); + removeUnsupportedArgs(unsupportedArgs); } @SafeVarargs @@ -170,7 +179,7 @@ public static String[] extractArgs(List> args) { } protected File writeFile(final String name, final Iterable lines) { - return org.apache.rat.testhelpers.FileUtils.writeFile(baseDir, name, lines); + return org.apache.rat.utils.FileUtils.writeFile(baseDir, name, lines); } final protected DocumentName mkDocName(final String name) { diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOption.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOption.java index a37f4a74a..a74c81dc8 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOption.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOption.java @@ -25,27 +25,40 @@ import java.util.function.Function; +/** + * Ai implementation of UIOption to use in general (non-UI limited or adjusted) testing. + */ public final class BaseOption extends UIOption { - BaseOption(BaseOptionBuilder builder) { + private BaseOption(BaseOptionBuilder builder) { super(builder); } - public UIOption.Builder builder() { + /** + * Creates a builder for the BaseOpton. + * @return the BaseOptionBuilder. + */ + public BaseOptionBuilder builder() { return new BaseOptionBuilder(); } + @Override protected String cleanupName(Option option) { return ArgumentTracker.extractKey(option); } + @Override public String getExample() { return ""; } + @Override public String getText() { return ""; } + /** + * The BaseOptionBuilder implementation. + */ public static class BaseOptionBuilder extends UIOption.Builder { @Override diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOptionCollection.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOptionCollection.java index 5e6793d4c..909cde7ef 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOptionCollection.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/BaseOptionCollection.java @@ -18,16 +18,53 @@ */ package org.apache.rat.testhelpers; +import org.apache.commons.cli.Option; import org.apache.rat.ui.UIOptionCollection; +/** + * A UIOptionCollection for testing purposes. The contained UIOptions are not UI limited or adjusted. + */ public final class BaseOptionCollection extends UIOptionCollection { + /** + * Constructs a BaseOptionCollection builder. + * @return the BaseOptionCollection.Builder. + */ + public static final Builder builder() { + return new Builder(); + } + + /** + * Constructs a default BaseOptionCllection + */ public BaseOptionCollection() { super(new Builder()); } + /** + * Constructs a BaseOptionCollecton from the provided builder. + * @param builder + */ + public BaseOptionCollection(Builder builder) { + super(builder); + } + + /** + * The BaseOptionCollection Builder implementation. + */ public static final class Builder extends UIOptionCollection.Builder { - public Builder() { + /** + * Constructor. + */ + Builder() { super(BaseOption.BaseOptionBuilder::new); } + + /** + * Builds a BaserOptionCollection. + * @return a new BaseOptionCollection implementation. + */ + public BaseOptionCollection build() { + return new BaseOptionCollection(this); + } } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocument.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocument.java index 1bd66377b..6cdb4c813 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocument.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocument.java @@ -31,58 +31,107 @@ import org.apache.rat.document.DocumentName; import org.apache.rat.document.FSInfoTest; +/** + * A Document for testing. The document is guaranteed to have a name and may have content is specified in the constructor. + */ public class TestingDocument extends Document { private final Reader reader; private final IOSupplier input; + /** + * Constructs a TestingDocument with the name "name" and no content. + */ public TestingDocument() { this("name"); } + /** + * Constructs a TestingDocument with the specified "name", no content and will not have an associated document name matcher. + * @param name The name of the document. + */ public TestingDocument(String name) { this(name, null); } + /** + * Constructs a TestingDocument with the specified DocumentName,no content and the {@link DocumentNameMatcher#MATCHES_ALL} + * name matcher associated with it. + * @documentName the document name. + */ public TestingDocument(DocumentName documentName) { super(documentName, DocumentNameMatcher.MATCHES_ALL); this.reader = null; this.input = null; } + /** + * Constructs a TestingDocument with the specified "name", no contentand the specified DocumentNameMatcher + * associated with it. + * @param name the document name. + * @param matcher the associated document name matcher. + */ public TestingDocument(String name, DocumentNameMatcher matcher) { super(DocumentName.builder().setName(name).setBaseName("").build(), matcher); this.reader = null; this.input = null; } + /** + * Constructs a TestingDocument with the name "name" and the content provided by the reader. + * @param reader the Reader that provides content for the document. + * @param name the name of the document + */ public TestingDocument(Reader reader, String name) { super(DocumentName.builder().setName(name).setBaseName("").build(), DocumentNameMatcher.MATCHES_ALL); this.reader = reader; this.input = null; } - public TestingDocument(IOSupplier inputStream, String name) { + /** + * Constructs a TestingDocument with the name "name" and the content provided by the input stream. + * @param inputSupplier the input supplier that provides content for the document as an input stream. + * @param name the name of the document + */ + public TestingDocument(IOSupplier inputSupplier, String name) { super(DocumentName.builder(FSInfoTest.UNIX).setName(name).setBaseName("").build(), DocumentNameMatcher.MATCHES_ALL); - this.input = inputStream; + this.input = inputSupplier; this.reader = null; } + /** + * Gets the reader for the document content. + * @return the Reader for the contents. + * @throws IOException on IO error when reading from input stream. + * @throws NullPointerException if neither the reader nor the input stream were provided. + */ @Override public Reader reader() throws IOException { return reader == null ? new InputStreamReader(input.get()) : reader; } + /** + * @return always returns false. + */ @Override public boolean isDirectory() { return false; } + /** + * @return Always returns an empty set. + */ @Override public SortedSet listChildren() { return Collections.emptySortedSet(); } + /** + * Returns the input stream if it was provided in the constructor. + * @return the input stream if it was provided in the constructor. + * @throws IOException if the input stream can not be retrieved. + * @throws UnsupportedOperationException if the input stream was not provided. + */ @Override public InputStream inputStream() throws IOException { if (input != null) { diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocumentAnalyser.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocumentAnalyser.java index a4daaba08..054534d09 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocumentAnalyser.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocumentAnalyser.java @@ -24,8 +24,14 @@ import org.apache.rat.api.Document; import org.apache.rat.document.DocumentAnalyser; +/** + * A document analyzer to used int est where an actual analysis is not desired. + */ public class TestingDocumentAnalyser implements DocumentAnalyser { + /** + * A list of document that this analyser "analysed". + */ public final List matches = new ArrayList<>(); @Override diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLog.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLog.java index 171cacacd..d79e31248 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLog.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLog.java @@ -24,8 +24,10 @@ * Log that captures output for later review. */ public class TestingLog implements Log { - + /** The captured logging. */ private StringBuilder captured = new StringBuilder(); + /** The log level to capture. */ + private Log.Level level = Log.Level.INFO; /** * Clears the captured buffer @@ -42,60 +44,24 @@ public String getCaptured() { return captured.toString(); } - /** - * Asserts the text was found in the given log entry. - * @param expected the text to find. - */ - public void assertContains(String expected) { - TextUtils.assertContains(expected, captured.toString()); - } - - /** - * Asserts the text was found exactly n times in the log. - * @param times the number of times to find the expected text. - * @param expected the expected test. - */ - public void assertContainsExactly(int times, String expected) { - TextUtils.assertContainsExactly(times, expected, getCaptured()); - } - - /** - * Asserts that the text is not found in the log. - * @param notExpected the text that should not be in the log. - */ - public void assertNotContains(String notExpected) { - TextUtils.assertNotContains(notExpected, captured.toString()); - } - - - /** - * Asserts that a regular expression is found in the log. - * @param pattern the regular expression to search for. - */ - public void assertContainsPattern(String pattern) { - TextUtils.assertPatternInTarget(pattern, captured.toString()); - } - - /** - * Asserts that a regular expression is not found in the log. - * @param pattern the regular expression that should not be in the log. - */ - public void assertNotContainsPattern(String pattern) { - TextUtils.assertPatternNotInTarget(pattern, captured.toString()); + @Override + public Level getLevel() { + return level; } @Override - public Level getLevel() { - return Level.DEBUG; + public void setLevel(Level level) { + this.level = level; } @Override public void log(Level level, String msg) { - captured.append(String.format("%s: %s%n", level, msg)); + if (isEnabled(level)) + captured.append(String.format("%s: %s%n", level, msg)); } /** - * Returns true if the log is empty. + * Determines if the log is empty. * @return {@code true} if the log is empty. */ public boolean isEmpty() { diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TextUtils.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TextUtils.java index e90a30b9c..cb1d498d4 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TextUtils.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TextUtils.java @@ -40,7 +40,9 @@ public class TextUtils { * * @param pattern the pattern to match. * @param target the string to match. + * @deprecated use assertThat(target).containsPattern(pattern) */ + @Deprecated public static void assertPatternInTarget(String pattern, String target) { assertThat(isMatching(pattern, target)).as(() -> format("Target does not match string: %s%n%s", pattern, target)) .isTrue(); @@ -51,7 +53,9 @@ public static void assertPatternInTarget(String pattern, String target) { * * @param pattern the pattern to match. * @param target the string to match. + * @deprecated use assertThat(target).dosNotContainPattern(pattern) */ + @Deprecated public static void assertPatternNotInTarget(String pattern, String target) { assertThat(isMatching(pattern, target)).as(() -> format("Target matches the pattern: %s%n%s", pattern, target)) .isFalse(); @@ -63,48 +67,13 @@ public static void assertPatternNotInTarget(String pattern, String target) { * @param pattern the pattern to match. * @param target the string to match. * @return {@code true} if a regular expression pattern is in a string + * @deprecated use assertThat(target).matches(pattern) */ + @Deprecated public static boolean isMatching(final String pattern, final String target) { return Pattern.compile(pattern, Pattern.MULTILINE).matcher(target).find(); } - /** - * Asserts that a string is contained within another string. - * @param find The string to find. - * @param target The string to search. - */ - public static void assertContains(final String find, final String target) { - assertThat(target.contains(find)).as(() -> format("Target does not contain the text: %s%n%s", find, target)) - .isTrue(); - } - - /** - * Asserts that a string is contained exactly a specified number of times within another string. - * @param times The number of times to find the string in the target. - * @param find The string to find. - * @param target The string to search. - */ - public static void assertContainsExactly(int times, String find, String target) { - String t = target; - for (int i = 0; i < times; i++) { - assertThat(t.contains(find)).as(() -> format("Target does not contain %s copies of %s%n%s", times, find, target)) - .isTrue(); - t = t.substring(t.indexOf(find) + find.length()); - } - assertThat(t.contains(find)).as(() -> format("Target contains more than %s copies of %s%n%s", times, find, target)) - .isFalse(); - } - - /** - * Asserts that a string is not contained within another string. - * @param find The string to find. - * @param target The string to search. - */ - public static void assertNotContains(final String find, final String target) { - assertThat(target.contains(find)).as(() -> format("Target contains the text: %s%n%s", find , target)) - .isFalse(); - } - /** * Read given file as UTF-8. * @param f File to read from. diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java index 7f53c9a61..346b2014c 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java @@ -34,6 +34,7 @@ import java.util.List; import java.util.Map; +import javax.xml.namespace.QName; import javax.xml.parsers.ParserConfigurationException; import javax.xml.parsers.SAXParserFactory; import javax.xml.transform.OutputKeys; @@ -44,11 +45,13 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import org.apache.rat.report.xml.writer.XmlWriter; import org.apache.rat.utils.DefaultLog; import org.apache.rat.utils.StandardXmlFactory; +import org.opentest4j.AssertionFailedError; import org.w3c.dom.Document; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; @@ -57,6 +60,9 @@ import org.xml.sax.SAXException; import org.xml.sax.XMLReader; +/** + * Utilities to help test XML doucments/ + */ public final class XmlUtils { /** * Private constructor, to prevent accidental instantiation. @@ -65,6 +71,12 @@ private XmlUtils() { // Does nothing } + /** + * Construct a safe XML reader. + * @return an XML reader. + * @throws SAXException on sax exception + * @throws ParserConfigurationException on parser configuration exception + */ public static XMLReader newXMLReader() throws SAXException, ParserConfigurationException { final SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setValidating(false); @@ -72,14 +84,29 @@ public static XMLReader newXMLReader() throws SAXException, ParserConfigurationE return spf.newSAXParser().getXMLReader(); } + /** + * Determines if the document string is wellformed. + * @param string the document string to check. + * @return {@code true} if the document is wellformed, {@code false} otherwise. + */ public static boolean isWellFormedXml(final String string) { return isWellFormedXml(new InputSource(new StringReader(string))); } + /** + * Determines if the document in the input stream is wellformed. + * @param in the input stream containing the document. + * @return {@code true} if the document is wellformed, {@code false} otherwise. + */ public static boolean isWellFormedXml(final InputStream in) { return isWellFormedXml(new InputSource(in)); } + /** + * Determines if the document in the input source is wellformed. + * @param isource the input source containing the document. + * @return {@code true} if the document is wellformed, {@code false} otherwise. + */ public static boolean isWellFormedXml(final InputSource isource) { try { newXMLReader().parse(isource); @@ -92,15 +119,39 @@ public static boolean isWellFormedXml(final InputSource isource) { } } + /** + * Gets a Nodelist from an xpath string. + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + * @return the NodeList of nodes that match the xpath. + * @throws XPathExpressionException on error. + */ public static NodeList getNodeList(Object source, XPath xPath, String xpath) throws XPathExpressionException { return (NodeList) xPath.compile(xpath).evaluate(source, XPathConstants.NODESET); } + /** + * Determines if an xpath identified an node in the source + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + * @return {@code true} if the document is contains the node identified by the xpath statement, {@code false} otherwise. + * @throws XPathExpressionException on error. + */ public static boolean isPresent(Object source, XPath xPath, String xpath) throws XPathExpressionException { Object node = xPath.compile(xpath).evaluate(source, XPathConstants.NODE); return node != null; } + /** + * Gets a List of Nodes from an xpath string. + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + * @return the list of nodes that match the xpath. + * @throws XPathExpressionException on error. + */ public static List getNodes(Object source, XPath xPath, String xpath) throws XPathExpressionException { NodeList nodeList = (NodeList) xPath.compile(xpath).evaluate(source, XPathConstants.NODESET); List result = new ArrayList<>(); @@ -110,12 +161,26 @@ public static List getNodes(Object source, XPath xPath, String xpath) thro return result; } + /** + * Gets a node identified by an xpath. + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + * @return the identified Node. + * @throws XPathExpressionException on error. + * @throws AssertionFailedError if more than one node is found. + */ public static Node getNode(Object source, XPath xPath, String xpath) throws XPathExpressionException { NodeList nodeList = getNodeList(source, xPath, xpath); assertEquals(1, nodeList.getLength(), "Could not find exactly one" + xpath); return nodeList.item(0); } + /** + * Prints the specifide NodeList as a string representation of its contents. + * @param nodeList the Nodelist to pring. + * @return the String that contains the textual representation of the NodeList nodes. + */ public static String printNodeList(NodeList nodeList) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < nodeList.getLength(); i++) { @@ -143,6 +208,13 @@ public static Document toDom(final InputStream inputStream) return StandardXmlFactory.documentBuilder().parse(inputStream); } + /** + * Write a boolean attribute ot an XML writer. + * @param writer the writer to write to. + * @param name the name of the attribute + * @param booleanValue the boolean value. + * @throws IOException on write error. + */ public static void writeAttribute(final XmlWriter writer, final String name, final boolean booleanValue) throws IOException { final String value = Boolean.toString(booleanValue); @@ -150,8 +222,8 @@ public static void writeAttribute(final XmlWriter writer, final String name, fin } /** - * Print the properties and XML document to the output stream - * + * Print the XML document to the output stream + * * @param out the OutputStream to print the document to. * @param document The XML DOM document to print */ @@ -173,6 +245,15 @@ public static void printDocument(OutputStream out, Document document) { } } + /** + * Get an attribute from an Xpath statement + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + * @param attribute attribute to retrieve from the node specified by the xpath statement. + * @return the string value of the attribute. + * @throws XPathExpressionException on error + */ public static String getAttribute(Object source, XPath xPath, String xpath, String attribute) throws XPathExpressionException { Node node = XmlUtils.getNode(source, xPath, xpath); NamedNodeMap attr = node.getAttributes(); @@ -189,10 +270,27 @@ public static Map mapOf(String... parts) { return map; } - public static void assertAttributes(Object source, XPath xPath, String xpath, String... mapValues) throws XPathExpressionException { - assertAttributes(source, xPath, xpath, mapOf(mapValues)); + /** + * Use {@link #assertAttributes(Object, XPath, String, Map)}. + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + * @param values a decomposed map of values. + * @throws XPathExpressionException + */ + @Deprecated + public static void assertAttributes(Object source, XPath xPath, String xpath, String... values) throws XPathExpressionException { + assertAttributes(source, xPath, xpath, mapOf(values)); } + /** + * Assert that attributes are set on a node. + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + * @param attributes a map of attribute names to values. + * @throws XPathExpressionException on error. + */ public static void assertAttributes(Object source, XPath xPath, String xpath, Map attributes) throws XPathExpressionException { Node node = XmlUtils.getNode(source, xPath, xpath); NamedNodeMap attr = node.getAttributes(); @@ -203,18 +301,44 @@ public static void assertAttributes(Object source, XPath xPath, String xpath, Ma } } + /** + * Assert that an xpath is present in the document. + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + */ public static void assertIsPresent(Object source, XPath xPath, String xpath) throws XPathExpressionException { assertThat(isPresent(source, xPath, xpath)).as("Presence of " + xpath).isTrue(); } + /** + * Assert that an xpath is not present in the document. + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + */ public static void assertIsNotPresent(Object source, XPath xPath, String xpath) throws XPathExpressionException { assertThat(isPresent(source, xPath, xpath)).as("Non-presence of " + xpath).isFalse(); } + /** + * Assert that a named xpath is present in the document. + * @param identifier the name of the object. + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + */ public static void assertIsPresent(String identifier, Object source, XPath xPath, String xpath) throws XPathExpressionException { assertThat(isPresent(source, xPath, xpath)).as(identifier + ": Presence of " + xpath).isTrue(); } + /** + * Assert that a named xpath is not present in the document. + * @param identifier the name of the object. + * @param source the context for the xpath statement to be evaluated in. See {@link XPathExpression#evaluate(Object, QName)}. + * @param xPath The XPath object to compile the statement with. + * @param xpath the Xpath statement to compile. + */ public static void assertIsNotPresent(String identifier, Object source, XPath xPath, String xpath) throws XPathExpressionException { assertThat(isPresent(source, xPath, xpath)).as(identifier + ": Non-presence of " + xpath).isFalse(); } diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/data/AbstractTestDataProvider.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/data/AbstractTestDataProvider.java new file mode 100644 index 000000000..08957d73d --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/data/AbstractTestDataProvider.java @@ -0,0 +1,366 @@ +/* + * 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.rat.testhelpers.data; + + +import com.google.common.collect.ImmutableList; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.TreeMap; +import java.util.TreeSet; +import java.util.stream.Stream; +import org.apache.commons.cli.Option; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.rat.OptionCollectionParser; +import org.apache.rat.commandline.Arg; +import org.apache.rat.ui.UIOptionCollection; +import org.apache.rat.ui.ArgumentTracker; +import org.apache.rat.utils.DefaultLog; + +/** + * Generates a list of TestData to test an implementatin. + * The tests work by creating a Path Consumer to construct a directory under the test base directory and creating files and/or + * directories within that directory. A test validator is created to validate the expected results of the operation and a {@link TestData} + * object is created for each test. + * + * Each {@code TestData} represents a single test of a command line option or set of options. * + * + * Use of this class ensures consistent testing across the UIs. + */ +public abstract class AbstractTestDataProvider { + + /** The list of exclude args */ + static final String[] EXCLUDE_ARGS = {"*.foo", "%regex[[A-Z]\\.bar]", "justbaz"}; + /** the list of include args */ + static final String[] INCLUDE_ARGS = {"B.bar", "justbaz"}; + // Sonar suggests List.of(), but we need an Immutable list. + public static final ImmutableList> NO_OPTIONS = ImmutableList.of(ImmutablePair.nullPair()); // NOSONAR + + /** + * Generates a map of TestData indexed by the testName + * @param optionCollection the collection of options for the UI under test. + * @return the map of testName to Test Data. + */ + public final Map getOptionTestMap(final UIOptionCollection optionCollection) { + Map map = new TreeMap<>(); + for (TestData test : getOptionTests(optionCollection)) { + map.put(test.getTestName(), test); + } + return map; + } + + /** + * Generates a list of test data for Option testing. + * This is different from UI testing as this is to test + * that the command line is properly parsed into a configuration. + * @param optionCollection the collection of options for the UI under test. + * @return a set of TestData for the tests. + */ + public final Set getOptionTests(final UIOptionCollection optionCollection) { + // the optionCollection establishes any changes to the Arg values. + List