1 /* 2 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 package jdk.incubator.jpackage.internal; 26 27 import java.io.IOException; 28 import java.nio.file.Files; 29 import java.nio.file.Path; 30 import java.util.*; 31 import java.util.function.Consumer; 32 import java.util.function.Predicate; 33 import java.util.function.UnaryOperator; 34 import java.util.stream.Collectors; 35 import java.util.stream.Stream; 36 import static org.hamcrest.CoreMatchers.equalTo; 37 import static org.hamcrest.CoreMatchers.not; 38 import static org.junit.Assert.*; 39 import org.junit.Rule; 40 import org.junit.Test; 41 import org.junit.rules.TemporaryFolder; 42 43 44 public class PathGroupTest { 45 46 @Rule 47 public final TemporaryFolder tempFolder = new TemporaryFolder(); 48 49 @Test(expected = NullPointerException.class) 50 public void testNullId() { 51 new PathGroup(Map.of()).getPath(null); 52 } 53 54 @Test 55 public void testEmptyPathGroup() { 56 PathGroup pg = new PathGroup(Map.of()); 57 58 assertNull(pg.getPath("foo")); 59 60 assertEquals(0, pg.paths().size()); 61 assertEquals(0, pg.roots().size()); 62 } 63 64 @Test 65 public void testRootsSinglePath() { 66 final PathGroup pg = new PathGroup(Map.of("main", PATH_FOO)); 67 68 List<Path> paths = pg.paths(); 69 assertEquals(1, paths.size()); 70 assertEquals(PATH_FOO, paths.iterator().next()); 71 72 List<Path> roots = pg.roots(); 73 assertEquals(1, roots.size()); 74 assertEquals(PATH_FOO, roots.iterator().next()); 75 } 76 77 @Test 78 public void testDuplicatedRoots() { 79 final PathGroup pg = new PathGroup(Map.of("main", PATH_FOO, "another", 80 PATH_FOO, "root", PATH_EMPTY)); 81 82 List<Path> paths = pg.paths(); 83 Collections.sort(paths); 84 85 assertEquals(3, paths.size()); 86 assertEquals(PATH_EMPTY, paths.get(0)); 87 assertEquals(PATH_FOO, paths.get(1)); 88 assertEquals(PATH_FOO, paths.get(2)); 89 90 List<Path> roots = pg.roots(); 91 assertEquals(1, roots.size()); 92 assertEquals(PATH_EMPTY, roots.get(0)); 93 } 94 95 @Test 96 public void testRoots() { 97 final PathGroup pg = new PathGroup(Map.of(1, Path.of("foo"), 2, Path.of( 98 "foo", "bar"), 3, Path.of("foo", "bar", "buz"))); 99 100 List<Path> paths = pg.paths(); 101 assertEquals(3, paths.size()); 102 assertTrue(paths.contains(Path.of("foo"))); 103 assertTrue(paths.contains(Path.of("foo", "bar"))); 104 assertTrue(paths.contains(Path.of("foo", "bar", "buz"))); 105 106 List<Path> roots = pg.roots(); 107 assertEquals(1, roots.size()); 108 assertEquals(Path.of("foo"), roots.get(0)); 109 } 110 111 @Test 112 public void testResolveAt() { 113 final PathGroup pg = new PathGroup(Map.of(0, PATH_FOO, 1, PATH_BAR, 2, 114 PATH_EMPTY)); 115 116 final Path aPath = Path.of("a"); 117 118 final PathGroup pg2 = pg.resolveAt(aPath); 119 assertThat(pg, not(equalTo(pg2))); 120 121 List<Path> paths = pg.paths(); 122 assertEquals(3, paths.size()); 123 assertTrue(paths.contains(PATH_EMPTY)); 124 assertTrue(paths.contains(PATH_FOO)); 125 assertTrue(paths.contains(PATH_BAR)); 126 assertEquals(PATH_EMPTY, pg.roots().get(0)); 127 128 paths = pg2.paths(); 129 assertEquals(3, paths.size()); 130 assertTrue(paths.contains(aPath.resolve(PATH_EMPTY))); 131 assertTrue(paths.contains(aPath.resolve(PATH_FOO))); 132 assertTrue(paths.contains(aPath.resolve(PATH_BAR))); 133 assertEquals(aPath, pg2.roots().get(0)); 134 } 135 136 @Test 137 public void testTransform() throws IOException { 138 for (var transform : TransformType.values()) { 139 testTransform(false, transform); 140 } 141 } 142 143 @Test 144 public void testTransformWithExcludes() throws IOException { 145 for (var transform : TransformType.values()) { 146 testTransform(true, transform); 147 } 148 } 149 150 enum TransformType { Copy, Move, Handler }; 151 152 private void testTransform(boolean withExcludes, TransformType transform) 153 throws IOException { 154 final PathGroup pg = new PathGroup(Map.of(0, PATH_FOO, 1, PATH_BAR, 2, 155 PATH_EMPTY, 3, PATH_BAZ)); 156 157 final Path srcDir = tempFolder.newFolder().toPath(); 158 final Path dstDir = tempFolder.newFolder().toPath(); 159 160 Files.createDirectories(srcDir.resolve(PATH_FOO).resolve("a/b/c/d")); 161 Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/c/file1")); 162 Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/file2")); 163 Files.createFile(srcDir.resolve(PATH_FOO).resolve("a/b/file3")); 164 Files.createFile(srcDir.resolve(PATH_BAR)); 165 Files.createFile(srcDir.resolve(PATH_EMPTY).resolve("file4")); 166 Files.createDirectories(srcDir.resolve(PATH_BAZ).resolve("1/2/3")); 167 168 var dst = pg.resolveAt(dstDir); 169 var src = pg.resolveAt(srcDir); 170 if (withExcludes) { 171 // Exclude from transformation. 172 src.setPath(new Object(), srcDir.resolve(PATH_FOO).resolve("a/b/c")); 173 src.setPath(new Object(), srcDir.resolve(PATH_EMPTY).resolve("file4")); 174 } 175 176 var srcFilesBeforeTransform = walkFiles(srcDir); 177 178 if (transform == TransformType.Handler) { 179 List<Map.Entry<Path, Path>> copyFile = new ArrayList<>(); 180 List<Path> createDirectory = new ArrayList<>(); 181 src.transform(dst, new PathGroup.TransformHandler() { 182 @Override 183 public void copyFile(Path src, Path dst) throws IOException { 184 copyFile.add(Map.entry(src, dst)); 185 } 186 187 @Override 188 public void createDirectory(Path dir) throws IOException { 189 createDirectory.add(dir); 190 } 191 }); 192 193 Consumer<Path> assertFile = path -> { 194 var entry = Map.entry(srcDir.resolve(path), dstDir.resolve(path)); 195 assertTrue(copyFile.contains(entry)); 196 }; 197 198 Consumer<Path> assertDir = path -> { 199 assertTrue(createDirectory.contains(dstDir.resolve(path))); 200 }; 201 202 assertEquals(withExcludes ? 3 : 5, copyFile.size()); 203 assertEquals(withExcludes ? 8 : 10, createDirectory.size()); 204 205 assertFile.accept(PATH_FOO.resolve("a/b/file2")); 206 assertFile.accept(PATH_FOO.resolve("a/b/file3")); 207 assertFile.accept(PATH_BAR); 208 assertDir.accept(PATH_FOO.resolve("a/b")); 209 assertDir.accept(PATH_FOO.resolve("a")); 210 assertDir.accept(PATH_FOO); 211 assertDir.accept(PATH_BAZ); 212 assertDir.accept(PATH_BAZ.resolve("1")); 213 assertDir.accept(PATH_BAZ.resolve("1/2")); 214 assertDir.accept(PATH_BAZ.resolve("1/2/3")); 215 assertDir.accept(PATH_EMPTY); 216 217 if (!withExcludes) { 218 assertFile.accept(PATH_FOO.resolve("a/b/c/file1")); 219 assertFile.accept(PATH_EMPTY.resolve("file4")); 220 assertDir.accept(PATH_FOO.resolve("a/b/c/d")); 221 assertDir.accept(PATH_FOO.resolve("a/b/c")); 222 } 223 224 assertArrayEquals(new Path[] { Path.of("") }, walkFiles(dstDir)); 225 return; 226 } 227 228 if (transform == TransformType.Copy) { 229 src.copy(dst); 230 } else if (transform == TransformType.Move) { 231 src.move(dst); 232 } 233 234 final List<Path> excludedPaths; 235 if (withExcludes) { 236 excludedPaths = List.of( 237 PATH_EMPTY.resolve("file4"), 238 PATH_FOO.resolve("a/b/c") 239 ); 240 } else { 241 excludedPaths = Collections.emptyList(); 242 } 243 UnaryOperator<Path[]> removeExcludes = paths -> { 244 return Stream.of(paths) 245 .filter(path -> !excludedPaths.stream().anyMatch( 246 path::startsWith)) 247 .collect(Collectors.toList()).toArray(Path[]::new); 248 }; 249 250 var dstFiles = walkFiles(dstDir); 251 assertArrayEquals(removeExcludes.apply(srcFilesBeforeTransform), dstFiles); 252 253 if (transform == TransformType.Copy) { 254 assertArrayEquals(dstFiles, removeExcludes.apply(walkFiles(srcDir))); 255 } else if (transform == TransformType.Move) { 256 assertFalse(Files.exists(srcDir)); 257 } 258 } 259 260 private static Path[] walkFiles(Path root) throws IOException { 261 try (var files = Files.walk(root)) { 262 return files.map(root::relativize).sorted().collect( 263 Collectors.toList()).toArray(Path[]::new); 264 } 265 } 266 267 private final static Path PATH_FOO = Path.of("foo"); 268 private final static Path PATH_BAR = Path.of("bar"); 269 private final static Path PATH_BAZ = Path.of("baz"); 270 private final static Path PATH_EMPTY = Path.of(""); 271 }