GenModuleInfo.java revision 3294:9adfb22ff08f
199193Sjmallett/* 299193Sjmallett * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. 399193Sjmallett * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 499193Sjmallett * 599193Sjmallett * This code is free software; you can redistribute it and/or modify it 699193Sjmallett * under the terms of the GNU General Public License version 2 only, as 799193Sjmallett * published by the Free Software Foundation. 899193Sjmallett * 999193Sjmallett * This code is distributed in the hope that it will be useful, but WITHOUT 1099193Sjmallett * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1199193Sjmallett * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1299193Sjmallett * version 2 for more details (a copy is included in the LICENSE file that 1399193Sjmallett * accompanied this code). 1499193Sjmallett * 1599193Sjmallett * You should have received a copy of the GNU General Public License version 1699193Sjmallett * 2 along with this work; if not, write to the Free Software Foundation, 1799193Sjmallett * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1899193Sjmallett * 1999193Sjmallett * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2099193Sjmallett * or visit www.oracle.com if you need additional information or have any 2199193Sjmallett * questions. 2299193Sjmallett */ 2399193Sjmallett 2499193Sjmallett/* 2599193Sjmallett * @test 2699193Sjmallett * @summary Tests jdeps -genmoduleinfo option 2799193Sjmallett * @library .. 2899193Sjmallett * @build CompilerUtils 2999193Sjmallett * @modules jdk.jdeps/com.sun.tools.jdeps 3099193Sjmallett * @run testng GenModuleInfo 3199193Sjmallett */ 3299193Sjmallett 3399193Sjmallettimport java.io.*; 3499193Sjmallettimport java.lang.module.ModuleDescriptor; 3599193Sjmallett 3699193Sjmallettimport java.nio.file.Files; 3799193Sjmallettimport java.nio.file.Path; 3899193Sjmallettimport java.nio.file.Paths; 3999193Sjmallett 4099193Sjmallettimport java.util.Arrays; 4199193Sjmallettimport java.util.Set; 42109506Sjmallettimport java.util.jar.JarEntry; 43109506Sjmallettimport java.util.jar.JarOutputStream; 4499193Sjmallettimport java.util.stream.Collectors; 4599193Sjmallettimport java.util.stream.Stream; 4699193Sjmallett 4799193Sjmallettimport org.testng.annotations.DataProvider; 4899193Sjmallettimport org.testng.annotations.BeforeTest; 4999193Sjmallettimport org.testng.annotations.Test; 5099193Sjmallett 51109506Sjmallett 52109506Sjmallettimport static org.testng.Assert.assertEquals; 53109506Sjmallettimport static org.testng.Assert.assertTrue; 5499193Sjmallett 5599193Sjmallettpublic class GenModuleInfo { 5699193Sjmallett private static final String MODULE_INFO = "module-info.class"; 5799193Sjmallett private static final String TEST_SRC = System.getProperty("test.src"); 5899193Sjmallett private static final String TEST_CLASSES = System.getProperty("test.classes"); 59109462Sjmallett 6099193Sjmallett private static final Path SRC_DIR = Paths.get(TEST_SRC, "src"); 61109462Sjmallett private static final Path MODS_DIR = Paths.get("mods"); 62109462Sjmallett private static final Path LIBS_DIR = Paths.get("libs"); 6399193Sjmallett private static final Path DEST_DIR = Paths.get("moduleinfosrc"); 6499193Sjmallett private static final Path NEW_MODS_DIR = Paths.get("new_mods"); 65109462Sjmallett 6699193Sjmallett // the names of the modules in this test 6799193Sjmallett private static final String UNSUPPORTED = "unsupported"; 6899193Sjmallett private static String[] modules = new String[] {"m1", "m2", "m3", UNSUPPORTED}; 6999193Sjmallett /** 70109462Sjmallett * Compiles all modules used by the test 7199193Sjmallett */ 7299193Sjmallett @BeforeTest 7399193Sjmallett public void compileAll() throws Exception { 7499193Sjmallett CompilerUtils.cleanDir(MODS_DIR); 7599193Sjmallett CompilerUtils.cleanDir(LIBS_DIR); 7699193Sjmallett CompilerUtils.cleanDir(DEST_DIR); 7799193Sjmallett CompilerUtils.cleanDir(NEW_MODS_DIR); 7899193Sjmallett 79109462Sjmallett assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, UNSUPPORTED, 8099193Sjmallett "-XaddExports:java.base/jdk.internal.perf=" + UNSUPPORTED)); 81109462Sjmallett Arrays.asList("m1", "m2", "m3") 82109462Sjmallett .forEach(mn -> assertTrue(CompilerUtils.compileModule(SRC_DIR, MODS_DIR, mn))); 83109462Sjmallett 84109462Sjmallett Files.createDirectory(LIBS_DIR); 85109462Sjmallett Files.createDirectory(DEST_DIR); 86109462Sjmallett 87109462Sjmallett for (String mn : modules) { 88109462Sjmallett Path root = MODS_DIR.resolve(mn); 89109462Sjmallett createJar(LIBS_DIR.resolve(mn + ".jar"), root, 90109462Sjmallett Files.walk(root, Integer.MAX_VALUE) 91109462Sjmallett .filter(f -> { 92109462Sjmallett String fn = f.getFileName().toString(); 9399193Sjmallett return fn.endsWith(".class") && !fn.equals("module-info.class"); 9499193Sjmallett })); 9599193Sjmallett } 9699193Sjmallett } 9799193Sjmallett 98109462Sjmallett @Test 9999193Sjmallett public void jdeps() throws IOException { 10099193Sjmallett Stream<String> files = Arrays.stream(modules) 10199193Sjmallett .map(mn -> LIBS_DIR.resolve(mn + ".jar")) 10299193Sjmallett .map(Path::toString); 10399193Sjmallett jdeps(Stream.concat(Stream.of("-cp"), files).toArray(String[]::new)); 104109506Sjmallett } 105109506Sjmallett 106109506Sjmallett @Test 107109506Sjmallett public void test() throws IOException { 10899193Sjmallett Stream<String> files = Arrays.stream(modules) 10999193Sjmallett .map(mn -> LIBS_DIR.resolve(mn + ".jar")) 11099193Sjmallett .map(Path::toString); 11199193Sjmallett 11299193Sjmallett jdeps(Stream.concat(Stream.of("-genmoduleinfo", DEST_DIR.toString()), 11399193Sjmallett files) 114109506Sjmallett .toArray(String[]::new)); 115109506Sjmallett 116109506Sjmallett // check file exists 117109506Sjmallett Arrays.stream(modules) 11899193Sjmallett .map(mn -> DEST_DIR.resolve(mn).resolve("module-info.java")) 11999193Sjmallett .forEach(f -> assertTrue(Files.exists(f))); 120109462Sjmallett 12199222Sjmallett // copy classes except the original module-info.class 122109506Sjmallett Files.walk(MODS_DIR, Integer.MAX_VALUE) 123109506Sjmallett .filter(path -> !path.getFileName().toString().equals(MODULE_INFO) && 124109506Sjmallett path.getFileName().toString().endsWith(".class")) 125109506Sjmallett .map(path -> MODS_DIR.relativize(path)) 126109506Sjmallett .forEach(path -> { 127109506Sjmallett try { 128109506Sjmallett Path newFile = NEW_MODS_DIR.resolve(path); 129109506Sjmallett Files.createDirectories(newFile.getParent()); 130109506Sjmallett Files.copy(MODS_DIR.resolve(path), newFile); 131109506Sjmallett } catch (IOException e) { 132109506Sjmallett throw new UncheckedIOException(e); 133109506Sjmallett } 134109506Sjmallett }); 135109506Sjmallett 136109506Sjmallett // compile new module-info.java 13799193Sjmallett assertTrue(CompilerUtils.compileModule(DEST_DIR, NEW_MODS_DIR, UNSUPPORTED, 13899193Sjmallett "-mp", NEW_MODS_DIR.toString(), "-verbose", 139109506Sjmallett "-XaddExports:java.base/jdk.internal.perf=" + UNSUPPORTED)); 14099193Sjmallett Arrays.asList("m1", "m2", "m3") 14199193Sjmallett .forEach(mn -> assertTrue(CompilerUtils.compileModule(DEST_DIR, NEW_MODS_DIR, 14299193Sjmallett mn, "-mp", NEW_MODS_DIR.toString()))); 14399193Sjmallett 14499193Sjmallett for (String mn : modules) { 14599193Sjmallett Path p1 = NEW_MODS_DIR.resolve(mn).resolve(MODULE_INFO); 14699823Sjmallett Path p2 = MODS_DIR.resolve(mn).resolve(MODULE_INFO); 14799823Sjmallett 148109506Sjmallett try (InputStream in1 = Files.newInputStream(p1); 149101687Sjmallett InputStream in2 = Files.newInputStream(p2)) { 150105737Sjmallett verify(ModuleDescriptor.read(in1), 15199193Sjmallett ModuleDescriptor.read(in2, () -> packages(MODS_DIR.resolve(mn)))); 152109506Sjmallett } 153109506Sjmallett } 154109506Sjmallett } 155109506Sjmallett 156109506Sjmallett private void verify(ModuleDescriptor md1, ModuleDescriptor md2) { 157109506Sjmallett System.out.println("verifying: " + md1.name()); 158109506Sjmallett assertEquals(md1.name(), md2.name()); 159109506Sjmallett assertEquals(md1.requires(), md2.requires()); 160109506Sjmallett // all packages are exported 161109506Sjmallett assertEquals(md1.exports().stream() 16299193Sjmallett .map(ModuleDescriptor.Exports::source) 163109462Sjmallett .collect(Collectors.toSet()), md2.packages()); 16499193Sjmallett } 16599193Sjmallett 16699193Sjmallett private Set<String> packages(Path dir) { 16799193Sjmallett try { 16899193Sjmallett return Files.find(dir, Integer.MAX_VALUE, 169 ((path, attrs) -> attrs.isRegularFile() && 170 path.toString().endsWith(".class"))) 171 .map(path -> toPackageName(dir.relativize(path))) 172 .filter(pkg -> pkg.length() > 0) // module-info 173 .distinct() 174 .collect(Collectors.toSet()); 175 } catch (IOException x) { 176 throw new UncheckedIOException(x); 177 } 178 } 179 180 private String toPackageName(Path path) { 181 String name = path.toString(); 182 assert name.endsWith(".class"); 183 int index = name.lastIndexOf(File.separatorChar); 184 if (index != -1) { 185 return name.substring(0, index).replace(File.separatorChar, '.'); 186 } else { 187 return ""; 188 } 189 } 190 191 /* 192 * Runs jdeps with the given arguments 193 */ 194 public static String[] jdeps(String... args) { 195 String lineSep = System.getProperty("line.separator"); 196 StringWriter sw = new StringWriter(); 197 PrintWriter pw = new PrintWriter(sw); 198 System.err.println("jdeps " + Arrays.toString(args)); 199 int rc = com.sun.tools.jdeps.Main.run(args, pw); 200 pw.close(); 201 String out = sw.toString(); 202 if (!out.isEmpty()) 203 System.err.println(out); 204 if (rc != 0) 205 throw new Error("jdeps failed: rc=" + rc); 206 return out.split(lineSep); 207 } 208 209 /** 210 * Create a jar file using the list of files provided. 211 */ 212 public static void createJar(Path jarfile, Path root, Stream<Path> files) 213 throws IOException { 214 try (JarOutputStream target = new JarOutputStream( 215 Files.newOutputStream(jarfile))) { 216 files.forEach(file -> add(root.relativize(file), file, target)); 217 } 218 } 219 220 private static void add(Path path, Path source, JarOutputStream target) { 221 try { 222 String name = path.toString().replace(File.separatorChar, '/'); 223 JarEntry entry = new JarEntry(name); 224 entry.setTime(source.toFile().lastModified()); 225 target.putNextEntry(entry); 226 Files.copy(source, target); 227 target.closeEntry(); 228 } catch (IOException e) { 229 throw new UncheckedIOException(e); 230 } 231 } 232 233} 234