From b3e46a18908e2f0eaafafa223e7485cab047af50 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Tue, 9 Jun 2026 14:45:38 +0100 Subject: [PATCH 01/36] fix DocumentName issues --- .../java/org/apache/rat/document/DocumentName.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java index c6cc55f22..ca6736599 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java +++ b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java @@ -625,6 +625,16 @@ private int compareData(final DocumentName.FSInfoData otherData) { return result; } + /** + * Creates a path separated by the directory separator. + * Starting with an empty string will cause the directory separateor to appear at the beginning. + * @param segments the segments that make up the path. + * @return the path string. + */ + public String mkPath(final String... segments) { + return String.join(dirSeparator(), segments); + } + @Override public int compareTo(final FSInfo other) { int result = this.name.compareToIgnoreCase(other.name); From 51064da30a508a156958ecca27b84838c48cf117 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Tue, 16 Jun 2026 16:00:39 +0100 Subject: [PATCH 02/36] checkpoint --- .../ReportTest/RAT_406/src/dojo/dojo2.jav | 7 +++ .../AbstractConfigurationOptionsProvider.java | 47 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 apache-rat-core/src/it/resources/ReportTest/RAT_406/src/dojo/dojo2.jav diff --git a/apache-rat-core/src/it/resources/ReportTest/RAT_406/src/dojo/dojo2.jav b/apache-rat-core/src/it/resources/ReportTest/RAT_406/src/dojo/dojo2.jav new file mode 100644 index 000000000..f832e15d6 --- /dev/null +++ b/apache-rat-core/src/it/resources/ReportTest/RAT_406/src/dojo/dojo2.jav @@ -0,0 +1,7 @@ +/** + * DOJO flag + http://dojotoolkit.org/community/licensing.shtml + */ +interface dojo2 { + +} 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 5d34d80a8..0ed4694c1 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 @@ -552,6 +552,53 @@ Licensed to the Apache Software Foundation (ASF) under one or more return xmlPath.toString(); } + private String writeConfigXML(String name) { + String licenseText = """ + 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."""; + String capName = WordUtils.capitalize(name); + String upperName = name.toUpperCase(Locale.ROOT); + + Path xmlPath = OptionCollectionTest.getTestPath().resolve(".rat/" + capName + ".xml"); + File f = xmlPath.toFile(); + try { + FileUtils.forceMkdir(f.getParentFile()); + try (FileWriter writer = new FileWriter(f); + XmlWriter xmlWriter = new XmlWriter(writer)) { + + xmlWriter.startDocument() + .comment(licenseText) + .openElement("rat-config") + .openElement("families") + .openElement("family") + .attribute("id", upperName) + .attribute("name", "from " + capName + ".xml") + .closeElement("families") + .openElement("licenses") + .openElement("license") + .attribute("family", upperName) + .openElement("text") + .content(name) + .closeElement("rat-config"); + } + } catch (IOException e) { + throw new RuntimeException(e); + } + return xmlPath.toString(); + } + private void configTest(final Option option) { String[] args = {writeConfigXML("one"), writeConfigXML("two")}; Pair arg1 = ImmutablePair.of(option, args); From 805b4230a4fd9b8530d253841544afe569bf8150 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Thu, 18 Jun 2026 13:49:48 +0100 Subject: [PATCH 03/36] Fixed several parsing errors in DocumentName.Builder Add testing Expanded testing to include multiple file system types Fix recursion issue in DocumentName equals and compareTo Additional migration to assertj Changed File options to return DocumentName instances. Cleaned up Sonar review issues --- .../ReportTest/RAT_406/src/dojo/dojo2.jav | 7 ---- .../org/apache/rat/document/DocumentName.java | 37 +++++++++++++++++++ .../rat/commandline/FileConverterTest.java | 1 + .../AbstractConfigurationOptionsProvider.java | 2 +- 4 files changed, 39 insertions(+), 8 deletions(-) delete mode 100644 apache-rat-core/src/it/resources/ReportTest/RAT_406/src/dojo/dojo2.jav diff --git a/apache-rat-core/src/it/resources/ReportTest/RAT_406/src/dojo/dojo2.jav b/apache-rat-core/src/it/resources/ReportTest/RAT_406/src/dojo/dojo2.jav deleted file mode 100644 index f832e15d6..000000000 --- a/apache-rat-core/src/it/resources/ReportTest/RAT_406/src/dojo/dojo2.jav +++ /dev/null @@ -1,7 +0,0 @@ -/** - * DOJO flag - http://dojotoolkit.org/community/licensing.shtml - */ -interface dojo2 { - -} diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java index ca6736599..c86106920 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java +++ b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java @@ -635,6 +635,43 @@ public String mkPath(final String... segments) { return String.join(dirSeparator(), segments); } + /** + * Determines if the candidate string starts with a root or directory separator as defined in this + * FSInfo. + * @param candidate the candidate string to test. + * @return {@code true} if the candidate starts with a root or a directory separator. + */ + public boolean startsWithRootOrSeparator(final String candidate) { + if (candidate == null) { + return false; + } + String target = candidate.trim(); + if (StringUtils.isBlank(target)) { + return false; + } + for (String root : roots()) { + if (target.startsWith(root)) { + return true; + } + } + return target.startsWith(dirSeparator()); + } + + private int compareData(final DocumentName.FSInfoData otherData) { + int result = Boolean.compare(this.data.isCaseSensitive, otherData.isCaseSensitive); + if (result == 0) { + result = this.data.separator.compareTo(otherData.separator); + if (result == 0) { + if (new HashSet<>(this.data.roots).containsAll(otherData.roots)) { + result = new HashSet<>(otherData.roots).containsAll(this.data.roots) ? 0 : 1; + } else { + result = -1; + } + } + } + return result; + } + @Override public int compareTo(final FSInfo other) { int result = this.name.compareToIgnoreCase(other.name); diff --git a/apache-rat-core/src/test/java/org/apache/rat/commandline/FileConverterTest.java b/apache-rat-core/src/test/java/org/apache/rat/commandline/FileConverterTest.java index f1922638a..8213bbdb5 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/commandline/FileConverterTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/commandline/FileConverterTest.java @@ -78,6 +78,7 @@ static List applyTestData() { String root = fsInfo.roots()[1]; lst.add(Arguments.of(fsInfo, root + "foo/bar.txt", underTest, root + String.join(fsInfo.dirSeparator(), "foo", "bar.txt"))); lst.add(Arguments.of(fsInfo, root + "foo\\bar.txt", underTest, root + String.join(fsInfo.dirSeparator(), "foo", "bar.txt"))); + } } return lst; 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 0ed4694c1..df5888a88 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 @@ -571,7 +571,7 @@ Licensed to the Apache Software Foundation (ASF) under one or more String capName = WordUtils.capitalize(name); String upperName = name.toUpperCase(Locale.ROOT); - Path xmlPath = OptionCollectionTest.getTestPath().resolve(".rat/" + capName + ".xml"); + Path xmlPath = this.baseDir.toPath().resolve(".rat/" + capName + ".xml"); File f = xmlPath.toFile(); try { FileUtils.forceMkdir(f.getParentFile()); From 57124fc54470fafa21299884598a9b7392552581 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sun, 10 May 2026 10:23:40 +0100 Subject: [PATCH 04/36] initial changes --- .../java/org/apache/rat/utils}/FileUtils.java | 23 +- .../apache/rat/ReporterOptionsProvider.java | 2 +- .../org/apache/rat/ReporterOptionsTest.java | 2 +- .../rat/test/AbstractOptionsProvider.java | 2 +- .../data/AbstractTestDataProvider.java | 200 +++++++++++++++ .../apache/rat/testhelpers/data/TestData.java | 242 ++++++++++++++++++ .../rat/testhelpers/data/ValidatorData.java | 113 ++++++++ 7 files changed, 571 insertions(+), 13 deletions(-) rename apache-rat-core/src/{test/java/org/apache/rat/testhelpers => main/java/org/apache/rat/utils}/FileUtils.java (81%) create mode 100644 apache-rat-core/src/test/java/org/apache/rat/testhelpers/data/AbstractTestDataProvider.java create mode 100644 apache-rat-core/src/test/java/org/apache/rat/testhelpers/data/TestData.java create mode 100644 apache-rat-core/src/test/java/org/apache/rat/testhelpers/data/ValidatorData.java 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 81% 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..50da3eccd 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,7 +16,7 @@ * 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; @@ -25,15 +25,17 @@ import java.util.Arrays; import java.util.Collections; -import static org.assertj.core.api.Fail.fail; -public class FileUtils { +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,7 +43,7 @@ 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 { @@ -62,15 +64,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 +85,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 +95,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/test/java/org/apache/rat/ReporterOptionsProvider.java b/apache-rat-core/src/test/java/org/apache/rat/ReporterOptionsProvider.java index 0ef6f019c..b6167cbf7 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 @@ -54,7 +54,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; 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 ccb82f3c6..2694b4c91 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 @@ -27,7 +27,7 @@ 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; 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..1f55d2ba0 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 @@ -170,7 +170,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/data/AbstractTestDataProvider.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/data/AbstractTestDataProvider.java new file mode 100644 index 000000000..94b23a358 --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/data/AbstractTestDataProvider.java @@ -0,0 +1,200 @@ +/* + * 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.AbstractOptionCollection; +import org.apache.rat.ui.ArgumentTracker; +import org.apache.rat.utils.DefaultLog; + +/** + * Generates a list of TestData for executing the Report. + * Use of this interface ensures consistent testing across the UIs. Each method + * tests an Option from {@link OptionCollectionParser} that must be implemented in the UI. + * This differes from the {@link OptionTestDataProvider} in that tests from this set + * expect that execptions will be thrown during execution, and tests the xml output. + */ +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"}; + public final ImmutableList> NO_OPTIONS = ImmutableList.of(ImmutablePair.nullPair()); + + /** + * 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 AbstractOptionCollection 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 AbstractOptionCollection optionCollection) { + // the optionCollection establishes any changes to the Arg values. + List