--- /dev/null 2019-12-03 13:58:12.000000000 -0500 +++ new/test/jdk/tools/jpackage/junit/jdk/incubator/jpackage/internal/PathGroupTest.java 2019-12-03 13:58:10.161523800 -0500 @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package jdk.incubator.jpackage.internal; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.*; +import java.util.function.Consumer; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.CoreMatchers.not; +import static org.junit.Assert.*; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + + +public class PathGroupTest { + + @Rule + public final TemporaryFolder tempFolder = new TemporaryFolder(); + + @Test(expected = NullPointerException.class) + public void testNullId() { + new PathGroup(Map.of()).getPath(null); + } + + @Test + public void testEmptyPathGroup() { + PathGroup pg = new PathGroup(Map.of()); + + assertNull(pg.getPath("foo")); + + assertEquals(0, pg.paths().size()); + assertEquals(0, pg.roots().size()); + } + + @Test + public void testRootsSinglePath() { + final PathGroup pg = new PathGroup(Map.of("main", PATH_FOO)); + + List paths = pg.paths(); + assertEquals(1, paths.size()); + assertEquals(PATH_FOO, paths.iterator().next()); + + List roots = pg.roots(); + assertEquals(1, roots.size()); + assertEquals(PATH_FOO, roots.iterator().next()); + } + + @Test + public void testDuplicatedRoots() { + final PathGroup pg = new PathGroup(Map.of("main", PATH_FOO, "another", + PATH_FOO, "root", PATH_EMPTY)); + + List paths = pg.paths(); + Collections.sort(paths); + + assertEquals(3, paths.size()); + assertEquals(PATH_EMPTY, paths.get(0)); + assertEquals(PATH_FOO, paths.get(1)); + assertEquals(PATH_FOO, paths.get(2)); + + List roots = pg.roots(); + assertEquals(1, roots.size()); + assertEquals(PATH_EMPTY, roots.get(0)); + } + + @Test + public void testRoots() { + final PathGroup pg = new PathGroup(Map.of(1, Path.of("foo"), 2, Path.of( + "foo", "bar"), 3, Path.of("foo", "bar", "buz"))); + + List paths = pg.paths(); + assertEquals(3, paths.size()); + assertTrue(paths.contains(Path.of("foo"))); + assertTrue(paths.contains(Path.of("foo", "bar"))); + assertTrue(paths.contains(Path.of("foo", "bar", "buz"))); + + List roots = pg.roots(); + assertEquals(1, roots.size()); + assertEquals(Path.of("foo"), roots.get(0)); + } + + @Test + public void testResolveAt() { + final PathGroup pg = new PathGroup(Map.of(0, PATH_FOO, 1, PATH_BAR, 2, + PATH_EMPTY)); + + final Path aPath = Path.of("a"); + + final PathGroup pg2 = pg.resolveAt(aPath); + assertThat(pg, not(equalTo(pg2))); + + List paths = pg.paths(); + assertEquals(3, paths.size()); + assertTrue(paths.contains(PATH_EMPTY)); + assertTrue(paths.contains(PATH_FOO)); + assertTrue(paths.contains(PATH_BAR)); + assertEquals(PATH_EMPTY, pg.roots().get(0)); + + paths = pg2.paths(); + assertEquals(3, paths.size()); + assertTrue(paths.contains(aPath.resolve(PATH_EMPTY))); + assertTrue(paths.contains(aPath.resolve(PATH_FOO))); + assertTrue(paths.contains(aPath.resolve(PATH_BAR))); + assertEquals(aPath, pg2.roots().get(0)); + } + + @Test + public void testTransform() throws IOException { + for (var transform : TransformType.values()) { + testTransform(false, transform); + } + } + + @Test + public void testTransformWithExcludes() throws IOException { + for (var transform : TransformType.values()) { + testTransform(true, transform); + } + } + + enum TransformType { Copy, Move, Handler }; + + private void testTransform(boolean withExcludes, TransformType transform) + throws IOException { + final PathGroup pg = new PathGroup(Map.of(0, PATH_FOO, 1, PATH_BAR, 2, + PATH_EMPTY, 3, PATH_BAZ)); + + final Path srcDir = tempFolder.newFolder().toPath(); + final Path dstDir = tempFolder.newFolder().toPath(); + + Files.createDirectories(srcDir.resolve(PATH_FOO).resolve("a/b/c/d")); + Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/c/file1")); + Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/file2")); + Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/file3")); + Files.createFile(srcDir.resolve(PATH_BAR)); + Files.createFile(srcDir.resolve(PATH_EMPTY).resolve("file4")); + Files.createDirectories(srcDir.resolve(PATH_BAZ).resolve("1/2/3")); + + var dst = pg.resolveAt(dstDir); + var src = pg.resolveAt(srcDir); + if (withExcludes) { + // Exclude from transformation. + src.setPath(new Object(), srcDir.resolve(PATH_FOO).resolve("a/b/c")); + src.setPath(new Object(), srcDir.resolve(PATH_EMPTY).resolve("file4")); + } + + var srcFilesBeforeTransform = walkFiles(srcDir); + + if (transform == TransformType.Handler) { + List> copyFile = new ArrayList<>(); + List createDirectory = new ArrayList<>(); + src.transform(dst, new PathGroup.TransformHandler() { + @Override + public void copyFile(Path src, Path dst) throws IOException { + copyFile.add(Map.entry(src, dst)); + } + + @Override + public void createDirectory(Path dir) throws IOException { + createDirectory.add(dir); + } + }); + + Consumer assertFile = path -> { + var entry = Map.entry(srcDir.resolve(path), dstDir.resolve(path)); + assertTrue(copyFile.contains(entry)); + }; + + Consumer assertDir = path -> { + assertTrue(createDirectory.contains(dstDir.resolve(path))); + }; + + assertEquals(withExcludes ? 3 : 5, copyFile.size()); + assertEquals(withExcludes ? 8 : 10, createDirectory.size()); + + assertFile.accept(PATH_FOO.resolve("a/b/file2")); + assertFile.accept(PATH_FOO.resolve("a/b/file3")); + assertFile.accept(PATH_BAR); + assertDir.accept(PATH_FOO.resolve("a/b")); + assertDir.accept(PATH_FOO.resolve("a")); + assertDir.accept(PATH_FOO); + assertDir.accept(PATH_BAZ); + assertDir.accept(PATH_BAZ.resolve("1")); + assertDir.accept(PATH_BAZ.resolve("1/2")); + assertDir.accept(PATH_BAZ.resolve("1/2/3")); + assertDir.accept(PATH_EMPTY); + + if (!withExcludes) { + assertFile.accept(PATH_FOO.resolve("a/b/c/file1")); + assertFile.accept(PATH_EMPTY.resolve("file4")); + assertDir.accept(PATH_FOO.resolve("a/b/c/d")); + assertDir.accept(PATH_FOO.resolve("a/b/c")); + } + + assertArrayEquals(new Path[] { Path.of("") }, walkFiles(dstDir)); + return; + } + + if (transform == TransformType.Copy) { + src.copy(dst); + } else if (transform == TransformType.Move) { + src.move(dst); + } + + final List excludedPaths; + if (withExcludes) { + excludedPaths = List.of( + PATH_EMPTY.resolve("file4"), + PATH_FOO.resolve("a/b/c") + ); + } else { + excludedPaths = Collections.emptyList(); + } + UnaryOperator removeExcludes = paths -> { + return Stream.of(paths) + .filter(path -> !excludedPaths.stream().anyMatch( + path::startsWith)) + .collect(Collectors.toList()).toArray(Path[]::new); + }; + + var dstFiles = walkFiles(dstDir); + assertArrayEquals(removeExcludes.apply(srcFilesBeforeTransform), dstFiles); + + if (transform == TransformType.Copy) { + assertArrayEquals(dstFiles, removeExcludes.apply(walkFiles(srcDir))); + } else if (transform == TransformType.Move) { + assertFalse(Files.exists(srcDir)); + } + } + + private static Path[] walkFiles(Path root) throws IOException { + try (var files = Files.walk(root)) { + return files.map(root::relativize).sorted().collect( + Collectors.toList()).toArray(Path[]::new); + } + } + + private final static Path PATH_FOO = Path.of("foo"); + private final static Path PATH_BAR = Path.of("bar"); + private final static Path PATH_BAZ = Path.of("baz"); + private final static Path PATH_EMPTY = Path.of(""); +}