33 * @build CompilerUtils 34 * @run testng HashesTest 35 */ 36 37 import java.io.IOException; 38 import java.io.InputStream; 39 import java.lang.module.ModuleDescriptor; 40 import java.lang.module.ModuleFinder; 41 import java.lang.module.ModuleReader; 42 import java.lang.module.ModuleReference; 43 import java.nio.file.FileVisitResult; 44 import java.nio.file.Files; 45 import java.nio.file.Path; 46 import java.nio.file.Paths; 47 import java.nio.file.SimpleFileVisitor; 48 import java.nio.file.attribute.BasicFileAttributes; 49 import java.util.ArrayList; 50 import java.util.Arrays; 51 import java.util.Collections; 52 import java.util.List; 53 import java.util.Optional; 54 import java.util.Set; 55 import java.util.spi.ToolProvider; 56 import java.util.stream.Collectors; 57 58 import jdk.internal.misc.SharedSecrets; 59 import jdk.internal.misc.JavaLangModuleAccess; 60 import jdk.internal.module.ModuleHashes; 61 62 import org.testng.annotations.BeforeTest; 63 import org.testng.annotations.Test; 64 65 import static org.testng.Assert.*; 66 67 public class HashesTest { 68 static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") 69 .orElseThrow(() -> 70 new RuntimeException("jmod tool not found") 71 ); 72 73 private final Path testSrc = Paths.get(System.getProperty("test.src")); 74 private final Path modSrc = testSrc.resolve("src"); 75 private final Path mods = Paths.get("mods"); 76 private final Path jmods = Paths.get("jmods"); 77 private final String[] modules = new String[] { "m1", "m2", "m3"}; 78 79 @BeforeTest 80 private void setup() throws Exception { 86 // build m2, m3 required by m1 87 compileModule("m2", modSrc); 88 jmod("m2"); 89 90 compileModule("m3", modSrc); 91 jmod("m3"); 92 93 // build m1 94 compileModule("m1", modSrc); 95 // no hash is recorded since m1 has outgoing edges 96 jmod("m1", "--module-path", jmods.toString(), "--hash-modules", ".*"); 97 98 // compile org.bar and org.foo 99 compileModule("org.bar", modSrc); 100 compileModule("org.foo", modSrc); 101 } 102 103 @Test 104 public void test() throws Exception { 105 for (String mn : modules) { 106 assertFalse(hashes(mn).isPresent()); 107 } 108 109 // hash m1 in m2 110 jmod("m2", "--module-path", jmods.toString(), "--hash-modules", "m1"); 111 checkHashes(hashes("m2").get(), "m1"); 112 113 // hash m1 in m2 114 jmod("m2", "--module-path", jmods.toString(), "--hash-modules", ".*"); 115 checkHashes(hashes("m2").get(), "m1"); 116 117 // create m2.jmod with no hash 118 jmod("m2"); 119 // run jmod hash command to hash m1 in m2 and m3 120 runJmod(Arrays.asList("hash", "--module-path", jmods.toString(), 121 "--hash-modules", ".*")); 122 checkHashes(hashes("m2").get(), "m1"); 123 checkHashes(hashes("m3").get(), "m1"); 124 125 jmod("org.bar"); 126 jmod("org.foo"); 127 128 jmod("org.bar", "--module-path", jmods.toString(), "--hash-modules", "org.*"); 129 checkHashes(hashes("org.bar").get(), "org.foo"); 130 131 jmod("m3", "--module-path", jmods.toString(), "--hash-modules", ".*"); 132 checkHashes(hashes("m3").get(), "org.foo", "org.bar", "m1"); 133 } 134 135 private void checkHashes(ModuleHashes hashes, String... hashModules) { 136 assertTrue(hashes.names().equals(Set.of(hashModules))); 137 } 138 139 private Optional<ModuleHashes> hashes(String name) throws Exception { 140 ModuleFinder finder = SharedSecrets.getJavaLangModuleAccess() 141 .newModulePath(Runtime.version(), true, jmods.resolve(name + ".jmod")); 142 ModuleReference mref = finder.find(name).orElseThrow(RuntimeException::new); 143 ModuleReader reader = mref.open(); 144 try (InputStream in = reader.open("module-info.class").get()) { 145 ModuleDescriptor md = ModuleDescriptor.read(in); 146 JavaLangModuleAccess jmla = SharedSecrets.getJavaLangModuleAccess(); 147 Optional<ModuleHashes> hashes = jmla.hashes(md); 148 System.out.format("hashes in module %s %s%n", name, 149 hashes.isPresent() ? "present" : "absent"); 150 if (hashes.isPresent()) { 151 hashes.get().names().stream() 152 .sorted() 153 .forEach(n -> System.out.format(" %s %s%n", n, hashes.get().hashFor(n))); 154 } 155 return hashes; 156 } finally { 157 reader.close(); 158 } 159 } 160 161 private void deleteDirectory(Path dir) throws IOException { 162 Files.walkFileTree(dir, new SimpleFileVisitor<Path>() { 163 @Override 164 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 165 throws IOException 166 { 167 Files.delete(file); 168 return FileVisitResult.CONTINUE; 169 } 170 171 @Override 172 public FileVisitResult postVisitDirectory(Path dir, IOException exc) 173 throws IOException | 33 * @build CompilerUtils 34 * @run testng HashesTest 35 */ 36 37 import java.io.IOException; 38 import java.io.InputStream; 39 import java.lang.module.ModuleDescriptor; 40 import java.lang.module.ModuleFinder; 41 import java.lang.module.ModuleReader; 42 import java.lang.module.ModuleReference; 43 import java.nio.file.FileVisitResult; 44 import java.nio.file.Files; 45 import java.nio.file.Path; 46 import java.nio.file.Paths; 47 import java.nio.file.SimpleFileVisitor; 48 import java.nio.file.attribute.BasicFileAttributes; 49 import java.util.ArrayList; 50 import java.util.Arrays; 51 import java.util.Collections; 52 import java.util.List; 53 import java.util.Set; 54 import java.util.spi.ToolProvider; 55 import java.util.stream.Collectors; 56 57 import jdk.internal.module.ModuleInfo; 58 import jdk.internal.module.ModuleHashes; 59 import jdk.internal.module.ModulePath; 60 61 import org.testng.annotations.BeforeTest; 62 import org.testng.annotations.Test; 63 64 import static org.testng.Assert.*; 65 66 public class HashesTest { 67 static final ToolProvider JMOD_TOOL = ToolProvider.findFirst("jmod") 68 .orElseThrow(() -> 69 new RuntimeException("jmod tool not found") 70 ); 71 72 private final Path testSrc = Paths.get(System.getProperty("test.src")); 73 private final Path modSrc = testSrc.resolve("src"); 74 private final Path mods = Paths.get("mods"); 75 private final Path jmods = Paths.get("jmods"); 76 private final String[] modules = new String[] { "m1", "m2", "m3"}; 77 78 @BeforeTest 79 private void setup() throws Exception { 85 // build m2, m3 required by m1 86 compileModule("m2", modSrc); 87 jmod("m2"); 88 89 compileModule("m3", modSrc); 90 jmod("m3"); 91 92 // build m1 93 compileModule("m1", modSrc); 94 // no hash is recorded since m1 has outgoing edges 95 jmod("m1", "--module-path", jmods.toString(), "--hash-modules", ".*"); 96 97 // compile org.bar and org.foo 98 compileModule("org.bar", modSrc); 99 compileModule("org.foo", modSrc); 100 } 101 102 @Test 103 public void test() throws Exception { 104 for (String mn : modules) { 105 assertTrue(hashes(mn) == null); 106 } 107 108 // hash m1 in m2 109 jmod("m2", "--module-path", jmods.toString(), "--hash-modules", "m1"); 110 checkHashes(hashes("m2"), "m1"); 111 112 // hash m1 in m2 113 jmod("m2", "--module-path", jmods.toString(), "--hash-modules", ".*"); 114 checkHashes(hashes("m2"), "m1"); 115 116 // create m2.jmod with no hash 117 jmod("m2"); 118 // run jmod hash command to hash m1 in m2 and m3 119 runJmod(Arrays.asList("hash", "--module-path", jmods.toString(), 120 "--hash-modules", ".*")); 121 checkHashes(hashes("m2"), "m1"); 122 checkHashes(hashes("m3"), "m1"); 123 124 jmod("org.bar"); 125 jmod("org.foo"); 126 127 jmod("org.bar", "--module-path", jmods.toString(), "--hash-modules", "org.*"); 128 checkHashes(hashes("org.bar"), "org.foo"); 129 130 jmod("m3", "--module-path", jmods.toString(), "--hash-modules", ".*"); 131 checkHashes(hashes("m3"), "org.foo", "org.bar", "m1"); 132 } 133 134 private void checkHashes(ModuleHashes hashes, String... hashModules) { 135 assertTrue(hashes.names().equals(Set.of(hashModules))); 136 } 137 138 private ModuleHashes hashes(String name) throws Exception { 139 ModuleFinder finder = new ModulePath(Runtime.version(), 140 true, 141 jmods.resolve(name + ".jmod")); 142 ModuleReference mref = finder.find(name).orElseThrow(RuntimeException::new); 143 ModuleReader reader = mref.open(); 144 try (InputStream in = reader.open("module-info.class").get()) { 145 ModuleHashes hashes = ModuleInfo.read(in, null).recordedHashes(); 146 System.out.format("hashes in module %s %s%n", name, 147 (hashes != null) ? "present" : "absent"); 148 if (hashes != null) { 149 hashes.names().stream() 150 .sorted() 151 .forEach(n -> System.out.format(" %s %s%n", n, hashes.hashFor(n))); 152 } 153 return hashes; 154 } finally { 155 reader.close(); 156 } 157 } 158 159 private void deleteDirectory(Path dir) throws IOException { 160 Files.walkFileTree(dir, new SimpleFileVisitor<Path>() { 161 @Override 162 public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) 163 throws IOException 164 { 165 Files.delete(file); 166 return FileVisitResult.CONTINUE; 167 } 168 169 @Override 170 public FileVisitResult postVisitDirectory(Path dir, IOException exc) 171 throws IOException |