/*
* The Alluxio Open Foundation licenses this work under the Apache License, version 2.0
* (the "License"). You may not use this work except in compliance with the License, which is
* available at www.apache.org/licenses/LICENSE-2.0
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied, as more fully set forth in the License.
*
* See the NOTICE file distributed with this work for information regarding copyright ownership.
*/
package alluxio.util.io;
import alluxio.Constants;
import alluxio.exception.ExceptionMessage;
import alluxio.exception.InvalidPathException;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import java.util.LinkedList;
/**
* Tests for the {@link PathUtils} class.
*/
public class PathUtilsTest {
/**
* The expected exception thrown during a test.
*/
@Rule
public final ExpectedException mException = ExpectedException.none();
/**
* Tests the {@link PathUtils#cleanPath(String)} method.
*/
@Test
public void cleanPathNoException() throws InvalidPathException {
// test clean path
Assert.assertEquals("/foo/bar", PathUtils.cleanPath("/foo/bar"));
// test trailing slash
Assert.assertEquals("/foo/bar", PathUtils.cleanPath("/foo/bar/"));
// test redundant slashes
Assert.assertEquals("/foo/bar", PathUtils.cleanPath("/foo//bar"));
Assert.assertEquals("/foo/bar", PathUtils.cleanPath("/foo//bar//"));
Assert.assertEquals("/foo/bar", PathUtils.cleanPath("/foo///////bar//////"));
// test dots gets resolved
Assert.assertEquals("/foo/bar", PathUtils.cleanPath("/foo/./bar"));
Assert.assertEquals("/foo/bar", PathUtils.cleanPath("/foo/././bar"));
Assert.assertEquals("/foo", PathUtils.cleanPath("/foo/bar/.."));
Assert.assertEquals("/bar", PathUtils.cleanPath("/foo/../bar"));
Assert.assertEquals("/", PathUtils.cleanPath("/foo/bar/../.."));
// the following seems strange
// TODO(jiri): Instead of returning null, throw InvalidPathException.
Assert.assertNull(PathUtils.cleanPath("/foo/bar/../../.."));
}
/**
* Tests the {@link PathUtils#cleanPath(String)} method to thrown an exception in case an invalid
* path is provided.
*/
@Test
public void cleanPathException() throws InvalidPathException {
mException.expect(InvalidPathException.class);
Assert.assertEquals("/foo/bar", PathUtils.cleanPath("/\\ foo / bar"));
}
/**
* Tests the {@link PathUtils#concatPath(Object, Object...)} method.
*/
@Test
public void concatPath() {
Assert.assertEquals("/", PathUtils.concatPath("/"));
Assert.assertEquals("/", PathUtils.concatPath("/", ""));
Assert.assertEquals("/bar", PathUtils.concatPath("/", "bar"));
Assert.assertEquals("foo", PathUtils.concatPath("foo"));
Assert.assertEquals("/foo", PathUtils.concatPath("/foo"));
Assert.assertEquals("/foo", PathUtils.concatPath("/foo", ""));
// Join base without trailing "/"
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo", "bar"));
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo", "bar/"));
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo", "/bar"));
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo", "/bar/"));
// Join base with trailing "/"
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo/", "bar"));
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo/", "bar/"));
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo/", "/bar"));
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo/", "/bar/"));
// Whitespace must be trimmed.
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo ", "bar "));
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo ", " bar"));
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo ", " bar "));
// Redundant separator must be trimmed.
Assert.assertEquals("/foo/bar", PathUtils.concatPath("/foo/", "bar//"));
// Multiple components to join.
Assert.assertEquals("/foo/bar/a/b/c", PathUtils.concatPath("/foo", "bar", "a", "b", "c"));
Assert.assertEquals("/foo/bar/b/c", PathUtils.concatPath("/foo", "bar", "", "b", "c"));
// Non-string
Assert.assertEquals("/foo/bar/1", PathUtils.concatPath("/foo", "bar", 1));
Assert.assertEquals("/foo/bar/2", PathUtils.concatPath("/foo", "bar", 2L));
// Header
Assert.assertEquals(Constants.HEADER + "host:port/foo/bar",
PathUtils.concatPath(Constants.HEADER + "host:port", "/foo", "bar"));
}
/**
* Tests the {@link PathUtils#getParent(String)} method.
*/
@Test
public void getParent() throws InvalidPathException {
// get a parent that is non-root
Assert.assertEquals("/foo", PathUtils.getParent("/foo/bar"));
Assert.assertEquals("/foo", PathUtils.getParent("/foo/bar/"));
Assert.assertEquals("/foo", PathUtils.getParent("/foo/./bar/"));
Assert.assertEquals("/foo", PathUtils.getParent("/foo/././bar/"));
// get a parent that is root
Assert.assertEquals("/", PathUtils.getParent("/foo"));
Assert.assertEquals("/", PathUtils.getParent("/foo/bar/../"));
Assert.assertEquals("/", PathUtils.getParent("/foo/../bar/"));
// get parent of root
Assert.assertEquals("/", PathUtils.getParent("/"));
Assert.assertEquals("/", PathUtils.getParent("/foo/bar/../../"));
Assert.assertEquals("/", PathUtils.getParent("/foo/../bar/../"));
}
/**
* Tests the {@link PathUtils#getPathComponents(String)} method.
*/
@Test
public void getPathComponentsNoException() throws InvalidPathException {
Assert.assertArrayEquals(new String[] {""}, PathUtils.getPathComponents("/"));
Assert.assertArrayEquals(new String[] {"", "bar"}, PathUtils.getPathComponents("/bar"));
Assert.assertArrayEquals(new String[] {"", "foo", "bar"},
PathUtils.getPathComponents("/foo/bar"));
Assert.assertArrayEquals(new String[] {"", "foo", "bar"},
PathUtils.getPathComponents("/foo/bar/"));
Assert.assertArrayEquals(new String[] {"", "bar"},
PathUtils.getPathComponents("/foo/../bar"));
Assert.assertArrayEquals(new String[] {"", "foo", "bar", "a", "b", "c"},
PathUtils.getPathComponents("/foo//bar/a/b/c"));
}
/**
* Tests the {@link PathUtils#getPathComponents(String)} method to thrown an exception in case the
* path is invalid.
*/
@Test
public void getPathComponentsException() throws InvalidPathException {
mException.expect(InvalidPathException.class);
PathUtils.getPathComponents("/\\ foo / bar");
}
/**
* Tests the {@link PathUtils#subtractPaths(String, String)} method.
*/
@Test
public void subtractPaths() throws InvalidPathException {
Assert.assertEquals("b/c", PathUtils.subtractPaths("/a/b/c", "/a"));
Assert.assertEquals("b/c", PathUtils.subtractPaths("/a/b/c", "/a/"));
Assert.assertEquals("b/c", PathUtils.subtractPaths("/a/b/c", "/a/"));
Assert.assertEquals("c", PathUtils.subtractPaths("/a/b/c", "/a/b"));
Assert.assertEquals("a/b/c", PathUtils.subtractPaths("/a/b/c", "/"));
Assert.assertEquals("", PathUtils.subtractPaths("/", "/"));
Assert.assertEquals("", PathUtils.subtractPaths("/a/b/", "/a/b"));
Assert.assertEquals("", PathUtils.subtractPaths("/a/b", "/a/b"));
}
/**
* Tests {@link PathUtils#subtractPaths(String, String)} throws the right exception if an input
* path is invalid or the second argument isn't a prefix of the first.
*/
@Test
public void subtractPathsException() throws InvalidPathException {
try {
PathUtils.subtractPaths("", "/");
Assert.fail("\"\" should throw an InvalidPathException");
} catch (InvalidPathException e) {
Assert.assertEquals(ExceptionMessage.PATH_INVALID.getMessage(""), e.getMessage());
}
try {
PathUtils.subtractPaths("/", "noslash");
Assert.fail("noslash should be an invalid path");
} catch (InvalidPathException e) {
Assert.assertEquals(ExceptionMessage.PATH_INVALID.getMessage("noslash"), e.getMessage());
}
try {
PathUtils.subtractPaths("/a", "/not/a/prefix");
Assert.fail("subtractPaths should complain about the prefix not being a prefix");
} catch (RuntimeException e) {
String expectedMessage = "Cannot subtract /not/a/prefix from /a because it is not a prefix";
Assert.assertEquals(expectedMessage, e.getMessage());
}
}
/**
* Tests the {@link PathUtils#hasPrefix(String, String)} method.
*/
@Test
public void hasPrefix() throws InvalidPathException {
Assert.assertTrue(PathUtils.hasPrefix("/", "/"));
Assert.assertTrue(PathUtils.hasPrefix("/a", "/a"));
Assert.assertTrue(PathUtils.hasPrefix("/a", "/a/"));
Assert.assertTrue(PathUtils.hasPrefix("/a/b/c", "/a"));
Assert.assertTrue(PathUtils.hasPrefix("/a/b/c", "/a/b"));
Assert.assertTrue(PathUtils.hasPrefix("/a/b/c", "/a/b/c"));
Assert.assertFalse(PathUtils.hasPrefix("/", "/a"));
Assert.assertFalse(PathUtils.hasPrefix("/", "/a/b/c"));
Assert.assertFalse(PathUtils.hasPrefix("/a", "/a/b/c"));
Assert.assertFalse(PathUtils.hasPrefix("/a/b", "/a/b/c"));
Assert.assertFalse(PathUtils.hasPrefix("/a/b/c", "/aa"));
Assert.assertFalse(PathUtils.hasPrefix("/a/b/c", "/a/bb"));
Assert.assertFalse(PathUtils.hasPrefix("/a/b/c", "/a/b/cc"));
Assert.assertFalse(PathUtils.hasPrefix("/aa/b/c", "/a"));
Assert.assertFalse(PathUtils.hasPrefix("/a/bb/c", "/a/b"));
Assert.assertFalse(PathUtils.hasPrefix("/a/b/cc", "/a/b/c"));
}
/**
* Tests the {@link PathUtils#isRoot(String)} method.
*/
@Test
public void isRoot() throws InvalidPathException {
// check a path that is non-root
Assert.assertFalse(PathUtils.isRoot("/foo/bar"));
Assert.assertFalse(PathUtils.isRoot("/foo/bar/"));
Assert.assertFalse(PathUtils.isRoot("/foo/./bar/"));
Assert.assertFalse(PathUtils.isRoot("/foo/././bar/"));
Assert.assertFalse(PathUtils.isRoot("/foo/../bar"));
Assert.assertFalse(PathUtils.isRoot("/foo/../bar/"));
// check a path that is root
Assert.assertTrue(PathUtils.isRoot("/"));
Assert.assertTrue(PathUtils.isRoot("/"));
Assert.assertTrue(PathUtils.isRoot("/."));
Assert.assertTrue(PathUtils.isRoot("/./"));
Assert.assertTrue(PathUtils.isRoot("/foo/.."));
Assert.assertTrue(PathUtils.isRoot("/foo/../"));
}
/**
* Tests the {@link PathUtils#temporaryFileName(long, String)} method.
*/
@Test
public void temporaryFileName() {
Assert.assertEquals(PathUtils.temporaryFileName(1, "/"),
PathUtils.temporaryFileName(1, "/"));
Assert.assertNotEquals(PathUtils.temporaryFileName(1, "/"),
PathUtils.temporaryFileName(2, "/"));
Assert.assertNotEquals(PathUtils.temporaryFileName(1, "/"),
PathUtils.temporaryFileName(1, "/a"));
}
@Test
public void getPermanentFileName() {
Assert.assertEquals("/", PathUtils.getPermanentFileName(PathUtils.temporaryFileName(1, "/")));
Assert.assertEquals("/",
PathUtils.getPermanentFileName(PathUtils.temporaryFileName(0xFFFFFFFFFFFFFFFFL, "/")));
Assert.assertEquals("/foo.alluxio.0x0123456789ABCDEF.tmp", PathUtils
.getPermanentFileName(PathUtils.temporaryFileName(14324,
"/foo.alluxio.0x0123456789ABCDEF.tmp")));
}
/**
* Test the {@link PathUtils#isTemporaryFileName(String)} method.
*/
@Test
public void isTemporaryFileName() {
Assert.assertTrue(PathUtils.isTemporaryFileName(PathUtils.temporaryFileName(0, "/")));
Assert.assertTrue(
PathUtils.isTemporaryFileName(PathUtils.temporaryFileName(0xFFFFFFFFFFFFFFFFL, "/")));
Assert.assertTrue(PathUtils.isTemporaryFileName("foo.alluxio.0x0123456789ABCDEF.tmp"));
Assert.assertFalse(PathUtils.isTemporaryFileName("foo.alluxio.0x 0123456789.tmp"));
Assert.assertFalse(PathUtils.isTemporaryFileName("foo.alluxio.0x0123456789ABCDEFG.tmp"));
Assert.assertFalse(PathUtils.isTemporaryFileName("foo.alluxio.0x0123456789ABCDE.tmp"));
Assert.assertFalse(PathUtils.isTemporaryFileName("foo.0x0123456789ABCDEFG.tmp"));
Assert.assertFalse(PathUtils.isTemporaryFileName("alluxio.0x0123456789ABCDEFG"));
}
/**
* Tests the {@link PathUtils#uniqPath()} method.
*/
@Test
public void uniqPath() {
Assert.assertNotEquals(PathUtils.uniqPath(), PathUtils.uniqPath());
}
/**
* Tests the {@link PathUtils#validatePath(String)} method.
*
* @throws InvalidPathException thrown if the path is invalid
*/
@Test
public void validatePath() throws InvalidPathException {
// check valid paths
PathUtils.validatePath("/foo/bar");
PathUtils.validatePath("/foo/bar/");
PathUtils.validatePath("/foo/./bar/");
PathUtils.validatePath("/foo/././bar/");
PathUtils.validatePath("/foo/../bar");
PathUtils.validatePath("/foo/../bar/");
// check invalid paths
LinkedList<String> invalidPaths = new LinkedList<>();
invalidPaths.add(null);
invalidPaths.add("");
invalidPaths.add(" /");
invalidPaths.add("/ ");
for (String invalidPath : invalidPaths) {
try {
PathUtils.validatePath(invalidPath);
Assert.fail("validatePath(" + invalidPath + ") did not fail");
} catch (InvalidPathException e) {
// this is expected
}
}
}
/**
* Tests the {@link PathUtils#normalizePath(String, String)} method.
*/
@Test
public void normalizePath() throws Exception {
Assert.assertEquals("/", PathUtils.normalizePath("", "/"));
Assert.assertEquals("/", PathUtils.normalizePath("/", "/"));
Assert.assertEquals("/foo/bar/", PathUtils.normalizePath("/foo/bar", "/"));
Assert.assertEquals("/foo/bar/", PathUtils.normalizePath("/foo/bar/", "/"));
Assert.assertEquals("/foo/bar//", PathUtils.normalizePath("/foo/bar//", "/"));
Assert.assertEquals("/foo/bar%", PathUtils.normalizePath("/foo/bar", "%"));
}
}