/*
* JBoss, Home of Professional Open Source
* Copyright 2012, Red Hat Middleware LLC, and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed 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.jboss.shrinkwrap.impl.nio.file;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.FileSystem;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.WatchEvent.Kind;
import java.util.Iterator;
import java.util.logging.Logger;
import org.jboss.shrinkwrap.api.ArchivePaths;
import org.jboss.shrinkwrap.api.GenericArchive;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.nio.file.ShrinkWrapFileSystems;
import org.jboss.shrinkwrap.api.spec.JavaArchive;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
/**
* Test cases to assert the ShrinkWrap implementation of the NIO.2 {@link Path} is working as contracted.
*
* @author <a href="mailto:alr@jboss.org">Andrew Lee Rubinger</a>
*/
public class PathTestCase {
@SuppressWarnings("unused")
private static final Logger log = Logger.getLogger(PathTestCase.class.getName());
private ShrinkWrapFileSystem fileSystem;
@Before
public void createFileSystem() throws URISyntaxException, IOException {
// Setup and mount the archive
final String name = "test.jar";
final JavaArchive archive = ShrinkWrap.create(JavaArchive.class, name);
final ShrinkWrapFileSystem fs = (ShrinkWrapFileSystem) ShrinkWrapFileSystems.newFileSystem(archive);
this.fileSystem = fs;
}
@After
public void closeFs() throws IOException {
this.fileSystem.close();
}
@Test
public void rootIsAbsolute() {
final Path path = fileSystem.getPath("/");
Assert.assertTrue("Root path must be absolute", path.isAbsolute());
Assert.assertEquals("Root path should be equal to root archive path value", path.toString(), ArchivePaths
.root().get());
}
@Test
public void getFileSystem() {
final Path path = fileSystem.getPath("/");
Assert.assertEquals("FileSystem not obtained correctly via Path", fileSystem, path.getFileSystem());
}
@Test
public void getPathEmptyPath() {
final String empty = "";
final Path path = fileSystem.getPath(empty);
Assert.assertEquals("Empty path should be resolved to empty path value", empty, path.toString());
}
@Test
public void getFileNameEmptyPath() {
final String empty = "";
final Path path = fileSystem.getPath(empty);
Assert.assertEquals("Empty path should return null file name", null, path.getFileName());
}
@Test(expected = IllegalArgumentException.class)
public void getPathNullPath() {
fileSystem.getPath(null);
}
@Test
public void getPathRelative() {
final String relative = "relative";
final Path path = fileSystem.getPath(relative);
Assert.assertFalse("Relative paths must not be adjusted to absolute", path.isAbsolute());
Assert.assertEquals("Relative input was not resolved to path as expected", relative, path.toString());
}
@Test
public void getRoot() {
final Path path = fileSystem.getPath("/someNode");
final Path root = path.getRoot();
Assert.assertEquals("Did not return correct root", root.toString(), "/");
}
@Test
public void getRootFromRelative() {
final Path path = fileSystem.getPath("someNode");
final Path root = path.getRoot();
Assert.assertNull("Relative path should have null root", root);
}
@Test
public void getRootFromNested() {
final Path path = fileSystem.getPath("/someNode/child");
final Path root = path.getRoot();
Assert.assertEquals("Did not return correct root", root.toString(), "/");
}
@Test
public void getParent() {
final Path path = fileSystem.getPath("parent/child");
final Path parent = path.getParent();
Assert.assertEquals("Did not return correct parent", parent.toString(), "parent");
}
@Test
public void getParentRelative() {
final Path path = fileSystem.getPath("relativeName");
final Path parent = path.getParent();
Assert.assertNull("Single node relative paths should have no parent", parent);
}
@Test
public void getParentNested() {
final Path path = fileSystem.getPath("parent/child/grandchild");
final Path parent = path.getParent();
Assert.assertEquals("Did not return correct parent", parent.toString(), "parent/child");
}
@Test
public void getParentAbsolute() {
final Path path = fileSystem.getPath("/parent/child/grandchild");
final Path parent = path.getParent();
Assert.assertEquals("Did not return correct parent", parent.toString(), "/parent/child");
}
@Test
public void getParentRootIsNull() {
final Path path = fileSystem.getPath("/");
final Path parent = path.getParent();
Assert.assertNull("Parent of root should be null", parent);
}
@Test
public void getFileName() {
final String location = "/dir/nestedDir/";
final String fileNameString = "fileName";
final Path path = fileSystem.getPath(location + fileNameString);
final Path fileName = path.getFileName();
Assert.assertEquals("File name was not as expected", fileNameString, fileName.toString());
}
@Test
public void getRootFileName() {
final Path path = fileSystem.getPath("/");
final Path fileName = path.getFileName();
Assert.assertNull("Root file name should be null", fileName);
}
@Test
public void getRootNameCount() {
final Path path = fileSystem.getPath("/");
final int count = path.getNameCount();
Assert.assertEquals("Root should have no name count", 0, count);
}
@Test
public void getTopLevelNameCount() {
final Path path = fileSystem.getPath("/toplevel");
final int count = path.getNameCount();
Assert.assertEquals("Top-level element should have name count 1", 1, count);
}
@Test
public void getTopLevelAppendedSlashNameCount() {
final Path path = fileSystem.getPath("/toplevel/");
final int count = path.getNameCount();
Assert.assertEquals("Top-level element should have name count 1", 1, count);
}
@Test
public void getTopLevelNoPrecedingSlashNameCount() {
final Path path = fileSystem.getPath("toplevel/");
final int count = path.getNameCount();
Assert.assertEquals("Top-level element should have name count 1", 1, count);
}
@Test
public void nestedNameCount() {
final Path path = fileSystem.getPath("toplevel/nested");
final int count = path.getNameCount();
Assert.assertEquals("nested-level element should have name count 2", 2, count);
}
@Test
public void toAbsolutePath() {
final Path path = fileSystem.getPath("toplevel");
Assert.assertEquals("toAbsolute should return the absolute form of the Path", "/toplevel", path
.toAbsolutePath().toString());
}
@Test
public void toAbsolutePathAlreadyAbsolute() {
final String absolutePath = "/absolute";
final Path path = fileSystem.getPath(absolutePath);
Assert.assertEquals("toAbsolute should return the absolute form of the Path", absolutePath, path
.toAbsolutePath().toString());
}
@Test
public void isAbsolute() {
final Path path = fileSystem.getPath("/absolute");
Assert.assertTrue(path.isAbsolute());
}
@Test
public void isAbsoluteFalse() {
final Path path = fileSystem.getPath("relative");
Assert.assertFalse(path.isAbsolute());
}
@Test
public void iterator() {
final Path path = fileSystem.getPath("toplevel/second/third/fourth");
final Iterator<Path> paths = path.iterator();
Assert.assertEquals("/toplevel", paths.next().toString());
Assert.assertEquals("/toplevel/second", paths.next().toString());
Assert.assertEquals("/toplevel/second/third", paths.next().toString());
Assert.assertEquals("/toplevel/second/third/fourth", paths.next().toString());
}
@Test
public void iteratorRoot() {
final Path path = fileSystem.getPath("/");
final Iterator<Path> paths = path.iterator();
Assert.assertFalse("Iterator should not return root element", paths.hasNext());
}
@Test
public void toUri() {
final Path path = fileSystem.getPath("/toplevel/second");
final URI uri = path.toUri();
final String expected = ShrinkWrapFileSystems.PROTOCOL + "://" + fileSystem.getArchive().getId()
+ path.toString();
Assert.assertEquals("toUri did not return form as expected", expected, uri.toString());
}
@Test
public void getName() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final Path second = path.getName(2);
Assert.assertEquals("/toplevel/second/third", second.toString());
}
@Test
public void getNameRoot() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final Path second = path.getName(0);
Assert.assertEquals("/toplevel", second.toString());
}
@Test(expected = IllegalArgumentException.class)
public void subpathNegativeBegin() {
fileSystem.getPath("/toplevel/second/third").subpath(-1, 1);
}
@Test(expected = IllegalArgumentException.class)
public void subpathNegativeEnd() {
fileSystem.getPath("/toplevel/second/third").subpath(0, -1);
}
@Test(expected = IllegalArgumentException.class)
public void subpathEndBeforeBegin() {
fileSystem.getPath("/toplevel/second/third").subpath(2, 1);
}
@Test(expected = IllegalArgumentException.class)
public void subpathBeginTooLarge() {
fileSystem.getPath("/toplevel/second/third").subpath(4, 5);
}
@Test(expected = IllegalArgumentException.class)
public void subpathEndTooLarge() {
fileSystem.getPath("/toplevel/second/third").subpath(2, 4);
}
@Test
public void subpath() {
final Path subpath = fileSystem.getPath("/toplevel/second/third").subpath(1, 2);
Assert.assertEquals("/toplevel/second", subpath.toString());
}
@Test(expected = IllegalArgumentException.class)
public void startsWithNullPathInput() {
fileSystem.getPath("/toplevel/second/third").startsWith((Path) null);
}
@Test(expected = IllegalArgumentException.class)
public void startsWithNullStringInput() {
fileSystem.getPath("/toplevel/second/third").startsWith((String) null);
}
@Test
public void startsWithOtherPathImpl() {
final boolean startsWith = fileSystem.getPath("/toplevel/second/third").startsWith(new MockPath());
Assert.assertFalse(startsWith);
}
/**
* Path cannot start with a path from another FS
*/
@Test
public void startsWithOtherFs() throws IOException {
final FileSystem otherFs = ShrinkWrapFileSystems.newFileSystem(ShrinkWrap.create(GenericArchive.class));
final String pathName = "/toplevel/second";
final Path otherPath = otherFs.getPath(pathName);
final boolean startsWith = fileSystem.getPath(pathName).startsWith(otherPath);
Assert.assertFalse(startsWith);
}
@Test
public void startsWith() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean startsWith = path.startsWith(fileSystem.getPath("/toplevel/second/"));
Assert.assertTrue(startsWith);
}
@Test
public void startsWithRelative() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean startsWith = path.startsWith(fileSystem.getPath("toplevel/second/"));
Assert.assertTrue(startsWith);
}
@Test
public void startsWithAbsolute() {
final Path path = fileSystem.getPath("toplevel/second/third");
final boolean startsWith = path.startsWith(fileSystem.getPath("/toplevel/second/third"));
Assert.assertFalse("Other absolute pah and this relative path cannot match startsWith", startsWith);
}
@Test
public void startsWithString() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean startsWith = path.startsWith("/toplevel/second/");
Assert.assertTrue(startsWith);
}
@Test
public void startsWithNegative() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean startsWith = path.startsWith(fileSystem.getPath("/top"));
Assert.assertFalse(startsWith);
}
@Test
public void startsWithBiggerThan() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean startsWith = path.startsWith(fileSystem.getPath("/toplevel/second/third/fourth"));
Assert.assertFalse(startsWith);
}
// We don't interface w/ File API
@Test(expected = UnsupportedOperationException.class)
public void toFile() {
fileSystem.getPath("/toplevel").toFile();
}
// We don't support events
@Test(expected = UnsupportedOperationException.class)
public void register() throws IOException {
fileSystem.getPath("/toplevel").register(null, (Kind<?>) null);
}
// We don't support events
@Test(expected = UnsupportedOperationException.class)
public void registerLongform() throws IOException {
fileSystem.getPath("/toplevel").register(null, (Kind<?>) null, null);
}
@Test(expected = IllegalArgumentException.class)
public void endsWithNullPathInput() {
fileSystem.getPath("/toplevel/second/third").endsWith((Path) null);
}
@Test(expected = IllegalArgumentException.class)
public void endsWithNullStringInput() {
fileSystem.getPath("/toplevel/second/third").endsWith((String) null);
}
@Test
public void endsWithOtherPathImpl() {
final boolean endsWith = fileSystem.getPath("/toplevel/second/third").endsWith(new MockPath());
Assert.assertFalse(endsWith);
}
/**
* Path cannot start with a path from another FS
*/
@Test
public void endsWithOtherFs() throws IOException {
final FileSystem otherFs = ShrinkWrapFileSystems.newFileSystem(ShrinkWrap.create(GenericArchive.class));
final Path otherPath = otherFs.getPath("/otherpath");
final boolean endsWith = fileSystem.getPath("/toplevel/second/third").endsWith(otherPath);
Assert.assertFalse(endsWith);
}
@Test
public void endsWith() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean endsWith = path.endsWith(fileSystem.getPath("third"));
Assert.assertTrue("Should have identified path ends with last name component", endsWith);
}
@Test
public void endsString() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean endsWith = path.endsWith(fileSystem.getPath("third").toString());
Assert.assertTrue("Should have identified path ends with last name component", endsWith);
}
@Test
public void endsWithNested() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean endsWith = path.endsWith(fileSystem.getPath("second/third"));
Assert.assertTrue("Should have identified path ends with last and penultimate name component", endsWith);
}
@Test
public void endsWithPartial() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean endsWith = path.endsWith(fileSystem.getPath("ird"));
Assert.assertFalse(endsWith);
}
@Test
public void endsWithIncorrectRoot() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean endsWith = path.endsWith(fileSystem.getPath("/third"));
Assert.assertFalse(endsWith);
}
@Test
public void endsWithNegative() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean endsWith = path.endsWith(fileSystem.getPath("/toplevel"));
Assert.assertFalse(endsWith);
}
@Test
public void endsWithBiggerThan() {
final Path path = fileSystem.getPath("/toplevel/second/third");
final boolean endsWith = path.endsWith(fileSystem.getPath("/toplevel/second/third/fourth"));
Assert.assertFalse(endsWith);
}
@Test
public void toRealPath() throws IOException {
final String newPathName = "/toplevel/myAsset";
this.fileSystem.getArchive().add(EmptyAsset.INSTANCE, newPathName);
final Path path = fileSystem.getPath(newPathName);
final Path realPath = path.toRealPath((LinkOption[]) null);
Assert.assertEquals(path.toString(), realPath.toString());
}
@Test(expected = FileNotFoundException.class)
public void toRealPathDoesntExist() throws IOException {
final String newPathName = "/toplevel/myAsset";
final Path path = fileSystem.getPath(newPathName);
path.toRealPath((LinkOption[]) null);
}
@Test
public void normalizeNoop() {
final Path path = fileSystem.getPath("/a/b");
final Path normalized = path.normalize();
Assert.assertEquals(path.toString(), normalized.toString());
}
@Test
public void normalizeRelative() {
final Path path = fileSystem.getPath("a/b");
final Path normalized = path.normalize();
Assert.assertEquals(path.toString(), normalized.toString());
}
@Test
public void normalizeCurrentDirRefs() {
final Path path = fileSystem.getPath("/a/./b/./c/d/./e");
final Path normalized = path.normalize();
Assert.assertEquals("/a/b/c/d/e", normalized.toString());
}
@Test
public void normalizeBackDirRefs() {
final Path path = fileSystem.getPath("/a/../b/./c/d/../e");
final Path normalized = path.normalize();
Assert.assertEquals("/b/c/e", normalized.toString());
}
@Test
public void relativizeSuperset() {
final Path path = fileSystem.getPath("/a/b");
final Path other = fileSystem.getPath("/a/b/c/d");
final Path relativized = path.relativize(other);
Assert.assertEquals("c/d", relativized.toString());
}
@Test
public void relativizeSuperset2() {
final Path path = fileSystem.getPath("/a/b/c");
final Path other = fileSystem.getPath("/a/b/c/d");
final Path relativized = path.relativize(other);
Assert.assertEquals("d", relativized.toString());
}
@Test
public void relativizeCommonNode() {
final Path path = fileSystem.getPath("/a/b");
final Path other = fileSystem.getPath("/a/c");
final Path relativized = path.relativize(other);
Assert.assertEquals("../c", relativized.toString());
}
@Test
public void relativizeCommonNode2() {
final Path path = fileSystem.getPath("/a/b");
final Path other = fileSystem.getPath("/a/c/d");
final Path relativized = path.relativize(other);
Assert.assertEquals("../c/d", relativized.toString());
}
@Test(expected = IllegalArgumentException.class)
public void relativizeNull() {
final Path path = fileSystem.getPath("/toplevel/myAsset");
path.relativize(null);
}
@Test
public void resolve() {
final Path path = fileSystem.getPath("/topLevel/secondLevel");
final Path other = fileSystem.getPath("thirdLevel");
final Path resolved = path.resolve(other);
Assert.assertEquals("Resolve should join other to this", "/topLevel/secondLevel/thirdLevel",
resolved.toString());
}
@Test
public void resolveTrailingSlashOnThis() {
final Path path = fileSystem.getPath("/topLevel/secondLevel/");
final Path other = fileSystem.getPath("thirdLevel");
final Path resolved = path.resolve(other);
Assert.assertEquals("Resolve should join other to this", "/topLevel/secondLevel/thirdLevel",
resolved.toString());
}
@Test
public void resolveEmpty() {
final String thisLocation = "/topLevel/secondLevel";
final Path path = fileSystem.getPath(thisLocation);
final Path other = fileSystem.getPath("");
final Path resolved = path.resolve(other);
Assert.assertEquals("Resolve of empty path should return this path", thisLocation, resolved.toString());
}
@Test
public void resolveAbsolute() {
final Path path = fileSystem.getPath("/toplevel/myDir/");
final Path other = fileSystem.getPath("/toplevel/myDir/myAsset");
final Path resolved = path.resolve(other);
// Since absolute, by spec return the value of the other path
Assert.assertEquals(other.toString(), resolved.toString());
}
@Test(expected = IllegalArgumentException.class)
public void resolveNull() {
fileSystem.getPath("/toplevel/myDir/").resolve((Path) null);
}
@Test
public void resolveString() {
final Path path = fileSystem.getPath("/toplevel/myDir/");
final String otherName = "/toplevel/myDir/myAsset";
final Path other = fileSystem.getPath(otherName);
final Path resolved = path.resolve(otherName);
// Since absolute, by spec return the value of the other path
Assert.assertEquals(other.toString(), resolved.toString());
}
@Test(expected = IllegalArgumentException.class)
public void resolveNullString() {
fileSystem.getPath("/toplevel/myDir/").resolve((String) null);
}
/**
* This case outlined in {@link Path#relativize(Path)} APIDocs:
*
* For any two normalized paths p and q, where q does not have a root component,
*
* <code> p.relativize(p.resolve(q)).equals(q) </code>
*/
@Test
public void roundtripResolveRelativizeOfNormalizedPaths() {
final Path path = fileSystem.getPath("/a/b/f/../");
final Path other = fileSystem.getPath("a/b/../c");
final Path pathNormalized = path.normalize();
final Path otherNormalized = other.normalize();
Assert.assertTrue("Failed check that relativize undoes resolve, taking into account normalization",
(pathNormalized.relativize(pathNormalized.resolve(otherNormalized)).equals(otherNormalized)));
}
@Test
public void resolveSibling() {
final Path path = fileSystem.getPath("/toplevel/myDir/");
final Path other = fileSystem.getPath("/toplevel/myDir/myAsset");
final Path resolved = path.resolveSibling(other);
// Since absolute, by spec return the value of the other path
Assert.assertEquals(other.toString(), resolved.toString());
}
@Test(expected = IllegalArgumentException.class)
public void resolveSiblingNull() {
fileSystem.getPath("/toplevel/myDir/").resolveSibling((Path) null);
}
@Test
public void resolveSiblingString() {
final Path path = fileSystem.getPath("/toplevel/myDir/");
final String otherName = "/toplevel/myDir/myAsset";
final Path other = fileSystem.getPath(otherName);
final Path resolved = path.resolveSibling(otherName);
// Since absolute, by spec return the value of the other path
Assert.assertEquals(other.toString(), resolved.toString());
}
@Test(expected = IllegalArgumentException.class)
public void resolveSublingNullString() {
fileSystem.getPath("/toplevel/myDir/").resolveSibling((String) null);
}
@Test
public void compareToGreaterValue() {
final Path path = fileSystem.getPath("/toplevel/a");
final String otherName = "/toplevel/b";
final Path other = fileSystem.getPath(otherName);
final int compare = path.compareTo(other);
Assert.assertEquals(-1, compare);
}
@Test
public void compareToLesserValue() {
final Path path = fileSystem.getPath("/toplevel/b");
final String otherName = "/toplevel/a";
final Path other = fileSystem.getPath(otherName);
final int compare = path.compareTo(other);
Assert.assertEquals(1, compare);
}
@Test
public void compareToEqualValue() {
final Path path = fileSystem.getPath("/toplevel/a");
final String otherName = "/toplevel/a";
final Path other = fileSystem.getPath(otherName);
final int compare = path.compareTo(other);
Assert.assertEquals(0, compare);
}
@Test(expected = IllegalArgumentException.class)
public void compareToNull() throws IOException {
fileSystem.getPath("/toplevel/a").compareTo(null);
}
}