diff options
Diffstat (limited to 'node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerPathTest.java')
-rw-r--r-- | node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerPathTest.java | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerPathTest.java b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerPathTest.java new file mode 100644 index 00000000000..ead4ad7ecde --- /dev/null +++ b/node-admin/src/test/java/com/yahoo/vespa/hosted/node/admin/task/util/fs/ContainerPathTest.java @@ -0,0 +1,112 @@ +// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. +package com.yahoo.vespa.hosted.node.admin.task.util.fs; + +import com.yahoo.vespa.test.file.TestFileSystem; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.function.Executable; + +import static com.yahoo.vespa.hosted.node.admin.task.util.fs.ContainerPath.fromPathInContainer; +import static com.yahoo.vespa.hosted.node.admin.task.util.fs.ContainerPath.fromPathOnHost; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.nio.file.FileSystem; +import java.nio.file.Files; +import java.nio.file.LinkOption; +import java.nio.file.Path; + +/** + * @author valerijf + */ +class ContainerPathTest { + + private final FileSystem baseFs = TestFileSystem.create(); + private final ContainerFileSystem containerFs = new ContainerFileSystemProvider(baseFs.getPath("/data/storage/ctr1"), 0, 0).getFileSystem(null); + + @Test + public void create_new_container_path() { + ContainerPath path = fromPathInContainer(containerFs, Path.of("/opt/vespa//logs/./file")); + assertPaths(path, "/data/storage/ctr1/opt/vespa/logs/file", "/opt/vespa/logs/file"); + + path = fromPathOnHost(containerFs, baseFs.getPath("/data/storage/ctr1/opt/vespa/logs/file")); + assertPaths(path, "/data/storage/ctr1/opt/vespa/logs/file", "/opt/vespa/logs/file"); + + path = fromPathOnHost(containerFs, baseFs.getPath("/data/storage/ctr2/..////./ctr1/./opt")); + assertPaths(path, "/data/storage/ctr1/opt", "/opt"); + + assertThrows(() -> fromPathInContainer(containerFs, Path.of("relative/path")), "Path in container must be absolute: relative/path"); + assertThrows(() -> fromPathOnHost(containerFs, baseFs.getPath("relative/path")), "Paths have different roots: /data/storage/ctr1, relative/path"); + assertThrows(() -> fromPathOnHost(containerFs, baseFs.getPath("/data/storage/ctr2")), "Path /data/storage/ctr2 is not under container root /data/storage/ctr1"); + assertThrows(() -> fromPathOnHost(containerFs, baseFs.getPath("/data/storage/ctr1/../ctr2")), "Path /data/storage/ctr2 is not under container root /data/storage/ctr1"); + } + + @Test + public void container_path_operations() { + ContainerPath path = fromPathInContainer(containerFs, Path.of("/opt/vespa/logs/file")); + ContainerPath parent = path.getParent(); + assertPaths(path.getRoot(), "/data/storage/ctr1", "/"); + assertPaths(parent, "/data/storage/ctr1/opt/vespa/logs", "/opt/vespa/logs"); + assertNull(path.getRoot().getParent()); + + assertEquals(Path.of("file"), path.getFileName()); + assertEquals(Path.of("logs"), path.getName(2)); + assertEquals(4, path.getNameCount()); + assertEquals(Path.of("vespa/logs"), path.subpath(1, 3)); + + assertTrue(path.startsWith(path)); + assertTrue(path.startsWith(parent)); + assertFalse(parent.startsWith(path)); + assertFalse(path.startsWith(Path.of(path.toString()))); + + assertTrue(path.endsWith(Path.of(path.toString()))); + assertTrue(path.endsWith(Path.of("logs/file"))); + assertFalse(path.endsWith(Path.of("/logs/file"))); + } + + @Test + public void resolution() { + ContainerPath path = fromPathInContainer(containerFs, Path.of("/opt/vespa/logs")); + assertPaths(path.resolve(Path.of("/root")), "/data/storage/ctr1/root", "/root"); + assertPaths(path.resolve(Path.of("relative")), "/data/storage/ctr1/opt/vespa/logs/relative", "/opt/vespa/logs/relative"); + assertPaths(path.resolve(Path.of("/../../../dir2/../../../dir2")), "/data/storage/ctr1/dir2", "/dir2"); + assertPaths(path.resolve(Path.of("/some/././///path")), "/data/storage/ctr1/some/path", "/some/path"); + + assertPaths(path.resolve(Path.of("../dir")), "/data/storage/ctr1/opt/vespa/dir", "/opt/vespa/dir"); + assertEquals(path.resolve(Path.of("../dir")), path.resolveSibling("dir")); + } + + @Test + public void resolves_real_paths() throws IOException { + ContainerPath path = fromPathInContainer(containerFs, Path.of("/opt/vespa/logs")); + Files.createDirectories(path.pathOnHost().getParent()); + + Files.createFile(baseFs.getPath("/data/storage/ctr1/opt/vespa/target1")); + Files.createSymbolicLink(path.pathOnHost(), path.pathOnHost().resolveSibling("target1")); + assertPaths(path.toRealPath(LinkOption.NOFOLLOW_LINKS), "/data/storage/ctr1/opt/vespa/logs", "/opt/vespa/logs"); + assertPaths(path.toRealPath(), "/data/storage/ctr1/opt/vespa/target1", "/opt/vespa/target1"); + + Files.delete(path.pathOnHost()); + Files.createFile(baseFs.getPath("/data/storage/ctr1/opt/target2")); + Files.createSymbolicLink(path.pathOnHost(), baseFs.getPath("../target2")); + assertPaths(path.toRealPath(), "/data/storage/ctr1/opt/target2", "/opt/target2"); + + Files.delete(path.pathOnHost()); + Files.createFile(baseFs.getPath("/data/storage/ctr2")); + Files.createSymbolicLink(path.pathOnHost(), path.getRoot().pathOnHost().resolveSibling("ctr2")); + assertThrows(path::toRealPath, "Path /data/storage/ctr2 is not under container root /data/storage/ctr1"); + } + + private static void assertPaths(ContainerPath actual, String expectedPathOnHost, String expectedPathInContainer) { + assertEquals(expectedPathOnHost, actual.pathOnHost().toString()); + assertEquals(expectedPathInContainer, actual.toString()); + } + + private static void assertThrows(Executable executable, String expectedMsg) { + String actualMsg = Assertions.assertThrows(IllegalArgumentException.class, executable).getMessage(); + assertEquals(expectedMsg, actualMsg); + } +}
\ No newline at end of file |