This is an automated email from the ASF dual-hosted git repository. Claudenw pushed a commit to branch fix-DocumentName-issues in repository https://gitbox.apache.org/repos/asf/creadur-rat.git
commit 748f4baed34839482ede22da18b957d7484a4862 Author: Claude Warren <[email protected]> AuthorDate: Tue Jun 9 14:45:38 2026 +0100 fix DocumentName issues --- .../org/apache/rat/document/ArchiveEntryName.java | 29 +- .../java/org/apache/rat/document/DocumentName.java | 138 ++++++-- .../rat/document/DocumentNameBuilderTest.java | 318 +++++++++++------- .../org/apache/rat/document/DocumentNameTest.java | 368 ++++++++------------- 4 files changed, 467 insertions(+), 386 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryName.java b/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryName.java index 13b4668e..2a6d4739 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryName.java +++ b/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryName.java @@ -23,18 +23,33 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.Collections; +/** + * The DocumentName for an ArchiveEntry. + */ public class ArchiveEntryName extends DocumentName { /** The name of the document that contains this entry. */ private final DocumentName archiveFileName; + /** + * Sets the builder so that a propery DocumentName is constructed. + * @param archiveFileName the archvie file DocumentName + * @param archiveEntryName the entry name + * @return the DocumentName.Builder for the archive entry. + */ private static DocumentName.Builder prepareBuilder(final DocumentName archiveFileName, final String archiveEntryName) { - String root = archiveFileName.getName() + "#"; + String root = archiveFileName.getName() + "#/"; FSInfo fsInfo = new FSInfo("archiveEntry", "/", true, Collections.singletonList(root)); return DocumentName.builder(fsInfo) .setRoot(root) - .setBaseName(root + "/") + .setBaseName("/") .setName(archiveEntryName); } + + /** + * Constucts an archive file name from an archive file document name and an entry name. + * @param archiveFileName the archive file document name. + * @param archiveEntryName the archive entry name. + */ public ArchiveEntryName(final DocumentName archiveFileName, final String archiveEntryName) { super(prepareBuilder(archiveFileName, archiveEntryName)); this.archiveFileName = archiveFileName; @@ -71,14 +86,4 @@ public class ArchiveEntryName extends DocumentName { superLocal = superLocal.substring(superLocal.lastIndexOf("#") + 1); return archiveFileName.localized(dirSeparator) + "#" + superLocal; } - - @Override - public boolean equals(final Object other) { - return super.equals(other); - } - - @Override - public int hashCode() { - return super.hashCode(); - } } 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 c2c0510e..7700ca04 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 @@ -45,8 +45,8 @@ import org.apache.commons.lang3.tuple.Pair; * The name for a document. The {@code DocumentName} is an immutable structure that handles all the intricacies of file * naming on various operating systems. DocumentNames have several components: * <ul> - * <li>{@code root} - where in the file system the name starts (e.g C: on windows). May be empty but not null.</li> - * <li>{@code dirSeparator} - the separator between name segments (e.g. "\\" on windows, "/" on linux). May not be + * <li>{@code root} - where in the file system the name starts (e.g C:\ on Microsoft Windows). May be empty but not null.</li> + * <li>{@code dirSeparator} - the separator between name segments (e.g. "\" on MicroSoft Windows, "/" on linux). May not be * empty or null.</li> * <li>{@code name} - the name of the file relative to the {@code root}. May not be null. Does NOT begin with a {@code dirSeparator}</li> * <li>{@code baseName} - the name of a directory or file from which this file is reported. A DocumentName with a @@ -65,7 +65,7 @@ public class DocumentName implements Comparable<DocumentName> { private final DocumentName baseName; /** The file system info for this document. */ private final FSInfo fsInfo; - /** The root for the DocumentName. May be empty but not null. */ + /** The root for the DocumentName. May be empty but not null. Must be one of the roots in fsInfo*/ private final String root; /** @@ -126,7 +126,7 @@ public class DocumentName implements Comparable<DocumentName> { } /** - * Creates a file from the document name. + * Creates a file from the fully qualified document name. * @return a new File object. */ public File asFile() { @@ -134,7 +134,8 @@ public class DocumentName implements Comparable<DocumentName> { } /** - * Creates a path from the document name. + * Creates a path from the document name. This method uses the fullyqualified name without the root. + * this results in a relative file name from the root. * @return a new Path object. */ public Path asPath() { @@ -144,9 +145,23 @@ public class DocumentName implements Comparable<DocumentName> { /** * Creates a new DocumentName by adding the child to the current name. * Resulting documentName will have the same base name. + * Directory separator is normalized to the directory separator for this file system. + * If the child string: + * <dl> + * <dt>Is blank</dt> + * <dd>This DocumentName is returned.</dd> + * <dt>Starts with the file system root</dt> + * <dd>The root The root must match the root of this DocumentName and the directory structure + * must start with the directory structure of the basename for this DocuemntName.</dd> + * <dt>Starts with the directory separator character<dt> + * <dd>Result will be a tree starting at the directory specified by the basename.</dd> + * <dt>Does not start with a directory separator character</dt> + * <dd>Result will be a tree starting at the directory specified by this DocumentName</dd> + * </dl> * @param child the child to add (must use directory separator from this document name). * @return the new document name with the same {@link #baseName}, directory sensitivity and case sensitivity as * this one. + * @throws IllegalArgumentException if the child specifies a different root from this document name. */ public DocumentName resolve(final String child) { if (StringUtils.isBlank(child)) { @@ -156,8 +171,25 @@ public class DocumentName implements Comparable<DocumentName> { String pattern = separator.equals("/") ? child.replace('\\', '/') : child.replace('/', '\\'); + Optional<String> root = fsInfo.rootFor(child); + if (root.isPresent()) { + if (!root.get().equals(getRoot())) { + throw new IllegalArgumentException(String.format("%s does not start with %s", pattern, getName())); + } + if (!getRoot().equals(separator)) { + // we have something like C:\ as the root so convert the pattern to start with the separator. + pattern = separator + pattern.substring(getRoot().length()); + if (pattern.startsWith(baseName.name)) { + pattern = pattern.substring(baseName.name.length()); + } + } + } + + // patterns with separators either start with the name of this document plus a relative + // name, or are just directory off the baseName. In either case the name is correct. + // so just handle the relative case. if (!pattern.startsWith(separator)) { - pattern = name + separator + pattern; + pattern = name + separator + pattern; } return new Builder(this).setName(fsInfo.normalize(pattern)).build(); @@ -168,7 +200,7 @@ public class DocumentName implements Comparable<DocumentName> { * @return the fully qualified name of the document. */ public String getName() { - return root + fsInfo.dirSeparator() + name; + return root + name; } /** @@ -203,6 +235,14 @@ public class DocumentName implements Comparable<DocumentName> { return fsInfo.dirSeparator(); } + /** + * Returns the FSInfo for this document name. + * @return the FSInfo for this document name. + */ + public FSInfo fsInfo() { + return fsInfo; + } + /** * Determines if the candidate starts with the root or separator strings. * @param candidate the candidate to check. If blank method will return {@code false}. @@ -287,19 +327,30 @@ public class DocumentName implements Comparable<DocumentName> { @Override public int compareTo(final DocumentName other) { - return CompareToBuilder.reflectionCompare(this, other); + return new CompareToBuilder() + .append(this.root, other.root) + .append(this.getBaseName(), other.getBaseName()) + .append(this.getName(), other.getName()).build(); } @Override - public boolean equals(final Object other) { - return EqualsBuilder.reflectionEquals(this, other); + public final boolean equals(final Object other) { + if (other instanceof DocumentName otherDocumentName) { + return compareTo(otherDocumentName) == 0; + } + return false; } @Override - public int hashCode() { - return HashCodeBuilder.reflectionHashCode(this); + public final int hashCode() { + return new HashCodeBuilder().append(root).append(getBaseName()).append(getName()).toHashCode(); } + /** + * The File System Info Data for a DocumentName. + * Use to preserve data across DocumentNames without having to + * reconstruct the data for each DocumentName. + */ private static final class FSInfoData { /** The case sensitivity flag */ private final boolean isCaseSensitive; @@ -468,6 +519,14 @@ public class DocumentName implements Comparable<DocumentName> { return Optional.empty(); } + /** + * Gets the array of roots for this file system. + * @return an array of roots for this file system. + */ + public String[] roots() { + return data.roots.toArray(new String[0]); + } + /** * Tokenizes the string based on the directory separator of this DocumentName. * @param source the source to tokenize. @@ -486,7 +545,9 @@ public class DocumentName implements Comparable<DocumentName> { if (StringUtils.isBlank(pattern)) { return ""; } - List<String> parts = new ArrayList<>(Arrays.asList(tokenize(pattern))); + String adjustedPattern = dirSeparator().equals("/") ? pattern.replace("\\", "/") : pattern.replace("/", "\\"); + + List<String> parts = new ArrayList<>(Arrays.asList(tokenize(adjustedPattern))); for (int i = 0; i < parts.size(); i++) { String part = parts.get(i); if (part.equals("..")) { @@ -502,6 +563,16 @@ public class DocumentName implements Comparable<DocumentName> { return parts.stream().filter(Objects::nonNull).collect(Collectors.joining(dirSeparator())); } + /** + * 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) { return CompareToBuilder.reflectionCompare(this, other); @@ -538,7 +609,7 @@ public class DocumentName implements Comparable<DocumentName> { */ private Builder(final FSInfo fsInfo) { this.fsInfo = fsInfo; - root = ""; + root = fsInfo.data.roots.get(0); } /** @@ -625,12 +696,6 @@ public class DocumentName implements Comparable<DocumentName> { this.root = pair.getLeft(); } this.name = fsInfo.normalize(pair.getRight()); - if (this.baseName != null && !baseName.name.isEmpty()) { - if (!this.name.startsWith(baseName.name)) { - this.name = this.name.isEmpty() ? baseName.name : - baseName.name + fsInfo.dirSeparator() + this.name; - } - } return this; } @@ -644,16 +709,15 @@ public class DocumentName implements Comparable<DocumentName> { */ Pair<String, String> splitRoot(final String name) { String workingName = name; - Optional<String> maybeRoot = fsInfo.rootFor(name); - String root = maybeRoot.orElse(""); + String root = fsInfo.rootFor(name).orElse(""); if (!root.isEmpty()) { if (workingName.startsWith(root)) { workingName = workingName.substring(root.length()); - if (!workingName.startsWith(fsInfo.dirSeparator())) { - if (root.endsWith(fsInfo.dirSeparator())) { - root = root.substring(0, root.length() - fsInfo.dirSeparator().length()); - } - } +// if (!workingName.startsWith(fsInfo.dirSeparator())) { +// if (root.endsWith(fsInfo.dirSeparator())) { +// root = root.substring(0, root.length() - fsInfo.dirSeparator().length()); +// } +// } } } return ImmutablePair.of(root, workingName); @@ -751,6 +815,26 @@ public class DocumentName implements Comparable<DocumentName> { */ public DocumentName build() { verify(); + if (this.baseName != null) { + if (!this.name.startsWith(baseName.name)) { + this.name = this.name.isEmpty() ? baseName.name : + baseName.name + fsInfo.dirSeparator() + this.name; + } + if (!this.baseName.getRoot().equals(root)) { + Builder builder = new Builder(baseName).setRoot(root); + if (baseName.baseName != null && baseName.baseName != baseName) { + builder.setBaseName(baseName.baseName); + } else { + builder.baseName = null; + builder.sameNameFlag = true; + } + this.baseName = builder.build(); + } + } else { + if (this.name.startsWith(root)) { + this.name = this.name.substring(root.length()); + } + } return new DocumentName(this); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameBuilderTest.java b/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameBuilderTest.java index 0e0f0d1f..644fce5a 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameBuilderTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameBuilderTest.java @@ -19,23 +19,38 @@ package org.apache.rat.document; import java.io.File; -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Stream; + +import org.apache.commons.lang3.tuple.Pair; +import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; -import org.junit.jupiter.params.provider.Arguments; -import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.FieldSource; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.apache.rat.document.FSInfoTest.WINDOWS; +/** + * Tests the DcoumentName.Builder class + */ public class DocumentNameBuilderTest { - @ParameterizedTest(name="{0}") - @MethodSource("buildTestData") - void buildTest(String testName, DocumentName documentName, String name, String shortName, String baseName, String root, + private static final DocumentName.FSInfo[] TEST_SUITE = FSInfoTest.TEST_SUITE; + + /** + * Validates the data in a document name matches expected data. + * @param documentName the document name to check + * @param name the expected fully qualified name. + * @param shortName the name for the last segment of the name. + * @param baseName the name of the base document. + * @param root the root the document is in. + * @param directorySeparator the expected directory separator. + * @param isCaseSensitive the expected case sensitivity. + * @param localized the default localized name (e.g. path and file name from base name). + * @param localizedArg the localized name with directory separator set to '+' + */ + void assertDocumentName(DocumentName documentName, String name, String shortName, String baseName, String root, String directorySeparator, Boolean isCaseSensitive, String localized, String localizedArg) { assertThat(documentName.getName()).as("Invalid name").isEqualTo(name); assertThat(documentName.getShortName()).as("Invalid short name").isEqualTo(shortName); @@ -48,120 +63,189 @@ public class DocumentNameBuilderTest { assertThat(documentName.isCaseSensitive()).as("Invalid case sensitivity").isFalse(); } assertThat(documentName.localized()).as("Invalid localized ").isEqualTo(localized); - final String sep = documentName.getDirectorySeparator().equals("/") ? "\\" : "/"; - assertThat(documentName.localized(sep)).as(() -> String.format("Invalid localized('%s')", sep)).isEqualTo(localizedArg); + assertThat(documentName.localized("+")).as("Invalid localized('+')").isEqualTo(localizedArg); } - static Stream<Arguments> buildTestData() { - List<Arguments> lst = new ArrayList<>(); - - // - String testName = "windows\\foo direct"; - DocumentName documentName = DocumentName.builder(WINDOWS).setName("C:\\windows\\foo").setBaseName("C:\\windows").build(); - lst.add(Arguments.of( testName, documentName, "C:\\windows\\foo", "foo", "C:\\windows", "C:", "\\", false, - "\\foo", "/foo")); - DocumentName baseName = documentName; - - // - testName = "builder(docName)"; - documentName = DocumentName.builder(baseName).build(); - lst.add(Arguments.of( testName, documentName, "C:\\windows\\foo", "foo", "C:\\windows", "C:", "\\", false, - "\\foo", "/foo")); - - // - testName = "windows\\foo\\bar by resolve"; - documentName = baseName.resolve("bar"); - lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\bar", "bar", "C:\\windows", "C:", "\\", false, - "\\foo\\bar", "/foo/bar")); - - // - testName = "windows\\foo\\direct by basename"; - documentName = DocumentName.builder(baseName).setName("windows\\foo\\direct").build(); - lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\direct", "direct", "C:\\windows", "C:", "\\", false, - "\\foo\\direct", "/foo/direct")); - - // - testName = "windows\\foo\\bar by file"; - File file = mock(File.class); - File parent = mock(File.class); - when(file.getAbsolutePath()).thenReturn("C:\\windows\\foo\\bar"); - when(file.getParentFile()).thenReturn(parent); - when(file.isDirectory()).thenReturn(false); - when(parent.getAbsolutePath()).thenReturn("C:\\windows\\foo"); - when(parent.isDirectory()).thenReturn(true); - documentName = new DocumentName.Builder(WINDOWS, file).build(); - lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\bar", "bar", "C:\\windows\\foo", "C:", "\\", false, - "\\bar", "/bar")); - - // - testName = "windows\\foo\\bar by directory"; - file = mock(File.class); - parent = mock(File.class); - when(file.getAbsolutePath()).thenReturn("C:\\windows\\foo\\bar"); - when(file.getParentFile()).thenReturn(parent); - when(file.isDirectory()).thenReturn(true); - when(parent.getAbsolutePath()).thenReturn("C:\\windows\\foo"); - when(parent.isDirectory()).thenReturn(true); - documentName = new DocumentName.Builder(WINDOWS, file).build(); - lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\bar", "bar", "C:\\windows\\foo\\bar", "C:", "\\", false, - "\\", "/")); - - // - testName = "windows setRoot"; - documentName = DocumentName.builder(baseName).setRoot("D:").build(); - lst.add(Arguments.of(testName, documentName, "D:\\windows\\foo", "foo", "C:\\windows", "D:", "\\", false, - "D:\\windows\\foo", "D:/windows/foo")); - - testName = "windows setRoot(null)"; - documentName = DocumentName.builder(baseName).setRoot(null).build(); - lst.add(Arguments.of(testName, documentName, "\\windows\\foo", "foo", "C:\\windows", "", "\\", false, - "\\windows\\foo", "/windows/foo")); - - testName = "windows setRoot('')"; - documentName = DocumentName.builder(baseName).setRoot("").build(); - lst.add(Arguments.of(testName, documentName, "\\windows\\foo", "foo", "C:\\windows", "", "\\", false, - "\\windows\\foo", "/windows/foo")); - - // - testName = "windows setName('baz')"; - documentName = DocumentName.builder(baseName).setName("baz").build(); - lst.add(Arguments.of(testName, documentName, "C:\\windows\\baz", "baz", "C:\\windows", "C:", "\\", false, - "\\baz", "/baz")); - - testName = "windows setName((String)null)"; - documentName = DocumentName.builder(baseName).setName((String)null).build(); - lst.add(Arguments.of(testName, documentName, "C:\\windows", "windows", "C:\\windows", "C:", "\\", false, - "\\", "/")); - - testName = "windows setName('')"; - documentName = DocumentName.builder(baseName).setName("").build(); - lst.add(Arguments.of(testName, documentName, "C:\\windows", "windows", "C:\\windows", "C:", "\\", false, - "\\", "/")); - - file = mock(File.class); - parent = mock(File.class); - when(file.getAbsolutePath()).thenReturn("C:\\windows\\foo\\bar"); + /** + * Verifies tha the baseName is not modified when used in the builder. + * Base name is default root + OS name. For example C:\windows, or /unix + * @param fsInfo the file system info for the test. + */ + @ParameterizedTest + @FieldSource("TEST_SUITE") + void baseNamePreserved(DocumentName.FSInfo fsInfo) { + final String root = fsInfo.roots()[0]; + final String baseNameStr = root + fsInfo; + // create a document {os name}/bar. Used to establish basename in builder. + final DocumentName siblingName = DocumentName.builder(fsInfo).setName("bar").setBaseName(fsInfo.toString()).build(); + + // check a relative name does not change base name. + String nameStr = fsInfo.mkPath("foo", "baz"); + DocumentName documentName = DocumentName.builder(siblingName).setName(nameStr).build(); + String expected = root + fsInfo.mkPath(fsInfo.toString(), "foo", "baz"); + assertThat(documentName.getName()).as("relative value").isEqualTo(expected); + assertDocumentName(documentName, expected, "baz", baseNameStr, root, fsInfo.dirSeparator(), fsInfo.isCaseSensitive(), + fsInfo.dirSeparator() + nameStr, "+foo+baz"); + + // check a FQName results in the base name not being changed. + documentName = DocumentName.builder(siblingName).setName(expected).build(); + assertThat(documentName.getName()).as("absolute value").isEqualTo(expected); + assertDocumentName(documentName, expected, "baz", baseNameStr, root, fsInfo.dirSeparator(), fsInfo.isCaseSensitive(), + fsInfo.dirSeparator() + nameStr, "+foo+baz"); + + } + + @ParameterizedTest + @FieldSource("TEST_SUITE") + void documentNameFromFQNameWithBaseName(DocumentName.FSInfo fsInfo) { + final String root = fsInfo.roots()[0]; + final String baseNameStr = root + fsInfo; + String fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + DocumentName documentName = DocumentName.builder(fsInfo).setName(fqName).setBaseName(baseNameStr).build(); + assertDocumentName(documentName, fqName, "foo", baseNameStr, root, fsInfo.dirSeparator(), fsInfo.isCaseSensitive(), + fsInfo.dirSeparator() + "foo", "+foo"); + } + + @ParameterizedTest + @FieldSource("TEST_SUITE") + void noBaseNameThowsException(DocumentName.FSInfo fsInfo) { + final String root = fsInfo.roots()[0]; + String fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + assertThatThrownBy(() -> DocumentName.builder(fsInfo).setName(fqName).build()) + .isInstanceOf(NullPointerException.class) + .hasMessage("Basename must not be null"); + } + + @ParameterizedTest + @FieldSource("TEST_SUITE") + void noNameThowsException(DocumentName.FSInfo fsInfo) { + final String root = fsInfo.roots()[0]; + String fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + assertThatThrownBy(() -> DocumentName.builder(fsInfo).setBaseName(fqName).build()) + .isInstanceOf(NullPointerException.class) + .hasMessage("Name must not be null"); + } + + + @ParameterizedTest + @FieldSource("TEST_SUITE") + void DocumentNameFromDocumentName(DocumentName.FSInfo fsInfo) { + final String root = fsInfo.roots()[0]; + final String baseNameStr = root + fsInfo; + String fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + DocumentName expected = DocumentName.builder(fsInfo).setName(fqName).setBaseName(baseNameStr).build(); + + DocumentName actual = DocumentName.builder(expected).build(); + assertThat(actual).isEqualTo(expected); + + assertDocumentName(actual, fqName, "foo", baseNameStr, root, fsInfo.dirSeparator(), fsInfo.isCaseSensitive(), + fsInfo.dirSeparator() + "foo", "+foo"); + + } + + @ParameterizedTest + @FieldSource("TEST_SUITE") + void builderOnDocumentNameWithNameSharesBaseName(DocumentName.FSInfo fsInfo) { + final String root = fsInfo.roots()[0]; + final String baseNameStr = root + fsInfo; + + String fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + DocumentName firstName = DocumentName.builder(fsInfo).setName(fqName).setBaseName(baseNameStr).build(); + + fqName = root + fsInfo.mkPath(fsInfo.toString(), "bar"); + DocumentName actual = DocumentName.builder(firstName).setName(fqName).setBaseName(baseNameStr).build(); + + assertDocumentName(actual, fqName, "bar", baseNameStr, root, fsInfo.dirSeparator(), fsInfo.isCaseSensitive(), + fsInfo.dirSeparator() + "bar", "+bar"); + } + + @ParameterizedTest + @FieldSource("TEST_SUITE") + void builderOnFile(DocumentName.FSInfo fsInfo) { + final String root = fsInfo.roots()[0]; + final String baseNameStr = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + final String fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo", "bar"); + File file = mock(File.class); + File parent = mock(File.class); + when(file.getAbsolutePath()).thenReturn(fqName); when(file.getParentFile()).thenReturn(parent); when(file.isDirectory()).thenReturn(false); - when(parent.getAbsolutePath()).thenReturn("C:\\windows\\foo"); + when(parent.getAbsolutePath()).thenReturn(baseNameStr); when(parent.isDirectory()).thenReturn(true); - testName = "windows setName(file)"; - documentName = DocumentName.builder(baseName).setName(file).build(); - lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\bar", "bar", "C:\\windows\\foo", "C:", "\\", false, - "\\bar", "/bar")); - - file = mock(File.class); - parent = mock(File.class); - when(file.getAbsolutePath()).thenReturn("C:\\windows\\foo\\bar"); - when(file.getParentFile()).thenReturn(parent); - when(file.isDirectory()).thenReturn(true); - when(parent.getAbsolutePath()).thenReturn("C:\\windows\\foo"); - when(parent.isDirectory()).thenReturn(true); - testName = "windows setName(directory)"; - documentName = DocumentName.builder(baseName).setName(file).build(); - lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\bar", "bar", "C:\\windows\\foo\\bar", "C:", "\\", false, - "\\", "/")); - return lst.stream(); + DocumentName actual = new DocumentName.Builder(fsInfo, file).build(); + + assertDocumentName(actual, fqName, "bar", baseNameStr, root, fsInfo.dirSeparator(), fsInfo.isCaseSensitive(), + fsInfo.dirSeparator() + "bar", "+bar"); + + } + + @Test + void windowRootDifference() { + // verify that setting the root results in the entire DocumentName being re-rooted e.g. including the basename(s). + DocumentName.FSInfo fsInfo = WINDOWS; + String root = fsInfo.roots()[0]; + String baseNameStr = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + String fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo", "bar"); + DocumentName firstName = DocumentName.builder(fsInfo).setName(fqName).setBaseName(baseNameStr).build(); + + root = "D:\\"; + DocumentName actual = DocumentName.builder(firstName).setRoot(root).build(); + + baseNameStr = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo", "bar"); + + assertDocumentName(actual, fqName, "bar", baseNameStr, root, fsInfo.dirSeparator(), fsInfo.isCaseSensitive(), + fsInfo.dirSeparator() + "bar", "+bar"); + + } + + @ParameterizedTest + @FieldSource("TEST_SUITE") + void setRootNull(DocumentName.FSInfo fsInfo) { + String root = fsInfo.roots()[0]; + String baseNameStr = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + String fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo", "bar"); + DocumentName firstName = DocumentName.builder(fsInfo).setName(fqName).setBaseName(baseNameStr).build(); + + // verify setting the root to null results in relative names with a blank root set + root = null; + DocumentName actual = DocumentName.builder(firstName).setRoot(root).build(); + + baseNameStr = fsInfo.mkPath(fsInfo.toString(), "foo"); + fqName = fsInfo.mkPath(fsInfo.toString(), "foo", "bar"); + + assertDocumentName(actual, fqName, "bar", baseNameStr, "", fsInfo.dirSeparator(), fsInfo.isCaseSensitive(), + fsInfo.dirSeparator() + "bar", "+bar"); + + } + + @ParameterizedTest + @FieldSource("TEST_SUITE") + void setRootEmpty(DocumentName.FSInfo fsInfo) { + String root = fsInfo.roots()[0]; + String baseNameStr = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + String fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo", "bar"); + DocumentName firstName = DocumentName.builder(fsInfo).setName(fqName).setBaseName(baseNameStr).build(); + + root = ""; + DocumentName actual = DocumentName.builder(firstName).setRoot(root).build(); + + baseNameStr = root + fsInfo.mkPath(fsInfo.toString(), "foo"); + fqName = root + fsInfo.mkPath(fsInfo.toString(), "foo", "bar"); + + assertDocumentName(actual, fqName, "bar", baseNameStr, root, fsInfo.dirSeparator(), fsInfo.isCaseSensitive(), + fsInfo.dirSeparator() + "bar", "+bar"); + + } + + @ParameterizedTest + @FieldSource("TEST_SUITE") + void splitRootsTest(DocumentName.FSInfo fsInfo) { + String root = fsInfo.roots()[0]; + String path = fsInfo.mkPath("My", "path", "to", "a", "file.txt"); + Pair<String, String> result = DocumentName.builder(fsInfo).splitRoot(root + path); + assertThat(result.getLeft()).isEqualTo(root); + assertThat(result.getRight()).isEqualTo(path); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java b/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java index beeeeca9..f360cc8d 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java @@ -18,79 +18,78 @@ */ package org.apache.rat.document; +import java.io.BufferedReader; import java.io.File; import java.io.FileFilter; +import java.io.FileReader; +import java.io.FileWriter; import java.io.FilenameFilter; import java.io.IOException; -import java.nio.file.FileSystems; +import java.nio.charset.StandardCharsets; import java.nio.file.Path; import java.util.ArrayList; import java.util.Arrays; -import java.util.HashSet; import java.util.List; -import java.util.Set; import java.util.stream.Stream; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.tuple.Pair; import org.apache.rat.config.exclusion.ExclusionUtils; import org.apache.rat.document.DocumentName.FSInfo; -import org.assertj.core.util.Files; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.FieldSource; import org.junit.jupiter.params.provider.MethodSource; -import org.mockito.Mockito; import static org.assertj.core.api.Assertions.assertThat; -import static org.apache.rat.document.FSInfoTest.OSX; -import static org.apache.rat.document.FSInfoTest.UNIX; -import static org.apache.rat.document.FSInfoTest.WINDOWS; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static org.mockito.ArgumentMatchers.any; public class DocumentNameTest { - - public static DocumentName mkName(Path tempDir, FSInfo fsInfo) { - File docFile = mkFile(tempDir.toFile(), fsInfo); - DocumentName result = DocumentName.builder(fsInfo).setName(docFile).build(); - DocumentName mocked = Mockito.spy(result); - - String fn = result.localized(FileSystems.getDefault().getSeparator()); - File file = tempDir.resolve(fn.substring(1)).toFile(); - File mockedFile = mkFile(file, fsInfo); - when(mocked.asFile()).thenReturn(mockedFile); - - assertThat(mocked.asFile()).isEqualTo(mockedFile); - return mocked; - } - - private static File[] listFiles(File file, FSInfo fsInfo) { - File[] fileList = file.listFiles(); - if (fileList == null) { - return fileList; - } - return Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).toArray(File[]::new); + private static final FSInfo[] TEST_SUITE = FSInfoTest.TEST_SUITE; + + /** + * Create a list of mocked files from the specified directory. + * @param directory the native directory to read. + * @param fsInfo the file system to mock the files in. + * @return an array of mocked files in the file system. + */ + private static File[] listFiles(File directory, FSInfo fsInfo) { + File[] fileList = directory.listFiles(); + return fileList == null ? null : Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).toArray(File[]::new); } - private static File[] listFiles(File file, FSInfo fsInfo, FileFilter filter) { - File[] fileList = file.listFiles(); - if (fileList == null) { - return fileList; - } - return Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(filter::accept).toArray(File[]::new); + /** + * Create an array of mocked files from the specified directory then apply applying a file filter. + * @param directory the native directory to read files from. + * @param fsInfo the file system to create the mocked files in. + * @param filter the filter to apply to the mocked files. + * @return the array of mocked files that pass the filter. + */ + private static File[] listFiles(File directory, FSInfo fsInfo, FileFilter filter) { + File[] fileList = directory.listFiles(); + return fileList == null ? null : Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(filter::accept).toArray(File[]::new); } - private static File[] listFiles(File file, FSInfo fsInfo, FilenameFilter filter) { - File[] fileList = file.listFiles(); - if (fileList == null) { - return fileList; - } - return Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(x -> filter.accept(x, x.getName())).toArray(File[]::new); + /** + * Create an array of mocked files from the specified directory then apply applying a file filter. + * @param directory the native directory to read files from. + * @param fsInfo the file system to create the mocked files in. + * @param filter the filter to apply to the mocked files. + * @return the array of mocked files that pass the filter. + */ + private static File[] listFiles(File directory, FSInfo fsInfo, FilenameFilter filter) { + File[] fileList = directory.listFiles(); + return fileList == null ? null : Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(x -> filter.accept(x, x.getName())).toArray(File[]::new); } + /** + * Creates a mocked file on the specified file system with the + * @param file the name of the native file. + * @param fsInfo the file system to mock the file in. + * @return the mocked file in the specified file system + */ public static File mkFile(final File file, final FSInfo fsInfo) { File mockedFile = mock(File.class); when(mockedFile.listFiles()).thenAnswer( env -> listFiles(file, fsInfo)); @@ -105,222 +104,131 @@ public class DocumentNameTest { return mockedFile; } - public static DocumentName mkName(Path tempDir, DocumentName baseDir, String pth) throws IOException { - DocumentName result = baseDir.resolve(ExclusionUtils.convertSeparator(pth, "/", baseDir.getDirectorySeparator())); - DocumentName mocked = Mockito.spy(result); - - String fn = result.localized(FileSystems.getDefault().getSeparator()); - File file = tempDir.resolve(fn.substring(1)).toFile(); - File parent = file.getParentFile(); - if (parent.exists() && !parent.isDirectory()) { - parent.delete(); - } - parent.mkdirs(); - if (file.exists()) { - if (file.isDirectory()) { - FileUtils.deleteDirectory(file); - } else { - FileUtils.delete(file); - } - } - file.createNewFile(); - when(mocked.asFile()).thenReturn(file); - return mocked; - } - + /** + * Verifies that {@code resolve()} works correctly. + * @param fsInfo the file system under test. + * @param base the DocumentName to resolve from. + * @param toResolve the string to resolve. + * @param expected the expected DocumentName after resolution. + */ @ParameterizedTest(name = "{index} {0} {2}") @MethodSource("resolveTestData") - void resolveTest(String testName, DocumentName base, String toResolve, DocumentName expected) { + void resolveTest(DocumentName.FSInfo fsInfo, DocumentName base, String toResolve, DocumentName expected) { DocumentName actual = base.resolve(toResolve); assertThat(actual).isEqualTo(expected); } private static Stream<Arguments> resolveTestData() { List<Arguments> lst = new ArrayList<>(); + DocumentName base; + DocumentName expected; + for (DocumentName.FSInfo fsInfo : TEST_SUITE) { + String root = fsInfo.roots()[0]; + for (String baseName : List.of(root, root + fsInfo.mkPath("from", "base"))) { + String name = fsInfo.mkPath("", "dir", fsInfo.toString()); - DocumentName base = DocumentName.builder(UNIX).setName("/dir/unix").setBaseName("/").build(); - - DocumentName expected = DocumentName.builder(UNIX).setName("/dir/unix/relative").setBaseName("/").build(); - lst.add(Arguments.of("unix", base, "relative", expected)); - - expected = DocumentName.builder(UNIX).setName("/from/root").setBaseName("/").build(); - lst.add(Arguments.of("unix", base, "/from/root", expected)); + base = DocumentName.builder(fsInfo).setName(name).setBaseName(baseName).build(); - expected = DocumentName.builder(UNIX).setName("dir/up/and/down").setBaseName("/").build(); - lst.add(Arguments.of("unix", base, "../up/and/down", expected)); + expected = DocumentName.builder(fsInfo).setName(fsInfo.mkPath("", "dir", fsInfo.toString(), "relative")).setBaseName(baseName).build(); + lst.add(Arguments.of(fsInfo, base, "relative", expected)); - expected = DocumentName.builder(UNIX).setName("/from/root").setBaseName("/").build(); - lst.add(Arguments.of("unix", base, "\\from\\root", expected)); + expected = DocumentName.builder(fsInfo).setName(fsInfo.mkPath("", "from", "root")).setBaseName(baseName).build(); + lst.add(Arguments.of(fsInfo, base, fsInfo.mkPath("", "from", "root"), expected)); - expected = DocumentName.builder(UNIX).setName("dir/up/and/down").setBaseName("/").build(); - lst.add(Arguments.of("unix", base, "..\\up\\and\\down", expected)); + expected = DocumentName.builder(fsInfo).setName(fsInfo.mkPath("dir", "up", "and", "down")).setBaseName(baseName).build(); + lst.add(Arguments.of(fsInfo, base, fsInfo.mkPath("..", "up", "and", "down"), expected)); - // WINDOWS - base = DocumentName.builder(WINDOWS).setName("\\dir\\windows").setBaseName("C:\\").build(); - - expected = DocumentName.builder(WINDOWS).setName("\\dir\\windows\\relative").setBaseName("C:\\").build(); - lst.add(Arguments.of("windows", base, "relative", expected)); - - expected = DocumentName.builder(WINDOWS).setName("\\from\\root").setBaseName("C:\\").build(); - lst.add(Arguments.of("windows", base, "/from/root", expected)); - - expected = DocumentName.builder(WINDOWS).setName("dir\\up\\and\\down").setBaseName("C:\\").build(); - lst.add(Arguments.of("windows", base, "../up/and/down", expected)); - - expected = DocumentName.builder(WINDOWS).setName("\\from\\root").setBaseName("C:\\").build(); - lst.add(Arguments.of("windows", base, "\\from\\root", expected)); - - expected = DocumentName.builder(WINDOWS).setName("dir\\up\\and\\down").setBaseName("C:\\").build(); - lst.add(Arguments.of("windows", base, "..\\up\\and\\down", expected)); - - // OSX - base = DocumentName.builder(OSX).setName("/dir/osx").setBaseName("/").build(); - - expected = DocumentName.builder(OSX).setName("/dir/osx/relative").setBaseName("/").build(); - lst.add(Arguments.of("osx", base, "relative", expected)); - - expected = DocumentName.builder(OSX).setName("/from/root").setBaseName("/").build(); - lst.add(Arguments.of("osx", base, "/from/root", expected)); - - expected = DocumentName.builder(OSX).setName("dir/up/and/down").setBaseName("/").build(); - lst.add(Arguments.of("osx", base, "../up/and/down", expected)); - - expected = DocumentName.builder(OSX).setName("/from/root").setBaseName("/").build(); - lst.add(Arguments.of("osx", base, "\\from\\root", expected)); - - expected = DocumentName.builder(OSX).setName("dir/up/and/down").setBaseName("/").build(); - lst.add(Arguments.of("osx", base, "..\\up\\and\\down", expected)); + expected = DocumentName.builder(fsInfo).setName(fsInfo.mkPath("", "from", "root")).setBaseName(baseName).build(); + String wrongSeparator = fsInfo.dirSeparator().equals("/") ? "\\" : "/"; + lst.add(Arguments.of(fsInfo, base, String.join(wrongSeparator, "", "from", "root"), expected)); + expected = DocumentName.builder(fsInfo).setName(fsInfo.mkPath("dir", "up", "and", "down")).setBaseName(baseName).build(); + lst.add(Arguments.of(fsInfo, base, String.join(wrongSeparator, "..", "up", "and", "down"), expected)); + } + } return lst.stream(); } - @Test - void localizeTest() { - DocumentName documentName = DocumentName.builder(UNIX).setName("/a/b/c") - .setBaseName("/a").build(); - assertThat(documentName.localized()).isEqualTo("/b/c"); - assertThat(documentName.localized("-")).isEqualTo("-b-c"); - - documentName = DocumentName.builder(WINDOWS).setName("\\a\\b\\c") - .setBaseName("\\a").build(); - assertThat(documentName.localized()).isEqualTo("\\b\\c"); + @ParameterizedTest + @FieldSource("TEST_SUITE") + void localizeTest(FSInfo fsInfo) { + DocumentName documentName = DocumentName.builder(fsInfo).setName( + fsInfo.mkPath("", "a", "b", "c")) + .setBaseName(fsInfo.mkPath("", "a")).build(); + assertThat(documentName.localized()).isEqualTo(fsInfo.mkPath("", "b", "c")); assertThat(documentName.localized("-")).isEqualTo("-b-c"); - - documentName = DocumentName.builder(OSX).setName("/a/b/c") - .setBaseName("/a").build(); - assertThat(documentName.localized()).isEqualTo("/b/c"); - assertThat(documentName.localized("-")).isEqualTo("-b-c"); - } - - @ParameterizedTest(name = "{index} {0}") - @MethodSource("validBuilderData") - void validBuilderTest(String testName, DocumentName.Builder builder, String root, String name, String baseName, String dirSeparator) { - DocumentName underTest = builder.build(); - assertThat(underTest.getRoot()).as(testName).isEqualTo(root); - assertThat(underTest.getDirectorySeparator()).as(testName).isEqualTo(dirSeparator); - assertThat(underTest.getName()).as(testName).isEqualTo(root + dirSeparator + name); - assertThat(underTest.getBaseName()).as(testName).isEqualTo(root + dirSeparator + baseName); } - private static Stream<Arguments> validBuilderData() { - List<Arguments> lst = new ArrayList<>(); - File f = Files.newTemporaryFile(); - - Set<String> roots = new HashSet<>(); - File[] rootary = File.listRoots(); - if (rootary != null) { - for (File root : rootary) { - String name = root.getPath(); - roots.add(name); - } - } - - String name = f.getAbsolutePath(); - String root = ""; - for (String sysRoot : roots) { - if (name.startsWith(sysRoot)) { - name = name.substring(sysRoot.length()); - if (sysRoot.endsWith(File.separator)) { - root = sysRoot.substring(0, sysRoot.length() - File.separator.length()); - } - break; - } + @Test + void asFileTest() throws IOException { + File expected = File.createTempFile("docNameTest", ".txt"); + try (FileWriter fw = new FileWriter(expected, StandardCharsets.UTF_8)) { + fw.write("Hello world"); } - - File p = f.getParentFile(); - String baseName = p.getAbsolutePath().substring(root.length()); - if (baseName.startsWith(File.separator)) { - baseName = baseName.substring(File.separator.length()); + DocumentName underTest = DocumentName.builder(expected).build(); + File actual = underTest.asFile(); + try (FileReader fr = new FileReader(actual, StandardCharsets.UTF_8); + BufferedReader br = new BufferedReader(fr)) { + assertThat(br.readLine()).isEqualTo("Hello world"); } - lst.add(Arguments.of("setName(file)", DocumentName.builder().setName(f), root, name, baseName, File.separator)); - lst.add(Arguments.of("Builder(file)", DocumentName.builder(f), root, name, baseName, File.separator)); - - lst.add(Arguments.of("setName(dir)", DocumentName.builder().setName(p), root, baseName, baseName, File.separator)); - lst.add(Arguments.of("Builder(dir)", DocumentName.builder(p), root, baseName, baseName, File.separator)); - - File r = new File(root.isEmpty() ? File.separator : root); - lst.add(Arguments.of("setName(root)", DocumentName.builder().setName(r), root, "", "", File.separator)); - lst.add(Arguments.of("Builder(root)", DocumentName.builder(r), root, "", "", File.separator)); - - - lst.add(Arguments.of("foo/bar foo", DocumentName.builder(UNIX) - .setName("/foo/bar").setBaseName("foo"), "", "foo/bar", "foo", "/")); - - DocumentName.Builder builder = DocumentName.builder(WINDOWS).setName("\\foo\\bar").setBaseName("C:\\foo") - .setRoot("C:"); - lst.add(Arguments.of("\\foo\\bar foo", builder, "C:", "foo\\bar", "foo", "\\")); - - lst.add(Arguments.of("foo/bar foo", DocumentName.builder(OSX) - .setName("/foo/bar").setBaseName("foo"), "", "foo/bar", "foo", "/")); - - return lst.stream(); } @Test - void splitRootsTest() { - Pair<String, String> result = DocumentName.builder(WINDOWS).splitRoot("C:\\My\\path\\to\\a\\file.txt"); - assertThat(result.getLeft()).isEqualTo("C:"); - assertThat(result.getRight()).isEqualTo("My\\path\\to\\a\\file.txt"); - - result = DocumentName.builder(UNIX).splitRoot("/My/path/to/a/file.txt"); - assertThat(result.getLeft()).isEqualTo(""); - assertThat(result.getRight()).isEqualTo("My/path/to/a/file.txt"); - - result = DocumentName.builder(OSX).splitRoot("/My/path/to/a/file.txt"); - assertThat(result.getLeft()).isEqualTo(""); - assertThat(result.getRight()).isEqualTo("My/path/to/a/file.txt"); + void asPathTest() throws IOException { + File expected = File.createTempFile("docNameTest", ".txt"); + try (FileWriter fw = new FileWriter(expected, StandardCharsets.UTF_8)) { + fw.write("Hello world"); + } + DocumentName underTest = DocumentName.builder(expected).build(); + Path actual = underTest.asPath(); + Path root = Path.of(underTest.getRoot()); + File file = root.resolve(actual).toFile(); + try (FileReader fr = new FileReader(file, StandardCharsets.UTF_8); + BufferedReader br = new BufferedReader(fr)) { + assertThat(br.readLine()).isEqualTo("Hello world"); + } } - @Test - void archiveEntryNameTest() { - String entryName = "./anArchiveEntry.txt"; - DocumentName archiveName = DocumentName.builder(WINDOWS) - .setName("C:\\archives\\anArchive.zip").setBaseName("C:\\archives").build(); - - assertThat(archiveName.getRoot()).isEqualTo("C:"); - assertThat(archiveName.getDirectorySeparator()).isEqualTo("\\"); - assertThat(archiveName.getBaseName()).isEqualTo("C:\\archives"); - assertThat(archiveName.getName()).isEqualTo("C:\\archives\\anArchive.zip"); - assertThat(archiveName.localized()).isEqualTo("\\anArchive.zip"); - ArchiveEntryName archiveEntryName = new ArchiveEntryName(archiveName, entryName); - - assertThat(archiveEntryName.getRoot()).isEqualTo(archiveName.getName()+"#"); - assertThat(archiveEntryName.getDirectorySeparator()).isEqualTo("/"); - assertThat(archiveEntryName.getBaseName()).isEqualTo("C:\\archives\\anArchive.zip#"); - assertThat(archiveEntryName.getName()).isEqualTo("C:\\archives\\anArchive.zip#/anArchiveEntry.txt"); - assertThat(archiveEntryName.localized()).isEqualTo("/anArchiveEntry.txt"); - assertThat(archiveEntryName.localized("/")).isEqualTo("/anArchive.zip#/anArchiveEntry.txt"); + @ParameterizedTest(name = "{index} {0} {1}") + @MethodSource("archiveEntryTestData") + void archiveEntryNameTest(String os, String testName, DocumentName archiveName, String root, String separator, String baseName, + String localizedName) { + assertThat(archiveName.getRoot()).as("root").isEqualTo(root); + assertThat(archiveName.getDirectorySeparator()).as("separator").isEqualTo(separator); + assertThat(archiveName.getBaseName()).as("baseName").isEqualTo(baseName); + assertThat(archiveName.localized()).as("localized").isEqualTo(localizedName); + assertThat(archiveName.getName()).as("name").isEqualTo(baseName + localizedName); + if (!separator.equals(archiveName.fsInfo().dirSeparator())) + { + String newBaseName = separator.equals("/") ? baseName.replace('\\', '/') : baseName.replace('/', '\\'); + assertThat(archiveName.localized(separator)).as("localized(x)").isEqualTo(newBaseName + localizedName); + } + } - // test with directory - entryName = "./someDir/anArchiveEntry.txt"; - archiveEntryName = new ArchiveEntryName(archiveName, entryName); + static List<Arguments> archiveEntryTestData() { + List<Arguments> lst = new ArrayList<>(); - assertThat(archiveEntryName.getRoot()).isEqualTo(archiveName.getName()+"#"); - assertThat(archiveEntryName.getDirectorySeparator()).isEqualTo("/"); - assertThat(archiveEntryName.getBaseName()).isEqualTo("C:\\archives\\anArchive.zip#"); - assertThat(archiveEntryName.getName()).isEqualTo("C:\\archives\\anArchive.zip#/someDir/anArchiveEntry.txt"); - assertThat(archiveEntryName.localized()).isEqualTo("/someDir/anArchiveEntry.txt"); - assertThat(archiveEntryName.localized("/")).isEqualTo("/anArchive.zip#/someDir/anArchiveEntry.txt"); + for (FSInfo fsInfo : FSInfoTest.TEST_SUITE) { + String os = fsInfo.toString(); + String root = fsInfo.roots()[0]; + String baseName = String.format(String.format("%sarchives", root)); + String simpleName = String.format("%sanArchive.zip", fsInfo.dirSeparator()); + String entryName = "./anArchiveEntry.txt"; + DocumentName archiveName = DocumentName.builder(fsInfo).setName(baseName + simpleName).setBaseName(baseName).build(); + lst.add(Arguments.of(os, "archive name", archiveName, root, fsInfo.dirSeparator(), baseName, simpleName)); + + ArchiveEntryName archiveEntryName = new ArchiveEntryName(archiveName, entryName); + baseName = archiveName.getName() + "#"; + root = baseName + "/"; + lst.add(Arguments.of(os, "archive entry name", archiveEntryName, root, "/", baseName, "/anArchiveEntry.txt")); + + // test with directory + entryName = "./someDir/anArchiveEntry.txt"; + archiveEntryName = new ArchiveEntryName(archiveName, entryName); + + lst.add(Arguments.of(os, "archive entry with directory", archiveEntryName, root, "/", baseName, "/someDir/anArchiveEntry.txt")); + } + return lst; } }
